diff --git a/CREDITS b/CREDITS index 2520ba620ff1..2b88fb37ad50 100644 --- a/CREDITS +++ b/CREDITS @@ -1253,6 +1253,10 @@ S: 8124 Constitution Apt. 7 S: Sterling Heights, Michigan 48313 S: USA +N: Wolfgang Grandegger +E: wg@grandegger.com +D: Controller Area Network (device drivers) + N: William Greathouse E: wgreathouse@smva.com E: wgreathouse@myfavoritei.com diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index fbeaffc1dcc3..e36986663570 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -145,7 +145,6 @@ usage should require reading the full document. interface in STA mode at first! !Finclude/net/mac80211.h ieee80211_if_init_conf -!Finclude/net/mac80211.h ieee80211_if_conf diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index ec9ef5d0d7b3..7129846a2785 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -438,6 +438,13 @@ Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate Who: Jean Delvare Krzysztof Helt +--------------------------- + +What: CONFIG_RFKILL_INPUT +When: 2.6.33 +Why: Should be implemented in userspace, policy daemon. +Who: Johannes Berg + ---------------------------- What: CONFIG_X86_OLD_MCE diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index 5a2d69989a8c..f6010a536590 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX @@ -22,16 +22,11 @@ README.gigaset - info on the drivers for Siemens Gigaset ISDN adapters. README.icn - info on the ICN-ISDN-card and its driver. +>>>>>>> 93af7aca44f0e82e67bda10a0fb73d383edcc8bd:Documentation/isdn/00-INDEX README.HiSax - info on the HiSax driver which replaces the old teles. -README.hfc-pci - - info on hfc-pci based cards. -README.pcbit - - info on the PCBIT-D ISDN adapter and driver. -README.syncppp - - info on running Sync PPP over ISDN. -syncPPP.FAQ - - frequently asked questions about running PPP over ISDN. +README.audio + - info for running audio over ISDN. README.avmb1 - info on driver for AVM-B1 ISDN card. README.act2000 @@ -42,10 +37,28 @@ README.concap - info on "CONCAP" encapsulation protocol interface used for X.25. README.diversion - info on module for isdn diversion services. +README.fax + - info for using Fax over ISDN. +README.gigaset + - info on the drivers for Siemens Gigaset ISDN adapters +README.hfc-pci + - info on hfc-pci based cards. +README.hysdn + - info on driver for Hypercope active HYSDN cards +README.icn + - info on the ICN-ISDN-card and its driver. +README.mISDN + - info on the Modular ISDN subsystem (mISDN) +README.pcbit + - info on the PCBIT-D ISDN adapter and driver. README.sc - info on driver for Spellcaster cards. +README.syncppp + - info on running Sync PPP over ISDN. README.x25 - info for running X.25 over ISDN. +syncPPP.FAQ + - frequently asked questions about running PPP over ISDN. README.hysdn - info on driver for Hypercope active HYSDN cards README.mISDN diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/INTERFACE.CAPI index 786d619b36e5..686e107923ec 100644 --- a/Documentation/isdn/INTERFACE.CAPI +++ b/Documentation/isdn/INTERFACE.CAPI @@ -45,7 +45,7 @@ From then on, Kernel CAPI may call the registered callback functions for the device. If the device becomes unusable for any reason (shutdown, disconnect ...), the -driver has to call capi_ctr_reseted(). This will prevent further calls to the +driver has to call capi_ctr_down(). This will prevent further calls to the callback functions by Kernel CAPI. @@ -114,20 +114,36 @@ char *driver_name int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata) (optional) pointer to a callback function for sending firmware and configuration data to the device + Return value: 0 on success, error code on error + Called in process context. void (*reset_ctr)(struct capi_ctr *ctrlr) - pointer to a callback function for performing a reset on the device, - releasing all registered applications + (optional) pointer to a callback function for performing a reset on + the device, releasing all registered applications + Called in process context. void (*register_appl)(struct capi_ctr *ctrlr, u16 applid, capi_register_params *rparam) void (*release_appl)(struct capi_ctr *ctrlr, u16 applid) pointers to callback functions for registration and deregistration of applications with the device + Calls to these functions are serialized by Kernel CAPI so that only + one call to any of them is active at any time. u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) pointer to a callback function for sending a CAPI message to the device + Return value: CAPI error code + If the method returns 0 (CAPI_NOERROR) the driver has taken ownership + of the skb and the caller may no longer access it. If it returns a + non-zero (error) value then ownership of the skb returns to the caller + who may reuse or free it. + The return value should only be used to signal problems with respect + to accepting or queueing the message. Errors occurring during the + actual processing of the message should be signaled with an + appropriate reply message. + Calls to this function are not serialized by Kernel CAPI, ie. it must + be prepared to be re-entered. char *(*procinfo)(struct capi_ctr *ctrlr) pointer to a callback function returning the entry for the device in @@ -138,6 +154,8 @@ read_proc_t *ctr_read_proc system entry, /proc/capi/controllers/; will be called with a pointer to the device's capi_ctr structure as the last (data) argument +Note: Callback functions are never called in interrupt context. + - to be filled in before calling capi_ctr_ready(): u8 manu[CAPI_MANUFACTURER_LEN] @@ -153,6 +171,45 @@ u8 serial[CAPI_SERIAL_LEN] value to return for CAPI_GET_SERIAL +4.3 The _cmsg Structure + +(declared in ) + +The _cmsg structure stores the contents of a CAPI 2.0 message in an easily +accessible form. It contains members for all possible CAPI 2.0 parameters, of +which only those appearing in the message type currently being processed are +actually used. Unused members should be set to zero. + +Members are named after the CAPI 2.0 standard names of the parameters they +represent. See for the exact spelling. Member data +types are: + +u8 for CAPI parameters of type 'byte' + +u16 for CAPI parameters of type 'word' + +u32 for CAPI parameters of type 'dword' + +_cstruct for CAPI parameters of type 'struct' not containing any + variably-sized (struct) subparameters (eg. 'Called Party Number') + The member is a pointer to a buffer containing the parameter in + CAPI encoding (length + content). It may also be NULL, which will + be taken to represent an empty (zero length) parameter. + +_cmstruct for CAPI parameters of type 'struct' containing 'struct' + subparameters ('Additional Info' and 'B Protocol') + The representation is a single byte containing one of the values: + CAPI_DEFAULT: the parameter is empty + CAPI_COMPOSE: the values of the subparameters are stored + individually in the corresponding _cmsg structure members + +Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert +messages between their transport encoding described in the CAPI 2.0 standard +and their _cmsg structure representation. Note that capi_cmsg2message() does +not know or check the size of its destination buffer. The caller must make +sure it is big enough to accomodate the resulting CAPI message. + + 5. Lower Layer Interface Functions (declared in ) @@ -166,7 +223,7 @@ int detach_capi_ctr(struct capi_ctr *ctrlr) register/unregister a device (controller) with Kernel CAPI void capi_ctr_ready(struct capi_ctr *ctrlr) -void capi_ctr_reseted(struct capi_ctr *ctrlr) +void capi_ctr_down(struct capi_ctr *ctrlr) signal controller ready/not ready void capi_ctr_suspend_output(struct capi_ctr *ctrlr) @@ -211,3 +268,32 @@ CAPIMSG_CONTROL(m) CAPIMSG_SETCONTROL(m, contr) Controller/PLCI/NCCI (u32) CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16) + +Library functions for working with _cmsg structures +(from ): + +unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg) + Assembles a CAPI 2.0 message from the parameters in *cmsg, storing the + result in *msg. + +unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg) + Disassembles the CAPI 2.0 message in *msg, storing the parameters in + *cmsg. + +unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand, + u16 Messagenumber, u32 Controller) + Fills the header part and address field of the _cmsg structure *cmsg + with the given values, zeroing the remainder of the structure so only + parameters with non-default values need to be changed before sending + the message. + +void capi_cmsg_answer(_cmsg *cmsg) + Sets the low bit of the Subcommand field in *cmsg, thereby converting + _REQ to _CONF and _IND to _RESP. + +char *capi_cmd2str(u8 Command, u8 Subcommand) + Returns the CAPI 2.0 message name corresponding to the given command + and subcommand values, as a static ASCII string. The return value may + be NULL if the command/subcommand is not one of those defined in the + CAPI 2.0 standard. + diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset index 02c0e9341dd8..f9963103ae3d 100644 --- a/Documentation/isdn/README.gigaset +++ b/Documentation/isdn/README.gigaset @@ -149,10 +149,8 @@ GigaSet 307x Device Driver configuration files and chat scripts in the gigaset-VERSION/ppp directory in the driver packages from http://sourceforge.net/projects/gigaset307x/. Please note that the USB drivers are not able to change the state of the - control lines (the M105 driver can be configured to use some undocumented - control requests, if you really need the control lines, though). This means - you must use "Stupid Mode" if you are using wvdial or you should use the - nocrtscts option of pppd. + control lines. This means you must use "Stupid Mode" if you are using + wvdial or you should use the nocrtscts option of pppd. You must also assure that the ppp_async module is loaded with the parameter flag_time=0. You can do this e.g. by adding a line like @@ -190,20 +188,19 @@ GigaSet 307x Device Driver You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode setting (ttyGxy is ttyGU0 or ttyGB0). -2.6. M105 Undocumented USB Requests - ------------------------------ - - The Gigaset M105 USB data box understands a couple of useful, but - undocumented USB commands. These requests are not used in normal - operation (for wireless access to the base), but are needed for access - to the M105's own configuration mode (registration to the base, baudrate - and line format settings, device status queries) via the gigacontr - utility. Their use is controlled by the kernel configuration option - "Support for undocumented USB requests" (CONFIG_GIGASET_UNDOCREQ). If you - encounter error code -ENOTTY when trying to use some features of the - M105, try setting that option to "y" via 'make {x,menu}config' and - recompiling the driver. +2.6. Unregistered Wireless Devices (M101/M105) + ----------------------------------------- + The main purpose of the ser_gigaset and usb_gigaset drivers is to allow + the M101 and M105 wireless devices to be used as ISDN devices for ISDN + connections through a Gigaset base. Therefore they assume that the device + is registered to a DECT base. + If the M101/M105 device is not registered to a base, initialization of + the device fails, and a corresponding error message is logged by the + driver. In that situation, a restricted set of functions is available + which includes, in particular, those necessary for registering the device + to a base or for switching it between Fixed Part and Portable Part + modes. 3. Troubleshooting --------------- @@ -234,11 +231,12 @@ GigaSet 307x Device Driver Select Unimodem mode for all DECT data adapters. (see section 2.4.) Problem: - You want to configure your USB DECT data adapter (M105) but gigacontr - reports an error: "/dev/ttyGU0: Inappropriate ioctl for device". + Messages like this: + usb_gigaset 3-2:1.0: Could not initialize the device. + appear in your syslog. Solution: - Recompile the usb_gigaset driver with the kernel configuration option - CONFIG_GIGASET_UNDOCREQ set to 'y'. (see section 2.6.) + Check whether your M10x wireless device is correctly registered to the + Gigaset base. (see section 2.6.) 3.2. Telling the driver to provide more information ---------------------------------------------- diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt index 463d9e029ef3..cd79735013f9 100644 --- a/Documentation/networking/can.txt +++ b/Documentation/networking/can.txt @@ -36,10 +36,15 @@ This file contains 6.2 local loopback of sent frames 6.3 CAN controller hardware filters 6.4 The virtual CAN driver (vcan) - 6.5 currently supported CAN hardware - 6.6 todo + 6.5 The CAN network device driver interface + 6.5.1 Netlink interface to set/get devices properties + 6.5.2 Setting the CAN bit-timing + 6.5.3 Starting and stopping the CAN network device + 6.6 supported CAN hardware - 7 Credits + 7 Socket CAN resources + + 8 Credits ============================================================================ @@ -234,6 +239,8 @@ solution for a couple of reasons: the user application using the common CAN filter mechanisms. Inside this filter definition the (interested) type of errors may be selected. The reception of error frames is disabled by default. + The format of the CAN error frame is briefly decribed in the Linux + header file "include/linux/can/error.h". 4. How to use Socket CAN ------------------------ @@ -605,61 +612,213 @@ solution for a couple of reasons: removal of vcan network devices can be managed with the ip(8) tool: - Create a virtual CAN network interface: - ip link add type vcan + $ ip link add type vcan - Create a virtual CAN network interface with a specific name 'vcan42': - ip link add dev vcan42 type vcan + $ ip link add dev vcan42 type vcan - Remove a (virtual CAN) network interface 'vcan42': - ip link del vcan42 + $ ip link del vcan42 - The tool 'vcan' from the SocketCAN SVN repository on BerliOS is obsolete. + 6.5 The CAN network device driver interface - Virtual CAN network device creation in older Kernels: - In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan - netdevices at module load time by default. This value can be changed - with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8' + The CAN network device driver interface provides a generic interface + to setup, configure and monitor CAN network devices. The user can then + configure the CAN device, like setting the bit-timing parameters, via + the netlink interface using the program "ip" from the "IPROUTE2" + utility suite. The following chapter describes briefly how to use it. + Furthermore, the interface uses a common data structure and exports a + set of common functions, which all real CAN network device drivers + should use. Please have a look to the SJA1000 or MSCAN driver to + understand how to use them. The name of the module is can-dev.ko. - 6.5 currently supported CAN hardware + 6.5.1 Netlink interface to set/get devices properties - On the project website http://developer.berlios.de/projects/socketcan - there are different drivers available: + The CAN device must be configured via netlink interface. The supported + netlink message types are defined and briefly described in + "include/linux/can/netlink.h". CAN link support for the program "ip" + of the IPROUTE2 utility suite is avaiable and it can be used as shown + below: - vcan: Virtual CAN interface driver (if no real hardware is available) - sja1000: Philips SJA1000 CAN controller (recommended) - i82527: Intel i82527 CAN controller - mscan: Motorola/Freescale CAN controller (e.g. inside SOC MPC5200) - ccan: CCAN controller core (e.g. inside SOC h7202) - slcan: For a bunch of CAN adaptors that are attached via a - serial line ASCII protocol (for serial / USB adaptors) + - Setting CAN device properties: - Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport) - from PEAK Systemtechnik support the CAN netdevice driver model - since Linux driver v6.0: http://www.peak-system.com/linux/index.htm + $ ip link set can0 type can help + Usage: ip link set DEVICE type can + [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | + [ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1 + phase-seg2 PHASE-SEG2 [ sjw SJW ] ] - Please check the Mailing Lists on the berlios OSS project website. + [ loopback { on | off } ] + [ listen-only { on | off } ] + [ triple-sampling { on | off } ] - 6.6 todo + [ restart-ms TIME-MS ] + [ restart ] - The configuration interface for CAN network drivers is still an open - issue that has not been finalized in the socketcan project. Also the - idea of having a library module (candev.ko) that holds functions - that are needed by all CAN netdevices is not ready to ship. - Your contribution is welcome. + Where: BITRATE := { 1..1000000 } + SAMPLE-POINT := { 0.000..0.999 } + TQ := { NUMBER } + PROP-SEG := { 1..8 } + PHASE-SEG1 := { 1..8 } + PHASE-SEG2 := { 1..8 } + SJW := { 1..4 } + RESTART-MS := { 0 | NUMBER } -7. Credits + - Display CAN device details and statistics: + + $ ip -details -statistics link show can0 + 2: can0: mtu 16 qdisc pfifo_fast state UP qlen 10 + link/can + can state ERROR-ACTIVE restart-ms 100 + bitrate 125000 sample_point 0.875 + tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1 + sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1 + clock 8000000 + re-started bus-errors arbit-lost error-warn error-pass bus-off + 41 17457 0 41 42 41 + RX: bytes packets errors dropped overrun mcast + 140859 17608 17457 0 0 0 + TX: bytes packets errors dropped carrier collsns + 861 112 0 41 0 0 + + More info to the above output: + + "" + Shows the list of selected CAN controller modes: LOOPBACK, + LISTEN-ONLY, or TRIPLE-SAMPLING. + + "state ERROR-ACTIVE" + The current state of the CAN controller: "ERROR-ACTIVE", + "ERROR-WARNING", "ERROR-PASSIVE", "BUS-OFF" or "STOPPED" + + "restart-ms 100" + Automatic restart delay time. If set to a non-zero value, a + restart of the CAN controller will be triggered automatically + in case of a bus-off condition after the specified delay time + in milliseconds. By default it's off. + + "bitrate 125000 sample_point 0.875" + Shows the real bit-rate in bits/sec and the sample-point in the + range 0.000..0.999. If the calculation of bit-timing parameters + is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the + bit-timing can be defined by setting the "bitrate" argument. + Optionally the "sample-point" can be specified. By default it's + 0.000 assuming CIA-recommended sample-points. + + "tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1" + Shows the time quanta in ns, propagation segment, phase buffer + segment 1 and 2 and the synchronisation jump width in units of + tq. They allow to define the CAN bit-timing in a hardware + independent format as proposed by the Bosch CAN 2.0 spec (see + chapter 8 of http://www.semiconductors.bosch.de/pdf/can2spec.pdf). + + "sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1 + clock 8000000" + Shows the bit-timing constants of the CAN controller, here the + "sja1000". The minimum and maximum values of the time segment 1 + and 2, the synchronisation jump width in units of tq, the + bitrate pre-scaler and the CAN system clock frequency in Hz. + These constants could be used for user-defined (non-standard) + bit-timing calculation algorithms in user-space. + + "re-started bus-errors arbit-lost error-warn error-pass bus-off" + Shows the number of restarts, bus and arbitration lost errors, + and the state changes to the error-warning, error-passive and + bus-off state. RX overrun errors are listed in the "overrun" + field of the standard network statistics. + + 6.5.2 Setting the CAN bit-timing + + The CAN bit-timing parameters can always be defined in a hardware + independent format as proposed in the Bosch CAN 2.0 specification + specifying the arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" + and "sjw": + + $ ip link set canX type can tq 125 prop-seg 6 \ + phase-seg1 7 phase-seg2 2 sjw 1 + + If the kernel option CONFIG_CAN_CALC_BITTIMING is enabled, CIA + recommended CAN bit-timing parameters will be calculated if the bit- + rate is specified with the argument "bitrate": + + $ ip link set canX type can bitrate 125000 + + Note that this works fine for the most common CAN controllers with + standard bit-rates but may *fail* for exotic bit-rates or CAN system + clock frequencies. Disabling CONFIG_CAN_CALC_BITTIMING saves some + space and allows user-space tools to solely determine and set the + bit-timing parameters. The CAN controller specific bit-timing + constants can be used for that purpose. They are listed by the + following command: + + $ ip -details link show can0 + ... + sja1000: clock 8000000 tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1 + + 6.5.3 Starting and stopping the CAN network device + + A CAN network device is started or stopped as usual with the command + "ifconfig canX up/down" or "ip link set canX up/down". Be aware that + you *must* define proper bit-timing parameters for real CAN devices + before you can start it to avoid error-prone default settings: + + $ ip link set canX up type can bitrate 125000 + + A device may enter the "bus-off" state if too much errors occurred on + the CAN bus. Then no more messages are received or sent. An automatic + bus-off recovery can be enabled by setting the "restart-ms" to a + non-zero value, e.g.: + + $ ip link set canX type can restart-ms 100 + + Alternatively, the application may realize the "bus-off" condition + by monitoring CAN error frames and do a restart when appropriate with + the command: + + $ ip link set canX type can restart + + Note that a restart will also create a CAN error frame (see also + chapter 3.4). + + 6.6 Supported CAN hardware + + Please check the "Kconfig" file in "drivers/net/can" to get an actual + list of the support CAN hardware. On the Socket CAN project website + (see chapter 7) there might be further drivers available, also for + older kernel versions. + +7. Socket CAN resources +----------------------- + + You can find further resources for Socket CAN like user space tools, + support for old kernel versions, more drivers, mailing lists, etc. + at the BerliOS OSS project website for Socket CAN: + + http://developer.berlios.de/projects/socketcan + + If you have questions, bug fixes, etc., don't hesitate to post them to + the Socketcan-Users mailing list. But please search the archives first. + +8. Credits ---------- - Oliver Hartkopp (PF_CAN core, filters, drivers, bcm) + Oliver Hartkopp (PF_CAN core, filters, drivers, bcm, SJA1000 driver) Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan) Jan Kizka (RT-SocketCAN core, Socket-API reconciliation) - Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews) + Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews, + CAN device driver interface, MSCAN driver) Robert Schwebel (design reviews, PTXdist integration) Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers) Benedikt Spranger (reviews) Thomas Gleixner (LKML reviews, coding style, posting hints) - Andrey Volkov (kernel subtree structure, ioctls, mscan driver) + Andrey Volkov (kernel subtree structure, ioctls, MSCAN driver) Matthias Brukner (first SJA1000 CAN netdevice implementation Q2/2003) Klaus Hitschler (PEAK driver integration) Uwe Koppe (CAN netdevices with PF_PACKET approach) Michael Schulze (driver layer loopback requirement, RT CAN drivers review) + Pavel Pisa (Bit-timing calculation) + Sascha Hauer (SJA1000 platform driver) + Sebastian Haas (SJA1000 EMS PCI driver) + Markus Plessing (SJA1000 EMS PCI driver) + Per Dalen (SJA1000 Kvaser PCI driver) + Sam Ravnborg (reviews, coding style, kbuild help) diff --git a/Documentation/networking/ieee802154.txt b/Documentation/networking/ieee802154.txt new file mode 100644 index 000000000000..a0280ad2edc9 --- /dev/null +++ b/Documentation/networking/ieee802154.txt @@ -0,0 +1,76 @@ + + Linux IEEE 802.15.4 implementation + + +Introduction +============ + +The Linux-ZigBee project goal is to provide complete implementation +of IEEE 802.15.4 / ZigBee / 6LoWPAN protocols. IEEE 802.15.4 is a stack +of protocols for organizing Low-Rate Wireless Personal Area Networks. + +Currently only IEEE 802.15.4 layer is implemented. We have choosen +to use plain Berkeley socket API, the generic Linux networking stack +to transfer IEEE 802.15.4 messages and a special protocol over genetlink +for configuration/management + + +Socket API +========== + +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 +in our userspace package (see either linux-zigbee sourceforge download page +or git tree at git://linux-zigbee.git.sourceforge.net/gitroot/linux-zigbee). + +One can use SOCK_RAW for passing raw data towards device xmit function. YMMV. + + +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 above) provides CLI configuration utility for radio interfaces and simple +coordinator for IEEE 802.15.4 networks as an example users of MLME protocol. + + +Kernel side +============= + +Like with WiFi, there are several types of devices implementing IEEE 802.15.4. +1) 'HardMAC'. The MAC layer is implemented in the device itself, the device + exports MLME and data API. +2) 'SoftMAC' or just radio. These types of devices are just radio transceivers + possibly with some kinds of acceleration like automatic CRC computation and + comparation, automagic ACK handling, address matching, etc. + +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 +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. + +To hook the MLME interface you have to populate the ml_priv field of your +net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are +required. + +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 +in software. This is currently WIP. + +See header include/net/ieee802154/mac802154.h and several drivers in +drivers/ieee802154/ diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index b121c5db707f..8be76235fe67 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -168,7 +168,16 @@ tcp_dsack - BOOLEAN Allows TCP to send "duplicate" SACKs. tcp_ecn - BOOLEAN - Enable Explicit Congestion Notification in TCP. + Enable Explicit Congestion Notification (ECN) in TCP. ECN is only + used when both ends of the TCP flow support it. It is useful to + avoid losses due to congestion (when the bottleneck router supports + ECN). + Possible values are: + 0 disable ECN + 1 ECN enabled + 2 Only server-side ECN enabled. If the other end does + not support ECN, behavior is like with ECN disabled. + Default: 2 tcp_fack - BOOLEAN Enable FACK congestion avoidance and fast retransmission. @@ -1048,6 +1057,13 @@ disable_ipv6 - BOOLEAN address. Default: FALSE (enable IPv6 operation) + When this value is changed from 1 to 0 (IPv6 is being enabled), + it will dynamically create a link-local address on the given + interface and start Duplicate Address Detection, if necessary. + + When this value is changed from 0 to 1 (IPv6 is being disabled), + it will dynamically delete all address on the given interface. + accept_dad - INTEGER Whether to accept DAD (Duplicate Address Detection). 0: Disable DAD diff --git a/Documentation/networking/ipv6.txt b/Documentation/networking/ipv6.txt index 268e5c103dd8..9fd7e21296c8 100644 --- a/Documentation/networking/ipv6.txt +++ b/Documentation/networking/ipv6.txt @@ -33,3 +33,40 @@ disable A reboot is required to enable IPv6. +autoconf + + Specifies whether to enable IPv6 address autoconfiguration + on all interfaces. This might be used when one does not wish + for addresses to be automatically generated from prefixes + received in Router Advertisements. + + The possible values and their effects are: + + 0 + IPv6 address autoconfiguration is disabled on all interfaces. + + Only the IPv6 loopback address (::1) and link-local addresses + will be added to interfaces. + + 1 + IPv6 address autoconfiguration is enabled on all interfaces. + + This is the default value. + +disable_ipv6 + + Specifies whether to disable IPv6 on all interfaces. + This might be used when no IPv6 addresses are desired. + + The possible values and their effects are: + + 0 + IPv6 is enabled on all interfaces. + + This is the default value. + + 1 + IPv6 is disabled on all interfaces. + + No IPv6 addresses will be added to interfaces. + diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt index 84906ef3ed6e..b30e81ad5307 100644 --- a/Documentation/networking/mac80211-injection.txt +++ b/Documentation/networking/mac80211-injection.txt @@ -12,38 +12,22 @@ following format: The radiotap format is discussed in ./Documentation/networking/radiotap-headers.txt. -Despite 13 radiotap argument types are currently defined, most only make sense +Despite many radiotap parameters being currently defined, most only make sense to appear on received packets. The following information is parsed from the radiotap headers and used to control injection: - * IEEE80211_RADIOTAP_RATE - - rate in 500kbps units, automatic if invalid or not present - - - * IEEE80211_RADIOTAP_ANTENNA - - antenna to use, automatic if not present - - - * IEEE80211_RADIOTAP_DBM_TX_POWER - - transmit power in dBm, automatic if not present - - * IEEE80211_RADIOTAP_FLAGS IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the - current fragmentation threshold. Note that - this flag is only reliable when software - fragmentation is enabled) + current fragmentation threshold. + The injection code can also skip all other currently defined radiotap fields facilitating replay of captured radiotap headers directly. -Here is an example valid radiotap header defining these three parameters +Here is an example valid radiotap header defining some parameters 0x00, 0x00, // <-- radiotap version 0x0b, 0x00, // <- radiotap header length @@ -72,8 +56,8 @@ interface), along the following lines: ... r = pcap_inject(ppcap, u8aSendBuffer, nLength); -You can also find sources for a complete inject test applet here: +You can also find a link to a complete inject application here: -http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer +http://wireless.kernel.org/en/users/Documentation/packetspammer Andy Green diff --git a/Documentation/networking/operstates.txt b/Documentation/networking/operstates.txt index c9074f9b78bb..1a77a3cfae54 100644 --- a/Documentation/networking/operstates.txt +++ b/Documentation/networking/operstates.txt @@ -38,9 +38,6 @@ ifinfomsg::if_flags & IFF_LOWER_UP: ifinfomsg::if_flags & IFF_DORMANT: Driver has signaled netif_dormant_on() -These interface flags can also be queried without netlink using the -SIOCGIFFLAGS ioctl. - TLV IFLA_OPERSTATE contains RFC2863 state of the interface in numeric representation: diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 07c53d596035..a22fd85e3796 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -4,16 +4,18 @@ This file documents the CONFIG_PACKET_MMAP option available with the PACKET socket interface on 2.4 and 2.6 kernels. This type of sockets is used for -capture network traffic with utilities like tcpdump or any other that uses -the libpcap library. - -You can find the latest version of this document at +capture network traffic with utilities like tcpdump or any other that needs +raw access to network interface. +You can find the latest version of this document at: http://pusa.uv.es/~ulisses/packet_mmap/ -Please send me your comments to +Howto can be found at: + http://wiki.gnu-log.net (packet_mmap) +Please send your comments to Ulisses Alonso CamarĂ³ + Johann Baudy ------------------------------------------------------------------------------- + Why use PACKET_MMAP @@ -25,19 +27,24 @@ to capture each packet, it requires two if you want to get packet's timestamp (like libpcap always does). In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size -configurable circular buffer mapped in user space. This way reading packets just -needs to wait for them, most of the time there is no need to issue a single -system call. By using a shared buffer between the kernel and the user -also has the benefit of minimizing packet copies. +configurable circular buffer mapped in user space that can be used to either +send or receive packets. This way reading packets just needs to wait for them, +most of the time there is no need to issue a single system call. Concerning +transmission, multiple packets can be sent through one system call to get the +highest bandwidth. +By using a shared buffer between the kernel and the user also has the benefit +of minimizing packet copies. -It's fine to use PACKET_MMAP to improve the performance of the capture process, -but it isn't everything. At least, if you are capturing at high speeds (this -is relative to the cpu speed), you should check if the device driver of your -network interface card supports some sort of interrupt load mitigation or -(even better) if it supports NAPI, also make sure it is enabled. +It's fine to use PACKET_MMAP to improve the performance of the capture and +transmission process, but it isn't everything. At least, if you are capturing +at high speeds (this is relative to the cpu speed), you should check if the +device driver of your network interface card supports some sort of interrupt +load mitigation or (even better) if it supports NAPI, also make sure it is +enabled. For transmission, check the MTU (Maximum Transmission Unit) used and +supported by devices of your network. -------------------------------------------------------------------------------- -+ How to use CONFIG_PACKET_MMAP ++ How to use CONFIG_PACKET_MMAP to improve capture process -------------------------------------------------------------------------------- From the user standpoint, you should use the higher level libpcap library, which @@ -57,7 +64,7 @@ the low level details or want to improve libpcap by including PACKET_MMAP support. -------------------------------------------------------------------------------- -+ How to use CONFIG_PACKET_MMAP directly ++ How to use CONFIG_PACKET_MMAP directly to improve capture process -------------------------------------------------------------------------------- From the system calls stand point, the use of PACKET_MMAP involves @@ -66,6 +73,7 @@ the following process: [setup] socket() -------> creation of the capture socket setsockopt() ---> allocation of the circular buffer (ring) + option: PACKET_RX_RING mmap() ---------> mapping of the allocated buffer to the user process @@ -96,6 +104,65 @@ Next I will describe PACKET_MMAP settings and it's constraints, also the mapping of the circular buffer in the user process and the use of this buffer. +-------------------------------------------------------------------------------- ++ How to use CONFIG_PACKET_MMAP directly to improve transmission process +-------------------------------------------------------------------------------- +Transmission process is similar to capture as shown below. + +[setup] socket() -------> creation of the transmission socket + setsockopt() ---> allocation of the circular buffer (ring) + option: PACKET_TX_RING + bind() ---------> bind transmission socket with a network interface + mmap() ---------> mapping of the allocated buffer to the + user process + +[transmission] poll() ---------> wait for free packets (optional) + send() ---------> send all packets that are set as ready in + the ring + The flag MSG_DONTWAIT can be used to return + before end of transfer. + +[shutdown] close() --------> destruction of the transmission socket and + deallocation of all associated resources. + +Binding the socket to your network interface is mandatory (with zero copy) to +know the header size of frames used in the circular buffer. + +As capture, each frame contains two parts: + + -------------------- +| struct tpacket_hdr | Header. It contains the status of +| | of this frame +|--------------------| +| data buffer | +. . Data that will be sent over the network interface. +. . + -------------------- + + bind() associates the socket to your network interface thanks to + sll_ifindex parameter of struct sockaddr_ll. + + Initialization example: + + struct sockaddr_ll my_addr; + struct ifreq s_ifr; + ... + + strncpy (s_ifr.ifr_name, "eth0", sizeof(s_ifr.ifr_name)); + + /* get interface index of eth0 */ + ioctl(this->socket, SIOCGIFINDEX, &s_ifr); + + /* fill sockaddr_ll struct to prepare binding */ + my_addr.sll_family = AF_PACKET; + my_addr.sll_protocol = ETH_P_ALL; + my_addr.sll_ifindex = s_ifr.ifr_ifindex; + + /* bind socket to eth0 */ + bind(this->socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_ll)); + + A complete tutorial is available at: http://wiki.gnu-log.net/ + -------------------------------------------------------------------------------- + PACKET_MMAP settings -------------------------------------------------------------------------------- @@ -103,7 +170,10 @@ the use of this buffer. To setup PACKET_MMAP from user level code is done with a call like + - Capture process setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req)) + - Transmission process + setsockopt(fd, SOL_PACKET, PACKET_TX_RING, (void *) &req, sizeof(req)) The most significant argument in the previous call is the req parameter, this parameter must to have the following structure: @@ -117,11 +187,11 @@ this parameter must to have the following structure: }; This structure is defined in /usr/include/linux/if_packet.h and establishes a -circular buffer (ring) of unswappable memory mapped in the capture process. +circular buffer (ring) of unswappable memory. Being mapped in the capture process allows reading the captured frames and related meta-information like timestamps without requiring a system call. -Captured frames are grouped in blocks. Each block is a physically contiguous +Frames are grouped in blocks. Each block is a physically contiguous region of memory and holds tp_block_size/tp_frame_size frames. The total number of blocks is tp_block_nr. Note that tp_frame_nr is a redundant parameter because @@ -336,6 +406,7 @@ struct tpacket_hdr). If this field is 0 means that the frame is ready to be used for the kernel, If not, there is a frame the user can read and the following flags apply: ++++ Capture process: from include/linux/if_packet.h #define TP_STATUS_COPY 2 @@ -391,6 +462,37 @@ packets are in the ring: It doesn't incur in a race condition to first check the status value and then poll for frames. + +++ Transmission process +Those defines are also used for transmission: + + #define TP_STATUS_AVAILABLE 0 // Frame is available + #define TP_STATUS_SEND_REQUEST 1 // Frame will be sent on next send() + #define TP_STATUS_SENDING 2 // Frame is currently in transmission + #define TP_STATUS_WRONG_FORMAT 4 // Frame format is not correct + +First, the kernel initializes all frames to TP_STATUS_AVAILABLE. To send a +packet, the user fills a data buffer of an available frame, sets tp_len to +current data buffer size and sets its status field to TP_STATUS_SEND_REQUEST. +This can be done on multiple frames. Once the user is ready to transmit, it +calls send(). Then all buffers with status equal to TP_STATUS_SEND_REQUEST are +forwarded to the network device. The kernel updates each status of sent +frames with TP_STATUS_SENDING until the end of transfer. +At the end of each transfer, buffer status returns to TP_STATUS_AVAILABLE. + + header->tp_len = in_i_size; + header->tp_status = TP_STATUS_SEND_REQUEST; + retval = send(this->socket, NULL, 0, 0); + +The user can also use poll() to check if a buffer is available: +(status == TP_STATUS_SENDING) + + struct pollfd pfd; + pfd.fd = fd; + pfd.revents = 0; + pfd.events = POLLOUT; + retval = poll(&pfd, 1, timeout); + -------------------------------------------------------------------------------- + THANKS -------------------------------------------------------------------------------- diff --git a/Documentation/powerpc/dts-bindings/can/sja1000.txt b/Documentation/powerpc/dts-bindings/can/sja1000.txt new file mode 100644 index 000000000000..d6d209ded937 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/can/sja1000.txt @@ -0,0 +1,53 @@ +Memory mapped SJA1000 CAN controller from NXP (formerly Philips) + +Required properties: + +- compatible : should be "nxp,sja1000". + +- reg : should specify the chip select, address offset and size required + to map the registers of the SJA1000. The size is usually 0x80. + +- interrupts: property with a value describing the interrupt source + (number and sensitivity) required for the SJA1000. + +Optional properties: + +- nxp,external-clock-frequency : Frequency of the external oscillator + clock in Hz. Note that the internal clock frequency used by the + SJA1000 is half of that value. If not specified, a default value + of 16000000 (16 MHz) is used. + +- nxp,tx-output-mode : operation mode of the TX output control logic: + <0x0> : bi-phase output mode + <0x1> : normal output mode (default) + <0x2> : test output mode + <0x3> : clock output mode + +- nxp,tx-output-config : TX output pin configuration: + <0x01> : TX0 invert + <0x02> : TX0 pull-down (default) + <0x04> : TX0 pull-up + <0x06> : TX0 push-pull + <0x08> : TX1 invert + <0x10> : TX1 pull-down + <0x20> : TX1 pull-up + <0x30> : TX1 push-pull + +- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin. + If not specified or if the specified value is 0, the CLKOUT pin + will be disabled. + +- nxp,no-comparator-bypass : Allows to disable the CAN input comperator. + +For futher information, please have a look to the SJA1000 data sheet. + +Examples: + +can@3,100 { + compatible = "nxp,sja1000"; + reg = <3 0x100 0x80>; + interrupts = <2 0>; + interrupt-parent = <&mpic>; + nxp,external-clock-frequency = <16000000>; +}; + diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index 4d3ee317a4a3..1b74b5f30af4 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt @@ -1,575 +1,136 @@ -rfkill - RF switch subsystem support -==================================== +rfkill - RF kill switch support +=============================== -1 Introduction -2 Implementation details -3 Kernel driver guidelines -3.1 wireless device drivers -3.2 platform/switch drivers -3.3 input device drivers -4 Kernel API -5 Userspace support +1. Introduction +2. Implementation details +3. Kernel driver guidelines +4. Kernel API +5. Userspace support -1. Introduction: +1. Introduction -The rfkill switch subsystem exists to add a generic interface to circuitry that -can enable or disable the signal output of a wireless *transmitter* of any -type. By far, the most common use is to disable radio-frequency transmitters. +The rfkill subsystem provides a generic interface to disabling any radio +transmitter in the system. When a transmitter is blocked, it shall not +radiate any power. -Note that disabling the signal output means that the the transmitter is to be -made to not emit any energy when "blocked". rfkill is not about blocking data -transmissions, it is about blocking energy emission. +The subsystem also provides the ability to react on button presses and +disable all transmitters of a certain type (or all). This is intended for +situations where transmitters need to be turned off, for example on +aircraft. -The rfkill subsystem offers support for keys and switches often found on -laptops to enable wireless devices like WiFi and Bluetooth, so that these keys -and switches actually perform an action in all wireless devices of a given type -attached to the system. -The buttons to enable and disable the wireless transmitters are important in -situations where the user is for example using his laptop on a location where -radio-frequency transmitters _must_ be disabled (e.g. airplanes). -Because of this requirement, userspace support for the keys should not be made -mandatory. Because userspace might want to perform some additional smarter -tasks when the key is pressed, rfkill provides userspace the possibility to -take over the task to handle the key events. - -=============================================================================== -2: Implementation details +2. Implementation details The rfkill subsystem is composed of various components: the rfkill class, the rfkill-input module (an input layer handler), and some specific input layer events. -The rfkill class provides kernel drivers with an interface that allows them to -know when they should enable or disable a wireless network device transmitter. -This is enabled by the CONFIG_RFKILL Kconfig option. +The rfkill class is provided for kernel drivers to register their radio +transmitter with the kernel, provide methods for turning it on and off and, +optionally, letting the system know about hardware-disabled states that may +be implemented on the device. This code is enabled with the CONFIG_RFKILL +Kconfig option, which drivers can "select". -The rfkill class support makes sure userspace will be notified of all state -changes on rfkill devices through uevents. It provides a notification chain -for interested parties in the kernel to also get notified of rfkill state -changes in other drivers. It creates several sysfs entries which can be used -by userspace. See section "Userspace support". +The rfkill class code also notifies userspace of state changes, this is +achieved via uevents. It also provides some sysfs files for userspace to +check the status of radio transmitters. See the "Userspace support" section +below. -The rfkill-input module provides the kernel with the ability to implement a -basic response when the user presses a key or button (or toggles a switch) -related to rfkill functionality. It is an in-kernel implementation of default -policy of reacting to rfkill-related input events and neither mandatory nor -required for wireless drivers to operate. It is enabled by the -CONFIG_RFKILL_INPUT Kconfig option. -rfkill-input is a rfkill-related events input layer handler. This handler will -listen to all rfkill key events and will change the rfkill state of the -wireless devices accordingly. With this option enabled userspace could either -do nothing or simply perform monitoring tasks. +The rfkill-input code implements a basic response to rfkill buttons -- it +implements turning on/off all devices of a certain class (or all). -The rfkill-input module also provides EPO (emergency power-off) functionality -for all wireless transmitters. This function cannot be overridden, and it is -always active. rfkill EPO is related to *_RFKILL_ALL input layer events. +When the device is hard-blocked (either by a call to rfkill_set_hw_state() +or from query_hw_block) set_block() will be invoked but drivers can well +ignore the method call since they can use the return value of the function +rfkill_set_hw_state() to sync the software state instead of keeping track +of calls to set_block(). -Important terms for the rfkill subsystem: +The entire functionality is spread over more than one subsystem: -In order to avoid confusion, we avoid the term "switch" in rfkill when it is -referring to an electronic control circuit that enables or disables a -transmitter. We reserve it for the physical device a human manipulates -(which is an input device, by the way): + * The kernel input layer generates KEY_WWAN, KEY_WLAN etc. and + SW_RFKILL_ALL -- when the user presses a button. Drivers for radio + transmitters generally do not register to the input layer, unless the + device really provides an input device (i.e. a button that has no + effect other than generating a button press event) -rfkill switch: + * The rfkill-input code hooks up to these events and switches the soft-block + of the various radio transmitters, depending on the button type. - A physical device a human manipulates. Its state can be perceived by - the kernel either directly (through a GPIO pin, ACPI GPE) or by its - effect on a rfkill line of a wireless device. + * The rfkill drivers turn off/on their transmitters as requested. -rfkill controller: + * The rfkill class will generate userspace notifications (uevents) to tell + userspace what the current state is. - A hardware circuit that controls the state of a rfkill line, which a - kernel driver can interact with *to modify* that state (i.e. it has - either write-only or read/write access). -rfkill line: - An input channel (hardware or software) of a wireless device, which - causes a wireless transmitter to stop emitting energy (BLOCK) when it - is active. Point of view is extremely important here: rfkill lines are - always seen from the PoV of a wireless device (and its driver). +3. Kernel driver guidelines -soft rfkill line/software rfkill line: - A rfkill line the wireless device driver can directly change the state - of. Related to rfkill_state RFKILL_STATE_SOFT_BLOCKED. +Drivers for radio transmitters normally implement only the rfkill class. +These drivers may not unblock the transmitter based on own decisions, they +should act on information provided by the rfkill class only. -hard rfkill line/hardware rfkill line: +Platform drivers might implement input devices if the rfkill button is just +that, a button. If that button influences the hardware then you need to +implement an rfkill class instead. This also applies if the platform provides +a way to turn on/off the transmitter(s). - A rfkill line that works fully in hardware or firmware, and that cannot - be overridden by the kernel driver. The hardware device or the - firmware just exports its status to the driver, but it is read-only. - Related to rfkill_state RFKILL_STATE_HARD_BLOCKED. +During suspend/hibernation, transmitters should only be left enabled when +wake-on wlan or similar functionality requires it and the device wasn't +blocked before suspend/hibernate. Note that it may be necessary to update +the rfkill subsystem's idea of what the current state is at resume time if +the state may have changed over suspend. -The enum rfkill_state describes the rfkill state of a transmitter: -When a rfkill line or rfkill controller is in the RFKILL_STATE_UNBLOCKED state, -the wireless transmitter (radio TX circuit for example) is *enabled*. When the -it is in the RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the -wireless transmitter is to be *blocked* from operating. -RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change -that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio() -will not be able to change the state and will return with a suitable error if -attempts are made to set the state to RFKILL_STATE_UNBLOCKED. - -RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is -locked in the BLOCKED state by a hardwire rfkill line (typically an input pin -that, when active, forces the transmitter to be disabled) which the driver -CANNOT override. - -Full rfkill functionality requires two different subsystems to cooperate: the -input layer and the rfkill class. The input layer issues *commands* to the -entire system requesting that devices registered to the rfkill class change -state. The way this interaction happens is not complex, but it is not obvious -either: - -Kernel Input layer: - - * Generates KEY_WWAN, KEY_WLAN, KEY_BLUETOOTH, SW_RFKILL_ALL, and - other such events when the user presses certain keys, buttons, or - toggles certain physical switches. - - THE INPUT LAYER IS NEVER USED TO PROPAGATE STATUS, NOTIFICATIONS OR THE - KIND OF STUFF AN ON-SCREEN-DISPLAY APPLICATION WOULD REPORT. It is - used to issue *commands* for the system to change behaviour, and these - commands may or may not be carried out by some kernel driver or - userspace application. It follows that doing user feedback based only - on input events is broken, as there is no guarantee that an input event - will be acted upon. - - Most wireless communication device drivers implementing rfkill - functionality MUST NOT generate these events, and have no reason to - register themselves with the input layer. Doing otherwise is a common - misconception. There is an API to propagate rfkill status change - information, and it is NOT the input layer. - -rfkill class: - - * Calls a hook in a driver to effectively change the wireless - transmitter state; - * Keeps track of the wireless transmitter state (with help from - the driver); - * Generates userspace notifications (uevents) and a call to a - notification chain (kernel) when there is a wireless transmitter - state change; - * Connects a wireless communications driver with the common rfkill - control system, which, for example, allows actions such as - "switch all bluetooth devices offline" to be carried out by - userspace or by rfkill-input. - - THE RFKILL CLASS NEVER ISSUES INPUT EVENTS. THE RFKILL CLASS DOES - NOT LISTEN TO INPUT EVENTS. NO DRIVER USING THE RFKILL CLASS SHALL - EVER LISTEN TO, OR ACT ON RFKILL INPUT EVENTS. Doing otherwise is - a layering violation. - - Most wireless data communication drivers in the kernel have just to - implement the rfkill class API to work properly. Interfacing to the - input layer is not often required (and is very often a *bug*) on - wireless drivers. - - Platform drivers often have to attach to the input layer to *issue* - (but never to listen to) rfkill events for rfkill switches, and also to - the rfkill class to export a control interface for the platform rfkill - controllers to the rfkill subsystem. This does NOT mean the rfkill - switch is attached to a rfkill class (doing so is almost always wrong). - It just means the same kernel module is the driver for different - devices (rfkill switches and rfkill controllers). - - -Userspace input handlers (uevents) or kernel input handlers (rfkill-input): - - * Implements the policy of what should happen when one of the input - layer events related to rfkill operation is received. - * Uses the sysfs interface (userspace) or private rfkill API calls - to tell the devices registered with the rfkill class to change - their state (i.e. translates the input layer event into real - action). - - * rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0 - (power off all transmitters) in a special way: it ignores any - overrides and local state cache and forces all transmitters to the - RFKILL_STATE_SOFT_BLOCKED state (including those which are already - supposed to be BLOCKED). - * rfkill EPO will remain active until rfkill-input receives an - EV_SW SW_RFKILL_ALL 1 event. While the EPO is active, transmitters - are locked in the blocked state (rfkill will refuse to unblock them). - * rfkill-input implements different policies that the user can - select for handling EV_SW SW_RFKILL_ALL 1. It will unlock rfkill, - and either do nothing (leave transmitters blocked, but now unlocked), - restore the transmitters to their state before the EPO, or unblock - them all. - -Userspace uevent handler or kernel platform-specific drivers hooked to the -rfkill notifier chain: - - * Taps into the rfkill notifier chain or to KOBJ_CHANGE uevents, - in order to know when a device that is registered with the rfkill - class changes state; - * Issues feedback notifications to the user; - * In the rare platforms where this is required, synthesizes an input - event to command all *OTHER* rfkill devices to also change their - statues when a specific rfkill device changes state. - - -=============================================================================== -3: Kernel driver guidelines - -Remember: point-of-view is everything for a driver that connects to the rfkill -subsystem. All the details below must be measured/perceived from the point of -view of the specific driver being modified. - -The first thing one needs to know is whether his driver should be talking to -the rfkill class or to the input layer. In rare cases (platform drivers), it -could happen that you need to do both, as platform drivers often handle a -variety of devices in the same driver. - -Do not mistake input devices for rfkill controllers. The only type of "rfkill -switch" device that is to be registered with the rfkill class are those -directly controlling the circuits that cause a wireless transmitter to stop -working (or the software equivalent of them), i.e. what we call a rfkill -controller. Every other kind of "rfkill switch" is just an input device and -MUST NOT be registered with the rfkill class. - -A driver should register a device with the rfkill class when ALL of the -following conditions are met (they define a rfkill controller): - -1. The device is/controls a data communications wireless transmitter; - -2. The kernel can interact with the hardware/firmware to CHANGE the wireless - transmitter state (block/unblock TX operation); - -3. The transmitter can be made to not emit any energy when "blocked": - rfkill is not about blocking data transmissions, it is about blocking - energy emission; - -A driver should register a device with the input subsystem to issue -rfkill-related events (KEY_WLAN, KEY_BLUETOOTH, KEY_WWAN, KEY_WIMAX, -SW_RFKILL_ALL, etc) when ALL of the folowing conditions are met: - -1. It is directly related to some physical device the user interacts with, to - command the O.S./firmware/hardware to enable/disable a data communications - wireless transmitter. - - Examples of the physical device are: buttons, keys and switches the user - will press/touch/slide/switch to enable or disable the wireless - communication device. - -2. It is NOT slaved to another device, i.e. there is no other device that - issues rfkill-related input events in preference to this one. - - Please refer to the corner cases and examples section for more details. - -When in doubt, do not issue input events. For drivers that should generate -input events in some platforms, but not in others (e.g. b43), the best solution -is to NEVER generate input events in the first place. That work should be -deferred to a platform-specific kernel module (which will know when to generate -events through the rfkill notifier chain) or to userspace. This avoids the -usual maintenance problems with DMI whitelisting. - - -Corner cases and examples: -==================================== - -1. If the device is an input device that, because of hardware or firmware, -causes wireless transmitters to be blocked regardless of the kernel's will, it -is still just an input device, and NOT to be registered with the rfkill class. - -2. If the wireless transmitter switch control is read-only, it is an input -device and not to be registered with the rfkill class (and maybe not to be made -an input layer event source either, see below). - -3. If there is some other device driver *closer* to the actual hardware the -user interacted with (the button/switch/key) to issue an input event, THAT is -the device driver that should be issuing input events. - -E.g: - [RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input] - (platform driver) (wireless card driver) - -The user is closer to the RFKILL slide switch plaform driver, so the driver -which must issue input events is the platform driver looking at the GPIO -hardware, and NEVER the wireless card driver (which is just a slave). It is -very likely that there are other leaves than just the WLAN card rf-kill input -(e.g. a bluetooth card, etc)... - -On the other hand, some embedded devices do this: - - [RFKILL slider switch] -- [WLAN card rf-kill input] - (wireless card driver) - -In this situation, the wireless card driver *could* register itself as an input -device and issue rf-kill related input events... but in order to AVOID the need -for DMI whitelisting, the wireless card driver does NOT do it. Userspace (HAL) -or a platform driver (that exists only on these embedded devices) will do the -dirty job of issuing the input events. - - -COMMON MISTAKES in kernel drivers, related to rfkill: -==================================== - -1. NEVER confuse input device keys and buttons with input device switches. - - 1a. Switches are always set or reset. They report the current state - (on position or off position). - - 1b. Keys and buttons are either in the pressed or not-pressed state, and - that's it. A "button" that latches down when you press it, and - unlatches when you press it again is in fact a switch as far as input - devices go. - -Add the SW_* events you need for switches, do NOT try to emulate a button using -KEY_* events just because there is no such SW_* event yet. Do NOT try to use, -for example, KEY_BLUETOOTH when you should be using SW_BLUETOOTH instead. - -2. Input device switches (sources of EV_SW events) DO store their current state -(so you *must* initialize it by issuing a gratuitous input layer event on -driver start-up and also when resuming from sleep), and that state CAN be -queried from userspace through IOCTLs. There is no sysfs interface for this, -but that doesn't mean you should break things trying to hook it to the rfkill -class to get a sysfs interface :-) - -3. Do not issue *_RFKILL_ALL events by default, unless you are sure it is the -correct event for your switch/button. These events are emergency power-off -events when they are trying to turn the transmitters off. An example of an -input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill -switch in a laptop which is NOT a hotkey, but a real sliding/rocker switch. -An example of an input device which SHOULD NOT generate *_RFKILL_ALL events by -default, is any sort of hot key that is type-specific (e.g. the one for WLAN). - - -3.1 Guidelines for wireless device drivers ------------------------------------------- - -(in this text, rfkill->foo means the foo field of struct rfkill). - -1. Each independent transmitter in a wireless device (usually there is only one -transmitter per device) should have a SINGLE rfkill class attached to it. - -2. If the device does not have any sort of hardware assistance to allow the -driver to rfkill the device, the driver should emulate it by taking all actions -required to silence the transmitter. - -3. If it is impossible to silence the transmitter (i.e. it still emits energy, -even if it is just in brief pulses, when there is no data to transmit and there -is no hardware support to turn it off) do NOT lie to the users. Do not attach -it to a rfkill class. The rfkill subsystem does not deal with data -transmission, it deals with energy emission. If the transmitter is emitting -energy, it is not blocked in rfkill terms. - -4. It doesn't matter if the device has multiple rfkill input lines affecting -the same transmitter, their combined state is to be exported as a single state -per transmitter (see rule 1). - -This rule exists because users of the rfkill subsystem expect to get (and set, -when possible) the overall transmitter rfkill state, not of a particular rfkill -line. - -5. The wireless device driver MUST NOT leave the transmitter enabled during -suspend and hibernation unless: - - 5.1. The transmitter has to be enabled for some sort of functionality - like wake-on-wireless-packet or autonomous packed forwarding in a mesh - network, and that functionality is enabled for this suspend/hibernation - cycle. - -AND - - 5.2. The device was not on a user-requested BLOCKED state before - the suspend (i.e. the driver must NOT unblock a device, not even - to support wake-on-wireless-packet or remain in the mesh). - -In other words, there is absolutely no allowed scenario where a driver can -automatically take action to unblock a rfkill controller (obviously, this deals -with scenarios where soft-blocking or both soft and hard blocking is happening. -Scenarios where hardware rfkill lines are the only ones blocking the -transmitter are outside of this rule, since the wireless device driver does not -control its input hardware rfkill lines in the first place). - -6. During resume, rfkill will try to restore its previous state. - -7. After a rfkill class is suspended, it will *not* call rfkill->toggle_radio -until it is resumed. - - -Example of a WLAN wireless driver connected to the rfkill subsystem: --------------------------------------------------------------------- - -A certain WLAN card has one input pin that causes it to block the transmitter -and makes the status of that input pin available (only for reading!) to the -kernel driver. This is a hard rfkill input line (it cannot be overridden by -the kernel driver). - -The card also has one PCI register that, if manipulated by the driver, causes -it to block the transmitter. This is a soft rfkill input line. - -It has also a thermal protection circuitry that shuts down its transmitter if -the card overheats, and makes the status of that protection available (only for -reading!) to the kernel driver. This is also a hard rfkill input line. - -If either one of these rfkill lines are active, the transmitter is blocked by -the hardware and forced offline. - -The driver should allocate and attach to its struct device *ONE* instance of -the rfkill class (there is only one transmitter). - -It can implement the get_state() hook, and return RFKILL_STATE_HARD_BLOCKED if -either one of its two hard rfkill input lines are active. If the two hard -rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft -rfkill input line is active. Only if none of the rfkill input lines are -active, will it return RFKILL_STATE_UNBLOCKED. - -Since the device has a hardware rfkill line, it IS subject to state changes -external to rfkill. Therefore, the driver must make sure that it calls -rfkill_force_state() to keep the status always up-to-date, and it must do a -rfkill_force_state() on resume from sleep. - -Every time the driver gets a notification from the card that one of its rfkill -lines changed state (polling might be needed on badly designed cards that don't -generate interrupts for such events), it recomputes the rfkill state as per -above, and calls rfkill_force_state() to update it. - -The driver should implement the toggle_radio() hook, that: - -1. Returns an error if one of the hardware rfkill lines are active, and the -caller asked for RFKILL_STATE_UNBLOCKED. - -2. Activates the soft rfkill line if the caller asked for state -RFKILL_STATE_SOFT_BLOCKED. It should do this even if one of the hard rfkill -lines are active, effectively double-blocking the transmitter. - -3. Deactivates the soft rfkill line if none of the hardware rfkill lines are -active and the caller asked for RFKILL_STATE_UNBLOCKED. - -=============================================================================== -4: Kernel API +4. Kernel API To build a driver with rfkill subsystem support, the driver should depend on -(or select) the Kconfig symbol RFKILL; it should _not_ depend on RKFILL_INPUT. +(or select) the Kconfig symbol RFKILL. The hardware the driver talks to may be write-only (where the current state of the hardware is unknown), or read-write (where the hardware can be queried about its current state). -The rfkill class will call the get_state hook of a device every time it needs -to know the *real* current state of the hardware. This can happen often, but -it does not do any polling, so it is not enough on hardware that is subject -to state changes outside of the rfkill subsystem. +Calling rfkill_set_hw_state() when a state change happens is required from +rfkill drivers that control devices that can be hard-blocked unless they also +assign the poll_hw_block() callback (then the rfkill core will poll the +device). Don't do this unless you cannot get the event in any other way. -Therefore, calling rfkill_force_state() when a state change happens is -mandatory when the device has a hardware rfkill line, or when something else -like the firmware could cause its state to be changed without going through the -rfkill class. -Some hardware provides events when its status changes. In these cases, it is -best for the driver to not provide a get_state hook, and instead register the -rfkill class *already* with the correct status, and keep it updated using -rfkill_force_state() when it gets an event from the hardware. -rfkill_force_state() must be used on the device resume handlers to update the -rfkill status, should there be any chance of the device status changing during -the sleep. +5. Userspace support -There is no provision for a statically-allocated rfkill struct. You must -use rfkill_allocate() to allocate one. - -You should: - - rfkill_allocate() - - modify rfkill fields (flags, name) - - modify state to the current hardware state (THIS IS THE ONLY TIME - YOU CAN ACCESS state DIRECTLY) - - rfkill_register() - -The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through -a suitable return of get_state() or through rfkill_force_state(). - -When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch -it to a different state is through a suitable return of get_state() or through -rfkill_force_state(). - -If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED -when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should -not return an error. Instead, it should try to double-block the transmitter, -so that its state will change from RFKILL_STATE_HARD_BLOCKED to -RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease. - -Please refer to the source for more documentation. - -=============================================================================== -5: Userspace support - -rfkill devices issue uevents (with an action of "change"), with the following -environment variables set: - -RFKILL_NAME -RFKILL_STATE -RFKILL_TYPE - -The ABI for these variables is defined by the sysfs attributes. It is best -to take a quick look at the source to make sure of the possible values. - -It is expected that HAL will trap those, and bridge them to DBUS, etc. These -events CAN and SHOULD be used to give feedback to the user about the rfkill -status of the system. - -Input devices may issue events that are related to rfkill. These are the -various KEY_* events and SW_* events supported by rfkill-input.c. - -******IMPORTANT****** -When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL -SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it -has set to true the user_claim attribute for that particular switch. This rule -is *absolute*; do NOT violate it. -******IMPORTANT****** - -Userspace must not assume it is the only source of control for rfkill switches. -Their state CAN and WILL change due to firmware actions, direct user actions, -and the rfkill-input EPO override for *_RFKILL_ALL. - -When rfkill-input is not active, userspace must initiate a rfkill status -change by writing to the "state" attribute in order for anything to happen. - -Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that -switch is set to OFF, *every* rfkill device *MUST* be immediately put into the -RFKILL_STATE_SOFT_BLOCKED state, no questions asked. - -The following sysfs entries will be created: +The following sysfs entries exist for every rfkill device: name: Name assigned by driver to this key (interface or driver name). type: Name of the key type ("wlan", "bluetooth", etc). state: Current state of the transmitter 0: RFKILL_STATE_SOFT_BLOCKED - transmitter is forced off, but one can override it - by a write to the state attribute; + transmitter is turned off by software 1: RFKILL_STATE_UNBLOCKED - transmiter is NOT forced off, and may operate if - all other conditions for such operation are met - (such as interface is up and configured, etc); + transmitter is (potentially) active 2: RFKILL_STATE_HARD_BLOCKED transmitter is forced off by something outside of - the driver's control. One cannot set a device to - this state through writes to the state attribute; - claim: 1: Userspace handles events, 0: Kernel handles events + the driver's control. + claim: 0: Kernel handles events (currently always reads that value) -Both the "state" and "claim" entries are also writable. For the "state" entry -this means that when 1 or 0 is written, the device rfkill state (if not yet in -the requested state), will be will be toggled accordingly. +rfkill devices also issue uevents (with an action of "change"), with the +following environment variables set: -For the "claim" entry writing 1 to it means that the kernel no longer handles -key events even though RFKILL_INPUT input was enabled. When "claim" has been -set to 0, userspace should make sure that it listens for the input events or -check the sysfs "state" entry regularly to correctly perform the required tasks -when the rkfill key is pressed. +RFKILL_NAME +RFKILL_STATE +RFKILL_TYPE -A note about input devices and EV_SW events: +The contents of these variables corresponds to the "name", "state" and +"type" sysfs files explained above. -In order to know the current state of an input device switch (like -SW_RFKILL_ALL), you will need to use an IOCTL. That information is not -available through sysfs in a generic way at this time, and it is not available -through the rfkill class AT ALL. +An alternative userspace interface exists as a misc device /dev/rfkill, +which allows userspace to obtain and set the state of rfkill devices and +sets of devices. It also notifies userspace about device addition and +removal. The API is a simple read/write API that is defined in +linux/rfkill.h. diff --git a/MAINTAINERS b/MAINTAINERS index a1fe87ad4832..2cb7566904b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -947,6 +947,12 @@ P: Luis R. Rodriguez M: lrodriguez@atheros.com P: Jouni Malinen M: jmalinen@atheros.com +P: Sujith Manoharan +M: Sujith.Manoharan@atheros.com +P: Vasanthakumar Thiagarajan +M: vasanth@atheros.com +P: Senthil Balasubramanian +M: senthilkumar@atheros.com L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org S: Supported @@ -1339,6 +1345,13 @@ F: drivers/net/can/ F: include/linux/can/ F: include/linux/can.h +CAN NETWORK DRIVERS +P: Wolfgang Grandegger +M: wg@grandegger.com +L: socketcan-core@lists.berlios.de (subscribers-only) +W: http://developer.berlios.de/projects/socketcan/ +S: Maintained + CELL BROADBAND ENGINE ARCHITECTURE P: Arnd Bergmann M: arnd@arndb.de @@ -2843,6 +2856,18 @@ L: linux1394-devel@lists.sourceforge.net S: Maintained F: drivers/ieee1394/raw1394* +IEEE 802.15.4 SUBSYSTEM +P: Dmitry Eremin-Solenikov +M: dbaryshkov@gmail.com +P: Sergey Lapin +M: slapin@ossfans.org +L: linux-zigbee-devel@lists.sourceforge.net +W: http://apps.sourceforge.net/trac/linux-zigbee +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lumag/lowpan.git +S: Maintained +F: net/ieee802154/ +F: drivers/ieee801254/ + INTEGRITY MEASUREMENT ARCHITECTURE (IMA) P: Mimi Zohar M: zohar@us.ibm.com @@ -3136,6 +3161,7 @@ M: samuel@sortiz.org L: irda-users@lists.sourceforge.net (subscribers-only) W: http://irda.sourceforge.net/ S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git F: Documentation/networking/irda.txt F: drivers/net/irda/ F: include/net/irda/ @@ -4621,8 +4647,8 @@ S: Maintained F: drivers/ata/sata_promise.* PS3 NETWORK SUPPORT -P: Masakazu Mokuno -M: mokuno@sm.sony.co.jp +P: Geoff Levand +M: geoffrey.levand@am.sony.com L: netdev@vger.kernel.org L: cbe-oss-dev@ozlabs.org S: Supported @@ -4823,7 +4849,7 @@ F: drivers/net/r6040.c RDS - RELIABLE DATAGRAM SOCKETS P: Andy Grover M: andy.grover@oracle.com -L: rds-devel@oss.oracle.com +L: rds-devel@oss.oracle.com (moderated for non-subscribers) S: Supported F: net/rds/ @@ -4863,9 +4889,9 @@ S: Supported F: fs/reiserfs/ RFKILL -P: Ivo van Doorn -M: IvDoorn@gmail.com -L: netdev@vger.kernel.org +P: Johannes Berg +M: johannes@sipsolutions.net +L: linux-wireless@vger.kernel.org S: Maintained F Documentation/rfkill.txt F: net/rfkill/ diff --git a/arch/alpha/include/asm/errno.h b/arch/alpha/include/asm/errno.h index 69e2655249d2..98099bda9370 100644 --- a/arch/alpha/include/asm/errno.h +++ b/arch/alpha/include/asm/errno.h @@ -120,4 +120,6 @@ #define EOWNERDEAD 136 /* Owner died */ #define ENOTRECOVERABLE 137 /* State not recoverable */ +#define ERFKILL 138 /* Operation not possible due to RF-kill */ + #endif diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 442b87476f97..93bb4247b7ed 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -536,7 +536,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, return err; } -static inline void restart_syscall(struct pt_regs *regs) +static inline void setup_syscall_restart(struct pt_regs *regs) { regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; @@ -571,7 +571,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, } /* fallthrough */ case -ERESTARTNOINTR: - restart_syscall(regs); + setup_syscall_restart(regs); } } @@ -695,7 +695,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { - restart_syscall(regs); + setup_syscall_restart(regs); } } single_step_set(current); diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c index fb0294bd4310..c31e601eb49c 100644 --- a/arch/arm/mach-pxa/tosa-bt.c +++ b/arch/arm/mach-pxa/tosa-bt.c @@ -35,21 +35,25 @@ static void tosa_bt_off(struct tosa_bt_data *data) gpio_set_value(data->gpio_reset, 0); } -static int tosa_bt_toggle_radio(void *data, enum rfkill_state state) +static int tosa_bt_set_block(void *data, bool blocked) { - pr_info("BT_RADIO going: %s\n", - state == RFKILL_STATE_ON ? "on" : "off"); + pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on"); - if (state == RFKILL_STATE_ON) { + if (!blocked) { pr_info("TOSA_BT: going ON\n"); tosa_bt_on(data); } else { pr_info("TOSA_BT: going OFF\n"); tosa_bt_off(data); } + return 0; } +static const struct rfkill_ops tosa_bt_rfkill_ops = { + .set_block = tosa_bt_set_block, +}; + static int tosa_bt_probe(struct platform_device *dev) { int rc; @@ -70,18 +74,14 @@ static int tosa_bt_probe(struct platform_device *dev) if (rc) goto err_pwr_dir; - rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH); + rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH, + &tosa_bt_rfkill_ops, data); if (!rfk) { rc = -ENOMEM; goto err_rfk_alloc; } - rfk->name = "tosa-bt"; - rfk->toggle_radio = tosa_bt_toggle_radio; - rfk->data = data; -#ifdef CONFIG_RFKILL_LEDS - rfk->led_trigger.name = "tosa-bt"; -#endif + rfkill_set_led_trigger_name(rfk, "tosa-bt"); rc = rfkill_register(rfk); if (rc) @@ -92,9 +92,7 @@ static int tosa_bt_probe(struct platform_device *dev) return 0; err_rfkill: - if (rfk) - rfkill_free(rfk); - rfk = NULL; + rfkill_destroy(rfk); err_rfk_alloc: tosa_bt_off(data); err_pwr_dir: @@ -113,8 +111,10 @@ static int __devexit tosa_bt_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); - if (rfk) + if (rfk) { rfkill_unregister(rfk); + rfkill_destroy(rfk); + } rfk = NULL; tosa_bt_off(data); diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 168267a5dfb3..117ad5920e53 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index 803d7be0938f..27227561bad6 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -212,7 +212,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return err; } -static inline void restart_syscall(struct pt_regs *regs) +static inline void setup_syscall_restart(struct pt_regs *regs) { if (regs->r12 == -ERESTART_RESTARTBLOCK) regs->r8 = __NR_restart_syscall; @@ -296,7 +296,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) } /* fall through */ case -ERESTARTNOINTR: - restart_syscall(regs); + setup_syscall_restart(regs); } } diff --git a/arch/mips/include/asm/errno.h b/arch/mips/include/asm/errno.h index 3c0d840e4577..a0efc73819e4 100644 --- a/arch/mips/include/asm/errno.h +++ b/arch/mips/include/asm/errno.h @@ -119,6 +119,8 @@ #define EOWNERDEAD 165 /* Owner died */ #define ENOTRECOVERABLE 166 /* State not recoverable */ +#define ERFKILL 167 /* Operation not possible due to RF-kill */ + #define EDQUOT 1133 /* Quota exceeded */ #ifdef __KERNEL__ diff --git a/arch/parisc/include/asm/errno.h b/arch/parisc/include/asm/errno.h index e2f3ddc796be..9992abdd782d 100644 --- a/arch/parisc/include/asm/errno.h +++ b/arch/parisc/include/asm/errno.h @@ -120,5 +120,6 @@ #define EOWNERDEAD 254 /* Owner died */ #define ENOTRECOVERABLE 255 /* State not recoverable */ +#define ERFKILL 256 /* Operation not possible due to RF-kill */ #endif diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index e0faf332c9c9..157c5ca581c8 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h @@ -675,6 +675,8 @@ struct ucc_slow_pram { #define UCC_GETH_UPSMR_RMM 0x00001000 #define UCC_GETH_UPSMR_CAM 0x00000400 #define UCC_GETH_UPSMR_BRO 0x00000200 +#define UCC_GETH_UPSMR_SMM 0x00000080 +#define UCC_GETH_UPSMR_SGMM 0x00000020 /* UCC Transmit On Demand Register (UTODR) */ #define UCC_SLOW_TOD 0x8000 diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index 0eb6d7f62241..51fcae41f08a 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -115,7 +116,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev, struct mii_bus *bus; struct resource res; struct device_node *node; - int ret, i; + int ret; node = of_get_parent(ofdev->node); of_node_put(node); @@ -130,17 +131,13 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev, if (!bus) return -ENOMEM; - bus->phy_mask = 0; bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - for (i = 0; i < PHY_MAX_ADDR; i++) - bus->irq[i] = -1; - bus->name = "ep8248e-mdio-bitbang"; bus->parent = &ofdev->dev; snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); - return mdiobus_register(bus); + return of_mdiobus_register(bus, ofdev->node); } static int ep8248e_mdio_remove(struct of_device *ofdev) diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 75cc165d5bee..3bf546797cbb 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #define DELAY 1 @@ -39,6 +39,7 @@ static void __iomem *gpio_regs; struct gpio_priv { int mdc_pin; int mdio_pin; + int mdio_irqs[PHY_MAX_ADDR]; }; #define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin) @@ -218,12 +219,11 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device *dev = &ofdev->dev; - struct device_node *phy_dn, *np = ofdev->node; + struct device_node *np = ofdev->node; struct mii_bus *new_bus; struct gpio_priv *priv; const unsigned int *prop; int err; - int i; err = -ENOMEM; priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL); @@ -244,27 +244,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop); new_bus->priv = priv; - new_bus->phy_mask = 0; - - new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); - - if (!new_bus->irq) - goto out_free_bus; - - for (i = 0; i < PHY_MAX_ADDR; i++) - new_bus->irq[i] = NO_IRQ; - - for (phy_dn = of_get_next_child(np, NULL); - phy_dn != NULL; - phy_dn = of_get_next_child(np, phy_dn)) { - const unsigned int *ip, *regp; - - ip = of_get_property(phy_dn, "interrupts", NULL); - regp = of_get_property(phy_dn, "reg", NULL); - if (!ip || !regp || *regp >= PHY_MAX_ADDR) - continue; - new_bus->irq[*regp] = irq_create_mapping(NULL, *ip); - } + new_bus->irq = priv->mdio_irqs; prop = of_get_property(np, "mdc-pin", NULL); priv->mdc_pin = *prop; @@ -275,7 +255,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, new_bus->parent = dev; dev_set_drvdata(dev, new_bus); - err = mdiobus_register(new_bus); + err = of_mdiobus_register(new_bus, np); if (err != 0) { printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n", @@ -286,8 +266,6 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, return 0; out_free_irq: - kfree(new_bus->irq); -out_free_bus: kfree(new_bus); out_free_priv: kfree(priv); diff --git a/arch/sparc/include/asm/errno.h b/arch/sparc/include/asm/errno.h index a9ef172977de..4e2bc490d714 100644 --- a/arch/sparc/include/asm/errno.h +++ b/arch/sparc/include/asm/errno.h @@ -110,4 +110,6 @@ #define EOWNERDEAD 132 /* Owner died */ #define ENOTRECOVERABLE 133 /* State not recoverable */ +#define ERFKILL 134 /* Operation not possible due to RF-kill */ + #endif diff --git a/drivers/Makefile b/drivers/Makefile index 1266ead6ace0..9e7d4e56c85b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -107,3 +107,4 @@ obj-$(CONFIG_SSB) += ssb/ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_STAGING) += staging/ obj-y += platform/ +obj-y += ieee802154/ diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 31693bc24444..965ece2c7e4d 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -34,13 +34,6 @@ new_skb(ulong len) skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); - skb->priority = 0; - skb->next = skb->prev = NULL; - - /* tell the network layer not to perform IP checksums - * or to get the NIC to do it - */ - skb->ip_summed = CHECKSUM_NONE; } return skb; } diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 901bdd95655f..2cc7b3266eaf 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -415,6 +415,8 @@ static int dtl1_hci_send_frame(struct sk_buff *skb) hdev->stat.sco_tx++; nsh.type = 0x83; break; + default: + return -EILSEQ; }; nsh.zero = 0; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 0bbefba6469c..1df9dda2e377 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -40,7 +40,7 @@ #include #include -#define VERSION "1.2" +#define VERSION "1.3" static int minor = MISC_DYNAMIC_MINOR; @@ -51,14 +51,8 @@ struct vhci_data { wait_queue_head_t read_wait; struct sk_buff_head readq; - - struct fasync_struct *fasync; }; -#define VHCI_FASYNC 0x0010 - -static struct miscdevice vhci_miscdev; - static int vhci_open_dev(struct hci_dev *hdev) { set_bit(HCI_RUNNING, &hdev->flags); @@ -105,9 +99,6 @@ static int vhci_send_frame(struct sk_buff *skb) memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); skb_queue_tail(&data->readq, skb); - if (data->flags & VHCI_FASYNC) - kill_fasync(&data->fasync, SIGIO, POLL_IN); - wake_up_interruptible(&data->read_wait); return 0; @@ -179,41 +170,31 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, static ssize_t vhci_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { - DECLARE_WAITQUEUE(wait, current); struct vhci_data *data = file->private_data; struct sk_buff *skb; ssize_t ret = 0; - add_wait_queue(&data->read_wait, &wait); while (count) { - set_current_state(TASK_INTERRUPTIBLE); - skb = skb_dequeue(&data->readq); - if (!skb) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - schedule(); - continue; + if (skb) { + ret = vhci_put_user(data, skb, buf, count); + if (ret < 0) + skb_queue_head(&data->readq, skb); + else + kfree_skb(skb); + break; } - if (access_ok(VERIFY_WRITE, buf, count)) - ret = vhci_put_user(data, skb, buf, count); - else - ret = -EFAULT; + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } - kfree_skb(skb); - break; + ret = wait_event_interruptible(data->read_wait, + !skb_queue_empty(&data->readq)); + if (ret < 0) + break; } - set_current_state(TASK_RUNNING); - remove_wait_queue(&data->read_wait, &wait); return ret; } @@ -223,9 +204,6 @@ static ssize_t vhci_write(struct file *file, { struct vhci_data *data = file->private_data; - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - return vhci_get_user(data, buf, count); } @@ -259,11 +237,9 @@ static int vhci_open(struct inode *inode, struct file *file) skb_queue_head_init(&data->readq); init_waitqueue_head(&data->read_wait); - lock_kernel(); hdev = hci_alloc_dev(); if (!hdev) { kfree(data); - unlock_kernel(); return -ENOMEM; } @@ -284,12 +260,10 @@ static int vhci_open(struct inode *inode, struct file *file) BT_ERR("Can't register HCI device"); kfree(data); hci_free_dev(hdev); - unlock_kernel(); return -EBUSY; } file->private_data = data; - unlock_kernel(); return nonseekable_open(inode, file); } @@ -310,48 +284,25 @@ static int vhci_release(struct inode *inode, struct file *file) return 0; } -static int vhci_fasync(int fd, struct file *file, int on) -{ - struct vhci_data *data = file->private_data; - int err = 0; - - lock_kernel(); - err = fasync_helper(fd, file, on, &data->fasync); - if (err < 0) - goto out; - - if (on) - data->flags |= VHCI_FASYNC; - else - data->flags &= ~VHCI_FASYNC; - -out: - unlock_kernel(); - return err; -} - static const struct file_operations vhci_fops = { - .owner = THIS_MODULE, .read = vhci_read, .write = vhci_write, .poll = vhci_poll, .ioctl = vhci_ioctl, .open = vhci_open, .release = vhci_release, - .fasync = vhci_fasync, }; static struct miscdevice vhci_miscdev= { - .name = "vhci", - .fops = &vhci_fops, + .name = "vhci", + .fops = &vhci_fops, + .minor = MISC_DYNAMIC_MINOR, }; static int __init vhci_init(void) { BT_INFO("Virtual HCI driver ver %s", VERSION); - vhci_miscdev.minor = minor; - if (misc_register(&vhci_miscdev) < 0) { BT_ERR("Can't register misc device with minor %d", minor); return -EIO; @@ -369,9 +320,6 @@ static void __exit vhci_exit(void) module_init(vhci_init); module_exit(vhci_exit); -module_param(minor, int, 0444); -MODULE_PARM_DESC(minor, "Miscellaneous minor device number"); - MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig new file mode 100644 index 000000000000..9b9f43aa2f85 --- /dev/null +++ b/drivers/ieee802154/Kconfig @@ -0,0 +1,22 @@ +menuconfig IEEE802154_DRIVERS + tristate "IEEE 802.15.4 drivers" + depends on NETDEVICES && IEEE802154 + default y + ---help--- + Say Y here to get to see options for IEEE 802.15.4 Low-Rate + Wireless Personal Area Network device drivers. This option alone + does not add any kernel code. + + If you say N, all options in this submenu will be skipped and + disabled. + +config IEEE802154_FAKEHARD + tristate "Fake LR-WPAN driver with several interconnected devices" + depends on IEEE802154_DRIVERS + ---help--- + Say Y here to enable the fake driver that serves as an example + of HardMAC device driver. + + This driver can also be built as a module. To do so say M here. + The module will be called 'fakehard'. + diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile new file mode 100644 index 000000000000..e0e8e1a184ff --- /dev/null +++ b/drivers/ieee802154/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o + +EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c new file mode 100644 index 000000000000..0384144c0b34 --- /dev/null +++ b/drivers/ieee802154/fakehard.c @@ -0,0 +1,270 @@ +/* + * Sample driver for HardMAC IEEE 802.15.4 devices + * + * Copyright (C) 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. + * + * Written by: + * Dmitry Eremin-Solenikov + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static u16 fake_get_pan_id(struct net_device *dev) +{ + BUG_ON(dev->type != ARPHRD_IEEE802154); + + return 0xeba1; +} + +static u16 fake_get_short_addr(struct net_device *dev) +{ + BUG_ON(dev->type != ARPHRD_IEEE802154); + + return 0x1; +} + +static u8 fake_get_dsn(struct net_device *dev) +{ + BUG_ON(dev->type != ARPHRD_IEEE802154); + + return 0x00; /* DSN are implemented in HW, so return just 0 */ +} + +static u8 fake_get_bsn(struct net_device *dev) +{ + BUG_ON(dev->type != ARPHRD_IEEE802154); + + return 0x00; /* BSN are implemented in HW, so return just 0 */ +} + +static int fake_assoc_req(struct net_device *dev, + struct ieee802154_addr *addr, u8 channel, u8 cap) +{ + /* We simply emulate it here */ + return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev), + IEEE802154_SUCCESS); +} + +static int fake_assoc_resp(struct net_device *dev, + struct ieee802154_addr *addr, u16 short_addr, u8 status) +{ + return 0; +} + +static int fake_disassoc_req(struct net_device *dev, + struct ieee802154_addr *addr, u8 reason) +{ + return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS); +} + +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) +{ + return 0; +} + +static int fake_scan_req(struct net_device *dev, u8 type, u32 channels, + u8 duration) +{ + u8 edl[27] = {}; + return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type, + channels, + type == IEEE802154_MAC_SCAN_ED ? edl : NULL); +} + +static struct ieee802154_mlme_ops fake_mlme = { + .assoc_req = fake_assoc_req, + .assoc_resp = fake_assoc_resp, + .disassoc_req = fake_disassoc_req, + .start_req = fake_start_req, + .scan_req = fake_scan_req, + + .get_pan_id = fake_get_pan_id, + .get_short_addr = fake_get_short_addr, + .get_dsn = fake_get_dsn, + .get_bsn = fake_get_bsn, +}; + +static int ieee802154_fake_open(struct net_device *dev) +{ + netif_start_queue(dev); + return 0; +} + +static int ieee802154_fake_close(struct net_device *dev) +{ + netif_stop_queue(dev); + return 0; +} + +static int ieee802154_fake_xmit(struct sk_buff *skb, struct net_device *dev) +{ + skb->iif = dev->ifindex; + skb->dev = dev; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + dev->trans_start = jiffies; + + /* FIXME: do hardware work here ... */ + + return 0; +} + + +static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr, + int cmd) +{ + struct sockaddr_ieee802154 *sa = + (struct sockaddr_ieee802154 *)&ifr->ifr_addr; + u16 pan_id, short_addr; + + switch (cmd) { + case SIOCGIFADDR: + /* FIXME: fixed here, get from device IRL */ + pan_id = fake_get_pan_id(dev); + short_addr = fake_get_short_addr(dev); + if (pan_id == IEEE802154_PANID_BROADCAST || + short_addr == IEEE802154_ADDR_BROADCAST) + return -EADDRNOTAVAIL; + + sa->family = AF_IEEE802154; + sa->addr.addr_type = IEEE802154_ADDR_SHORT; + sa->addr.pan_id = pan_id; + sa->addr.short_addr = short_addr; + return 0; + } + return -ENOIOCTLCMD; +} + +static int ieee802154_fake_mac_addr(struct net_device *dev, void *p) +{ + return -EBUSY; /* HW address is built into the device */ +} + +static const struct net_device_ops fake_ops = { + .ndo_open = ieee802154_fake_open, + .ndo_stop = ieee802154_fake_close, + .ndo_start_xmit = ieee802154_fake_xmit, + .ndo_do_ioctl = ieee802154_fake_ioctl, + .ndo_set_mac_address = ieee802154_fake_mac_addr, +}; + + +static void ieee802154_fake_setup(struct net_device *dev) +{ + dev->addr_len = IEEE802154_ADDR_LEN; + memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); + dev->features = NETIF_F_NO_CSUM; + dev->needed_tailroom = 2; /* FCS */ + dev->mtu = 127; + dev->tx_queue_len = 10; + dev->type = ARPHRD_IEEE802154; + dev->flags = IFF_NOARP | IFF_BROADCAST; + dev->watchdog_timeo = 0; +} + + +static int __devinit ieee802154fake_probe(struct platform_device *pdev) +{ + struct net_device *dev = + alloc_netdev(0, "hardwpan%d", ieee802154_fake_setup); + int err; + + if (!dev) + return -ENOMEM; + + memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef", + dev->addr_len); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + dev->netdev_ops = &fake_ops; + dev->ml_priv = &fake_mlme; + + /* + * If the name is a format string the caller wants us to do a + * name allocation. + */ + if (strchr(dev->name, '%')) { + err = dev_alloc_name(dev, dev->name); + if (err < 0) + goto out; + } + + SET_NETDEV_DEV(dev, &pdev->dev); + + platform_set_drvdata(pdev, dev); + + err = register_netdev(dev); + if (err < 0) + goto out; + + + dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n"); + return 0; + +out: + unregister_netdev(dev); + return err; +} + +static int __devexit ieee802154fake_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + unregister_netdev(dev); + free_netdev(dev); + return 0; +} + +static struct platform_device *ieee802154fake_dev; + +static struct platform_driver ieee802154fake_driver = { + .probe = ieee802154fake_probe, + .remove = __devexit_p(ieee802154fake_remove), + .driver = { + .name = "ieee802154hardmac", + .owner = THIS_MODULE, + }, +}; + +static __init int fake_init(void) +{ + ieee802154fake_dev = platform_device_register_simple( + "ieee802154hardmac", -1, NULL, 0); + return platform_driver_register(&ieee802154fake_driver); +} + +static __exit void fake_exit(void) +{ + platform_driver_unregister(&ieee802154fake_driver); + platform_device_unregister(ieee802154fake_dev); +} + +module_init(fake_init); +module_exit(fake_exit); +MODULE_LICENSE("GPL"); + diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 47d588ba2a7f..181b1f32325f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1394,8 +1394,8 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb, struct ipoib_dev_priv *priv = netdev_priv(dev); int e = skb_queue_empty(&priv->cm.skb_queue); - if (skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); skb_queue_tail(&priv->cm.skb_queue, skb); if (e) @@ -1455,13 +1455,15 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, struct net_device *dev = to_net_dev(d); struct ipoib_dev_priv *priv = netdev_priv(dev); + if (!rtnl_trylock()) + return restart_syscall(); + /* flush paths if we switch modes so that connections are restarted */ if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); ipoib_warn(priv, "enabling connected mode " "will cause multicast packet drops\n"); - rtnl_lock(); dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); rtnl_unlock(); priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; @@ -1473,7 +1475,6 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, if (!strcmp(buf, "datagram\n")) { clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); - rtnl_lock(); if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; if (priv->hca_caps & IB_DEVICE_UD_TSO) @@ -1485,6 +1486,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, return count; } + rtnl_unlock(); return -EINVAL; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index ab2c192c76bc..e319d91f60a6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -561,7 +561,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) struct ipoib_neigh *neigh; unsigned long flags; - neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev); + neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev); if (!neigh) { ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -570,9 +570,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->lock, flags); - path = __path_find(dev, skb->dst->neighbour->ha + 4); + path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4); if (!path) { - path = path_rec_create(dev, skb->dst->neighbour->ha + 4); + path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4); if (!path) goto err_path; @@ -605,7 +605,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) goto err_drop; } } else - ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha)); + ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); } else { neigh->ah = NULL; @@ -635,15 +635,15 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(skb->dev); /* Look up path record for unicasts */ - if (skb->dst->neighbour->ha[4] != 0xff) { + if (skb_dst(skb)->neighbour->ha[4] != 0xff) { neigh_add_path(skb, dev); return; } /* Add in the P_Key for multicasts */ - skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff; - skb->dst->neighbour->ha[9] = priv->pkey & 0xff; - ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb); + skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff; + skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff; + ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb); } static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, @@ -708,16 +708,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) struct ipoib_neigh *neigh; unsigned long flags; - if (likely(skb->dst && skb->dst->neighbour)) { - if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) { + if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) { + if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) { ipoib_path_lookup(skb, dev); return NETDEV_TX_OK; } - neigh = *to_ipoib_neigh(skb->dst->neighbour); + neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour); if (unlikely((memcmp(&neigh->dgid.raw, - skb->dst->neighbour->ha + 4, + skb_dst(skb)->neighbour->ha + 4, sizeof(union ib_gid))) || (neigh->dev != dev))) { spin_lock_irqsave(&priv->lock, flags); @@ -743,7 +743,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } else if (neigh->ah) { - ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha)); + ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); return NETDEV_TX_OK; } @@ -772,7 +772,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) && (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) { ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n", - skb->dst ? "neigh" : "dst", + skb_dst(skb) ? "neigh" : "dst", be16_to_cpup((__be16 *) skb->data), IPOIB_QPN(phdr->hwaddr), phdr->hwaddr + 4); @@ -817,7 +817,7 @@ static int ipoib_hard_header(struct sk_buff *skb, * destination address onto the front of the skb so we can * figure out where to send the packet later. */ - if ((!skb->dst || !skb->dst->neighbour) && daddr) { + if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); @@ -1053,6 +1053,7 @@ static void ipoib_setup(struct net_device *dev) dev->tx_queue_len = ipoib_sendq_size * 2; dev->features = (NETIF_F_VLAN_CHALLENGED | NETIF_F_HIGHDMA); + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 425e31112ed7..a0e97532e714 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -261,7 +261,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, skb->dev = dev; - if (!skb->dst || !skb->dst->neighbour) { + if (!skb_dst(skb) || !skb_dst(skb)->neighbour) { /* put pseudoheader back on for next time */ skb_push(skb, sizeof (struct ipoib_pseudoheader)); } @@ -707,10 +707,10 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) out: if (mcast && mcast->ah) { - if (skb->dst && - skb->dst->neighbour && - !*to_ipoib_neigh(skb->dst->neighbour)) { - struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour, + if (skb_dst(skb) && + skb_dst(skb)->neighbour && + !*to_ipoib_neigh(skb_dst(skb)->neighbour)) { + struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev); if (neigh) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 4c57f329dd50..e3bf00d8cd25 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -61,7 +61,8 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ppriv = netdev_priv(pdev); - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); mutex_lock(&ppriv->vlan_mutex); /* @@ -167,7 +168,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) ppriv = netdev_priv(pdev); - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); mutex_lock(&ppriv->vlan_mutex); list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { if (priv->pkey == pkey) { diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index 3d113c6e4a70..02bdca6f95c3 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -61,4 +61,6 @@ source "drivers/isdn/hardware/Kconfig" endif # ISDN_CAPI +source "drivers/isdn/gigaset/Kconfig" + endif # ISDN diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index 29419a8d31dc..16f2e465e5f9 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -490,7 +490,14 @@ static void pars_2_message(_cmsg * cmsg) } } -/*-------------------------------------------------------*/ +/** + * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure + * @cmsg: _cmsg structure + * @msg: buffer for assembled message + * + * Return value: 0 for success + */ + unsigned capi_cmsg2message(_cmsg * cmsg, u8 * msg) { cmsg->m = msg; @@ -553,7 +560,14 @@ static void message_2_pars(_cmsg * cmsg) } } -/*-------------------------------------------------------*/ +/** + * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure + * @cmsg: _cmsg structure + * @msg: buffer for assembled message + * + * Return value: 0 for success + */ + unsigned capi_message2cmsg(_cmsg * cmsg, u8 * msg) { memset(cmsg, 0, sizeof(_cmsg)); @@ -573,7 +587,18 @@ unsigned capi_message2cmsg(_cmsg * cmsg, u8 * msg) return 0; } -/*-------------------------------------------------------*/ +/** + * capi_cmsg_header() - initialize header part of _cmsg structure + * @cmsg: _cmsg structure + * @_ApplId: ApplID field value + * @_Command: Command field value + * @_Subcommand: Subcommand field value + * @_Messagenumber: Message Number field value + * @_Controller: Controller/PLCI/NCCI field value + * + * Return value: 0 for success + */ + unsigned capi_cmsg_header(_cmsg * cmsg, u16 _ApplId, u8 _Command, u8 _Subcommand, u16 _Messagenumber, u32 _Controller) @@ -641,6 +666,14 @@ static char *mnames[] = [0x4e] = "MANUFACTURER_RESP" }; +/** + * capi_cmd2str() - convert CAPI 2.0 command/subcommand number to name + * @cmd: command number + * @subcmd: subcommand number + * + * Return value: static string, NULL if command/subcommand unknown + */ + char *capi_cmd2str(u8 cmd, u8 subcmd) { return mnames[command_2_index(cmd, subcmd)]; @@ -879,6 +912,11 @@ static _cdebbuf *cdebbuf_alloc(void) return cdb; } +/** + * cdebbuf_free() - free CAPI debug buffer + * @cdb: buffer to free + */ + void cdebbuf_free(_cdebbuf *cdb) { if (likely(cdb == g_debbuf)) { @@ -891,6 +929,16 @@ void cdebbuf_free(_cdebbuf *cdb) } +/** + * capi_message2str() - format CAPI 2.0 message for printing + * @msg: CAPI 2.0 message + * + * Allocates a CAPI debug buffer and fills it with a printable representation + * of the CAPI 2.0 message in @msg. + * Return value: allocated debug buffer, NULL on error + * The returned buffer should be freed by a call to cdebbuf_free() after use. + */ + _cdebbuf *capi_message2str(u8 * msg) { _cdebbuf *cdb; @@ -926,10 +974,23 @@ _cdebbuf *capi_message2str(u8 * msg) return cdb; } +/** + * capi_cmsg2str() - format _cmsg structure for printing + * @cmsg: _cmsg structure + * + * Allocates a CAPI debug buffer and fills it with a printable representation + * of the CAPI 2.0 message stored in @cmsg by a previous call to + * capi_cmsg2message() or capi_message2cmsg(). + * Return value: allocated debug buffer, NULL on error + * The returned buffer should be freed by a call to cdebbuf_free() after use. + */ + _cdebbuf *capi_cmsg2str(_cmsg * cmsg) { _cdebbuf *cdb; + if (!cmsg->m) + return NULL; /* no message */ cdb = cdebbuf_alloc(); if (!cdb) return NULL; diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index f33170368cd1..57d26360f64e 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -377,14 +377,14 @@ void capi_ctr_ready(struct capi_ctr * card) EXPORT_SYMBOL(capi_ctr_ready); /** - * capi_ctr_reseted() - signal CAPI controller reset + * capi_ctr_down() - signal CAPI controller not ready * @card: controller descriptor structure. * * Called by hardware driver to signal that the controller is down and * unavailable for use. */ -void capi_ctr_reseted(struct capi_ctr * card) +void capi_ctr_down(struct capi_ctr * card) { u16 appl; @@ -413,7 +413,7 @@ void capi_ctr_reseted(struct capi_ctr * card) notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); } -EXPORT_SYMBOL(capi_ctr_reseted); +EXPORT_SYMBOL(capi_ctr_down); /** * capi_ctr_suspend_output() - suspend controller @@ -517,7 +517,7 @@ EXPORT_SYMBOL(attach_capi_ctr); int detach_capi_ctr(struct capi_ctr *card) { if (card->cardstate != CARD_DETECTED) - capi_ctr_reseted(card); + capi_ctr_down(card); ncards--; diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 9ca889adf120..18ab8652aa57 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -1,5 +1,6 @@ menuconfig ISDN_DRV_GIGASET tristate "Siemens Gigaset support" + depends on ISDN_I4L select CRC_CCITT select BITREVERSE help @@ -42,11 +43,4 @@ config GIGASET_DEBUG This enables debugging code in the Gigaset drivers. If in doubt, say yes. -config GIGASET_UNDOCREQ - bool "Support for undocumented USB requests" - help - This enables support for USB requests we only know from - reverse engineering (currently M105 only). If you need - features like configuration mode of M105, say yes. - endif # ISDN_DRV_GIGASET diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 2a4ce96f04bd..234cc5d53312 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -174,9 +174,8 @@ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, if (unlikely(fcs != PPP_GOODFCS)) { dev_err(cs->dev, - "Packet checksum at %lu failed, " - "packet is corrupted (%u bytes)!\n", - bcs->rcvbytes, skb->len); + "Checksum failed, %u bytes corrupted!\n", + skb->len); compskb = NULL; gigaset_rcv_error(compskb, cs, bcs); error = 1; diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 0048ce98bfa8..e4141bf8b2f3 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -565,8 +565,6 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); gigaset_at_init(&bcs->at_state, bcs, cs, -1); - bcs->rcvbytes = 0; - #ifdef CONFIG_GIGASET_DEBUG bcs->emptycount = 0; #endif @@ -672,14 +670,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->tty = NULL; cs->tty_dev = NULL; cs->cidmode = cidmode != 0; - - //if(onechannel) { //FIXME - cs->tabnocid = gigaset_tab_nocid_m10x; - cs->tabcid = gigaset_tab_cid_m10x; - //} else { - // cs->tabnocid = gigaset_tab_nocid; - // cs->tabcid = gigaset_tab_cid; - //} + cs->tabnocid = gigaset_tab_nocid; + cs->tabcid = gigaset_tab_cid; init_waitqueue_head(&cs->waitqueue); cs->waiting = 0; diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index e582a4887bc1..ec5169604a6a 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -160,7 +160,7 @@ // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring -struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ +struct reply_t gigaset_tab_nocid[] = { /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ @@ -280,7 +280,7 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ }; // 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall -struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ +struct reply_t gigaset_tab_cid[] = { /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 747178f03d2c..a2f6125739eb 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -282,8 +282,8 @@ struct reply_t { char *command; /* NULL==none */ }; -extern struct reply_t gigaset_tab_cid_m10x[]; -extern struct reply_t gigaset_tab_nocid_m10x[]; +extern struct reply_t gigaset_tab_cid[]; +extern struct reply_t gigaset_tab_nocid[]; struct inbuf_t { unsigned char *rcvbuf; /* usb-gigaset receive buffer */ @@ -384,7 +384,6 @@ struct bc_state { int trans_up; /* Counter of packages (upstream) */ struct at_state_t at_state; - unsigned long rcvbytes; __u16 fcs; struct sk_buff *skb; diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 69a702f0db93..9b22f9cf2f33 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -544,11 +544,11 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); - //iif->id[sizeof(iif->id) - 1]=0; - //strncpy(iif->id, isdnid, sizeof(iif->id) - 1); if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) - >= sizeof iif->id) - return -ENOMEM; //FIXME EINVAL/...?? + >= sizeof iif->id) { + pr_err("ID too long: %s\n", isdnid); + return 0; + } iif->owner = THIS_MODULE; iif->channels = cs->channels; @@ -568,8 +568,10 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) iif->rcvcallb_skb = NULL; /* Will be set by LL */ iif->statcallb = NULL; /* Will be set by LL */ - if (!register_isdn(iif)) + if (!register_isdn(iif)) { + pr_err("register_isdn failed\n"); return 0; + } cs->myid = iif->channels; /* Set my device id */ return 1; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 820a30923fee..1ebfcab74662 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -599,8 +599,7 @@ void gigaset_if_init(struct cardstate *cs) if (!IS_ERR(cs->tty_dev)) dev_set_drvdata(cs->tty_dev, cs); else { - dev_warn(cs->dev, - "could not register device to the tty subsystem\n"); + pr_warning("could not register device to the tty subsystem\n"); cs->tty_dev = NULL; } mutex_unlock(&cs->mutex); diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 29808c4fb1cb..db3a1e4cd489 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -246,6 +246,10 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, unsigned char c; static char dbgline[3 * 32 + 1]; int i = 0; + + if (!(gigaset_debuglevel & level)) + return; + while (count-- > 0) { if (i > sizeof(dbgline) - 4) { dbgline[i] = '\0'; diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index da6f3acf9fd0..9715aad9c3f0 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -79,5 +79,5 @@ void gigaset_init_dev_sysfs(struct cardstate *cs) gig_dbg(DEBUG_INIT, "setting up sysfs"); if (device_create_file(cs->tty_dev, &dev_attr_cidmode)) - dev_err(cs->dev, "could not create sysfs attribute\n"); + pr_err("could not create sysfs attribute\n"); } diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index d78385166099..4deb1ab0dbf8 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -153,8 +153,6 @@ static inline unsigned tiocm_to_gigaset(unsigned state) return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0); } -#ifdef CONFIG_GIGASET_UNDOCREQ -/* WARNING: EXPERIMENTAL! */ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state) { @@ -176,6 +174,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, return 0; } +/* + * Set M105 configuration value + * using undocumented device commands reverse engineered from USB traces + * of the Siemens Windows driver + */ static int set_value(struct cardstate *cs, u8 req, u16 val) { struct usb_device *udev = cs->hw.usb->udev; @@ -205,8 +208,10 @@ static int set_value(struct cardstate *cs, u8 req, u16 val) return r < 0 ? r : (r2 < 0 ? r2 : 0); } -/* WARNING: HIGHLY EXPERIMENTAL! */ -// don't use this in an interrupt/BH +/* + * set the baud rate on the internal serial adapter + * using the undocumented parameter setting command + */ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) { u16 val; @@ -237,8 +242,10 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) return set_value(cs, 1, val); } -/* WARNING: HIGHLY EXPERIMENTAL! */ -// don't use this in an interrupt/BH +/* + * set the line format on the internal serial adapter + * using the undocumented parameter setting command + */ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) { u16 val = 0; @@ -274,24 +281,6 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) return set_value(cs, 3, val); } -#else -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - return -ENOTTY; -} - -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - return -ENOTTY; -} - -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - return -ENOTTY; -} -#endif - /*================================================================================================================*/ static int gigaset_init_bchannel(struct bc_state *bcs) @@ -362,10 +351,8 @@ static void gigaset_modem_fill(unsigned long data) } while (again); } -/** - * gigaset_read_int_callback - * - * It is called if the data was received from the device. +/* + * Interrupt Input URB completion routine */ static void gigaset_read_int_callback(struct urb *urb) { @@ -567,18 +554,19 @@ static int gigaset_chars_in_buffer(struct cardstate *cs) return cs->cmdbytes; } +/* + * set the break characters on the internal serial adapter + * using undocumented device commands reverse engineered from USB traces + * of the Siemens Windows driver + */ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) { -#ifdef CONFIG_GIGASET_UNDOCREQ struct usb_device *udev = cs->hw.usb->udev; gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); memcpy(cs->hw.usb->bchars, buf, 6); return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, 0, 0, &buf, 6, 2000); -#else - return -ENOTTY; -#endif } static int gigaset_freebcshw(struct bc_state *bcs) @@ -625,7 +613,6 @@ static int gigaset_initcshw(struct cardstate *cs) ucs->bchars[5] = 0x13; ucs->bulk_out_buffer = NULL; ucs->bulk_out_urb = NULL; - //ucs->urb_cmd_out = NULL; ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, &gigaset_modem_fill, (unsigned long) cs); @@ -742,7 +729,7 @@ static int gigaset_probe(struct usb_interface *interface, cs->dev = &interface->dev; /* save address of controller structure */ - usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs); + usb_set_intfdata(interface, cs); endpoint = &hostif->endpoint[0].desc; @@ -921,8 +908,7 @@ static const struct gigaset_ops ops = { gigaset_m10x_input, }; -/** - * usb_gigaset_init +/* * This function is called while kernel-module is loaded */ static int __init usb_gigaset_init(void) @@ -952,9 +938,7 @@ static int __init usb_gigaset_init(void) return -1; } - -/** - * usb_gigaset_exit +/* * This function is called while unloading the kernel-module */ static void __exit usb_gigaset_exit(void) diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index abf05ec31760..a7c0083e78a7 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -330,7 +330,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl) spin_lock_irqsave(&card->lock, flags); capilib_release(&cinfo->ncci_head); spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_reseted(ctrl); + capi_ctr_down(ctrl); } void b1_register_appl(struct capi_ctr *ctrl, diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index da34b98e3de7..0e84aaae43fd 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c @@ -759,7 +759,7 @@ void b1dma_reset_ctr(struct capi_ctr *ctrl) memset(cinfo->version, 0, sizeof(cinfo->version)); capilib_release(&cinfo->ncci_head); spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_reseted(ctrl); + capi_ctr_down(ctrl); } /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 9df1d3f66c87..6833301a45fc 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -681,7 +681,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) spin_lock_irqsave(&card->lock, flags); capilib_release(&cinfo->ncci_head); spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_reseted(&cinfo->capi_ctrl); + capi_ctr_down(&cinfo->capi_ctrl); } card->nlogcontr = 0; return IRQ_HANDLED; @@ -909,7 +909,7 @@ static void c4_reset_ctr(struct capi_ctr *ctrl) for (i=0; i < card->nr_controllers; i++) { cinfo = &card->ctrlinfo[i]; memset(cinfo->version, 0, sizeof(cinfo->version)); - capi_ctr_reseted(&cinfo->capi_ctrl); + capi_ctr_down(&cinfo->capi_ctrl); } card->nlogcontr = 0; } diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index e7724493738c..1c53fd49adb6 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -339,7 +339,7 @@ static void t1isa_reset_ctr(struct capi_ctr *ctrl) spin_lock_irqsave(&card->lock, flags); capilib_release(&cinfo->ncci_head); spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_reseted(ctrl); + capi_ctr_down(ctrl); } static void t1isa_remove(struct pci_dev *pdev) diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig index fd112ae252cf..3024566dd099 100644 --- a/drivers/isdn/hardware/mISDN/Kconfig +++ b/drivers/isdn/hardware/mISDN/Kconfig @@ -13,7 +13,7 @@ config MISDN_HFCPCI config MISDN_HFCMULTI tristate "Support for HFC multiport cards (HFC-4S/8S/E1)" - depends on PCI + depends on PCI || 8xx depends on MISDN help Enable support for cards with Cologne Chip AG's HFC multiport @@ -23,6 +23,15 @@ config MISDN_HFCMULTI * HFC-8S (8 S/T interfaces on one chip) * HFC-E1 (E1 interface for 2Mbit ISDN) +config MISDN_HFCMULTI_8xx + boolean "Support for XHFC embedded board in HFC multiport driver" + depends on MISDN + depends on MISDN_HFCMULTI + depends on 8xx + default 8xx + help + Enable support for the XHFC embedded solution from Speech Design. + config MISDN_HFCUSB tristate "Support for HFC-S USB based TAs" depends on USB diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h index 663b77f578be..0c773866efc7 100644 --- a/drivers/isdn/hardware/mISDN/hfc_multi.h +++ b/drivers/isdn/hardware/mISDN/hfc_multi.h @@ -17,6 +17,16 @@ #define PCI_ENA_REGIO 0x01 #define PCI_ENA_MEMIO 0x02 +#define XHFC_IRQ 4 /* SIU_IRQ2 */ +#define XHFC_MEMBASE 0xFE000000 +#define XHFC_MEMSIZE 0x00001000 +#define XHFC_OFFSET 0x00001000 +#define PA_XHFC_A0 0x0020 /* PA10 */ +#define PB_XHFC_IRQ1 0x00000100 /* PB23 */ +#define PB_XHFC_IRQ2 0x00000200 /* PB22 */ +#define PB_XHFC_IRQ3 0x00000400 /* PB21 */ +#define PB_XHFC_IRQ4 0x00000800 /* PB20 */ + /* * NOTE: some registers are assigned multiple times due to different modes * also registers are assigned differen for HFC-4s/8s and HFC-E1 @@ -44,6 +54,7 @@ struct hfc_chan { int conf; /* conference setting of TX slot */ int txpending; /* if there is currently data in */ /* the FIFO 0=no, 1=yes, 2=splloop */ + int Zfill; /* rx-fifo level on last hfcmulti_tx */ int rx_off; /* set to turn fifo receive off */ int coeff_count; /* curren coeff block */ s32 *coeff; /* memory pointer to 8 coeff blocks */ @@ -62,6 +73,7 @@ struct hfcm_hw { u_char r_sci_msk; u_char r_tx0, r_tx1; u_char a_st_ctrl0[8]; + u_char r_bert_wd_md; timer_t timer; }; @@ -79,6 +91,11 @@ struct hfcm_hw { #define HFC_CFG_CRC4 10 /* disable CRC-4 Multiframe mode, */ /* use double frame instead. */ +#define HFC_TYPE_E1 1 /* controller is HFC-E1 */ +#define HFC_TYPE_4S 4 /* controller is HFC-4S */ +#define HFC_TYPE_8S 8 /* controller is HFC-8S */ +#define HFC_TYPE_XHFC 5 /* controller is XHFC */ + #define HFC_CHIP_EXRAM_128 0 /* external ram 128k */ #define HFC_CHIP_EXRAM_512 1 /* external ram 256k */ #define HFC_CHIP_REVISION0 2 /* old fifo handling */ @@ -86,19 +103,22 @@ struct hfcm_hw { #define HFC_CHIP_PCM_MASTER 4 /* PCM is master */ #define HFC_CHIP_RX_SYNC 5 /* disable pll sync for pcm */ #define HFC_CHIP_DTMF 6 /* DTMF decoding is enabled */ -#define HFC_CHIP_ULAW 7 /* ULAW mode */ -#define HFC_CHIP_CLOCK2 8 /* double clock mode */ -#define HFC_CHIP_E1CLOCK_GET 9 /* always get clock from E1 interface */ -#define HFC_CHIP_E1CLOCK_PUT 10 /* always put clock from E1 interface */ -#define HFC_CHIP_WATCHDOG 11 /* whether we should send signals */ +#define HFC_CHIP_CONF 7 /* conference handling is enabled */ +#define HFC_CHIP_ULAW 8 /* ULAW mode */ +#define HFC_CHIP_CLOCK2 9 /* double clock mode */ +#define HFC_CHIP_E1CLOCK_GET 10 /* always get clock from E1 interface */ +#define HFC_CHIP_E1CLOCK_PUT 11 /* always put clock from E1 interface */ +#define HFC_CHIP_WATCHDOG 12 /* whether we should send signals */ /* to the watchdog */ -#define HFC_CHIP_B410P 12 /* whether we have a b410p with echocan in */ +#define HFC_CHIP_B410P 13 /* whether we have a b410p with echocan in */ /* hw */ -#define HFC_CHIP_PLXSD 13 /* whether we have a Speech-Design PLX */ +#define HFC_CHIP_PLXSD 14 /* whether we have a Speech-Design PLX */ +#define HFC_CHIP_EMBSD 15 /* whether we have a SD Embedded board */ #define HFC_IO_MODE_PCIMEM 0x00 /* normal memory mapped IO */ #define HFC_IO_MODE_REGIO 0x01 /* PCI io access */ #define HFC_IO_MODE_PLXSD 0x02 /* access HFC via PLX9030 */ +#define HFC_IO_MODE_EMBSD 0x03 /* direct access */ /* table entry in the PCI devices list */ struct hm_map { @@ -111,6 +131,7 @@ struct hm_map { int opticalsupport; int dip_type; int io_mode; + int irq; }; struct hfc_multi { @@ -118,7 +139,7 @@ struct hfc_multi { struct hm_map *mtyp; int id; int pcm; /* id of pcm bus */ - int type; + int ctype; /* controller type */ int ports; u_int irq; /* irq used by card */ @@ -158,10 +179,16 @@ struct hfc_multi { int len); void (*write_fifo)(struct hfc_multi *hc, u_char *data, int len); - u_long pci_origmembase, plx_origmembase, dsp_origmembase; + u_long pci_origmembase, plx_origmembase; void __iomem *pci_membase; /* PCI memory */ void __iomem *plx_membase; /* PLX memory */ - u_char *dsp_membase; /* DSP on PLX */ + u_long xhfc_origmembase; + u_char *xhfc_membase; + u_long *xhfc_memaddr, *xhfc_memdata; +#ifdef CONFIG_MISDN_HFCMULTI_8xx + struct immap *immap; +#endif + u_long pb_irqmsk; /* Portbit mask to check the IRQ line */ u_long pci_iobase; /* PCI IO */ struct hfcm_hw hw; /* remember data of write-only-registers */ diff --git a/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h b/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h new file mode 100644 index 000000000000..45ddced956d5 --- /dev/null +++ b/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h @@ -0,0 +1,167 @@ +/* + * For License see notice in hfc_multi.c + * + * special IO and init functions for the embedded XHFC board + * from Speech Design + * + */ + +#include + +/* Change this to the value used by your board */ +#ifndef IMAP_ADDR +#define IMAP_ADDR 0xFFF00000 +#endif + +static void +#ifdef HFC_REGISTER_DEBUG +HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val, + const char *function, int line) +#else +HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val) +#endif +{ + hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; + writeb(reg, hc->xhfc_memaddr); + hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); + writeb(val, hc->xhfc_memdata); +} +static u_char +#ifdef HFC_REGISTER_DEBUG +HFC_inb_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) +#else +HFC_inb_embsd(struct hfc_multi *hc, u_char reg) +#endif +{ + hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; + writeb(reg, hc->xhfc_memaddr); + hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); + return readb(hc->xhfc_memdata); +} +static u_short +#ifdef HFC_REGISTER_DEBUG +HFC_inw_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) +#else +HFC_inw_embsd(struct hfc_multi *hc, u_char reg) +#endif +{ + hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; + writeb(reg, hc->xhfc_memaddr); + hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); + return readb(hc->xhfc_memdata); +} +static void +#ifdef HFC_REGISTER_DEBUG +HFC_wait_embsd(struct hfc_multi *hc, const char *function, int line) +#else +HFC_wait_embsd(struct hfc_multi *hc) +#endif +{ + hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; + writeb(R_STATUS, hc->xhfc_memaddr); + hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); + while (readb(hc->xhfc_memdata) & V_BUSY) + cpu_relax(); +} + +/* write fifo data (EMBSD) */ +void +write_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) +{ + hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; + *hc->xhfc_memaddr = A_FIFO_DATA0; + hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); + while (len) { + *hc->xhfc_memdata = *data; + data++; + len--; + } +} + +/* read fifo data (EMBSD) */ +void +read_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) +{ + hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; + *hc->xhfc_memaddr = A_FIFO_DATA0; + hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); + while (len) { + *data = (u_char)(*hc->xhfc_memdata); + data++; + len--; + } +} + +static int +setup_embedded(struct hfc_multi *hc, struct hm_map *m) +{ + printk(KERN_INFO + "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", + m->vendor_name, m->card_name, m->clock2 ? "double" : "normal"); + + hc->pci_dev = NULL; + if (m->clock2) + test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); + + hc->leds = m->leds; + hc->ledstate = 0xAFFEAFFE; + hc->opticalsupport = m->opticalsupport; + + hc->pci_iobase = 0; + hc->pci_membase = 0; + hc->xhfc_membase = NULL; + hc->xhfc_memaddr = NULL; + hc->xhfc_memdata = NULL; + + /* set memory access methods */ + if (m->io_mode) /* use mode from card config */ + hc->io_mode = m->io_mode; + switch (hc->io_mode) { + case HFC_IO_MODE_EMBSD: + test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip); + hc->slots = 128; /* required */ + /* fall through */ + hc->HFC_outb = HFC_outb_embsd; + hc->HFC_inb = HFC_inb_embsd; + hc->HFC_inw = HFC_inw_embsd; + hc->HFC_wait = HFC_wait_embsd; + hc->read_fifo = read_fifo_embsd; + hc->write_fifo = write_fifo_embsd; + hc->xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc->id; + hc->xhfc_membase = (u_char *)ioremap(hc->xhfc_origmembase, + XHFC_MEMSIZE); + if (!hc->xhfc_membase) { + printk(KERN_WARNING + "HFC-multi: failed to remap xhfc address space. " + "(internal error)\n"); + return -EIO; + } + hc->xhfc_memaddr = (u_long *)(hc->xhfc_membase + 4); + hc->xhfc_memdata = (u_long *)(hc->xhfc_membase); + printk(KERN_INFO + "HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx " + "xhfc_memaddr:%#lx xhfc_memdata:%#lx\n", + (u_long)hc->xhfc_membase, hc->xhfc_origmembase, + (u_long)hc->xhfc_memaddr, (u_long)hc->xhfc_memdata); + break; + default: + printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); + return -EIO; + } + + /* Prepare the MPC8XX PortA 10 as output (address/data selector) */ + hc->immap = (struct immap *)(IMAP_ADDR); + hc->immap->im_ioport.iop_papar &= ~(PA_XHFC_A0); + hc->immap->im_ioport.iop_paodr &= ~(PA_XHFC_A0); + hc->immap->im_ioport.iop_padir |= PA_XHFC_A0; + + /* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */ + hc->pb_irqmsk = (PB_XHFC_IRQ1 << hc->id); + hc->immap->im_cpm.cp_pbpar &= ~(hc->pb_irqmsk); + hc->immap->im_cpm.cp_pbodr &= ~(hc->pb_irqmsk); + hc->immap->im_cpm.cp_pbdir &= ~(hc->pb_irqmsk); + + /* At this point the needed config is done */ + /* fifos are still not enabled */ + return 0; +} diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 0b28141e43bf..e1dab30aed30 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -104,7 +104,7 @@ * If unsure, don't give this parameter. * * dslot: - * NOTE: only one poll value must be given for every card. + * NOTE: only one dslot value must be given for every card. * Also this value must be given for non-E1 cards. If omitted, the E1 * card has D-channel on time slot 16, which is default. * If 1..15 or 17..31, an alternate time slot is used for D-channel. @@ -139,6 +139,10 @@ * Selects interface with clock source for mISDN and applications. * Set to card number starting with 1. Set to -1 to disable. * By default, the first card is used as clock source. + * + * hwid: + * NOTE: only one hwid value must be given once + * Enable special embedded devices with XHFC controllers. */ /* @@ -206,6 +210,11 @@ static int clock; static uint timer; static uint clockdelay_te = CLKDEL_TE; static uint clockdelay_nt = CLKDEL_NT; +#define HWID_NONE 0 +#define HWID_MINIP4 1 +#define HWID_MINIP8 2 +#define HWID_MINIP16 3 +static uint hwid = HWID_NONE; static int HFC_cnt, Port_cnt, PCM_cnt = 99; @@ -223,6 +232,7 @@ module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR); module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR); module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR); module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); +module_param(hwid, uint, S_IRUGO | S_IWUSR); /* The hardware ID */ #ifdef HFC_REGISTER_DEBUG #define HFC_outb(hc, reg, val) \ @@ -252,6 +262,10 @@ module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); #define HFC_wait_nodebug(hc) (hc->HFC_wait_nodebug(hc)) #endif +#ifdef CONFIG_MISDN_HFCMULTI_8xx +#include "hfc_multi_8xx.h" +#endif + /* HFC_IO_MODE_PCIMEM */ static void #ifdef HFC_REGISTER_DEBUG @@ -261,7 +275,7 @@ HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val, HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val) #endif { - writeb(val, (hc->pci_membase)+reg); + writeb(val, hc->pci_membase + reg); } static u_char #ifdef HFC_REGISTER_DEBUG @@ -270,7 +284,7 @@ HFC_inb_pcimem(struct hfc_multi *hc, u_char reg, const char *function, int line) HFC_inb_pcimem(struct hfc_multi *hc, u_char reg) #endif { - return readb((hc->pci_membase)+reg); + return readb(hc->pci_membase + reg); } static u_short #ifdef HFC_REGISTER_DEBUG @@ -279,7 +293,7 @@ HFC_inw_pcimem(struct hfc_multi *hc, u_char reg, const char *function, int line) HFC_inw_pcimem(struct hfc_multi *hc, u_char reg) #endif { - return readw((hc->pci_membase)+reg); + return readw(hc->pci_membase + reg); } static void #ifdef HFC_REGISTER_DEBUG @@ -288,7 +302,8 @@ HFC_wait_pcimem(struct hfc_multi *hc, const char *function, int line) HFC_wait_pcimem(struct hfc_multi *hc) #endif { - while (readb((hc->pci_membase)+R_STATUS) & V_BUSY); + while (readb(hc->pci_membase + R_STATUS) & V_BUSY) + cpu_relax(); } /* HFC_IO_MODE_REGIO */ @@ -300,7 +315,7 @@ HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val, HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val) #endif { - outb(reg, (hc->pci_iobase)+4); + outb(reg, hc->pci_iobase + 4); outb(val, hc->pci_iobase); } static u_char @@ -310,7 +325,7 @@ HFC_inb_regio(struct hfc_multi *hc, u_char reg, const char *function, int line) HFC_inb_regio(struct hfc_multi *hc, u_char reg) #endif { - outb(reg, (hc->pci_iobase)+4); + outb(reg, hc->pci_iobase + 4); return inb(hc->pci_iobase); } static u_short @@ -320,7 +335,7 @@ HFC_inw_regio(struct hfc_multi *hc, u_char reg, const char *function, int line) HFC_inw_regio(struct hfc_multi *hc, u_char reg) #endif { - outb(reg, (hc->pci_iobase)+4); + outb(reg, hc->pci_iobase + 4); return inw(hc->pci_iobase); } static void @@ -330,8 +345,9 @@ HFC_wait_regio(struct hfc_multi *hc, const char *function, int line) HFC_wait_regio(struct hfc_multi *hc) #endif { - outb(R_STATUS, (hc->pci_iobase)+4); - while (inb(hc->pci_iobase) & V_BUSY); + outb(R_STATUS, hc->pci_iobase + 4); + while (inb(hc->pci_iobase) & V_BUSY) + cpu_relax(); } #ifdef HFC_REGISTER_DEBUG @@ -350,14 +366,14 @@ HFC_outb_debug(struct hfc_multi *hc, u_char reg, u_char val, if (regname[0] == '\0') strcpy(regname, "register"); - bits[7] = '0'+(!!(val&1)); - bits[6] = '0'+(!!(val&2)); - bits[5] = '0'+(!!(val&4)); - bits[4] = '0'+(!!(val&8)); - bits[3] = '0'+(!!(val&16)); - bits[2] = '0'+(!!(val&32)); - bits[1] = '0'+(!!(val&64)); - bits[0] = '0'+(!!(val&128)); + bits[7] = '0' + (!!(val & 1)); + bits[6] = '0' + (!!(val & 2)); + bits[5] = '0' + (!!(val & 4)); + bits[4] = '0' + (!!(val & 8)); + bits[3] = '0' + (!!(val & 16)); + bits[2] = '0' + (!!(val & 32)); + bits[1] = '0' + (!!(val & 64)); + bits[0] = '0' + (!!(val & 128)); printk(KERN_DEBUG "HFC_outb(chip %d, %02x=%s, 0x%02x=%s); in %s() line %d\n", hc->id, reg, regname, val, bits, function, line); @@ -380,14 +396,14 @@ HFC_inb_debug(struct hfc_multi *hc, u_char reg, const char *function, int line) if (regname[0] == '\0') strcpy(regname, "register"); - bits[7] = '0'+(!!(val&1)); - bits[6] = '0'+(!!(val&2)); - bits[5] = '0'+(!!(val&4)); - bits[4] = '0'+(!!(val&8)); - bits[3] = '0'+(!!(val&16)); - bits[2] = '0'+(!!(val&32)); - bits[1] = '0'+(!!(val&64)); - bits[0] = '0'+(!!(val&128)); + bits[7] = '0' + (!!(val & 1)); + bits[6] = '0' + (!!(val & 2)); + bits[5] = '0' + (!!(val & 4)); + bits[4] = '0' + (!!(val & 8)); + bits[3] = '0' + (!!(val & 16)); + bits[2] = '0' + (!!(val & 32)); + bits[1] = '0' + (!!(val & 64)); + bits[0] = '0' + (!!(val & 128)); printk(KERN_DEBUG "HFC_inb(chip %d, %02x=%s) = 0x%02x=%s; in %s() line %d\n", hc->id, reg, regname, val, bits, function, line); @@ -467,6 +483,7 @@ write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) len--; } } + /* read fifo data (REGIO) */ static void read_fifo_regio(struct hfc_multi *hc, u_char *data, int len) @@ -512,7 +529,6 @@ read_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) } } - static void enable_hwirq(struct hfc_multi *hc) { @@ -928,7 +944,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) writel(pv, plx_acc_32); if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) { pcmmaster = hc; - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { if (debug & DEBUG_HFCMULTI_PLXSD) printk(KERN_DEBUG "Schedule SYNC_I\n"); @@ -949,7 +965,8 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) pv |= PLX_SYNC_O_EN; writel(pv, plx_acc_32); /* switch to jatt PLL, if not disabled by RX_SYNC */ - if (hc->type == 1 && !test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) { + if (hc->ctype == HFC_TYPE_E1 + && !test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) { if (debug & DEBUG_HFCMULTI_PLXSD) printk(KERN_DEBUG "Schedule jatt PLL\n"); hc->e1_resync |= 2; /* switch to jatt */ @@ -961,7 +978,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) printk(KERN_DEBUG "id=%d (0x%p) = PCM master syncronized " "with QUARTZ\n", hc->id, hc); - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { /* Use the crystal clock for the PCM master card */ if (debug & DEBUG_HFCMULTI_PLXSD) @@ -972,7 +989,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) if (debug & DEBUG_HFCMULTI_PLXSD) printk(KERN_DEBUG "QUARTZ is automatically " - "enabled by HFC-%dS\n", hc->type); + "enabled by HFC-%dS\n", hc->ctype); } plx_acc_32 = hc->plx_membase + PLX_GPIOC; pv = readl(plx_acc_32); @@ -996,7 +1013,7 @@ plxsd_checksync(struct hfc_multi *hc, int rm) if (hc->syncronized) { if (syncmaster == NULL) { if (debug & DEBUG_HFCMULTI_PLXSD) - printk(KERN_WARNING "%s: GOT sync on card %d" + printk(KERN_DEBUG "%s: GOT sync on card %d" " (id=%d)\n", __func__, hc->id + 1, hc->id); hfcmulti_resync(hc, hc, rm); @@ -1004,7 +1021,7 @@ plxsd_checksync(struct hfc_multi *hc, int rm) } else { if (syncmaster == hc) { if (debug & DEBUG_HFCMULTI_PLXSD) - printk(KERN_WARNING "%s: LOST sync on card %d" + printk(KERN_DEBUG "%s: LOST sync on card %d" " (id=%d)\n", __func__, hc->id + 1, hc->id); hfcmulti_resync(hc, NULL, rm); @@ -1053,20 +1070,23 @@ release_io_hfcmulti(struct hfc_multi *hc) pv &= ~PLX_DSP_RES_N; writel(pv, plx_acc_32); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: PCM off: PLX_GPIO=%x\n", + printk(KERN_DEBUG "%s: PCM off: PLX_GPIO=%x\n", __func__, pv); spin_unlock_irqrestore(&plx_lock, plx_flags); } /* disable memory mapped ports / io ports */ test_and_clear_bit(HFC_CHIP_PLXSD, &hc->chip); /* prevent resync */ - pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0); + if (hc->pci_dev) + pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0); if (hc->pci_membase) iounmap(hc->pci_membase); if (hc->plx_membase) iounmap(hc->plx_membase); if (hc->pci_iobase) release_region(hc->pci_iobase, 8); + if (hc->xhfc_membase) + iounmap((void *)hc->xhfc_membase); if (hc->pci_dev) { pci_disable_device(hc->pci_dev); @@ -1100,8 +1120,9 @@ init_chip(struct hfc_multi *hc) /* revision check */ if (debug & DEBUG_HFCMULTI_INIT) printk(KERN_DEBUG "%s: entered\n", __func__); - val = HFC_inb(hc, R_CHIP_ID)>>4; - if (val != 0x8 && val != 0xc && val != 0xe) { + val = HFC_inb(hc, R_CHIP_ID); + if ((val >> 4) != 0x8 && (val >> 4) != 0xc && (val >> 4) != 0xe && + (val >> 1) != 0x31) { printk(KERN_INFO "HFC_multi: unknown CHIP_ID:%x\n", (u_int)val); err = -EIO; goto out; @@ -1109,8 +1130,9 @@ init_chip(struct hfc_multi *hc) rev = HFC_inb(hc, R_CHIP_RV); printk(KERN_INFO "HFC_multi: detected HFC with chip ID=0x%lx revision=%ld%s\n", - val, rev, (rev == 0) ? " (old FIFO handling)" : ""); - if (rev == 0) { + val, rev, (rev == 0 && (hc->ctype != HFC_TYPE_XHFC)) ? + " (old FIFO handling)" : ""); + if (hc->ctype != HFC_TYPE_XHFC && rev == 0) { test_and_set_bit(HFC_CHIP_REVISION0, &hc->chip); printk(KERN_WARNING "HFC_multi: NOTE: Your chip is revision 0, " @@ -1152,6 +1174,12 @@ init_chip(struct hfc_multi *hc) hc->Zlen = 8000; hc->DTMFbase = 0x2000; } + if (hc->ctype == HFC_TYPE_XHFC) { + hc->Flen = 0x8; + hc->Zmin = 0x0; + hc->Zlen = 64; + hc->DTMFbase = 0x0; + } hc->max_trans = poll << 1; if (hc->max_trans > hc->Zlen) hc->max_trans = hc->Zlen; @@ -1176,7 +1204,7 @@ init_chip(struct hfc_multi *hc) writel(pv, plx_acc_32); spin_unlock_irqrestore(&plx_lock, plx_flags); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: slave/term: PLX_GPIO=%x\n", + printk(KERN_DEBUG "%s: slave/term: PLX_GPIO=%x\n", __func__, pv); /* * If we are the 3rd PLXSD card or higher, we must turn @@ -1204,13 +1232,17 @@ init_chip(struct hfc_multi *hc) writel(pv, plx_acc_32); spin_unlock_irqrestore(&plx_lock, plx_flags); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: term off: PLX_GPIO=%x\n", - __func__, pv); + printk(KERN_DEBUG + "%s: term off: PLX_GPIO=%x\n", + __func__, pv); } spin_unlock_irqrestore(&HFClock, hfc_flags); hc->hw.r_pcm_md0 = V_F0_LEN; /* shift clock for DSP */ } + if (test_bit(HFC_CHIP_EMBSD, &hc->chip)) + hc->hw.r_pcm_md0 = V_F0_LEN; /* shift clock for DSP */ + /* we only want the real Z2 read-pointer for revision > 0 */ if (!test_bit(HFC_CHIP_REVISION0, &hc->chip)) hc->hw.r_ram_sz |= V_FZ_MD; @@ -1234,15 +1266,24 @@ init_chip(struct hfc_multi *hc) /* soft reset */ HFC_outb(hc, R_CTRL, hc->hw.r_ctrl); - HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, 0x0C /* R_FIFO_THRES */, + 0x11 /* 16 Bytes TX/RX */); + else + HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz); HFC_outb(hc, R_FIFO_MD, 0); - hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES | V_RLD_EPR; + if (hc->ctype == HFC_TYPE_XHFC) + hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES; + else + hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES + | V_RLD_EPR; HFC_outb(hc, R_CIRM, hc->hw.r_cirm); udelay(100); hc->hw.r_cirm = 0; HFC_outb(hc, R_CIRM, hc->hw.r_cirm); udelay(100); - HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz); + if (hc->ctype != HFC_TYPE_XHFC) + HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz); /* Speech Design PLX bridge pcm and sync mode */ if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { @@ -1254,13 +1295,13 @@ init_chip(struct hfc_multi *hc) pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N; pv |= PLX_SYNC_O_EN; if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: master: PLX_GPIO=%x\n", + printk(KERN_DEBUG "%s: master: PLX_GPIO=%x\n", __func__, pv); } else { pv &= ~(PLX_MASTER_EN | PLX_SLAVE_EN_N); pv &= ~PLX_SYNC_O_EN; if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: slave: PLX_GPIO=%x\n", + printk(KERN_DEBUG "%s: slave: PLX_GPIO=%x\n", __func__, pv); } writel(pv, plx_acc_32); @@ -1278,13 +1319,16 @@ init_chip(struct hfc_multi *hc) HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0); if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) HFC_outb(hc, R_PCM_MD2, V_SYNC_SRC); /* sync via SYNC_I / O */ + else if (test_bit(HFC_CHIP_EMBSD, &hc->chip)) + HFC_outb(hc, R_PCM_MD2, 0x10); /* V_C2O_EN */ else HFC_outb(hc, R_PCM_MD2, 0x00); /* sync from interface */ HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00); for (i = 0; i < 256; i++) { HFC_outb_nodebug(hc, R_SLOT, i); HFC_outb_nodebug(hc, A_SL_CFG, 0); - HFC_outb_nodebug(hc, A_CONF, 0); + if (hc->ctype != HFC_TYPE_XHFC) + HFC_outb_nodebug(hc, A_CONF, 0); hc->slot_owner[i] = -1; } @@ -1296,6 +1340,9 @@ init_chip(struct hfc_multi *hc) HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK); } + if (test_bit(HFC_CHIP_EMBSD, &hc->chip)) + HFC_outb(hc, 0x02 /* R_CLK_CFG */, 0x40 /* V_CLKO_OFF */); + /* B410P GPIO */ if (test_bit(HFC_CHIP_B410P, &hc->chip)) { printk(KERN_NOTICE "Setting GPIOs\n"); @@ -1366,8 +1413,8 @@ init_chip(struct hfc_multi *hc) writel(pv, plx_acc_32); spin_unlock_irqrestore(&plx_lock, plx_flags); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: master: PLX_GPIO" - "=%x\n", __func__, pv); + printk(KERN_DEBUG "%s: master: " + "PLX_GPIO=%x\n", __func__, pv); } hc->hw.r_pcm_md0 |= V_PCM_MD; HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00); @@ -1401,7 +1448,7 @@ init_chip(struct hfc_multi *hc) writel(pv, plx_acc_32); spin_unlock_irqrestore(&plx_lock, plx_flags); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: reset off: PLX_GPIO=%x\n", + printk(KERN_DEBUG "%s: reset off: PLX_GPIO=%x\n", __func__, pv); } @@ -1424,7 +1471,7 @@ init_chip(struct hfc_multi *hc) hc->hw.r_irqmsk_misc |= V_TI_IRQMSK; /* set E1 state machine IRQ */ - if (hc->type == 1) + if (hc->ctype == HFC_TYPE_E1) hc->hw.r_irqmsk_misc |= V_STA_IRQMSK; /* set DTMF detection */ @@ -1444,7 +1491,8 @@ init_chip(struct hfc_multi *hc) r_conf_en = V_CONF_EN | V_ULAW; else r_conf_en = V_CONF_EN; - HFC_outb(hc, R_CONF_EN, r_conf_en); + if (hc->ctype != HFC_TYPE_XHFC) + HFC_outb(hc, R_CONF_EN, r_conf_en); /* setting leds */ switch (hc->leds) { @@ -1468,16 +1516,23 @@ init_chip(struct hfc_multi *hc) break; } + if (test_bit(HFC_CHIP_EMBSD, &hc->chip)) { + hc->hw.r_st_sync = 0x10; /* V_AUTO_SYNCI */ + HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync); + } + /* set master clock */ if (hc->masterclk >= 0) { if (debug & DEBUG_HFCMULTI_INIT) printk(KERN_DEBUG "%s: setting ST master clock " "to port %d (0..%d)\n", __func__, hc->masterclk, hc->ports-1); - hc->hw.r_st_sync = hc->masterclk | V_AUTO_SYNC; + hc->hw.r_st_sync |= (hc->masterclk | V_AUTO_SYNC); HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync); } + + /* setting misc irq */ HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc); if (debug & DEBUG_HFCMULTI_INIT) @@ -1817,8 +1872,8 @@ hfcmulti_dtmf(struct hfc_multi *hc) coeff[(co<<1)|1] = mantissa; } if (debug & DEBUG_HFCMULTI_DTMF) - printk("%s: DTMF ready %08x %08x %08x %08x " - "%08x %08x %08x %08x\n", __func__, + printk(" DTMF ready %08x %08x %08x %08x " + "%08x %08x %08x %08x\n", coeff[0], coeff[1], coeff[2], coeff[3], coeff[4], coeff[5], coeff[6], coeff[7]); hc->chan[ch].coeff_count++; @@ -1826,7 +1881,7 @@ hfcmulti_dtmf(struct hfc_multi *hc) hc->chan[ch].coeff_count = 0; skb = mI_alloc_skb(512, GFP_ATOMIC); if (!skb) { - printk(KERN_WARNING "%s: No memory for skb\n", + printk(KERN_DEBUG "%s: No memory for skb\n", __func__); continue; } @@ -1929,7 +1984,7 @@ hfcmulti_tx(struct hfc_multi *hc, int ch) Fspace = 1; } /* one frame only for ST D-channels, to allow resending */ - if (hc->type != 1 && dch) { + if (hc->ctype != HFC_TYPE_E1 && dch) { if (f1 != f2) Fspace = 0; } @@ -1945,6 +2000,9 @@ hfcmulti_tx(struct hfc_multi *hc, int ch) "%d!=%d\n", __func__, hc->id + 1, temp, z2); z2 = temp; /* repeat unti Z2 is equal */ } + hc->chan[ch].Zfill = z1 - z2; + if (hc->chan[ch].Zfill < 0) + hc->chan[ch].Zfill += hc->Zlen; Zspace = z2 - z1; if (Zspace <= 0) Zspace += hc->Zlen; @@ -1968,12 +2026,22 @@ hfcmulti_tx(struct hfc_multi *hc, int ch) "slot_tx %d\n", __func__, ch, slot_tx); /* connect slot */ - HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | - V_HDLC_TRP | V_IFF); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, A_CON_HDLC, 0xc0 + | 0x07 << 2 | V_HDLC_TRP | V_IFF); + /* Enable FIFO, no interrupt */ + else + HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | + V_HDLC_TRP | V_IFF); HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1); HFC_wait_nodebug(hc); - HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | - V_HDLC_TRP | V_IFF); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, A_CON_HDLC, 0xc0 + | 0x07 << 2 | V_HDLC_TRP | V_IFF); + /* Enable FIFO, no interrupt */ + else + HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | + V_HDLC_TRP | V_IFF); HFC_outb_nodebug(hc, R_FIFO, ch<<1); HFC_wait_nodebug(hc); } @@ -2001,10 +2069,22 @@ hfcmulti_tx(struct hfc_multi *hc, int ch) "FIFO data: channel %d slot_tx %d\n", __func__, ch, slot_tx); /* disconnect slot */ - HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, A_CON_HDLC, 0x80 + | 0x07 << 2 | V_HDLC_TRP | V_IFF); + /* Enable FIFO, no interrupt */ + else + HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | + V_HDLC_TRP | V_IFF); HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1); HFC_wait_nodebug(hc); - HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, A_CON_HDLC, 0x80 + | 0x07 << 2 | V_HDLC_TRP | V_IFF); + /* Enable FIFO, no interrupt */ + else + HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | + V_HDLC_TRP | V_IFF); HFC_outb_nodebug(hc, R_FIFO, ch<<1); HFC_wait_nodebug(hc); } @@ -2027,10 +2107,11 @@ hfcmulti_tx(struct hfc_multi *hc, int ch) printk(KERN_DEBUG "%s(card %d): fifo(%d) has %d bytes space " "left (z1=%04x, z2=%04x) sending %d of %d bytes %s\n", __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, - temp ? "HDLC":"TRANS"); + temp ? "HDLC" : "TRANS"); /* Have to prep the audio data */ hc->write_fifo(hc, d, ii - i); + hc->chan[ch].Zfill += ii - i; *idxp = ii; /* if not all data has been written */ @@ -2226,7 +2307,7 @@ hfcmulti_rx(struct hfc_multi *hc, int ch) if (dch) recv_Dchannel(dch); else - recv_Bchannel(bch); + recv_Bchannel(bch, MISDN_ID_ANY); *sp = skb; again++; goto next_frame; @@ -2258,7 +2339,7 @@ hfcmulti_rx(struct hfc_multi *hc, int ch) "(z1=%04x, z2=%04x) TRANS\n", __func__, hc->id + 1, ch, Zsize, z1, z2); /* only bch is transparent */ - recv_Bchannel(bch); + recv_Bchannel(bch, hc->chan[ch].Zfill); *sp = skb; } } @@ -2323,7 +2404,7 @@ handle_timer_irq(struct hfc_multi *hc) spin_unlock_irqrestore(&HFClock, flags); } - if (hc->type != 1 || hc->e1_state == 1) + if (hc->ctype != HFC_TYPE_E1 || hc->e1_state == 1) for (ch = 0; ch <= 31; ch++) { if (hc->created[hc->chan[ch].port]) { hfcmulti_tx(hc, ch); @@ -2346,7 +2427,7 @@ handle_timer_irq(struct hfc_multi *hc) } } } - if (hc->type == 1 && hc->created[0]) { + if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) { dch = hc->chan[hc->dslot].dch; if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) { /* LOS */ @@ -2606,7 +2687,10 @@ hfcmulti_interrupt(int intno, void *dev_id) "card %d, this is no bug.\n", hc->id + 1, irqsem); irqsem = hc->id + 1; #endif - +#ifdef CONFIG_MISDN_HFCMULTI_8xx + if (hc->immap->im_cpm.cp_pbdat & hc->pb_irqmsk) + goto irq_notforus; +#endif if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, flags); plx_acc = hc->plx_membase + PLX_INTCSR; @@ -2646,7 +2730,7 @@ hfcmulti_interrupt(int intno, void *dev_id) } hc->irqcnt++; if (r_irq_statech) { - if (hc->type != 1) + if (hc->ctype != HFC_TYPE_E1) ph_state_irq(hc, r_irq_statech); } if (status & V_EXT_IRQSTA) @@ -2660,7 +2744,7 @@ hfcmulti_interrupt(int intno, void *dev_id) r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC); r_irq_misc &= hc->hw.r_irqmsk_misc; /* ignore disabled irqs */ if (r_irq_misc & V_STA_IRQ) { - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { /* state machine */ dch = hc->chan[hc->dslot].dch; e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA); @@ -2699,13 +2783,13 @@ hfcmulti_interrupt(int intno, void *dev_id) handle_timer_irq(hc); } - if (r_irq_misc & V_DTMF_IRQ) { + if (r_irq_misc & V_DTMF_IRQ) hfcmulti_dtmf(hc); - } + if (r_irq_misc & V_IRQ_PROC) { static int irq_proc_cnt; if (!irq_proc_cnt++) - printk(KERN_WARNING "%s: got V_IRQ_PROC -" + printk(KERN_DEBUG "%s: got V_IRQ_PROC -" " this should not happen\n", __func__); } @@ -2782,7 +2866,8 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, if (hc->slot_owner[oslot_tx<<1] == ch) { HFC_outb(hc, R_SLOT, oslot_tx << 1); HFC_outb(hc, A_SL_CFG, 0); - HFC_outb(hc, A_CONF, 0); + if (hc->ctype != HFC_TYPE_XHFC) + HFC_outb(hc, A_CONF, 0); hc->slot_owner[oslot_tx<<1] = -1; } else { if (debug & DEBUG_HFCMULTI_MODE) @@ -2835,7 +2920,9 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, flow_tx, routing, conf); HFC_outb(hc, R_SLOT, slot_tx << 1); HFC_outb(hc, A_SL_CFG, (ch<<1) | routing); - HFC_outb(hc, A_CONF, (conf < 0) ? 0 : (conf | V_CONF_SL)); + if (hc->ctype != HFC_TYPE_XHFC) + HFC_outb(hc, A_CONF, + (conf < 0) ? 0 : (conf | V_CONF_SL)); hc->slot_owner[slot_tx << 1] = ch; hc->chan[ch].slot_tx = slot_tx; hc->chan[ch].bank_tx = bank_tx; @@ -2852,7 +2939,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, else flow_rx = 0xc0; /* ST->(FIFO,PCM) */ /* put on slot */ - routing = bank_rx?0x80:0xc0; /* reversed */ + routing = bank_rx ? 0x80 : 0xc0; /* reversed */ if (conf >= 0 || bank_rx > 1) routing = 0x40; /* loop */ if (debug & DEBUG_HFCMULTI_MODE) @@ -2885,9 +2972,9 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, HFC_outb(hc, A_IRQ_MSK, 0); HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); HFC_wait(hc); - if (hc->chan[ch].bch && hc->type != 1) { + if (hc->chan[ch].bch && hc->ctype != HFC_TYPE_E1) { hc->hw.a_st_ctrl0[hc->chan[ch].port] &= - ((ch & 0x3) == 0)? ~V_B1_EN: ~V_B2_EN; + ((ch & 0x3) == 0) ? ~V_B1_EN : ~V_B2_EN; HFC_outb(hc, R_ST_SEL, hc->chan[ch].port); /* undocumented: delay after R_ST_SEL */ udelay(1); @@ -2961,8 +3048,13 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, /* enable TX fifo */ HFC_outb(hc, R_FIFO, ch << 1); HFC_wait(hc); - HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | - V_HDLC_TRP | V_IFF); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, A_CON_HDLC, flow_tx | 0x07 << 2 | + V_HDLC_TRP | V_IFF); + /* Enable FIFO, no interrupt */ + else + HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | + V_HDLC_TRP | V_IFF); HFC_outb(hc, A_SUBCH_CFG, 0); HFC_outb(hc, A_IRQ_MSK, 0); HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); @@ -2972,13 +3064,19 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, /* enable RX fifo */ HFC_outb(hc, R_FIFO, (ch<<1)|1); HFC_wait(hc); - HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP); + if (hc->ctype == HFC_TYPE_XHFC) + HFC_outb(hc, A_CON_HDLC, flow_rx | 0x07 << 2 | + V_HDLC_TRP); + /* Enable FIFO, no interrupt*/ + else + HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | + V_HDLC_TRP); HFC_outb(hc, A_SUBCH_CFG, 0); HFC_outb(hc, A_IRQ_MSK, 0); HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); HFC_wait(hc); } - if (hc->type != 1) { + if (hc->ctype != HFC_TYPE_E1) { hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch & 0x3) == 0) ? V_B1_EN : V_B2_EN; HFC_outb(hc, R_ST_SEL, hc->chan[ch].port); @@ -2999,7 +3097,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, /* enable TX fifo */ HFC_outb(hc, R_FIFO, ch<<1); HFC_wait(hc); - if (hc->type == 1 || hc->chan[ch].bch) { + if (hc->ctype == HFC_TYPE_E1 || hc->chan[ch].bch) { /* E1 or B-channel */ HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04); HFC_outb(hc, A_SUBCH_CFG, 0); @@ -3015,7 +3113,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, HFC_outb(hc, R_FIFO, (ch<<1)|1); HFC_wait(hc); HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04); - if (hc->type == 1 || hc->chan[ch].bch) + if (hc->ctype == HFC_TYPE_E1 || hc->chan[ch].bch) HFC_outb(hc, A_SUBCH_CFG, 0); /* full 8 bits */ else HFC_outb(hc, A_SUBCH_CFG, 2); /* 2 bits dchannel */ @@ -3024,7 +3122,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, HFC_wait(hc); if (hc->chan[ch].bch) { test_and_set_bit(FLG_HDLC, &hc->chan[ch].bch->Flags); - if (hc->type != 1) { + if (hc->ctype != HFC_TYPE_E1) { hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch&0x3) == 0) ? V_B1_EN : V_B2_EN; HFC_outb(hc, R_ST_SEL, hc->chan[ch].port); @@ -3104,7 +3202,7 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) case HW_RESET_REQ: /* start activation */ spin_lock_irqsave(&hc->lock, flags); - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { if (debug & DEBUG_HFCMULTI_MSG) printk(KERN_DEBUG "%s: HW_RESET_REQ no BRI\n", @@ -3125,7 +3223,7 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) case HW_DEACT_REQ: /* start deactivation */ spin_lock_irqsave(&hc->lock, flags); - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { if (debug & DEBUG_HFCMULTI_MSG) printk(KERN_DEBUG "%s: HW_DEACT_REQ no BRI\n", @@ -3159,7 +3257,7 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) break; case HW_POWERUP_REQ: spin_lock_irqsave(&hc->lock, flags); - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { if (debug & DEBUG_HFCMULTI_MSG) printk(KERN_DEBUG "%s: HW_POWERUP_REQ no BRI\n", @@ -3236,7 +3334,7 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) __func__, hc->chan[dch->slot].port, hc->ports-1); /* start activation */ - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { ph_state_change(dch); if (debug & DEBUG_HFCMULTI_STATE) printk(KERN_DEBUG @@ -3269,7 +3367,7 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) __func__, hc->chan[dch->slot].port, hc->ports-1); /* start deactivation */ - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { if (debug & DEBUG_HFCMULTI_MSG) printk(KERN_DEBUG "%s: PH_DEACTIVATE no BRI\n", @@ -3410,9 +3508,9 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb) switch (hh->id) { case HFC_SPL_LOOP_ON: /* set sample loop */ if (debug & DEBUG_HFCMULTI_MSG) - printk(KERN_DEBUG - "%s: HFC_SPL_LOOP_ON (len = %d)\n", - __func__, skb->len); + printk(KERN_DEBUG + "%s: HFC_SPL_LOOP_ON (len = %d)\n", + __func__, skb->len); ret = 0; break; case HFC_SPL_LOOP_OFF: /* set silence */ @@ -3489,6 +3587,8 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) features->hfc_id = hc->id; if (test_bit(HFC_CHIP_DTMF, &hc->chip)) features->hfc_dtmf = 1; + if (test_bit(HFC_CHIP_CONF, &hc->chip)) + features->hfc_conf = 1; features->hfc_loops = 0; if (test_bit(HFC_CHIP_B410P, &hc->chip)) { features->hfc_echocanhw = 1; @@ -3619,14 +3719,13 @@ ph_state_change(struct dchannel *dch) int ch, i; if (!dch) { - printk(KERN_WARNING "%s: ERROR given dch is NULL\n", - __func__); + printk(KERN_WARNING "%s: ERROR given dch is NULL\n", __func__); return; } hc = dch->hw; ch = dch->slot; - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { if (dch->dev.D.protocol == ISDN_P_TE_E1) { if (debug & DEBUG_HFCMULTI_STATE) printk(KERN_DEBUG @@ -3641,14 +3740,15 @@ ph_state_change(struct dchannel *dch) switch (dch->state) { case (1): if (hc->e1_state != 1) { - for (i = 1; i <= 31; i++) { - /* reset fifos on e1 activation */ - HFC_outb_nodebug(hc, R_FIFO, (i << 1) | 1); - HFC_wait_nodebug(hc); - HFC_outb_nodebug(hc, - R_INC_RES_FIFO, V_RES_F); - HFC_wait_nodebug(hc); - } + for (i = 1; i <= 31; i++) { + /* reset fifos on e1 activation */ + HFC_outb_nodebug(hc, R_FIFO, + (i << 1) | 1); + HFC_wait_nodebug(hc); + HFC_outb_nodebug(hc, R_INC_RES_FIFO, + V_RES_F); + HFC_wait_nodebug(hc); + } } test_and_set_bit(FLG_ACTIVE, &dch->Flags); _queue_data(&dch->dev.D, PH_ACTIVATE_IND, @@ -3751,7 +3851,7 @@ hfcmulti_initmode(struct dchannel *dch) if (debug & DEBUG_HFCMULTI_INIT) printk(KERN_DEBUG "%s: entered\n", __func__); - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { hc->chan[hc->dslot].slot_tx = -1; hc->chan[hc->dslot].slot_rx = -1; hc->chan[hc->dslot].conf = -1; @@ -3900,6 +4000,11 @@ hfcmulti_initmode(struct dchannel *dch) } if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg)) hc->hw.a_st_ctrl0[pt] |= V_TX_LI; + if (hc->ctype == HFC_TYPE_XHFC) { + hc->hw.a_st_ctrl0[pt] |= 0x40 /* V_ST_PU_CTRL */; + HFC_outb(hc, 0x35 /* A_ST_CTRL3 */, + 0x7c << 1 /* V_ST_PULSE */); + } /* line setup */ HFC_outb(hc, A_ST_CTRL0, hc->hw.a_st_ctrl0[pt]); /* disable E-channel */ @@ -3943,12 +4048,12 @@ open_dchannel(struct hfc_multi *hc, struct dchannel *dch, return -EINVAL; if ((dch->dev.D.protocol != ISDN_P_NONE) && (dch->dev.D.protocol != rq->protocol)) { - if (debug & DEBUG_HFCMULTI_MODE) - printk(KERN_WARNING "%s: change protocol %x to %x\n", - __func__, dch->dev.D.protocol, rq->protocol); + if (debug & DEBUG_HFCMULTI_MODE) + printk(KERN_DEBUG "%s: change protocol %x to %x\n", + __func__, dch->dev.D.protocol, rq->protocol); } - if ((dch->dev.D.protocol == ISDN_P_TE_S0) - && (rq->protocol != ISDN_P_TE_S0)) + if ((dch->dev.D.protocol == ISDN_P_TE_S0) && + (rq->protocol != ISDN_P_TE_S0)) l1_event(dch->l1, CLOSE_CHANNEL); if (dch->dev.D.protocol != rq->protocol) { if (rq->protocol == ISDN_P_TE_S0) { @@ -3986,7 +4091,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; - if (hc->type == 1) + if (hc->ctype == HFC_TYPE_E1) ch = rq->adr.channel; else ch = (rq->adr.channel - 1) + (dch->slot - 2); @@ -4013,11 +4118,41 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, static int channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq) { + struct hfc_multi *hc = dch->hw; int ret = 0; + int wd_mode, wd_cnt; switch (cq->op) { case MISDN_CTRL_GETOP: - cq->op = 0; + cq->op = MISDN_CTRL_HFC_OP; + break; + case MISDN_CTRL_HFC_WD_INIT: /* init the watchdog */ + wd_cnt = cq->p1 & 0xf; + wd_mode = !!(cq->p1 >> 4); + if (debug & DEBUG_HFCMULTI_MSG) + printk(KERN_DEBUG "%s: MISDN_CTRL_HFC_WD_INIT mode %s" + ", counter 0x%x\n", __func__, + wd_mode ? "AUTO" : "MANUAL", wd_cnt); + /* set the watchdog timer */ + HFC_outb(hc, R_TI_WD, poll_timer | (wd_cnt << 4)); + hc->hw.r_bert_wd_md = (wd_mode ? V_AUTO_WD_RES : 0); + if (hc->ctype == HFC_TYPE_XHFC) + hc->hw.r_bert_wd_md |= 0x40 /* V_WD_EN */; + /* init the watchdog register and reset the counter */ + HFC_outb(hc, R_BERT_WD_MD, hc->hw.r_bert_wd_md | V_WD_RES); + if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { + /* enable the watchdog output for Speech-Design */ + HFC_outb(hc, R_GPIO_SEL, V_GPIO_SEL7); + HFC_outb(hc, R_GPIO_EN1, V_GPIO_EN15); + HFC_outb(hc, R_GPIO_OUT1, 0); + HFC_outb(hc, R_GPIO_OUT1, V_GPIO_OUT15); + } + break; + case MISDN_CTRL_HFC_WD_RESET: /* reset the watchdog counter */ + if (debug & DEBUG_HFCMULTI_MSG) + printk(KERN_DEBUG "%s: MISDN_CTRL_HFC_WD_RESET\n", + __func__); + HFC_outb(hc, R_BERT_WD_MD, hc->hw.r_bert_wd_md | V_WD_RES); break; default: printk(KERN_WARNING "%s: unknown Op %x\n", @@ -4047,7 +4182,7 @@ hfcm_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg) switch (rq->protocol) { case ISDN_P_TE_S0: case ISDN_P_NT_S0: - if (hc->type == 1) { + if (hc->ctype == HFC_TYPE_E1) { err = -EINVAL; break; } @@ -4055,7 +4190,7 @@ hfcm_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg) break; case ISDN_P_TE_E1: case ISDN_P_NT_E1: - if (hc->type != 1) { + if (hc->ctype != HFC_TYPE_E1) { err = -EINVAL; break; } @@ -4122,13 +4257,13 @@ init_card(struct hfc_multi *hc) disable_hwirq(hc); spin_unlock_irqrestore(&hc->lock, flags); - if (request_irq(hc->pci_dev->irq, hfcmulti_interrupt, IRQF_SHARED, + if (request_irq(hc->irq, hfcmulti_interrupt, IRQF_SHARED, "HFC-multi", hc)) { printk(KERN_WARNING "mISDN: Could not get interrupt %d.\n", - hc->pci_dev->irq); + hc->irq); + hc->irq = 0; return -EIO; } - hc->irq = hc->pci_dev->irq; if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, plx_flags); @@ -4187,7 +4322,7 @@ init_card(struct hfc_multi *hc) } if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: free irq %d\n", __func__, hc->irq); + printk(KERN_DEBUG "%s: free irq %d\n", __func__, hc->irq); if (hc->irq) { free_irq(hc->irq, hc); hc->irq = 0; @@ -4235,6 +4370,10 @@ setup_pci(struct hfc_multi *hc, struct pci_dev *pdev, hc->ledstate = 0xAFFEAFFE; hc->opticalsupport = m->opticalsupport; + hc->pci_iobase = 0; + hc->pci_membase = NULL; + hc->plx_membase = NULL; + /* set memory access methods */ if (m->io_mode) /* use mode from card config */ hc->io_mode = m->io_mode; @@ -4242,44 +4381,12 @@ setup_pci(struct hfc_multi *hc, struct pci_dev *pdev, case HFC_IO_MODE_PLXSD: test_and_set_bit(HFC_CHIP_PLXSD, &hc->chip); hc->slots = 128; /* required */ - /* fall through */ - case HFC_IO_MODE_PCIMEM: hc->HFC_outb = HFC_outb_pcimem; hc->HFC_inb = HFC_inb_pcimem; hc->HFC_inw = HFC_inw_pcimem; hc->HFC_wait = HFC_wait_pcimem; hc->read_fifo = read_fifo_pcimem; hc->write_fifo = write_fifo_pcimem; - break; - case HFC_IO_MODE_REGIO: - hc->HFC_outb = HFC_outb_regio; - hc->HFC_inb = HFC_inb_regio; - hc->HFC_inw = HFC_inw_regio; - hc->HFC_wait = HFC_wait_regio; - hc->read_fifo = read_fifo_regio; - hc->write_fifo = write_fifo_regio; - break; - default: - printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); - pci_disable_device(hc->pci_dev); - return -EIO; - } - hc->HFC_outb_nodebug = hc->HFC_outb; - hc->HFC_inb_nodebug = hc->HFC_inb; - hc->HFC_inw_nodebug = hc->HFC_inw; - hc->HFC_wait_nodebug = hc->HFC_wait; -#ifdef HFC_REGISTER_DEBUG - hc->HFC_outb = HFC_outb_debug; - hc->HFC_inb = HFC_inb_debug; - hc->HFC_inw = HFC_inw_debug; - hc->HFC_wait = HFC_wait_debug; -#endif - hc->pci_iobase = 0; - hc->pci_membase = NULL; - hc->plx_membase = NULL; - - switch (hc->io_mode) { - case HFC_IO_MODE_PLXSD: hc->plx_origmembase = hc->pci_dev->resource[0].start; /* MEMBASE 1 is PLX PCI Bridge */ @@ -4327,6 +4434,12 @@ setup_pci(struct hfc_multi *hc, struct pci_dev *pdev, pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO); break; case HFC_IO_MODE_PCIMEM: + hc->HFC_outb = HFC_outb_pcimem; + hc->HFC_inb = HFC_inb_pcimem; + hc->HFC_inw = HFC_inw_pcimem; + hc->HFC_wait = HFC_wait_pcimem; + hc->read_fifo = read_fifo_pcimem; + hc->write_fifo = write_fifo_pcimem; hc->pci_origmembase = hc->pci_dev->resource[1].start; if (!hc->pci_origmembase) { printk(KERN_WARNING @@ -4343,12 +4456,18 @@ setup_pci(struct hfc_multi *hc, struct pci_dev *pdev, pci_disable_device(hc->pci_dev); return -EIO; } - printk(KERN_INFO "card %d: defined at MEMBASE %#lx (%#lx) IRQ %d " - "HZ %d leds-type %d\n", hc->id, (u_long)hc->pci_membase, + printk(KERN_INFO "card %d: defined at MEMBASE %#lx (%#lx) IRQ " + "%d HZ %d leds-type %d\n", hc->id, (u_long)hc->pci_membase, hc->pci_origmembase, hc->pci_dev->irq, HZ, hc->leds); pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO); break; case HFC_IO_MODE_REGIO: + hc->HFC_outb = HFC_outb_regio; + hc->HFC_inb = HFC_inb_regio; + hc->HFC_inw = HFC_inw_regio; + hc->HFC_wait = HFC_wait_regio; + hc->read_fifo = read_fifo_regio; + hc->write_fifo = write_fifo_regio; hc->pci_iobase = (u_int) hc->pci_dev->resource[0].start; if (!hc->pci_iobase) { printk(KERN_WARNING @@ -4430,7 +4549,7 @@ release_port(struct hfc_multi *hc, struct dchannel *dch) dch->timer.function = NULL; } - if (hc->type == 1) { /* E1 */ + if (hc->ctype == HFC_TYPE_E1) { /* E1 */ /* remove sync */ if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { hc->syncronized = 0; @@ -4508,7 +4627,7 @@ release_card(struct hfc_multi *hc) int ch; if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: release card (%d) entered\n", + printk(KERN_DEBUG "%s: release card (%d) entered\n", __func__, hc->id); /* unregister clock source */ @@ -4537,7 +4656,7 @@ release_card(struct hfc_multi *hc) /* release hardware & irq */ if (hc->irq) { if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: free irq %d\n", + printk(KERN_DEBUG "%s: free irq %d\n", __func__, hc->irq); free_irq(hc->irq, hc); hc->irq = 0; @@ -4546,17 +4665,17 @@ release_card(struct hfc_multi *hc) release_io_hfcmulti(hc); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: remove instance from list\n", + printk(KERN_DEBUG "%s: remove instance from list\n", __func__); list_del(&hc->list); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: delete instance\n", __func__); + printk(KERN_DEBUG "%s: delete instance\n", __func__); if (hc == syncmaster) syncmaster = NULL; kfree(hc); if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_WARNING "%s: card successfully removed\n", + printk(KERN_DEBUG "%s: card successfully removed\n", __func__); } @@ -4579,7 +4698,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); dch->dev.D.send = handle_dmsg; dch->dev.D.ctrl = hfcm_dctrl; - dch->dev.nrbchan = (hc->dslot)?30:31; + dch->dev.nrbchan = (hc->dslot) ? 30 : 31; dch->slot = hc->dslot; hc->chan[hc->dslot].dch = dch; hc->chan[hc->dslot].port = 0; @@ -4821,7 +4940,7 @@ init_multi_port(struct hfc_multi *hc, int pt) } /* disable E-channel */ if (port[Port_cnt] & 0x004) { - if (debug & DEBUG_HFCMULTI_INIT) + if (debug & DEBUG_HFCMULTI_INIT) printk(KERN_DEBUG "%s: PROTOCOL disable E-channel: " "card(%d) port(%d)\n", @@ -4829,9 +4948,15 @@ init_multi_port(struct hfc_multi *hc, int pt) test_and_set_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i + 2].cfg); } - snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d", - hc->type, HFC_cnt + 1, pt + 1); - ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); + if (hc->ctype == HFC_TYPE_XHFC) { + snprintf(name, MISDN_MAX_IDLEN - 1, "xhfc.%d-%d", + HFC_cnt + 1, pt + 1); + ret = mISDN_register_device(&dch->dev, NULL, name); + } else { + snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d", + hc->ctype, HFC_cnt + 1, pt + 1); + ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); + } if (ret) goto free_chan; hc->created[pt] = 1; @@ -4842,9 +4967,9 @@ init_multi_port(struct hfc_multi *hc, int pt) } static int -hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) +hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct hm_map *m = (struct hm_map *)ent->driver_data; int ret_err = 0; int pt; struct hfc_multi *hc; @@ -4879,16 +5004,18 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) } spin_lock_init(&hc->lock); hc->mtyp = m; - hc->type = m->type; + hc->ctype = m->type; hc->ports = m->ports; hc->id = HFC_cnt; hc->pcm = pcm[HFC_cnt]; hc->io_mode = iomode[HFC_cnt]; - if (dslot[HFC_cnt] < 0 && hc->type == 1) { + if (dslot[HFC_cnt] < 0 && hc->ctype == HFC_TYPE_E1) { hc->dslot = 0; printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " "31 B-channels\n"); - } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) { + } + if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 + && hc->ctype == HFC_TYPE_E1) { hc->dslot = dslot[HFC_cnt]; printk(KERN_INFO "HFC-E1 card has alternating D-channel on " "time slot %d\n", dslot[HFC_cnt]); @@ -4910,8 +5037,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < (poll >> 1); i++) hc->silence_data[i] = hc->silence; - if (!(type[HFC_cnt] & 0x200)) - test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); + if (hc->ctype != HFC_TYPE_XHFC) { + if (!(type[HFC_cnt] & 0x200)) + test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); + test_and_set_bit(HFC_CHIP_CONF, &hc->chip); + } if (type[HFC_cnt] & 0x800) test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); @@ -4935,8 +5065,18 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) printk(KERN_NOTICE "Watchdog enabled\n"); } - /* setup pci, hc->slots may change due to PLXSD */ - ret_err = setup_pci(hc, pdev, ent); + if (pdev && ent) + /* setup pci, hc->slots may change due to PLXSD */ + ret_err = setup_pci(hc, pdev, ent); + else +#ifdef CONFIG_MISDN_HFCMULTI_8xx + ret_err = setup_embedded(hc, m); +#else + { + printk(KERN_WARNING "Embedded IO Mode not selected\n"); + ret_err = -EIO; + } +#endif if (ret_err) { if (hc == syncmaster) syncmaster = NULL; @@ -4944,7 +5084,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) return ret_err; } - /* crate channels */ + hc->HFC_outb_nodebug = hc->HFC_outb; + hc->HFC_inb_nodebug = hc->HFC_inb; + hc->HFC_inw_nodebug = hc->HFC_inw; + hc->HFC_wait_nodebug = hc->HFC_wait; +#ifdef HFC_REGISTER_DEBUG + hc->HFC_outb = HFC_outb_debug; + hc->HFC_inb = HFC_inb_debug; + hc->HFC_inw = HFC_inw_debug; + hc->HFC_wait = HFC_wait_debug; +#endif + /* create channels */ for (pt = 0; pt < hc->ports; pt++) { if (Port_cnt >= MAX_PORTS) { printk(KERN_ERR "too many ports (max=%d).\n", @@ -4952,7 +5102,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) ret_err = -EINVAL; goto free_card; } - if (hc->type == 1) + if (hc->ctype == HFC_TYPE_E1) ret_err = init_e1_port(hc, m); else ret_err = init_multi_port(hc, pt); @@ -5036,6 +5186,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) hc->iclock = mISDN_register_clock("HFCMulti", 0, clockctl, hc); /* initialize hardware */ + hc->irq = (m->irq) ? : hc->pci_dev->irq; ret_err = init_card(hc); if (ret_err) { printk(KERN_ERR "init card returns %d\n", ret_err); @@ -5074,7 +5225,7 @@ static void __devexit hfc_remove_pci(struct pci_dev *pdev) spin_unlock_irqrestore(&HFClock, flags); } else { if (debug) - printk(KERN_WARNING "%s: drvdata allready removed\n", + printk(KERN_DEBUG "%s: drvdata allready removed\n", __func__); } } @@ -5086,45 +5237,48 @@ static void __devexit hfc_remove_pci(struct pci_dev *pdev) #define VENDOR_PRIM "PrimuX" static const struct hm_map hfcm_map[] = { -/*0*/ {VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0}, -/*1*/ {VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S, 0}, -/*2*/ {VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0}, -/*3*/ {VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0}, -/*4*/ {VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0}, -/*5*/ {VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0}, -/*6*/ {VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, DIP_4S, 0}, -/*7*/ {VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0}, -/*8*/ {VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO}, -/*9*/ {VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0}, -/*10*/ {VENDOR_JH, "HFC-4S (junghanns 2.0)", 4, 4, 1, 2, 0, 0, 0}, -/*11*/ {VENDOR_PRIM, "HFC-2S Primux Card", 4, 2, 0, 0, 0, 0, 0}, +/*0*/ {VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0, 0}, +/*1*/ {VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S, 0, 0}, +/*2*/ {VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0, 0}, +/*3*/ {VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0, 0}, +/*4*/ {VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0, 0}, +/*5*/ {VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0, 0}, +/*6*/ {VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, DIP_4S, 0, 0}, +/*7*/ {VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0, 0}, +/*8*/ {VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO, 0}, +/*9*/ {VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0, 0}, +/*10*/ {VENDOR_JH, "HFC-4S (junghanns 2.0)", 4, 4, 1, 2, 0, 0, 0, 0}, +/*11*/ {VENDOR_PRIM, "HFC-2S Primux Card", 4, 2, 0, 0, 0, 0, 0, 0}, -/*12*/ {VENDOR_BN, "HFC-8S Card", 8, 8, 1, 0, 0, 0, 0}, +/*12*/ {VENDOR_BN, "HFC-8S Card", 8, 8, 1, 0, 0, 0, 0, 0}, /*13*/ {VENDOR_BN, "HFC-8S Card (+)", 8, 8, 1, 8, 0, DIP_8S, - HFC_IO_MODE_REGIO}, -/*14*/ {VENDOR_CCD, "HFC-8S Eval (old)", 8, 8, 0, 0, 0, 0, 0}, -/*15*/ {VENDOR_CCD, "HFC-8S IOB4ST Recording", 8, 8, 1, 0, 0, 0, 0}, + HFC_IO_MODE_REGIO, 0}, +/*14*/ {VENDOR_CCD, "HFC-8S Eval (old)", 8, 8, 0, 0, 0, 0, 0, 0}, +/*15*/ {VENDOR_CCD, "HFC-8S IOB4ST Recording", 8, 8, 1, 0, 0, 0, 0, 0}, -/*16*/ {VENDOR_CCD, "HFC-8S IOB8ST", 8, 8, 1, 0, 0, 0, 0}, -/*17*/ {VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0}, -/*18*/ {VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0}, +/*16*/ {VENDOR_CCD, "HFC-8S IOB8ST", 8, 8, 1, 0, 0, 0, 0, 0}, +/*17*/ {VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0, 0}, +/*18*/ {VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0, 0}, -/*19*/ {VENDOR_BN, "HFC-E1 Card", 1, 1, 0, 1, 0, DIP_E1, 0}, -/*20*/ {VENDOR_BN, "HFC-E1 Card (mini PCI)", 1, 1, 0, 1, 0, 0, 0}, -/*21*/ {VENDOR_BN, "HFC-E1+ Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0}, -/*22*/ {VENDOR_BN, "HFC-E1 Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0}, +/*19*/ {VENDOR_BN, "HFC-E1 Card", 1, 1, 0, 1, 0, DIP_E1, 0, 0}, +/*20*/ {VENDOR_BN, "HFC-E1 Card (mini PCI)", 1, 1, 0, 1, 0, 0, 0, 0}, +/*21*/ {VENDOR_BN, "HFC-E1+ Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0, 0}, +/*22*/ {VENDOR_BN, "HFC-E1 Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0, 0}, -/*23*/ {VENDOR_CCD, "HFC-E1 Eval (old)", 1, 1, 0, 0, 0, 0, 0}, -/*24*/ {VENDOR_CCD, "HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0, 0}, -/*25*/ {VENDOR_CCD, "HFC-E1", 1, 1, 0, 1, 0, 0, 0}, +/*23*/ {VENDOR_CCD, "HFC-E1 Eval (old)", 1, 1, 0, 0, 0, 0, 0, 0}, +/*24*/ {VENDOR_CCD, "HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0, 0, 0}, +/*25*/ {VENDOR_CCD, "HFC-E1", 1, 1, 0, 1, 0, 0, 0, 0}, /*26*/ {VENDOR_CCD, "HFC-4S Speech Design", 4, 4, 0, 0, 0, 0, - HFC_IO_MODE_PLXSD}, + HFC_IO_MODE_PLXSD, 0}, /*27*/ {VENDOR_CCD, "HFC-E1 Speech Design", 1, 1, 0, 0, 0, 0, - HFC_IO_MODE_PLXSD}, -/*28*/ {VENDOR_CCD, "HFC-4S OpenVox", 4, 4, 1, 0, 0, 0, 0}, -/*29*/ {VENDOR_CCD, "HFC-2S OpenVox", 4, 2, 1, 0, 0, 0, 0}, -/*30*/ {VENDOR_CCD, "HFC-8S OpenVox", 8, 8, 1, 0, 0, 0, 0}, + HFC_IO_MODE_PLXSD, 0}, +/*28*/ {VENDOR_CCD, "HFC-4S OpenVox", 4, 4, 1, 0, 0, 0, 0, 0}, +/*29*/ {VENDOR_CCD, "HFC-2S OpenVox", 4, 2, 1, 0, 0, 0, 0, 0}, +/*30*/ {VENDOR_CCD, "HFC-8S OpenVox", 8, 8, 1, 0, 0, 0, 0, 0}, +/*31*/ {VENDOR_CCD, "XHFC-4S Speech Design", 5, 4, 0, 0, 0, 0, + HFC_IO_MODE_EMBSD, XHFC_IRQ}, +/*32*/ {VENDOR_JH, "HFC-8S (junghanns)", 8, 8, 1, 0, 0, 0, 0, 0}, }; #undef H @@ -5178,6 +5332,8 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = { PCI_SUBDEVICE_ID_CCD_HFC8S, 0, 0, H(18)}, /* 8S */ { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, PCI_SUBDEVICE_ID_CCD_OV8S, 0, 0, H(30)}, /* OpenVox 8 */ + { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, + PCI_SUBDEVICE_ID_CCD_JH8S, 0, 0, H(32)}, /* Junganns 8S */ /* Cards with HFC-E1 Chip */ @@ -5201,6 +5357,10 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = { PCI_SUBDEVICE_ID_CCD_SPD4S, 0, 0, H(26)}, /* PLX PCI Bridge */ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_CCD, PCI_SUBDEVICE_ID_CCD_SPDE1, 0, 0, H(27)}, /* PLX PCI Bridge */ + + { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, + PCI_SUBDEVICE_ID_CCD_JHSE1, 0, 0, H(25)}, /* Junghanns E1 */ + { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_ANY_ID, PCI_ANY_ID, @@ -5231,7 +5391,7 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent) "Please contact the driver maintainer for support.\n"); return -ENODEV; } - ret = hfcmulti_init(pdev, ent); + ret = hfcmulti_init(m, pdev, ent); if (ret) return ret; HFC_cnt++; @@ -5261,6 +5421,8 @@ static int __init HFCmulti_init(void) { int err; + int i, xhfc = 0; + struct hm_map m; printk(KERN_INFO "mISDN: HFC-multi driver %s\n", HFC_MULTI_VERSION); @@ -5308,11 +5470,43 @@ HFCmulti_init(void) if (!clock) clock = 1; + /* Register the embedded devices. + * This should be done before the PCI cards registration */ + switch (hwid) { + case HWID_MINIP4: + xhfc = 1; + m = hfcm_map[31]; + break; + case HWID_MINIP8: + xhfc = 2; + m = hfcm_map[31]; + break; + case HWID_MINIP16: + xhfc = 4; + m = hfcm_map[31]; + break; + default: + xhfc = 0; + } + + for (i = 0; i < xhfc; ++i) { + err = hfcmulti_init(&m, NULL, NULL); + if (err) { + printk(KERN_ERR "error registering embedded driver: " + "%x\n", err); + return -err; + } + HFC_cnt++; + printk(KERN_INFO "%d devices registered\n", HFC_cnt); + } + + /* Register the PCI cards */ err = pci_register_driver(&hfcmultipci_driver); if (err < 0) { printk(KERN_ERR "error registering pci driver: %x\n", err); return err; } + return 0; } diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 641a9cd1a532..228ffbed1286 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -257,7 +257,7 @@ reset_hfcpci(struct hfc_pci *hc) Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1); /* Clear already pending ints */ - if (Read_hfc(hc, HFCPCI_INT_S1)); + val = Read_hfc(hc, HFCPCI_INT_S1); /* set NT/TE mode */ hfcpci_setmode(hc); @@ -452,7 +452,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz, } bz->za[new_f2].z2 = cpu_to_le16(new_z2); bz->f2 = new_f2; /* next buffer */ - recv_Bchannel(bch); + recv_Bchannel(bch, MISDN_ID_ANY); } } @@ -499,7 +499,8 @@ receive_dmsg(struct hfc_pci *hc) df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ df->za[df->f2 & D_FREG_MASK].z2 = - cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1)); + cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & + (D_FIFO_SIZE - 1)); } else { dch->rx_skb = mI_alloc_skb(rcnt - 3, GFP_ATOMIC); if (!dch->rx_skb) { @@ -541,35 +542,45 @@ receive_dmsg(struct hfc_pci *hc) * check for transparent receive data and read max one 'poll' size if avail */ static void -hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) +hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz, + struct bzfifo *txbz, u_char *bdata) { - __le16 *z1r, *z2r; - int new_z2, fcnt, maxlen; - u_char *ptr, *ptr1; + __le16 *z1r, *z2r, *z1t, *z2t; + int new_z2, fcnt_rx, fcnt_tx, maxlen; + u_char *ptr, *ptr1; - z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ + z1r = &rxbz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ z2r = z1r + 1; + z1t = &txbz->za[MAX_B_FRAMES].z1; + z2t = z1t + 1; - fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r); - if (!fcnt) + fcnt_rx = le16_to_cpu(*z1r) - le16_to_cpu(*z2r); + if (!fcnt_rx) return; /* no data avail */ - if (fcnt <= 0) - fcnt += B_FIFO_SIZE; /* bytes actually buffered */ - new_z2 = le16_to_cpu(*z2r) + fcnt; /* new position in fifo */ + if (fcnt_rx <= 0) + fcnt_rx += B_FIFO_SIZE; /* bytes actually buffered */ + new_z2 = le16_to_cpu(*z2r) + fcnt_rx; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ - if (fcnt > MAX_DATA_SIZE) { /* flush, if oversized */ + if (fcnt_rx > MAX_DATA_SIZE) { /* flush, if oversized */ *z2r = cpu_to_le16(new_z2); /* new position */ return; } - bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC); + fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); + if (fcnt_tx <= 0) + fcnt_tx += B_FIFO_SIZE; + /* fcnt_tx contains available bytes in tx-fifo */ + fcnt_tx = B_FIFO_SIZE - fcnt_tx; + /* remaining bytes to send (bytes in tx-fifo) */ + + bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC); if (bch->rx_skb) { - ptr = skb_put(bch->rx_skb, fcnt); - if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL) - maxlen = fcnt; /* complete transfer */ + ptr = skb_put(bch->rx_skb, fcnt_rx); + if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL) + maxlen = fcnt_rx; /* complete transfer */ else maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r); /* maximum */ @@ -577,14 +588,14 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ - fcnt -= maxlen; + fcnt_rx -= maxlen; - if (fcnt) { /* rest remaining */ + if (fcnt_rx) { /* rest remaining */ ptr += maxlen; ptr1 = bdata; /* start of buffer */ - memcpy(ptr, ptr1, fcnt); /* rest */ + memcpy(ptr, ptr1, fcnt_rx); /* rest */ } - recv_Bchannel(bch); + recv_Bchannel(bch, fcnt_tx); /* bch, id */ } else printk(KERN_WARNING "HFCPCI: receive out of memory\n"); @@ -600,26 +611,28 @@ main_rec_hfcpci(struct bchannel *bch) struct hfc_pci *hc = bch->hw; int rcnt, real_fifo; int receive = 0, count = 5; - struct bzfifo *bz; + struct bzfifo *txbz, *rxbz; u_char *bdata; struct zt *zp; if ((bch->nr & 2) && (!hc->hw.bswapped)) { - bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2; + rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2; + txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2; bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2; real_fifo = 1; } else { - bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1; + rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1; + txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b1; bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1; real_fifo = 0; } Begin: count--; - if (bz->f1 != bz->f2) { + if (rxbz->f1 != rxbz->f2) { if (bch->debug & DEBUG_HW_BCHANNEL) printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n", - bch->nr, bz->f1, bz->f2); - zp = &bz->za[bz->f2]; + bch->nr, rxbz->f1, rxbz->f2); + zp = &rxbz->za[rxbz->f2]; rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); if (rcnt < 0) @@ -630,8 +643,8 @@ main_rec_hfcpci(struct bchannel *bch) "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n", bch->nr, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); - hfcpci_empty_bfifo(bch, bz, bdata, rcnt); - rcnt = bz->f1 - bz->f2; + hfcpci_empty_bfifo(bch, rxbz, bdata, rcnt); + rcnt = rxbz->f1 - rxbz->f2; if (rcnt < 0) rcnt += MAX_B_FRAMES + 1; if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) { @@ -644,7 +657,7 @@ main_rec_hfcpci(struct bchannel *bch) else receive = 0; } else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { - hfcpci_empty_fifo_trans(bch, bz, bdata); + hfcpci_empty_fifo_trans(bch, rxbz, txbz, bdata); return; } else receive = 0; @@ -954,6 +967,7 @@ static void ph_state_nt(struct dchannel *dch) { struct hfc_pci *hc = dch->hw; + u_char val; if (dch->debug) printk(KERN_DEBUG "%s: NT newstate %x\n", @@ -967,7 +981,7 @@ ph_state_nt(struct dchannel *dch) hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER; Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1); /* Clear already pending ints */ - if (Read_hfc(hc, HFCPCI_INT_S1)); + val = Read_hfc(hc, HFCPCI_INT_S1); Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); udelay(10); Write_hfc(hc, HFCPCI_STATES, 4); @@ -1256,8 +1270,7 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol) rx_slot = (bc>>8) & 0xff; tx_slot = (bc>>16) & 0xff; bc = bc & 0xff; - } else if (test_bit(HFC_CFG_PCM, &hc->cfg) && - (protocol > ISDN_P_NONE)) + } else if (test_bit(HFC_CFG_PCM, &hc->cfg) && (protocol > ISDN_P_NONE)) printk(KERN_WARNING "%s: no pcm channel id but HFC_CFG_PCM\n", __func__); if (hc->chanlimit > 1) { @@ -1315,8 +1328,8 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol) case (ISDN_P_B_RAW): bch->state = protocol; bch->nr = bc; - hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0); - hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0); + hfcpci_clear_fifo_rx(hc, (fifo2 & 2) ? 1 : 0); + hfcpci_clear_fifo_tx(hc, (fifo2 & 2) ? 1 : 0); if (bc & 2) { hc->hw.sctrl |= SCTRL_B2_ENA; hc->hw.sctrl_r |= SCTRL_B2_ENA; @@ -1350,8 +1363,8 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol) case (ISDN_P_B_HDLC): bch->state = protocol; bch->nr = bc; - hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0); - hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0); + hfcpci_clear_fifo_rx(hc, (fifo2 & 2) ? 1 : 0); + hfcpci_clear_fifo_tx(hc, (fifo2 & 2) ? 1 : 0); if (bc & 2) { hc->hw.sctrl |= SCTRL_B2_ENA; hc->hw.sctrl_r |= SCTRL_B2_ENA; @@ -1445,7 +1458,7 @@ set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan) switch (protocol) { case (ISDN_P_B_RAW): bch->state = protocol; - hfcpci_clear_fifo_rx(hc, (chan & 2)?1:0); + hfcpci_clear_fifo_rx(hc, (chan & 2) ? 1 : 0); if (chan & 2) { hc->hw.sctrl_r |= SCTRL_B2_ENA; hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX; @@ -1470,7 +1483,7 @@ set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan) break; case (ISDN_P_B_HDLC): bch->state = protocol; - hfcpci_clear_fifo_rx(hc, (chan & 2)?1:0); + hfcpci_clear_fifo_rx(hc, (chan & 2) ? 1 : 0); if (chan & 2) { hc->hw.sctrl_r |= SCTRL_B2_ENA; hc->hw.last_bfifo_cnt[1] = 0; @@ -1793,10 +1806,9 @@ init_card(struct hfc_pci *hc) printk(KERN_WARNING "HFC PCI: IRQ(%d) getting no interrupts " "during init %d\n", hc->irq, 4 - cnt); - if (cnt == 1) { - spin_unlock_irqrestore(&hc->lock, flags); - return -EIO; - } else { + if (cnt == 1) + break; + else { reset_hfcpci(hc); cnt--; } @@ -2035,7 +2047,8 @@ setup_hw(struct hfc_pci *hc) printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); return 1; } - hc->hw.pci_io = (char __iomem *)(unsigned long)hc->pdev->resource[1].start; + hc->hw.pci_io = + (char __iomem *)(unsigned long)hc->pdev->resource[1].start; if (!hc->hw.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); @@ -2277,7 +2290,7 @@ hfc_remove_pci(struct pci_dev *pdev) release_card(card); else if (debug) - printk(KERN_WARNING "%s: drvdata already removed\n", + printk(KERN_DEBUG "%s: drvdata already removed\n", __func__); } diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 9c427fb204ee..6b7704c41b94 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -947,7 +947,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len, if (fifo->dch) recv_Dchannel(fifo->dch); if (fifo->bch) - recv_Bchannel(fifo->bch); + recv_Bchannel(fifo->bch, MISDN_ID_ANY); if (fifo->ech) recv_Echannel(fifo->ech, &hw->dch); @@ -969,7 +969,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len, } else { /* deliver transparent data to layer2 */ if (rx_skb->len >= poll) - recv_Bchannel(fifo->bch); + recv_Bchannel(fifo->bch, MISDN_ID_ANY); } spin_unlock(&hw->lock); } diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index f1265667b062..3d337d924c23 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -82,8 +82,9 @@ release_io_hfcpci(struct IsdnCardState *cs) Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ del_timer(&cs->hw.hfcpci.timer); - kfree(cs->hw.hfcpci.share_start); - cs->hw.hfcpci.share_start = NULL; + pci_free_consistent(cs->hw.hfcpci.dev, 0x8000, + cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma); + cs->hw.hfcpci.fifos = NULL; iounmap((void *)cs->hw.hfcpci.pci_io); } @@ -1663,8 +1664,19 @@ setup_hfcpci(struct IsdnCard *card) dev_hfcpci); i++; if (tmp_hfcpci) { + dma_addr_t dma_mask = DMA_BIT_MASK(32) & ~0x7fffUL; if (pci_enable_device(tmp_hfcpci)) continue; + if (pci_set_dma_mask(tmp_hfcpci, dma_mask)) { + printk(KERN_WARNING + "HiSax hfc_pci: No suitable DMA available.\n"); + continue; + } + if (pci_set_consistent_dma_mask(tmp_hfcpci, dma_mask)) { + printk(KERN_WARNING + "HiSax hfc_pci: No suitable consistent DMA available.\n"); + continue; + } pci_set_master(tmp_hfcpci); if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) continue; @@ -1693,22 +1705,29 @@ setup_hfcpci(struct IsdnCard *card) printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); return (0); } + /* Allocate memory for FIFOS */ - /* Because the HFC-PCI needs a 32K physical alignment, we */ - /* need to allocate the double mem and align the address */ - if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) { - printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); + cs->hw.hfcpci.fifos = pci_alloc_consistent(cs->hw.hfcpci.dev, + 0x8000, &cs->hw.hfcpci.dma); + if (!cs->hw.hfcpci.fifos) { + printk(KERN_WARNING "HFC-PCI: Error allocating FIFO memory!\n"); return 0; } - cs->hw.hfcpci.fifos = (void *) - (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; - pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); + if (cs->hw.hfcpci.dma & 0x7fff) { + printk(KERN_WARNING + "HFC-PCI: Error DMA memory not on 32K boundary (%lx)\n", + (u_long)cs->hw.hfcpci.dma); + pci_free_consistent(cs->hw.hfcpci.dev, 0x8000, + cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma); + return 0; + } + pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u32)cs->hw.hfcpci.dma); cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); printk(KERN_INFO - "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n", + "HFC-PCI: defined at mem %p fifo %p(%lx) IRQ %d HZ %d\n", cs->hw.hfcpci.pci_io, cs->hw.hfcpci.fifos, - (u_int) virt_to_bus(cs->hw.hfcpci.fifos), + (u_long)cs->hw.hfcpci.dma, cs->irq, HZ); spin_lock_irqsave(&cs->lock, flags); diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index f8527046f197..0685c1946969 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -703,7 +703,7 @@ struct hfcPCI_hw { int nt_timer; struct pci_dev *dev; unsigned char *pci_io; /* start of PCI IO memory */ - void *share_start; /* shared memory for Fifos start */ + dma_addr_t dma; /* dma handle for Fifos */ void *fifos; /* FIFO memory */ int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */ struct timer_list timer; diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 53f6ad1235db..4ffaa14b9fc4 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -67,7 +67,7 @@ hycapi_reset_ctr(struct capi_ctr *ctrl) printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n"); #endif capilib_release(&cinfo->ncci_head); - capi_ctr_reseted(ctrl); + capi_ctr_down(ctrl); } /****************************** @@ -347,7 +347,7 @@ int hycapi_capi_stop(hysdn_card *card) if(cinfo) { ctrl = &cinfo->capi_ctrl; /* ctrl->suspend_output(ctrl); */ - capi_ctr_reseted(ctrl); + capi_ctr_down(ctrl); } return 0; } diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 36778b270c30..ed3510f273d8 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -135,5 +135,3 @@ source "drivers/isdn/act2000/Kconfig" source "drivers/isdn/hysdn/Kconfig" endmenu - -source "drivers/isdn/gigaset/Kconfig" diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index cb8943da4f12..34d54e7281fd 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1069,7 +1069,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) lp = isdn_net_get_locked_lp(nd); if (!lp) { printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name); - return 1; + return NETDEV_TX_BUSY; } /* we have our lp locked from now on */ @@ -1273,14 +1273,14 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) spin_unlock_irqrestore(&dev->lock, flags); isdn_net_dial(); /* Initiate dialing */ netif_stop_queue(ndev); - return 1; /* let upper layer requeue skb packet */ + return NETDEV_TX_BUSY; /* let upper layer requeue skb packet */ } #endif /* Initiate dialing */ spin_unlock_irqrestore(&dev->lock, flags); isdn_net_dial(); isdn_net_device_stop_queue(lp); - return 1; + return NETDEV_TX_BUSY; } else { isdn_net_unreachable(ndev, skb, "No phone number"); diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 1a2222cbb805..b4d4522e5071 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1592,7 +1592,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) int retval, line; line = tty->index; - if (line < 0 || line > ISDN_MAX_CHANNELS) + if (line < 0 || line >= ISDN_MAX_CHANNELS) return -ENODEV; info = &dev->mdm.info[line]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c index 9426c9827e47..21d34be5af6a 100644 --- a/drivers/isdn/mISDN/core.c +++ b/drivers/isdn/mISDN/core.c @@ -214,7 +214,7 @@ get_free_devid(void) if (!test_and_set_bit(i, (u_long *)&device_ids)) break; if (i > MAX_DEVICE_ID) - return -1; + return -EBUSY; return i; } @@ -224,10 +224,10 @@ mISDN_register_device(struct mISDNdevice *dev, { int err; - dev->id = get_free_devid(); - err = -EBUSY; - if (dev->id < 0) + err = get_free_devid(); + if (err < 0) goto error1; + dev->id = err; device_initialize(&dev->dev); if (name && name[0]) diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h index 98a33c58f091..18af86879c05 100644 --- a/drivers/isdn/mISDN/dsp.h +++ b/drivers/isdn/mISDN/dsp.h @@ -112,9 +112,11 @@ struct dsp_conf { #define DSP_DTMF_NPOINTS 102 -#define ECHOCAN_BUFLEN (4*128) +#define ECHOCAN_BUFF_SIZE 0x400 /* must be 2**n */ +#define ECHOCAN_BUFF_MASK 0x3ff /* -1 */ struct dsp_dtmf { + int enable; /* dtmf is enabled */ int treshold; /* above this is dtmf (square of) */ int software; /* dtmf uses software decoding */ int hardware; /* dtmf uses hardware decoding */ @@ -123,7 +125,7 @@ struct dsp_dtmf { /* buffers one full dtmf frame */ u8 lastwhat, lastdigit; int count; - u8 digits[16]; /* just the dtmf result */ + u8 digits[16]; /* dtmf result */ }; @@ -150,6 +152,15 @@ struct dsp_tone { struct timer_list tl; }; +/*************** + * echo stuff * + ***************/ + +struct dsp_echo { + int software; /* echo is generated by software */ + int hardware; /* echo is generated by hardware */ +}; + /***************** * general stuff * *****************/ @@ -160,7 +171,7 @@ struct dsp { struct mISDNchannel *up; unsigned char name[64]; int b_active; - int echo; /* echo is enabled */ + struct dsp_echo echo; int rx_disabled; /* what the user wants */ int rx_is_off; /* what the card is */ int tx_mix; @@ -261,5 +272,5 @@ extern int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg); extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len); extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, - int len); + int len, unsigned int txlen); diff --git a/drivers/isdn/mISDN/dsp_audio.c b/drivers/isdn/mISDN/dsp_audio.c index de3795e3f432..9c7c6451bf3d 100644 --- a/drivers/isdn/mISDN/dsp_audio.c +++ b/drivers/isdn/mISDN/dsp_audio.c @@ -210,9 +210,8 @@ dsp_audio_generate_seven(void) j = 0; for (k = 0; k < 256; k++) { if (dsp_audio_alaw_to_s32[k] - < dsp_audio_alaw_to_s32[i]) { - j++; - } + < dsp_audio_alaw_to_s32[i]) + j++; } sorted_alaw[j] = i; } diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 58c43e429f73..9c7c0d1ba55f 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c @@ -163,8 +163,9 @@ dsp_cmx_debug(struct dsp *dsp) printk(KERN_DEBUG "-----Current DSP\n"); list_for_each_entry(odsp, &dsp_ilist, list) { - printk(KERN_DEBUG "* %s echo=%d txmix=%d", - odsp->name, odsp->echo, odsp->tx_mix); + printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d", + odsp->name, odsp->echo.hardware, odsp->echo.software, + odsp->tx_mix); if (odsp->conf) printk(" (Conf %d)", odsp->conf->id); if (dsp == odsp) @@ -177,10 +178,12 @@ dsp_cmx_debug(struct dsp *dsp) list_for_each_entry(member, &conf->mlist, list) { printk(KERN_DEBUG " - member = %s (slot_tx %d, bank_tx %d, " - "slot_rx %d, bank_rx %d hfc_conf %d)%s\n", + "slot_rx %d, bank_rx %d hfc_conf %d " + "tx_data %d rx_is_off %d)%s\n", member->dsp->name, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx, member->dsp->hfc_conf, + member->dsp->tx_data, member->dsp->rx_is_off, (member->dsp == dsp) ? " *this*" : ""); } } @@ -235,7 +238,7 @@ dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf) member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC); if (!member) { - printk(KERN_ERR "kmalloc struct dsp_conf_member failed\n"); + printk(KERN_ERR "kzalloc struct dsp_conf_member failed\n"); return -ENOMEM; } member->dsp = dsp; @@ -314,7 +317,7 @@ static struct dsp_conf conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC); if (!conf) { - printk(KERN_ERR "kmalloc struct dsp_conf failed\n"); + printk(KERN_ERR "kzalloc struct dsp_conf failed\n"); return NULL; } INIT_LIST_HEAD(&conf->mlist); @@ -385,7 +388,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) int freeunits[8]; u_char freeslots[256]; int same_hfc = -1, same_pcm = -1, current_conf = -1, - all_conf = 1; + all_conf = 1, tx_data = 0; /* dsp gets updated (no conf) */ if (!conf) { @@ -409,7 +412,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) /* process hw echo */ if (dsp->features.pcm_banks < 1) return; - if (!dsp->echo) { + if (!dsp->echo.software && !dsp->echo.hardware) { /* NO ECHO: remove PCM slot if assigned */ if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) { if (dsp_debug & DEBUG_DSP_CMX) @@ -427,10 +430,15 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) } return; } + /* echo is enabled, find out if we use soft or hardware */ + dsp->echo.software = dsp->tx_data; + dsp->echo.hardware = 0; /* ECHO: already echo */ if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 && - dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) + dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) { + dsp->echo.hardware = 1; return; + } /* ECHO: if slot already assigned */ if (dsp->pcm_slot_tx >= 0) { dsp->pcm_slot_rx = dsp->pcm_slot_tx; @@ -443,6 +451,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) dsp->pcm_slot_tx); dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN, dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2); + dsp->echo.hardware = 1; return; } /* ECHO: find slot */ @@ -472,6 +481,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) "%s no slot available for echo\n", __func__); /* no more slots available */ + dsp->echo.software = 1; return; } /* assign free slot */ @@ -485,6 +495,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) __func__, dsp->name, dsp->pcm_slot_tx); dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN, dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2); + dsp->echo.hardware = 1; return; } @@ -554,7 +565,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) return; } /* check if member has echo turned on */ - if (member->dsp->echo) { + if (member->dsp->echo.hardware || member->dsp->echo.software) { if (dsp_debug & DEBUG_DSP_CMX) printk(KERN_DEBUG "%s dsp %s cannot form a conf, because " @@ -592,10 +603,9 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) if (member->dsp->tx_data) { if (dsp_debug & DEBUG_DSP_CMX) printk(KERN_DEBUG - "%s dsp %s cannot form a conf, because " - "tx_data is turned on\n", + "%s dsp %s tx_data is turned on\n", __func__, member->dsp->name); - goto conf_software; + tx_data = 1; } /* check if pipeline exists */ if (member->dsp->pipeline.inuse) { @@ -794,7 +804,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx); conf->hardware = 1; - conf->software = 0; + conf->software = tx_data; return; /* if members have one bank (or on the same chip) */ } else { @@ -904,7 +914,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx); conf->hardware = 1; - conf->software = 0; + conf->software = tx_data; return; } } @@ -937,6 +947,10 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) if (current_conf >= 0) { join_members: list_for_each_entry(member, &conf->mlist, list) { + /* if no conference engine on our chip, change to + * software */ + if (!member->dsp->features.hfc_conf) + goto conf_software; /* in case of hdlc, change to software */ if (member->dsp->hdlc) goto conf_software; @@ -1295,17 +1309,25 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) int r, rr, t, tt, o_r, o_rr; int preload = 0; struct mISDNhead *hh, *thh; + int tx_data_only = 0; /* don't process if: */ if (!dsp->b_active) { /* if not active */ dsp->last_tx = 0; return; } - if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */ + if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */ + dsp->echo.hardware) && /* OR hardware echo */ dsp->tx_R == dsp->tx_W && /* AND no tx-data */ !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */ - dsp->last_tx = 0; - return; + if (!dsp->tx_data) { /* no tx_data for user space required */ + dsp->last_tx = 0; + return; + } + if (dsp->conf && dsp->conf->software && dsp->conf->hardware) + tx_data_only = 1; + if (dsp->conf->software && dsp->echo.hardware) + tx_data_only = 1; } #ifdef CMX_DEBUG @@ -1367,7 +1389,8 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) while (r != rr && t != tt) { #ifdef CMX_TX_DEBUG if (strlen(debugbuf) < 48) - sprintf(debugbuf+strlen(debugbuf), " %02x", p[t]); + sprintf(debugbuf+strlen(debugbuf), " %02x", + p[t]); #endif *d++ = p[t]; /* write tx_buff */ t = (t+1) & CMX_BUFF_MASK; @@ -1388,7 +1411,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) /* PROCESS DATA (one member / no conf) */ if (!conf || members <= 1) { /* -> if echo is NOT enabled */ - if (!dsp->echo) { + if (!dsp->echo.software) { /* -> send tx-data if available or use 0-volume */ while (r != rr && t != tt) { *d++ = p[t]; /* write tx_buff */ @@ -1438,7 +1461,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) o_r = (o_rr - rr + r) & CMX_BUFF_MASK; /* start rx-pointer at current read position*/ /* -> if echo is NOT enabled */ - if (!dsp->echo) { + if (!dsp->echo.software) { /* * -> copy other member's rx-data, * if tx-data is available, mix @@ -1486,7 +1509,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) #endif /* PROCESS DATA (three or more members) */ /* -> if echo is NOT enabled */ - if (!dsp->echo) { + if (!dsp->echo.software) { /* * -> substract rx-data from conf-data, * if tx-data is available, mix @@ -1550,27 +1573,40 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) * becuase we want what we send, not what we filtered */ if (dsp->tx_data) { - /* PREPARE RESULT */ - txskb = mI_alloc_skb(len, GFP_ATOMIC); - if (!txskb) { - printk(KERN_ERR - "FATAL ERROR in mISDN_dsp.o: " - "cannot alloc %d bytes\n", len); + if (tx_data_only) { + hh->prim = DL_DATA_REQ; + hh->id = 0; + /* queue and trigger */ + skb_queue_tail(&dsp->sendq, nskb); + schedule_work(&dsp->workq); + /* exit because only tx_data is used */ + return; } else { - thh = mISDN_HEAD_P(txskb); - thh->prim = DL_DATA_REQ; - thh->id = 0; - memcpy(skb_put(txskb, len), nskb->data+preload, len); - /* queue (trigger later) */ - skb_queue_tail(&dsp->sendq, txskb); + txskb = mI_alloc_skb(len, GFP_ATOMIC); + if (!txskb) { + printk(KERN_ERR + "FATAL ERROR in mISDN_dsp.o: " + "cannot alloc %d bytes\n", len); + } else { + thh = mISDN_HEAD_P(txskb); + thh->prim = DL_DATA_REQ; + thh->id = 0; + memcpy(skb_put(txskb, len), nskb->data+preload, + len); + /* queue (trigger later) */ + skb_queue_tail(&dsp->sendq, txskb); + } } } + + /* send data only to card, if we don't just calculated tx_data */ /* adjust volume */ if (dsp->tx_volume) dsp_change_volume(nskb, dsp->tx_volume); /* pipeline */ if (dsp->pipeline.inuse) - dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len); + dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, + nskb->len); /* crypt */ if (dsp->bf_enable) dsp_bf_encrypt(dsp, nskb->data, nskb->len); @@ -1592,7 +1628,8 @@ dsp_cmx_send(void *arg) struct dsp_conf_member *member; struct dsp *dsp; int mustmix, members; - s32 mixbuffer[MAX_POLL+100], *c; + static s32 mixbuffer[MAX_POLL+100]; + s32 *c; u8 *p, *q; int r, rr; int jittercheck = 0, delay, i; @@ -1890,10 +1927,8 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb) /* no conf */ if (!dsp->conf) { - /* in case of hardware (echo) */ - if (dsp->pcm_slot_tx >= 0) - return; - if (dsp->echo) { + /* in case of software echo */ + if (dsp->echo.software) { nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { hh = mISDN_HEAD_P(nskb); @@ -1909,7 +1944,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb) if (dsp->conf->hardware) return; list_for_each_entry(member, &dsp->conf->mlist, list) { - if (dsp->echo || member->dsp != dsp) { + if (dsp->echo.software || member->dsp != dsp) { nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { hh = mISDN_HEAD_P(nskb); diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 47dbfe298b43..77ee2867c8b4 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -203,13 +203,13 @@ dsp_rx_off_member(struct dsp *dsp) else if (dsp->dtmf.software) rx_off = 0; /* echo in software */ - else if (dsp->echo && dsp->pcm_slot_tx < 0) + else if (dsp->echo.software) rx_off = 0; /* bridge in software */ - else if (dsp->conf) { - if (dsp->conf->software) - rx_off = 0; - } + else if (dsp->conf && dsp->conf->software) + rx_off = 0; + /* data is not required by user space and not required + * for echo dtmf detection, soft-echo, soft-bridging */ if (rx_off == dsp->rx_is_off) return; @@ -280,7 +280,7 @@ dsp_fill_empty(struct dsp *dsp) static int dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) { - struct sk_buff *nskb; + struct sk_buff *nskb; int ret = 0; int cont; u8 *data; @@ -306,15 +306,18 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) "to %d\n", *((int *)data)); dsp->dtmf.treshold = (*(int *)data) * 10000; } + dsp->dtmf.enable = 1; /* init goertzel */ dsp_dtmf_goertzel_init(dsp); /* check dtmf hardware */ dsp_dtmf_hardware(dsp); + dsp_rx_off(dsp); break; case DTMF_TONE_STOP: /* turn off DTMF */ if (dsp_debug & DEBUG_DSP_CORE) printk(KERN_DEBUG "%s: stop dtmf\n", __func__); + dsp->dtmf.enable = 0; dsp->dtmf.hardware = 0; dsp->dtmf.software = 0; break; @@ -414,7 +417,7 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) dsp_rx_off(dsp); break; case DSP_ECHO_ON: /* enable echo */ - dsp->echo = 1; /* soft echo */ + dsp->echo.software = 1; /* soft echo */ if (dsp_debug & DEBUG_DSP_CORE) printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__); dsp_cmx_hardware(dsp->conf, dsp); @@ -423,7 +426,8 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) dsp_cmx_debug(dsp); break; case DSP_ECHO_OFF: /* disable echo */ - dsp->echo = 0; + dsp->echo.software = 0; + dsp->echo.hardware = 0; if (dsp_debug & DEBUG_DSP_CORE) printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__); dsp_cmx_hardware(dsp->conf, dsp); @@ -556,7 +560,7 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) dsp->pipeline.inuse = 1; dsp_cmx_hardware(dsp->conf, dsp); ret = dsp_pipeline_build(&dsp->pipeline, - len > 0 ? (char *)data : NULL); + len > 0 ? data : NULL); dsp_cmx_hardware(dsp->conf, dsp); dsp_rx_off(dsp); } @@ -657,11 +661,10 @@ get_features(struct mISDNchannel *ch) static int dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) { - struct dsp *dsp = container_of(ch, struct dsp, ch); + struct dsp *dsp = container_of(ch, struct dsp, ch); struct mISDNhead *hh; int ret = 0; - u8 *digits; - int cont; + u8 *digits = NULL; u_long flags; hh = mISDN_HEAD_P(skb); @@ -704,50 +707,55 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) break; } + spin_lock_irqsave(&dsp_lock, flags); + /* decrypt if enabled */ if (dsp->bf_enable) dsp_bf_decrypt(dsp, skb->data, skb->len); /* pipeline */ if (dsp->pipeline.inuse) dsp_pipeline_process_rx(&dsp->pipeline, skb->data, - skb->len); + skb->len, hh->id); /* change volume if requested */ if (dsp->rx_volume) dsp_change_volume(skb, dsp->rx_volume); - /* check if dtmf soft decoding is turned on */ if (dsp->dtmf.software) { digits = dsp_dtmf_goertzel_decode(dsp, skb->data, - skb->len, (dsp_options&DSP_OPT_ULAW)?1:0); + skb->len, (dsp_options&DSP_OPT_ULAW) ? 1 : 0); + } + /* we need to process receive data if software */ + if (dsp->conf && dsp->conf->software) { + /* process data from card at cmx */ + dsp_cmx_receive(dsp, skb); + } + + spin_unlock_irqrestore(&dsp_lock, flags); + + /* send dtmf result, if any */ + if (digits) { while (*digits) { + int k; struct sk_buff *nskb; if (dsp_debug & DEBUG_DSP_DTMF) printk(KERN_DEBUG "%s: digit" "(%c) to layer %s\n", __func__, *digits, dsp->name); - cont = DTMF_TONE_VAL | *digits; + k = *digits | DTMF_TONE_VAL; nskb = _alloc_mISDN_skb(PH_CONTROL_IND, - MISDN_ID_ANY, sizeof(int), &cont, - GFP_ATOMIC); + MISDN_ID_ANY, sizeof(int), &k, + GFP_ATOMIC); if (nskb) { if (dsp->up) { if (dsp->up->send( dsp->up, nskb)) - dev_kfree_skb(nskb); + dev_kfree_skb(nskb); } else dev_kfree_skb(nskb); } digits++; } } - /* we need to process receive data if software */ - spin_lock_irqsave(&dsp_lock, flags); - if (dsp->pcm_slot_tx < 0 && dsp->pcm_slot_rx < 0) { - /* process data from card at cmx */ - dsp_cmx_receive(dsp, skb); - } - spin_unlock_irqrestore(&dsp_lock, flags); - if (dsp->rx_disabled) { /* if receive is not allowed */ break; @@ -787,7 +795,7 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) if (dsp->up) { if (dsp->up->send( dsp->up, nskb)) - dev_kfree_skb(nskb); + dev_kfree_skb(nskb); } else dev_kfree_skb(nskb); } @@ -946,7 +954,7 @@ dsp_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) int err = 0; if (debug & DEBUG_DSP_CTRL) - printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd); + printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd); switch (cmd) { case OPEN_CHANNEL: @@ -1169,9 +1177,9 @@ static int dsp_init(void) /* init conversion tables */ dsp_audio_generate_law_tables(); - dsp_silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a; - dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW)?dsp_audio_ulaw_to_s32: - dsp_audio_alaw_to_s32; + dsp_silence = (dsp_options&DSP_OPT_ULAW) ? 0xff : 0x2a; + dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW) ? + dsp_audio_ulaw_to_s32 : dsp_audio_alaw_to_s32; dsp_audio_generate_s2law_table(); dsp_audio_generate_seven(); dsp_audio_generate_mix_table(); diff --git a/drivers/isdn/mISDN/dsp_dtmf.c b/drivers/isdn/mISDN/dsp_dtmf.c index efc371c1f0dc..9ae2d33b06f7 100644 --- a/drivers/isdn/mISDN/dsp_dtmf.c +++ b/drivers/isdn/mISDN/dsp_dtmf.c @@ -51,6 +51,9 @@ void dsp_dtmf_hardware(struct dsp *dsp) { int hardware = 1; + if (!dsp->dtmf.enable) + return; + if (!dsp->features.hfc_dtmf) hardware = 0; diff --git a/drivers/isdn/mISDN/dsp_ecdis.h b/drivers/isdn/mISDN/dsp_ecdis.h index 8a20af43308b..21dbd153ee26 100644 --- a/drivers/isdn/mISDN/dsp_ecdis.h +++ b/drivers/isdn/mISDN/dsp_ecdis.h @@ -91,7 +91,7 @@ int16_t amp) && det->tone_cycle_duration <= 475*8) { det->good_cycles++; if (det->good_cycles > 2) - det->hit = TRUE; + det->hit = TRUE; } det->tone_cycle_duration = 0; } diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c index 18cf87c113e7..e9941678edfa 100644 --- a/drivers/isdn/mISDN/dsp_pipeline.c +++ b/drivers/isdn/mISDN/dsp_pipeline.c @@ -55,20 +55,19 @@ static ssize_t attr_show_args(struct device *dev, struct device_attribute *attr, char *buf) { struct mISDN_dsp_element *elem = dev_get_drvdata(dev); - ssize_t len = 0; - int i = 0; + int i; + char *p = buf; *buf = 0; - for (; i < elem->num_args; ++i) - len = sprintf(buf, "%sName: %s\n%s%s%sDescription: %s\n" - "\n", buf, + for (i = 0; i < elem->num_args; i++) + p += sprintf(p, "Name: %s\n%s%s%sDescription: %s\n\n", elem->args[i].name, elem->args[i].def ? "Default: " : "", elem->args[i].def ? elem->args[i].def : "", elem->args[i].def ? "\n" : "", elem->args[i].desc); - return len; + return p - buf; } static struct device_attribute element_attributes[] = { @@ -347,7 +346,8 @@ void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len) entry->elem->process_tx(entry->p, data, len); } -void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len) +void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len, + unsigned int txlen) { struct dsp_pipeline_entry *entry; @@ -356,7 +356,7 @@ void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len) list_for_each_entry_reverse(entry, &pipeline->list, list) if (entry->elem->process_rx) - entry->elem->process_rx(entry->p, data, len); + entry->elem->process_rx(entry->p, data, len, txlen); } diff --git a/drivers/isdn/mISDN/dsp_tones.c b/drivers/isdn/mISDN/dsp_tones.c index 7a9af66f4b19..1debf53670de 100644 --- a/drivers/isdn/mISDN/dsp_tones.c +++ b/drivers/isdn/mISDN/dsp_tones.c @@ -253,18 +253,24 @@ static struct pattern { {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_DIALPBX, - {DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, + NULL}, + {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, + NULL}, {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, {TONE_GERMAN_OLDDIALPBX, - {DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, + NULL}, + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, + NULL}, {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, {TONE_AMERICAN_DIALPBX, - {DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL, NULL}, - {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL, NULL}, + {DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL, + NULL}, + {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL, + NULL}, {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, {TONE_GERMAN_RINGING, @@ -434,7 +440,7 @@ dsp_tone_hw_message(struct dsp *dsp, u8 *sample, int len) /* unlocking is not required, because we don't expect a response */ nskb = _alloc_mISDN_skb(PH_CONTROL_REQ, - (len)?HFC_SPL_LOOP_ON:HFC_SPL_LOOP_OFF, len, sample, + (len) ? HFC_SPL_LOOP_ON : HFC_SPL_LOOP_OFF, len, sample, GFP_ATOMIC); if (nskb) { if (dsp->ch.peer) { @@ -498,8 +504,7 @@ dsp_tone(struct dsp *dsp, int tone) /* we turn off the tone */ if (!tone) { - if (dsp->features.hfc_loops) - if (timer_pending(&tonet->tl)) + if (dsp->features.hfc_loops && timer_pending(&tonet->tl)) del_timer(&tonet->tl); if (dsp->features.hfc_loops) dsp_tone_hw_message(dsp, NULL, 0); diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index ab1168a110ae..0481a0cdf6db 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -185,13 +185,13 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch) EXPORT_SYMBOL(recv_Echannel); void -recv_Bchannel(struct bchannel *bch) +recv_Bchannel(struct bchannel *bch, unsigned int id) { struct mISDNhead *hh; hh = mISDN_HEAD_P(bch->rx_skb); hh->prim = PH_DATA_IND; - hh->id = MISDN_ID_ANY; + hh->id = id; if (bch->rcount >= 64) { printk(KERN_WARNING "B-channel %p receive queue overflow, " "fushing!\n", bch); diff --git a/drivers/isdn/mISDN/l1oip.h b/drivers/isdn/mISDN/l1oip.h index a23d575449f6..bc26c890d9a2 100644 --- a/drivers/isdn/mISDN/l1oip.h +++ b/drivers/isdn/mISDN/l1oip.h @@ -76,7 +76,7 @@ struct l1oip { struct sockaddr_in sin_local; /* local socket name */ struct sockaddr_in sin_remote; /* remote socket name */ struct msghdr sendmsg; /* ip message to send */ - struct iovec sendiov; /* iov for message */ + struct kvec sendiov; /* iov for message */ /* frame */ struct l1oip_chan chan[128]; /* channel instances */ diff --git a/drivers/isdn/mISDN/l1oip_codec.c b/drivers/isdn/mISDN/l1oip_codec.c index e4ecba3d48df..bbfd1b863ed3 100644 --- a/drivers/isdn/mISDN/l1oip_codec.c +++ b/drivers/isdn/mISDN/l1oip_codec.c @@ -48,6 +48,7 @@ NOTE: The bytes are handled as they are law-encoded. #include #include +#include #include "core.h" #include "l1oip.h" diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index abe574989572..990e6a7e6674 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -279,7 +279,6 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, int multi = 0; u8 frame[len+32]; struct socket *socket = NULL; - mm_segment_t oldfs; if (debug & DEBUG_L1OIP_MSG) printk(KERN_DEBUG "%s: sending data to socket (len = %d)\n", @@ -308,8 +307,8 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, /* assemble frame */ *p++ = (L1OIP_VERSION<<6) /* version and coding */ - | (hc->pri?0x20:0x00) /* type */ - | (hc->id?0x10:0x00) /* id */ + | (hc->pri ? 0x20 : 0x00) /* type */ + | (hc->id ? 0x10 : 0x00) /* id */ | localcodec; if (hc->id) { *p++ = hc->id>>24; /* id */ @@ -317,7 +316,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, *p++ = hc->id>>8; *p++ = hc->id; } - *p++ = (multi == 1)?0x80:0x00 + channel; /* m-flag, channel */ + *p++ = (multi == 1) ? 0x80 : 0x00 + channel; /* m-flag, channel */ if (multi == 1) *p++ = len; /* length */ *p++ = timebase>>8; /* time base */ @@ -352,10 +351,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, "= %d)\n", __func__, len); hc->sendiov.iov_base = frame; hc->sendiov.iov_len = len; - oldfs = get_fs(); - set_fs(KERNEL_DS); - len = sock_sendmsg(socket, &hc->sendmsg, len); - set_fs(oldfs); + len = kernel_sendmsg(socket, &hc->sendmsg, &hc->sendiov, 1, len); /* give socket back */ hc->socket = socket; /* no locking required */ @@ -401,12 +397,12 @@ l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase, } /* prepare message */ - nskb = mI_alloc_skb((remotecodec == 3)?(len<<1):len, GFP_ATOMIC); + nskb = mI_alloc_skb((remotecodec == 3) ? (len<<1) : len, GFP_ATOMIC); if (!nskb) { printk(KERN_ERR "%s: No mem for skb.\n", __func__); return; } - p = skb_put(nskb, (remotecodec == 3)?(len<<1):len); + p = skb_put(nskb, (remotecodec == 3) ? (len<<1) : len); if (remotecodec == 1 && ulaw) l1oip_alaw_to_ulaw(buf, len, p); @@ -458,7 +454,7 @@ l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase, hc->chan[channel].disorder_flag ^= 1; if (nskb) #endif - queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb); + queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb); } } @@ -660,21 +656,29 @@ l1oip_socket_thread(void *data) struct l1oip *hc = (struct l1oip *)data; int ret = 0; struct msghdr msg; - struct iovec iov; - mm_segment_t oldfs; struct sockaddr_in sin_rx; - unsigned char recvbuf[1500]; + unsigned char *recvbuf; + size_t recvbuf_size = 1500; int recvlen; struct socket *socket = NULL; DECLARE_COMPLETION(wait); + /* allocate buffer memory */ + recvbuf = kmalloc(recvbuf_size, GFP_KERNEL); + if (!recvbuf) { + printk(KERN_ERR "%s: Failed to alloc recvbuf.\n", __func__); + ret = -ENOMEM; + goto fail; + } + /* make daemon */ allow_signal(SIGTERM); /* create socket */ if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &socket)) { printk(KERN_ERR "%s: Failed to create socket.\n", __func__); - return -EIO; + ret = -EIO; + goto fail; } /* set incoming address */ @@ -708,16 +712,12 @@ l1oip_socket_thread(void *data) msg.msg_namelen = sizeof(sin_rx); msg.msg_control = NULL; msg.msg_controllen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; /* build send message */ hc->sendmsg.msg_name = &hc->sin_remote; hc->sendmsg.msg_namelen = sizeof(hc->sin_remote); hc->sendmsg.msg_control = NULL; hc->sendmsg.msg_controllen = 0; - hc->sendmsg.msg_iov = &hc->sendiov; - hc->sendmsg.msg_iovlen = 1; /* give away socket */ spin_lock(&hc->socket_lock); @@ -729,18 +729,18 @@ l1oip_socket_thread(void *data) printk(KERN_DEBUG "%s: socket created and open\n", __func__); while (!signal_pending(current)) { - iov.iov_base = recvbuf; - iov.iov_len = sizeof(recvbuf); - oldfs = get_fs(); - set_fs(KERNEL_DS); - recvlen = sock_recvmsg(socket, &msg, sizeof(recvbuf), 0); - set_fs(oldfs); + struct kvec iov = { + .iov_base = recvbuf, + .iov_len = sizeof(recvbuf), + }; + recvlen = kernel_recvmsg(socket, &msg, &iov, 1, + sizeof(recvbuf), 0); if (recvlen > 0) { l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen); } else { if (debug & DEBUG_L1OIP_SOCKET) - printk(KERN_WARNING "%s: broken pipe on socket\n", - __func__); + printk(KERN_WARNING + "%s: broken pipe on socket\n", __func__); } } @@ -760,6 +760,9 @@ l1oip_socket_thread(void *data) __func__); fail: + /* free recvbuf */ + kfree(recvbuf); + /* close socket */ if (socket) sock_release(socket); @@ -912,7 +915,7 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) p = skb->data; l = skb->len; while (l) { - ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME; + ll = (l < L1OIP_MAX_PERFRAME) ? l : L1OIP_MAX_PERFRAME; l1oip_socket_send(hc, 0, dch->slot, 0, hc->chan[dch->slot].tx_counter++, p, ll); p += ll; @@ -1160,7 +1163,7 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb) p = skb->data; l = skb->len; while (l) { - ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME; + ll = (l < L1OIP_MAX_PERFRAME) ? l : L1OIP_MAX_PERFRAME; l1oip_socket_send(hc, hc->codec, bch->slot, 0, hc->chan[bch->slot].tx_counter, p, ll); hc->chan[bch->slot].tx_counter += ll; @@ -1318,8 +1321,8 @@ init_card(struct l1oip *hc, int pri, int bundle) spin_lock_init(&hc->socket_lock); hc->idx = l1oip_cnt; hc->pri = pri; - hc->d_idx = pri?16:3; - hc->b_num = pri?30:2; + hc->d_idx = pri ? 16 : 3; + hc->b_num = pri ? 30 : 2; hc->bundle = bundle; if (hc->pri) sprintf(hc->name, "l1oip-e1.%d", l1oip_cnt + 1); @@ -1504,9 +1507,9 @@ l1oip_init(void) if (debug & DEBUG_L1OIP_INIT) printk(KERN_DEBUG "%s: interface %d is %s with %s.\n", - __func__, l1oip_cnt, pri?"PRI":"BRI", - bundle?"bundled IP packet for all B-channels" - :"seperate IP packets for every B-channel"); + __func__, l1oip_cnt, pri ? "PRI" : "BRI", + bundle ? "bundled IP packet for all B-channels" : + "seperate IP packets for every B-channel"); hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); if (!hc) { diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index d6e2863f224a..9c2589e986d6 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -99,7 +99,7 @@ l2m_debug(struct FsmInst *fi, char *fmt, ...) if (!(*debug & DEBUG_L2_FSM)) return; va_start(va, fmt); - printk(KERN_DEBUG "l2 (tei %d): ", l2->tei); + printk(KERN_DEBUG "l2 (sapi %d tei %d): ", l2->sapi, l2->tei); vprintk(fmt, va); printk("\n"); va_end(va); @@ -1859,20 +1859,18 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) psapi >>= 2; ptei >>= 1; if (psapi != l2->sapi) { - /* not our bussiness - * printk(KERN_DEBUG "%s: sapi %d/%d sapi mismatch\n", - * __func__, - * psapi, l2->sapi); - */ + /* not our bussiness */ + if (*debug & DEBUG_L2) + printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n", + __func__, psapi, l2->sapi); dev_kfree_skb(skb); return 0; } if ((ptei != l2->tei) && (ptei != GROUP_TEI)) { - /* not our bussiness - * printk(KERN_DEBUG "%s: tei %d/%d sapi %d mismatch\n", - * __func__, - * ptei, l2->tei, psapi); - */ + /* not our bussiness */ + if (*debug & DEBUG_L2) + printk(KERN_DEBUG "%s: tei %d/%d mismatch\n", + __func__, ptei, l2->tei); dev_kfree_skb(skb); return 0; } @@ -1927,8 +1925,8 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb) int ret = -EINVAL; if (*debug & DEBUG_L2_RECV) - printk(KERN_DEBUG "%s: prim(%x) id(%x) tei(%d)\n", - __func__, hh->prim, hh->id, l2->tei); + printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n", + __func__, hh->prim, hh->id, l2->sapi, l2->tei); switch (hh->prim) { case PH_DATA_IND: ret = ph_data_indication(l2, hh, skb); @@ -2068,7 +2066,8 @@ l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) } struct layer2 * -create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg) +create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei, + int sapi) { struct layer2 *l2; struct channel_req rq; @@ -2089,7 +2088,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg) test_and_set_bit(FLG_LAPD, &l2->flag); test_and_set_bit(FLG_LAPD_NET, &l2->flag); test_and_set_bit(FLG_MOD128, &l2->flag); - l2->sapi = 0; + l2->sapi = sapi; l2->maxlen = MAX_DFRAME_LEN; if (test_bit(OPTION_L2_PMX, &options)) l2->window = 7; @@ -2099,7 +2098,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg) test_and_set_bit(FLG_PTP, &l2->flag); if (test_bit(OPTION_L2_FIXEDTEI, &options)) test_and_set_bit(FLG_FIXED_TEI, &l2->flag); - l2->tei = (u_int)arg; + l2->tei = tei; l2->T200 = 1000; l2->N200 = 3; l2->T203 = 10000; @@ -2114,7 +2113,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg) test_and_set_bit(FLG_LAPD, &l2->flag); test_and_set_bit(FLG_MOD128, &l2->flag); test_and_set_bit(FLG_ORIG, &l2->flag); - l2->sapi = 0; + l2->sapi = sapi; l2->maxlen = MAX_DFRAME_LEN; if (test_bit(OPTION_L2_PMX, &options)) l2->window = 7; @@ -2124,7 +2123,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg) test_and_set_bit(FLG_PTP, &l2->flag); if (test_bit(OPTION_L2_FIXEDTEI, &options)) test_and_set_bit(FLG_FIXED_TEI, &l2->flag); - l2->tei = (u_int)arg; + l2->tei = tei; l2->T200 = 1000; l2->N200 = 3; l2->T203 = 10000; @@ -2180,7 +2179,7 @@ x75create(struct channel_req *crq) if (crq->protocol != ISDN_P_B_X75SLP) return -EPROTONOSUPPORT; - l2 = create_l2(crq->ch, crq->protocol, 0, 0); + l2 = create_l2(crq->ch, crq->protocol, 0, 0, 0); if (!l2) return -ENOMEM; crq->ch = &l2->ch; diff --git a/drivers/isdn/mISDN/layer2.h b/drivers/isdn/mISDN/layer2.h index 6293f80dc2d3..9547fb3707a3 100644 --- a/drivers/isdn/mISDN/layer2.h +++ b/drivers/isdn/mISDN/layer2.h @@ -90,7 +90,7 @@ enum { #define L2_STATE_COUNT (ST_L2_8+1) extern struct layer2 *create_l2(struct mISDNchannel *, u_int, - u_long, u_long); + u_long, int, int); extern int tei_l2(struct layer2 *, u_int, u_long arg); diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 508945d1b9c1..c36f52137456 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -209,7 +209,7 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock, if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { err = -EFAULT; - goto drop; + goto done; } memcpy(mISDN_HEAD_P(skb), skb->data, MISDN_HEADER_LEN); @@ -222,7 +222,7 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock, } else { /* use default for L2 messages */ if ((sk->sk_protocol == ISDN_P_LAPD_TE) || (sk->sk_protocol == ISDN_P_LAPD_NT)) - mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr; + mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr; } if (*debug & DEBUG_SOCKET) @@ -230,19 +230,21 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock, __func__, mISDN_HEAD_ID(skb)); err = -ENODEV; - if (!_pms(sk)->ch.peer || - (err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb))) - goto drop; - - err = len; + if (!_pms(sk)->ch.peer) + goto done; + err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb); + if (err) + goto done; + else { + skb = NULL; + err = len; + } done: + if (skb) + kfree_skb(skb); release_sock(sk); return err; - -drop: - kfree_skb(skb); - goto done; } static int @@ -292,7 +294,7 @@ static int data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) { struct mISDN_ctrl_req cq; - int err = -EINVAL, val; + int err = -EINVAL, val[2]; struct mISDNchannel *bchan, *next; lock_sock(sk); @@ -328,12 +330,27 @@ data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) err = -EINVAL; break; } - if (get_user(val, (int __user *)p)) { + val[0] = cmd; + if (get_user(val[1], (int __user *)p)) { err = -EFAULT; break; } err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, - CONTROL_CHANNEL, &val); + CONTROL_CHANNEL, val); + break; + case IMHOLD_L1: + if (sk->sk_protocol != ISDN_P_LAPD_NT + && sk->sk_protocol != ISDN_P_LAPD_TE) { + err = -EINVAL; + break; + } + val[0] = cmd; + if (get_user(val[1], (int __user *)p)) { + err = -EFAULT; + break; + } + err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, + CONTROL_CHANNEL, val); break; default: err = -EINVAL; diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index b452dead8fd0..e04bad6c5baf 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -122,8 +122,11 @@ da_deactivate(struct FsmInst *fi, int event, void *arg) } read_unlock_irqrestore(&mgr->lock, flags); /* All TEI are inactiv */ - mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 1); - mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING); + if (!test_bit(OPTION_L1_HOLD, &mgr->options)) { + mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, + NULL, 1); + mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING); + } } static void @@ -132,9 +135,11 @@ da_ui(struct FsmInst *fi, int event, void *arg) struct manager *mgr = fi->userdata; /* restart da timer */ - mISDN_FsmDelTimer(&mgr->datimer, 2); - mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 2); - + if (!test_bit(OPTION_L1_HOLD, &mgr->options)) { + mISDN_FsmDelTimer(&mgr->datimer, 2); + mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, + NULL, 2); + } } static void @@ -222,7 +227,7 @@ tei_debug(struct FsmInst *fi, char *fmt, ...) if (!(*debug & DEBUG_L2_TEIFSM)) return; va_start(va, fmt); - printk(KERN_DEBUG "tei(%d): ", tm->l2->tei); + printk(KERN_DEBUG "sapi(%d) tei(%d): ", tm->l2->sapi, tm->l2->tei); vprintk(fmt, va); printk("\n"); va_end(va); @@ -421,7 +426,7 @@ findtei(struct manager *mgr, int tei) } static void -put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei) +put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, int tei) { struct sk_buff *skb; u_char bp[8]; @@ -435,9 +440,8 @@ put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei) bp[4] = ri >> 8; bp[5] = ri & 0xff; bp[6] = m_id; - bp[7] = (tei << 1) | 1; - skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), - 8, bp, GFP_ATOMIC); + bp[7] = ((tei << 1) & 0xff) | 1; + skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), 8, bp, GFP_ATOMIC); if (!skb) { printk(KERN_WARNING "%s: no skb for tei msg\n", __func__); return; @@ -772,7 +776,7 @@ tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len) } static struct layer2 * -create_new_tei(struct manager *mgr, int tei) +create_new_tei(struct manager *mgr, int tei, int sapi) { u_long opt = 0; u_long flags; @@ -781,12 +785,12 @@ create_new_tei(struct manager *mgr, int tei) if (!mgr->up) return NULL; - if (tei < 64) + if ((tei >= 0) && (tei < 64)) test_and_set_bit(OPTION_L2_FIXEDTEI, &opt); if (mgr->ch.st->dev->Dprotocols & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1))) test_and_set_bit(OPTION_L2_PMX, &opt); - l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei); + l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi); if (!l2) { printk(KERN_WARNING "%s:no memory for layer2\n", __func__); return NULL; @@ -834,12 +838,17 @@ new_tei_req(struct manager *mgr, u_char *dp) ri += dp[1]; if (!mgr->up) goto denied; - tei = get_free_tei(mgr); + if (!(dp[3] & 1)) /* Extension bit != 1 */ + goto denied; + if (dp[3] != 0xff) + tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */ + else + tei = get_free_tei(mgr); if (tei < 0) { printk(KERN_WARNING "%s:No free tei\n", __func__); goto denied; } - l2 = create_new_tei(mgr, tei); + l2 = create_new_tei(mgr, tei, CTRL_SAPI); if (!l2) goto denied; else @@ -853,8 +862,7 @@ static int ph_data_ind(struct manager *mgr, struct sk_buff *skb) { int ret = -EINVAL; - struct layer2 *l2; - u_long flags; + struct layer2 *l2, *nl2; u_char mt; if (skb->len < 8) { @@ -863,7 +871,6 @@ ph_data_ind(struct manager *mgr, struct sk_buff *skb) __func__, skb->len); goto done; } - if (*debug & DEBUG_L2_TEI) if ((skb->data[0] >> 2) != TEI_SAPI) /* not for us */ goto done; @@ -900,11 +907,9 @@ ph_data_ind(struct manager *mgr, struct sk_buff *skb) new_tei_req(mgr, &skb->data[4]); goto done; } - read_lock_irqsave(&mgr->lock, flags); - list_for_each_entry(l2, &mgr->layer2, list) { + list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) { tei_ph_data_ind(l2->tm, mt, &skb->data[4], skb->len - 4); } - read_unlock_irqrestore(&mgr->lock, flags); done: return ret; } @@ -971,8 +976,6 @@ create_teimgr(struct manager *mgr, struct channel_req *crq) __func__, dev_name(&mgr->ch.st->dev->dev), crq->protocol, crq->adr.dev, crq->adr.channel, crq->adr.sapi, crq->adr.tei); - if (crq->adr.sapi != 0) /* not supported yet */ - return -EINVAL; if (crq->adr.tei > GROUP_TEI) return -EINVAL; if (crq->adr.tei < 64) @@ -1019,8 +1022,8 @@ create_teimgr(struct manager *mgr, struct channel_req *crq) } return 0; } - l2 = create_l2(crq->ch, crq->protocol, (u_int)opt, - (u_long)crq->adr.tei); + l2 = create_l2(crq->ch, crq->protocol, opt, + crq->adr.tei, crq->adr.sapi); if (!l2) return -ENOMEM; l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL); @@ -1103,6 +1106,7 @@ free_teimanager(struct manager *mgr) { struct layer2 *l2, *nl2; + test_and_clear_bit(OPTION_L1_HOLD, &mgr->options); if (test_bit(MGR_OPT_NETWORK, &mgr->options)) { /* not locked lock is taken in release tei */ mgr->up = NULL; @@ -1133,13 +1137,26 @@ static int ctrl_teimanager(struct manager *mgr, void *arg) { /* currently we only have one option */ - int clean = *((int *)arg); + int *val = (int *)arg; + int ret = 0; - if (clean) - test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options); - else - test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options); - return 0; + switch (val[0]) { + case IMCLEAR_L2: + if (val[1]) + test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options); + else + test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options); + break; + case IMHOLD_L1: + if (val[1]) + test_and_set_bit(OPTION_L1_HOLD, &mgr->options); + else + test_and_clear_bit(OPTION_L1_HOLD, &mgr->options); + break; + default: + ret = -EINVAL; + } + return ret; } /* This function does create a L2 for fixed TEI in NT Mode */ @@ -1147,7 +1164,7 @@ static int check_data(struct manager *mgr, struct sk_buff *skb) { struct mISDNhead *hh = mISDN_HEAD_P(skb); - int ret, tei; + int ret, tei, sapi; struct layer2 *l2; if (*debug & DEBUG_L2_CTRL) @@ -1159,20 +1176,27 @@ check_data(struct manager *mgr, struct sk_buff *skb) return -ENOTCONN; if (skb->len != 3) return -ENOTCONN; - if (skb->data[0] != 0) - /* only SAPI 0 command */ - return -ENOTCONN; + if (skb->data[0] & 3) /* EA0 and CR must be 0 */ + return -EINVAL; + sapi = skb->data[0] >> 2; if (!(skb->data[1] & 1)) /* invalid EA1 */ return -EINVAL; - tei = skb->data[1] >> 0; + tei = skb->data[1] >> 1; if (tei > 63) /* not a fixed tei */ return -ENOTCONN; if ((skb->data[2] & ~0x10) != SABME) return -ENOTCONN; /* We got a SABME for a fixed TEI */ - l2 = create_new_tei(mgr, tei); - if (!l2) + if (*debug & DEBUG_L2_CTRL) + printk(KERN_DEBUG "%s: SABME sapi(%d) tei(%d)\n", + __func__, sapi, tei); + l2 = create_new_tei(mgr, tei, sapi); + if (!l2) { + if (*debug & DEBUG_L2_CTRL) + printk(KERN_DEBUG "%s: failed to create new tei\n", + __func__); return -ENOMEM; + } ret = l2->ch.send(&l2->ch, skb); return ret; } diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index bbd99d3282c0..5b7e9bf514f1 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c @@ -259,7 +259,7 @@ mISDN_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, return ret; } -static struct file_operations mISDN_fops = { +static const struct file_operations mISDN_fops = { .read = mISDN_read, .poll = mISDN_poll, .ioctl = mISDN_ioctl, diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index c2804f26cb44..a9e48e28b1dc 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -703,7 +703,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) printk (KERN_ERR "%s: no tx context available: %u\n", __func__, priv->mpt_txfidx_tail); - return 1; + return NETDEV_TX_BUSY; } mf = mpt_get_msg_frame(LanCtx, mpt_dev); @@ -713,7 +713,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) printk (KERN_ERR "%s: Unable to alloc request frame\n", __func__); - return 1; + return NETDEV_TX_BUSY; } ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--]; diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 6faefcffcb53..8d1c60a3f0df 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -450,7 +450,8 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) "packet\n", sizeof(struct xpnet_pending_msg)); dev->stats.tx_errors++; - return -ENOMEM; + dev_kfree_skb(skb); + return NETDEV_TX_OK; } /* get the beginning of the first cacheline and end of last */ diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 1c5344aa57cc..367bec63620c 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -281,7 +281,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr) autoirq = probe_irq_off(irq_mask); if (autoirq == 0) { - printk(KERN_WARNING "%s probe at %#x failed to detect IRQ line.\n", + pr_warning("%s probe at %#x failed to detect IRQ line.\n", mname, ioaddr); release_region(ioaddr, EL1_IO_EXTENT); return -EAGAIN; @@ -297,16 +297,16 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr) if (autoirq) dev->irq = autoirq; - printk(KERN_INFO "%s: %s EtherLink at %#lx, using %sIRQ %d.\n", + pr_info("%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr, autoirq ? "auto":"assigned ", dev->irq); #ifdef CONFIG_IP_MULTICAST - printk(KERN_WARNING "WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n"); + pr_warning("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n"); #endif if (el_debug) - printk(KERN_DEBUG "%s", version); + pr_debug("%s", version); lp = netdev_priv(dev); memset(lp, 0, sizeof(struct net_local)); @@ -343,7 +343,7 @@ static int el_open(struct net_device *dev) unsigned long flags; if (el_debug > 2) - printk(KERN_DEBUG "%s: Doing el_open()...", dev->name); + pr_debug("%s: Doing el_open()...\n", dev->name); retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev); if (retval) @@ -374,7 +374,7 @@ static void el_timeout(struct net_device *dev) int ioaddr = dev->base_addr; if (el_debug) - printk(KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", + pr_debug("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); dev->stats.tx_errors++; @@ -483,14 +483,13 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev) lp->loading = 0; dev->trans_start = jiffies; if (el_debug > 2) - printk(KERN_DEBUG " queued xmit.\n"); + pr_debug(" queued xmit.\n"); dev_kfree_skb(skb); return 0; } /* A receive upset our load, despite our best efforts */ if (el_debug > 2) - printk(KERN_DEBUG "%s: burped during tx load.\n", - dev->name); + pr_debug("%s: burped during tx load.\n", dev->name); spin_lock_irqsave(&lp->lock, flags); } while (1); } @@ -540,11 +539,10 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) */ if (el_debug > 3) - printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x", - dev->name, axsr); + pr_debug("%s: el_interrupt() aux=%#02x\n", dev->name, axsr); if (lp->loading == 1 && !lp->txing) - printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n", + pr_warning("%s: Inconsistent state loading while not in tx\n", dev->name); if (lp->txing) { @@ -555,19 +553,17 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) int txsr = inb(TX_STATUS); if (lp->loading == 1) { - if (el_debug > 2) { - printk(KERN_DEBUG "%s: Interrupt while loading [", - dev->name); - printk(" txsr=%02x gp=%04x rp=%04x]\n", - txsr, inw(GP_LOW), inw(RX_LOW)); - } + if (el_debug > 2) + pr_debug("%s: Interrupt while loading [txsr=%02x gp=%04x rp=%04x]\n", + dev->name, txsr, inw(GP_LOW), inw(RX_LOW)); + /* Force a reload */ lp->loading = 2; spin_unlock(&lp->lock); goto out; } if (el_debug > 6) - printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x", + pr_debug("%s: txsr=%02x gp=%04x rp=%04x\n", dev->name, txsr, inw(GP_LOW), inw(RX_LOW)); if ((axsr & 0x80) && (txsr & TX_READY) == 0) { @@ -576,7 +572,7 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) * on trying or reset immediately ? */ if (el_debug > 1) - printk(KERN_DEBUG "%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n", + pr_debug("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); @@ -587,7 +583,7 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) * Timed out */ if (el_debug) - printk(KERN_DEBUG "%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name); + pr_debug("%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name); outb(AX_SYS, AX_CMD); lp->txing = 0; dev->stats.tx_aborted_errors++; @@ -598,7 +594,7 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) */ if (el_debug > 6) - printk(KERN_DEBUG " retransmitting after a collision.\n"); + pr_debug("%s: retransmitting after a collision.\n", dev->name); /* * Poor little chip can't reset its own start * pointer @@ -616,9 +612,8 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) */ dev->stats.tx_packets++; if (el_debug > 6) - printk(KERN_DEBUG " Tx succeeded %s\n", - (txsr & TX_RDY) ? "." : - "but tx is busy!"); + pr_debug("%s: Tx succeeded %s\n", dev->name, + (txsr & TX_RDY) ? "." : "but tx is busy!"); /* * This is safe the interrupt is atomic WRT itself. */ @@ -633,7 +628,8 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) int rxsr = inb(RX_STATUS); if (el_debug > 5) - printk(KERN_DEBUG " rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS), inw(RX_LOW)); + pr_debug("%s: rxsr=%02x txsr=%02x rp=%04x\n", + dev->name, rxsr, inb(TX_STATUS), inw(RX_LOW)); /* * Just reading rx_status fixes most errors. */ @@ -643,7 +639,7 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) /* Handled to avoid board lock-up. */ dev->stats.rx_length_errors++; if (el_debug > 5) - printk(KERN_DEBUG " runt.\n"); + pr_debug("%s: runt.\n", dev->name); } else if (rxsr & RX_GOOD) { /* * Receive worked. @@ -654,12 +650,10 @@ static irqreturn_t el_interrupt(int irq, void *dev_id) * Nothing? Something is broken! */ if (el_debug > 2) - printk(KERN_DEBUG "%s: No packet seen, rxsr=%02x **resetting 3c501***\n", + pr_debug("%s: No packet seen, rxsr=%02x **resetting 3c501***\n", dev->name, rxsr); el_reset(dev); } - if (el_debug > 3) - printk(KERN_DEBUG ".\n"); } /* @@ -695,11 +689,11 @@ static void el_receive(struct net_device *dev) pkt_len = inw(RX_LOW); if (el_debug > 4) - printk(KERN_DEBUG " el_receive %d.\n", pkt_len); + pr_debug(" el_receive %d.\n", pkt_len); if (pkt_len < 60 || pkt_len > 1536) { if (el_debug) - printk(KERN_DEBUG "%s: bogus packet, length=%d\n", + pr_debug("%s: bogus packet, length=%d\n", dev->name, pkt_len); dev->stats.rx_over_errors++; return; @@ -718,8 +712,7 @@ static void el_receive(struct net_device *dev) outw(0x00, GP_LOW); if (skb == NULL) { - printk(KERN_INFO "%s: Memory squeeze, dropping packet.\n", - dev->name); + pr_info("%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; return; } else { @@ -753,7 +746,7 @@ static void el_reset(struct net_device *dev) int ioaddr = dev->base_addr; if (el_debug > 2) - printk(KERN_INFO "3c501 reset..."); + pr_info("3c501 reset...\n"); outb(AX_RESET, AX_CMD); /* Reset the chip */ /* Aux control, irq and loopback enabled */ outb(AX_LOOP, AX_CMD); @@ -787,7 +780,7 @@ static int el1_close(struct net_device *dev) int ioaddr = dev->base_addr; if (el_debug > 2) - printk(KERN_INFO "%s: Shutting down Ethernet card at %#x.\n", + pr_info("%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr); netif_stop_queue(dev); diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 4f08bd995836..134638a9759f 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -234,16 +234,16 @@ el2_probe1(struct net_device *dev, int ioaddr) } if (ei_debug && version_printed++ == 0) - printk(version); + pr_debug("%s", version); dev->base_addr = ioaddr; - printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr); + pr_info("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr); /* Retrieve and print the ethernet address. */ for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(ioaddr + i); - printk("%pM", dev->dev_addr); + pr_cont("%pM", dev->dev_addr); /* Map the 8390 back into the window. */ outb(ECNTRL_THIN, ioaddr + 0x406); @@ -256,7 +256,8 @@ el2_probe1(struct net_device *dev, int ioaddr) outb_p(E8390_PAGE0, ioaddr + E8390_CMD); /* Probe for, turn on and clear the board's shared memory. */ - if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg); + if (ei_debug > 2) + pr_cont(" memory jumpers %2.2x ", membase_reg); outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */ /* This should be probed for (or set via an ioctl()) at run-time. @@ -268,7 +269,7 @@ el2_probe1(struct net_device *dev, int ioaddr) #else ei_status.interface_num = dev->mem_end & 0xf; #endif - printk(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex"); + pr_cont(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex"); if ((membase_reg & 0xf0) == 0) { dev->mem_start = 0; @@ -292,7 +293,7 @@ el2_probe1(struct net_device *dev, int ioaddr) writel(test_val, mem_base + i); if (readl(mem_base) != 0xba5eba5e || readl(mem_base + i) != test_val) { - printk("3c503: memory failure or memory address conflict.\n"); + pr_warning("3c503: memory failure or memory address conflict.\n"); dev->mem_start = 0; ei_status.name = "3c503-PIO"; iounmap(mem_base); @@ -344,7 +345,7 @@ el2_probe1(struct net_device *dev, int ioaddr) if (dev->irq == 2) dev->irq = 9; else if (dev->irq > 5 && dev->irq != 9) { - printk("3c503: configured interrupt %d invalid, will use autoIRQ.\n", + pr_warning("3c503: configured interrupt %d invalid, will use autoIRQ.\n", dev->irq); dev->irq = 0; } @@ -359,7 +360,7 @@ el2_probe1(struct net_device *dev, int ioaddr) goto out1; if (dev->mem_start) - printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n", + pr_info("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n", dev->name, ei_status.name, (wordlength+1)<<3, dev->mem_start, dev->mem_end-1); @@ -367,7 +368,7 @@ el2_probe1(struct net_device *dev, int ioaddr) { ei_status.tx_start_page = EL2_MB1_START_PG; ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES; - printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n", + pr_info("%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n", dev->name, ei_status.name, (wordlength+1)<<3); } release_region(ioaddr + 0x400, 8); @@ -435,15 +436,16 @@ static void el2_reset_8390(struct net_device *dev) { if (ei_debug > 1) { - printk("%s: Resetting the 3c503 board...", dev->name); - printk("%#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR), + pr_debug("%s: Resetting the 3c503 board...", dev->name); + pr_cont(" %#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR), E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR)); } outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL); ei_status.txing = 0; outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); el2_init_card(dev); - if (ei_debug > 1) printk("done\n"); + if (ei_debug > 1) + pr_cont("done\n"); } /* Initialize the 3c503 GA registers after a reset. */ @@ -529,7 +531,7 @@ el2_block_output(struct net_device *dev, int count, { if(!boguscount--) { - printk("%s: FIFO blocked in el2_block_output.\n", dev->name); + pr_notice("%s: FIFO blocked in el2_block_output.\n", dev->name); el2_reset_8390(dev); goto blocked; } @@ -581,7 +583,7 @@ el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_pag { if(!boguscount--) { - printk("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name); + pr_notice("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name); memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr)); el2_reset_8390(dev); goto blocked; @@ -645,7 +647,7 @@ el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring { if(!boguscount--) { - printk("%s: FIFO blocked in el2_block_input.\n", dev->name); + pr_notice("%s: FIFO blocked in el2_block_input.\n", dev->name); el2_reset_8390(dev); goto blocked; } @@ -707,7 +709,7 @@ init_module(void) for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { if (io[this_dev] == 0) { if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "3c503.c: Presently autoprobing (not recommended) for a single card.\n"); + pr_notice("3c503.c: Presently autoprobing (not recommended) for a single card.\n"); } dev = alloc_eip_netdev(); if (!dev) @@ -720,7 +722,7 @@ init_module(void) continue; } free_netdev(dev); - printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); + pr_warning("3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); break; } if (found) diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 2de1c9cd7bde..f71b35402755 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -126,26 +126,25 @@ * *********************************************************/ -static const char filename[] = __FILE__; +#define filename __FILE__ -static const char timeout_msg[] = "*** timeout at %s:%s (line %d) ***\n"; +#define timeout_msg "*** timeout at %s:%s (line %d) ***\n" #define TIMEOUT_MSG(lineno) \ - printk(timeout_msg, filename,__func__,(lineno)) + pr_notice(timeout_msg, filename, __func__, (lineno)) -static const char invalid_pcb_msg[] = -"*** invalid pcb length %d at %s:%s (line %d) ***\n"; +#define invalid_pcb_msg "*** invalid pcb length %d at %s:%s (line %d) ***\n" #define INVALID_PCB_MSG(len) \ - printk(invalid_pcb_msg, (len),filename,__func__,__LINE__) + pr_notice(invalid_pcb_msg, (len), filename, __func__, __LINE__) -static char search_msg[] __initdata = KERN_INFO "%s: Looking for 3c505 adapter at address %#x..."; +#define search_msg "%s: Looking for 3c505 adapter at address %#x..." -static char stilllooking_msg[] __initdata = "still looking..."; +#define stilllooking_msg "still looking..." -static char found_msg[] __initdata = "found.\n"; +#define found_msg "found.\n" -static char notfound_msg[] __initdata = "not found (reason = %d)\n"; +#define notfound_msg "not found (reason = %d)\n" -static char couldnot_msg[] __initdata = KERN_INFO "%s: 3c505 not found\n"; +#define couldnot_msg "%s: 3c505 not found\n" /********************************************************* * @@ -284,7 +283,7 @@ static inline void adapter_reset(struct net_device *dev) outb_control(orig_hcr, dev); if (!start_receive(dev, &adapter->tx_pcb)) - printk(KERN_ERR "%s: start receive command failed \n", dev->name); + pr_err("%s: start receive command failed\n", dev->name); } /* Check to make sure that a DMA transfer hasn't timed out. This should @@ -296,7 +295,9 @@ static inline void check_3c505_dma(struct net_device *dev) elp_device *adapter = netdev_priv(dev); if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) { unsigned long flags, f; - printk(KERN_ERR "%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma)); + pr_err("%s: DMA %s timed out, %d bytes left\n", dev->name, + adapter->current_dma.direction ? "download" : "upload", + get_dma_residue(dev->dma)); spin_lock_irqsave(&adapter->lock, flags); adapter->dmaing = 0; adapter->busy = 0; @@ -321,7 +322,7 @@ static inline bool send_pcb_slow(unsigned int base_addr, unsigned char byte) if (inb_status(base_addr) & HCRE) return false; } - printk(KERN_WARNING "3c505: send_pcb_slow timed out\n"); + pr_warning("3c505: send_pcb_slow timed out\n"); return true; } @@ -333,7 +334,7 @@ static inline bool send_pcb_fast(unsigned int base_addr, unsigned char byte) if (inb_status(base_addr) & HCRE) return false; } - printk(KERN_WARNING "3c505: send_pcb_fast timed out\n"); + pr_warning("3c505: send_pcb_fast timed out\n"); return true; } @@ -386,7 +387,7 @@ static bool send_pcb(struct net_device *dev, pcb_struct * pcb) /* Avoid contention */ if (test_and_set_bit(1, &adapter->send_pcb_semaphore)) { if (elp_debug >= 3) { - printk(KERN_DEBUG "%s: send_pcb entered while threaded\n", dev->name); + pr_debug("%s: send_pcb entered while threaded\n", dev->name); } return false; } @@ -424,14 +425,15 @@ static bool send_pcb(struct net_device *dev, pcb_struct * pcb) case ASF_PCB_NAK: #ifdef ELP_DEBUG - printk(KERN_DEBUG "%s: send_pcb got NAK\n", dev->name); + pr_debug("%s: send_pcb got NAK\n", dev->name); #endif goto abort; } } if (elp_debug >= 1) - printk(KERN_DEBUG "%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr)); + pr_debug("%s: timeout waiting for PCB acknowledge (status %02x)\n", + dev->name, inb_status(dev->base_addr)); goto abort; sti_abort: @@ -481,7 +483,7 @@ static bool receive_pcb(struct net_device *dev, pcb_struct * pcb) while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); - printk(KERN_INFO "%s: status %02x\n", dev->name, stat); + pr_info("%s: status %02x\n", dev->name, stat); return false; } pcb->length = inb_command(dev->base_addr); @@ -518,7 +520,7 @@ static bool receive_pcb(struct net_device *dev, pcb_struct * pcb) /* safety check total length vs data length */ if (total_length != (pcb->length + 2)) { if (elp_debug >= 2) - printk(KERN_WARNING "%s: mangled PCB received\n", dev->name); + pr_warning("%s: mangled PCB received\n", dev->name); set_hsf(dev, HSF_PCB_NAK); return false; } @@ -527,7 +529,7 @@ static bool receive_pcb(struct net_device *dev, pcb_struct * pcb) if (test_and_set_bit(0, (void *) &adapter->busy)) { if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) { set_hsf(dev, HSF_PCB_NAK); - printk(KERN_WARNING "%s: PCB rejected, transfer in progress and backlog full\n", dev->name); + pr_warning("%s: PCB rejected, transfer in progress and backlog full\n", dev->name); pcb->command = 0; return true; } else { @@ -552,7 +554,7 @@ static bool start_receive(struct net_device *dev, pcb_struct * tx_pcb) elp_device *adapter = netdev_priv(dev); if (elp_debug >= 3) - printk(KERN_DEBUG "%s: restarting receiver\n", dev->name); + pr_debug("%s: restarting receiver\n", dev->name); tx_pcb->command = CMD_RECEIVE_PACKET; tx_pcb->length = sizeof(struct Rcv_pkt); tx_pcb->data.rcv_pkt.buf_seg @@ -586,7 +588,7 @@ static void receive_packet(struct net_device *dev, int len) skb = dev_alloc_skb(rlen + 2); if (!skb) { - printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name); + pr_warning("%s: memory squeeze, dropping packet\n", dev->name); target = adapter->dma_buffer; adapter->current_dma.target = NULL; /* FIXME: stats */ @@ -604,7 +606,8 @@ static void receive_packet(struct net_device *dev, int len) /* if this happens, we die */ if (test_and_set_bit(0, (void *) &adapter->dmaing)) - printk(KERN_ERR "%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction); + pr_err("%s: rx blocked, DMA in progress, dir %d\n", + dev->name, adapter->current_dma.direction); adapter->current_dma.direction = 0; adapter->current_dma.length = rlen; @@ -623,14 +626,14 @@ static void receive_packet(struct net_device *dev, int len) release_dma_lock(flags); if (elp_debug >= 3) { - printk(KERN_DEBUG "%s: rx DMA transfer started\n", dev->name); + pr_debug("%s: rx DMA transfer started\n", dev->name); } if (adapter->rx_active) adapter->rx_active--; if (!adapter->busy) - printk(KERN_WARNING "%s: receive_packet called, busy not set.\n", dev->name); + pr_warning("%s: receive_packet called, busy not set.\n", dev->name); } /****************************************************** @@ -655,12 +658,13 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) * has a DMA transfer finished? */ if (inb_status(dev->base_addr) & DONE) { - if (!adapter->dmaing) { - printk(KERN_WARNING "%s: phantom DMA completed\n", dev->name); - } - if (elp_debug >= 3) { - printk(KERN_DEBUG "%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr)); - } + if (!adapter->dmaing) + pr_warning("%s: phantom DMA completed\n", dev->name); + + if (elp_debug >= 3) + pr_debug("%s: %s DMA complete, status %02x\n", dev->name, + adapter->current_dma.direction ? "tx" : "rx", + inb_status(dev->base_addr)); outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev); if (adapter->current_dma.direction) { @@ -682,7 +686,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) int t = adapter->rx_backlog.length[adapter->rx_backlog.out]; adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out); if (elp_debug >= 2) - printk(KERN_DEBUG "%s: receiving backlogged packet (%d)\n", dev->name, t); + pr_debug("%s: receiving backlogged packet (%d)\n", dev->name, t); receive_packet(dev, t); } else { adapter->busy = 0; @@ -713,21 +717,23 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) len = adapter->irx_pcb.data.rcv_resp.pkt_len; dlen = adapter->irx_pcb.data.rcv_resp.buf_len; if (adapter->irx_pcb.data.rcv_resp.timeout != 0) { - printk(KERN_ERR "%s: interrupt - packet not received correctly\n", dev->name); + pr_err("%s: interrupt - packet not received correctly\n", dev->name); } else { if (elp_debug >= 3) { - printk(KERN_DEBUG "%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen); + pr_debug("%s: interrupt - packet received of length %i (%i)\n", + dev->name, len, dlen); } if (adapter->irx_pcb.command == 0xff) { if (elp_debug >= 2) - printk(KERN_DEBUG "%s: adding packet to backlog (len = %d)\n", dev->name, dlen); + pr_debug("%s: adding packet to backlog (len = %d)\n", + dev->name, dlen); adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen; adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in); } else { receive_packet(dev, dlen); } if (elp_debug >= 3) - printk(KERN_DEBUG "%s: packet received\n", dev->name); + pr_debug("%s: packet received\n", dev->name); } break; @@ -737,7 +743,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) case CMD_CONFIGURE_82586_RESPONSE: adapter->got[CMD_CONFIGURE_82586] = 1; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: interrupt - configure response received\n", dev->name); + pr_debug("%s: interrupt - configure response received\n", dev->name); break; /* @@ -746,7 +752,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) case CMD_CONFIGURE_ADAPTER_RESPONSE: adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: Adapter memory configuration %s.\n", dev->name, + pr_debug("%s: Adapter memory configuration %s.\n", dev->name, adapter->irx_pcb.data.failed ? "failed" : "succeeded"); break; @@ -756,7 +762,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) case CMD_LOAD_MULTICAST_RESPONSE: adapter->got[CMD_LOAD_MULTICAST_LIST] = 1; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: Multicast address list loading %s.\n", dev->name, + pr_debug("%s: Multicast address list loading %s.\n", dev->name, adapter->irx_pcb.data.failed ? "failed" : "succeeded"); break; @@ -766,7 +772,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) case CMD_SET_ADDRESS_RESPONSE: adapter->got[CMD_SET_STATION_ADDRESS] = 1; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: Ethernet address setting %s.\n", dev->name, + pr_debug("%s: Ethernet address setting %s.\n", dev->name, adapter->irx_pcb.data.failed ? "failed" : "succeeded"); break; @@ -783,7 +789,7 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) dev->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res; adapter->got[CMD_NETWORK_STATISTICS] = 1; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: interrupt - statistics response received\n", dev->name); + pr_debug("%s: interrupt - statistics response received\n", dev->name); break; /* @@ -791,17 +797,17 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) */ case CMD_TRANSMIT_PACKET_COMPLETE: if (elp_debug >= 3) - printk(KERN_DEBUG "%s: interrupt - packet sent\n", dev->name); + pr_debug("%s: interrupt - packet sent\n", dev->name); if (!netif_running(dev)) break; switch (adapter->irx_pcb.data.xmit_resp.c_stat) { case 0xffff: dev->stats.tx_aborted_errors++; - printk(KERN_INFO "%s: transmit timed out, network cable problem?\n", dev->name); + pr_info("%s: transmit timed out, network cable problem?\n", dev->name); break; case 0xfffe: dev->stats.tx_fifo_errors++; - printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name); + pr_info("%s: transmit timed out, FIFO underrun\n", dev->name); break; } netif_wake_queue(dev); @@ -811,11 +817,12 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id) * some unknown PCB */ default: - printk(KERN_DEBUG "%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command); + pr_debug("%s: unknown PCB received - %2.2x\n", + dev->name, adapter->irx_pcb.command); break; } } else { - printk(KERN_WARNING "%s: failed to read PCB on interrupt\n", dev->name); + pr_warning("%s: failed to read PCB on interrupt\n", dev->name); adapter_reset(dev); } } @@ -844,13 +851,13 @@ static int elp_open(struct net_device *dev) int retval; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: request to open device\n", dev->name); + pr_debug("%s: request to open device\n", dev->name); /* * make sure we actually found the device */ if (adapter == NULL) { - printk(KERN_ERR "%s: Opening a non-existent physical device\n", dev->name); + pr_err("%s: Opening a non-existent physical device\n", dev->name); return -EAGAIN; } /* @@ -880,17 +887,17 @@ static int elp_open(struct net_device *dev) * install our interrupt service routine */ if ((retval = request_irq(dev->irq, &elp_interrupt, 0, dev->name, dev))) { - printk(KERN_ERR "%s: could not allocate IRQ%d\n", dev->name, dev->irq); + pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq); return retval; } if ((retval = request_dma(dev->dma, dev->name))) { free_irq(dev->irq, dev); - printk(KERN_ERR "%s: could not allocate DMA%d channel\n", dev->name, dev->dma); + pr_err("%s: could not allocate DMA%d channel\n", dev->name, dev->dma); return retval; } adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE); if (!adapter->dma_buffer) { - printk(KERN_ERR "%s: could not allocate DMA buffer\n", dev->name); + pr_err("%s: could not allocate DMA buffer\n", dev->name); free_dma(dev->dma); free_irq(dev->irq, dev); return -ENOMEM; @@ -906,7 +913,7 @@ static int elp_open(struct net_device *dev) * configure adapter memory: we need 10 multicast addresses, default==0 */ if (elp_debug >= 3) - printk(KERN_DEBUG "%s: sending 3c505 memory configuration command\n", dev->name); + pr_debug("%s: sending 3c505 memory configuration command\n", dev->name); adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY; adapter->tx_pcb.data.memconf.cmd_q = 10; adapter->tx_pcb.data.memconf.rcv_q = 20; @@ -917,7 +924,7 @@ static int elp_open(struct net_device *dev) adapter->tx_pcb.length = sizeof(struct Memconf); adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) - printk(KERN_ERR "%s: couldn't send memory configuration command\n", dev->name); + pr_err("%s: couldn't send memory configuration command\n", dev->name); else { unsigned long timeout = jiffies + TIMEOUT; while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout)); @@ -930,13 +937,13 @@ static int elp_open(struct net_device *dev) * configure adapter to receive broadcast messages and wait for response */ if (elp_debug >= 3) - printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name); + pr_debug("%s: sending 82586 configure command\n", dev->name); adapter->tx_pcb.command = CMD_CONFIGURE_82586; adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; adapter->tx_pcb.length = 2; adapter->got[CMD_CONFIGURE_82586] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) - printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name); + pr_err("%s: couldn't send 82586 configure command\n", dev->name); else { unsigned long timeout = jiffies + TIMEOUT; while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout)); @@ -952,7 +959,7 @@ static int elp_open(struct net_device *dev) */ prime_rx(dev); if (elp_debug >= 3) - printk(KERN_DEBUG "%s: %d receive PCBs active\n", dev->name, adapter->rx_active); + pr_debug("%s: %d receive PCBs active\n", dev->name, adapter->rx_active); /* * device is now officially open! @@ -982,7 +989,7 @@ static bool send_packet(struct net_device *dev, struct sk_buff *skb) if (test_and_set_bit(0, (void *) &adapter->busy)) { if (elp_debug >= 2) - printk(KERN_DEBUG "%s: transmit blocked\n", dev->name); + pr_debug("%s: transmit blocked\n", dev->name); return false; } @@ -1004,7 +1011,7 @@ static bool send_packet(struct net_device *dev, struct sk_buff *skb) } /* if this happens, we die */ if (test_and_set_bit(0, (void *) &adapter->dmaing)) - printk(KERN_DEBUG "%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction); + pr_debug("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction); adapter->current_dma.direction = 1; adapter->current_dma.start_time = jiffies; @@ -1030,7 +1037,7 @@ static bool send_packet(struct net_device *dev, struct sk_buff *skb) release_dma_lock(flags); if (elp_debug >= 3) - printk(KERN_DEBUG "%s: DMA transfer started\n", dev->name); + pr_debug("%s: DMA transfer started\n", dev->name); return true; } @@ -1044,9 +1051,10 @@ static void elp_timeout(struct net_device *dev) int stat; stat = inb_status(dev->base_addr); - printk(KERN_WARNING "%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command"); + pr_warning("%s: transmit timed out, lost %s?\n", dev->name, + (stat & ACRF) ? "interrupt" : "command"); if (elp_debug >= 1) - printk(KERN_DEBUG "%s: status %#02x\n", dev->name, stat); + pr_debug("%s: status %#02x\n", dev->name, stat); dev->trans_start = jiffies; dev->stats.tx_dropped++; netif_wake_queue(dev); @@ -1068,7 +1076,7 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev) check_3c505_dma(dev); if (elp_debug >= 3) - printk(KERN_DEBUG "%s: request to send packet of length %d\n", dev->name, (int) skb->len); + pr_debug("%s: request to send packet of length %d\n", dev->name, (int) skb->len); netif_stop_queue(dev); @@ -1077,13 +1085,13 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev) */ if (!send_packet(dev, skb)) { if (elp_debug >= 2) { - printk(KERN_DEBUG "%s: failed to transmit packet\n", dev->name); + pr_debug("%s: failed to transmit packet\n", dev->name); } spin_unlock_irqrestore(&adapter->lock, flags); - return 1; + return NETDEV_TX_BUSY; } if (elp_debug >= 3) - printk(KERN_DEBUG "%s: packet of length %d sent\n", dev->name, (int) skb->len); + pr_debug("%s: packet of length %d sent\n", dev->name, (int) skb->len); /* * start the transmit timeout @@ -1107,7 +1115,7 @@ static struct net_device_stats *elp_get_stats(struct net_device *dev) elp_device *adapter = netdev_priv(dev); if (elp_debug >= 3) - printk(KERN_DEBUG "%s: request for stats\n", dev->name); + pr_debug("%s: request for stats\n", dev->name); /* If the device is closed, just return the latest stats we have, - we cannot ask from the adapter without interrupts */ @@ -1119,7 +1127,7 @@ static struct net_device_stats *elp_get_stats(struct net_device *dev) adapter->tx_pcb.length = 0; adapter->got[CMD_NETWORK_STATISTICS] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) - printk(KERN_ERR "%s: couldn't send get statistics command\n", dev->name); + pr_err("%s: couldn't send get statistics command\n", dev->name); else { unsigned long timeout = jiffies + TIMEOUT; while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout)); @@ -1169,7 +1177,7 @@ static int elp_close(struct net_device *dev) elp_device *adapter = netdev_priv(dev); if (elp_debug >= 3) - printk(KERN_DEBUG "%s: request to close device\n", dev->name); + pr_debug("%s: request to close device\n", dev->name); netif_stop_queue(dev); @@ -1213,7 +1221,7 @@ static void elp_set_mc_list(struct net_device *dev) unsigned long flags; if (elp_debug >= 3) - printk(KERN_DEBUG "%s: request to set multicast list\n", dev->name); + pr_debug("%s: request to set multicast list\n", dev->name); spin_lock_irqsave(&adapter->lock, flags); @@ -1228,7 +1236,7 @@ static void elp_set_mc_list(struct net_device *dev) } adapter->got[CMD_LOAD_MULTICAST_LIST] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) - printk(KERN_ERR "%s: couldn't send set_multicast command\n", dev->name); + pr_err("%s: couldn't send set_multicast command\n", dev->name); else { unsigned long timeout = jiffies + TIMEOUT; while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout)); @@ -1247,14 +1255,14 @@ static void elp_set_mc_list(struct net_device *dev) * and wait for response */ if (elp_debug >= 3) - printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name); + pr_debug("%s: sending 82586 configure command\n", dev->name); adapter->tx_pcb.command = CMD_CONFIGURE_82586; adapter->tx_pcb.length = 2; adapter->got[CMD_CONFIGURE_82586] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) { spin_unlock_irqrestore(&adapter->lock, flags); - printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name); + pr_err("%s: couldn't send 82586 configure command\n", dev->name); } else { unsigned long timeout = jiffies + TIMEOUT; @@ -1283,17 +1291,17 @@ static int __init elp_sense(struct net_device *dev) orig_HSR = inb_status(addr); if (elp_debug > 0) - printk(search_msg, name, addr); + pr_debug(search_msg, name, addr); if (orig_HSR == 0xff) { if (elp_debug > 0) - printk(notfound_msg, 1); + pr_cont(notfound_msg, 1); goto out; } /* Wait for a while; the adapter may still be booting up */ if (elp_debug > 0) - printk(stilllooking_msg); + pr_cont(stilllooking_msg); if (orig_HSR & DIR) { /* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */ @@ -1301,7 +1309,7 @@ static int __init elp_sense(struct net_device *dev) msleep(300); if (inb_status(addr) & DIR) { if (elp_debug > 0) - printk(notfound_msg, 2); + pr_cont(notfound_msg, 2); goto out; } } else { @@ -1310,7 +1318,7 @@ static int __init elp_sense(struct net_device *dev) msleep(300); if (!(inb_status(addr) & DIR)) { if (elp_debug > 0) - printk(notfound_msg, 3); + pr_cont(notfound_msg, 3); goto out; } } @@ -1318,7 +1326,7 @@ static int __init elp_sense(struct net_device *dev) * It certainly looks like a 3c505. */ if (elp_debug > 0) - printk(found_msg); + pr_cont(found_msg); return 0; out: @@ -1349,7 +1357,7 @@ static int __init elp_autodetect(struct net_device *dev) /* could not find an adapter */ if (elp_debug > 0) - printk(couldnot_msg, dev->name); + pr_debug(couldnot_msg, dev->name); return 0; /* Because of this, the layer above will return -ENODEV */ } @@ -1424,16 +1432,16 @@ static int __init elplus_setup(struct net_device *dev) /* Nope, it's ignoring the command register. This means that * either it's still booting up, or it's died. */ - printk(KERN_ERR "%s: command register wouldn't drain, ", dev->name); + pr_err("%s: command register wouldn't drain, ", dev->name); if ((inb_status(dev->base_addr) & 7) == 3) { /* If the adapter status is 3, it *could* still be booting. * Give it the benefit of the doubt for 10 seconds. */ - printk("assuming 3c505 still starting\n"); + pr_cont("assuming 3c505 still starting\n"); timeout = jiffies + 10*HZ; while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7)); if (inb_status(dev->base_addr) & 7) { - printk(KERN_ERR "%s: 3c505 failed to start\n", dev->name); + pr_err("%s: 3c505 failed to start\n", dev->name); } else { okay = 1; /* It started */ } @@ -1441,7 +1449,7 @@ static int __init elplus_setup(struct net_device *dev) /* Otherwise, it must just be in a strange * state. We probably need to kick it. */ - printk("3c505 is sulking\n"); + pr_cont("3c505 is sulking\n"); } } for (tries = 0; tries < 5 && okay; tries++) { @@ -1454,18 +1462,19 @@ static int __init elplus_setup(struct net_device *dev) adapter->tx_pcb.length = 0; cookie = probe_irq_on(); if (!send_pcb(dev, &adapter->tx_pcb)) { - printk(KERN_ERR "%s: could not send first PCB\n", dev->name); + pr_err("%s: could not send first PCB\n", dev->name); probe_irq_off(cookie); continue; } if (!receive_pcb(dev, &adapter->rx_pcb)) { - printk(KERN_ERR "%s: could not read first PCB\n", dev->name); + pr_err("%s: could not read first PCB\n", dev->name); probe_irq_off(cookie); continue; } if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) || (adapter->rx_pcb.length != 6)) { - printk(KERN_ERR "%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length); + pr_err("%s: first PCB wrong (%d, %d)\n", dev->name, + adapter->rx_pcb.command, adapter->rx_pcb.length); probe_irq_off(cookie); continue; } @@ -1474,32 +1483,32 @@ static int __init elplus_setup(struct net_device *dev) /* It's broken. Do a hard reset to re-initialise the board, * and try again. */ - printk(KERN_INFO "%s: resetting adapter\n", dev->name); + pr_info("%s: resetting adapter\n", dev->name); outb_control(adapter->hcr_val | FLSH | ATTN, dev); outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev); } - printk(KERN_ERR "%s: failed to initialise 3c505\n", dev->name); + pr_err("%s: failed to initialise 3c505\n", dev->name); goto out; okay: if (dev->irq) { /* Is there a preset IRQ? */ int rpt = probe_irq_off(cookie); if (dev->irq != rpt) { - printk(KERN_WARNING "%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt); + pr_warning("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt); } /* if dev->irq == probe_irq_off(cookie), all is well */ } else /* No preset IRQ; just use what we can detect */ dev->irq = probe_irq_off(cookie); switch (dev->irq) { /* Legal, sane? */ case 0: - printk(KERN_ERR "%s: IRQ probe failed: check 3c505 jumpers.\n", + pr_err("%s: IRQ probe failed: check 3c505 jumpers.\n", dev->name); goto out; case 1: case 6: case 8: case 13: - printk(KERN_ERR "%s: Impossible IRQ %d reported by probe_irq_off().\n", + pr_err("%s: Impossible IRQ %d reported by probe_irq_off().\n", dev->name, dev->irq); goto out; } @@ -1521,7 +1530,7 @@ static int __init elplus_setup(struct net_device *dev) dev->dma = dev->mem_start & 7; } else { - printk(KERN_WARNING "%s: warning, DMA channel not specified, using default\n", dev->name); + pr_warning("%s: warning, DMA channel not specified, using default\n", dev->name); dev->dma = ELP_DMA; } } @@ -1529,11 +1538,8 @@ static int __init elplus_setup(struct net_device *dev) /* * print remainder of startup message */ - printk(KERN_INFO "%s: 3c505 at %#lx, irq %d, dma %d, " - "addr %pM, ", - dev->name, dev->base_addr, dev->irq, dev->dma, - dev->dev_addr); - + pr_info("%s: 3c505 at %#lx, irq %d, dma %d, addr %pM, ", + dev->name, dev->base_addr, dev->irq, dev->dma, dev->dev_addr); /* * read more information from the adapter */ @@ -1544,9 +1550,10 @@ static int __init elplus_setup(struct net_device *dev) !receive_pcb(dev, &adapter->rx_pcb) || (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) || (adapter->rx_pcb.length != 10)) { - printk("not responding to second PCB\n"); + pr_cont("not responding to second PCB\n"); } - printk("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz); + pr_cont("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, + adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz); /* * reconfigure the adapter memory to better suit our purposes @@ -1563,10 +1570,10 @@ static int __init elplus_setup(struct net_device *dev) !receive_pcb(dev, &adapter->rx_pcb) || (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) || (adapter->rx_pcb.length != 2)) { - printk(KERN_ERR "%s: could not configure adapter memory\n", dev->name); + pr_err("%s: could not configure adapter memory\n", dev->name); } if (adapter->rx_pcb.data.configure) { - printk(KERN_ERR "%s: adapter configuration failed\n", dev->name); + pr_err("%s: adapter configuration failed\n", dev->name); } dev->netdev_ops = &elp_netdev_ops; @@ -1631,17 +1638,17 @@ int __init init_module(void) dev->dma = dma[this_dev]; } else { dev->dma = ELP_DMA; - printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n"); + pr_warning("3c505.c: warning, using default DMA channel,\n"); } if (io[this_dev] == 0) { if (this_dev) { free_netdev(dev); break; } - printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n"); + pr_notice("3c505.c: module autoprobe not recommended, give io=xx.\n"); } if (elplus_setup(dev) != 0) { - printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]); + pr_warning("3c505.c: Failed to register card at 0x%x.\n", io[this_dev]); free_netdev(dev); break; } diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index fbbaf826deff..96b86659381a 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -364,7 +364,7 @@ static const struct net_device_ops netdev_ops = { static int __init el16_probe1(struct net_device *dev, int ioaddr) { - static unsigned char init_ID_done, version_printed; + static unsigned char init_ID_done; int i, irq, irqval, retval; struct net_local *lp; @@ -391,10 +391,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr) goto out; } - if (net_debug && version_printed++ == 0) - printk(version); - - printk("%s: 3c507 at %#x,", dev->name, ioaddr); + pr_info("%s: 3c507 at %#x,", dev->name, ioaddr); /* We should make a few more checks here, like the first three octets of the S.A. for the manufacturer's code. */ @@ -403,7 +400,8 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr) irqval = request_irq(irq, &el16_interrupt, 0, DRV_NAME, dev); if (irqval) { - printk(KERN_ERR "3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval); + pr_cont("\n"); + pr_err("3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval); retval = -EAGAIN; goto out; } @@ -414,7 +412,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr) outb(0x01, ioaddr + MISC_CTRL); for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(ioaddr + i); - printk(" %pM", dev->dev_addr); + pr_cont(" %pM", dev->dev_addr); if (mem_start) net_debug = mem_start & 7; @@ -443,18 +441,18 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr) dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0; dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq, + pr_cont(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq, dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1); if (net_debug) - printk(version); + pr_debug("%s", version); lp = netdev_priv(dev); memset(lp, 0, sizeof(*lp)); spin_lock_init(&lp->lock); lp->base = ioremap(dev->mem_start, RX_BUF_END); if (!lp->base) { - printk(KERN_ERR "3c507: unable to remap memory\n"); + pr_err("3c507: unable to remap memory\n"); retval = -EAGAIN; goto out1; } @@ -488,20 +486,20 @@ static void el16_tx_timeout (struct net_device *dev) void __iomem *shmem = lp->base; if (net_debug > 1) - printk ("%s: transmit timed out, %s? ", dev->name, + pr_debug("%s: transmit timed out, %s? ", dev->name, readw(shmem + iSCB_STATUS) & 0x8000 ? "IRQ conflict" : "network cable problem"); /* Try to restart the adaptor. */ if (lp->last_restart == dev->stats.tx_packets) { if (net_debug > 1) - printk ("Resetting board.\n"); + pr_cont("Resetting board.\n"); /* Completely reset the adaptor. */ init_82586_mem (dev); lp->tx_pkts_in_ring = 0; } else { /* Issue the channel attention signal and hope it "gets better". */ if (net_debug > 1) - printk ("Kicking board.\n"); + pr_cont("Kicking board.\n"); writew(0xf000 | CUC_START | RX_START, shmem + iSCB_CMD); outb (0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ lp->last_restart = dev->stats.tx_packets; @@ -553,7 +551,8 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) void __iomem *shmem; if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); + pr_err("%s: net_interrupt(): irq %d for unknown device.\n", + dev->name, irq); return IRQ_NONE; } @@ -566,7 +565,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) status = readw(shmem+iSCB_STATUS); if (net_debug > 4) { - printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status); + pr_debug("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status); } /* Disable the 82586's input to the interrupt line. */ @@ -577,7 +576,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) unsigned short tx_status = readw(shmem+lp->tx_reap); if (!(tx_status & 0x8000)) { if (net_debug > 5) - printk("Tx command incomplete (%#x).\n", lp->tx_reap); + pr_debug("Tx command incomplete (%#x).\n", lp->tx_reap); break; } /* Tx unsuccessful or some interesting status bit set. */ @@ -591,7 +590,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) } dev->stats.tx_packets++; if (net_debug > 5) - printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); + pr_debug("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); lp->tx_reap += TX_BUF_SIZE; if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE) lp->tx_reap = TX_BUF_START; @@ -606,7 +605,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) if (status & 0x4000) { /* Packet received. */ if (net_debug > 5) - printk("Received packet, rx_head %04x.\n", lp->rx_head); + pr_debug("Received packet, rx_head %04x.\n", lp->rx_head); el16_rx(dev); } @@ -615,7 +614,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) if ((status & 0x0700) != 0x0200 && netif_running(dev)) { if (net_debug) - printk("%s: Command unit stopped, status %04x, restarting.\n", + pr_debug("%s: Command unit stopped, status %04x, restarting.\n", dev->name, status); /* If this ever occurs we should really re-write the idle loop, reset the Tx list, and do a complete restart of the command unit. @@ -627,7 +626,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) /* The Rx unit is not ready, it must be hung. Restart the receiver by initializing the rx buffers, and issuing an Rx start command. */ if (net_debug) - printk("%s: Rx unit stopped, status %04x, restarting.\n", + pr_debug("%s: Rx unit stopped, status %04x, restarting.\n", dev->name, status); init_rx_bufs(dev); writew(RX_BUF_START,shmem+iSCB_RFA); @@ -753,9 +752,8 @@ static void init_82586_mem(struct net_device *dev) int boguscnt = 50; while (readw(shmem+iSCB_STATUS) == 0) if (--boguscnt == 0) { - printk("%s: i82586 initialization timed out with status %04x, " - "cmd %04x.\n", dev->name, - readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD)); + pr_warning("%s: i82586 initialization timed out with status %04x, cmd %04x.\n", + dev->name, readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD)); break; } /* Issue channel-attn -- the 82586 won't start. */ @@ -765,7 +763,7 @@ static void init_82586_mem(struct net_device *dev) /* Disable loopback and enable interrupts. */ outb(0x84, ioaddr + MISC_CTRL); if (net_debug > 4) - printk("%s: Initialized 82586, status %04x.\n", dev->name, + pr_debug("%s: Initialized 82586, status %04x.\n", dev->name, readw(shmem+iSCB_STATUS)); return; } @@ -810,7 +808,7 @@ static void hardware_send_packet(struct net_device *dev, void *buf, short length lp->tx_head = TX_BUF_START; if (net_debug > 4) { - printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n", + pr_debug("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n", dev->name, ioaddr, length, tx_block, lp->tx_head); } @@ -838,7 +836,7 @@ static void el16_rx(struct net_device *dev) if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 || (pkt_len & 0xC000) != 0xC000) { - printk(KERN_ERR "%s: Rx frame at %#x corrupted, " + pr_err("%s: Rx frame at %#x corrupted, " "status %04x cmd %04x next %04x " "data-buf @%04x %04x.\n", dev->name, rx_head, frame_status, rfd_cmd, @@ -858,8 +856,7 @@ static void el16_rx(struct net_device *dev) pkt_len &= 0x3fff; skb = dev_alloc_skb(pkt_len+2); if (skb == NULL) { - printk(KERN_ERR "%s: Memory squeeze, " - "dropping packet.\n", + pr_err("%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; break; @@ -926,7 +923,7 @@ MODULE_PARM_DESC(irq, "(ignored)"); int __init init_module(void) { if (io == 0) - printk("3c507: You should not use auto-probing with insmod!\n"); + pr_notice("3c507: You should not use auto-probing with insmod!\n"); dev_3c507 = el16_probe(-1); return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0; } diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 682aad897081..d2137efbd455 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -257,7 +257,7 @@ static int el3_isa_id_sequence(__be16 *phys_addr) && !memcmp(phys_addr, el3_devs[i]->dev_addr, ETH_ALEN)) { if (el3_debug > 3) - printk(KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n", + pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n", phys_addr[0] & 0xff, phys_addr[0] >> 8, phys_addr[1] & 0xff, phys_addr[1] >> 8, phys_addr[2] & 0xff, phys_addr[2] >> 8); @@ -578,19 +578,18 @@ static int __devinit el3_common_init(struct net_device *dev) err = register_netdev(dev); if (err) { - printk(KERN_ERR "Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n", + pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n", dev->base_addr, dev->irq); release_region(dev->base_addr, EL3_IO_EXTENT); return err; } - printk(KERN_INFO "%s: 3c5x9 found at %#3.3lx, %s port, " - "address %pM, IRQ %d.\n", + pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n", dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)], dev->dev_addr, dev->irq); if (el3_debug > 0) - printk(KERN_INFO "%s", version); + pr_info("%s", version); return 0; } @@ -629,8 +628,8 @@ static int __init el3_mca_probe(struct device *device) irq = pos5 & 0x0f; - printk(KERN_INFO "3c529: found %s at slot %d\n", - el3_mca_adapter_names[mdev->index], slot + 1); + pr_info("3c529: found %s at slot %d\n", + el3_mca_adapter_names[mdev->index], slot + 1); /* claim the slot */ strncpy(mdev->name, el3_mca_adapter_names[mdev->index], @@ -642,7 +641,7 @@ static int __init el3_mca_probe(struct device *device) irq = mca_device_transform_irq(mdev, irq); ioaddr = mca_device_transform_ioport(mdev, ioaddr); if (el3_debug > 2) { - printk(KERN_DEBUG "3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port); + pr_debug("3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port); } EL3WINDOW(0); for (i = 0; i < 3; i++) @@ -657,11 +656,11 @@ static int __init el3_mca_probe(struct device *device) netdev_boot_setup_check(dev); el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA); - device->driver_data = dev; + dev_set_drvdata(device, dev); err = el3_common_init(dev); if (err) { - device->driver_data = NULL; + dev_set_drvdata(device, NULL); free_netdev(dev); return -ENOMEM; } @@ -725,12 +724,12 @@ static int __init el3_eisa_probe (struct device *device) /* This remove works for all device types. * - * The net dev must be stored in the driver_data field */ + * The net dev must be stored in the driver data field */ static int __devexit el3_device_remove (struct device *device) { struct net_device *dev; - dev = device->driver_data; + dev = dev_get_drvdata(device); el3_common_remove (dev); return 0; @@ -765,7 +764,7 @@ static ushort id_read_eeprom(int index) word = (word << 1) + (inb(id_port) & 0x01); if (el3_debug > 3) - printk(KERN_DEBUG " 3c509 EEPROM word %d %#4.4x.\n", index, word); + pr_debug(" 3c509 EEPROM word %d %#4.4x.\n", index, word); return word; } @@ -787,13 +786,13 @@ el3_open(struct net_device *dev) EL3WINDOW(0); if (el3_debug > 3) - printk(KERN_DEBUG "%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name, + pr_debug("%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name, dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS)); el3_up(dev); if (el3_debug > 3) - printk(KERN_DEBUG "%s: Opened 3c509 IRQ %d status %4.4x.\n", + pr_debug("%s: Opened 3c509 IRQ %d status %4.4x.\n", dev->name, dev->irq, inw(ioaddr + EL3_STATUS)); return 0; @@ -805,8 +804,7 @@ el3_tx_timeout (struct net_device *dev) int ioaddr = dev->base_addr; /* Transmitter timeout, serious problems. */ - printk(KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x " - "Tx FIFO room %d.\n", + pr_warning("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d.\n", dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS), inw(ioaddr + TX_FREE)); dev->stats.tx_errors++; @@ -830,7 +828,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_bytes += skb->len; if (el3_debug > 4) { - printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n", + pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n", dev->name, skb->len, inw(ioaddr + EL3_STATUS)); } #if 0 @@ -839,7 +837,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev) ushort status = inw(ioaddr + EL3_STATUS); if (status & 0x0001 /* IRQ line active, missed one. */ && inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */ - printk(KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x" + pr_debug("%s: Missed interrupt, status then %04x now %04x" " Tx %2.2x Rx %4.4x.\n", dev->name, status, inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS), inw(ioaddr + RX_STATUS)); @@ -913,7 +911,7 @@ el3_interrupt(int irq, void *dev_id) if (el3_debug > 4) { status = inw(ioaddr + EL3_STATUS); - printk(KERN_DEBUG "%s: interrupt, status %4.4x.\n", dev->name, status); + pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status); } while ((status = inw(ioaddr + EL3_STATUS)) & @@ -924,7 +922,7 @@ el3_interrupt(int irq, void *dev_id) if (status & TxAvailable) { if (el3_debug > 5) - printk(KERN_DEBUG " TX room bit was handled.\n"); + pr_debug(" TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue (dev); @@ -962,7 +960,7 @@ el3_interrupt(int irq, void *dev_id) } if (--i < 0) { - printk(KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n", + pr_err("%s: Infinite loop in interrupt, status %4.4x.\n", dev->name, status); /* Clear all interrupts. */ outw(AckIntr | 0xFF, ioaddr + EL3_CMD); @@ -973,7 +971,7 @@ el3_interrupt(int irq, void *dev_id) } if (el3_debug > 4) { - printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name, + pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); } spin_unlock(&lp->lock); @@ -1021,7 +1019,7 @@ static void update_stats(struct net_device *dev) int ioaddr = dev->base_addr; if (el3_debug > 5) - printk(" Updating the statistics.\n"); + pr_debug(" Updating the statistics.\n"); /* Turn off statistics updates while reading. */ outw(StatsDisable, ioaddr + EL3_CMD); /* Switch to the stats window, and read everything. */ @@ -1051,7 +1049,7 @@ el3_rx(struct net_device *dev) short rx_status; if (el3_debug > 5) - printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", + pr_debug(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) { if (rx_status & 0x4000) { /* Error, update stats. */ @@ -1073,7 +1071,7 @@ el3_rx(struct net_device *dev) skb = dev_alloc_skb(pkt_len+5); if (el3_debug > 4) - printk("Receiving packet size %d status %4.4x.\n", + pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); if (skb != NULL) { skb_reserve(skb, 2); /* Align IP on 16 byte */ @@ -1092,12 +1090,12 @@ el3_rx(struct net_device *dev) outw(RxDiscard, ioaddr + EL3_CMD); dev->stats.rx_dropped++; if (el3_debug) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", + pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len); } inw(ioaddr + EL3_STATUS); /* Delay. */ while (inw(ioaddr + EL3_STATUS) & 0x1000) - printk(KERN_DEBUG " Waiting for 3c509 to discard packet, status %x.\n", + pr_debug(" Waiting for 3c509 to discard packet, status %x.\n", inw(ioaddr + EL3_STATUS) ); } @@ -1118,7 +1116,7 @@ set_multicast_list(struct net_device *dev) static int old; if (old != dev->mc_count) { old = dev->mc_count; - printk("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count); + pr_debug("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count); } } spin_lock_irqsave(&lp->lock, flags); @@ -1141,7 +1139,7 @@ el3_close(struct net_device *dev) struct el3_private *lp = netdev_priv(dev); if (el3_debug > 2) - printk("%s: Shutting down ethercard.\n", dev->name); + pr_debug("%s: Shutting down ethercard.\n", dev->name); el3_down(dev); @@ -1388,30 +1386,30 @@ el3_up(struct net_device *dev) EL3WINDOW(4); net_diag = inw(ioaddr + WN4_NETDIAG); net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */ - printk("%s: ", dev->name); + pr_info("%s: ", dev->name); switch (dev->if_port & 0x0c) { case 12: /* force full-duplex mode if 3c5x9b */ if (sw_info & 0x000f) { - printk("Forcing 3c5x9b full-duplex mode"); + pr_cont("Forcing 3c5x9b full-duplex mode"); break; } case 8: /* set full-duplex mode based on eeprom config setting */ if ((sw_info & 0x000f) && (sw_info & 0x8000)) { - printk("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)"); + pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)"); break; } default: /* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */ - printk("Setting 3c5x9/3c5x9B half-duplex mode"); + pr_cont("Setting 3c5x9/3c5x9B half-duplex mode"); net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */ } outw(net_diag, ioaddr + WN4_NETDIAG); - printk(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info); + pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info); if (el3_debug > 3) - printk("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag); + pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag); /* Enable link beat and jabber check. */ outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA); } @@ -1455,7 +1453,7 @@ el3_suspend(struct device *pdev, pm_message_t state) struct el3_private *lp; int ioaddr; - dev = pdev->driver_data; + dev = dev_get_drvdata(pdev); lp = netdev_priv(dev); ioaddr = dev->base_addr; @@ -1479,7 +1477,7 @@ el3_resume(struct device *pdev) struct el3_private *lp; int ioaddr; - dev = pdev->driver_data; + dev = dev_get_drvdata(pdev); lp = netdev_priv(dev); ioaddr = dev->base_addr; @@ -1539,7 +1537,7 @@ static int __init el3_init_module(void) } if (id_port >= 0x200) { id_port = 0; - printk(KERN_ERR "No I/O port available for 3c509 activation.\n"); + pr_err("No I/O port available for 3c509 activation.\n"); } else { ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS); if (!ret) diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 167bf23066ea..3e00fa8ea65f 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -420,7 +420,7 @@ int init_module(void) if (debug >= 0) corkscrew_debug = debug; if (corkscrew_debug) - printk(version); + pr_debug("%s", version); while (corkscrew_scan(-1)) found++; return found ? 0 : -ENODEV; @@ -437,7 +437,7 @@ struct net_device *tc515_probe(int unit) if (corkscrew_debug > 0 && !printed) { printed = 1; - printk(version); + pr_debug("%s", version); } return dev; @@ -516,7 +516,7 @@ static struct net_device *corkscrew_scan(int unit) if (pnp_device_attach(idev) < 0) continue; if (pnp_activate_dev(idev) < 0) { - printk("pnp activate failed (out of resources?)\n"); + pr_warning("pnp activate failed (out of resources?)\n"); pnp_device_detach(idev); continue; } @@ -531,9 +531,9 @@ static struct net_device *corkscrew_scan(int unit) continue; } if(corkscrew_debug) - printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n", + pr_debug("ISAPNP reports %s at i/o 0x%x, irq %d\n", (char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq); - printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", + pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); /* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */ SET_NETDEV_DEV(dev, &idev->dev); @@ -552,7 +552,7 @@ static struct net_device *corkscrew_scan(int unit) if (!check_device(ioaddr)) continue; - printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", + pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); err = corkscrew_setup(dev, ioaddr, NULL, cards_found++); if (!err) @@ -625,7 +625,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr, list_add(&vp->list, &root_corkscrew_dev); #endif - printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr); + pr_info("%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr); spin_lock_init(&vp->lock); @@ -648,19 +648,19 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr, } checksum = (checksum ^ (checksum >> 8)) & 0xff; if (checksum != 0x00) - printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); - printk(" %pM", dev->dev_addr); + pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum); + pr_cont(" %pM", dev->dev_addr); if (eeprom[16] == 0x11c7) { /* Corkscrew */ if (request_dma(dev->dma, "3c515")) { - printk(", DMA %d allocation failed", dev->dma); + pr_cont(", DMA %d allocation failed", dev->dma); dev->dma = 0; } else - printk(", DMA %d", dev->dma); + pr_cont(", DMA %d", dev->dma); } - printk(", IRQ %d\n", dev->irq); + pr_cont(", IRQ %d\n", dev->irq); /* Tell them about an invalid IRQ. */ if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15)) - printk(KERN_WARNING " *** Warning: this IRQ is unlikely to work! ***\n"); + pr_warning(" *** Warning: this IRQ is unlikely to work! ***\n"); { char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" }; @@ -669,9 +669,9 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr, vp->available_media = inw(ioaddr + Wn3_Options); config = inl(ioaddr + Wn3_Config); if (corkscrew_debug > 1) - printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n", + pr_info(" Internal config register is %4.4x, transceivers %#x.\n", config, inw(ioaddr + Wn3_Options)); - printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", + pr_info(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 8 << config & Ram_size, config & Ram_width ? "word" : "byte", ram_split[(config & Ram_split) >> Ram_split_shift], @@ -682,7 +682,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr, dev->if_port = vp->default_media; } if (vp->media_override != 7) { - printk(KERN_INFO " Media override to transceiver type %d (%s).\n", + pr_info(" Media override to transceiver type %d (%s).\n", vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; @@ -718,7 +718,7 @@ static int corkscrew_open(struct net_device *dev) if (vp->media_override != 7) { if (corkscrew_debug > 1) - printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", + pr_info("%s: Media override to transceiver %d (%s).\n", dev->name, vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; @@ -729,7 +729,7 @@ static int corkscrew_open(struct net_device *dev) dev->if_port = media_tbl[dev->if_port].next; if (corkscrew_debug > 1) - printk("%s: Initial media type %s.\n", + pr_debug("%s: Initial media type %s.\n", dev->name, media_tbl[dev->if_port].name); init_timer(&vp->timer); @@ -744,7 +744,7 @@ static int corkscrew_open(struct net_device *dev) outl(config, ioaddr + Wn3_Config); if (corkscrew_debug > 1) { - printk("%s: corkscrew_open() InternalConfig %8.8x.\n", + pr_debug("%s: corkscrew_open() InternalConfig %8.8x.\n", dev->name, config); } @@ -777,7 +777,7 @@ static int corkscrew_open(struct net_device *dev) if (corkscrew_debug > 1) { EL3WINDOW(4); - printk("%s: corkscrew_open() irq %d media status %4.4x.\n", + pr_debug("%s: corkscrew_open() irq %d media status %4.4x.\n", dev->name, dev->irq, inw(ioaddr + Wn4_Media)); } @@ -814,8 +814,7 @@ static int corkscrew_open(struct net_device *dev) if (vp->full_bus_master_rx) { /* Boomerang bus master. */ vp->cur_rx = vp->dirty_rx = 0; if (corkscrew_debug > 2) - printk("%s: Filling in the Rx ring.\n", - dev->name); + pr_debug("%s: Filling in the Rx ring.\n", dev->name); for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; if (i < (RX_RING_SIZE - 1)) @@ -877,7 +876,7 @@ static void corkscrew_timer(unsigned long data) int ok = 0; if (corkscrew_debug > 1) - printk("%s: Media selection timer tick happened, %s.\n", + pr_debug("%s: Media selection timer tick happened, %s.\n", dev->name, media_tbl[dev->if_port].name); spin_lock_irqsave(&vp->lock, flags); @@ -894,12 +893,12 @@ static void corkscrew_timer(unsigned long data) if (media_status & Media_LnkBeat) { ok = 1; if (corkscrew_debug > 1) - printk("%s: Media %s has link beat, %x.\n", + pr_debug("%s: Media %s has link beat, %x.\n", dev->name, media_tbl[dev->if_port].name, media_status); } else if (corkscrew_debug > 1) - printk("%s: Media %s is has no link beat, %x.\n", + pr_debug("%s: Media %s is has no link beat, %x.\n", dev->name, media_tbl[dev->if_port].name, media_status); @@ -907,7 +906,7 @@ static void corkscrew_timer(unsigned long data) break; default: /* Other media types handled by Tx timeouts. */ if (corkscrew_debug > 1) - printk("%s: Media %s is has no indication, %x.\n", + pr_debug("%s: Media %s is has no indication, %x.\n", dev->name, media_tbl[dev->if_port].name, media_status); @@ -925,12 +924,12 @@ static void corkscrew_timer(unsigned long data) if (dev->if_port == 8) { /* Go back to default. */ dev->if_port = vp->default_media; if (corkscrew_debug > 1) - printk("%s: Media selection failing, using default %s port.\n", + pr_debug("%s: Media selection failing, using default %s port.\n", dev->name, media_tbl[dev->if_port].name); } else { if (corkscrew_debug > 1) - printk("%s: Media selection failed, now trying %s port.\n", + pr_debug("%s: Media selection failed, now trying %s port.\n", dev->name, media_tbl[dev->if_port].name); vp->timer.expires = jiffies + media_tbl[dev->if_port].wait; @@ -953,7 +952,7 @@ static void corkscrew_timer(unsigned long data) spin_unlock_irqrestore(&vp->lock, flags); if (corkscrew_debug > 1) - printk("%s: Media selection timer finished, %s.\n", + pr_debug("%s: Media selection timer finished, %s.\n", dev->name, media_tbl[dev->if_port].name); #endif /* AUTOMEDIA */ @@ -966,23 +965,21 @@ static void corkscrew_timeout(struct net_device *dev) struct corkscrew_private *vp = netdev_priv(dev); int ioaddr = dev->base_addr; - printk(KERN_WARNING - "%s: transmit timed out, tx_status %2.2x status %4.4x.\n", + pr_warning("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", dev->name, inb(ioaddr + TxStatus), inw(ioaddr + EL3_STATUS)); /* Slight code bloat to be user friendly. */ if ((inb(ioaddr + TxStatus) & 0x88) == 0x88) - printk(KERN_WARNING - "%s: Transmitter encountered 16 collisions -- network" + pr_warning("%s: Transmitter encountered 16 collisions --" " network cable problem?\n", dev->name); #ifndef final_version - printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n", + pr_debug(" Flags; bus-master %d, full %d; dirty %d current %d.\n", vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx); - printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr), + pr_debug(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr), &vp->tx_ring[0]); for (i = 0; i < TX_RING_SIZE; i++) { - printk(" %d: %p length %8.8x status %8.8x\n", i, + pr_debug(" %d: %p length %8.8x status %8.8x\n", i, &vp->tx_ring[i], vp->tx_ring[i].length, vp->tx_ring[i].status); } @@ -1017,13 +1014,13 @@ static int corkscrew_start_xmit(struct sk_buff *skb, int i; if (vp->tx_full) /* No room to transmit with */ - return 1; + return NETDEV_TX_BUSY; if (vp->cur_tx != 0) prev_entry = &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE]; else prev_entry = NULL; if (corkscrew_debug > 3) - printk("%s: Trying to send a packet, Tx index %d.\n", + pr_debug("%s: Trying to send a packet, Tx index %d.\n", dev->name, vp->cur_tx); /* vp->tx_full = 1; */ vp->tx_skbuff[entry] = skb; @@ -1102,7 +1099,7 @@ static int corkscrew_start_xmit(struct sk_buff *skb, while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ if (corkscrew_debug > 2) - printk("%s: Tx error, status %2.2x.\n", + pr_debug("%s: Tx error, status %2.2x.\n", dev->name, tx_status); if (tx_status & 0x04) dev->stats.tx_fifo_errors++; @@ -1143,7 +1140,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) status = inw(ioaddr + EL3_STATUS); if (corkscrew_debug > 4) - printk("%s: interrupt, status %4.4x, timer %d.\n", + pr_debug("%s: interrupt, status %4.4x, timer %d.\n", dev->name, status, latency); if ((status & 0xE000) != 0xE000) { static int donedidthis; @@ -1151,7 +1148,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) Ignore a single early interrupt, but don't hang the machine for other interrupt problems. */ if (donedidthis++ > 100) { - printk(KERN_ERR "%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", + pr_err("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", dev->name, status, netif_running(dev)); free_irq(dev->irq, dev); dev->irq = -1; @@ -1160,14 +1157,14 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) do { if (corkscrew_debug > 5) - printk("%s: In interrupt loop, status %4.4x.\n", + pr_debug("%s: In interrupt loop, status %4.4x.\n", dev->name, status); if (status & RxComplete) corkscrew_rx(dev); if (status & TxAvailable) { if (corkscrew_debug > 5) - printk(" TX room bit was handled.\n"); + pr_debug(" TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue(dev); @@ -1212,19 +1209,20 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) if (status & StatsFull) { /* Empty statistics. */ static int DoneDidThat; if (corkscrew_debug > 4) - printk("%s: Updating stats.\n", dev->name); + pr_debug("%s: Updating stats.\n", dev->name); update_stats(ioaddr, dev); /* DEBUG HACK: Disable statistics as an interrupt source. */ /* This occurs when we have the wrong media type! */ if (DoneDidThat == 0 && inw(ioaddr + EL3_STATUS) & StatsFull) { int win, reg; - printk("%s: Updating stats failed, disabling stats as an" - " interrupt source.\n", dev->name); + pr_notice("%s: Updating stats failed, disabling stats as an interrupt source.\n", + dev->name); for (win = 0; win < 8; win++) { EL3WINDOW(win); - printk("\n Vortex window %d:", win); + pr_notice("Vortex window %d:", win); for (reg = 0; reg < 16; reg++) - printk(" %2.2x", inb(ioaddr + reg)); + pr_cont(" %2.2x", inb(ioaddr + reg)); + pr_cont("\n"); } EL3WINDOW(7); outw(SetIntrEnb | TxAvailable | @@ -1246,9 +1244,8 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) } if (--i < 0) { - printk(KERN_ERR "%s: Too much work in interrupt, status %4.4x. " - "Disabling functions (%4.4x).\n", dev->name, - status, SetStatusEnb | ((~status) & 0x7FE)); + pr_err("%s: Too much work in interrupt, status %4.4x. Disabling functions (%4.4x).\n", + dev->name, status, SetStatusEnb | ((~status) & 0x7FE)); /* Disable all pending interrupts. */ outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD); outw(AckIntr | 0x7FF, ioaddr + EL3_CMD); @@ -1262,7 +1259,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) spin_unlock(&lp->lock); if (corkscrew_debug > 4) - printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status); + pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status); return IRQ_HANDLED; } @@ -1273,13 +1270,13 @@ static int corkscrew_rx(struct net_device *dev) short rx_status; if (corkscrew_debug > 5) - printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", + pr_debug(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus)); while ((rx_status = inw(ioaddr + RxStatus)) > 0) { if (rx_status & 0x4000) { /* Error, update stats. */ unsigned char rx_error = inb(ioaddr + RxErrors); if (corkscrew_debug > 2) - printk(" Rx error: status %2.2x.\n", + pr_debug(" Rx error: status %2.2x.\n", rx_error); dev->stats.rx_errors++; if (rx_error & 0x01) @@ -1299,7 +1296,7 @@ static int corkscrew_rx(struct net_device *dev) skb = dev_alloc_skb(pkt_len + 5 + 2); if (corkscrew_debug > 4) - printk("Receiving packet size %d status %4.4x.\n", + pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); if (skb != NULL) { skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ @@ -1318,7 +1315,7 @@ static int corkscrew_rx(struct net_device *dev) break; continue; } else if (corkscrew_debug) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len); + pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len); } outw(RxDiscard, ioaddr + EL3_CMD); dev->stats.rx_dropped++; @@ -1338,13 +1335,13 @@ static int boomerang_rx(struct net_device *dev) int rx_status; if (corkscrew_debug > 5) - printk(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n", + pr_debug(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n", inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus)); while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) { if (rx_status & RxDError) { /* Error, update stats. */ unsigned char rx_error = rx_status >> 16; if (corkscrew_debug > 2) - printk(" Rx error: status %2.2x.\n", + pr_debug(" Rx error: status %2.2x.\n", rx_error); dev->stats.rx_errors++; if (rx_error & 0x01) @@ -1364,7 +1361,7 @@ static int boomerang_rx(struct net_device *dev) dev->stats.rx_bytes += pkt_len; if (corkscrew_debug > 4) - printk("Receiving packet size %d status %4.4x.\n", + pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); /* Check if the packet is long enough to just accept without @@ -1385,7 +1382,7 @@ static int boomerang_rx(struct net_device *dev) temp = skb_put(skb, pkt_len); /* Remove this checking code for final release. */ if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp) - printk("%s: Warning -- the skbuff addresses do not match" + pr_warning("%s: Warning -- the skbuff addresses do not match" " in boomerang_rx: %p vs. %p / %p.\n", dev->name, isa_bus_to_virt(vp-> @@ -1427,12 +1424,11 @@ static int corkscrew_close(struct net_device *dev) netif_stop_queue(dev); if (corkscrew_debug > 1) { - printk("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n", + pr_debug("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n", dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); - printk("%s: corkscrew close stats: rx_nocopy %d rx_copy %d" - " tx_queued %d.\n", dev->name, rx_nocopy, rx_copy, - queued_packet); + pr_debug("%s: corkscrew close stats: rx_nocopy %d rx_copy %d tx_queued %d.\n", + dev->name, rx_nocopy, rx_copy, queued_packet); } del_timer(&vp->timer); @@ -1534,7 +1530,7 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { if (corkscrew_debug > 3) - printk("%s: Setting promiscuous mode.\n", + pr_debug("%s: Setting promiscuous mode.\n", dev->name); new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm; } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 8f734d74b513..cdd955c4014c 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -176,7 +176,7 @@ sizeof(nop_cmd) = 8; if(!p->scb->cmd) break; \ DELAY_16(); \ if(i == 1023) { \ - printk(KERN_WARNING "%s:%d: scb_cmd timed out .. resetting i82586\n",\ + pr_warning("%s:%d: scb_cmd timed out .. resetting i82586\n",\ dev->name,__LINE__); \ elmc_id_reset586(); } } } @@ -291,7 +291,7 @@ static int elmc_open(struct net_device *dev) ret = request_irq(dev->irq, &elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (ret) { - printk(KERN_ERR "%s: couldn't get irq %d\n", dev->name, dev->irq); + pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq); elmc_id_reset586(); return ret; } @@ -371,9 +371,9 @@ static void alloc586(struct net_device *dev) DELAY(2); - if (p->iscp->busy) { - printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name); - } + if (p->iscp->busy) + pr_err("%s: Init-Problems (alloc).\n", dev->name); + memset((char *) p->scb, 0, sizeof(struct scb_struct)); } @@ -470,7 +470,7 @@ static int __init do_elmc_probe(struct net_device *dev) mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev); /* if we get this far, adapter has been found - carry on */ - printk(KERN_INFO "%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); + pr_info("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); /* Now we extract configuration info from the card. The 3c523 provides information in two of the POS registers, but @@ -507,7 +507,7 @@ static int __init do_elmc_probe(struct net_device *dev) memset(pr, 0, sizeof(struct priv)); pr->slot = slot; - printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, + pr_info("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, dev->base_addr); /* Determine if we're using the on-board transceiver (i.e. coax) or @@ -529,7 +529,7 @@ static int __init do_elmc_probe(struct net_device *dev) size = 0x4000; /* check for 16K mem */ if (!check586(dev, dev->mem_start, size)) { - printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, + pr_err("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, dev->mem_start); retval = -ENODEV; goto err_out; @@ -546,7 +546,7 @@ static int __init do_elmc_probe(struct net_device *dev) pr->num_recv_buffs = NUM_RECV_BUFFS_16; /* dump all the assorted information */ - printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, + pr_info("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, dev->irq, dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end - 1); @@ -555,7 +555,7 @@ static int __init do_elmc_probe(struct net_device *dev) for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(dev->base_addr + i); - printk(KERN_INFO "%s: hardware address %pM\n", + pr_info("%s: hardware address %pM\n", dev->name, dev->dev_addr); dev->netdev_ops = &netdev_ops; @@ -660,7 +660,7 @@ static int init586(struct net_device *dev) } if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) { - printk(KERN_WARNING "%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); + pr_warning("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); return 1; } /* @@ -686,7 +686,8 @@ static int init586(struct net_device *dev) } if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) { - printk(KERN_WARNING "%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status); + pr_warning("%s (elmc): individual address setup command failed: %04x\n", + dev->name, ias_cmd->cmd_status); return 1; } /* @@ -707,7 +708,7 @@ static int init586(struct net_device *dev) s = jiffies; while (!(tdr_cmd->cmd_status & STAT_COMPL)) { if (time_after(jiffies, s + 30*HZ/100)) { - printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__); + pr_warning("%s: %d Problems while running the TDR.\n", dev->name, __LINE__); result = 1; break; } @@ -723,14 +724,14 @@ static int init586(struct net_device *dev) if (result & TDR_LNK_OK) { /* empty */ } else if (result & TDR_XCVR_PRB) { - printk(KERN_WARNING "%s: TDR: Transceiver problem!\n", dev->name); + pr_warning("%s: TDR: Transceiver problem!\n", dev->name); } else if (result & TDR_ET_OPN) { - printk(KERN_WARNING "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); + pr_warning("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else if (result & TDR_ET_SRT) { if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ - printk(KERN_WARNING "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); + pr_warning("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else { - printk(KERN_WARNING "%s: TDR: Unknown status %04x\n", dev->name, result); + pr_warning("%s: TDR: Unknown status %04x\n", dev->name, result); } } /* @@ -774,11 +775,11 @@ static int init586(struct net_device *dev) /* I don't understand this: do we really need memory after the init? */ int len = ((char *) p->iscp - (char *) ptr - 8) / 6; if (len <= 0) { - printk(KERN_ERR "%s: Ooooops, no memory for MC-Setup!\n", dev->name); + pr_err("%s: Ooooops, no memory for MC-Setup!\n", dev->name); } else { if (len < num_addrs) { num_addrs = len; - printk(KERN_WARNING "%s: Sorry, can only apply %d MC-Address(es).\n", + pr_warning("%s: Sorry, can only apply %d MC-Address(es).\n", dev->name, num_addrs); } mc_cmd = (struct mcsetup_cmd_struct *) ptr; @@ -799,7 +800,7 @@ static int init586(struct net_device *dev) break; } if (!(mc_cmd->cmd_status & STAT_COMPL)) { - printk(KERN_WARNING "%s: Can't apply multicast-address-list.\n", dev->name); + pr_warning("%s: Can't apply multicast-address-list.\n", dev->name); } } } @@ -812,7 +813,7 @@ static int init586(struct net_device *dev) p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */ ptr = (char *) ptr + sizeof(struct tbd_struct); if ((void *) ptr > (void *) p->iscp) { - printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name); + pr_err("%s: not enough shared-mem for your configuration!\n", dev->name); return 1; } memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct)); @@ -936,7 +937,8 @@ elmc_interrupt(int irq, void *dev_id) if (stat & STAT_CNA) { /* CU went 'not ready' */ if (netif_running(dev)) { - printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); + pr_warning("%s: oops! CU has left active state. stat: %04x/%04x.\n", + dev->name, (int) stat, (int) p->scb->status); } } #endif @@ -951,7 +953,8 @@ elmc_interrupt(int irq, void *dev_id) p->scb->cmd = RUC_RESUME; elmc_attn586(); } else { - printk(KERN_WARNING "%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); + pr_warning("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", + dev->name, (int) stat, (int) p->scb->status); elmc_rnr_int(dev); } } @@ -995,11 +998,11 @@ static void elmc_rcv_int(struct net_device *dev) dev->stats.rx_dropped++; } } else { - printk(KERN_WARNING "%s: received oversized frame.\n", dev->name); + pr_warning("%s: received oversized frame.\n", dev->name); dev->stats.rx_dropped++; } } else { /* frame !(ok), only with 'save-bad-frames' */ - printk(KERN_WARNING "%s: oops! rfd-error-status: %04x\n", dev->name, status); + pr_warning("%s: oops! rfd-error-status: %04x\n", dev->name, status); dev->stats.rx_errors++; } p->rfd_top->status = 0; @@ -1028,7 +1031,7 @@ static void elmc_rnr_int(struct net_device *dev) alloc_rfa(dev, (char *) p->rfd_first); startrecv586(dev); /* restart RU */ - printk(KERN_WARNING "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status); + pr_warning("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status); } @@ -1043,7 +1046,7 @@ static void elmc_xmt_int(struct net_device *dev) status = p->xmit_cmds[p->xmit_last]->cmd_status; if (!(status & STAT_COMPL)) { - printk(KERN_WARNING "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); + pr_warning("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); } if (status & STAT_OK) { dev->stats.tx_packets++; @@ -1051,18 +1054,18 @@ static void elmc_xmt_int(struct net_device *dev) } else { dev->stats.tx_errors++; if (status & TCMD_LATECOLL) { - printk(KERN_WARNING "%s: late collision detected.\n", dev->name); + pr_warning("%s: late collision detected.\n", dev->name); dev->stats.collisions++; } else if (status & TCMD_NOCARRIER) { dev->stats.tx_carrier_errors++; - printk(KERN_WARNING "%s: no carrier detected.\n", dev->name); + pr_warning("%s: no carrier detected.\n", dev->name); } else if (status & TCMD_LOSTCTS) { - printk(KERN_WARNING "%s: loss of CTS detected.\n", dev->name); + pr_warning("%s: loss of CTS detected.\n", dev->name); } else if (status & TCMD_UNDERRUN) { dev->stats.tx_fifo_errors++; - printk(KERN_WARNING "%s: DMA underrun detected.\n", dev->name); + pr_warning("%s: DMA underrun detected.\n", dev->name); } else if (status & TCMD_MAXCOLL) { - printk(KERN_WARNING "%s: Max. collisions exceeded.\n", dev->name); + pr_warning("%s: Max. collisions exceeded.\n", dev->name); dev->stats.collisions += 16; } } @@ -1099,10 +1102,11 @@ static void elmc_timeout(struct net_device *dev) struct priv *p = netdev_priv(dev); /* COMMAND-UNIT active? */ if (p->scb->status & CU_ACTIVE) { -#ifdef DEBUG - printk("%s: strange ... timeout with CU active?!?\n", dev->name); - printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point); -#endif + pr_debug("%s: strange ... timeout with CU active?!?\n", dev->name); + pr_debug("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, + (int)p->xmit_cmds[0]->cmd_status, + (int)p->nop_cmds[0]->cmd_status, + (int)p->nop_cmds[1]->cmd_status, (int)p->nop_point); p->scb->cmd = CUC_ABORT; elmc_attn586(); WAIT_4_SCB_CMD(); @@ -1112,10 +1116,10 @@ static void elmc_timeout(struct net_device *dev) WAIT_4_SCB_CMD(); netif_wake_queue(dev); } else { -#ifdef DEBUG - printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status); - printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status); -#endif + pr_debug("%s: xmitter timed out, try to restart! stat: %04x\n", + dev->name, p->scb->status); + pr_debug("%s: command-stats: %04x %04x\n", dev->name, + p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status); elmc_close(dev); elmc_open(dev); } @@ -1162,7 +1166,7 @@ static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev) break; } if (i == 15) { - printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name); + pr_warning("%s: Can't start transmit-command.\n", dev->name); } } #else @@ -1287,11 +1291,12 @@ int __init init_module(void) free_netdev(dev); if (io[this_dev]==0) break; - printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); + pr_warning("3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); } if(found==0) { - if(io[0]==0) printk(KERN_NOTICE "3c523.c: No 3c523 cards found\n"); + if (io[0]==0) + pr_notice("3c523.c: No 3c523 cards found\n"); return -ENXIO; } else return 0; } diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index b61073c42bf8..aaa8a9f405d4 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -125,8 +125,6 @@ static const char* cardname = DRV_NAME; #define NET_DEBUG 2 #endif -#undef DEBUG_IRQ - static unsigned int mc32_debug = NET_DEBUG; /* The number of low I/O ports used by the ethercard. */ @@ -351,15 +349,15 @@ static int __init mc32_probe1(struct net_device *dev, int slot) /* Time to play MCA games */ if (mc32_debug && version_printed++ == 0) - printk(KERN_DEBUG "%s", version); + pr_debug("%s", version); - printk(KERN_INFO "%s: %s found in slot %d:", dev->name, cardname, slot); + pr_info("%s: %s found in slot %d: ", dev->name, cardname, slot); POS = mca_read_stored_pos(slot, 2); if(!(POS&1)) { - printk(" disabled.\n"); + pr_cont("disabled.\n"); return -ENODEV; } @@ -370,7 +368,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) POS = mca_read_stored_pos(slot, 4); if(!(POS&1)) { - printk("memory window disabled.\n"); + pr_cont("memory window disabled.\n"); return -ENODEV; } @@ -379,7 +377,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) i=(POS>>4)&3; if(i==3) { - printk("invalid memory window.\n"); + pr_cont("invalid memory window.\n"); return -ENODEV; } @@ -392,11 +390,11 @@ static int __init mc32_probe1(struct net_device *dev, int slot) if(!request_region(dev->base_addr, MC32_IO_EXTENT, cardname)) { - printk("io 0x%3lX, which is busy.\n", dev->base_addr); + pr_cont("io 0x%3lX, which is busy.\n", dev->base_addr); return -EBUSY; } - printk("io 0x%3lX irq %d mem 0x%lX (%dK)\n", + pr_cont("io 0x%3lX irq %d mem 0x%lX (%dK)\n", dev->base_addr, dev->irq, dev->mem_start, i/1024); @@ -416,7 +414,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) dev->dev_addr[i] = mca_read_pos(slot,3); } - printk("%s: Address %pM", dev->name, dev->dev_addr); + pr_info("%s: Address %pM ", dev->name, dev->dev_addr); mca_write_pos(slot, 6, 0); mca_write_pos(slot, 7, 0); @@ -424,9 +422,9 @@ static int __init mc32_probe1(struct net_device *dev, int slot) POS = mca_read_stored_pos(slot, 4); if(POS&2) - printk(" : BNC port selected.\n"); + pr_cont(": BNC port selected.\n"); else - printk(" : AUI port selected.\n"); + pr_cont(": AUI port selected.\n"); POS=inb(dev->base_addr+HOST_CTRL); POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET; @@ -447,7 +445,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) err = request_irq(dev->irq, &mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev); if (err) { release_region(dev->base_addr, MC32_IO_EXTENT); - printk(KERN_ERR "%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq); + pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq); goto err_exit_ports; } @@ -463,7 +461,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) i++; if(i == 1000) { - printk(KERN_ERR "%s: failed to boot adapter.\n", dev->name); + pr_err("%s: failed to boot adapter.\n", dev->name); err = -ENODEV; goto err_exit_irq; } @@ -475,10 +473,10 @@ static int __init mc32_probe1(struct net_device *dev, int slot) if(base>0) { if(base < 0x0C) - printk(KERN_ERR "%s: %s%s.\n", dev->name, failures[base-1], + pr_err("%s: %s%s.\n", dev->name, failures[base-1], base<0x0A?" test failure":""); else - printk(KERN_ERR "%s: unknown failure %d.\n", dev->name, base); + pr_err("%s: unknown failure %d.\n", dev->name, base); err = -ENODEV; goto err_exit_irq; } @@ -494,7 +492,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) udelay(50); if(n>100) { - printk(KERN_ERR "%s: mailbox read fail (%d).\n", dev->name, i); + pr_err("%s: mailbox read fail (%d).\n", dev->name, i); err = -ENODEV; goto err_exit_irq; } @@ -527,7 +525,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) init_completion(&lp->execution_cmd); init_completion(&lp->xceiver_cmd); - printk("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n", + pr_info("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n", dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base); dev->netdev_ops = &netdev_ops; @@ -939,7 +937,7 @@ static int mc32_open(struct net_device *dev) */ if(mc32_command(dev, 8, descnumbuffs, 4)) { - printk("%s: %s rejected our buffer configuration!\n", + pr_info("%s: %s rejected our buffer configuration!\n", dev->name, cardname); mc32_close(dev); return -ENOBUFS; @@ -995,7 +993,7 @@ static int mc32_open(struct net_device *dev) static void mc32_timeout(struct net_device *dev) { - printk(KERN_WARNING "%s: transmit timed out?\n", dev->name); + pr_warning("%s: transmit timed out?\n", dev->name); /* Try to restart the adaptor. */ netif_wake_queue(dev); } @@ -1032,7 +1030,7 @@ static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); if(atomic_read(&lp->tx_count)==0) { - return 1; + return NETDEV_TX_BUSY; } if (skb_padto(skb, ETH_ZLEN)) { @@ -1335,11 +1333,9 @@ static irqreturn_t mc32_interrupt(int irq, void *dev_id) { status=inb(ioaddr+HOST_CMD); -#ifdef DEBUG_IRQ - printk("Status TX%d RX%d EX%d OV%d BC%d\n", + pr_debug("Status TX%d RX%d EX%d OV%d BC%d\n", (status&7), (status>>3)&7, (status>>6)&1, (status>>7)&1, boguscount); -#endif switch(status&7) { @@ -1354,7 +1350,7 @@ static irqreturn_t mc32_interrupt(int irq, void *dev_id) complete(&lp->xceiver_cmd); break; default: - printk("%s: strange tx ack %d\n", dev->name, status&7); + pr_notice("%s: strange tx ack %d\n", dev->name, status&7); } status>>=3; switch(status&7) @@ -1376,7 +1372,7 @@ static irqreturn_t mc32_interrupt(int irq, void *dev_id) mc32_start_transceiver(dev); break; default: - printk("%s: strange rx ack %d\n", + pr_notice("%s: strange rx ack %d\n", dev->name, status&7); } status>>=3; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c56698402420..c34aee91250b 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -828,14 +828,14 @@ static int vortex_resume(struct pci_dev *pdev) pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) { - printk(KERN_WARNING "%s: Could not enable device \n", + pr_warning("%s: Could not enable device\n", dev->name); return err; } pci_set_master(pdev); if (request_irq(dev->irq, vp->full_bus_master_rx ? &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) { - printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq); + pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq); pci_disable_device(pdev); return -EBUSY; } @@ -894,7 +894,7 @@ static int __devexit vortex_eisa_remove(struct device *device) dev = eisa_get_drvdata(edev); if (!dev) { - printk("vortex_eisa_remove called for Compaq device!\n"); + pr_err("vortex_eisa_remove called for Compaq device!\n"); BUG(); } @@ -1051,7 +1051,7 @@ static int __devinit vortex_probe1(struct device *gendev, struct eisa_device *edev = NULL; if (!printed_version) { - printk (version); + pr_info("%s", version); printed_version = 1; } @@ -1068,7 +1068,7 @@ static int __devinit vortex_probe1(struct device *gendev, dev = alloc_etherdev(sizeof(*vp)); retval = -ENOMEM; if (!dev) { - printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n"); + pr_err(PFX "unable to allocate etherdev, aborting\n"); goto out; } SET_NETDEV_DEV(dev, gendev); @@ -1100,9 +1100,9 @@ static int __devinit vortex_probe1(struct device *gendev, print_info = (vortex_debug > 1); if (print_info) - printk (KERN_INFO "See Documentation/networking/vortex.txt\n"); + pr_info("See Documentation/networking/vortex.txt\n"); - printk(KERN_INFO "%s: 3Com %s %s at %p.\n", + pr_info("%s: 3Com %s %s at %p.\n", print_name, pdev ? "PCI" : "EISA", vci->name, @@ -1144,10 +1144,9 @@ static int __devinit vortex_probe1(struct device *gendev, chip only. */ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < new_latency) { - printk(KERN_INFO "%s: Overriding PCI latency" - " timer (CFLT) setting of %d, new value is %d.\n", + pr_info("%s: Overriding PCI latency timer (CFLT) setting of %d, new value is %d.\n", print_name, pci_latency, new_latency); - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency); } } } @@ -1236,17 +1235,17 @@ static int __devinit vortex_probe1(struct device *gendev, checksum = (checksum ^ (checksum >> 8)) & 0xff; } if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO)) - printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); + pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum); for (i = 0; i < 3; i++) ((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); if (print_info) - printk(" %pM", dev->dev_addr); + pr_cont(" %pM", dev->dev_addr); /* Unfortunately an all zero eeprom passes the checksum and this gets found in the wild in failure cases. Crypto is hard 8) */ if (!is_valid_ether_addr(dev->dev_addr)) { retval = -EINVAL; - printk(KERN_ERR "*** EEPROM MAC address is invalid.\n"); + pr_err("*** EEPROM MAC address is invalid.\n"); goto free_ring; /* With every pack */ } EL3WINDOW(2); @@ -1254,17 +1253,17 @@ static int __devinit vortex_probe1(struct device *gendev, iowrite8(dev->dev_addr[i], ioaddr + i); if (print_info) - printk(", IRQ %d\n", dev->irq); + pr_cont(", IRQ %d\n", dev->irq); /* Tell them about an invalid IRQ. */ if (dev->irq <= 0 || dev->irq >= nr_irqs) - printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", + pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n", dev->irq); EL3WINDOW(4); step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; if (print_info) { - printk(KERN_INFO " product code %02x%02x rev %02x.%d date %02d-" - "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], + pr_info(" product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n", + eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9); } @@ -1279,8 +1278,7 @@ static int __devinit vortex_probe1(struct device *gendev, } if (print_info) { - printk(KERN_INFO "%s: CardBus functions mapped " - "%16.16llx->%p\n", + pr_info("%s: CardBus functions mapped %16.16llx->%p\n", print_name, (unsigned long long)pci_resource_start(pdev, 2), vp->cb_fn_base); @@ -1307,7 +1305,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (vp->info1 & 0x8000) { vp->full_duplex = 1; if (print_info) - printk(KERN_INFO "Full duplex capable\n"); + pr_info("Full duplex capable\n"); } { @@ -1319,9 +1317,9 @@ static int __devinit vortex_probe1(struct device *gendev, vp->available_media = 0x40; config = ioread32(ioaddr + Wn3_Config); if (print_info) { - printk(KERN_DEBUG " Internal config register is %4.4x, " - "transceivers %#x.\n", config, ioread16(ioaddr + Wn3_Options)); - printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", + pr_debug(" Internal config register is %4.4x, transceivers %#x.\n", + config, ioread16(ioaddr + Wn3_Options)); + pr_info(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 8 << RAM_SIZE(config), RAM_WIDTH(config) ? "word" : "byte", ram_split[RAM_SPLIT(config)], @@ -1336,7 +1334,7 @@ static int __devinit vortex_probe1(struct device *gendev, } if (vp->media_override != 7) { - printk(KERN_INFO "%s: Media override to transceiver type %d (%s).\n", + pr_info("%s: Media override to transceiver type %d (%s).\n", print_name, vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; @@ -1369,8 +1367,8 @@ static int __devinit vortex_probe1(struct device *gendev, if (mii_status && mii_status != 0xffff) { vp->phys[phy_idx++] = phyx; if (print_info) { - printk(KERN_INFO " MII transceiver found at address %d," - " status %4x.\n", phyx, mii_status); + pr_info(" MII transceiver found at address %d, status %4x.\n", + phyx, mii_status); } if ((mii_status & 0x0040) == 0) mii_preamble_required++; @@ -1378,7 +1376,7 @@ static int __devinit vortex_probe1(struct device *gendev, } mii_preamble_required--; if (phy_idx == 0) { - printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n"); + pr_warning(" ***WARNING*** No MII transceivers found!\n"); vp->phys[0] = 24; } else { vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE); @@ -1394,7 +1392,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (vp->capabilities & CapBusMaster) { vp->full_bus_master_tx = 1; if (print_info) { - printk(KERN_INFO " Enabling bus-master transmits and %s receives.\n", + pr_info(" Enabling bus-master transmits and %s receives.\n", (vp->info2 & 1) ? "early" : "whole-frame" ); } vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2; @@ -1414,7 +1412,7 @@ static int __devinit vortex_probe1(struct device *gendev, dev->netdev_ops = &vortex_netdev_ops; if (print_info) { - printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums %sabled\n", + pr_info("%s: scatter/gather %sabled. h/w checksums %sabled\n", print_name, (dev->features & NETIF_F_SG) ? "en":"dis", (dev->features & NETIF_F_IP_CSUM) ? "en":"dis"); @@ -1442,7 +1440,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (vp->must_free_region) release_region(dev->base_addr, vci->io_size); free_netdev(dev); - printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval); + pr_err(PFX "vortex_probe1 fails. Returns %d\n", retval); out: return retval; } @@ -1464,13 +1462,13 @@ issue_and_wait(struct net_device *dev, int cmd) for (i = 0; i < 100000; i++) { if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) { if (vortex_debug > 1) - printk(KERN_INFO "%s: command 0x%04x took %d usecs\n", + pr_info("%s: command 0x%04x took %d usecs\n", dev->name, cmd, i * 10); return; } udelay(10); } - printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n", + pr_err("%s: command 0x%04x did not complete! Status=0x%x\n", dev->name, cmd, ioread16(ioaddr + EL3_STATUS)); } @@ -1480,7 +1478,7 @@ vortex_set_duplex(struct net_device *dev) struct vortex_private *vp = netdev_priv(dev); void __iomem *ioaddr = vp->ioaddr; - printk(KERN_INFO "%s: setting %s-duplex.\n", + pr_info("%s: setting %s-duplex.\n", dev->name, (vp->full_duplex) ? "full" : "half"); EL3WINDOW(3); @@ -1522,7 +1520,7 @@ vortex_up(struct net_device *dev) pci_restore_state(VORTEX_PCI(vp)); err = pci_enable_device(VORTEX_PCI(vp)); if (err) { - printk(KERN_WARNING "%s: Could not enable device \n", + pr_warning("%s: Could not enable device\n", dev->name); goto err_out; } @@ -1533,14 +1531,14 @@ vortex_up(struct net_device *dev) config = ioread32(ioaddr + Wn3_Config); if (vp->media_override != 7) { - printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", + pr_info("%s: Media override to transceiver %d (%s).\n", dev->name, vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; } else if (vp->autoselect) { if (vp->has_nway) { if (vortex_debug > 1) - printk(KERN_INFO "%s: using NWAY device table, not %d\n", + pr_info("%s: using NWAY device table, not %d\n", dev->name, dev->if_port); dev->if_port = XCVR_NWAY; } else { @@ -1549,13 +1547,13 @@ vortex_up(struct net_device *dev) while (! (vp->available_media & media_tbl[dev->if_port].mask)) dev->if_port = media_tbl[dev->if_port].next; if (vortex_debug > 1) - printk(KERN_INFO "%s: first available media type: %s\n", + pr_info("%s: first available media type: %s\n", dev->name, media_tbl[dev->if_port].name); } } else { dev->if_port = vp->default_media; if (vortex_debug > 1) - printk(KERN_INFO "%s: using default media %s\n", + pr_info("%s: using default media %s\n", dev->name, media_tbl[dev->if_port].name); } @@ -1570,13 +1568,13 @@ vortex_up(struct net_device *dev) vp->rx_oom_timer.function = rx_oom_timer; if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Initial media type %s.\n", + pr_debug("%s: Initial media type %s.\n", dev->name, media_tbl[dev->if_port].name); vp->full_duplex = vp->mii.force_media; config = BFINS(config, dev->if_port, 20, 4); if (vortex_debug > 6) - printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config); + pr_debug("vortex_up(): writing 0x%x to InternalConfig\n", config); iowrite32(config, ioaddr + Wn3_Config); if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { @@ -1602,7 +1600,7 @@ vortex_up(struct net_device *dev) if (vortex_debug > 1) { EL3WINDOW(4); - printk(KERN_DEBUG "%s: vortex_up() irq %d media status %4.4x.\n", + pr_debug("%s: vortex_up() irq %d media status %4.4x.\n", dev->name, dev->irq, ioread16(ioaddr + Wn4_Media)); } @@ -1704,13 +1702,13 @@ vortex_open(struct net_device *dev) /* Use the now-standard shared IRQ implementation. */ if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ? &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev))) { - printk(KERN_ERR "%s: Could not reserve IRQ %d\n", dev->name, dev->irq); + pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq); goto err; } if (vp->full_bus_master_rx) { /* Boomerang bus master. */ if (vortex_debug > 2) - printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name); + pr_debug("%s: Filling in the Rx ring.\n", dev->name); for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1)); @@ -1728,7 +1726,7 @@ vortex_open(struct net_device *dev) } if (i != RX_RING_SIZE) { int j; - printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name); + pr_emerg("%s: no memory for rx ring\n", dev->name); for (j = 0; j < i; j++) { if (vp->rx_skbuff[j]) { dev_kfree_skb(vp->rx_skbuff[j]); @@ -1750,7 +1748,7 @@ vortex_open(struct net_device *dev) free_irq(dev->irq, dev); err: if (vortex_debug > 1) - printk(KERN_ERR "%s: vortex_open() fails: returning %d\n", dev->name, retval); + pr_err("%s: vortex_open() fails: returning %d\n", dev->name, retval); out: return retval; } @@ -1766,9 +1764,9 @@ vortex_timer(unsigned long data) int media_status, old_window; if (vortex_debug > 2) { - printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n", + pr_debug("%s: Media selection timer tick happened, %s.\n", dev->name, media_tbl[dev->if_port].name); - printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo); + pr_debug("dev->watchdog_timeo=%d\n", dev->watchdog_timeo); } disable_irq_lockdep(dev->irq); @@ -1781,12 +1779,12 @@ vortex_timer(unsigned long data) netif_carrier_on(dev); ok = 1; if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n", + pr_debug("%s: Media %s has link beat, %x.\n", dev->name, media_tbl[dev->if_port].name, media_status); } else { netif_carrier_off(dev); if (vortex_debug > 1) { - printk(KERN_DEBUG "%s: Media %s has no link beat, %x.\n", + pr_debug("%s: Media %s has no link beat, %x.\n", dev->name, media_tbl[dev->if_port].name, media_status); } } @@ -1802,7 +1800,7 @@ vortex_timer(unsigned long data) break; default: /* Other media types handled by Tx timeouts. */ if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media %s has no indication, %x.\n", + pr_debug("%s: Media %s has no indication, %x.\n", dev->name, media_tbl[dev->if_port].name, media_status); ok = 1; } @@ -1822,13 +1820,11 @@ vortex_timer(unsigned long data) if (dev->if_port == XCVR_Default) { /* Go back to default. */ dev->if_port = vp->default_media; if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media selection failing, using default " - "%s port.\n", + pr_debug("%s: Media selection failing, using default %s port.\n", dev->name, media_tbl[dev->if_port].name); } else { if (vortex_debug > 1) - printk(KERN_DEBUG "%s: Media selection failed, now trying " - "%s port.\n", + pr_debug("%s: Media selection failed, now trying %s port.\n", dev->name, media_tbl[dev->if_port].name); next_tick = media_tbl[dev->if_port].wait; } @@ -1843,13 +1839,13 @@ vortex_timer(unsigned long data) iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, ioaddr + EL3_CMD); if (vortex_debug > 1) - printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config); + pr_debug("wrote 0x%08x to Wn3_Config\n", config); /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */ } leave_media_alone: if (vortex_debug > 2) - printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n", + pr_debug("%s: Media selection timer finished, %s.\n", dev->name, media_tbl[dev->if_port].name); EL3WINDOW(old_window); @@ -1865,21 +1861,21 @@ static void vortex_tx_timeout(struct net_device *dev) struct vortex_private *vp = netdev_priv(dev); void __iomem *ioaddr = vp->ioaddr; - printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n", + pr_err("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", dev->name, ioread8(ioaddr + TxStatus), ioread16(ioaddr + EL3_STATUS)); EL3WINDOW(4); - printk(KERN_ERR " diagnostics: net %04x media %04x dma %08x fifo %04x\n", + pr_err(" diagnostics: net %04x media %04x dma %08x fifo %04x\n", ioread16(ioaddr + Wn4_NetDiag), ioread16(ioaddr + Wn4_Media), ioread32(ioaddr + PktStatus), ioread16(ioaddr + Wn4_FIFODiag)); /* Slight code bloat to be user friendly. */ if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88) - printk(KERN_ERR "%s: Transmitter encountered 16 collisions --" + pr_err("%s: Transmitter encountered 16 collisions --" " network cable problem?\n", dev->name); if (ioread16(ioaddr + EL3_STATUS) & IntLatch) { - printk(KERN_ERR "%s: Interrupt posted but not delivered --" + pr_err("%s: Interrupt posted but not delivered --" " IRQ blocked by another device?\n", dev->name); /* Bad idea here.. but we might as well handle a few events. */ { @@ -1903,7 +1899,7 @@ static void vortex_tx_timeout(struct net_device *dev) dev->stats.tx_errors++; if (vp->full_bus_master_tx) { - printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", dev->name); + pr_debug("%s: Resetting the Tx ring pointer.\n", dev->name); if (vp->cur_tx - vp->dirty_tx > 0 && ioread32(ioaddr + DownListPtr) == 0) iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc), ioaddr + DownListPtr); @@ -1938,7 +1934,7 @@ vortex_error(struct net_device *dev, int status) unsigned char tx_status = 0; if (vortex_debug > 2) { - printk(KERN_ERR "%s: vortex_error(), status=0x%x\n", dev->name, status); + pr_err("%s: vortex_error(), status=0x%x\n", dev->name, status); } if (status & TxComplete) { /* Really "TxError" for us. */ @@ -1946,10 +1942,10 @@ vortex_error(struct net_device *dev, int status) /* Presumably a tx-timeout. We must merely re-enable. */ if (vortex_debug > 2 || (tx_status != 0x88 && vortex_debug > 0)) { - printk(KERN_ERR "%s: Transmit error, Tx status register %2.2x.\n", + pr_err("%s: Transmit error, Tx status register %2.2x.\n", dev->name, tx_status); if (tx_status == 0x82) { - printk(KERN_ERR "Probably a duplex mismatch. See " + pr_err("Probably a duplex mismatch. See " "Documentation/networking/vortex.txt\n"); } dump_tx_ring(dev); @@ -1975,13 +1971,13 @@ vortex_error(struct net_device *dev, int status) if (status & StatsFull) { /* Empty statistics. */ static int DoneDidThat; if (vortex_debug > 4) - printk(KERN_DEBUG "%s: Updating stats.\n", dev->name); + pr_debug("%s: Updating stats.\n", dev->name); update_stats(ioaddr, dev); /* HACK: Disable statistics as an interrupt source. */ /* This occurs when we have the wrong media type! */ if (DoneDidThat == 0 && ioread16(ioaddr + EL3_STATUS) & StatsFull) { - printk(KERN_WARNING "%s: Updating statistics failed, disabling " + pr_warning("%s: Updating statistics failed, disabling " "stats as an interrupt source.\n", dev->name); EL3WINDOW(5); iowrite16(SetIntrEnb | (ioread16(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); @@ -1998,7 +1994,7 @@ vortex_error(struct net_device *dev, int status) u16 fifo_diag; EL3WINDOW(4); fifo_diag = ioread16(ioaddr + Wn4_FIFODiag); - printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n", + pr_err("%s: Host error, FIFO diagnostic register %4.4x.\n", dev->name, fifo_diag); /* Adapter failure requires Tx/Rx reset and reinit. */ if (vp->full_bus_master_tx) { @@ -2006,7 +2002,7 @@ vortex_error(struct net_device *dev, int status) /* 0x80000000 PCI master abort. */ /* 0x40000000 PCI target abort. */ if (vortex_debug) - printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status); + pr_err("%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status); /* In this case, blow the card away */ /* Must not enter D3 or we can't legally issue the reset! */ @@ -2075,7 +2071,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) while (--i > 0 && (tx_status = ioread8(ioaddr + TxStatus)) > 0) { if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ if (vortex_debug > 2) - printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n", + pr_debug("%s: Tx error, status %2.2x.\n", dev->name, tx_status); if (tx_status & 0x04) dev->stats.tx_fifo_errors++; if (tx_status & 0x38) dev->stats.tx_aborted_errors++; @@ -2101,17 +2097,17 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; if (vortex_debug > 6) { - printk(KERN_DEBUG "boomerang_start_xmit()\n"); - printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n", + pr_debug("boomerang_start_xmit()\n"); + pr_debug("%s: Trying to send a packet, Tx index %d.\n", dev->name, vp->cur_tx); } if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { if (vortex_debug > 0) - printk(KERN_WARNING "%s: BUG! Tx Ring full, refusing to send buffer.\n", + pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n", dev->name); netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; } vp->tx_skbuff[entry] = skb; @@ -2204,7 +2200,7 @@ vortex_interrupt(int irq, void *dev_id) status = ioread16(ioaddr + EL3_STATUS); if (vortex_debug > 6) - printk("vortex_interrupt(). status=0x%4x\n", status); + pr_debug("vortex_interrupt(). status=0x%4x\n", status); if ((status & IntLatch) == 0) goto handler_exit; /* No interrupt: shared IRQs cause this */ @@ -2219,19 +2215,19 @@ vortex_interrupt(int irq, void *dev_id) goto handler_exit; if (vortex_debug > 4) - printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", + pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n", dev->name, status, ioread8(ioaddr + Timer)); do { if (vortex_debug > 5) - printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n", + pr_debug("%s: In interrupt loop, status %4.4x.\n", dev->name, status); if (status & RxComplete) vortex_rx(dev); if (status & TxAvailable) { if (vortex_debug > 5) - printk(KERN_DEBUG " TX room bit was handled.\n"); + pr_debug(" TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue (dev); @@ -2263,8 +2259,8 @@ vortex_interrupt(int irq, void *dev_id) } if (--work_done < 0) { - printk(KERN_WARNING "%s: Too much work in interrupt, status " - "%4.4x.\n", dev->name, status); + pr_warning("%s: Too much work in interrupt, status %4.4x.\n", + dev->name, status); /* Disable all pending interrupts. */ do { vp->deferred |= status; @@ -2281,7 +2277,7 @@ vortex_interrupt(int irq, void *dev_id) } while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); if (vortex_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", + pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status); handler_exit: spin_unlock(&vp->lock); @@ -2313,14 +2309,14 @@ boomerang_interrupt(int irq, void *dev_id) status = ioread16(ioaddr + EL3_STATUS); if (vortex_debug > 6) - printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status); + pr_debug("boomerang_interrupt. status=0x%4x\n", status); if ((status & IntLatch) == 0) goto handler_exit; /* No interrupt: shared IRQs can cause this */ if (status == 0xffff) { /* h/w no longer present (hotplug)? */ if (vortex_debug > 1) - printk(KERN_DEBUG "boomerang_interrupt(1): status = 0xffff\n"); + pr_debug("boomerang_interrupt(1): status = 0xffff\n"); goto handler_exit; } @@ -2330,16 +2326,16 @@ boomerang_interrupt(int irq, void *dev_id) } if (vortex_debug > 4) - printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", + pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n", dev->name, status, ioread8(ioaddr + Timer)); do { if (vortex_debug > 5) - printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n", + pr_debug("%s: In interrupt loop, status %4.4x.\n", dev->name, status); if (status & UpComplete) { iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD); if (vortex_debug > 5) - printk(KERN_DEBUG "boomerang_interrupt->boomerang_rx\n"); + pr_debug("boomerang_interrupt->boomerang_rx\n"); boomerang_rx(dev); } @@ -2374,7 +2370,7 @@ boomerang_interrupt(int irq, void *dev_id) dev_kfree_skb_irq(skb); vp->tx_skbuff[entry] = NULL; } else { - printk(KERN_DEBUG "boomerang_interrupt: no skb!\n"); + pr_debug("boomerang_interrupt: no skb!\n"); } /* dev->stats.tx_packets++; Counted below. */ dirty_tx++; @@ -2382,7 +2378,7 @@ boomerang_interrupt(int irq, void *dev_id) vp->dirty_tx = dirty_tx; if (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1) { if (vortex_debug > 6) - printk(KERN_DEBUG "boomerang_interrupt: wake queue\n"); + pr_debug("boomerang_interrupt: wake queue\n"); netif_wake_queue (dev); } } @@ -2392,8 +2388,8 @@ boomerang_interrupt(int irq, void *dev_id) vortex_error(dev, status); if (--work_done < 0) { - printk(KERN_WARNING "%s: Too much work in interrupt, status " - "%4.4x.\n", dev->name, status); + pr_warning("%s: Too much work in interrupt, status %4.4x.\n", + dev->name, status); /* Disable all pending interrupts. */ do { vp->deferred |= status; @@ -2413,7 +2409,7 @@ boomerang_interrupt(int irq, void *dev_id) } while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch); if (vortex_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", + pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status); handler_exit: spin_unlock(&vp->lock); @@ -2428,13 +2424,13 @@ static int vortex_rx(struct net_device *dev) short rx_status; if (vortex_debug > 5) - printk(KERN_DEBUG "vortex_rx(): status %4.4x, rx_status %4.4x.\n", + pr_debug("vortex_rx(): status %4.4x, rx_status %4.4x.\n", ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus)); while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) { if (rx_status & 0x4000) { /* Error, update stats. */ unsigned char rx_error = ioread8(ioaddr + RxErrors); if (vortex_debug > 2) - printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); + pr_debug(" Rx error: status %2.2x.\n", rx_error); dev->stats.rx_errors++; if (rx_error & 0x01) dev->stats.rx_over_errors++; if (rx_error & 0x02) dev->stats.rx_length_errors++; @@ -2448,7 +2444,7 @@ static int vortex_rx(struct net_device *dev) skb = dev_alloc_skb(pkt_len + 5); if (vortex_debug > 4) - printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", + pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); if (skb != NULL) { skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ @@ -2478,8 +2474,8 @@ static int vortex_rx(struct net_device *dev) break; continue; } else if (vortex_debug > 0) - printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of " - "size %d.\n", dev->name, pkt_len); + pr_notice("%s: No memory to allocate a sk_buff of size %d.\n", + dev->name, pkt_len); dev->stats.rx_dropped++; } issue_and_wait(dev, RxDiscard); @@ -2498,7 +2494,7 @@ boomerang_rx(struct net_device *dev) int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx; if (vortex_debug > 5) - printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS)); + pr_debug("boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS)); while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){ if (--rx_work_limit < 0) @@ -2506,7 +2502,7 @@ boomerang_rx(struct net_device *dev) if (rx_status & RxDError) { /* Error, update stats. */ unsigned char rx_error = rx_status >> 16; if (vortex_debug > 2) - printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); + pr_debug(" Rx error: status %2.2x.\n", rx_error); dev->stats.rx_errors++; if (rx_error & 0x01) dev->stats.rx_over_errors++; if (rx_error & 0x02) dev->stats.rx_length_errors++; @@ -2520,7 +2516,7 @@ boomerang_rx(struct net_device *dev) dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr); if (vortex_debug > 4) - printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", + pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); /* Check if the packet is long enough to just accept without @@ -2566,7 +2562,7 @@ boomerang_rx(struct net_device *dev) if (skb == NULL) { static unsigned long last_jif; if (time_after(jiffies, last_jif + 10 * HZ)) { - printk(KERN_WARNING "%s: memory shortage\n", dev->name); + pr_warning("%s: memory shortage\n", dev->name); last_jif = jiffies; } if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE) @@ -2598,7 +2594,7 @@ rx_oom_timer(unsigned long arg) if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE) /* This test is redundant, but makes me feel good */ boomerang_rx(dev); if (vortex_debug > 1) { - printk(KERN_DEBUG "%s: rx_oom_timer %s\n", dev->name, + pr_debug("%s: rx_oom_timer %s\n", dev->name, ((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying"); } spin_unlock_irq(&vp->lock); @@ -2655,9 +2651,9 @@ vortex_close(struct net_device *dev) vortex_down(dev, 1); if (vortex_debug > 1) { - printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n", + pr_debug("%s: vortex_close() status %4.4x, Tx status %2.2x.\n", dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus)); - printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d" + pr_debug("%s: vortex close stats: rx_nocopy %d rx_copy %d" " tx_queued %d Rx pre-checksummed %d.\n", dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits); } @@ -2666,8 +2662,7 @@ vortex_close(struct net_device *dev) if (vp->rx_csumhits && (vp->drv_flags & HAS_HWCKSM) == 0 && (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) { - printk(KERN_WARNING "%s supports hardware checksums, and we're " - "not using them!\n", dev->name); + pr_warning("%s supports hardware checksums, and we're not using them!\n", dev->name); } #endif @@ -2717,16 +2712,16 @@ dump_tx_ring(struct net_device *dev) int i; int stalled = ioread32(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */ - printk(KERN_ERR " Flags; bus-master %d, dirty %d(%d) current %d(%d)\n", + pr_err(" Flags; bus-master %d, dirty %d(%d) current %d(%d)\n", vp->full_bus_master_tx, vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE, vp->cur_tx, vp->cur_tx % TX_RING_SIZE); - printk(KERN_ERR " Transmit list %8.8x vs. %p.\n", + pr_err(" Transmit list %8.8x vs. %p.\n", ioread32(ioaddr + DownListPtr), &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]); issue_and_wait(dev, DownStall); for (i = 0; i < TX_RING_SIZE; i++) { - printk(KERN_ERR " %d: @%p length %8.8x status %8.8x\n", i, + pr_err(" %d: @%p length %8.8x status %8.8x\n", i, &vp->tx_ring[i], #if DO_ZEROCOPY le32_to_cpu(vp->tx_ring[i].frag[0].length), @@ -2970,7 +2965,7 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { if (vortex_debug > 3) - printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name); + pr_notice("%s: Setting promiscuous mode.\n", dev->name); new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; @@ -3145,8 +3140,7 @@ static void acpi_set_WOL(struct net_device *dev) iowrite16(RxEnable, ioaddr + EL3_CMD); if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) { - printk(KERN_INFO "%s: WOL not supported.\n", - pci_name(VORTEX_PCI(vp))); + pr_info("%s: WOL not supported.\n", pci_name(VORTEX_PCI(vp))); vp->enable_wol = 0; return; @@ -3164,7 +3158,7 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev) struct vortex_private *vp; if (!dev) { - printk("vortex_remove_one called for Compaq device!\n"); + pr_err("vortex_remove_one called for Compaq device!\n"); BUG(); } diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 7a331acc34ad..69f5b7d298a6 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -541,7 +541,7 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) unsigned long flags; if (!TX_BUFFS_AVAIL) - return -1; + return NETDEV_TX_LOCKED; netif_stop_queue (dev); diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 02330f3d5a55..50efde11ea6c 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -471,8 +471,7 @@ static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, u32 status, u32 len) { if (netif_msg_rx_err (cp)) - printk (KERN_DEBUG - "%s: rx err, slot %d status 0x%x len %d\n", + pr_debug("%s: rx err, slot %d status 0x%x len %d\n", cp->dev->name, rx_tail, status, len); cp->dev->stats.rx_errors++; if (status & RxErrFrame) @@ -547,7 +546,7 @@ static int cp_rx_poll(struct napi_struct *napi, int budget) } if (netif_msg_rx_status(cp)) - printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n", + pr_debug("%s: rx slot %d status 0x%x len %d\n", dev->name, rx_tail, status, len); buflen = cp->rx_buf_sz + NET_IP_ALIGN; @@ -626,7 +625,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) return IRQ_NONE; if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: intr, status %04x cmd %02x cpcmd %04x\n", + pr_debug("%s: intr, status %04x cmd %02x cpcmd %04x\n", dev->name, status, cpr8(Cmd), cpr16(CpCmd)); cpw16(IntrStatus, status & ~cp_rx_intr_mask); @@ -658,7 +657,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) pci_read_config_word(cp->pdev, PCI_STATUS, &pci_status); pci_write_config_word(cp->pdev, PCI_STATUS, pci_status); - printk(KERN_ERR "%s: PCI bus error, status=%04x, PCI status=%04x\n", + pr_err("%s: PCI bus error, status=%04x, PCI status=%04x\n", dev->name, status, pci_status); /* TODO: reset hardware */ @@ -705,7 +704,7 @@ static void cp_tx (struct cp_private *cp) if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { if (netif_msg_tx_err(cp)) - printk(KERN_DEBUG "%s: tx err, status 0x%x\n", + pr_debug("%s: tx err, status 0x%x\n", cp->dev->name, status); cp->dev->stats.tx_errors++; if (status & TxOWC) @@ -722,7 +721,7 @@ static void cp_tx (struct cp_private *cp) cp->dev->stats.tx_packets++; cp->dev->stats.tx_bytes += skb->len; if (netif_msg_tx_done(cp)) - printk(KERN_DEBUG "%s: tx done, slot %d\n", cp->dev->name, tx_tail); + pr_debug("%s: tx done, slot %d\n", cp->dev->name, tx_tail); } dev_kfree_skb_irq(skb); } @@ -755,9 +754,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); spin_unlock_irqrestore(&cp->lock, intr_flags); - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", + pr_err(PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } #if CP_VLAN_TAG_USED @@ -882,7 +881,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) } cp->tx_head = entry; if (netif_msg_tx_queued(cp)) - printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n", + pr_debug("%s: tx queued, slot %d, skblen %d\n", dev->name, entry, skb->len); if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); @@ -996,7 +995,7 @@ static void cp_reset_hw (struct cp_private *cp) schedule_timeout_uninterruptible(10); } - printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name); + pr_err("%s: hardware reset timeout\n", cp->dev->name); } static inline void cp_start_hw (struct cp_private *cp) @@ -1166,7 +1165,7 @@ static int cp_open (struct net_device *dev) int rc; if (netif_msg_ifup(cp)) - printk(KERN_DEBUG "%s: enabling interface\n", dev->name); + pr_debug("%s: enabling interface\n", dev->name); rc = cp_alloc_rings(cp); if (rc) @@ -1201,7 +1200,7 @@ static int cp_close (struct net_device *dev) napi_disable(&cp->napi); if (netif_msg_ifdown(cp)) - printk(KERN_DEBUG "%s: disabling interface\n", dev->name); + pr_debug("%s: disabling interface\n", dev->name); spin_lock_irqsave(&cp->lock, flags); @@ -1224,7 +1223,7 @@ static void cp_tx_timeout(struct net_device *dev) unsigned long flags; int rc; - printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n", + pr_warning("%s: Transmit timeout, status %2x %4x %4x %4x\n", dev->name, cpr8(Cmd), cpr16(CpCmd), cpr16(IntrStatus), cpr16(IntrMask)); @@ -1873,7 +1872,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) #ifndef MODULE static int version_printed; if (version_printed++ == 0) - printk("%s", version); + pr_info("%s", version); #endif if (pdev->vendor == PCI_VENDOR_ID_REALTEK && @@ -1995,8 +1994,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_iomap; - printk (KERN_INFO "%s: RTL-8139C+ at 0x%lx, " - "%pM, IRQ %d\n", + pr_info("%s: RTL-8139C+ at 0x%lx, %pM, IRQ %d\n", dev->name, dev->base_addr, dev->dev_addr, @@ -2113,7 +2111,7 @@ static struct pci_driver cp_driver = { static int __init cp_init (void) { #ifdef MODULE - printk("%s", version); + pr_info("%s", version); #endif return pci_register_driver(&cp_driver); } diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 1fc45431a620..8ae72ec14456 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -126,19 +126,12 @@ #undef RTL8139_NDEBUG -#if RTL8139_DEBUG -/* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - #ifdef RTL8139_NDEBUG # define assert(expr) do {} while (0) #else # define assert(expr) \ if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ + pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ #expr, __FILE__, __func__, __LINE__); \ } #endif @@ -784,8 +777,8 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) /* set this immediately, we need to know before * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); + pr_debug("PIO region size == 0x%02lX\n", pio_len); + pr_debug("MMIO region size == 0x%02lX\n", mmio_len); retry: if (use_io) { @@ -865,19 +858,17 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) } /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, - "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); + dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); + dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); tp->chipset = 0; match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", + pr_debug("chipset id (%d) == index %d, '%s'\n", version, i, rtl_chip_info[i].name); if (tp->chipset >= CH_8139B) { u8 new_tmp8 = tmp8 = RTL_R8 (Config1); - DPRINTK("PCI PM wakeup\n"); + pr_debug("PCI PM wakeup\n"); if ((rtl_chip_info[tp->chipset].flags & HasLWake) && (tmp8 & LWAKE)) new_tmp8 &= ~LWAKE; @@ -896,7 +887,7 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) } } } else { - DPRINTK("Old chip wakeup\n"); + pr_debug("Old chip wakeup\n"); tmp8 = RTL_R8 (Config1); tmp8 &= ~(SLEEP | PWRDN); RTL_W8 (Config1, tmp8); @@ -949,7 +940,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, { static int printed_version; if (!printed_version++) - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); + pr_info(RTL8139_DRIVER_NAME "\n"); } #endif @@ -965,7 +956,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n"); + pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); use_io = 1; } @@ -1018,21 +1009,20 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, tp->mii.reg_num_mask = 0x1f; /* dev is fully set up and ready to use now */ - DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); + pr_debug("about to register device named %s (%p)...\n", dev->name, dev); i = register_netdev (dev); if (i) goto err_out; pci_set_drvdata (pdev, dev); - printk (KERN_INFO "%s: %s at 0x%lx, " - "%pM, IRQ %d\n", + pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", dev->name, board_info[ent->driver_data].name, dev->base_addr, dev->dev_addr, dev->irq); - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", + pr_debug("%s: Identified 8139 chip type '%s'\n", dev->name, rtl_chip_info[tp->chipset].name); /* Find the connected MII xcvrs. @@ -1046,14 +1036,12 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, if (mii_status != 0xffff && mii_status != 0x0000) { u16 advertising = mdio_read(dev, phy, 4); tp->phys[phy_idx++] = phy; - printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " - "advertising %4.4x.\n", + pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", dev->name, phy, mii_status, advertising); } } if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " - "transceiver.\n", + pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", dev->name); tp->phys[0] = 32; } @@ -1073,13 +1061,13 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) tp->mii.full_duplex = full_duplex[board_idx]; if (tp->mii.full_duplex) { - printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); + pr_info("%s: Media type forced to Full Duplex.\n", dev->name); /* Changing the MII-advertised media because might prevent re-connection. */ tp->mii.force_media = 1; } if (tp->default_port) { - printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", + pr_info(" Forcing %dMbps %s-duplex operation.\n", (option & 0x20 ? 100 : 10), (option & 0x10 ? "full" : "half")); mdio_write(dev, tp->phys[0], 0, @@ -1342,7 +1330,7 @@ static int rtl8139_open (struct net_device *dev) netif_start_queue (dev); if (netif_msg_ifup(tp)) - printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d" + pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" " GP Pins %2.2x %s-duplex.\n", dev->name, (unsigned long long)pci_resource_start (tp->pci_dev, 1), dev->irq, RTL_R8 (MediaStatus), @@ -1404,7 +1392,7 @@ static void rtl8139_hw_start (struct net_device *dev) RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); } - DPRINTK("init buffer addresses\n"); + pr_debug("init buffer addresses\n"); /* Lock Config[01234] and BMCR register writes */ RTL_W8 (Cfg9346, Cfg9346_Lock); @@ -1566,14 +1554,13 @@ static inline void rtl8139_thread_iter (struct net_device *dev, tp->mii.full_duplex = duplex; if (mii_lpa) { - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" + pr_info("%s: Setting %s-duplex based on MII #%d link" " partner ability of %4.4x.\n", dev->name, tp->mii.full_duplex ? "full" : "half", tp->phys[0], mii_lpa); } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", + pr_info("%s: media is unconnected, link down, or incompatible connection\n", dev->name); } #if 0 @@ -1588,11 +1575,11 @@ static inline void rtl8139_thread_iter (struct net_device *dev, rtl8139_tune_twister (dev, tp); - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", + pr_debug("%s: Media selection tick, Link partner %4.4x.\n", dev->name, RTL_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", + pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", + pr_debug("%s: Chip config %2.2x %2.2x.\n", dev->name, RTL_R8 (Config0), RTL_R8 (Config1)); } @@ -1652,14 +1639,14 @@ static void rtl8139_tx_timeout_task (struct work_struct *work) int i; u8 tmp8; - printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " - "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), + pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", + dev->name, RTL_R8 (ChipCmd), RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %ld dirty entry %ld.\n", + pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", dev->name, tp->cur_tx, tp->dirty_tx); for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", + pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); @@ -1741,7 +1728,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&tp->lock, flags); if (netif_msg_tx_queued(tp)) - printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", + pr_debug("%s: Queued Tx packet size %u to slot %d.\n", dev->name, len, entry); return 0; @@ -1772,7 +1759,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev, if (txstatus & (TxOutOfWindow | TxAborted)) { /* There was an major error, log it. */ if (netif_msg_tx_err(tp)) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + pr_debug("%s: Transmit error, Tx status %8.8x.\n", dev->name, txstatus); dev->stats.tx_errors++; if (txstatus & TxAborted) { @@ -1803,7 +1790,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev, #ifndef RTL8139_NDEBUG if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", + pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", dev->name, dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; } @@ -1828,12 +1815,12 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, #endif if (netif_msg_rx_err (tp)) - printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", + pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", dev->name, rx_status); dev->stats.rx_errors++; if (!(rx_status & RxStatusOK)) { if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", + pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", dev->name, rx_status); /* A.C.: The chip hangs here. */ } @@ -1866,7 +1853,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, break; } if (tmp_work <= 0) - printk (KERN_WARNING PFX "rx stop wait too long\n"); + pr_warning(PFX "rx stop wait too long\n"); /* restart receive */ tmp_work = 200; while (--tmp_work > 0) { @@ -1877,7 +1864,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, break; } if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); + pr_warning(PFX "tx/rx enable wait too long\n"); /* and reinitialize all rx related registers */ RTL_W8_F (Cfg9346, Cfg9346_Unlock); @@ -1888,7 +1875,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, RTL_W32 (RxConfig, tp->rx_config); tp->cur_rx = 0; - DPRINTK("init buffer addresses\n"); + pr_debug("init buffer addresses\n"); /* Lock Config[01234] and BMCR register writes */ RTL_W8 (Cfg9346, Cfg9346_Lock); @@ -1942,7 +1929,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, unsigned int cur_rx = tp->cur_rx; unsigned int rx_size = 0; - DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," + pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); @@ -1962,17 +1949,17 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, pkt_size = rx_size - 4; if (netif_msg_rx_status(tp)) - printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," + pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," " cur %4.4x.\n", dev->name, rx_status, rx_size, cur_rx); #if RTL8139_DEBUG > 2 { int i; - DPRINTK ("%s: Frame contents ", dev->name); + pr_debug("%s: Frame contents ", dev->name); for (i = 0; i < 70; i++) - printk (" %2.2x", + pr_cont(" %2.2x", rx_ring[ring_offset + i]); - printk (".\n"); + pr_cont(".\n"); } #endif @@ -1984,12 +1971,12 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, if (!tp->fifo_copy_timeout) tp->fifo_copy_timeout = jiffies + 2; else if (time_after(jiffies, tp->fifo_copy_timeout)) { - DPRINTK ("%s: hung FIFO. Reset.", dev->name); + pr_debug("%s: hung FIFO. Reset.", dev->name); rx_size = 0; goto no_early_rx; } if (netif_msg_intr(tp)) { - printk(KERN_DEBUG "%s: fifo copy in progress.", + pr_debug("%s: fifo copy in progress.", dev->name); } tp->xstats.early_rx++; @@ -2033,8 +2020,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, netif_receive_skb (skb); } else { if (net_ratelimit()) - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", + pr_warning("%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; } @@ -2049,12 +2035,10 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, if (unlikely(!received || rx_size == 0xfff0)) rtl8139_isr_ack(tp); -#if RTL8139_DEBUG > 1 - DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," + pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); -#endif tp->cur_rx = cur_rx; @@ -2075,7 +2059,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev, void __iomem *ioaddr, int status, int link_changed) { - DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", + pr_debug("%s: Abnormal interrupt, status %8.8x.\n", dev->name, status); assert (dev != NULL); @@ -2104,7 +2088,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev, pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", + pr_err("%s: PCI Bus error %4.4x.\n", dev->name, pci_cmd_status); } } @@ -2198,7 +2182,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) out: spin_unlock (&tp->lock); - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", + pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); return IRQ_RETVAL(handled); } @@ -2249,7 +2233,7 @@ static int rtl8139_close (struct net_device *dev) napi_disable(&tp->napi); if (netif_msg_ifdown(tp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", + pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", dev->name, RTL_R16 (IntrStatus)); spin_lock_irqsave (&tp->lock, flags); @@ -2292,11 +2276,11 @@ static int rtl8139_close (struct net_device *dev) other threads or interrupts aren't messing with the 8139. */ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; + struct rtl8139_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { + spin_lock_irq(&tp->lock); + if (rtl_chip_info[tp->chipset].flags & HasLWake) { u8 cfg3 = RTL_R8 (Config3); u8 cfg5 = RTL_R8 (Config5); @@ -2317,7 +2301,7 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (cfg5 & Cfg5_BWF) wol->wolopts |= WAKE_BCAST; } - spin_unlock_irq(&np->lock); + spin_unlock_irq(&tp->lock); } @@ -2326,19 +2310,19 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) aren't messing with the 8139. */ static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; + struct rtl8139_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; u32 support; u8 cfg3, cfg5; - support = ((rtl_chip_info[np->chipset].flags & HasLWake) + support = ((rtl_chip_info[tp->chipset].flags & HasLWake) ? (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) : 0); if (wol->wolopts & ~support) return -EINVAL; - spin_lock_irq(&np->lock); + spin_lock_irq(&tp->lock); cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); if (wol->wolopts & WAKE_PHY) cfg3 |= Cfg3_LinkUp; @@ -2359,87 +2343,87 @@ static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & WAKE_BCAST) cfg5 |= Cfg5_BWF; RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); + spin_unlock_irq(&tp->lock); return 0; } static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; + strcpy(info->bus_info, pci_name(tp->pci_dev)); + info->regdump_len = tp->regs_len; } static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); + struct rtl8139_private *tp = netdev_priv(dev); + spin_lock_irq(&tp->lock); + mii_ethtool_gset(&tp->mii, cmd); + spin_unlock_irq(&tp->lock); return 0; } static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); + spin_lock_irq(&tp->lock); + rc = mii_ethtool_sset(&tp->mii, cmd); + spin_unlock_irq(&tp->lock); return rc; } static int rtl8139_nway_reset(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); + struct rtl8139_private *tp = netdev_priv(dev); + return mii_nway_restart(&tp->mii); } static u32 rtl8139_get_link(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); + struct rtl8139_private *tp = netdev_priv(dev); + return mii_link_ok(&tp->mii); } static u32 rtl8139_get_msglevel(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; + struct rtl8139_private *tp = netdev_priv(dev); + return tp->msg_enable; } static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) { - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; + struct rtl8139_private *tp = netdev_priv(dev); + tp->msg_enable = datum; } static int rtl8139_get_regs_len(struct net_device *dev) { - struct rtl8139_private *np; + struct rtl8139_private *tp; /* TODO: we are too slack to do reg dumping for pio, for now */ if (use_io) return 0; - np = netdev_priv(dev); - return np->regs_len; + tp = netdev_priv(dev); + return tp->regs_len; } static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { - struct rtl8139_private *np; + struct rtl8139_private *tp; /* TODO: we are too slack to do reg dumping for pio, for now */ if (use_io) return; - np = netdev_priv(dev); + tp = netdev_priv(dev); regs->version = RTL_REGS_VER; - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); + spin_lock_irq(&tp->lock); + memcpy_fromio(regbuf, tp->mmio_addr, regs->len); + spin_unlock_irq(&tp->lock); } static int rtl8139_get_sset_count(struct net_device *dev, int sset) @@ -2454,12 +2438,12 @@ static int rtl8139_get_sset_count(struct net_device *dev, int sset) static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; + data[0] = tp->xstats.early_rx; + data[1] = tp->xstats.tx_buf_mapped; + data[2] = tp->xstats.tx_timeouts; + data[3] = tp->xstats.rx_lost_in_ring; } static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -2486,15 +2470,15 @@ static const struct ethtool_ops rtl8139_ethtool_ops = { static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); int rc; if (!netif_running(dev)) return -EINVAL; - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); + spin_lock_irq(&tp->lock); + rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); + spin_unlock_irq(&tp->lock); return rc; } @@ -2527,7 +2511,7 @@ static void __set_rx_mode (struct net_device *dev) int i, rx_mode; u32 tmp; - DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", + pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", dev->name, dev->flags, RTL_R32 (RxConfig)); /* Note: do not reorder, GCC is clever about common statements. */ @@ -2643,7 +2627,7 @@ static int __init rtl8139_init_module (void) * even if no 8139 board is found. */ #ifdef MODULE - printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); + pr_info(RTL8139_DRIVER_NAME "\n"); #endif return pci_register_driver(&rtl8139_pci_driver); diff --git a/drivers/net/82596.c b/drivers/net/82596.c index cca94b9c08ae..77547545509b 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -122,13 +122,13 @@ static char version[] __initdata = #define ISCP_BUSY 0x00010000 #define MACH_IS_APRICOT 0 #else -#define WSWAPrfd(x) ((struct i596_rfd *)(x)) -#define WSWAPrbd(x) ((struct i596_rbd *)(x)) -#define WSWAPiscp(x) ((struct i596_iscp *)(x)) -#define WSWAPscb(x) ((struct i596_scb *)(x)) -#define WSWAPcmd(x) ((struct i596_cmd *)(x)) -#define WSWAPtbd(x) ((struct i596_tbd *)(x)) -#define WSWAPchar(x) ((char *)(x)) +#define WSWAPrfd(x) ((struct i596_rfd *)((long)x)) +#define WSWAPrbd(x) ((struct i596_rbd *)((long)x)) +#define WSWAPiscp(x) ((struct i596_iscp *)((long)x)) +#define WSWAPscb(x) ((struct i596_scb *)((long)x)) +#define WSWAPcmd(x) ((struct i596_cmd *)((long)x)) +#define WSWAPtbd(x) ((struct i596_tbd *)((long)x)) +#define WSWAPchar(x) ((char *)((long)x)) #define ISCP_BUSY 0x0001 #define MACH_IS_APRICOT 1 #endif diff --git a/drivers/net/8390.c b/drivers/net/8390.c index ec3e22e6306f..21153dea8ebe 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -74,14 +74,8 @@ EXPORT_SYMBOL(ei_netdev_ops); struct net_device *__alloc_ei_netdev(int size) { struct net_device *dev = ____alloc_ei_netdev(size); -#ifdef CONFIG_COMPAT_NET_DEV_OPS - if (dev) { - dev->hard_start_xmit = ei_start_xmit; - dev->get_stats = ei_get_stats; - dev->set_multicast_list = ei_set_multicast_list; - dev->tx_timeout = ei_tx_timeout; - } -#endif + if (dev) + dev->netdev_ops = &ei_netdev_ops; return dev; } EXPORT_SYMBOL(__alloc_ei_netdev); diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c index da863c91d1d0..d225c291fd93 100644 --- a/drivers/net/8390p.c +++ b/drivers/net/8390p.c @@ -79,14 +79,8 @@ EXPORT_SYMBOL(eip_netdev_ops); struct net_device *__alloc_eip_netdev(int size) { struct net_device *dev = ____alloc_ei_netdev(size); -#ifdef CONFIG_COMPAT_NET_DEV_OPS - if (dev) { - dev->hard_start_xmit = eip_start_xmit; - dev->get_stats = eip_get_stats; - dev->set_multicast_list = eip_set_multicast_list; - dev->tx_timeout = eip_tx_timeout; - } -#endif + if (dev) + dev->netdev_ops = &eip_netdev_ops; return dev; } EXPORT_SYMBOL(__alloc_eip_netdev); @@ -97,16 +91,15 @@ void NS8390p_init(struct net_device *dev, int startp) } EXPORT_SYMBOL(NS8390p_init); -#if defined(MODULE) - -int init_module(void) +static int __init NS8390p_init_module(void) { return 0; } -void cleanup_module(void) +static void __exit NS8390p_cleanup_module(void) { } -#endif /* MODULE */ +module_init(NS8390p_init_module); +module_exit(NS8390p_cleanup_module); MODULE_LICENSE("GPL"); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3111b6c7cbc3..01f282cd0989 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1,4 +1,3 @@ - # # Network device configuration # @@ -26,15 +25,6 @@ menuconfig NETDEVICES # that for each of the symbols. if NETDEVICES -config COMPAT_NET_DEV_OPS - default y - bool "Enable older network device API compatibility" - ---help--- - This option enables kernel compatibility with older network devices - that do not use net_device_ops interface. - - If unsure, say Y. - config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT @@ -526,15 +516,16 @@ config STNIC config SH_ETH tristate "Renesas SuperH Ethernet support" depends on SUPERH && \ - (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7763 || \ - CPU_SUBTYPE_SH7619) + (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ + CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ + CPU_SUBTYPE_SH7724) select CRC32 select MII select MDIO_BITBANG select PHYLIB help Renesas SuperH Ethernet device driver. - This driver support SH7710, SH7712, SH7763 and SH7619. + This driver support SH7710, SH7712, SH7763, SH7619, and SH7724. config SUNLANCE tristate "Sun LANCE support" @@ -927,6 +918,16 @@ config NET_NETX To compile this driver as a module, choose M here. The module will be called netx-eth. +config TI_DAVINCI_EMAC + tristate "TI DaVinci EMAC Support" + depends on ARM && ARCH_DAVINCI + select PHYLIB + help + This driver supports TI's DaVinci Ethernet . + + To compile this driver as a module, choose M here: the module + will be called davinci_emac_driver. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS @@ -1000,7 +1001,7 @@ config SMC911X config SMSC911X tristate "SMSC LAN911x/LAN921x families embedded ethernet support" - depends on ARM || SUPERH + depends on ARM || SUPERH || BLACKFIN select CRC32 select MII select PHYLIB @@ -1722,6 +1723,11 @@ config TLAN Please email feedback to . +config KS8842 + tristate "Micrel KSZ8842" + help + This platform driver is for Micrel KSZ8842 chip. + config VIA_RHINE tristate "VIA Rhine support" depends on NET_PCI && PCI @@ -1858,8 +1864,8 @@ config 68360_ENET the Motorola 68360 processor. config FEC - bool "FEC ethernet controller (of ColdFire CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 + bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" + depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 help Say Y here if you want to use the built-in 10/100 Fast ethernet controller on some Motorola ColdFire and Freescale i.MX processors. @@ -2362,7 +2368,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "Marvell Discovery (643XX) and Orion ethernet support" - depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION + depends on MV64X60 || PPC32 || PLAT_ORION select INET_LRO select PHYLIB help @@ -2373,6 +2379,14 @@ config MV643XX_ETH Some boards that use the Discovery chipset are the Momenco Ocelot C and Jaguar ATX and Pegasos II. +config XILINX_LL_TEMAC + tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" + select PHYLIB + depends on PPC_DCR_NATIVE + help + This driver supports the Xilinx 10/100/1000 LocalLink TEMAC + core used in Xilinx Spartan and Virtex FPGAs + config QLA3XXX tristate "QLogic QLA3XXX Network Driver Support" depends on PCI @@ -2446,10 +2460,14 @@ menuconfig NETDEV_10000 if NETDEV_10000 +config MDIO + tristate + config CHELSIO_T1 tristate "Chelsio 10Gb Ethernet support" depends on PCI select CRC32 + select MDIO help This driver supports Chelsio gigabit and 10-gigabit Ethernet cards. More information about adapter features and @@ -2482,6 +2500,7 @@ config CHELSIO_T3 tristate "Chelsio Communications T3 10Gb Ethernet support" depends on CHELSIO_T3_DEPENDS select FW_LOADER + select MDIO help This driver supports Chelsio T3-based gigabit and 10Gb Ethernet adapters. @@ -2517,6 +2536,7 @@ config ENIC config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" depends on PCI && INET + select MDIO ---help--- This driver supports Intel(R) 10GbE PCI Express family of adapters. For more information on how to identify your adapter, go @@ -2679,6 +2699,7 @@ config TEHUTI config BNX2X tristate "Broadcom NetXtremeII 10Gb support" depends on PCI + select FW_LOADER select ZLIB_INFLATE select LIBCRC32C help @@ -2715,6 +2736,8 @@ source "drivers/net/wan/Kconfig" source "drivers/atm/Kconfig" +source "drivers/ieee802154/Kconfig" + source "drivers/s390/net/Kconfig" config XEN_NETDEV_FRONTEND diff --git a/drivers/net/Makefile b/drivers/net/Makefile index db30ebd7b262..d366fb2b40e9 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -2,6 +2,8 @@ # Makefile for the Linux network (ethercard) device drivers. # +obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o + obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/ @@ -85,6 +87,7 @@ obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o obj-$(CONFIG_SKFP) += skfp/ +obj-$(CONFIG_KS8842) += ks8842.o obj-$(CONFIG_VIA_RHINE) += via-rhine.o obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o @@ -96,6 +99,7 @@ obj-$(CONFIG_SH_ETH) += sh_eth.o # obj-$(CONFIG_MII) += mii.o +obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_SUNDANCE) += sundance.o @@ -135,6 +139,8 @@ obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o +ll_temac-objs := ll_temac_main.o ll_temac_mdio.o +obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o obj-$(CONFIG_QLA3XXX) += qla3xxx.o obj-$(CONFIG_QLGE) += qlge/ diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 02f64d578641..85a18175730b 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -564,7 +564,7 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) if (!TX_BUFFS_AVAIL){ local_irq_restore(flags); - return -1; + return NETDEV_TX_LOCKED; } #ifdef DEBUG_DRIVER diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 57bc71527850..08419ee10290 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -2573,7 +2573,6 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_wake_queue(dev); } - dev->trans_start = jiffies; return NETDEV_TX_OK; overflow: diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c index da64ba88d7f8..78cea5e80b1d 100644 --- a/drivers/net/appletalk/ipddp.c +++ b/drivers/net/appletalk/ipddp.c @@ -39,6 +39,7 @@ static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson \n"; static struct ipddp_route *ipddp_route_list; +static DEFINE_SPINLOCK(ipddp_route_lock); #ifdef CONFIG_IPDDP_ENCAP static int ipddp_mode = IPDDP_ENCAP; @@ -50,7 +51,7 @@ static int ipddp_mode = IPDDP_DECAP; static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev); static int ipddp_create(struct ipddp_route *new_rt); static int ipddp_delete(struct ipddp_route *rt); -static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt); +static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt); static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static const struct net_device_ops ipddp_netdev_ops = { @@ -71,6 +72,7 @@ static struct net_device * __init ipddp_init(void) if (!dev) return ERR_PTR(-ENOMEM); + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; strcpy(dev->name, "ipddp%d"); if (version_printed++ == 0) @@ -113,11 +115,13 @@ static struct net_device * __init ipddp_init(void) */ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) { - __be32 paddr = ((struct rtable*)skb->dst)->rt_gateway; + __be32 paddr = skb_rtable(skb)->rt_gateway; struct ddpehdr *ddp; struct ipddp_route *rt; struct atalk_addr *our_addr; + spin_lock(&ipddp_route_lock); + /* * Find appropriate route to use, based only on IP number. */ @@ -126,8 +130,10 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) if(rt->ip == paddr) break; } - if(rt == NULL) + if(rt == NULL) { + spin_unlock(&ipddp_route_lock); return 0; + } our_addr = atalk_find_dev_addr(rt->dev); @@ -173,6 +179,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0) dev_kfree_skb(skb); + spin_unlock(&ipddp_route_lock); + return 0; } @@ -195,7 +203,9 @@ static int ipddp_create(struct ipddp_route *new_rt) return -ENETUNREACH; } - if (ipddp_find_route(rt)) { + spin_lock_bh(&ipddp_route_lock); + if (__ipddp_find_route(rt)) { + spin_unlock_bh(&ipddp_route_lock); kfree(rt); return -EEXIST; } @@ -203,6 +213,8 @@ static int ipddp_create(struct ipddp_route *new_rt) rt->next = ipddp_route_list; ipddp_route_list = rt; + spin_unlock_bh(&ipddp_route_lock); + return 0; } @@ -215,6 +227,7 @@ static int ipddp_delete(struct ipddp_route *rt) struct ipddp_route **r = &ipddp_route_list; struct ipddp_route *tmp; + spin_lock_bh(&ipddp_route_lock); while((tmp = *r) != NULL) { if(tmp->ip == rt->ip @@ -222,19 +235,21 @@ static int ipddp_delete(struct ipddp_route *rt) && tmp->at.s_node == rt->at.s_node) { *r = tmp->next; + spin_unlock_bh(&ipddp_route_lock); kfree(tmp); return 0; } r = &tmp->next; } + spin_unlock_bh(&ipddp_route_lock); return (-ENOENT); } /* * Find a routing entry, we only return a FULL match */ -static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt) +static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt) { struct ipddp_route *f; @@ -252,7 +267,7 @@ static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt) static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct ipddp_route __user *rt = ifr->ifr_data; - struct ipddp_route rcp; + struct ipddp_route rcp, rcp2, *rp; if(!capable(CAP_NET_ADMIN)) return -EPERM; @@ -266,9 +281,19 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return (ipddp_create(&rcp)); case SIOCFINDIPDDPRT: - if(copy_to_user(rt, ipddp_find_route(&rcp), sizeof(struct ipddp_route))) - return -EFAULT; - return 0; + spin_lock_bh(&ipddp_route_lock); + rp = __ipddp_find_route(&rcp); + if (rp) + memcpy(&rcp2, rp, sizeof(rcp2)); + spin_unlock_bh(&ipddp_route_lock); + + if (rp) { + if (copy_to_user(rt, &rcp2, + sizeof(struct ipddp_route))) + return -EFAULT; + return 0; + } else + return -ENOENT; case SIOCDELIPDDPRT: return (ipddp_delete(&rcp)); diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 7f4bc8ae5462..2e7419a61191 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -829,7 +829,7 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; } else { printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n"); - return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) + return NETDEV_TX_BUSY; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) on this skb, he also reports -ENETDOWN and printk's, so either we free and return(0) or don't free and return 1 */ } diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index b72b3d639f6e..fbf4645417d4 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -253,7 +253,7 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) skb = dev_alloc_skb(length + 2); if (likely(skb != NULL)) { skb_reserve(skb, 2); - dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr, + dma_sync_single_for_cpu(NULL, ep->descs->rdesc[entry].buf_addr, length, DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); skb_put(skb, length); @@ -331,7 +331,7 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) ep->descs->tdesc[entry].tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); skb_copy_and_csum_dev(skb, ep->tx_buf[entry]); - dma_sync_single(NULL, ep->descs->tdesc[entry].buf_addr, + dma_sync_single_for_cpu(NULL, ep->descs->tdesc[entry].buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb(skb); diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index ec8a1ae1e887..455037134aa3 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -526,7 +526,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) if (priv(dev)->tx_tail == next_ptr) { local_irq_restore(flags); - return 1; /* unable to queue */ + return NETDEV_TX_BUSY; /* unable to queue */ } dev->trans_start = jiffies; diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index b6d188115caf..6f42ad728915 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -562,8 +562,8 @@ static int eth_poll(struct napi_struct *napi, int budget) dma_unmap_single(&dev->dev, desc->data - NET_IP_ALIGN, RX_BUFF_SIZE, DMA_FROM_DEVICE); #else - dma_sync_single(&dev->dev, desc->data - NET_IP_ALIGN, - RX_BUFF_SIZE, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(&dev->dev, desc->data - NET_IP_ALIGN, + RX_BUFF_SIZE, DMA_FROM_DEVICE); memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n], ALIGN(NET_IP_ALIGN + desc->pkt_len, 4) / 4); #endif @@ -1151,7 +1151,7 @@ static int __devinit eth_init_one(struct platform_device *pdev) struct net_device *dev; struct eth_plat_info *plat = pdev->dev.platform_data; u32 regs_phys; - char phy_id[BUS_ID_SIZE]; + char phy_id[MII_BUS_ID_SIZE + 3]; int err; if (!(dev = alloc_etherdev(sizeof(struct port)))) @@ -1209,7 +1209,7 @@ static int __devinit eth_init_one(struct platform_device *pdev) __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); udelay(50); - snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); + snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy); port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, PHY_INTERFACE_MODE_MII); if ((err = IS_ERR(port->phydev))) diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index 45c5b7332cd3..e4afbd628c23 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -271,7 +271,7 @@ static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct atl1c_adapter *adapter = netdev_priv(netdev); if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_MCAST | WAKE_BCAST | WAKE_MCAST)) + WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) return -EOPNOTSUPP; /* these settings will always override what we currently have */ adapter->wol = 0; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 83a12125b94e..cd547a205fb9 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -163,6 +163,24 @@ static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) atl1c_irq_enable(adapter); } +/* + * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads + * of the idle status register until the device is actually idle + */ +static u32 atl1c_wait_until_idle(struct atl1c_hw *hw) +{ + int timeout; + u32 data; + + for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { + AT_READ_REG(hw, REG_IDLE_STATUS, &data); + if ((data & IDLE_STATUS_MASK) == 0) + return 0; + msleep(1); + } + return data; +} + /* * atl1c_phy_config - Timer Call-back * @data: pointer to netdev cast into an unsigned long @@ -220,11 +238,11 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) /* link down */ if (netif_carrier_ok(netdev)) { hw->hibernate = true; - atl1c_set_aspm(hw, false); if (atl1c_stop_mac(hw) != 0) if (netif_msg_hw(adapter)) dev_warn(&pdev->dev, "stop mac failed\n"); + atl1c_set_aspm(hw, false); } netif_carrier_off(netdev); } else { @@ -240,10 +258,10 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) adapter->link_duplex != duplex) { adapter->link_speed = speed; adapter->link_duplex = duplex; + atl1c_set_aspm(hw, true); atl1c_enable_tx_ctrl(hw); atl1c_enable_rx_ctrl(hw); atl1c_setup_mac_ctrl(adapter); - atl1c_set_aspm(hw, true); if (netif_msg_link(adapter)) dev_info(&pdev->dev, "%s: %s NIC Link is Up<%d Mbps %s>\n", @@ -1106,7 +1124,6 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter) static int atl1c_stop_mac(struct atl1c_hw *hw) { u32 data; - int timeout; AT_READ_REG(hw, REG_RXQ_CTRL, &data); data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN | @@ -1117,25 +1134,13 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) data &= ~TXQ_CTRL_EN; AT_WRITE_REG(hw, REG_TWSI_CTRL, data); - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - AT_READ_REG(hw, REG_IDLE_STATUS, &data); - if ((data & (IDLE_STATUS_RXQ_NO_IDLE | - IDLE_STATUS_TXQ_NO_IDLE)) == 0) - break; - msleep(1); - } + atl1c_wait_until_idle(hw); AT_READ_REG(hw, REG_MAC_CTRL, &data); data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); AT_WRITE_REG(hw, REG_MAC_CTRL, data); - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - AT_READ_REG(hw, REG_IDLE_STATUS, &data); - if ((data & IDLE_STATUS_MASK) == 0) - return 0; - msleep(1); - } - return data; + return (int)atl1c_wait_until_idle(hw); } static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) @@ -1178,8 +1183,6 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) { struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; struct pci_dev *pdev = adapter->pdev; - u32 idle_status_data = 0; - int timeout = 0; int ret; AT_WRITE_REG(hw, REG_IMR, 0); @@ -1198,15 +1201,10 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) AT_WRITE_FLUSH(hw); msleep(10); /* Wait at least 10ms for All module to be Idle */ - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - AT_READ_REG(hw, REG_IDLE_STATUS, &idle_status_data); - if ((idle_status_data & IDLE_STATUS_MASK) == 0) - break; - msleep(1); - } - if (timeout >= AT_HW_MAX_IDLE_DELAY) { + + if (atl1c_wait_until_idle(hw)) { dev_err(&pdev->dev, - "MAC state machine cann't be idle since" + "MAC state machine can't be idle since" " disabled for 10ms second\n"); return -1; } @@ -1242,9 +1240,7 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - pm_ctrl_data &= PM_CTRL_SERDES_PD_EX_L1; - pm_ctrl_data |= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; - pm_ctrl_data |= ~PM_CTRL_SERDES_L1_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << PM_CTRL_L1_ENTRY_TIMER_SHIFT); @@ -1254,19 +1250,11 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; - if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) { - pm_ctrl_data |= AT_ASPM_L1_TIMER << - PM_CTRL_L1_ENTRY_TIMER_SHIFT; - pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; - } else - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - - if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; - else - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - + pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; + pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; } else { + pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; @@ -2123,7 +2111,6 @@ static int atl1c_xmit_frame(struct sk_buff *skb, struct net_device *netdev) atl1c_tx_map(adapter, skb, tpd, type); atl1c_tx_queue(adapter, skb, tpd, type); - netdev->trans_start = jiffies; spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; } diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h index 2bf63b4368e2..ba48220df16a 100644 --- a/drivers/net/atl1e/atl1e.h +++ b/drivers/net/atl1e/atl1e.h @@ -429,7 +429,6 @@ struct atl1e_adapter { struct mii_if_info mii; /* MII interface info */ struct atl1e_hw hw; struct atl1e_hw_stats hw_stats; - struct net_device_stats net_stats; bool have_msi; u32 wol; diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 1342418fb209..9fc6d6d9060e 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -1154,7 +1154,7 @@ static struct net_device_stats *atl1e_get_stats(struct net_device *netdev) { struct atl1e_adapter *adapter = netdev_priv(netdev); struct atl1e_hw_stats *hw_stats = &adapter->hw_stats; - struct net_device_stats *net_stats = &adapter->net_stats; + struct net_device_stats *net_stats = &netdev->stats; net_stats->rx_packets = hw_stats->rx_ok; net_stats->tx_packets = hw_stats->tx_ok; @@ -1182,7 +1182,7 @@ static struct net_device_stats *atl1e_get_stats(struct net_device *netdev) net_stats->tx_aborted_errors = hw_stats->tx_abort_col; net_stats->tx_window_errors = hw_stats->tx_late_col; - return &adapter->net_stats; + return net_stats; } static void atl1e_update_hw_stats(struct atl1e_adapter *adapter) @@ -1310,7 +1310,7 @@ static irqreturn_t atl1e_intr(int irq, void *data) /* link event */ if (status & (ISR_GPHY | ISR_MANUAL)) { - adapter->net_stats.tx_carrier_errors++; + netdev->stats.tx_carrier_errors++; atl1e_link_chg_event(adapter); break; } @@ -1602,7 +1602,7 @@ static u16 atl1e_cal_tdp_req(const struct sk_buff *skb) } if (skb_is_gso(skb)) { - if (skb->protocol == ntohs(ETH_P_IP) || + if (skb->protocol == htons(ETH_P_IP) || (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) { proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); @@ -1795,8 +1795,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc)); tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - if (tx_buffer->skb) - BUG(); + BUG_ON(tx_buffer->skb); tx_buffer->skb = NULL; tx_buffer->length = @@ -1879,7 +1878,7 @@ static int atl1e_xmit_frame(struct sk_buff *skb, struct net_device *netdev) TPD_VLAN_SHIFT; } - if (skb->protocol == ntohs(ETH_P_8021Q)) + if (skb->protocol == htons(ETH_P_8021Q)) tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT; if (skb_network_offset(skb) != ETH_HLEN) @@ -1895,7 +1894,7 @@ static int atl1e_xmit_frame(struct sk_buff *skb, struct net_device *netdev) atl1e_tx_map(adapter, skb, tpd); atl1e_tx_queue(adapter, tpd_req, tpd); - netdev->trans_start = jiffies; + netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; } diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 4e817126e280..94d7325caf4f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2213,8 +2213,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, nr_frags = skb_shinfo(skb)->nr_frags; next_to_use = atomic_read(&tpd_ring->next_to_use); buffer_info = &tpd_ring->buffer_info[next_to_use]; - if (unlikely(buffer_info->skb)) - BUG(); + BUG_ON(buffer_info->skb); /* put skb in last TPD */ buffer_info->skb = NULL; @@ -2280,8 +2279,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, ATL1_MAX_TX_BUF_LEN; for (i = 0; i < nseg; i++) { buffer_info = &tpd_ring->buffer_info[next_to_use]; - if (unlikely(buffer_info->skb)) - BUG(); + BUG_ON(buffer_info->skb); + buffer_info->skb = NULL; buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ? ATL1_MAX_TX_BUF_LEN : buf_len; @@ -2383,7 +2382,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) mss = skb_shinfo(skb)->gso_size; if (mss) { - if (skb->protocol == ntohs(ETH_P_IP)) { + if (skb->protocol == htons(ETH_P_IP)) { proto_hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); if (unlikely(proto_hdr_len > len)) { @@ -2438,7 +2437,6 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) atl1_tx_queue(adapter, count, ptpd); atl1_update_mailbox(adapter); mmiowb(); - netdev->trans_start = jiffies; return NETDEV_TX_OK; } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index d58c105fc779..d3c734f4d679 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -957,7 +957,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) /* We've wrapped around and the transmitter is still busy */ netif_stop_queue(dev); aup->tx_full = 1; - return 1; + return NETDEV_TX_BUSY; } else if (buff_stat & TX_T_DONE) { update_tx_stats(dev, ptxd->status); diff --git a/drivers/net/b44.c b/drivers/net/b44.c index b70b81ec34c3..36d4d377ec2f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -782,7 +782,7 @@ static int b44_rx(struct b44 *bp, int budget) drop_it: b44_recycle_rx(bp, cons, bp->rx_prod); drop_it_no_recycle: - bp->stats.rx_dropped++; + bp->dev->stats.rx_dropped++; goto next_pkt; } @@ -1647,7 +1647,7 @@ static int b44_close(struct net_device *dev) static struct net_device_stats *b44_get_stats(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); - struct net_device_stats *nstat = &bp->stats; + struct net_device_stats *nstat = &dev->stats; struct b44_hw_stats *hwstat = &bp->hw_stats; /* Convert HW stats into netdevice stats. */ diff --git a/drivers/net/b44.h b/drivers/net/b44.h index d24158e7f309..e1905a49279f 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -384,7 +384,6 @@ struct b44 { struct timer_list timer; - struct net_device_stats stats; struct b44_hw_stats hw_stats; struct ssb_device *sdev; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 5c378b5e8e41..66bb56874d9b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -168,6 +168,7 @@ static void netdev_stats_update(struct be_adapter *adapter) struct be_port_rxf_stats *port_stats = &rxf_stats->port[adapter->port_num]; struct net_device_stats *dev_stats = &adapter->stats.net_stats; + struct be_erx_stats *erx_stats = &hw_stats->erx; dev_stats->rx_packets = port_stats->rx_total_frames; dev_stats->tx_packets = port_stats->tx_unicastframes + @@ -181,29 +182,33 @@ static void netdev_stats_update(struct be_adapter *adapter) dev_stats->rx_errors = port_stats->rx_crc_errors + port_stats->rx_alignment_symbol_errors + port_stats->rx_in_range_errors + - port_stats->rx_out_range_errors + port_stats->rx_frame_too_long; + port_stats->rx_out_range_errors + + port_stats->rx_frame_too_long + + port_stats->rx_dropped_too_small + + port_stats->rx_dropped_too_short + + port_stats->rx_dropped_header_too_small + + port_stats->rx_dropped_tcp_length + + port_stats->rx_dropped_runt + + port_stats->rx_tcp_checksum_errs + + port_stats->rx_ip_checksum_errs + + port_stats->rx_udp_checksum_errs; - /* packet transmit problems */ - dev_stats->tx_errors = 0; - - /* no space in linux buffers */ - dev_stats->rx_dropped = 0; - - /* no space available in linux */ - dev_stats->tx_dropped = 0; - - dev_stats->multicast = port_stats->tx_multicastframes; - dev_stats->collisions = 0; + /* no space in linux buffers: best possible approximation */ + dev_stats->rx_dropped = erx_stats->rx_drops_no_fragments[0]; /* detailed rx errors */ dev_stats->rx_length_errors = port_stats->rx_in_range_errors + - port_stats->rx_out_range_errors + port_stats->rx_frame_too_long; + port_stats->rx_out_range_errors + + port_stats->rx_frame_too_long; + /* receive ring buffer overflow */ dev_stats->rx_over_errors = 0; + dev_stats->rx_crc_errors = port_stats->rx_crc_errors; /* frame alignment errors */ dev_stats->rx_frame_errors = port_stats->rx_alignment_symbol_errors; + /* receiver fifo overrun */ /* drops_no_pbuf is no per i/f, it's per BE card */ dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow + @@ -211,6 +216,16 @@ static void netdev_stats_update(struct be_adapter *adapter) rxf_stats->rx_drops_no_pbuf; /* receiver missed packetd */ dev_stats->rx_missed_errors = 0; + + /* packet transmit problems */ + dev_stats->tx_errors = 0; + + /* no space available in linux */ + dev_stats->tx_dropped = 0; + + dev_stats->multicast = port_stats->tx_multicastframes; + dev_stats->collisions = 0; + /* detailed tx_errors */ dev_stats->tx_aborted_errors = 0; dev_stats->tx_carrier_errors = 0; @@ -337,13 +352,10 @@ static void be_tx_stats_update(struct be_adapter *adapter, /* Determine number of WRB entries needed to xmit data in an skb */ static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy) { - int cnt = 0; - while (skb) { - if (skb->len > skb->data_len) - cnt++; - cnt += skb_shinfo(skb)->nr_frags; - skb = skb_shinfo(skb)->frag_list; - } + int cnt = (skb->len > skb->data_len); + + cnt += skb_shinfo(skb)->nr_frags; + /* to account for hdr wrb */ cnt++; if (cnt & 1) { @@ -409,31 +421,28 @@ static int make_tx_wrbs(struct be_adapter *adapter, hdr = queue_head_node(txq); queue_head_inc(txq); - while (skb) { - if (skb->len > skb->data_len) { - int len = skb->len - skb->data_len; - busaddr = pci_map_single(pdev, skb->data, len, - PCI_DMA_TODEVICE); - wrb = queue_head_node(txq); - wrb_fill(wrb, busaddr, len); - be_dws_cpu_to_le(wrb, sizeof(*wrb)); - queue_head_inc(txq); - copied += len; - } + if (skb->len > skb->data_len) { + int len = skb->len - skb->data_len; + busaddr = pci_map_single(pdev, skb->data, len, + PCI_DMA_TODEVICE); + wrb = queue_head_node(txq); + wrb_fill(wrb, busaddr, len); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + copied += len; + } - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - 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); - wrb = queue_head_node(txq); - wrb_fill(wrb, busaddr, frag->size); - be_dws_cpu_to_le(wrb, sizeof(*wrb)); - queue_head_inc(txq); - copied += frag->size; - } - skb = skb_shinfo(skb)->frag_list; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + 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); + wrb = queue_head_node(txq); + wrb_fill(wrb, busaddr, frag->size); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + copied += frag->size; } if (dummy_wrb) { @@ -478,8 +487,6 @@ static int be_xmit(struct sk_buff *skb, struct net_device *netdev) be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt); - netdev->trans_start = jiffies; - be_tx_stats_update(adapter, wrb_cnt, copied, stopped); return NETDEV_TX_OK; } @@ -637,6 +644,22 @@ static void be_rx_stats_update(struct be_adapter *adapter, stats->be_rx_bytes += pktsize; } +static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) +{ + u8 l4_cksm, ip_version, ipcksm, tcpf = 0, udpf = 0, ipv6_chk; + + l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); + ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp); + ip_version = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp); + if (ip_version) { + tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); + udpf = AMAP_GET_BITS(struct amap_eth_rx_compl, udpf, rxcp); + } + ipv6_chk = (ip_version && (tcpf || udpf)); + + return ((l4_cksm && ipv6_chk && ipcksm) && cso) ? false : true; +} + static struct be_rx_page_info * get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) { @@ -720,7 +743,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, if (pktsize <= rx_frag_size) { BUG_ON(num_rcvd != 1); - return; + goto done; } /* More frags present for this completion */ @@ -742,6 +765,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, memset(page_info, 0, sizeof(*page_info)); } +done: be_rx_stats_update(adapter, pktsize, num_rcvd); return; } @@ -752,9 +776,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, { struct sk_buff *skb; u32 vtp, vid; - int l4_cksm; - l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN); @@ -769,10 +791,10 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb_fill_rx_data(adapter, skb, rxcp); - if (l4_cksm && adapter->rx_csum) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else + if (do_pkt_csum(rxcp, adapter->rx_csum)) skb->ip_summed = CHECKSUM_NONE; + else + skb->ip_summed = CHECKSUM_UNNECESSARY; skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, adapter->netdev); @@ -854,12 +876,19 @@ static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) be_dws_le_to_cpu(rxcp, sizeof(*rxcp)); - rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0; - queue_tail_inc(&adapter->rx_obj.cq); return rxcp; } +/* To reset the valid bit, we need to reset the whole word as + * when walking the queue the valid entries are little-endian + * and invalid entries are host endian + */ +static inline void be_rx_compl_reset(struct be_eth_rx_compl *rxcp) +{ + rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0; +} + static inline struct page *be_alloc_pages(u32 size) { gfp_t alloc_flags = GFP_ATOMIC; @@ -991,6 +1020,7 @@ static void be_rx_q_clean(struct be_adapter *adapter) /* First cleanup pending rx completions */ 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); } @@ -1026,8 +1056,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) struct be_queue_info *q; q = &adapter->tx_obj.q; - if (q->created) + 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); + } be_queue_free(adapter, q); q = &adapter->tx_obj.cq; @@ -1035,10 +1070,6 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); be_queue_free(adapter, q); - /* 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); - q = &adapter->tx_eq.q; if (q->created) be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); @@ -1272,6 +1303,8 @@ int be_poll_rx(struct napi_struct *napi, int budget) be_rx_compl_process_lro(adapter, rxcp); else be_rx_compl_process(adapter, rxcp); + + be_rx_compl_reset(rxcp); } lro_flush_all(&adapter->rx_obj.lro_mgr); @@ -1527,7 +1560,7 @@ static int be_close(struct net_device *netdev) struct be_eq_obj *tx_eq = &adapter->tx_eq; int vec; - cancel_delayed_work(&adapter->work); + cancel_delayed_work_sync(&adapter->work); netif_stop_queue(netdev); netif_carrier_off(netdev); @@ -1626,10 +1659,12 @@ 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_TSO6; + NETIF_F_IPV6_CSUM; netdev->flags |= IFF_MULTICAST; + adapter->rx_csum = true; + BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index b4da18213324..c15fc281f79f 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -194,13 +194,13 @@ static int desc_list_init(void) struct dma_descriptor *b = &(r->desc_b); /* allocate a new skb for next time receive */ - new_skb = dev_alloc_skb(PKT_BUF_SZ + 2); + new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); if (!new_skb) { printk(KERN_NOTICE DRV_NAME ": init: low on mem - packet dropped\n"); goto init_error; } - skb_reserve(new_skb, 2); + skb_reserve(new_skb, NET_IP_ALIGN); r->skb = new_skb; /* @@ -566,9 +566,9 @@ static void adjust_tx_list(void) */ if (current_tx_ptr->next->next == tx_list_head) { while (tx_list_head->status.status_word == 0) { - mdelay(1); + udelay(10); if (tx_list_head->status.status_word != 0 - || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) { + || !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) { goto adjust_head; } if (timeout_cnt-- < 0) { @@ -606,93 +606,41 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { u16 *data; - + u32 data_align = (unsigned long)(skb->data) & 0x3; current_tx_ptr->skb = skb; - if (ANOMALY_05000285) { - /* - * TXDWA feature is not avaible to older revision < 0.3 silicon - * of BF537 - * - * Only if data buffer is ODD WORD alignment, we do not - * need to memcpy - */ - u32 data_align = (u32)(skb->data) & 0x3; - if (data_align == 0x2) { - /* move skb->data to current_tx_ptr payload */ - data = (u16 *)(skb->data) - 1; - *data = (u16)(skb->len); - current_tx_ptr->desc_a.start_addr = (u32)data; - /* this is important! */ - blackfin_dcache_flush_range((u32)data, - (u32)((u8 *)data + skb->len + 4)); - } else { - *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); - memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, - skb->len); - current_tx_ptr->desc_a.start_addr = - (u32)current_tx_ptr->packet; - if (current_tx_ptr->status.status_word != 0) - current_tx_ptr->status.status_word = 0; - blackfin_dcache_flush_range( - (u32)current_tx_ptr->packet, - (u32)(current_tx_ptr->packet + skb->len + 2)); - } + if (data_align == 0x2) { + /* move skb->data to current_tx_ptr payload */ + data = (u16 *)(skb->data) - 1; + *data = (u16)(skb->len); + current_tx_ptr->desc_a.start_addr = (u32)data; + /* this is important! */ + blackfin_dcache_flush_range((u32)data, + (u32)((u8 *)data + skb->len + 4)); } else { - /* - * TXDWA feature is avaible to revision < 0.3 silicon of - * BF537 and always avaible to BF52x - */ - u32 data_align = (u32)(skb->data) & 0x3; - if (data_align == 0x0) { - u16 sysctl = bfin_read_EMAC_SYSCTL(); - sysctl |= TXDWA; - bfin_write_EMAC_SYSCTL(sysctl); - - /* move skb->data to current_tx_ptr payload */ - data = (u16 *)(skb->data) - 2; - *data = (u16)(skb->len); - current_tx_ptr->desc_a.start_addr = (u32)data; - /* this is important! */ - blackfin_dcache_flush_range( - (u32)data, - (u32)((u8 *)data + skb->len + 4)); - } else if (data_align == 0x2) { - u16 sysctl = bfin_read_EMAC_SYSCTL(); - sysctl &= ~TXDWA; - bfin_write_EMAC_SYSCTL(sysctl); - - /* move skb->data to current_tx_ptr payload */ - data = (u16 *)(skb->data) - 1; - *data = (u16)(skb->len); - current_tx_ptr->desc_a.start_addr = (u32)data; - /* this is important! */ - blackfin_dcache_flush_range( - (u32)data, - (u32)((u8 *)data + skb->len + 4)); - } else { - u16 sysctl = bfin_read_EMAC_SYSCTL(); - sysctl &= ~TXDWA; - bfin_write_EMAC_SYSCTL(sysctl); - - *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); - memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, - skb->len); - current_tx_ptr->desc_a.start_addr = - (u32)current_tx_ptr->packet; - if (current_tx_ptr->status.status_word != 0) - current_tx_ptr->status.status_word = 0; - blackfin_dcache_flush_range( - (u32)current_tx_ptr->packet, - (u32)(current_tx_ptr->packet + skb->len + 2)); - } + *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); + memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, + skb->len); + current_tx_ptr->desc_a.start_addr = + (u32)current_tx_ptr->packet; + if (current_tx_ptr->status.status_word != 0) + current_tx_ptr->status.status_word = 0; + blackfin_dcache_flush_range( + (u32)current_tx_ptr->packet, + (u32)(current_tx_ptr->packet + skb->len + 2)); } + /* make sure the internal data buffers in the core are drained + * so that the DMA descriptors are completely written when the + * DMA engine goes to fetch them below + */ + SSYNC(); + /* enable this packet's dma */ current_tx_ptr->desc_a.config |= DMAEN; /* tx dma is running, just return */ - if (bfin_read_DMA2_IRQ_STATUS() & 0x08) + if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN) goto out; /* tx dma is not running */ @@ -718,7 +666,7 @@ static void bfin_mac_rx(struct net_device *dev) /* allocate a new skb for next time receive */ skb = current_rx_ptr->skb; - new_skb = dev_alloc_skb(PKT_BUF_SZ + 2); + new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); if (!new_skb) { printk(KERN_NOTICE DRV_NAME ": rx: low on mem - packet dropped\n"); @@ -726,7 +674,7 @@ static void bfin_mac_rx(struct net_device *dev) goto out; } /* reserve 2 bytes for RXDWA padding */ - skb_reserve(new_skb, 2); + skb_reserve(new_skb, NET_IP_ALIGN); current_rx_ptr->skb = new_skb; current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; @@ -1022,7 +970,8 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) { struct net_device *ndev; struct bfin_mac_local *lp; - int rc, i; + struct platform_device *pd; + int rc; ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); if (!ndev) { @@ -1047,13 +996,6 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) goto out_err_probe_mac; } - /* set the GPIO pins to Ethernet mode */ - rc = peripheral_request_list(pin_req, DRV_NAME); - if (rc) { - dev_err(&pdev->dev, "Requesting peripherals failed!\n"); - rc = -EFAULT; - goto out_err_setup_pin_mux; - } /* * Is it valid? (Did bootloader initialize it?) @@ -1069,26 +1011,14 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) setup_mac_addr(ndev->dev_addr); - /* MDIO bus initial */ - lp->mii_bus = mdiobus_alloc(); - if (lp->mii_bus == NULL) - goto out_err_mdiobus_alloc; - - lp->mii_bus->priv = ndev; - lp->mii_bus->read = bfin_mdiobus_read; - lp->mii_bus->write = bfin_mdiobus_write; - lp->mii_bus->reset = bfin_mdiobus_reset; - lp->mii_bus->name = "bfin_mac_mdio"; - snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "0"); - lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); - for (i = 0; i < PHY_MAX_ADDR; ++i) - lp->mii_bus->irq[i] = PHY_POLL; - - rc = mdiobus_register(lp->mii_bus); - if (rc) { - dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); - goto out_err_mdiobus_register; + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n"); + rc = -ENODEV; + goto out_err_probe_mac; } + pd = pdev->dev.platform_data; + lp->mii_bus = platform_get_drvdata(pd); + lp->mii_bus->priv = ndev; rc = mii_probe(ndev); if (rc) { @@ -1107,7 +1037,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) /* now, enable interrupts */ /* register irq handler */ rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, - IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev); + IRQF_DISABLED, "EMAC_RX", ndev); if (rc) { dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); rc = -EBUSY; @@ -1130,11 +1060,8 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) out_err_request_irq: out_err_mii_probe: mdiobus_unregister(lp->mii_bus); -out_err_mdiobus_register: mdiobus_free(lp->mii_bus); -out_err_mdiobus_alloc: peripheral_free_list(pin_req); -out_err_setup_pin_mux: out_err_probe_mac: platform_set_drvdata(pdev, NULL); free_netdev(ndev); @@ -1149,8 +1076,7 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - mdiobus_unregister(lp->mii_bus); - mdiobus_free(lp->mii_bus); + lp->mii_bus->priv = NULL; unregister_netdev(ndev); @@ -1188,6 +1114,74 @@ static int bfin_mac_resume(struct platform_device *pdev) #define bfin_mac_resume NULL #endif /* CONFIG_PM */ +static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) +{ + struct mii_bus *miibus; + int rc, i; + + /* + * We are setting up a network card, + * so set the GPIO pins to Ethernet mode + */ + rc = peripheral_request_list(pin_req, DRV_NAME); + if (rc) { + dev_err(&pdev->dev, "Requesting peripherals failed!\n"); + return rc; + } + + rc = -ENOMEM; + miibus = mdiobus_alloc(); + if (miibus == NULL) + goto out_err_alloc; + miibus->read = bfin_mdiobus_read; + miibus->write = bfin_mdiobus_write; + miibus->reset = bfin_mdiobus_reset; + + miibus->parent = &pdev->dev; + miibus->name = "bfin_mii_bus"; + snprintf(miibus->id, MII_BUS_ID_SIZE, "0"); + miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + if (miibus->irq == NULL) + goto out_err_alloc; + for (i = 0; i < PHY_MAX_ADDR; ++i) + miibus->irq[i] = PHY_POLL; + + rc = mdiobus_register(miibus); + if (rc) { + dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); + goto out_err_mdiobus_register; + } + + platform_set_drvdata(pdev, miibus); + return 0; + +out_err_mdiobus_register: + mdiobus_free(miibus); +out_err_alloc: + peripheral_free_list(pin_req); + + return rc; +} + +static int __devexit bfin_mii_bus_remove(struct platform_device *pdev) +{ + struct mii_bus *miibus = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); + mdiobus_unregister(miibus); + mdiobus_free(miibus); + peripheral_free_list(pin_req); + return 0; +} + +static struct platform_driver bfin_mii_bus_driver = { + .probe = bfin_mii_bus_probe, + .remove = __devexit_p(bfin_mii_bus_remove), + .driver = { + .name = "bfin_mii_bus", + .owner = THIS_MODULE, + }, +}; + static struct platform_driver bfin_mac_driver = { .probe = bfin_mac_probe, .remove = __devexit_p(bfin_mac_remove), @@ -1201,7 +1195,11 @@ static struct platform_driver bfin_mac_driver = { static int __init bfin_mac_init(void) { - return platform_driver_register(&bfin_mac_driver); + int ret; + ret = platform_driver_register(&bfin_mii_bus_driver); + if (!ret) + return platform_driver_register(&bfin_mac_driver); + return -ENODEV; } module_init(bfin_mac_init); @@ -1209,6 +1207,7 @@ module_init(bfin_mac_init); static void __exit bfin_mac_cleanup(void) { platform_driver_unregister(&bfin_mac_driver); + platform_driver_unregister(&bfin_mii_bus_driver); } module_exit(bfin_mac_cleanup); diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 44d015f70d1c..9578a3dfac01 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1247,6 +1247,16 @@ static const struct ethtool_ops bmac_ethtool_ops = { .get_link = ethtool_op_get_link, }; +static const struct net_device_ops bmac_netdev_ops = { + .ndo_open = bmac_open, + .ndo_stop = bmac_close, + .ndo_start_xmit = bmac_output, + .ndo_set_multicast_list = bmac_set_multicast, + .ndo_set_mac_address = bmac_set_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match) { int j, rev, ret; @@ -1308,12 +1318,8 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i bmac_enable_and_reset_chip(dev); bmwrite(dev, INTDISABLE, DisableAll); - dev->open = bmac_open; - dev->stop = bmac_close; + dev->netdev_ops = &bmac_netdev_ops; dev->ethtool_ops = &bmac_ethtool_ops; - dev->hard_start_xmit = bmac_output; - dev->set_multicast_list = bmac_set_multicast; - dev->set_mac_address = bmac_set_address; bmac_get_station_address(dev, addr); if (bmac_verify_checksum(dev) != 0) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 3f5fcb0156a1..7e3738112c4e 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -48,6 +48,7 @@ #include #include #include +#include #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) #define BCM_CNIC 1 @@ -703,8 +704,7 @@ bnx2_free_rx_mem(struct bnx2 *bp) rxr->rx_desc_mapping[j]); rxr->rx_desc_ring[j] = NULL; } - if (rxr->rx_buf_ring) - vfree(rxr->rx_buf_ring); + vfree(rxr->rx_buf_ring); rxr->rx_buf_ring = NULL; for (j = 0; j < bp->rx_max_pg_ring; j++) { @@ -714,8 +714,7 @@ bnx2_free_rx_mem(struct bnx2 *bp) rxr->rx_pg_desc_mapping[j]); rxr->rx_pg_desc_ring[j] = NULL; } - if (rxr->rx_pg_ring) - vfree(rxr->rx_pg_ring); + vfree(rxr->rx_pg_ring); rxr->rx_pg_ring = NULL; } } @@ -2788,14 +2787,15 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) tx_buf = &txr->tx_buf_ring[sw_ring_cons]; skb = tx_buf->skb; + /* prefetch skb_end_pointer() to speedup skb_shinfo(skb) */ + prefetch(&skb->end); + /* partial BD completions possible with TSO packets */ - if (skb_is_gso(skb)) { + if (tx_buf->is_gso) { u16 last_idx, last_ring_idx; - last_idx = sw_cons + - skb_shinfo(skb)->nr_frags + 1; - last_ring_idx = sw_ring_cons + - skb_shinfo(skb)->nr_frags + 1; + last_idx = sw_cons + tx_buf->nr_frags + 1; + last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1; if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) { last_idx++; } @@ -2807,7 +2807,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE); tx_buf->skb = NULL; - last = skb_shinfo(skb)->nr_frags; + last = tx_buf->nr_frags; for (i = 0; i < last; i++) { sw_cons = NEXT_TX_BD(sw_cons); @@ -2820,7 +2820,8 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) if (tx_pkt == budget) break; - hw_cons = bnx2_get_hw_tx_cons(bnapi); + if (hw_cons == sw_cons) + hw_cons = bnx2_get_hw_tx_cons(bnapi); } txr->hw_tx_cons = hw_cons; @@ -3492,7 +3493,7 @@ bnx2_set_rx_mode(struct net_device *dev) { struct bnx2 *bp = netdev_priv(dev); u32 rx_mode, sort_mode; - struct dev_addr_list *uc_ptr; + struct netdev_hw_addr *ha; int i; if (!netif_running(dev)) @@ -3551,21 +3552,19 @@ bnx2_set_rx_mode(struct net_device *dev) sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN; } - uc_ptr = NULL; if (dev->uc_count > BNX2_MAX_UNICAST_ADDRESSES) { rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS; sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN | BNX2_RPM_SORT_USER0_PROM_VLAN; } else if (!(dev->flags & IFF_PROMISC)) { - uc_ptr = dev->uc_list; - /* Add all entries into to the match filter list */ - for (i = 0; i < dev->uc_count; i++) { - bnx2_set_mac_addr(bp, uc_ptr->da_addr, + i = 0; + list_for_each_entry(ha, &dev->uc_list, list) { + bnx2_set_mac_addr(bp, ha->addr, i + BNX2_START_UNICAST_ADDRESS_INDEX); sort_mode |= (1 << (i + BNX2_START_UNICAST_ADDRESS_INDEX)); - uc_ptr = uc_ptr->next; + i++; } } @@ -5673,7 +5672,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) dev_kfree_skb(skb); return -EIO; } - map = skb_shinfo(skb)->dma_maps[0]; + map = skb_shinfo(skb)->dma_head; REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); @@ -6353,7 +6352,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } sp = skb_shinfo(skb); - mapping = sp->dma_maps[0]; + mapping = sp->dma_head; tx_buf = &txr->tx_buf_ring[ring_prod]; tx_buf->skb = skb; @@ -6366,6 +6365,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START; last_frag = skb_shinfo(skb)->nr_frags; + tx_buf->nr_frags = last_frag; + tx_buf->is_gso = skb_is_gso(skb); for (i = 0; i < last_frag; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -6375,7 +6376,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) txbd = &txr->tx_desc_ring[ring_prod]; len = frag->size; - mapping = sp->dma_maps[i + 1]; + mapping = sp->dma_maps[i]; txbd->tx_bd_haddr_hi = (u64) mapping >> 32; txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff; @@ -6394,7 +6395,6 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) mmiowb(); txr->tx_prod = prod; - dev->trans_start = jiffies; if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) { netif_tx_stop_queue(txq); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index a1ff739bc9b5..f1edfaa9e56a 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6556,6 +6556,8 @@ struct sw_pg { struct sw_tx_bd { struct sk_buff *skb; + unsigned short is_gso; + unsigned short nr_frags; }; #define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index a329bee25550..8678457849f9 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -965,6 +965,21 @@ struct bnx2x { int gunzip_outlen; #define FW_BUF_SIZE 0x8000 + struct raw_op *init_ops; + /* Init blocks offsets inside init_ops */ + u16 *init_ops_offsets; + /* Data blob - has 32 bit granularity */ + 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; }; diff --git a/drivers/net/bnx2x_fw_file_hdr.h b/drivers/net/bnx2x_fw_file_hdr.h new file mode 100644 index 000000000000..3f5ee5d7cc2a --- /dev/null +++ b/drivers/net/bnx2x_fw_file_hdr.h @@ -0,0 +1,37 @@ +/* bnx2x_fw_file_hdr.h: FW binary file header structure. + * + * Copyright (c) 2007-2009 Broadcom Corporation + * + * 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. + * + * Maintained by: Eilon Greenstein + * Written by: Vladislav Zolotarov + * Based on the original idea of John Wright . + */ + +#ifndef BNX2X_INIT_FILE_HDR_H +#define BNX2X_INIT_FILE_HDR_H + +struct bnx2x_fw_file_section { + __be32 len; + __be32 offset; +}; + +struct bnx2x_fw_file_hdr { + struct bnx2x_fw_file_section init_ops; + struct bnx2x_fw_file_section init_ops_offsets; + struct bnx2x_fw_file_section init_data; + struct bnx2x_fw_file_section tsem_int_table_data; + struct bnx2x_fw_file_section tsem_pram_data; + struct bnx2x_fw_file_section usem_int_table_data; + struct bnx2x_fw_file_section usem_pram_data; + struct bnx2x_fw_file_section csem_int_table_data; + struct bnx2x_fw_file_section csem_pram_data; + struct bnx2x_fw_file_section xsem_int_table_data; + struct bnx2x_fw_file_section xsem_pram_data; + struct bnx2x_fw_file_section fw_version; +}; + +#endif /* BNX2X_INIT_FILE_HDR_H */ diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index 39ba2936c0c2..3ba4d888068f 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -1,4 +1,5 @@ /* bnx2x_init.h: Broadcom Everest network driver. + * Structures and macroes needed during the initialization. * * Copyright (c) 2007-2009 Broadcom Corporation * @@ -8,6 +9,7 @@ * * Maintained by: Eilon Greenstein * Written by: Eliezer Tamir + * Modified by: Vladislav Zolotarov */ #ifndef BNX2X_INIT_H @@ -45,33 +47,71 @@ #define OP_WR_64 0x8 /* write 64 bit pattern */ #define OP_WB 0x9 /* copy a string using DMAE */ -/* Operation specific for E1 */ -#define OP_RD_E1 0xa /* read single register */ -#define OP_WR_E1 0xb /* write single register */ -#define OP_IW_E1 0xc /* write single register using mailbox */ -#define OP_SW_E1 0xd /* copy a string to the device */ -#define OP_SI_E1 0xe /* copy a string using mailbox */ -#define OP_ZR_E1 0xf /* clear memory */ -#define OP_ZP_E1 0x10 /* unzip then copy with DMAE */ -#define OP_WR_64_E1 0x11 /* write 64 bit pattern on E1 */ -#define OP_WB_E1 0x12 /* copy a string using DMAE */ - -/* Operation specific for E1H */ -#define OP_RD_E1H 0x13 /* read single register */ -#define OP_WR_E1H 0x14 /* write single register */ -#define OP_IW_E1H 0x15 /* write single register using mailbox */ -#define OP_SW_E1H 0x16 /* copy a string to the device */ -#define OP_SI_E1H 0x17 /* copy a string using mailbox */ -#define OP_ZR_E1H 0x18 /* clear memory */ -#define OP_ZP_E1H 0x19 /* unzip then copy with DMAE */ -#define OP_WR_64_E1H 0x1a /* write 64 bit pattern on E1H */ -#define OP_WB_E1H 0x1b /* copy a string using DMAE */ - /* FPGA and EMUL specific operations */ -#define OP_WR_EMUL_E1H 0x1c /* write single register on E1H Emul */ -#define OP_WR_EMUL 0x1d /* write single register on Emulation */ -#define OP_WR_FPGA 0x1e /* write single register on FPGA */ -#define OP_WR_ASIC 0x1f /* write single register on ASIC */ +#define OP_WR_EMUL 0xa /* write single register on Emulation */ +#define OP_WR_FPGA 0xb /* write single register on FPGA */ +#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 + + +/* 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 + +/* 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)) struct raw_op { @@ -118,292 +158,6 @@ union init_op { struct raw_op raw; }; -#include "bnx2x_init_values.h" - -static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); -static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len); - -static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data, - u32 len) -{ - int 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) -{ - int 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); -} - -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; - - memset(bp->gunzip_buf, 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); - } -} - -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; - u64 data64 = 0; - int 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; - - *pdata = data64; - } - - 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); - } -} - -/********************************************************* - There are different blobs for each PRAM section. - In addition, each blob write operation is divided into a few operations - in order to decrease the amount of phys. contiguous buffer needed. - Thus, when we select a blob the address may be with some offset - from the beginning of PRAM section. - The same holds for the INT_TABLE sections. -**********************************************************/ -#define IF_IS_INT_TABLE_ADDR(base, addr) \ - if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) - -#define IF_IS_PRAM_ADDR(base, addr) \ - if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) - -static const u32 *bnx2x_sel_blob(u32 addr, const u32 *data, int is_e1) -{ - IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr) - data = is_e1 ? tsem_int_table_data_e1 : - tsem_int_table_data_e1h; - else - IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr) - data = is_e1 ? csem_int_table_data_e1 : - csem_int_table_data_e1h; - else - IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr) - data = is_e1 ? usem_int_table_data_e1 : - usem_int_table_data_e1h; - else - IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr) - data = is_e1 ? xsem_int_table_data_e1 : - xsem_int_table_data_e1h; - else - IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr) - data = is_e1 ? tsem_pram_data_e1 : tsem_pram_data_e1h; - else - IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr) - data = is_e1 ? csem_pram_data_e1 : csem_pram_data_e1h; - else - IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr) - data = is_e1 ? usem_pram_data_e1 : usem_pram_data_e1h; - else - IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr) - data = is_e1 ? xsem_pram_data_e1 : xsem_pram_data_e1h; - - return data; -} - -static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, - u32 len, int gunzip, int is_e1, u32 blob_off) -{ - int offset = 0; - - data = bnx2x_sel_blob(addr, data, is_e1) + blob_off; - - if (gunzip) { - int rc; -#ifdef __BIG_ENDIAN - int i, size; - u32 *temp; - - temp = kmalloc(len, GFP_KERNEL); - size = (len / 4) + ((len % 4) ? 1 : 0); - for (i = 0; i < size; i++) - temp[i] = swab32(data[i]); - data = temp; -#endif - rc = bnx2x_gunzip(bp, (u8 *)data, len); - if (rc) { - BNX2X_ERR("gunzip failed ! rc %d\n", rc); -#ifdef __BIG_ENDIAN - kfree(temp); -#endif - return; - } - len = bp->gunzip_outlen; -#ifdef __BIG_ENDIAN - kfree(temp); - for (i = 0; i < len; i++) - ((u32 *)bp->gunzip_buf)[i] = - swab32(((u32 *)bp->gunzip_buf)[i]); -#endif - } else { - 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); - } - - 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); -} - -static void bnx2x_init_block(struct bnx2x *bp, u32 op_start, u32 op_end) -{ - int is_e1 = CHIP_IS_E1(bp); - int is_e1h = CHIP_IS_E1H(bp); - int is_emul_e1h = (CHIP_REV_IS_EMUL(bp) && is_e1h); - int hw_wr, i; - union init_op *op; - u32 op_type, addr, len; - const u32 *data, *data_base; - - if (CHIP_REV_IS_FPGA(bp)) - hw_wr = OP_WR_FPGA; - else if (CHIP_REV_IS_EMUL(bp)) - hw_wr = OP_WR_EMUL; - else - hw_wr = OP_WR_ASIC; - - if (is_e1) - data_base = init_data_e1; - else /* CHIP_IS_E1H(bp) */ - data_base = init_data_e1h; - - for (i = op_start; i < op_end; i++) { - - op = (union init_op *)&(init_ops[i]); - - op_type = op->str_wr.op; - addr = op->str_wr.offset; - len = op->str_wr.data_len; - data = data_base + op->str_wr.data_off; - - /* careful! it must be in order */ - if (unlikely(op_type > OP_WB)) { - - /* If E1 only */ - if (op_type <= OP_WB_E1) { - if (is_e1) - op_type -= (OP_RD_E1 - OP_RD); - - /* If E1H only */ - } else if (op_type <= OP_WB_E1H) { - if (is_e1h) - op_type -= (OP_RD_E1H - OP_RD); - } - - /* HW/EMUL specific */ - if (op_type == hw_wr) - op_type = OP_WR; - - /* EMUL on E1H is special */ - if ((op_type == OP_WR_EMUL_E1H) && is_emul_e1h) - op_type = OP_WR; - } - - switch (op_type) { - case OP_RD: - REG_RD(bp, addr); - break; - case OP_WR: - REG_WR(bp, addr, op->write.val); - break; - case OP_SW: - bnx2x_init_str_wr(bp, addr, data, len); - break; - case OP_WB: - bnx2x_init_wr_wb(bp, addr, data, len, 0, is_e1, 0); - break; - case OP_SI: - bnx2x_init_ind_wr(bp, addr, data, len); - break; - case OP_ZR: - bnx2x_init_fill(bp, addr, 0, op->zero.len); - break; - case OP_ZP: - bnx2x_init_wr_wb(bp, addr, data, len, 1, is_e1, - op->str_wr.data_off); - break; - case OP_WR_64: - bnx2x_init_wr_64(bp, addr, data, len); - 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 ****************************************************************************/ @@ -567,111 +321,6 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = { PXP2_REG_RQ_BW_WR_UBOUND30} }; -static void bnx2x_init_pxp(struct bnx2x *bp) -{ - 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); - r_order = MAX_RD_ORD; - } - if (w_order > MAX_WR_ORD) { - DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n", - w_order, MAX_WR_ORD); - w_order = MAX_WR_ORD; - } - if (CHIP_REV_IS_FPGA(bp)) { - DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n"); - w_order = 0; - } - DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order); - - for (i = 0; i < NUM_RD_Q-1; i++) { - REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l); - REG_WR(bp, read_arb_addr[i].add, - read_arb_data[i][r_order].add); - REG_WR(bp, read_arb_addr[i].ubound, - read_arb_data[i][r_order].ubound); - } - - for (i = 0; i < NUM_WR_Q-1; i++) { - if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || - (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { - - REG_WR(bp, write_arb_addr[i].l, - write_arb_data[i][w_order].l); - - REG_WR(bp, write_arb_addr[i].add, - write_arb_data[i][w_order].add); - - REG_WR(bp, write_arb_addr[i].ubound, - write_arb_data[i][w_order].ubound); - } else { - - val = REG_RD(bp, write_arb_addr[i].l); - REG_WR(bp, write_arb_addr[i].l, - val | (write_arb_data[i][w_order].l << 10)); - - val = REG_RD(bp, write_arb_addr[i].add); - REG_WR(bp, write_arb_addr[i].add, - val | (write_arb_data[i][w_order].add << 10)); - - val = REG_RD(bp, write_arb_addr[i].ubound); - REG_WR(bp, write_arb_addr[i].ubound, - val | (write_arb_data[i][w_order].ubound << 7)); - } - } - - val = write_arb_data[NUM_WR_Q-1][w_order].add; - val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; - val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; - REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val); - - val = read_arb_data[NUM_RD_Q-1][r_order].add; - val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; - val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; - REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val); - - REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order); - REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order); - REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order); - REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order); - - if (r_order == MAX_RD_ORD) - REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); - - REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); - - if (CHIP_IS_E1H(bp)) { - val = ((w_order == 0) ? 2 : 3); - REG_WR(bp, PXP2_REG_WR_HC_MPS, val); - REG_WR(bp, PXP2_REG_WR_USDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_QM_MPS, val); - REG_WR(bp, PXP2_REG_WR_TM_MPS, val); - REG_WR(bp, PXP2_REG_WR_SRC_MPS, val); - REG_WR(bp, PXP2_REG_WR_DBG_MPS, val); - REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */ - REG_WR(bp, PXP2_REG_WR_CDU_MPS, val); - } -} - /**************************************************************************** * CDU @@ -695,128 +344,12 @@ static void bnx2x_init_pxp(struct bnx2x *bp) (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. - ****************************************************************************/ -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; -} /* registers addresses are not in order so these arrays help simplify the code */ -static const int cm_start[E1H_FUNC_MAX][9] = { - {MISC_FUNC0_START, TCM_FUNC0_START, UCM_FUNC0_START, CCM_FUNC0_START, - XCM_FUNC0_START, TSEM_FUNC0_START, USEM_FUNC0_START, CSEM_FUNC0_START, - XSEM_FUNC0_START}, - {MISC_FUNC1_START, TCM_FUNC1_START, UCM_FUNC1_START, CCM_FUNC1_START, - XCM_FUNC1_START, TSEM_FUNC1_START, USEM_FUNC1_START, CSEM_FUNC1_START, - XSEM_FUNC1_START}, - {MISC_FUNC2_START, TCM_FUNC2_START, UCM_FUNC2_START, CCM_FUNC2_START, - XCM_FUNC2_START, TSEM_FUNC2_START, USEM_FUNC2_START, CSEM_FUNC2_START, - XSEM_FUNC2_START}, - {MISC_FUNC3_START, TCM_FUNC3_START, UCM_FUNC3_START, CCM_FUNC3_START, - XCM_FUNC3_START, TSEM_FUNC3_START, USEM_FUNC3_START, CSEM_FUNC3_START, - XSEM_FUNC3_START}, - {MISC_FUNC4_START, TCM_FUNC4_START, UCM_FUNC4_START, CCM_FUNC4_START, - XCM_FUNC4_START, TSEM_FUNC4_START, USEM_FUNC4_START, CSEM_FUNC4_START, - XSEM_FUNC4_START}, - {MISC_FUNC5_START, TCM_FUNC5_START, UCM_FUNC5_START, CCM_FUNC5_START, - XCM_FUNC5_START, TSEM_FUNC5_START, USEM_FUNC5_START, CSEM_FUNC5_START, - XSEM_FUNC5_START}, - {MISC_FUNC6_START, TCM_FUNC6_START, UCM_FUNC6_START, CCM_FUNC6_START, - XCM_FUNC6_START, TSEM_FUNC6_START, USEM_FUNC6_START, CSEM_FUNC6_START, - XSEM_FUNC6_START}, - {MISC_FUNC7_START, TCM_FUNC7_START, UCM_FUNC7_START, CCM_FUNC7_START, - XCM_FUNC7_START, TSEM_FUNC7_START, USEM_FUNC7_START, CSEM_FUNC7_START, - XSEM_FUNC7_START} -}; - -static const int cm_end[E1H_FUNC_MAX][9] = { - {MISC_FUNC0_END, TCM_FUNC0_END, UCM_FUNC0_END, CCM_FUNC0_END, - XCM_FUNC0_END, TSEM_FUNC0_END, USEM_FUNC0_END, CSEM_FUNC0_END, - XSEM_FUNC0_END}, - {MISC_FUNC1_END, TCM_FUNC1_END, UCM_FUNC1_END, CCM_FUNC1_END, - XCM_FUNC1_END, TSEM_FUNC1_END, USEM_FUNC1_END, CSEM_FUNC1_END, - XSEM_FUNC1_END}, - {MISC_FUNC2_END, TCM_FUNC2_END, UCM_FUNC2_END, CCM_FUNC2_END, - XCM_FUNC2_END, TSEM_FUNC2_END, USEM_FUNC2_END, CSEM_FUNC2_END, - XSEM_FUNC2_END}, - {MISC_FUNC3_END, TCM_FUNC3_END, UCM_FUNC3_END, CCM_FUNC3_END, - XCM_FUNC3_END, TSEM_FUNC3_END, USEM_FUNC3_END, CSEM_FUNC3_END, - XSEM_FUNC3_END}, - {MISC_FUNC4_END, TCM_FUNC4_END, UCM_FUNC4_END, CCM_FUNC4_END, - XCM_FUNC4_END, TSEM_FUNC4_END, USEM_FUNC4_END, CSEM_FUNC4_END, - XSEM_FUNC4_END}, - {MISC_FUNC5_END, TCM_FUNC5_END, UCM_FUNC5_END, CCM_FUNC5_END, - XCM_FUNC5_END, TSEM_FUNC5_END, USEM_FUNC5_END, CSEM_FUNC5_END, - XSEM_FUNC5_END}, - {MISC_FUNC6_END, TCM_FUNC6_END, UCM_FUNC6_END, CCM_FUNC6_END, - XCM_FUNC6_END, TSEM_FUNC6_END, USEM_FUNC6_END, CSEM_FUNC6_END, - XSEM_FUNC6_END}, - {MISC_FUNC7_END, TCM_FUNC7_END, UCM_FUNC7_END, CCM_FUNC7_END, - XCM_FUNC7_END, TSEM_FUNC7_END, USEM_FUNC7_END, CSEM_FUNC7_END, - XSEM_FUNC7_END}, -}; - -static const int hc_limits[E1H_FUNC_MAX][2] = { - {HC_FUNC0_START, HC_FUNC0_END}, - {HC_FUNC1_START, HC_FUNC1_END}, - {HC_FUNC2_START, HC_FUNC2_END}, - {HC_FUNC3_START, HC_FUNC3_END}, - {HC_FUNC4_START, HC_FUNC4_END}, - {HC_FUNC5_START, HC_FUNC5_END}, - {HC_FUNC6_START, HC_FUNC6_END}, - {HC_FUNC7_START, HC_FUNC7_END} +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 new file mode 100644 index 000000000000..32552b9366cb --- /dev/null +++ b/drivers/net/bnx2x_init_ops.h @@ -0,0 +1,442 @@ +/* bnx2x_init_ops.h: Broadcom Everest network driver. + * Static functions needed during the initialization. + * This file is "included" in bnx2x_main.c. + * + * Copyright (c) 2007-2009 Broadcom Corporation + * + * 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. + * + * Maintained by: Eilon Greenstein + * Written by: Vladislav Zolotarov + */ +#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; + + 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) +{ + int 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); +} + +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; + + memset(bp->gunzip_buf, 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); + } +} + +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; + u64 data64 = 0; + int 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; + + *pdata = data64; + } + + 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); + } +} + +/********************************************************* + There are different blobs for each PRAM section. + In addition, each blob write operation is divided into a few operations + in order to decrease the amount of phys. contiguous buffer needed. + Thus, when we select a blob the address may be with some offset + from the beginning of PRAM section. + The same holds for the INT_TABLE sections. +**********************************************************/ +#define IF_IS_INT_TABLE_ADDR(base, addr) \ + if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) + +#define IF_IS_PRAM_ADDR(base, addr) \ + if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) + +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; + + 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); +} + +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); + + 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); +} + +static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, + u32 len, u32 blob_off) +{ + int rc, i; + const u8 *data = NULL; + + data = bnx2x_sel_blob(bp, addr, data) + 4*blob_off; + + if (data == NULL) { + panic("Blob not found for addr 0x%x\n", addr); + return; + } + + 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); + return; + } + + /* gunzip_outlen is in dwords */ + len = bp->gunzip_outlen; + for (i = 0; i < len; i++) + ((u32 *)bp->gunzip_buf)[i] = + cpu_to_le32(((u32 *)bp->gunzip_buf)[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)]; + u16 op_end = + bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_END)]; + union init_op *op; + u32 op_type, addr, len; + const u32 *data, *data_base; + + /* If empty block */ + if (op_start == op_end) + return; + + if (CHIP_REV_IS_FPGA(bp)) + hw_wr = OP_WR_FPGA; + else if (CHIP_REV_IS_EMUL(bp)) + hw_wr = OP_WR_EMUL; + else + hw_wr = OP_WR_ASIC; + + data_base = bp->init_data; + + for (i = op_start; i < op_end; i++) { + + op = (union init_op *)&(bp->init_ops[i]); + + op_type = op->str_wr.op; + addr = op->str_wr.offset; + len = op->str_wr.data_len; + data = data_base + op->str_wr.data_off; + + /* HW/EMUL specific */ + if (unlikely((op_type > OP_WB) && (op_type == hw_wr))) + op_type = OP_WR; + + switch (op_type) { + case OP_RD: + REG_RD(bp, addr); + break; + case OP_WR: + REG_WR(bp, addr, op->write.val); + break; + case OP_SW: + bnx2x_init_str_wr(bp, addr, data, len); + break; + case OP_WB: + bnx2x_init_wr_wb(bp, addr, data, len); + break; + case OP_SI: + bnx2x_init_ind_wr(bp, addr, data, len); + break; + case OP_ZR: + bnx2x_init_fill(bp, addr, 0, op->zero.len); + break; + case OP_ZP: + bnx2x_init_wr_zp(bp, addr, len, + op->str_wr.data_off); + break; + case OP_WR_64: + bnx2x_init_wr_64(bp, addr, data, len); + 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) +{ + 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); + r_order = MAX_RD_ORD; + } + if (w_order > MAX_WR_ORD) { + DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n", + w_order, MAX_WR_ORD); + w_order = MAX_WR_ORD; + } + if (CHIP_REV_IS_FPGA(bp)) { + DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n"); + w_order = 0; + } + DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order); + + for (i = 0; i < NUM_RD_Q-1; i++) { + REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l); + REG_WR(bp, read_arb_addr[i].add, + read_arb_data[i][r_order].add); + REG_WR(bp, read_arb_addr[i].ubound, + read_arb_data[i][r_order].ubound); + } + + for (i = 0; i < NUM_WR_Q-1; i++) { + if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || + (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { + + REG_WR(bp, write_arb_addr[i].l, + write_arb_data[i][w_order].l); + + REG_WR(bp, write_arb_addr[i].add, + write_arb_data[i][w_order].add); + + REG_WR(bp, write_arb_addr[i].ubound, + write_arb_data[i][w_order].ubound); + } else { + + val = REG_RD(bp, write_arb_addr[i].l); + REG_WR(bp, write_arb_addr[i].l, + val | (write_arb_data[i][w_order].l << 10)); + + val = REG_RD(bp, write_arb_addr[i].add); + REG_WR(bp, write_arb_addr[i].add, + val | (write_arb_data[i][w_order].add << 10)); + + val = REG_RD(bp, write_arb_addr[i].ubound); + REG_WR(bp, write_arb_addr[i].ubound, + val | (write_arb_data[i][w_order].ubound << 7)); + } + } + + val = write_arb_data[NUM_WR_Q-1][w_order].add; + val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; + val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; + REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val); + + val = read_arb_data[NUM_RD_Q-1][r_order].add; + val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; + val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; + REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val); + + REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order); + REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order); + REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order); + REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order); + + if (r_order == MAX_RD_ORD) + REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); + + REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); + + if (CHIP_IS_E1H(bp)) { + val = ((w_order == 0) ? 2 : 3); + REG_WR(bp, PXP2_REG_WR_HC_MPS, val); + REG_WR(bp, PXP2_REG_WR_USDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_QM_MPS, val); + REG_WR(bp, PXP2_REG_WR_TM_MPS, val); + REG_WR(bp, PXP2_REG_WR_SRC_MPS, val); + REG_WR(bp, PXP2_REG_WR_DBG_MPS, val); + REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */ + REG_WR(bp, PXP2_REG_WR_CDU_MPS, val); + } +} + +/***************************************************************************** + * 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_init_values.h b/drivers/net/bnx2x_init_values.h deleted file mode 100644 index 1f22c9ab66d4..000000000000 --- a/drivers/net/bnx2x_init_values.h +++ /dev/null @@ -1,16322 +0,0 @@ -#ifndef __BNX2X_INIT_VALUES_H__ -#define __BNX2X_INIT_VALUES_H__ - -/* bnx2x_init_values.h: Broadcom NX2 10G network driver. - * - * Copyright (c) 2007-2009 Broadcom Corporation - * - * 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, except as noted below. - * - * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2007-2009 Broadcom Corporation. - * - * Permission is hereby granted for the distribution of this firmware data - * in hexadecimal or equivalent format, provided this copyright notice is - * accompanying it. - * - * - * This array contains the list of operations needed to initialize the chip. - * - * For each block in the chip there are three init stages: - * common - HW used by both ports, - * port1 and port2 - initialization for a specific Ethernet port. - * When a port is opened or closed, the management CPU tells the driver - * whether to init/disable common HW in addition to the port HW. - * This way the first port going up will first initializes the common HW, - * and the last port going down also resets the common HW - * - * For each init stage/block there is a list of actions needed in a format: - * {operation, register, data} - * where: - * OP_WR - write a value to the chip. - * OP_RD - read a register (usually a clear on read register). - * OP_SW - string write, write a section of consecutive addresses to the chip. - * OP_SI - copy a string using indirect writes. - * OP_ZR - clear a range of memory. - * OP_ZP - unzip and copy using DMAE. - * OP_WB - string copy using DMAE. - * - * The #defines mark the stages. - * - */ - -static const struct raw_op init_ops[] = { -#define PRS_COMMON_START 0 - {OP_WR, PRS_REG_INC_VALUE, 0xf}, - {OP_WR, PRS_REG_EVENT_ID_1, 0x45}, - {OP_WR, PRS_REG_EVENT_ID_2, 0x84}, - {OP_WR, PRS_REG_EVENT_ID_3, 0x6}, - {OP_WR, PRS_REG_NO_MATCH_EVENT_ID, 0x4}, - {OP_WR, PRS_REG_CM_HDR_TYPE_0, 0x0}, - {OP_WR, PRS_REG_CM_HDR_TYPE_1, 0x12170000}, - {OP_WR, PRS_REG_CM_HDR_TYPE_2, 0x22170000}, - {OP_WR, PRS_REG_CM_HDR_TYPE_3, 0x32170000}, - {OP_ZR, PRS_REG_CM_HDR_TYPE_4, 0x5}, - {OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_1, 0x12150000}, - {OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_2, 0x22150000}, - {OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_3, 0x32150000}, - {OP_ZR, PRS_REG_CM_HDR_LOOPBACK_TYPE_4, 0x4}, - {OP_WR, PRS_REG_CM_NO_MATCH_HDR, 0x2100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_0, 0x100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_1, 0x10100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_2, 0x20100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_3, 0x30100000}, - {OP_ZR_E1, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4, 0x4}, - {OP_WR_E1H, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4, 0x40100000}, - {OP_ZR_E1H, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_5, 0x3}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_0, 0x100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_1, 0x12140000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_2, 0x22140000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_3, 0x32140000}, - {OP_ZR_E1, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4, 0x4}, - {OP_WR_E1H, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4, 0x42140000}, - {OP_ZR_E1H, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_5, 0x3}, - {OP_RD, PRS_REG_NUM_OF_PACKETS, 0x0}, - {OP_RD, PRS_REG_NUM_OF_CFC_FLUSH_MESSAGES, 0x0}, - {OP_RD, PRS_REG_NUM_OF_TRANSPARENT_FLUSH_MESSAGES, 0x0}, - {OP_RD, PRS_REG_NUM_OF_DEAD_CYCLES, 0x0}, - {OP_WR_E1H, PRS_REG_FCOE_TYPE, 0x8906}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_0, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_1, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_2, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_3, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_4, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_5, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_6, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_7, 0xff}, - {OP_WR, PRS_REG_PURE_REGIONS, 0x3e}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_0, 0x0}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_1, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_2, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_3, 0x3f}, - {OP_WR_E1, PRS_REG_PACKET_REGIONS_TYPE_4, 0x0}, - {OP_WR_E1H, PRS_REG_PACKET_REGIONS_TYPE_4, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_5, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_6, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_7, 0x3f}, -#define PRS_COMMON_END 52 -#define SRCH_COMMON_START 52 - {OP_WR_E1H, SRC_REG_E1HMF_ENABLE, 0x1}, -#define SRCH_COMMON_END 53 -#define TSDM_COMMON_START 53 - {OP_WR_E1, TSDM_REG_CFC_RSP_START_ADDR, 0x411}, - {OP_WR_E1H, TSDM_REG_CFC_RSP_START_ADDR, 0x211}, - {OP_WR_E1, TSDM_REG_CMP_COUNTER_START_ADDR, 0x400}, - {OP_WR_E1H, TSDM_REG_CMP_COUNTER_START_ADDR, 0x200}, - {OP_WR_E1, TSDM_REG_Q_COUNTER_START_ADDR, 0x404}, - {OP_WR_E1H, TSDM_REG_Q_COUNTER_START_ADDR, 0x204}, - {OP_WR_E1, TSDM_REG_PCK_END_MSG_START_ADDR, 0x419}, - {OP_WR_E1H, TSDM_REG_PCK_END_MSG_START_ADDR, 0x219}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_ZR_E1, TSDM_REG_AGG_INT_EVENT_0, 0x2}, - {OP_WR_E1H, TSDM_REG_AGG_INT_EVENT_0, 0x20}, - {OP_WR_E1H, TSDM_REG_AGG_INT_EVENT_1, 0x0}, - {OP_WR, TSDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, TSDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_ZR_E1, TSDM_REG_AGG_INT_EVENT_4, 0x7c}, - {OP_ZR_E1H, TSDM_REG_AGG_INT_EVENT_4, 0x1c}, - {OP_WR_E1H, TSDM_REG_AGG_INT_T_0, 0x1}, - {OP_ZR_E1H, TSDM_REG_AGG_INT_T_1, 0x5f}, - {OP_WR, TSDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, TSDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, TSDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, TSDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, TSDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, TSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, TSDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, TSDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, TSDM_REG_TIMER_TICK, 0xa}, -#define TSDM_COMMON_END 96 -#define TCM_COMMON_START 96 - {OP_WR, TCM_REG_XX_MAX_LL_SZ, 0x20}, - {OP_WR, TCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, TCM_REG_TQM_TCM_HDR_P, 0x2150020}, - {OP_WR, TCM_REG_TQM_TCM_HDR_S, 0x2150020}, - {OP_WR, TCM_REG_TM_TCM_HDR, 0x30}, - {OP_WR, TCM_REG_ERR_TCM_HDR, 0x8100000}, - {OP_WR, TCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, TCM_REG_EXPR_EVNT_ID, 0x30}, - {OP_WR, TCM_REG_STOP_EVNT_ID, 0x31}, - {OP_WR, TCM_REG_STORM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_PRS_WEIGHT, 0x5}, - {OP_WR, TCM_REG_PBF_WEIGHT, 0x6}, - {OP_WR, TCM_REG_USEM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_CSEM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_CP_WEIGHT, 0x0}, - {OP_WR, TCM_REG_TSDM_WEIGHT, 0x5}, - {OP_WR, TCM_REG_TQM_P_WEIGHT, 0x2}, - {OP_WR, TCM_REG_TQM_S_WEIGHT, 0x2}, - {OP_WR, TCM_REG_TM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_TCM_TQM_USE_Q, 0x1}, - {OP_WR, TCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, TCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, TCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, TCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, TCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, TCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, TCM_REG_TQM_INIT_CRD, 0x20}, - {OP_WR, TCM_REG_XX_INIT_CRD, 0x13}, - {OP_WR, TCM_REG_XX_MSG_NUM, 0x20}, - {OP_ZR, TCM_REG_XX_TABLE, 0xa}, - {OP_SW, TCM_REG_XX_DESCR_TABLE, 0x200000}, - {OP_WR, TCM_REG_N_SM_CTX_LD_0, 0x7}, - {OP_WR, TCM_REG_N_SM_CTX_LD_1, 0x7}, - {OP_WR, TCM_REG_N_SM_CTX_LD_2, 0x8}, - {OP_WR, TCM_REG_N_SM_CTX_LD_3, 0x8}, - {OP_ZR_E1, TCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR_E1H, TCM_REG_N_SM_CTX_LD_4, 0x1}, - {OP_ZR_E1H, TCM_REG_N_SM_CTX_LD_5, 0x3}, - {OP_WR, TCM_REG_TCM_REG0_SZ, 0x6}, - {OP_WR_E1, TCM_REG_PHYS_QNUM0_0, 0xd}, - {OP_WR_E1, TCM_REG_PHYS_QNUM0_1, 0x2d}, - {OP_WR_E1, TCM_REG_PHYS_QNUM1_0, 0x7}, - {OP_WR_E1, TCM_REG_PHYS_QNUM1_1, 0x27}, - {OP_WR_E1, TCM_REG_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1, TCM_REG_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1, TCM_REG_PHYS_QNUM3_0, 0x7}, - {OP_WR_E1, TCM_REG_PHYS_QNUM3_1, 0x27}, - {OP_WR, TCM_REG_TCM_STORM0_IFEN, 0x1}, - {OP_WR, TCM_REG_TCM_STORM1_IFEN, 0x1}, - {OP_WR, TCM_REG_TCM_TQM_IFEN, 0x1}, - {OP_WR, TCM_REG_STORM_TCM_IFEN, 0x1}, - {OP_WR, TCM_REG_TQM_TCM_IFEN, 0x1}, - {OP_WR, TCM_REG_TSDM_IFEN, 0x1}, - {OP_WR, TCM_REG_TM_TCM_IFEN, 0x1}, - {OP_WR, TCM_REG_PRS_IFEN, 0x1}, - {OP_WR, TCM_REG_PBF_IFEN, 0x1}, - {OP_WR, TCM_REG_USEM_IFEN, 0x1}, - {OP_WR, TCM_REG_CSEM_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, TCM_REG_TCM_CFC_IFEN, 0x1}, -#define TCM_COMMON_END 159 -#define TCM_FUNC0_START 159 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0xd}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x7}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x7}, -#define TCM_FUNC0_END 163 -#define TCM_FUNC1_START 163 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x2d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x27}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x27}, -#define TCM_FUNC1_END 167 -#define TCM_FUNC2_START 167 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x1d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x17}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x17}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x17}, -#define TCM_FUNC2_END 171 -#define TCM_FUNC3_START 171 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x3d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x37}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x37}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x37}, -#define TCM_FUNC3_END 175 -#define TCM_FUNC4_START 175 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x4d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x47}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x47}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x47}, -#define TCM_FUNC4_END 179 -#define TCM_FUNC5_START 179 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x6d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x67}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x67}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x67}, -#define TCM_FUNC5_END 183 -#define TCM_FUNC6_START 183 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x5d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x57}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x57}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x57}, -#define TCM_FUNC6_END 187 -#define TCM_FUNC7_START 187 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x7d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x77}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x77}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x77}, -#define TCM_FUNC7_END 191 -#define BRB1_COMMON_START 191 - {OP_SW, BRB1_REG_LL_RAM, 0x2000020}, - {OP_WR, BRB1_REG_SOFT_RESET, 0x1}, - {OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_4, 0x0}, - {OP_SW, BRB1_REG_FREE_LIST_PRS_CRDT, 0x30220}, - {OP_WR, BRB1_REG_SOFT_RESET, 0x0}, -#define BRB1_COMMON_END 196 -#define BRB1_PORT0_START 196 - {OP_WR_E1, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0xb8}, - {OP_WR_E1, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 0x114}, - {OP_RD, BRB1_REG_NUM_OF_PAUSE_CYCLES_0, 0x0}, - {OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_0, 0x0}, -#define BRB1_PORT0_END 200 -#define BRB1_PORT1_START 200 - {OP_WR_E1, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0xb8}, - {OP_WR_E1, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 0x114}, - {OP_RD, BRB1_REG_NUM_OF_PAUSE_CYCLES_1, 0x0}, - {OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_1, 0x0}, -#define BRB1_PORT1_END 204 -#define TSEM_COMMON_START 204 - {OP_RD, TSEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, TSEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, TSEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, TSEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, TSEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, TSEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, TSEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, TSEM_REG_TS_0_AS, 0x0}, - {OP_WR, TSEM_REG_TS_1_AS, 0x1}, - {OP_WR, TSEM_REG_TS_2_AS, 0x4}, - {OP_WR, TSEM_REG_TS_3_AS, 0x0}, - {OP_WR, TSEM_REG_TS_4_AS, 0x1}, - {OP_WR, TSEM_REG_TS_5_AS, 0x3}, - {OP_WR, TSEM_REG_TS_6_AS, 0x0}, - {OP_WR, TSEM_REG_TS_7_AS, 0x1}, - {OP_WR, TSEM_REG_TS_8_AS, 0x4}, - {OP_WR, TSEM_REG_TS_9_AS, 0x0}, - {OP_WR, TSEM_REG_TS_10_AS, 0x1}, - {OP_WR, TSEM_REG_TS_11_AS, 0x3}, - {OP_WR, TSEM_REG_TS_12_AS, 0x0}, - {OP_WR, TSEM_REG_TS_13_AS, 0x1}, - {OP_WR, TSEM_REG_TS_14_AS, 0x4}, - {OP_WR, TSEM_REG_TS_15_AS, 0x0}, - {OP_WR, TSEM_REG_TS_16_AS, 0x4}, - {OP_WR, TSEM_REG_TS_17_AS, 0x3}, - {OP_ZR, TSEM_REG_TS_18_AS, 0x2}, - {OP_WR, TSEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, TSEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, TSEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, TSEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, TSEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, TSEM_REG_THREADS_LIST, 0xff}, - {OP_ZR, TSEM_REG_PASSIVE_BUFFER, 0x400}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18000, 0x34}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18040, 0x18}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18080, 0xc}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x180c0, 0x20}, - {OP_WR_ASIC, TSEM_REG_FAST_MEMORY + 0x18300, 0x7a120}, - {OP_WR_EMUL, TSEM_REG_FAST_MEMORY + 0x18300, 0x138}, - {OP_WR_FPGA, TSEM_REG_FAST_MEMORY + 0x18300, 0x1388}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2000, 0xb2}, - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x23c8, 0xc1}, - {OP_WR_EMUL_E1H, TSEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x23c8 + 0x304, 0x10223}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x1000, 0x2b3}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x1000 + 0xacc, 0x10223}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xa020, 0xc8}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1c18, 0x4}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xa000, 0x2}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1c10, 0x2}, - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x1ad0, 0x0}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x800, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x1ad8, 0x4}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x808, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3678, 0x6}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x810, 0x4}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3670, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb0, 0x40224}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5000, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x4cb0, 0x80228}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5008, 0x4}, - {OP_ZP_E1, TSEM_REG_INT_TABLE, 0x930000}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5018, 0x4}, - {OP_WR_64_E1, TSEM_REG_INT_TABLE + 0x360, 0x140230}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5028, 0x4}, - {OP_ZP_E1, TSEM_REG_PRAM, 0x324f0000}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5038, 0x4}, - {OP_ZP_E1, TSEM_REG_PRAM + 0x8000, 0x33250c94}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5048, 0x4}, - {OP_ZP_E1, TSEM_REG_PRAM + 0x10000, 0xe4d195e}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5058, 0x4}, - {OP_WR_64_E1, TSEM_REG_PRAM + 0x11e00, 0x5c400232}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5068, 0x4}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5078, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4000, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4008, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x62c0, 0x200224}, - {OP_ZP_E1H, TSEM_REG_INT_TABLE, 0x9b0000}, - {OP_WR_64_E1H, TSEM_REG_INT_TABLE + 0x398, 0xd0244}, - {OP_ZP_E1H, TSEM_REG_PRAM, 0x325e0000}, - {OP_ZP_E1H, TSEM_REG_PRAM + 0x8000, 0x35960c98}, - {OP_ZP_E1H, TSEM_REG_PRAM + 0x10000, 0x1aea19fe}, - {OP_WR_64_E1H, TSEM_REG_PRAM + 0x143d0, 0x57860246}, -#define TSEM_COMMON_END 297 -#define TSEM_PORT0_START 297 - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x22c8, 0x20}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x2000, 0x16c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x4000, 0x16c}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb000, 0x28}, - {OP_WR_E1, TSEM_REG_FAST_MEMORY + 0x4b60, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb140, 0xc}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1400, 0xa}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x32c0, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1450, 0x6}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3350, 0x64}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1500, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x8108, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1500 + 0x8, 0x50234}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1500 + 0x1c, 0x7}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1570, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x9c0, 0x4c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x800, 0x2}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x820, 0xe}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb0, 0x20239}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2908, 0x2}, -#define TSEM_PORT0_END 317 -#define TSEM_PORT1_START 317 - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2348, 0x20}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x25b0, 0x16c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x45b0, 0x16c}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb0a0, 0x28}, - {OP_WR_E1, TSEM_REG_FAST_MEMORY + 0x4b64, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb170, 0xc}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1428, 0xa}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3308, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1468, 0x6}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x34e0, 0x64}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1538, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x8110, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1538 + 0x8, 0x5023b}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1538 + 0x1c, 0x7}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x15b8, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0xaf0, 0x4c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x808, 0x2}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x858, 0xe}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb8, 0x20240}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2910, 0x2}, -#define TSEM_PORT1_END 337 -#define TSEM_FUNC0_START 337 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b60, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3000, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3000 + 0x8, 0x50248}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3000 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x31c0, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5000, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5080, 0x12}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4000, 0x2}, -#define TSEM_FUNC0_END 345 -#define TSEM_FUNC1_START 345 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b64, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3038, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3038 + 0x8, 0x5024d}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3038 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x31e0, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5010, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x50c8, 0x12}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4008, 0x2}, -#define TSEM_FUNC1_END 353 -#define TSEM_FUNC2_START 353 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b68, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3070, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3070 + 0x8, 0x50252}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3070 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3200, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5020, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5110, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4010, 0x20257}, -#define TSEM_FUNC2_END 361 -#define TSEM_FUNC3_START 361 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b6c, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30a8, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x30a8 + 0x8, 0x50259}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30a8 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3220, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5030, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5158, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4018, 0x2025e}, -#define TSEM_FUNC3_END 369 -#define TSEM_FUNC4_START 369 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b70, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30e0, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x30e0 + 0x8, 0x50260}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30e0 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3240, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5040, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x51a0, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4020, 0x20265}, -#define TSEM_FUNC4_END 377 -#define TSEM_FUNC5_START 377 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b74, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3118, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3118 + 0x8, 0x50267}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3118 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3260, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5050, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x51e8, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4028, 0x2026c}, -#define TSEM_FUNC5_END 385 -#define TSEM_FUNC6_START 385 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b78, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3150, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3150 + 0x8, 0x5026e}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3150 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3280, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5060, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5230, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4030, 0x20273}, -#define TSEM_FUNC6_END 393 -#define TSEM_FUNC7_START 393 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b7c, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3188, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3188 + 0x8, 0x50275}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3188 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x32a0, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5070, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5278, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4038, 0x2027a}, -#define TSEM_FUNC7_END 401 -#define MISC_COMMON_START 401 - {OP_WR_E1, MISC_REG_GRC_TIMEOUT_EN, 0x1}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_1, 0x71d2911}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_2, 0x0}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_3, 0x9c0424}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_4, 0x0}, - {OP_WR, MISC_REG_LCPLL_CTRL_1, 0x209}, - {OP_WR_E1, MISC_REG_SPIO, 0xff000000}, -#define MISC_COMMON_END 408 -#define MISC_FUNC0_START 408 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC0_END 409 -#define MISC_FUNC1_START 409 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC1_END 410 -#define MISC_FUNC2_START 410 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC2_END 411 -#define MISC_FUNC3_START 411 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC3_END 412 -#define MISC_FUNC4_START 412 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC4_END 413 -#define MISC_FUNC5_START 413 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC5_END 414 -#define MISC_FUNC6_START 414 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC6_END 415 -#define MISC_FUNC7_START 415 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC7_END 416 -#define NIG_COMMON_START 416 - {OP_WR, NIG_REG_PBF_LB_IN_EN, 0x1}, - {OP_WR, NIG_REG_PRS_REQ_IN_EN, 0x1}, - {OP_WR, NIG_REG_EGRESS_DEBUG_IN_EN, 0x1}, - {OP_WR, NIG_REG_BRB_LB_OUT_EN, 0x1}, - {OP_WR, NIG_REG_PRS_EOP_OUT_EN, 0x1}, -#define NIG_COMMON_END 421 -#define NIG_PORT0_START 421 - {OP_WR, NIG_REG_LLH0_CM_HEADER, 0x300000}, - {OP_WR, NIG_REG_LLH0_EVENT_ID, 0x28}, - {OP_WR, NIG_REG_LLH0_ERROR_MASK, 0x0}, - {OP_WR, NIG_REG_LLH0_XCM_MASK, 0x4}, - {OP_WR, NIG_REG_LLH0_BRB1_NOT_MCP, 0x1}, - {OP_WR, NIG_REG_STATUS_INTERRUPT_PORT0, 0x0}, - {OP_WR_E1H, NIG_REG_LLH0_CLS_TYPE, 0x1}, - {OP_WR, NIG_REG_LLH0_XCM_INIT_CREDIT, 0x30}, - {OP_WR, NIG_REG_BRB0_PAUSE_IN_EN, 0x1}, - {OP_WR, NIG_REG_EGRESS_PBF0_IN_EN, 0x1}, - {OP_WR, NIG_REG_BRB0_OUT_EN, 0x1}, - {OP_WR, NIG_REG_XCM0_OUT_EN, 0x1}, -#define NIG_PORT0_END 433 -#define NIG_PORT1_START 433 - {OP_WR, NIG_REG_LLH1_CM_HEADER, 0x300000}, - {OP_WR, NIG_REG_LLH1_EVENT_ID, 0x28}, - {OP_WR, NIG_REG_LLH1_ERROR_MASK, 0x0}, - {OP_WR, NIG_REG_LLH1_XCM_MASK, 0x4}, - {OP_WR, NIG_REG_LLH1_BRB1_NOT_MCP, 0x1}, - {OP_WR, NIG_REG_STATUS_INTERRUPT_PORT1, 0x0}, - {OP_WR_E1H, NIG_REG_LLH1_CLS_TYPE, 0x1}, - {OP_WR, NIG_REG_LLH1_XCM_INIT_CREDIT, 0x30}, - {OP_WR, NIG_REG_BRB1_PAUSE_IN_EN, 0x1}, - {OP_WR, NIG_REG_EGRESS_PBF1_IN_EN, 0x1}, - {OP_WR, NIG_REG_BRB1_OUT_EN, 0x1}, - {OP_WR, NIG_REG_XCM1_OUT_EN, 0x1}, -#define NIG_PORT1_END 445 -#define UPB_COMMON_START 445 - {OP_WR, GRCBASE_UPB + PB_REG_CONTROL, 0x20}, -#define UPB_COMMON_END 446 -#define CSDM_COMMON_START 446 - {OP_WR_E1, CSDM_REG_CFC_RSP_START_ADDR, 0xa11}, - {OP_WR_E1H, CSDM_REG_CFC_RSP_START_ADDR, 0x211}, - {OP_WR_E1, CSDM_REG_CMP_COUNTER_START_ADDR, 0xa00}, - {OP_WR_E1H, CSDM_REG_CMP_COUNTER_START_ADDR, 0x200}, - {OP_WR_E1, CSDM_REG_Q_COUNTER_START_ADDR, 0xa04}, - {OP_WR_E1H, CSDM_REG_Q_COUNTER_START_ADDR, 0x204}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_0, 0xc6}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_1, 0x0}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_ZR, CSDM_REG_AGG_INT_EVENT_4, 0x1c}, - {OP_WR, CSDM_REG_AGG_INT_T_0, 0x1}, - {OP_ZR, CSDM_REG_AGG_INT_T_1, 0x5f}, - {OP_WR, CSDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, CSDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, CSDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, CSDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, CSDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, CSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, CSDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, CSDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, CSDM_REG_TIMER_TICK, 0xa}, -#define CSDM_COMMON_END 485 -#define USDM_COMMON_START 485 - {OP_WR_E1, USDM_REG_CFC_RSP_START_ADDR, 0xa11}, - {OP_WR_E1H, USDM_REG_CFC_RSP_START_ADDR, 0x411}, - {OP_WR_E1, USDM_REG_CMP_COUNTER_START_ADDR, 0xa00}, - {OP_WR_E1H, USDM_REG_CMP_COUNTER_START_ADDR, 0x400}, - {OP_WR_E1, USDM_REG_Q_COUNTER_START_ADDR, 0xa04}, - {OP_WR_E1H, USDM_REG_Q_COUNTER_START_ADDR, 0x404}, - {OP_WR_E1, USDM_REG_PCK_END_MSG_START_ADDR, 0xa21}, - {OP_WR_E1H, USDM_REG_PCK_END_MSG_START_ADDR, 0x421}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_WR, USDM_REG_AGG_INT_EVENT_0, 0x46}, - {OP_WR, USDM_REG_AGG_INT_EVENT_1, 0x5}, - {OP_WR, USDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, USDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_ZR_E1, USDM_REG_AGG_INT_EVENT_4, 0x5c}, - {OP_WR_E1H, USDM_REG_AGG_INT_EVENT_4, 0x7}, - {OP_ZR_E1H, USDM_REG_AGG_INT_EVENT_5, 0x5b}, - {OP_WR, USDM_REG_AGG_INT_MODE_0, 0x1}, - {OP_ZR_E1, USDM_REG_AGG_INT_MODE_1, 0x1f}, - {OP_ZR_E1H, USDM_REG_AGG_INT_MODE_1, 0x3}, - {OP_WR_E1H, USDM_REG_AGG_INT_MODE_4, 0x1}, - {OP_ZR_E1H, USDM_REG_AGG_INT_MODE_5, 0x1b}, - {OP_WR, USDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, USDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, USDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, USDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, USDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q2_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, USDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, USDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, USDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, USDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, USDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, USDM_REG_TIMER_TICK, 0xa}, -#define USDM_COMMON_END 532 -#define CCM_COMMON_START 532 - {OP_WR, CCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, CCM_REG_CQM_CCM_HDR_P, 0x2150020}, - {OP_WR, CCM_REG_CQM_CCM_HDR_S, 0x2150020}, - {OP_WR, CCM_REG_ERR_CCM_HDR, 0x8100000}, - {OP_WR, CCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, CCM_REG_STORM_WEIGHT, 0x2}, - {OP_WR, CCM_REG_TSEM_WEIGHT, 0x0}, - {OP_WR, CCM_REG_XSEM_WEIGHT, 0x5}, - {OP_WR, CCM_REG_USEM_WEIGHT, 0x5}, - {OP_ZR, CCM_REG_PBF_WEIGHT, 0x2}, - {OP_WR, CCM_REG_CSDM_WEIGHT, 0x2}, - {OP_WR, CCM_REG_CQM_P_WEIGHT, 0x3}, - {OP_WR, CCM_REG_CQM_S_WEIGHT, 0x2}, - {OP_WR, CCM_REG_CCM_CQM_USE_Q, 0x1}, - {OP_WR, CCM_REG_CNT_AUX1_Q, 0x2}, - {OP_WR, CCM_REG_CNT_AUX2_Q, 0x2}, - {OP_WR, CCM_REG_INV_DONE_Q, 0x1}, - {OP_WR, CCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, CCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, CCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, CCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, CCM_REG_CQM_INIT_CRD, 0x20}, - {OP_WR, CCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, CCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, CCM_REG_XX_INIT_CRD, 0x3}, - {OP_WR, CCM_REG_XX_MSG_NUM, 0x18}, - {OP_ZR, CCM_REG_XX_TABLE, 0x12}, - {OP_SW_E1, CCM_REG_XX_DESCR_TABLE, 0x240242}, - {OP_SW_E1H, CCM_REG_XX_DESCR_TABLE, 0x24027c}, - {OP_WR, CCM_REG_N_SM_CTX_LD_0, 0x1}, - {OP_WR, CCM_REG_N_SM_CTX_LD_1, 0x2}, - {OP_WR, CCM_REG_N_SM_CTX_LD_2, 0x8}, - {OP_WR, CCM_REG_N_SM_CTX_LD_3, 0x8}, - {OP_ZR, CCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR, CCM_REG_CCM_REG0_SZ, 0x4}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM0_0, 0x9}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM0_1, 0x29}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM1_0, 0xa}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM1_1, 0x2a}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM3_0, 0x7}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM3_1, 0x27}, - {OP_WR_E1, CCM_REG_PHYS_QNUM1_0, 0xc}, - {OP_WR_E1, CCM_REG_PHYS_QNUM1_1, 0x2c}, - {OP_WR_E1, CCM_REG_PHYS_QNUM2_0, 0xc}, - {OP_WR_E1, CCM_REG_PHYS_QNUM2_1, 0x2c}, - {OP_WR_E1, CCM_REG_PHYS_QNUM3_0, 0xc}, - {OP_WR_E1, CCM_REG_PHYS_QNUM3_1, 0x2c}, - {OP_WR, CCM_REG_CCM_STORM0_IFEN, 0x1}, - {OP_WR, CCM_REG_CCM_STORM1_IFEN, 0x1}, - {OP_WR, CCM_REG_CCM_CQM_IFEN, 0x1}, - {OP_WR, CCM_REG_STORM_CCM_IFEN, 0x1}, - {OP_WR, CCM_REG_CQM_CCM_IFEN, 0x1}, - {OP_WR, CCM_REG_CSDM_IFEN, 0x1}, - {OP_WR, CCM_REG_TSEM_IFEN, 0x1}, - {OP_WR, CCM_REG_XSEM_IFEN, 0x1}, - {OP_WR, CCM_REG_USEM_IFEN, 0x1}, - {OP_WR, CCM_REG_PBF_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, CCM_REG_CCM_CFC_IFEN, 0x1}, -#define CCM_COMMON_END 596 -#define CCM_FUNC0_START 596 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x9}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0xa}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x7}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0xc}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0xb}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x7}, -#define CCM_FUNC0_END 603 -#define CCM_FUNC1_START 603 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x29}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x2a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x27}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x2c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x2b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x27}, -#define CCM_FUNC1_END 610 -#define CCM_FUNC2_START 610 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x19}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x1a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x17}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x17}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x1c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x1b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x17}, -#define CCM_FUNC2_END 617 -#define CCM_FUNC3_START 617 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x39}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x3a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x37}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x37}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x3c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x3b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x37}, -#define CCM_FUNC3_END 624 -#define CCM_FUNC4_START 624 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x49}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x4a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x47}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x47}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x4c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x4b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x47}, -#define CCM_FUNC4_END 631 -#define CCM_FUNC5_START 631 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x69}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x6a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x67}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x67}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x6c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x6b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x67}, -#define CCM_FUNC5_END 638 -#define CCM_FUNC6_START 638 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x59}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x5a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x57}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x57}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x5c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x5b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x57}, -#define CCM_FUNC6_END 645 -#define CCM_FUNC7_START 645 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x79}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x7a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x77}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x77}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x7c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x7b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x77}, -#define CCM_FUNC7_END 652 -#define UCM_COMMON_START 652 - {OP_WR, UCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, UCM_REG_UQM_UCM_HDR_P, 0x2150020}, - {OP_WR, UCM_REG_UQM_UCM_HDR_S, 0x2150020}, - {OP_WR, UCM_REG_TM_UCM_HDR, 0x30}, - {OP_WR, UCM_REG_ERR_UCM_HDR, 0x8100000}, - {OP_WR, UCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, UCM_REG_EXPR_EVNT_ID, 0x30}, - {OP_WR, UCM_REG_STOP_EVNT_ID, 0x31}, - {OP_WR, UCM_REG_STORM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_TSEM_WEIGHT, 0x4}, - {OP_WR, UCM_REG_CSEM_WEIGHT, 0x0}, - {OP_WR, UCM_REG_XSEM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_DORQ_WEIGHT, 0x2}, - {OP_WR, UCM_REG_CP_WEIGHT, 0x0}, - {OP_WR, UCM_REG_USDM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_UQM_P_WEIGHT, 0x7}, - {OP_WR, UCM_REG_UQM_S_WEIGHT, 0x2}, - {OP_WR, UCM_REG_TM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_UCM_UQM_USE_Q, 0x1}, - {OP_WR, UCM_REG_INV_CFLG_Q, 0x1}, - {OP_WR, UCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, UCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, UCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, UCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, UCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, UCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, UCM_REG_TM_INIT_CRD, 0x4}, - {OP_WR, UCM_REG_UQM_INIT_CRD, 0x20}, - {OP_WR, UCM_REG_XX_INIT_CRD, 0xe}, - {OP_WR, UCM_REG_XX_MSG_NUM, 0x1b}, - {OP_ZR, UCM_REG_XX_TABLE, 0x12}, - {OP_SW_E1, UCM_REG_XX_DESCR_TABLE, 0x1b0266}, - {OP_SW_E1H, UCM_REG_XX_DESCR_TABLE, 0x1b02a0}, - {OP_WR, UCM_REG_N_SM_CTX_LD_0, 0x10}, - {OP_WR, UCM_REG_N_SM_CTX_LD_1, 0x7}, - {OP_WR, UCM_REG_N_SM_CTX_LD_2, 0xf}, - {OP_WR, UCM_REG_N_SM_CTX_LD_3, 0x10}, - {OP_ZR_E1, UCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR_E1H, UCM_REG_N_SM_CTX_LD_4, 0xb}, - {OP_ZR_E1H, UCM_REG_N_SM_CTX_LD_5, 0x3}, - {OP_WR, UCM_REG_UCM_REG0_SZ, 0x3}, - {OP_WR_E1, UCM_REG_PHYS_QNUM0_0, 0xf}, - {OP_WR_E1, UCM_REG_PHYS_QNUM0_1, 0x2f}, - {OP_WR_E1, UCM_REG_PHYS_QNUM1_0, 0xe}, - {OP_WR_E1, UCM_REG_PHYS_QNUM1_1, 0x2e}, - {OP_WR, UCM_REG_UCM_STORM0_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_STORM1_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_UQM_IFEN, 0x1}, - {OP_WR, UCM_REG_STORM_UCM_IFEN, 0x1}, - {OP_WR, UCM_REG_UQM_UCM_IFEN, 0x1}, - {OP_WR, UCM_REG_USDM_IFEN, 0x1}, - {OP_WR, UCM_REG_TM_UCM_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_TM_IFEN, 0x1}, - {OP_WR, UCM_REG_TSEM_IFEN, 0x1}, - {OP_WR, UCM_REG_CSEM_IFEN, 0x1}, - {OP_WR, UCM_REG_XSEM_IFEN, 0x1}, - {OP_WR, UCM_REG_DORQ_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_CFC_IFEN, 0x1}, -#define UCM_COMMON_END 714 -#define UCM_FUNC0_START 714 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0xf}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0xe}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC0_END 718 -#define UCM_FUNC1_START 718 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x2f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x2e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC1_END 722 -#define UCM_FUNC2_START 722 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x1f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x1e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC2_END 726 -#define UCM_FUNC3_START 726 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x3f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x3e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC3_END 730 -#define UCM_FUNC4_START 730 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x4f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x4e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC4_END 734 -#define UCM_FUNC5_START 734 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x6f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x6e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC5_END 738 -#define UCM_FUNC6_START 738 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x5f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x5e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC6_END 742 -#define UCM_FUNC7_START 742 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x7f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x7e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC7_END 746 -#define USEM_COMMON_START 746 - {OP_RD, USEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, USEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, USEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, USEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, USEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, USEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, USEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, USEM_REG_TS_0_AS, 0x0}, - {OP_WR, USEM_REG_TS_1_AS, 0x1}, - {OP_WR, USEM_REG_TS_2_AS, 0x4}, - {OP_WR, USEM_REG_TS_3_AS, 0x0}, - {OP_WR, USEM_REG_TS_4_AS, 0x1}, - {OP_WR, USEM_REG_TS_5_AS, 0x3}, - {OP_WR, USEM_REG_TS_6_AS, 0x0}, - {OP_WR, USEM_REG_TS_7_AS, 0x1}, - {OP_WR, USEM_REG_TS_8_AS, 0x4}, - {OP_WR, USEM_REG_TS_9_AS, 0x0}, - {OP_WR, USEM_REG_TS_10_AS, 0x1}, - {OP_WR, USEM_REG_TS_11_AS, 0x3}, - {OP_WR, USEM_REG_TS_12_AS, 0x0}, - {OP_WR, USEM_REG_TS_13_AS, 0x1}, - {OP_WR, USEM_REG_TS_14_AS, 0x4}, - {OP_WR, USEM_REG_TS_15_AS, 0x0}, - {OP_WR, USEM_REG_TS_16_AS, 0x4}, - {OP_WR, USEM_REG_TS_17_AS, 0x3}, - {OP_ZR, USEM_REG_TS_18_AS, 0x2}, - {OP_WR, USEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, USEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, USEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, USEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, USEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, USEM_REG_THREADS_LIST, 0xffff}, - {OP_ZR, USEM_REG_PASSIVE_BUFFER, 0x800}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18000, 0x1a}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18040, 0x4e}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18080, 0x10}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x180c0, 0x20}, - {OP_WR_ASIC, USEM_REG_FAST_MEMORY + 0x18300, 0x7a120}, - {OP_WR_EMUL, USEM_REG_FAST_MEMORY + 0x18300, 0x138}, - {OP_WR_FPGA, USEM_REG_FAST_MEMORY + 0x18300, 0x1388}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_WR_ASIC, USEM_REG_FAST_MEMORY + 0x18380, 0x1dcd6500}, - {OP_WR_EMUL, USEM_REG_FAST_MEMORY + 0x18380, 0x4c4b4}, - {OP_WR_FPGA, USEM_REG_FAST_MEMORY + 0x18380, 0x4c4b40}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5000, 0xc2}, - {OP_WR_EMUL_E1H, USEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2000, 0x102}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4640, 0x40}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8980, 0xc8}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x57f0, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8960, 0x2}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x57d8, 0x5}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3228, 0x4}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x57d8 + 0x14, 0x10281}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3200, 0x9}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1c60, 0x20}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x3200 + 0x24, 0x102bb}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x2830, 0x20282}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3180, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x400}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000, 0x2}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0x8, 0x102bc}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0xc, 0x3}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b68, 0x2}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x6b68 + 0x8, 0x202bd}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b10, 0x2}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x74c0, 0x202bf}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x1000000}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c00, 0x100284}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c00, 0x1002c1}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x0}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c40, 0x100294}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c40, 0x1002d1}, - {OP_ZP_E1, USEM_REG_INT_TABLE, 0xc30000}, - {OP_ZP_E1H, USEM_REG_INT_TABLE, 0xd20000}, - {OP_WR_64_E1, USEM_REG_INT_TABLE + 0x368, 0x1302a4}, - {OP_WR_64_E1H, USEM_REG_INT_TABLE + 0x3a8, 0xb02e1}, - {OP_ZP_E1, USEM_REG_PRAM, 0x314c0000}, - {OP_ZP_E1H, USEM_REG_PRAM, 0x31b60000}, - {OP_ZP_E1, USEM_REG_PRAM + 0x8000, 0x35ef0c53}, - {OP_ZP_E1H, USEM_REG_PRAM + 0x8000, 0x36500c6e}, - {OP_ZP_E1, USEM_REG_PRAM + 0x10000, 0x361319cf}, - {OP_ZP_E1H, USEM_REG_PRAM + 0x10000, 0x37591a02}, - {OP_ZP_E1, USEM_REG_PRAM + 0x18000, 0x7112754}, - {OP_ZP_E1H, USEM_REG_PRAM + 0x18000, 0x286127d9}, - {OP_WR_64_E1, USEM_REG_PRAM + 0x18ee0, 0x4e2402a6}, - {OP_WR_64_E1H, USEM_REG_PRAM + 0x1ff40, 0x401802e3}, -#define USEM_COMMON_END 842 -#define USEM_PORT0_START 842 - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1400, 0xa0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9000, 0xa0}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1900, 0x10}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9500, 0x40}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1980, 0x30}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9700, 0x3c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4740, 0xb4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2450, 0xb4}, - {OP_WR_E1, USEM_REG_FAST_MEMORY + 0x1d90, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2ad0, 0x2}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b40, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3080, 0x20}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b60, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8000, 0x12c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5318, 0x98}, - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x3238, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5100, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5200, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5300, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5400, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5500, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5600, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5700, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5800, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5900, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b78, 0x52}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e08, 0xc}, -#define USEM_PORT0_END 876 -#define USEM_PORT1_START 876 - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1680, 0xa0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9280, 0xa0}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1940, 0x10}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9600, 0x40}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1a40, 0x30}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x97f0, 0x3c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4a10, 0xb4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2720, 0xb4}, - {OP_WR_E1, USEM_REG_FAST_MEMORY + 0x1d94, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2ad8, 0x2}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b50, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3100, 0x20}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1be0, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x84b0, 0x12c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5578, 0x98}, - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x323c, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5080, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5180, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5280, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5380, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5480, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5580, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5680, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5780, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5880, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5980, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6cc0, 0x52}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e38, 0xc}, -#define USEM_PORT1_END 910 -#define USEM_FUNC0_START 910 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a30, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3000, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4018, 0x2}, -#define USEM_FUNC0_END 913 -#define USEM_FUNC1_START 913 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a34, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3010, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4028, 0x2}, -#define USEM_FUNC1_END 916 -#define USEM_FUNC2_START 916 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a38, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3020, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4038, 0x2}, -#define USEM_FUNC2_END 919 -#define USEM_FUNC3_START 919 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a3c, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3030, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4048, 0x2}, -#define USEM_FUNC3_END 922 -#define USEM_FUNC4_START 922 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a40, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3040, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4058, 0x2}, -#define USEM_FUNC4_END 925 -#define USEM_FUNC5_START 925 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a44, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3050, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4068, 0x2}, -#define USEM_FUNC5_END 928 -#define USEM_FUNC6_START 928 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a48, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3060, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4078, 0x2}, -#define USEM_FUNC6_END 931 -#define USEM_FUNC7_START 931 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a4c, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3070, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4088, 0x2}, -#define USEM_FUNC7_END 934 -#define CSEM_COMMON_START 934 - {OP_RD, CSEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, CSEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, CSEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, CSEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, CSEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, CSEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, CSEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, CSEM_REG_TS_0_AS, 0x0}, - {OP_WR, CSEM_REG_TS_1_AS, 0x1}, - {OP_WR, CSEM_REG_TS_2_AS, 0x4}, - {OP_WR, CSEM_REG_TS_3_AS, 0x0}, - {OP_WR, CSEM_REG_TS_4_AS, 0x1}, - {OP_WR, CSEM_REG_TS_5_AS, 0x3}, - {OP_WR, CSEM_REG_TS_6_AS, 0x0}, - {OP_WR, CSEM_REG_TS_7_AS, 0x1}, - {OP_WR, CSEM_REG_TS_8_AS, 0x4}, - {OP_WR, CSEM_REG_TS_9_AS, 0x0}, - {OP_WR, CSEM_REG_TS_10_AS, 0x1}, - {OP_WR, CSEM_REG_TS_11_AS, 0x3}, - {OP_WR, CSEM_REG_TS_12_AS, 0x0}, - {OP_WR, CSEM_REG_TS_13_AS, 0x1}, - {OP_WR, CSEM_REG_TS_14_AS, 0x4}, - {OP_WR, CSEM_REG_TS_15_AS, 0x0}, - {OP_WR, CSEM_REG_TS_16_AS, 0x4}, - {OP_WR, CSEM_REG_TS_17_AS, 0x3}, - {OP_ZR, CSEM_REG_TS_18_AS, 0x2}, - {OP_WR, CSEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, CSEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, CSEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, CSEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, CSEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, CSEM_REG_THREADS_LIST, 0xffff}, - {OP_ZR, CSEM_REG_PASSIVE_BUFFER, 0x800}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18000, 0x10}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18040, 0x12}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18080, 0x30}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x180c0, 0xe}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x5000, 0x42}, - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_WR_EMUL_E1H, CSEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x1000, 0x42}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2000, 0xc0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x7020, 0xc8}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3070, 0x80}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x7000, 0x2}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x4280, 0x4}, - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11e8, 0x0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x25c0, 0x240}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3000, 0xc0}, - {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x2ec8, 0x802a8}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4070, 0x80}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x5280, 0x4}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6700, 0x100}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x9000, 0x400}, - {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x6b08, 0x2002e5}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x13fffff}, - {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c00, 0x1002b0}, - {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c00, 0x100305}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x0}, - {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c40, 0x1002c0}, - {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c40, 0x100315}, - {OP_ZP_E1, CSEM_REG_INT_TABLE, 0x710000}, - {OP_ZP_E1H, CSEM_REG_INT_TABLE, 0x740000}, - {OP_WR_64_E1, CSEM_REG_INT_TABLE + 0x380, 0x1002d0}, - {OP_WR_64_E1H, CSEM_REG_INT_TABLE + 0x380, 0x100325}, - {OP_ZP_E1, CSEM_REG_PRAM, 0x32290000}, - {OP_ZP_E1H, CSEM_REG_PRAM, 0x32260000}, - {OP_ZP_E1, CSEM_REG_PRAM + 0x8000, 0x23630c8b}, - {OP_ZP_E1H, CSEM_REG_PRAM + 0x8000, 0x246e0c8a}, - {OP_WR_64_E1, CSEM_REG_PRAM + 0xc930, 0x654002d2}, - {OP_WR_64_E1H, CSEM_REG_PRAM + 0xcbb0, 0x64f00327}, -#define CSEM_COMMON_END 1014 -#define CSEM_PORT0_START 1014 - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1400, 0xa0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8000, 0xa0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1900, 0x10}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8500, 0x40}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1980, 0x30}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8700, 0x3c}, - {OP_WR_E1, CSEM_REG_FAST_MEMORY + 0x5118, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4040, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2300, 0xe}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3040, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2410, 0x30}, -#define CSEM_PORT0_END 1025 -#define CSEM_PORT1_START 1025 - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1680, 0xa0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8280, 0xa0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1940, 0x10}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8600, 0x40}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1a40, 0x30}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x87f0, 0x3c}, - {OP_WR_E1, CSEM_REG_FAST_MEMORY + 0x511c, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4058, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2338, 0xe}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3058, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x24d0, 0x30}, -#define CSEM_PORT1_END 1036 -#define CSEM_FUNC0_START 1036 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1148, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3300, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6040, 0x30}, -#define CSEM_FUNC0_END 1039 -#define CSEM_FUNC1_START 1039 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x114c, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3308, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6100, 0x30}, -#define CSEM_FUNC1_END 1042 -#define CSEM_FUNC2_START 1042 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1150, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3310, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x61c0, 0x30}, -#define CSEM_FUNC2_END 1045 -#define CSEM_FUNC3_START 1045 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1154, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3318, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6280, 0x30}, -#define CSEM_FUNC3_END 1048 -#define CSEM_FUNC4_START 1048 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1158, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3320, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6340, 0x30}, -#define CSEM_FUNC4_END 1051 -#define CSEM_FUNC5_START 1051 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x115c, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3328, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6400, 0x30}, -#define CSEM_FUNC5_END 1054 -#define CSEM_FUNC6_START 1054 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1160, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3330, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x64c0, 0x30}, -#define CSEM_FUNC6_END 1057 -#define CSEM_FUNC7_START 1057 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1164, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3338, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6580, 0x30}, -#define CSEM_FUNC7_END 1060 -#define XPB_COMMON_START 1060 - {OP_WR, GRCBASE_XPB + PB_REG_CONTROL, 0x20}, -#define XPB_COMMON_END 1061 -#define DQ_COMMON_START 1061 - {OP_WR, DORQ_REG_MODE_ACT, 0x2}, - {OP_WR, DORQ_REG_NORM_CID_OFST, 0x3}, - {OP_WR, DORQ_REG_OUTST_REQ, 0x4}, - {OP_WR, DORQ_REG_DPM_CID_ADDR, 0x8}, - {OP_WR, DORQ_REG_RSP_INIT_CRD, 0x2}, - {OP_WR, DORQ_REG_NORM_CMHEAD_TX, 0x90}, - {OP_WR, DORQ_REG_CMHEAD_RX, 0x90}, - {OP_WR, DORQ_REG_SHRT_CMHEAD, 0x800090}, - {OP_WR, DORQ_REG_ERR_CMHEAD, 0x8140000}, - {OP_WR, DORQ_REG_AGG_CMD0, 0x8a}, - {OP_WR, DORQ_REG_AGG_CMD1, 0x80}, - {OP_WR, DORQ_REG_AGG_CMD2, 0x90}, - {OP_WR, DORQ_REG_AGG_CMD3, 0x80}, - {OP_WR, DORQ_REG_SHRT_ACT_CNT, 0x6}, - {OP_WR, DORQ_REG_DQ_FIFO_FULL_TH, 0x7d0}, - {OP_WR, DORQ_REG_DQ_FIFO_AFULL_TH, 0x76c}, - {OP_WR, DORQ_REG_REGN, 0x7c1004}, - {OP_WR, DORQ_REG_IF_EN, 0xf}, -#define DQ_COMMON_END 1079 -#define TIMERS_COMMON_START 1079 - {OP_ZR, TM_REG_CLIN_PRIOR0_CLIENT, 0x2}, - {OP_WR, TM_REG_LIN_SETCLR_FIFO_ALFULL_THR, 0x1c}, - {OP_WR, TM_REG_CFC_AC_CRDCNT_VAL, 0x1}, - {OP_WR, TM_REG_CFC_CLD_CRDCNT_VAL, 0x1}, - {OP_WR, TM_REG_CLOUT_CRDCNT0_VAL, 0x1}, - {OP_WR, TM_REG_CLOUT_CRDCNT1_VAL, 0x1}, - {OP_WR, TM_REG_CLOUT_CRDCNT2_VAL, 0x1}, - {OP_WR, TM_REG_EXP_CRDCNT_VAL, 0x1}, - {OP_WR_E1, TM_REG_PCIARB_CRDCNT_VAL, 0x1}, - {OP_WR_E1H, TM_REG_PCIARB_CRDCNT_VAL, 0x2}, - {OP_WR_ASIC, TM_REG_TIMER_TICK_SIZE, 0x3d090}, - {OP_WR_EMUL, TM_REG_TIMER_TICK_SIZE, 0x9c}, - {OP_WR_FPGA, TM_REG_TIMER_TICK_SIZE, 0x9c4}, - {OP_WR, TM_REG_CL0_CONT_REGION, 0x8}, - {OP_WR, TM_REG_CL1_CONT_REGION, 0xc}, - {OP_WR, TM_REG_CL2_CONT_REGION, 0x10}, - {OP_WR, TM_REG_TM_CONTEXT_REGION, 0x20}, - {OP_WR, TM_REG_EN_TIMERS, 0x1}, - {OP_WR, TM_REG_EN_REAL_TIME_CNT, 0x1}, - {OP_WR, TM_REG_EN_CL0_INPUT, 0x1}, - {OP_WR, TM_REG_EN_CL1_INPUT, 0x1}, - {OP_WR, TM_REG_EN_CL2_INPUT, 0x1}, -#define TIMERS_COMMON_END 1101 -#define TIMERS_PORT0_START 1101 - {OP_WR, TM_REG_LIN0_LOGIC_ADDR, 0x0}, - {OP_WR, TM_REG_LIN0_PHY_ADDR_VALID, 0x0}, - {OP_ZR, TM_REG_LIN0_PHY_ADDR, 0x2}, -#define TIMERS_PORT0_END 1104 -#define TIMERS_PORT1_START 1104 - {OP_WR, TM_REG_LIN1_LOGIC_ADDR, 0x0}, - {OP_WR, TM_REG_LIN1_PHY_ADDR_VALID, 0x0}, - {OP_ZR, TM_REG_LIN1_PHY_ADDR, 0x2}, -#define TIMERS_PORT1_END 1107 -#define XSDM_COMMON_START 1107 - {OP_WR_E1, XSDM_REG_CFC_RSP_START_ADDR, 0x614}, - {OP_WR_E1H, XSDM_REG_CFC_RSP_START_ADDR, 0x424}, - {OP_WR_E1, XSDM_REG_CMP_COUNTER_START_ADDR, 0x600}, - {OP_WR_E1H, XSDM_REG_CMP_COUNTER_START_ADDR, 0x410}, - {OP_WR_E1, XSDM_REG_Q_COUNTER_START_ADDR, 0x604}, - {OP_WR_E1H, XSDM_REG_Q_COUNTER_START_ADDR, 0x414}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_0, 0x20}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_1, 0x20}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_4, 0x23}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_5, 0x24}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_6, 0x25}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_7, 0x26}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_8, 0x27}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_9, 0x29}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_10, 0x2a}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_11, 0x2b}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_12, 0x2c}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_13, 0x2d}, - {OP_ZR, XSDM_REG_AGG_INT_EVENT_14, 0x52}, - {OP_WR, XSDM_REG_AGG_INT_MODE_0, 0x1}, - {OP_ZR, XSDM_REG_AGG_INT_MODE_1, 0x1f}, - {OP_WR, XSDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, XSDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, XSDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, XSDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, XSDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, XSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, XSDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, XSDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, XSDM_REG_TIMER_TICK, 0xa}, -#define XSDM_COMMON_END 1156 -#define QM_COMMON_START 1156 - {OP_WR, QM_REG_ACTCTRINITVAL_0, 0x6}, - {OP_WR, QM_REG_ACTCTRINITVAL_1, 0x5}, - {OP_WR, QM_REG_ACTCTRINITVAL_2, 0xa}, - {OP_WR, QM_REG_ACTCTRINITVAL_3, 0x5}, - {OP_WR, QM_REG_PCIREQAT, 0x2}, - {OP_WR, QM_REG_CMINITCRD_0, 0x4}, - {OP_WR, QM_REG_CMINITCRD_1, 0x4}, - {OP_WR, QM_REG_CMINITCRD_2, 0x4}, - {OP_WR, QM_REG_CMINITCRD_3, 0x4}, - {OP_WR, QM_REG_CMINITCRD_4, 0x4}, - {OP_WR, QM_REG_CMINITCRD_5, 0x4}, - {OP_WR, QM_REG_CMINITCRD_6, 0x4}, - {OP_WR, QM_REG_CMINITCRD_7, 0x4}, - {OP_WR, QM_REG_OUTLDREQ, 0x4}, - {OP_WR, QM_REG_CTXREG_0, 0x7c}, - {OP_WR, QM_REG_CTXREG_1, 0x3d}, - {OP_WR, QM_REG_CTXREG_2, 0x3f}, - {OP_WR, QM_REG_CTXREG_3, 0x9c}, - {OP_WR, QM_REG_ENSEC, 0x7}, - {OP_ZR, QM_REG_QVOQIDX_0, 0x5}, - {OP_WR, QM_REG_WRRWEIGHTS_0, 0x1010101}, - {OP_WR, QM_REG_QVOQIDX_5, 0x0}, - {OP_WR, QM_REG_QVOQIDX_6, 0x4}, - {OP_WR, QM_REG_QVOQIDX_7, 0x4}, - {OP_WR, QM_REG_QVOQIDX_8, 0x2}, - {OP_WR, QM_REG_WRRWEIGHTS_1, 0x8012004}, - {OP_WR, QM_REG_QVOQIDX_9, 0x5}, - {OP_WR, QM_REG_QVOQIDX_10, 0x5}, - {OP_WR, QM_REG_QVOQIDX_11, 0x5}, - {OP_WR, QM_REG_QVOQIDX_12, 0x5}, - {OP_WR, QM_REG_WRRWEIGHTS_2, 0x20081001}, - {OP_WR, QM_REG_QVOQIDX_13, 0x8}, - {OP_WR, QM_REG_QVOQIDX_14, 0x6}, - {OP_WR, QM_REG_QVOQIDX_15, 0x7}, - {OP_WR, QM_REG_QVOQIDX_16, 0x0}, - {OP_WR, QM_REG_WRRWEIGHTS_3, 0x1010120}, - {OP_ZR, QM_REG_QVOQIDX_17, 0x4}, - {OP_WR, QM_REG_WRRWEIGHTS_4, 0x1010101}, - {OP_ZR_E1, QM_REG_QVOQIDX_21, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_21, 0x0}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_5, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_22, 0x4}, - {OP_ZR_E1, QM_REG_QVOQIDX_25, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_23, 0x4}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_6, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_24, 0x2}, - {OP_ZR_E1, QM_REG_QVOQIDX_29, 0x3}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_5, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_25, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_26, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_27, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_28, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_6, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_29, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_30, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_31, 0x7}, - {OP_WR, QM_REG_QVOQIDX_32, 0x1}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_7, 0x1010101}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_7, 0x1010120}, - {OP_WR, QM_REG_QVOQIDX_33, 0x1}, - {OP_WR, QM_REG_QVOQIDX_34, 0x1}, - {OP_WR, QM_REG_QVOQIDX_35, 0x1}, - {OP_WR, QM_REG_QVOQIDX_36, 0x1}, - {OP_WR, QM_REG_WRRWEIGHTS_8, 0x1010101}, - {OP_WR, QM_REG_QVOQIDX_37, 0x1}, - {OP_WR, QM_REG_QVOQIDX_38, 0x4}, - {OP_WR, QM_REG_QVOQIDX_39, 0x4}, - {OP_WR, QM_REG_QVOQIDX_40, 0x2}, - {OP_WR, QM_REG_WRRWEIGHTS_9, 0x8012004}, - {OP_WR, QM_REG_QVOQIDX_41, 0x5}, - {OP_WR, QM_REG_QVOQIDX_42, 0x5}, - {OP_WR, QM_REG_QVOQIDX_43, 0x5}, - {OP_WR, QM_REG_QVOQIDX_44, 0x5}, - {OP_WR, QM_REG_WRRWEIGHTS_10, 0x20081001}, - {OP_WR, QM_REG_QVOQIDX_45, 0x8}, - {OP_WR, QM_REG_QVOQIDX_46, 0x6}, - {OP_WR, QM_REG_QVOQIDX_47, 0x7}, - {OP_WR, QM_REG_QVOQIDX_48, 0x1}, - {OP_WR, QM_REG_WRRWEIGHTS_11, 0x1010120}, - {OP_WR, QM_REG_QVOQIDX_49, 0x1}, - {OP_WR, QM_REG_QVOQIDX_50, 0x1}, - {OP_WR, QM_REG_QVOQIDX_51, 0x1}, - {OP_WR, QM_REG_QVOQIDX_52, 0x1}, - {OP_WR, QM_REG_WRRWEIGHTS_12, 0x1010101}, - {OP_WR, QM_REG_QVOQIDX_53, 0x1}, - {OP_WR_E1, QM_REG_QVOQIDX_54, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_54, 0x4}, - {OP_WR_E1, QM_REG_QVOQIDX_55, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_55, 0x4}, - {OP_WR_E1, QM_REG_QVOQIDX_56, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_56, 0x2}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_13, 0x1010101}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_13, 0x8012004}, - {OP_WR_E1, QM_REG_QVOQIDX_57, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_57, 0x5}, - {OP_WR_E1, QM_REG_QVOQIDX_58, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_58, 0x5}, - {OP_WR_E1, QM_REG_QVOQIDX_59, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_59, 0x5}, - {OP_WR_E1, QM_REG_QVOQIDX_60, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_60, 0x5}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_14, 0x1010101}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_14, 0x20081001}, - {OP_WR_E1, QM_REG_QVOQIDX_61, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_61, 0x8}, - {OP_WR_E1, QM_REG_QVOQIDX_62, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_62, 0x6}, - {OP_WR_E1, QM_REG_QVOQIDX_63, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_63, 0x7}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_15, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_64, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_0_LSB, 0xffff003f}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_15, 0x1010120}, - {OP_ZR_E1, QM_REG_VOQQMASK_0_MSB, 0x2}, - {OP_ZR_E1H, QM_REG_QVOQIDX_65, 0x4}, - {OP_WR_E1, QM_REG_VOQQMASK_1_MSB, 0xffff003f}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_16, 0x1010101}, - {OP_WR_E1, QM_REG_VOQQMASK_2_LSB, 0x100}, - {OP_WR_E1H, QM_REG_QVOQIDX_69, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_2_MSB, 0x100}, - {OP_WR_E1H, QM_REG_QVOQIDX_70, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_71, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_72, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_17, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_73, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_74, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_75, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_76, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_18, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_77, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_78, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_79, 0x7}, - {OP_WR_E1H, QM_REG_QVOQIDX_80, 0x0}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_19, 0x1010120}, - {OP_ZR_E1H, QM_REG_QVOQIDX_81, 0x4}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_20, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_85, 0x0}, - {OP_WR_E1H, QM_REG_QVOQIDX_86, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_87, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_88, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_21, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_89, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_90, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_91, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_92, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_22, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_93, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_94, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_95, 0x7}, - {OP_WR_E1H, QM_REG_QVOQIDX_96, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_23, 0x1010120}, - {OP_WR_E1H, QM_REG_QVOQIDX_97, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_98, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_99, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_100, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_24, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_101, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_102, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_103, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_104, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_25, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_105, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_106, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_107, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_108, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_26, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_109, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_110, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_111, 0x7}, - {OP_WR_E1H, QM_REG_QVOQIDX_112, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_27, 0x1010120}, - {OP_WR_E1H, QM_REG_QVOQIDX_113, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_114, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_115, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_116, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_28, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_117, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_118, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_119, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_120, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_29, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_121, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_122, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_123, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_124, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_30, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_125, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_126, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_127, 0x7}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_31, 0x1010120}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_LSB, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_MSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_LSB_EXT_A, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_LSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_MSB, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_MSB_EXT_A, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_LSB, 0x1000100}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_MSB, 0x1000100}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_LSB_EXT_A, 0x1000100}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_MSB_EXT_A, 0x1000100}, - {OP_ZR, QM_REG_VOQQMASK_3_LSB, 0x2}, - {OP_WR_E1, QM_REG_VOQQMASK_4_LSB, 0xc0}, - {OP_WR_E1H, QM_REG_VOQQMASK_3_LSB_EXT_A, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_4_MSB, 0xc0}, - {OP_WR_E1H, QM_REG_VOQQMASK_3_MSB_EXT_A, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_5_LSB, 0x1e00}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_LSB, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_5_MSB, 0x1e00}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_MSB, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_6_LSB, 0x4000}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_LSB_EXT_A, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_6_MSB, 0x4000}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_MSB_EXT_A, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_7_LSB, 0x8000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_LSB, 0x1e001e00}, - {OP_WR_E1, QM_REG_VOQQMASK_7_MSB, 0x8000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_MSB, 0x1e001e00}, - {OP_WR_E1, QM_REG_VOQQMASK_8_LSB, 0x2000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_LSB_EXT_A, 0x1e001e00}, - {OP_WR_E1, QM_REG_VOQQMASK_8_MSB, 0x2000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_MSB_EXT_A, 0x1e001e00}, - {OP_ZR_E1, QM_REG_VOQQMASK_9_LSB, 0x7}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_LSB, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_MSB, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_LSB_EXT_A, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_MSB_EXT_A, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_LSB, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_MSB, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_LSB_EXT_A, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_MSB_EXT_A, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_LSB, 0x20002000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_MSB, 0x20002000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_LSB_EXT_A, 0x20002000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_MSB_EXT_A, 0x20002000}, - {OP_ZR_E1H, QM_REG_VOQQMASK_9_LSB, 0x2}, - {OP_WR_E1H, QM_REG_VOQQMASK_9_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_9_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_LSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_MSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_LSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_MSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQPORT_0, 0x0}, - {OP_WR, QM_REG_VOQPORT_1, 0x1}, - {OP_ZR, QM_REG_VOQPORT_2, 0xa}, - {OP_WR, QM_REG_CMINTVOQMASK_0, 0xc08}, - {OP_WR, QM_REG_CMINTVOQMASK_1, 0x40}, - {OP_WR, QM_REG_CMINTVOQMASK_2, 0x100}, - {OP_WR, QM_REG_CMINTVOQMASK_3, 0x20}, - {OP_WR, QM_REG_CMINTVOQMASK_4, 0x17}, - {OP_WR, QM_REG_CMINTVOQMASK_5, 0x80}, - {OP_WR, QM_REG_CMINTVOQMASK_6, 0x200}, - {OP_WR, QM_REG_CMINTVOQMASK_7, 0x0}, - {OP_WR_E1, QM_REG_HWAEMPTYMASK_LSB, 0xffff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_LSB, 0x1ff01ff}, - {OP_WR_E1, QM_REG_HWAEMPTYMASK_MSB, 0xffff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_MSB, 0x1ff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_LSB_EXT_A, 0x1ff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_MSB_EXT_A, 0x1ff01ff}, - {OP_WR, QM_REG_ENBYPVOQMASK, 0x13}, - {OP_WR, QM_REG_VOQCREDITAFULLTHR, 0x13f}, - {OP_WR, QM_REG_VOQINITCREDIT_0, 0x140}, - {OP_WR, QM_REG_VOQINITCREDIT_1, 0x140}, - {OP_ZR, QM_REG_VOQINITCREDIT_2, 0x2}, - {OP_WR, QM_REG_VOQINITCREDIT_4, 0xc0}, - {OP_ZR, QM_REG_VOQINITCREDIT_5, 0x7}, - {OP_WR, QM_REG_TASKCRDCOST_0, 0x48}, - {OP_WR, QM_REG_TASKCRDCOST_1, 0x48}, - {OP_ZR, QM_REG_TASKCRDCOST_2, 0x2}, - {OP_WR, QM_REG_TASKCRDCOST_4, 0x48}, - {OP_ZR, QM_REG_TASKCRDCOST_5, 0x7}, - {OP_WR, QM_REG_BYTECRDINITVAL, 0x8000}, - {OP_WR, QM_REG_BYTECRDCOST, 0x25e4}, - {OP_WR, QM_REG_BYTECREDITAFULLTHR, 0x7fff}, - {OP_WR_E1, QM_REG_ENBYTECRD_LSB, 0x7}, - {OP_WR_E1H, QM_REG_ENBYTECRD_LSB, 0x70007}, - {OP_WR_E1, QM_REG_ENBYTECRD_MSB, 0x7}, - {OP_WR_E1H, QM_REG_ENBYTECRD_MSB, 0x70007}, - {OP_WR_E1H, QM_REG_ENBYTECRD_LSB_EXT_A, 0x70007}, - {OP_WR_E1H, QM_REG_ENBYTECRD_MSB_EXT_A, 0x70007}, - {OP_WR, QM_REG_BYTECRDPORT_LSB, 0x0}, - {OP_WR, QM_REG_BYTECRDPORT_MSB, 0xffffffff}, - {OP_WR_E1, QM_REG_FUNCNUMSEL_LSB, 0x0}, - {OP_WR_E1H, QM_REG_BYTECRDPORT_LSB_EXT_A, 0x0}, - {OP_WR_E1, QM_REG_FUNCNUMSEL_MSB, 0xffffffff}, - {OP_WR_E1H, QM_REG_BYTECRDPORT_MSB_EXT_A, 0xffffffff}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_0, 0x0}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_1, 0x2}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_2, 0x1}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_3, 0x3}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_4, 0x4}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_5, 0x6}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_6, 0x5}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_7, 0x7}, - {OP_WR, QM_REG_CMINTEN, 0xff}, -#define QM_COMMON_END 1456 -#define PBF_COMMON_START 1456 - {OP_WR, PBF_REG_INIT, 0x1}, - {OP_WR, PBF_REG_INIT_P4, 0x1}, - {OP_WR, PBF_REG_MAC_LB_ENABLE, 0x1}, - {OP_WR, PBF_REG_IF_ENABLE_REG, 0x7fff}, - {OP_WR, PBF_REG_INIT_P4, 0x0}, - {OP_WR, PBF_REG_INIT, 0x0}, - {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P4, 0x0}, -#define PBF_COMMON_END 1463 -#define PBF_PORT0_START 1463 - {OP_WR, PBF_REG_INIT_P0, 0x1}, - {OP_WR, PBF_REG_MAC_IF0_ENABLE, 0x1}, - {OP_WR, PBF_REG_INIT_P0, 0x0}, - {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P0, 0x0}, -#define PBF_PORT0_END 1467 -#define PBF_PORT1_START 1467 - {OP_WR, PBF_REG_INIT_P1, 0x1}, - {OP_WR, PBF_REG_MAC_IF1_ENABLE, 0x1}, - {OP_WR, PBF_REG_INIT_P1, 0x0}, - {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P1, 0x0}, -#define PBF_PORT1_END 1471 -#define XCM_COMMON_START 1471 - {OP_WR, XCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, XCM_REG_XQM_XCM_HDR_P, 0x3150020}, - {OP_WR, XCM_REG_XQM_XCM_HDR_S, 0x3150020}, - {OP_WR, XCM_REG_TM_XCM_HDR, 0x1000030}, - {OP_WR, XCM_REG_ERR_XCM_HDR, 0x8100000}, - {OP_WR, XCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, XCM_REG_EXPR_EVNT_ID, 0x30}, - {OP_WR, XCM_REG_STOP_EVNT_ID, 0x31}, - {OP_WR, XCM_REG_STORM_WEIGHT, 0x3}, - {OP_WR, XCM_REG_TSEM_WEIGHT, 0x6}, - {OP_WR, XCM_REG_CSEM_WEIGHT, 0x3}, - {OP_WR, XCM_REG_USEM_WEIGHT, 0x3}, - {OP_WR, XCM_REG_DORQ_WEIGHT, 0x2}, - {OP_WR, XCM_REG_PBF_WEIGHT, 0x0}, - {OP_WR, XCM_REG_NIG0_WEIGHT, 0x2}, - {OP_WR, XCM_REG_CP_WEIGHT, 0x0}, - {OP_WR, XCM_REG_XSDM_WEIGHT, 0x6}, - {OP_WR, XCM_REG_XQM_P_WEIGHT, 0x4}, - {OP_WR, XCM_REG_XQM_S_WEIGHT, 0x2}, - {OP_WR, XCM_REG_TM_WEIGHT, 0x2}, - {OP_WR, XCM_REG_XCM_XQM_USE_Q, 0x1}, - {OP_WR, XCM_REG_XQM_BYP_ACT_UPD, 0x6}, - {OP_WR, XCM_REG_UNA_GT_NXT_Q, 0x0}, - {OP_WR, XCM_REG_AUX1_Q, 0x2}, - {OP_WR, XCM_REG_AUX_CNT_FLG_Q_19, 0x1}, - {OP_WR, XCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, XCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, XCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, XCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, XCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, XCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, XCM_REG_TM_INIT_CRD, 0x4}, - {OP_WR, XCM_REG_XQM_INIT_CRD, 0x20}, - {OP_WR, XCM_REG_XX_INIT_CRD, 0x2}, - {OP_WR_E1, XCM_REG_XX_MSG_NUM, 0x1f}, - {OP_WR_E1H, XCM_REG_XX_MSG_NUM, 0x20}, - {OP_ZR, XCM_REG_XX_TABLE, 0x12}, - {OP_SW_E1, XCM_REG_XX_DESCR_TABLE, 0x1f02d4}, - {OP_SW_E1H, XCM_REG_XX_DESCR_TABLE, 0x1f0329}, - {OP_WR, XCM_REG_N_SM_CTX_LD_0, 0xf}, - {OP_WR, XCM_REG_N_SM_CTX_LD_1, 0x7}, - {OP_WR, XCM_REG_N_SM_CTX_LD_2, 0xb}, - {OP_WR, XCM_REG_N_SM_CTX_LD_3, 0xe}, - {OP_ZR_E1, XCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR_E1H, XCM_REG_N_SM_CTX_LD_4, 0xe}, - {OP_ZR_E1H, XCM_REG_N_SM_CTX_LD_5, 0x3}, - {OP_WR, XCM_REG_XCM_REG0_SZ, 0x4}, - {OP_WR, XCM_REG_XCM_STORM0_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_STORM1_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_XQM_IFEN, 0x1}, - {OP_WR, XCM_REG_STORM_XCM_IFEN, 0x1}, - {OP_WR, XCM_REG_XQM_XCM_IFEN, 0x1}, - {OP_WR, XCM_REG_XSDM_IFEN, 0x1}, - {OP_WR, XCM_REG_TM_XCM_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_TM_IFEN, 0x1}, - {OP_WR, XCM_REG_TSEM_IFEN, 0x1}, - {OP_WR, XCM_REG_CSEM_IFEN, 0x1}, - {OP_WR, XCM_REG_USEM_IFEN, 0x1}, - {OP_WR, XCM_REG_DORQ_IFEN, 0x1}, - {OP_WR, XCM_REG_PBF_IFEN, 0x1}, - {OP_WR, XCM_REG_NIG0_IFEN, 0x1}, - {OP_WR, XCM_REG_NIG1_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_CFC_IFEN, 0x1}, -#define XCM_COMMON_END 1538 -#define XCM_PORT0_START 1538 - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, -#define XCM_PORT0_END 1546 -#define XCM_PORT1_START 1546 - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, -#define XCM_PORT1_END 1554 -#define XCM_FUNC0_START 1554 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC0_END 1563 -#define XCM_FUNC1_START 1563 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC1_END 1572 -#define XCM_FUNC2_START 1572 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC2_END 1581 -#define XCM_FUNC3_START 1581 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC3_END 1590 -#define XCM_FUNC4_START 1590 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC4_END 1599 -#define XCM_FUNC5_START 1599 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC5_END 1608 -#define XCM_FUNC6_START 1608 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC6_END 1617 -#define XCM_FUNC7_START 1617 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC7_END 1626 -#define XSEM_COMMON_START 1626 - {OP_RD, XSEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, XSEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, XSEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, XSEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, XSEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, XSEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, XSEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, XSEM_REG_TS_0_AS, 0x0}, - {OP_WR, XSEM_REG_TS_1_AS, 0x1}, - {OP_WR, XSEM_REG_TS_2_AS, 0x4}, - {OP_WR, XSEM_REG_TS_3_AS, 0x0}, - {OP_WR, XSEM_REG_TS_4_AS, 0x1}, - {OP_WR, XSEM_REG_TS_5_AS, 0x3}, - {OP_WR, XSEM_REG_TS_6_AS, 0x0}, - {OP_WR, XSEM_REG_TS_7_AS, 0x1}, - {OP_WR, XSEM_REG_TS_8_AS, 0x4}, - {OP_WR, XSEM_REG_TS_9_AS, 0x0}, - {OP_WR, XSEM_REG_TS_10_AS, 0x1}, - {OP_WR, XSEM_REG_TS_11_AS, 0x3}, - {OP_WR, XSEM_REG_TS_12_AS, 0x0}, - {OP_WR, XSEM_REG_TS_13_AS, 0x1}, - {OP_WR, XSEM_REG_TS_14_AS, 0x4}, - {OP_WR, XSEM_REG_TS_15_AS, 0x0}, - {OP_WR, XSEM_REG_TS_16_AS, 0x4}, - {OP_WR, XSEM_REG_TS_17_AS, 0x3}, - {OP_ZR, XSEM_REG_TS_18_AS, 0x2}, - {OP_WR, XSEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, XSEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, XSEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, XSEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, XSEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, XSEM_REG_THREADS_LIST, 0xffff}, - {OP_ZR, XSEM_REG_PASSIVE_BUFFER, 0x800}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18000, 0x0}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18040, 0x18}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18080, 0xc}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x180c0, 0x66}, - {OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18300, 0x7a120}, - {OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18300, 0x138}, - {OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18300, 0x1388}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18340, 0x1f4}, - {OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18340, 0x0}, - {OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18340, 0x5}, - {OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18380, 0x4c4b4}, - {OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18380, 0x1dcd6500}, - {OP_WR_EMUL_E1H, XSEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18380, 0x4c4b40}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3d60, 0x4}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d60 + 0x10, 0x202f3}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x29c8, 0x4}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3000, 0x48}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29c8 + 0x10, 0x20348}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2080, 0x48}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9020, 0xc8}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3128, 0x8e}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9000, 0x2}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3368, 0x0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x21a8, 0x86}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3370, 0x202f5}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2000, 0x20}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3b90, 0x402f7}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x23c8, 0x0}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3e20, 0x202fb}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x23d0, 0x2034a}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1518, 0x1}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2498, 0x4034c}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1830, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2c20, 0x0}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1838, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2c10, 0x0}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1820, 0x202fd}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2c08, 0x20350}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4ac0, 0x2}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3010, 0x1}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b00, 0x4}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x4040, 0x10}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1f48, 0x202ff}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x4000, 0x100352}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6ac0, 0x2}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b00, 0x4}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x8408, 0x20362}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x0}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100301}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100364}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x1000000}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80311}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80374}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x2000000}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c60, 0x80319}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c60, 0x8037c}, - {OP_ZP_E1, XSEM_REG_INT_TABLE, 0xb50000}, - {OP_ZP_E1H, XSEM_REG_INT_TABLE, 0xbd0000}, - {OP_WR_64_E1, XSEM_REG_INT_TABLE + 0x368, 0x130321}, - {OP_WR_64_E1H, XSEM_REG_INT_TABLE + 0x3a8, 0xb0384}, - {OP_ZP_E1, XSEM_REG_PRAM, 0x33660000}, - {OP_ZP_E1H, XSEM_REG_PRAM, 0x34060000}, - {OP_ZP_E1, XSEM_REG_PRAM + 0x8000, 0x38b30cda}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x8000, 0x37960d02}, - {OP_ZP_E1, XSEM_REG_PRAM + 0x10000, 0x3bb11b07}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x10000, 0x3bc31ae8}, - {OP_ZP_E1, XSEM_REG_PRAM + 0x18000, 0x2a2629f4}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x18000, 0x382629d9}, - {OP_WR_64_E1, XSEM_REG_PRAM + 0x1d6c0, 0x45280323}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x20000, 0x124537e3}, - {OP_WR_64_E1H, XSEM_REG_PRAM + 0x22220, 0x3bbc0386}, -#define XSEM_COMMON_END 1741 -#define XSEM_PORT0_START 1741 - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3ba0, 0x14}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc000, 0xfc}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3c40, 0x24}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x24a8, 0x14}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1400, 0xa}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2548, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1450, 0x6}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2668, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3378, 0xfc}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2788, 0x24}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b58, 0x0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x28a8, 0x24}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d78, 0x20325}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa000, 0x28}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d88, 0x100327}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa140, 0xc}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1500, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29e0, 0x20388}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1508, 0x1}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3000, 0x1}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5020, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5030, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5000, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5010, 0x2}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x5040, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x5208, 0x1}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x5048, 0xe}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ac8, 0x2038a}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50b8, 0x1}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b10, 0x42}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ac8, 0x20337}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d20, 0x4}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b10, 0x42}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d20, 0x4}, -#define XSEM_PORT0_END 1775 -#define XSEM_PORT1_START 1775 - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3bf0, 0x14}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc3f0, 0xfc}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3cd0, 0x24}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x24f8, 0x14}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1428, 0xa}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x25d8, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1468, 0x6}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x26f8, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3768, 0xfc}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2818, 0x24}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b5c, 0x0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2938, 0x24}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d80, 0x20339}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa0a0, 0x28}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3dc8, 0x10033b}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa170, 0xc}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1504, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29e8, 0x2038c}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x150c, 0x1}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3004, 0x1}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5028, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5038, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5008, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5018, 0x2}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x5044, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x520c, 0x1}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x5080, 0xe}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ad0, 0x2038e}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50bc, 0x1}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6c18, 0x42}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ad0, 0x2034b}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d30, 0x4}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4c18, 0x42}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d30, 0x4}, -#define XSEM_PORT1_END 1809 -#define XSEM_FUNC0_START 1809 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e0, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29f0, 0x100390}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5048, 0xe}, -#define XSEM_FUNC0_END 1812 -#define XSEM_FUNC1_START 1812 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e4, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a30, 0x1003a0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5080, 0xe}, -#define XSEM_FUNC1_END 1815 -#define XSEM_FUNC2_START 1815 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e8, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a70, 0x1003b0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50b8, 0xe}, -#define XSEM_FUNC2_END 1818 -#define XSEM_FUNC3_START 1818 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7ec, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2ab0, 0x1003c0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50f0, 0xe}, -#define XSEM_FUNC3_END 1821 -#define XSEM_FUNC4_START 1821 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f0, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2af0, 0x1003d0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5128, 0xe}, -#define XSEM_FUNC4_END 1824 -#define XSEM_FUNC5_START 1824 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f4, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2b30, 0x1003e0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5160, 0xe}, -#define XSEM_FUNC5_END 1827 -#define XSEM_FUNC6_START 1827 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f8, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2b70, 0x1003f0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5198, 0xe}, -#define XSEM_FUNC6_END 1830 -#define XSEM_FUNC7_START 1830 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7fc, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2bb0, 0x100400}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x51d0, 0xe}, -#define XSEM_FUNC7_END 1833 -#define CDU_COMMON_START 1833 - {OP_WR, CDU_REG_CDU_CONTROL0, 0x1}, - {OP_WR_E1H, CDU_REG_MF_MODE, 0x1}, - {OP_WR, CDU_REG_CDU_CHK_MASK0, 0x3d000}, - {OP_WR, CDU_REG_CDU_CHK_MASK1, 0x3d}, - {OP_WB_E1, CDU_REG_L1TT, 0x200034d}, - {OP_WB_E1H, CDU_REG_L1TT, 0x2000410}, - {OP_WB_E1, CDU_REG_MATT, 0x20054d}, - {OP_WB_E1H, CDU_REG_MATT, 0x280610}, - {OP_ZR_E1, CDU_REG_MATT + 0x80, 0x2}, - {OP_WB_E1, CDU_REG_MATT + 0x88, 0x6056d}, - {OP_ZR, CDU_REG_MATT + 0xa0, 0x18}, -#define CDU_COMMON_END 1844 -#define DMAE_COMMON_START 1844 - {OP_ZR, DMAE_REG_CMD_MEM, 0xe0}, - {OP_WR, DMAE_REG_CRC16C_INIT, 0x0}, - {OP_WR, DMAE_REG_CRC16T10_INIT, 0x1}, - {OP_WR_E1, DMAE_REG_PXP_REQ_INIT_CRD, 0x1}, - {OP_WR_E1H, DMAE_REG_PXP_REQ_INIT_CRD, 0x2}, - {OP_WR, DMAE_REG_PCI_IFEN, 0x1}, - {OP_WR, DMAE_REG_GRC_IFEN, 0x1}, -#define DMAE_COMMON_END 1851 -#define PXP_COMMON_START 1851 - {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x400, 0x50573}, - {OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x400, 0x50638}, - {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x420, 0x50578}, - {OP_WB_E1H, PXP_REG_HST_INBOUND_INT, 0x5063d}, - {OP_WB_E1, PXP_REG_HST_INBOUND_INT, 0x5057d}, - {OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x20, 0x50642}, -#define PXP_COMMON_END 1857 -#define CFC_COMMON_START 1857 - {OP_ZR_E1H, CFC_REG_LINK_LIST, 0x100}, - {OP_WR, CFC_REG_CONTROL0, 0x10}, - {OP_WR, CFC_REG_DISABLE_ON_ERROR, 0x3fff}, - {OP_WR, CFC_REG_INTERFACES, 0x280000}, - {OP_WR, CFC_REG_LCREQ_WEIGHTS, 0x84924a}, - {OP_WR, CFC_REG_INTERFACES, 0x0}, -#define CFC_COMMON_END 1863 -#define HC_COMMON_START 1863 - {OP_ZR_E1, HC_REG_USTORM_ADDR_FOR_COALESCE, 0x4}, -#define HC_COMMON_END 1864 -#define HC_PORT0_START 1864 - {OP_WR_E1, HC_REG_CONFIG_0, 0x1080}, - {OP_ZR_E1, HC_REG_UC_RAM_ADDR_0, 0x2}, - {OP_WR_E1, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1, HC_REG_LEADING_EDGE_0, 0xffff}, - {OP_WR_E1, HC_REG_TRAILING_EDGE_0, 0xffff}, - {OP_WR_E1, HC_REG_AGG_INT_0, 0x0}, - {OP_WR_E1, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_PORT0_END 1882 -#define HC_PORT1_START 1882 - {OP_WR_E1, HC_REG_CONFIG_1, 0x1080}, - {OP_ZR_E1, HC_REG_UC_RAM_ADDR_1, 0x2}, - {OP_WR_E1, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1, HC_REG_LEADING_EDGE_1, 0xffff}, - {OP_WR_E1, HC_REG_TRAILING_EDGE_1, 0xffff}, - {OP_WR_E1, HC_REG_AGG_INT_1, 0x0}, - {OP_WR_E1, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_PORT1_END 1900 -#define HC_FUNC0_START 1900 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x0}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC0_END 1915 -#define HC_FUNC1_START 1915 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x1}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC1_END 1930 -#define HC_FUNC2_START 1930 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x2}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC2_END 1945 -#define HC_FUNC3_START 1945 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x3}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC3_END 1960 -#define HC_FUNC4_START 1960 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x4}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC4_END 1975 -#define HC_FUNC5_START 1975 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x5}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC5_END 1990 -#define HC_FUNC6_START 1990 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x6}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC6_END 2005 -#define HC_FUNC7_START 2005 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x7}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC7_END 2020 -#define PXP2_COMMON_START 2020 - {OP_WR_E1H, PXP2_REG_RQ_DRAM_ALIGN, 0x1}, - {OP_WR, PXP2_REG_PGL_CONTROL0, 0xe38340}, - {OP_WR, PXP2_REG_PGL_CONTROL1, 0x3c10}, - {OP_WR_E1H, PXP2_REG_RQ_ELT_DISABLE, 0x1}, - {OP_WR_E1H, PXP2_REG_WR_REV_MODE, 0x0}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_0, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_7, 0xffffffff}, - {OP_WR_E1, PXP2_REG_PGL_INT_USDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_7, 0xffffffff}, - {OP_WR_E1H, PXP2_REG_PGL_INT_XSDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_7, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_0, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_7, 0xffffffff}, - {OP_WR_E1, PXP2_REG_PGL_INT_XSDM_0, 0xffff3330}, - {OP_WR_E1H, PXP2_REG_PGL_INT_XSDM_0, 0xff802000}, - {OP_WR_E1, PXP2_REG_PGL_INT_XSDM_1, 0xffff3340}, - {OP_WR_E1H, PXP2_REG_PGL_INT_USDM_0, 0xf0005000}, - {OP_WR_E1, PXP2_REG_PGL_INT_USDM_0, 0xf0003000}, - {OP_WR_E1H, PXP2_REG_PGL_INT_USDM_1, 0xf0008000}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ6, 0x8}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ9, 0x8}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ10, 0x8}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ11, 0x2}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ17, 0x4}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ18, 0x5}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ19, 0x4}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ22, 0x0}, - {OP_WR, PXP2_REG_RD_START_INIT, 0x1}, - {OP_WR, PXP2_REG_WR_DMAE_TH, 0x3f}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD0, 0x40}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD1, 0x1808}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD2, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD3, 0x803}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD4, 0x40}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD5, 0x3}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD6, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD7, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD8, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD9, 0x10003}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD10, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD11, 0x803}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD12, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD13, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD14, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD15, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD16, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD17, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD18, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD19, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD20, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD22, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD23, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD24, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD25, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD26, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD27, 0x3}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD28, 0x2403}, - {OP_WR, PXP2_REG_RQ_BW_WR_ADD29, 0x2f}, - {OP_WR, PXP2_REG_RQ_BW_WR_ADD30, 0x9}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND0, 0x19}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB1, 0x184}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB2, 0x183}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB3, 0x306}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND4, 0x19}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND5, 0x6}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB6, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB7, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB8, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB9, 0xc86}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB10, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB11, 0x306}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND12, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND13, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND14, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND15, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND16, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND17, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND18, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND19, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND20, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND22, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND23, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND24, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND25, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND26, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND27, 0x6}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB28, 0x306}, - {OP_WR, PXP2_REG_RQ_BW_WR_UBOUND29, 0x13}, - {OP_WR, PXP2_REG_RQ_BW_WR_UBOUND30, 0x6}, - {OP_WR, PXP2_REG_PSWRQ_BW_L1, 0x1004}, - {OP_WR, PXP2_REG_PSWRQ_BW_L2, 0x1004}, - {OP_WR, PXP2_REG_PSWRQ_BW_RD, 0x106440}, - {OP_WR, PXP2_REG_PSWRQ_BW_WR, 0x106440}, - {OP_WR_E1H, PXP2_REG_RQ_ILT_MODE, 0x1}, - {OP_WR, PXP2_REG_RQ_RBC_DONE, 0x1}, -#define PXP2_COMMON_END 2137 -#define MISC_AEU_COMMON_START 2137 - {OP_ZR, MISC_REG_AEU_GENERAL_ATTN_0, 0x16}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_NIG_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_NIG_0, 0xf0000000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_PXP_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_PXP_0, 0x55555555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_PXP_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_0, 0xf0000000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_1, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_1, 0x55555555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_NIG_1, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_NIG_1, 0xf0000000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_PXP_1, 0x0}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_PXP_1, 0x10000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_PXP_1, 0x5014}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_1, 0x0}, - {OP_WR_E1H, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0xc00}, - {OP_WR_E1H, MISC_REG_AEU_GENERAL_MASK, 0x3}, -#define MISC_AEU_COMMON_END 2156 -#define MISC_AEU_PORT0_START 2156 - {OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xbf5c0000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xff5c0000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff51fef}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff55fff}, - {OP_WR, MISC_REG_AEU_ENABLE3_FUNC_0_OUT_0, 0xffff}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 0x500003e0}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 0xf00003e0}, - {OP_WR, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1, 0x0}, - {OP_WR, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_1, 0xa000}, - {OP_ZR, MISC_REG_AEU_ENABLE3_FUNC_0_OUT_1, 0x5}, - {OP_WR, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_2, 0xfe00000}, - {OP_ZR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3, 0x14}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3, 0x7}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_4, 0x400}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_5, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_NIG_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_5, 0x1000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_NIG_0, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_6, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_PXP_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_6, 0x4000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_PXP_0, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_7, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_PXP_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_7, 0x10000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_PXP_0, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x4}, - {OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x0}, - {OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_0, 0x3}, - {OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_0, 0x7}, -#define MISC_AEU_PORT0_END 2188 -#define MISC_AEU_PORT1_START 2188 - {OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xbf5c0000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xff5c0000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff51fef}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff55fff}, - {OP_WR, MISC_REG_AEU_ENABLE3_FUNC_1_OUT_0, 0xffff}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 0x500003e0}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 0xf00003e0}, - {OP_WR, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1, 0x0}, - {OP_WR, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_1, 0xa000}, - {OP_ZR, MISC_REG_AEU_ENABLE3_FUNC_1_OUT_1, 0x5}, - {OP_WR, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_2, 0xfe00000}, - {OP_ZR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3, 0x14}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3, 0x7}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_NIG_1, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_4, 0x800}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_NIG_1, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_5, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_NIG_1, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_5, 0x2000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_NIG_1, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_6, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_PXP_1, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_6, 0x8000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_PXP_1, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_7, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_PXP_1, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_7, 0x20000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_PXP_1, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x4}, - {OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x0}, - {OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_1, 0x3}, - {OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_1, 0x7}, -#define MISC_AEU_PORT1_END 2220 - -}; - -static const u32 init_data_e1[] = { - 0x00010000, 0x000204c0, 0x00030980, 0x00040e40, 0x00051300, 0x000617c0, - 0x00071c80, 0x00082140, 0x00092600, 0x000a2ac0, 0x000b2f80, 0x000c3440, - 0x000d3900, 0x000e3dc0, 0x000f4280, 0x00104740, 0x00114c00, 0x001250c0, - 0x00135580, 0x00145a40, 0x00155f00, 0x001663c0, 0x00176880, 0x00186d40, - 0x00197200, 0x001a76c0, 0x001b7b80, 0x001c8040, 0x001d8500, 0x001e89c0, - 0x001f8e80, 0x00209340, 0x00002000, 0x00004000, 0x00006000, 0x00008000, - 0x0000a000, 0x0000c000, 0x0000e000, 0x00010000, 0x00012000, 0x00014000, - 0x00016000, 0x00018000, 0x0001a000, 0x0001c000, 0x0001e000, 0x00020000, - 0x00022000, 0x00024000, 0x00026000, 0x00028000, 0x0002a000, 0x0002c000, - 0x0002e000, 0x00030000, 0x00032000, 0x00034000, 0x00036000, 0x00038000, - 0x0003a000, 0x0003c000, 0x0003e000, 0x00040000, 0x00042000, 0x00044000, - 0x00046000, 0x00048000, 0x0004a000, 0x0004c000, 0x0004e000, 0x00050000, - 0x00052000, 0x00054000, 0x00056000, 0x00058000, 0x0005a000, 0x0005c000, - 0x0005e000, 0x00060000, 0x00062000, 0x00064000, 0x00066000, 0x00068000, - 0x0006a000, 0x0006c000, 0x0006e000, 0x00070000, 0x00072000, 0x00074000, - 0x00076000, 0x00078000, 0x0007a000, 0x0007c000, 0x0007e000, 0x00080000, - 0x00082000, 0x00084000, 0x00086000, 0x00088000, 0x0008a000, 0x0008c000, - 0x0008e000, 0x00090000, 0x00092000, 0x00094000, 0x00096000, 0x00098000, - 0x0009a000, 0x0009c000, 0x0009e000, 0x000a0000, 0x000a2000, 0x000a4000, - 0x000a6000, 0x000a8000, 0x000aa000, 0x000ac000, 0x000ae000, 0x000b0000, - 0x000b2000, 0x000b4000, 0x000b6000, 0x000b8000, 0x000ba000, 0x000bc000, - 0x000be000, 0x000c0000, 0x000c2000, 0x000c4000, 0x000c6000, 0x000c8000, - 0x000ca000, 0x000cc000, 0x000ce000, 0x000d0000, 0x000d2000, 0x000d4000, - 0x000d6000, 0x000d8000, 0x000da000, 0x000dc000, 0x000de000, 0x000e0000, - 0x000e2000, 0x000e4000, 0x000e6000, 0x000e8000, 0x000ea000, 0x000ec000, - 0x000ee000, 0x000f0000, 0x000f2000, 0x000f4000, 0x000f6000, 0x000f8000, - 0x000fa000, 0x000fc000, 0x000fe000, 0x00100000, 0x00102000, 0x00104000, - 0x00106000, 0x00108000, 0x0010a000, 0x0010c000, 0x0010e000, 0x00110000, - 0x00112000, 0x00114000, 0x00116000, 0x00118000, 0x0011a000, 0x0011c000, - 0x0011e000, 0x00120000, 0x00122000, 0x00124000, 0x00126000, 0x00128000, - 0x0012a000, 0x0012c000, 0x0012e000, 0x00130000, 0x00132000, 0x00134000, - 0x00136000, 0x00138000, 0x0013a000, 0x0013c000, 0x0013e000, 0x00140000, - 0x00142000, 0x00144000, 0x00146000, 0x00148000, 0x0014a000, 0x0014c000, - 0x0014e000, 0x00150000, 0x00152000, 0x00154000, 0x00156000, 0x00158000, - 0x0015a000, 0x0015c000, 0x0015e000, 0x00160000, 0x00162000, 0x00164000, - 0x00166000, 0x00168000, 0x0016a000, 0x0016c000, 0x0016e000, 0x00170000, - 0x00172000, 0x00174000, 0x00176000, 0x00178000, 0x0017a000, 0x0017c000, - 0x0017e000, 0x00180000, 0x00182000, 0x00184000, 0x00186000, 0x00188000, - 0x0018a000, 0x0018c000, 0x0018e000, 0x00190000, 0x00192000, 0x00194000, - 0x00196000, 0x00198000, 0x0019a000, 0x0019c000, 0x0019e000, 0x001a0000, - 0x001a2000, 0x001a4000, 0x001a6000, 0x001a8000, 0x001aa000, 0x001ac000, - 0x001ae000, 0x001b0000, 0x001b2000, 0x001b4000, 0x001b6000, 0x001b8000, - 0x001ba000, 0x001bc000, 0x001be000, 0x001c0000, 0x001c2000, 0x001c4000, - 0x001c6000, 0x001c8000, 0x001ca000, 0x001cc000, 0x001ce000, 0x001d0000, - 0x001d2000, 0x001d4000, 0x001d6000, 0x001d8000, 0x001da000, 0x001dc000, - 0x001de000, 0x001e0000, 0x001e2000, 0x001e4000, 0x001e6000, 0x001e8000, - 0x001ea000, 0x001ec000, 0x001ee000, 0x001f0000, 0x001f2000, 0x001f4000, - 0x001f6000, 0x001f8000, 0x001fa000, 0x001fc000, 0x001fe000, 0x00200000, - 0x00202000, 0x00204000, 0x00206000, 0x00208000, 0x0020a000, 0x0020c000, - 0x0020e000, 0x00210000, 0x00212000, 0x00214000, 0x00216000, 0x00218000, - 0x0021a000, 0x0021c000, 0x0021e000, 0x00220000, 0x00222000, 0x00224000, - 0x00226000, 0x00228000, 0x0022a000, 0x0022c000, 0x0022e000, 0x00230000, - 0x00232000, 0x00234000, 0x00236000, 0x00238000, 0x0023a000, 0x0023c000, - 0x0023e000, 0x00240000, 0x00242000, 0x00244000, 0x00246000, 0x00248000, - 0x0024a000, 0x0024c000, 0x0024e000, 0x00250000, 0x00252000, 0x00254000, - 0x00256000, 0x00258000, 0x0025a000, 0x0025c000, 0x0025e000, 0x00260000, - 0x00262000, 0x00264000, 0x00266000, 0x00268000, 0x0026a000, 0x0026c000, - 0x0026e000, 0x00270000, 0x00272000, 0x00274000, 0x00276000, 0x00278000, - 0x0027a000, 0x0027c000, 0x0027e000, 0x00280000, 0x00282000, 0x00284000, - 0x00286000, 0x00288000, 0x0028a000, 0x0028c000, 0x0028e000, 0x00290000, - 0x00292000, 0x00294000, 0x00296000, 0x00298000, 0x0029a000, 0x0029c000, - 0x0029e000, 0x002a0000, 0x002a2000, 0x002a4000, 0x002a6000, 0x002a8000, - 0x002aa000, 0x002ac000, 0x002ae000, 0x002b0000, 0x002b2000, 0x002b4000, - 0x002b6000, 0x002b8000, 0x002ba000, 0x002bc000, 0x002be000, 0x002c0000, - 0x002c2000, 0x002c4000, 0x002c6000, 0x002c8000, 0x002ca000, 0x002cc000, - 0x002ce000, 0x002d0000, 0x002d2000, 0x002d4000, 0x002d6000, 0x002d8000, - 0x002da000, 0x002dc000, 0x002de000, 0x002e0000, 0x002e2000, 0x002e4000, - 0x002e6000, 0x002e8000, 0x002ea000, 0x002ec000, 0x002ee000, 0x002f0000, - 0x002f2000, 0x002f4000, 0x002f6000, 0x002f8000, 0x002fa000, 0x002fc000, - 0x002fe000, 0x00300000, 0x00302000, 0x00304000, 0x00306000, 0x00308000, - 0x0030a000, 0x0030c000, 0x0030e000, 0x00310000, 0x00312000, 0x00314000, - 0x00316000, 0x00318000, 0x0031a000, 0x0031c000, 0x0031e000, 0x00320000, - 0x00322000, 0x00324000, 0x00326000, 0x00328000, 0x0032a000, 0x0032c000, - 0x0032e000, 0x00330000, 0x00332000, 0x00334000, 0x00336000, 0x00338000, - 0x0033a000, 0x0033c000, 0x0033e000, 0x00340000, 0x00342000, 0x00344000, - 0x00346000, 0x00348000, 0x0034a000, 0x0034c000, 0x0034e000, 0x00350000, - 0x00352000, 0x00354000, 0x00356000, 0x00358000, 0x0035a000, 0x0035c000, - 0x0035e000, 0x00360000, 0x00362000, 0x00364000, 0x00366000, 0x00368000, - 0x0036a000, 0x0036c000, 0x0036e000, 0x00370000, 0x00372000, 0x00374000, - 0x00376000, 0x00378000, 0x0037a000, 0x0037c000, 0x0037e000, 0x00380000, - 0x00382000, 0x00384000, 0x00386000, 0x00388000, 0x0038a000, 0x0038c000, - 0x0038e000, 0x00390000, 0x00392000, 0x00394000, 0x00396000, 0x00398000, - 0x0039a000, 0x0039c000, 0x0039e000, 0x003a0000, 0x003a2000, 0x003a4000, - 0x003a6000, 0x003a8000, 0x003aa000, 0x003ac000, 0x003ae000, 0x003b0000, - 0x003b2000, 0x003b4000, 0x003b6000, 0x003b8000, 0x003ba000, 0x003bc000, - 0x003be000, 0x003c0000, 0x003c2000, 0x003c4000, 0x003c6000, 0x003c8000, - 0x003ca000, 0x003cc000, 0x003ce000, 0x003d0000, 0x003d2000, 0x003d4000, - 0x003d6000, 0x003d8000, 0x003da000, 0x003dc000, 0x003de000, 0x003e0000, - 0x003e2000, 0x003e4000, 0x003e6000, 0x003e8000, 0x003ea000, 0x003ec000, - 0x003ee000, 0x003f0000, 0x003f2000, 0x003f4000, 0x003f6000, 0x003f8000, - 0x003fa000, 0x003fc000, 0x003fe000, 0x003fe001, 0x00000000, 0x000001ff, - 0x00000200, 0x00000001, 0x00000003, 0x00bebc20, 0x00000003, 0x00bebc20, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00007ff8, 0x00000000, 0x00003500, - 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, - 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0x00000003, 0x00bebc20, 0x00002000, 0x000040c0, 0x00006180, 0x00008240, - 0x0000a300, 0x0000c3c0, 0x0000e480, 0x00010540, 0x00012600, 0x000146c0, - 0x00016780, 0x00018840, 0x0001a900, 0x0001c9c0, 0x0001ea80, 0x00020b40, - 0x00022c00, 0x00024cc0, 0x00026d80, 0x00028e40, 0x0002af00, 0x0002cfc0, - 0x0002f080, 0x00031140, 0x00033200, 0x000352c0, 0x00037380, 0x00039440, - 0x0003b500, 0x0003d5c0, 0x0003f680, 0x00041740, 0x00043800, 0x000458c0, - 0x00047980, 0x00049a40, 0x00008000, 0x00010380, 0x00018700, 0x00020a80, - 0x00028e00, 0x00031180, 0x00039500, 0x00041880, 0x00049c00, 0x00051f80, - 0x0005a300, 0x00062680, 0x0006aa00, 0x00072d80, 0x0007b100, 0x00083480, - 0x0008b800, 0x00093b80, 0x0009bf00, 0x000a4280, 0x000ac600, 0x000b4980, - 0x000bcd00, 0x000c5080, 0x000cd400, 0x000d5780, 0x000ddb00, 0x00001900, - 0x00000000, 0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8, - 0x00000000, 0x00001500, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x00000000, 0x00007ff8, 0x00000000, 0x00001500, 0x00001000, 0x00002080, - 0x00003100, 0x00004180, 0x00005200, 0x00006280, 0x00007300, 0x00008380, - 0x00009400, 0x0000a480, 0x0000b500, 0x0000c580, 0x0000d600, 0x0000e680, - 0x0000f700, 0x00010780, 0x00011800, 0x00012880, 0x00013900, 0x00014980, - 0x00015a00, 0x00016a80, 0x00017b00, 0x00018b80, 0x00019c00, 0x0001ac80, - 0x0001bd00, 0x0001cd80, 0x0001de00, 0x0001ee80, 0x0001ff00, 0x10000000, - 0x000028ad, 0x00000000, 0x00010001, 0x00350804, 0xccccccc1, 0xffffffff, - 0xffffffff, 0x7058103c, 0x00000000, 0xcccc0201, 0xcccccccc, 0x00000000, - 0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8, 0x00000000, - 0x00003500, 0x000e01b7, 0x011600d6, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x00100000, 0x00000000, 0x007201bb, 0x012300f3, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x00100000, 0x00000000, 0xfffffff3, - 0x320fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, - 0xcdcdcdcd, 0xfffffff1, 0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, - 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, - 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, - 0x31efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, - 0xcdcdcdcd, 0xfffffff5, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x310fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, - 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, - 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, - 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, - 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, - 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, 0x30efffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, - 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, - 0xcdcdcdcd, 0xfffffff3, 0x31efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, - 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, - 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, - 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, - 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, - 0xcdcdcdcd, 0xffffff97, 0x056fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, - 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x310fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, - 0x320fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, - 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, - 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, - 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffff8a, 0x042fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, - 0x05cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, - 0xcdcdcdcd, 0xfffffff5, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x300fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, - 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, - 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, - 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, - 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, - 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x040fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, - 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, - 0xcdcdcdcd, 0x00100000, 0x00070100, 0x00028170, 0x000b8198, 0x00020250, - 0x00010270, 0x000f0280, 0x00010370, 0x00080000, 0x00080080, 0x00028100, - 0x000b8128, 0x000201e0, 0x00010200, 0x00070210, 0x00020280, 0x000f0000, - 0x000800f0, 0x00028170, 0x000b8198, 0x00020250, 0x00010270, 0x000b8280, - 0x00080338, 0x00100000, 0x00080100, 0x00028180, 0x000b81a8, 0x00020260, - 0x00018280, 0x000e8298, 0x00080380, 0x00028000, 0x000b8028, 0x000200e0, - 0x00010100, 0x00008110, 0x00000118, 0xcccccccc, 0xcccccccc, 0xcccccccc, - 0xcccccccc, 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, - 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000 -}; - -static const u32 init_data_e1h[] = { - 0x00010000, 0x000204c0, 0x00030980, 0x00040e40, 0x00051300, 0x000617c0, - 0x00071c80, 0x00082140, 0x00092600, 0x000a2ac0, 0x000b2f80, 0x000c3440, - 0x000d3900, 0x000e3dc0, 0x000f4280, 0x00104740, 0x00114c00, 0x001250c0, - 0x00135580, 0x00145a40, 0x00155f00, 0x001663c0, 0x00176880, 0x00186d40, - 0x00197200, 0x001a76c0, 0x001b7b80, 0x001c8040, 0x001d8500, 0x001e89c0, - 0x001f8e80, 0x00209340, 0x00002000, 0x00004000, 0x00006000, 0x00008000, - 0x0000a000, 0x0000c000, 0x0000e000, 0x00010000, 0x00012000, 0x00014000, - 0x00016000, 0x00018000, 0x0001a000, 0x0001c000, 0x0001e000, 0x00020000, - 0x00022000, 0x00024000, 0x00026000, 0x00028000, 0x0002a000, 0x0002c000, - 0x0002e000, 0x00030000, 0x00032000, 0x00034000, 0x00036000, 0x00038000, - 0x0003a000, 0x0003c000, 0x0003e000, 0x00040000, 0x00042000, 0x00044000, - 0x00046000, 0x00048000, 0x0004a000, 0x0004c000, 0x0004e000, 0x00050000, - 0x00052000, 0x00054000, 0x00056000, 0x00058000, 0x0005a000, 0x0005c000, - 0x0005e000, 0x00060000, 0x00062000, 0x00064000, 0x00066000, 0x00068000, - 0x0006a000, 0x0006c000, 0x0006e000, 0x00070000, 0x00072000, 0x00074000, - 0x00076000, 0x00078000, 0x0007a000, 0x0007c000, 0x0007e000, 0x00080000, - 0x00082000, 0x00084000, 0x00086000, 0x00088000, 0x0008a000, 0x0008c000, - 0x0008e000, 0x00090000, 0x00092000, 0x00094000, 0x00096000, 0x00098000, - 0x0009a000, 0x0009c000, 0x0009e000, 0x000a0000, 0x000a2000, 0x000a4000, - 0x000a6000, 0x000a8000, 0x000aa000, 0x000ac000, 0x000ae000, 0x000b0000, - 0x000b2000, 0x000b4000, 0x000b6000, 0x000b8000, 0x000ba000, 0x000bc000, - 0x000be000, 0x000c0000, 0x000c2000, 0x000c4000, 0x000c6000, 0x000c8000, - 0x000ca000, 0x000cc000, 0x000ce000, 0x000d0000, 0x000d2000, 0x000d4000, - 0x000d6000, 0x000d8000, 0x000da000, 0x000dc000, 0x000de000, 0x000e0000, - 0x000e2000, 0x000e4000, 0x000e6000, 0x000e8000, 0x000ea000, 0x000ec000, - 0x000ee000, 0x000f0000, 0x000f2000, 0x000f4000, 0x000f6000, 0x000f8000, - 0x000fa000, 0x000fc000, 0x000fe000, 0x00100000, 0x00102000, 0x00104000, - 0x00106000, 0x00108000, 0x0010a000, 0x0010c000, 0x0010e000, 0x00110000, - 0x00112000, 0x00114000, 0x00116000, 0x00118000, 0x0011a000, 0x0011c000, - 0x0011e000, 0x00120000, 0x00122000, 0x00124000, 0x00126000, 0x00128000, - 0x0012a000, 0x0012c000, 0x0012e000, 0x00130000, 0x00132000, 0x00134000, - 0x00136000, 0x00138000, 0x0013a000, 0x0013c000, 0x0013e000, 0x00140000, - 0x00142000, 0x00144000, 0x00146000, 0x00148000, 0x0014a000, 0x0014c000, - 0x0014e000, 0x00150000, 0x00152000, 0x00154000, 0x00156000, 0x00158000, - 0x0015a000, 0x0015c000, 0x0015e000, 0x00160000, 0x00162000, 0x00164000, - 0x00166000, 0x00168000, 0x0016a000, 0x0016c000, 0x0016e000, 0x00170000, - 0x00172000, 0x00174000, 0x00176000, 0x00178000, 0x0017a000, 0x0017c000, - 0x0017e000, 0x00180000, 0x00182000, 0x00184000, 0x00186000, 0x00188000, - 0x0018a000, 0x0018c000, 0x0018e000, 0x00190000, 0x00192000, 0x00194000, - 0x00196000, 0x00198000, 0x0019a000, 0x0019c000, 0x0019e000, 0x001a0000, - 0x001a2000, 0x001a4000, 0x001a6000, 0x001a8000, 0x001aa000, 0x001ac000, - 0x001ae000, 0x001b0000, 0x001b2000, 0x001b4000, 0x001b6000, 0x001b8000, - 0x001ba000, 0x001bc000, 0x001be000, 0x001c0000, 0x001c2000, 0x001c4000, - 0x001c6000, 0x001c8000, 0x001ca000, 0x001cc000, 0x001ce000, 0x001d0000, - 0x001d2000, 0x001d4000, 0x001d6000, 0x001d8000, 0x001da000, 0x001dc000, - 0x001de000, 0x001e0000, 0x001e2000, 0x001e4000, 0x001e6000, 0x001e8000, - 0x001ea000, 0x001ec000, 0x001ee000, 0x001f0000, 0x001f2000, 0x001f4000, - 0x001f6000, 0x001f8000, 0x001fa000, 0x001fc000, 0x001fe000, 0x00200000, - 0x00202000, 0x00204000, 0x00206000, 0x00208000, 0x0020a000, 0x0020c000, - 0x0020e000, 0x00210000, 0x00212000, 0x00214000, 0x00216000, 0x00218000, - 0x0021a000, 0x0021c000, 0x0021e000, 0x00220000, 0x00222000, 0x00224000, - 0x00226000, 0x00228000, 0x0022a000, 0x0022c000, 0x0022e000, 0x00230000, - 0x00232000, 0x00234000, 0x00236000, 0x00238000, 0x0023a000, 0x0023c000, - 0x0023e000, 0x00240000, 0x00242000, 0x00244000, 0x00246000, 0x00248000, - 0x0024a000, 0x0024c000, 0x0024e000, 0x00250000, 0x00252000, 0x00254000, - 0x00256000, 0x00258000, 0x0025a000, 0x0025c000, 0x0025e000, 0x00260000, - 0x00262000, 0x00264000, 0x00266000, 0x00268000, 0x0026a000, 0x0026c000, - 0x0026e000, 0x00270000, 0x00272000, 0x00274000, 0x00276000, 0x00278000, - 0x0027a000, 0x0027c000, 0x0027e000, 0x00280000, 0x00282000, 0x00284000, - 0x00286000, 0x00288000, 0x0028a000, 0x0028c000, 0x0028e000, 0x00290000, - 0x00292000, 0x00294000, 0x00296000, 0x00298000, 0x0029a000, 0x0029c000, - 0x0029e000, 0x002a0000, 0x002a2000, 0x002a4000, 0x002a6000, 0x002a8000, - 0x002aa000, 0x002ac000, 0x002ae000, 0x002b0000, 0x002b2000, 0x002b4000, - 0x002b6000, 0x002b8000, 0x002ba000, 0x002bc000, 0x002be000, 0x002c0000, - 0x002c2000, 0x002c4000, 0x002c6000, 0x002c8000, 0x002ca000, 0x002cc000, - 0x002ce000, 0x002d0000, 0x002d2000, 0x002d4000, 0x002d6000, 0x002d8000, - 0x002da000, 0x002dc000, 0x002de000, 0x002e0000, 0x002e2000, 0x002e4000, - 0x002e6000, 0x002e8000, 0x002ea000, 0x002ec000, 0x002ee000, 0x002f0000, - 0x002f2000, 0x002f4000, 0x002f6000, 0x002f8000, 0x002fa000, 0x002fc000, - 0x002fe000, 0x00300000, 0x00302000, 0x00304000, 0x00306000, 0x00308000, - 0x0030a000, 0x0030c000, 0x0030e000, 0x00310000, 0x00312000, 0x00314000, - 0x00316000, 0x00318000, 0x0031a000, 0x0031c000, 0x0031e000, 0x00320000, - 0x00322000, 0x00324000, 0x00326000, 0x00328000, 0x0032a000, 0x0032c000, - 0x0032e000, 0x00330000, 0x00332000, 0x00334000, 0x00336000, 0x00338000, - 0x0033a000, 0x0033c000, 0x0033e000, 0x00340000, 0x00342000, 0x00344000, - 0x00346000, 0x00348000, 0x0034a000, 0x0034c000, 0x0034e000, 0x00350000, - 0x00352000, 0x00354000, 0x00356000, 0x00358000, 0x0035a000, 0x0035c000, - 0x0035e000, 0x00360000, 0x00362000, 0x00364000, 0x00366000, 0x00368000, - 0x0036a000, 0x0036c000, 0x0036e000, 0x00370000, 0x00372000, 0x00374000, - 0x00376000, 0x00378000, 0x0037a000, 0x0037c000, 0x0037e000, 0x00380000, - 0x00382000, 0x00384000, 0x00386000, 0x00388000, 0x0038a000, 0x0038c000, - 0x0038e000, 0x00390000, 0x00392000, 0x00394000, 0x00396000, 0x00398000, - 0x0039a000, 0x0039c000, 0x0039e000, 0x003a0000, 0x003a2000, 0x003a4000, - 0x003a6000, 0x003a8000, 0x003aa000, 0x003ac000, 0x003ae000, 0x003b0000, - 0x003b2000, 0x003b4000, 0x003b6000, 0x003b8000, 0x003ba000, 0x003bc000, - 0x003be000, 0x003c0000, 0x003c2000, 0x003c4000, 0x003c6000, 0x003c8000, - 0x003ca000, 0x003cc000, 0x003ce000, 0x003d0000, 0x003d2000, 0x003d4000, - 0x003d6000, 0x003d8000, 0x003da000, 0x003dc000, 0x003de000, 0x003e0000, - 0x003e2000, 0x003e4000, 0x003e6000, 0x003e8000, 0x003ea000, 0x003ec000, - 0x003ee000, 0x003f0000, 0x003f2000, 0x003f4000, 0x003f6000, 0x003f8000, - 0x003fa000, 0x003fc000, 0x003fe000, 0x003fe001, 0x00000000, 0x000001ff, - 0x00000200, 0x00000001, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00007ff8, - 0x00000000, 0x00003500, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, - 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0x00000003, 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, - 0xffffffff, 0x00000003, 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, - 0x00000000, 0xffffffff, 0x00000003, 0x00bebc20, 0xffffffff, 0x00000000, - 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, 0x00bebc20, 0xffffffff, - 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, 0x00bebc20, - 0x00002000, 0x000040c0, 0x00006180, 0x00008240, 0x0000a300, 0x0000c3c0, - 0x0000e480, 0x00010540, 0x00012600, 0x000146c0, 0x00016780, 0x00018840, - 0x0001a900, 0x0001c9c0, 0x0001ea80, 0x00020b40, 0x00022c00, 0x00024cc0, - 0x00026d80, 0x00028e40, 0x0002af00, 0x0002cfc0, 0x0002f080, 0x00031140, - 0x00033200, 0x000352c0, 0x00037380, 0x00039440, 0x0003b500, 0x0003d5c0, - 0x0003f680, 0x00041740, 0x00043800, 0x000458c0, 0x00047980, 0x00049a40, - 0x00008000, 0x00010380, 0x00018700, 0x00020a80, 0x00028e00, 0x00031180, - 0x00039500, 0x00041880, 0x00049c00, 0x00051f80, 0x0005a300, 0x00062680, - 0x0006aa00, 0x00072d80, 0x0007b100, 0x00083480, 0x0008b800, 0x00093b80, - 0x0009bf00, 0x000a4280, 0x000ac600, 0x000b4980, 0x000bcd00, 0x000c5080, - 0x000cd400, 0x000d5780, 0x000ddb00, 0x00001900, 0x00000028, 0x00100000, - 0x00000000, 0x00000000, 0xffffffff, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000, - 0x00007ff8, 0x00000000, 0x00001500, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x00000000, 0x00007ff8, 0x00000000, 0x00001500, 0x00001000, - 0x00002080, 0x00003100, 0x00004180, 0x00005200, 0x00006280, 0x00007300, - 0x00008380, 0x00009400, 0x0000a480, 0x0000b500, 0x0000c580, 0x0000d600, - 0x0000e680, 0x0000f700, 0x00010780, 0x00011800, 0x00012880, 0x00013900, - 0x00014980, 0x00015a00, 0x00016a80, 0x00017b00, 0x00018b80, 0x00019c00, - 0x0001ac80, 0x0001bd00, 0x0001cd80, 0x0001de00, 0x0001ee80, 0x0001ff00, - 0x10000000, 0x000028ad, 0x00000000, 0x00010001, 0x00350804, 0xccccccc5, - 0xffffffff, 0xffffffff, 0x7058103c, 0x00000000, 0xcccc0201, 0xcccccccc, - 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, - 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, - 0xcccc0201, 0xcccccccc, 0x00000000, 0xffffffff, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x00000000, 0x00007ff8, 0x00000000, 0x00003500, 0x000e0232, 0x011600d6, - 0x00100000, 0x00000000, 0x00720236, 0x012300f3, 0x00100000, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0xfffffff3, 0x320fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x30efffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, - 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, - 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, - 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, 0x31efffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x302fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, - 0xfffffff3, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, - 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, - 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, - 0xfffffff7, 0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x304fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x31efffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, - 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, - 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, - 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x056fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, - 0xfffffff5, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x320fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, - 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, - 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, - 0xffffff8a, 0x042fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, - 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x05cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x310fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, - 0xfffffff3, 0x316fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x302fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, - 0xfffffff6, 0x30bfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf314, 0xf3cf3cf3, - 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, - 0xfffffff7, 0x31cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0020cf3c, 0xcdcdcdcd, 0xfffffff0, 0x307fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0x00100000, 0x00070100, - 0x00028170, 0x000b8198, 0x00020250, 0x00010270, 0x000f0280, 0x00010370, - 0x00080000, 0x00080080, 0x00028100, 0x000b8128, 0x000201e0, 0x00010200, - 0x00070210, 0x00020280, 0x000f0000, 0x000800f0, 0x00028170, 0x000b8198, - 0x00020250, 0x00010270, 0x000b8280, 0x00080338, 0x00100000, 0x00080100, - 0x00028180, 0x000b81a8, 0x00020260, 0x00018280, 0x000e8298, 0x00080380, - 0x000b0000, 0x000100b0, 0x000280c0, 0x000580e8, 0x00020140, 0x00010160, - 0x000e0170, 0x00038250, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, - 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000, - 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x04002000 -}; - -static const u32 tsem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x19d9458a, 0x1138fc18, - 0x5980a1fc, 0xd8181998, 0x88039880, 0x81b8803d, 0x91a18191, 0xdafd7891, - 0xbf760862, 0x6ec30330, 0x0211e620, 0x1082239a, 0xf354029f, 0x0f5fc806, - 0x6512b315, 0x3a263860, 0x06a77ef0, 0x298d2ade, 0xc1124536, 0x1e4586de, - 0x93476f19, 0xca8922ff, 0xff4041df, 0x65296340, 0x229dbe54, 0x04a65e84, - 0xe4d1a5a1, 0xd7f2a1ed, 0x5192fea1, 0x0dee6ec6, 0xf8003ca8, 0x6065495c, - 0x00606549 -}; - -static const u32 tsem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7dedff00, 0xd554780b, 0x733ef0b5, 0x49999cce, - 0x424e4cce, 0x4c22f212, 0x21a08812, 0x8a80af0c, 0x2201277f, 0x282039f5, - 0x4201d458, 0xd4837908, 0xcdedaf4b, 0x11102484, 0x0547f435, 0x5088768b, - 0x340da2d1, 0x0ec160d2, 0x6d7b1420, 0xc0faf06f, 0x480bf5ea, 0xb12f3141, - 0xcbc57e20, 0xe7dad6bf, 0x264ce664, 0xafdbd880, 0xb4fdffff, 0xece7d9b8, - 0xebdaf7b3, 0x7b5ad7b5, 0x75923ded, 0xc7bf9302, 0x03fc45d8, 0x8c4d4fe5, - 0xf2c109b1, 0x80f66667, 0xc9b18727, 0x473afebd, 0x6d55633c, 0x9da23b19, - 0x99ec258c, 0x50281421, 0x2c23d5fe, 0xbfdf8250, 0xf097c365, 0x4219b6ff, - 0xd0977c3e, 0xc3e611e9, 0x02d5e4fb, 0x933a876b, 0xea0c319c, 0x4b19b98c, - 0x126b2c64, 0x4b223fa3, 0xe0ff828d, 0x8f392573, 0x27fc34b1, 0x61467574, - 0xc678c0ae, 0x5c531e32, 0x38a9d0d4, 0x843f7815, 0xbcd2c67f, 0x0731b725, - 0xbc03cf63, 0xbcf071c9, 0x61de3a5a, 0xc22eefe5, 0x3af3a1df, 0xae58cd6a, - 0x32773e30, 0x416589a7, 0xf3e33ebf, 0x3d6346ac, 0x4fe3d99b, 0xec3fc346, - 0x8c517ecc, 0xb1138f30, 0xcb3c018c, 0x632f0e54, 0x5467b2bd, 0x6a9b1f10, - 0x2c32a258, 0x852f0f58, 0x56338765, 0xed975e03, 0xf8165c16, 0x2f6c39fe, - 0xbed7e631, 0x15ead66b, 0xa362593e, 0xb50404a1, 0x67eff4e4, 0x11bfcb11, - 0x2b30fef1, 0xea4ab2a0, 0xaf805595, 0xfb765aaa, 0x67edfe95, 0x54e88933, - 0x5bf6b929, 0x5adefc61, 0xf1866ae6, 0x02d59997, 0x91fb2fac, 0x7a83e5d3, - 0x21476366, 0x36d0fa83, 0xc1198981, 0x9e00afef, 0x007f91db, 0xa52b2a1e, - 0x740642de, 0xb02bddec, 0x871c0ce6, 0x776cbbf7, 0x0c65f306, 0x6658e70c, - 0x32e73826, 0x74893a41, 0xd2073071, 0xf324bcc1, 0xcea84289, 0xb0f3dc54, - 0x9de29f7f, 0xe7f4ed87, 0x38e60b49, 0xf25700bd, 0x57a06650, 0x9d3ab5b1, - 0xea563265, 0xbe442969, 0x8decb538, 0x9e025855, 0xf7c02413, 0x08a78b7c, - 0x5798a9fb, 0xa780cd9d, 0x8d1859e6, 0xff2db43f, 0x0cf80933, 0xc4c5f3ba, - 0x76313f21, 0xf04f843c, 0x5a11f1cf, 0xde981c5d, 0xb08b2b97, 0x05f1091f, - 0x1f011772, 0x26a0423f, 0x544d28e0, 0x29fc573a, 0xd0a0d86b, 0xc3595bfa, - 0xe50069c6, 0x3f0cbc11, 0x0843ac61, 0x1cbd4be5, 0xb0ff3bba, 0x3c303b94, - 0x04f3d3ff, 0xab7e1274, 0x1fc8b700, 0xbfd97615, 0xca61f812, 0xf7c0e6ab, - 0x362a3f80, 0xd40b7e0b, 0xe8dbaf4d, 0x5e26f77d, 0x3765d80f, 0x16d74ff2, - 0xbdf00ba8, 0x1bf1fda5, 0x155ebf91, 0x3b763359, 0xfa84ca22, 0x3b06a4e5, - 0xc0750f1b, 0x578db147, 0xbbef362b, 0x692fbf1f, 0xf41b30b3, 0xf17bb157, - 0x7d42371d, 0xc33361f1, 0x6b5b1526, 0x2fa814e5, 0x582d0bf1, 0xf0e029ef, - 0xfe8976f9, 0xc7bed0ad, 0x1b389ed1, 0xc6ba73e8, 0x63329cca, 0xc4f6f675, - 0xa567c059, 0xf8851dfe, 0xc176e95d, 0xf29f6885, 0xc943d6ea, 0xb917af38, - 0x8b6d977c, 0x7f1d4e66, 0xab64f7f0, 0xbc1ef818, 0x64f3065f, 0xd662efd0, - 0xb07a8854, 0xd93aeb62, 0xebe20f69, 0xe34a8d74, 0x8bdfc9f4, 0x577c0e30, - 0xc2e08af9, 0x989a5629, 0x7bb0e517, 0xf3ce6db7, 0x56afce0a, 0xbce3b6ce, - 0x6ed8cb56, 0x2efe7fb1, 0xfea5cd54, 0xbc2172cd, 0x59b4dd2f, 0xdb910e2e, - 0x8c836db2, 0x1ac86d70, 0xd7208dec, 0xd7807841, 0x52f583b2, 0x0fa803d4, - 0x233cbf25, 0x852acf84, 0xb2cbe258, 0x1a73226d, 0xddd388f8, 0x13fc2ef7, - 0x6bdbe5f0, 0x74eabc27, 0x1aa7d3eb, 0x1aa8cedd, 0xbcdea51d, 0xf8f81119, - 0xc003a471, 0x827884d3, 0x9f06ad72, 0x97cb3263, 0x9b877fa0, 0x3cbb02a9, - 0xd999365f, 0xf563067c, 0xd2dd07b0, 0xd99750f5, 0xf582e652, 0x7bb1fa50, - 0x0493d42a, 0x9f3867ef, 0xc25bc17a, 0x2496abd7, 0x9579e00f, 0xfce0e6c0, - 0x30d0218f, 0xc0c955af, 0xa6f7809f, 0x8bcf7969, 0x3c7b0682, 0xb17f8bd6, - 0x39fa8326, 0xa198fd43, 0xf7cbac9f, 0x324e16a3, 0x9616a3f4, 0x8dfcfde8, - 0x595db1fa, 0x37854d3f, 0x2c29e118, 0x0491fbd5, 0xbf6f5768, 0x37a979b2, - 0x73c2364f, 0x13f53973, 0xbcc5d53b, 0x1ae7ae0a, 0xb776b03f, 0xed95ef08, - 0xb0d763b1, 0x5028be50, 0x0edb8005, 0x17ca1252, 0x0ca29331, 0x8eeb187c, - 0x27a1d433, 0x4175e4f5, 0x958813fd, 0x45397c69, 0x9f90bd26, 0x43faa562, - 0x85e90a29, 0x5ef06e87, 0x8e20eb83, 0x2ea192cd, 0x11ab477b, 0x14e01af8, - 0x60961258, 0x7ff52417, 0xf1ccdabf, 0x217a9050, 0x5f7c18fb, 0x8ecdea65, - 0xa635fa85, 0x6f116bfc, 0xe5eb812e, 0x63559128, 0x230b28bb, 0x233ab4fd, - 0x085f79ef, 0x00871a9e, 0xbf6085fd, 0x126f668d, 0xdaf8d7f2, 0xc0127c67, - 0xcc086ab7, 0x12ba0527, 0x60f8099e, 0xa43d5a3d, 0x69f10938, 0x43be4191, - 0xfc6197c7, 0x06ff1a1c, 0xc71ba3c4, 0xbe3fe84f, 0x61927325, 0x897a6b7c, - 0x0cab7c61, 0x4fbf03e3, 0xc6d66dad, 0xc0ddfc07, 0x99a134d8, 0x97a4b7c6, - 0x65abf8d0, 0x3f186256, 0x5bfc6faa, 0x819efe70, 0x83799fe6, 0xa5e9fe71, - 0x7ccbf9c6, 0x5f6ab3fe, 0xa28fc6d2, 0x5e16cff9, 0x2f4ff3e2, 0xf0b7f3e5, - 0x77c6fb7e, 0x5effe1f4, 0x8077bf9c, 0x93592df1, 0x5a1ff38d, 0x85bf9c6e, - 0xbb545f8f, 0xa15f1b53, 0x3b0917f1, 0x9687fcf9, 0xc5b2f8d3, 0x923e42eb, - 0xfdaaa353, 0x81a44f68, 0x1d260c40, 0x0472a6e5, 0x1fa00518, 0x04990a86, - 0x9c5143c7, 0x0145ceef, 0x7d4129bf, 0x5120fcc7, 0x352acfa0, 0x9edb2f9e, - 0xa59ea32f, 0x376889f7, 0x6d453ff1, 0x6c37ad22, 0x1c3fc5bd, 0x136eede0, - 0x5a2f587d, 0xa45f937f, 0xe5db8ef5, 0xf005c660, 0x1c9e5ff9, 0xaf3a1cd5, - 0x935172f0, 0x418764f9, 0xbe3c388e, 0x1aa23602, 0x26476be0, 0x9fac1098, - 0xc60a3d04, 0x7a0e3b2f, 0x6653cb14, 0x009c8f6e, 0x50e4cb3d, 0xf6e5a9b9, - 0x93bd8f88, 0x5bbaf303, 0xc4a4ff83, 0xb9727df1, 0x9ffc47e0, 0x4654b75b, - 0x09a8b4fd, 0x7910e98c, 0xd4e8d2af, 0x6fe2dbbb, 0x4e9f0816, 0x243dcfc4, - 0x97fd8c8a, 0xde2fd766, 0xddf0c830, 0x486fe63c, 0xd70bf682, 0xc2a21fce, - 0xc7307ffc, 0x53ed1632, 0x13548490, 0x354b31c9, 0xa7316f81, 0x15399d75, - 0x31ccf72a, 0xb9faec1b, 0x07fd635e, 0xb77ac625, 0xa1366fd9, 0x6044b1bd, - 0xfbdfa19b, 0xf5ef8daa, 0x71093671, 0x78daae9c, 0x78722777, 0x2c72c3ef, - 0xae89563e, 0x5bfcabf7, 0x87aa9e1d, 0xeb402ccd, 0x43024765, 0xc812fa3a, - 0x7caaf35e, 0xdef0e1de, 0x3dbab66f, 0x3ffdcf00, 0xe19f0912, 0x1ebc77f0, - 0x1d8136ed, 0x4be1b1d7, 0xe1b7da33, 0xff8709f3, 0xf3e11581, 0xf7d46551, - 0xcfe17df3, 0xf3849f39, 0xfe5b5553, 0xed2113a0, 0x3fbe5a2a, 0x7f0844e8, - 0x619b6d95, 0xcff12fa8, 0xbc5fb435, 0xfde1be61, 0x8625a6a2, 0x971b0bf7, - 0x7df3ea1a, 0x7fb4323f, 0xe1ad4560, 0x8fd57dfd, 0xa0ffde18, 0x3ea19d64, - 0xd0d1bbd7, 0x9b399efe, 0xaf4def0d, 0xe513bc8f, 0x915deea8, 0x5671bae1, - 0xda38f939, 0xc9156783, 0xb4f8f485, 0xe0e48926, 0xca938d74, 0x5671b6ee, - 0xc583d72f, 0x5e9c4c0c, 0x71af9ce1, 0x4665ea32, 0xc2aff3fa, 0xea0f9f05, - 0x849c137f, 0xcc83713f, 0x02c2c002, 0xe3e3eb8b, 0x7de4315e, 0x6fde65c7, - 0xd71f4100, 0x11d8bdff, 0xf35579f9, 0x046aa1fc, 0xb72821ff, 0xb9d7152c, - 0x0f7d6d1e, 0x302e5f7f, 0xc673e84f, 0xd79c9256, 0xb94ceb69, 0xf941f5cc, - 0xf402e4ce, 0x40e5cbbf, 0xc6a5f576, 0xa2a4016b, 0x3ceb449e, 0xa401f901, - 0x592fc0c0, 0xdceef906, 0x955c1227, 0xaf4013a8, 0xc19e63ae, 0x8133d426, - 0x8d77e903, 0x49dc3842, 0xa04b6f54, 0x66b3bd75, 0x1213a0fa, 0xe543c7d2, - 0xa87335a7, 0xa5e3593c, 0x094d44f2, 0xaa6bc795, 0x59a8eca9, 0x35c7e541, - 0xaa3f2a3e, 0xcff2a469, 0x1e544d35, 0xe540d9ad, 0x2a7e357b, 0x54dc6bbb, - 0xba2bf9f6, 0xecd78dfe, 0x80afcd55, 0x67ea8795, 0x43d4b9b4, 0x739276db, - 0xf9ca1257, 0x365ce519, 0x8e67e3da, 0x31996382, 0xf9c2be30, 0xba3a606d, - 0xf6295ec9, 0xf5c7fd03, 0xe28b6f7f, 0xd899b274, 0xd9a67074, 0xe17fc323, - 0x7543905a, 0x16065909, 0x7b0cd724, 0xed617e84, 0x8e5d7a43, 0x9bddcc4e, - 0x71e8133b, 0xe5bf99f2, 0xda75bf61, 0x407517fa, 0x059875a4, 0xbd21779e, - 0xeb46f042, 0x9aabef5a, 0xfe0cbfbe, 0xd7f0faba, 0xfbfe8e9e, 0xfea54141, - 0x985ab4cf, 0x13dc7884, 0x67e607ed, 0xef3f0e67, 0x965c7940, 0x444f5264, - 0x565e83c0, 0x4aa864b4, 0x66d3fae8, 0x12699fac, 0x7ad0b7a6, 0x35998cec, - 0x554af90a, 0xfa430c4f, 0xf7a95127, 0x56492cb3, 0x9ebc804f, 0xc31596de, - 0x5f3f6fd7, 0x12c7b707, 0x485f82bf, 0xf0deffed, 0x0e8fd40c, 0xecad630f, - 0x03ea2b13, 0xedf59778, 0xfd2672fd, 0x6c57e295, 0xda1cf98f, 0x7bf8160b, - 0x1207e291, 0xab7ef5d5, 0x659f445a, 0x6edf3e34, 0x73be0f18, 0xc5f73eea, - 0xadf14bcc, 0xc4864ec4, 0xf169d611, 0x366db2c6, 0xc4aeb8d5, 0x6d55ea1a, - 0x9d61aac9, 0xfc807fc1, 0x42416ab3, 0xb8d729be, 0x1a5247a8, 0xdcaf8005, - 0xab7ea4e4, 0xc2aede04, 0xe17b21da, 0xa72b5751, 0x9df040db, 0x94ec39ae, - 0xac4bde40, 0x7c0201e0, 0xa7232d25, 0x6aeb9ea2, 0x7b444bad, 0xf33c4cb0, - 0xf7c22790, 0x8d024d3b, 0xee6fc4b7, 0x1aa3ae35, 0x57e8307f, 0x167e4e7f, - 0xd4864e53, 0xcedc4d3b, 0x80f7ef0e, 0xf0e5efd6, 0x48fdb953, 0xfece8de1, - 0xfb6caa78, 0x1c92f642, 0x82f2ffc1, 0x57f1d278, 0x401cf26e, 0xedba5a7d, - 0x9fa3d918, 0x0fd97d9a, 0xf53f425f, 0x44929f9f, 0x5e7d5271, 0x6129303e, - 0x7c5a059c, 0x9ef7f817, 0xfd3d610f, 0x6ccddfec, 0x2ec7c00d, 0x6f782b40, - 0x13335fd6, 0xa17d4133, 0x5ad05b56, 0xcfdd7146, 0x2a8edc4c, 0xd1071e62, - 0xa1e53581, 0x4cc5d91d, 0x5d4f11d3, 0xb8c76dec, 0x329c3a10, 0x1667a4c9, - 0x18ed1a36, 0xf50d7fb0, 0xf58c1bc5, 0x11333662, 0x7af149f5, 0x340bf333, - 0xf7fbc33f, 0x7fe12a4d, 0x855eab31, 0xf9a4aaeb, 0x26540b23, 0x157c02a5, - 0x6f3679bf, 0x4c5fc63e, 0xe3d10fdc, 0x38e24b23, 0x7ef1a5fc, 0x3fef0dd9, - 0xf7771d69, 0x8b06488d, 0x89c6157f, 0x6d730c58, 0xfbf1fd65, 0x870fe16d, - 0xfbaf5f57, 0x383469c5, 0xdb826dc4, 0x2f7f811f, 0xeba67c68, 0xd5445beb, - 0x8ddc17e0, 0x21bf10f5, 0xb2e2d446, 0xee911322, 0x67d5aa5d, 0x14f7a18a, - 0xb4edf7b7, 0xde80eab8, 0x0679373f, 0x4ec81389, 0xed2165c8, 0xd2f26e7e, - 0xade14ef3, 0x995bb462, 0x3b45c814, 0xe218d614, 0x07e35953, 0x8b91ca31, - 0x833b66f1, 0x6fe81475, 0x9fa0f841, 0xdb92f655, 0xbbc62e58, 0xbfa1de41, - 0x87851cc7, 0x94dba805, 0x59fd8656, 0x7cf18c92, 0xaf58d39b, 0x1d207fc2, - 0x3f8a3046, 0xc2908f45, 0xa86018f0, 0xe32eed0f, 0x84e851f3, 0x201fdd91, - 0x8b10763e, 0x02556943, 0x26cf8c22, 0xfe7d9d49, 0x7bfa2656, 0x2f8a7e1c, - 0x2ae5fb40, 0xc5a95f6f, 0x507f97cf, 0x12ee3830, 0x3ceaa8fa, 0x21419068, - 0x7fbe3d75, 0x71fe625e, 0x3a6f41df, 0xd10d5561, 0xde4d739b, 0xd40f4869, - 0x009f0893, 0x760d78e3, 0x2a1a9a60, 0xf8c20be7, 0x88e1aae3, 0x5dfd0667, - 0x2ddef26e, 0xe387f426, 0xea4ffbaa, 0x4882ffd7, 0xfeeabcf3, 0xbfebf587, - 0x15ff5232, 0x977979bf, 0xf4a9f80f, 0x803a4f57, 0x5267d999, 0xe80ba253, - 0xc1b5be5e, 0xa9f97281, 0x5d2073e4, 0xd38bf33f, 0x16e7c923, 0xb74f9751, - 0xff11e422, 0x7e9d1f10, 0xd03bd1e9, 0xd5b73aae, 0x607c52ac, 0x0160259b, - 0x5d6caca6, 0x9b63e5c2, 0xafaf18e5, 0xb3f902fe, 0x2fa8cdaa, 0x32785f4a, - 0x40cde311, 0x0e7fcd49, 0xb9507f90, 0x68852fe5, 0x5eb15577, 0xdfe17bd2, - 0xe3e7f8e1, 0x2f981ec8, 0xaf7ff4c7, 0x6955f3ef, 0x7d6aa978, 0x84910bf4, - 0xcdfc83a5, 0x9a25f6f0, 0x68a4ffbd, 0xdf38a78f, 0xf9113644, 0xf307c74c, - 0xeebf7b73, 0x8f73a7c5, 0x5b9d3c01, 0xe421ddfe, 0xd727f284, 0x165a677b, - 0xe735fcfe, 0x0dd4f2c0, 0xaed4317a, 0x6767d7d6, 0xeca7e69b, 0x39b965e1, - 0xb03f40e0, 0xe5d9b37c, 0xfcbeba43, 0xc19e2ffc, 0x1607ccb8, 0xbfe870d7, - 0xef83e5ec, 0xb2f500dd, 0xdbf8e61d, 0x211434f8, 0x2a974831, 0x6c62bbf8, - 0xbfa50e90, 0x473b283e, 0x8e3fe7f1, 0x6ca3d20b, 0x8d993ec7, 0x298f8fea, - 0x0ee4fb2d, 0x5a5d0225, 0x3fa2158e, 0x57e2f751, 0xcfafea32, 0xe0d8175e, - 0xdcf8088c, 0x62ec907c, 0x51d113c4, 0xdd1f53a3, 0x0157dac2, 0xeabf505d, - 0xff7f0a74, 0xc7fe9a2f, 0xc4399cfe, 0x86bcafcf, 0xb67f28fb, 0x25fe70b8, - 0xc0e83caf, 0xaa929c79, 0xdb3f5f39, 0x7186e890, 0x44becc4b, 0xbcfe4a95, - 0x121fb9e4, 0xf23e2dbf, 0x7f8a44c3, 0x89b27730, 0x325f056c, 0xa6d16fce, - 0x62bf34d9, 0x2bbe25e6, 0xe0f45679, 0x8959e0fe, 0x4111df4d, 0xae24522e, - 0x5b354f8f, 0xa7654d70, 0x7dc0e170, 0xff45b785, 0x2dff8a56, 0x0fcaf8a5, - 0xb620fdf5, 0xad67ea8c, 0x885f4e9c, 0xac1abefa, 0xbafca13c, 0xd23b7565, - 0xf710f4e7, 0x571b8c60, 0xe1a7c931, 0xfd08b843, 0x0da6478a, 0x4e61f4e6, - 0x0efb4f29, 0x7c14fdf4, 0xcddbed8e, 0xe1ae5b6e, 0x2331763b, 0x6d72fe38, - 0x0a3b807c, 0x8953d5ed, 0x9845ff60, 0xafa4a15f, 0x85576037, 0x7c8857f0, - 0xf2df7973, 0x5d6f9708, 0xa633fdde, 0xbebffbe3, 0xbf07e5c3, 0xe0057b43, - 0xf7a60c0a, 0xa40966fb, 0x102c2c0f, 0x98b7ae49, 0xbe36b935, 0xe004f9d7, - 0xeddd7096, 0x3fec17e3, 0x764ff08e, 0xf87af16c, 0x565f442e, 0xfe8e78e1, - 0xbb72e9fd, 0x04ff9358, 0x6cff28c9, 0x81fb9713, 0x8f1f09fd, 0xbffd984b, - 0x15e50678, 0xaff713e4, 0x7b365fcb, 0x6f9fde70, 0xbddef03f, 0xb79fa720, - 0xd46a72e8, 0x5a72e19f, 0x8b0273b2, 0x639fa724, 0x3924421a, 0xe511e785, - 0x3e20e954, 0x4fe947fe, 0x85377f1d, 0x87d74fe1, 0x5c31e103, 0x7459fe1f, - 0xf087d446, 0xd7961de7, 0xbe74ff9f, 0xf4adf9d3, 0x29431597, 0xa5f3a63e, - 0x7c7d77ce, 0xbf5df3a9, 0x7f01a378, 0x182defe1, 0x3cb80183, 0x4714cdbb, - 0xf7c3df28, 0x43bbe17f, 0x4f09e3a9, 0x58c65a6e, 0xf8d4a1d3, 0xac3fbad0, - 0xded612de, 0x84f7561d, 0xd586f7b5, 0xcbed0dab, 0x3cc80edb, 0x686025af, - 0x8678ae27, 0x1228327d, 0x5fb9fabf, 0xec85fada, 0x7a50be43, 0x4af37be9, - 0x3c63b3e6, 0xf148af7c, 0xf1c01e91, 0x67a7182a, 0xf31f867b, 0x3c6c1a24, - 0xf6a3d4ee, 0x6c5ed03a, 0xdef5e588, 0xea157904, 0xaf79fd3d, 0x7af5c78d, - 0xd88ebd3c, 0xd8edfb10, 0x76f4911e, 0x8f4d9f87, 0x8ac267e4, 0xc1d47242, - 0xe3cf7a06, 0x2544d3fd, 0x5fc6057d, 0x8617449a, 0xef6a8a74, 0x419e6071, - 0x3bac9ecf, 0x45f3c0e7, 0x8db48a6f, 0x7b7683d8, 0x2dc7920c, 0x77f88725, - 0x53df329f, 0xbf7e3193, 0x4579fb87, 0x11ecc36b, 0xa9f896b6, 0xa32e5958, - 0xecbf053e, 0x82ff71b8, 0xd6a945cb, 0xe326c95f, 0xdc7bfd7b, 0xbdfb45c1, - 0xbdf18b74, 0x34078b57, 0x863272eb, 0x71fcd18d, 0xf4d28f1e, 0xe73134f2, - 0x8f4039ce, 0xc322c39e, 0x7b33fbfd, 0x99c7a244, 0x9ebf7ced, 0x23d7f6e2, - 0x3e92f77f, 0x89d4f1d4, 0xac0f24f2, 0xfd5f3aaf, 0x9187bcaf, 0x987d766f, - 0x3b2833fb, 0xfd907d77, 0xe6ffac5b, 0x590ff4fd, 0x5e53f6ff, 0x493ed1b7, - 0xe276ebcf, 0x7fbd9ef7, 0xeb187f4c, 0x9f142dbb, 0xabfd79ee, 0x9e9fe45c, - 0xd4129695, 0x80433d77, 0xec1f68fe, 0x83b72afd, 0xa27ad7d6, 0x99251fdb, - 0xfe7b47db, 0x8f10b1f6, 0xed0acc25, 0x49a3d786, 0xb35eaa9e, 0x67ad3c51, - 0xa17957ef, 0x9d77ff76, 0x7fb6a54f, 0x736763d9, 0xb17c2276, 0xeaa7df7c, - 0x5f3fd7b7, 0xad17f98b, 0xf085e4fb, 0xbeefca7e, 0xda3d45c9, 0x43db93b3, - 0xe78ee6dd, 0x68ee7f70, 0x6695dcfd, 0x0a3773c0, 0x9bac0a55, 0xa014cf0d, - 0xcbc7f4dc, 0xbc271437, 0xfcf47c52, 0xc10f835f, 0xdd9df5cd, 0xde70156f, - 0x21fc7f5f, 0x2dd785ea, 0x7cfa97c4, 0x25a96f3f, 0xf372e57b, 0x9c799876, - 0x799dffe4, 0x992b810b, 0x3ff328f7, 0x2d7fbd37, 0xe12e8939, 0xcf9fd072, - 0xf5443ef7, 0x822eed97, 0xfdf90af7, 0xf9f27ff6, 0xefba6b7f, 0x2e3bba04, - 0x7ff2ef3f, 0x4c0f79f2, 0xd7ef37f7, 0x7e62aee8, 0xbeefd54b, 0xadbef821, - 0x4ffb5b9e, 0xcd03ef2e, 0xd7ebb75f, 0x994d5c98, 0xaf439f18, 0xc569d601, - 0xc311b33e, 0xcc466b85, 0x14ced154, 0xf52bf6c3, 0xfb99af72, 0x5bee224d, - 0x086f9c62, 0xcd31f38f, 0x3d2da28f, 0x8a525a18, 0x94958ec9, 0x96bedc55, - 0xc06eed5c, 0x176b9acb, 0x887728b8, 0xc5ea3d8d, 0x1764da7a, 0xfcc3afc5, - 0xb9817ac9, 0xa56fb005, 0x8c396f6b, 0x84798dfe, 0xa5c96029, 0xab9618f2, - 0x59a4b8b5, 0x8f7e0d95, 0xdbac6392, 0x45bac69c, 0x38cacfeb, 0xe624d6fc, - 0x38b4f8c7, 0x798abf72, 0x8918e26d, 0xb1b75009, 0x17fa1f26, 0xf7e32496, - 0x1ec0311b, 0x5abdcf12, 0xe1f6f63c, 0x1bbb6c71, 0x44d238f1, 0x2e4a6b71, - 0xfcb8bc25, 0x8d9e786b, 0x55d788d5, 0x094f88ed, 0x7f6e5ffd, 0x34ccdf91, - 0xbad2597f, 0xdc984690, 0xcd3b6336, 0x9d2cbe4f, 0xcbd25d38, 0x332d3a35, - 0x43a745d0, 0xe818fa04, 0xdbf9e3a2, 0x2e9c27d2, 0x6fdff8e1, 0x07fe1276, - 0x974e97a2, 0x50cdc534, 0xbf9acd5e, 0x49fd1530, 0x1879a7ac, 0xfe6b33ed, - 0x66ef1482, 0xea93a43e, 0xf42f4862, 0xb7e002db, 0xf3fb7efd, 0x7aea2714, - 0x081dd8e9, 0x456fd94f, 0x75fc0566, 0x00b3b76f, 0x65f92f7e, 0x5b4b43f4, - 0x33fb8a45, 0x57779029, 0x6eafbec8, 0xcafd97f7, 0xdd29f34e, 0x06dff169, - 0xfaee97df, 0xb0ec9724, 0xd7e4bd95, 0x38125ef8, 0xb91d7ddd, 0x2a5bafb8, - 0x9c23ff71, 0x9e65625f, 0x3bb9d027, 0x6dc60e7a, 0xdf3c6d84, 0x1ee5b4b6, - 0x7f90c5b3, 0x91dbd666, 0x28bdf05e, 0xc213be50, 0xa9e79a17, 0x2f9d1dfb, - 0x36be1c0a, 0x76f31fb3, 0xe8edb74b, 0xe953f8c6, 0xc30b8b51, 0xbedb55d2, - 0x298dfda0, 0xd1d97abf, 0x68b6fe41, 0xf3f43f88, 0xc489b7fb, 0x15ad951f, - 0x9d4087e4, 0x25b2a2f8, 0x72ebfc72, 0xafd969fe, 0x01f2eef6, 0xfd7ecb0a, - 0x5be30382, 0x3ab7dba7, 0x76dfffc8, 0x3f5bb8e9, 0x91e5bf3f, 0xa7f9fa4b, - 0xbfe01ff1, 0xc58720dc, 0x220db649, 0xcbe0047f, 0xadef948b, 0xcbd95bf3, - 0x38c39f67, 0xcfcee774, 0xcb78439f, 0xe7cbfbff, 0xaf609fd0, 0x88add4db, - 0xa5de9797, 0xddfe9e38, 0x9dc7992c, 0x817c5fbb, 0x1fdd9fe2, 0x7f01df80, - 0x4a9ef7ba, 0x7bb27f47, 0x1889d7c7, 0x77be592f, 0xef9c60da, 0x0ca757f2, - 0x88f41166, 0xfadf225e, 0x1afe20af, 0xad03af4e, 0xe9efc807, 0xdfa37a02, - 0x69b717d9, 0x3071e0a9, 0xd9af16a7, 0xddce391e, 0x7ad33e2f, 0x8d379dd7, - 0x72ecd2c7, 0xd3882bb2, 0x1c7403bc, 0xdbf4057d, 0x7fe688fe, 0x175fa646, - 0xb4e803fe, 0x677e8c2c, 0xfcfd175b, 0x3ad77c19, 0x4d38c068, 0xa6f00ae0, - 0x27bfd1c7, 0xa3227fbb, 0x25fced7c, 0x6e90c5c5, 0xbb44c1b7, 0x8e9b3e5f, - 0x9a9f0ffb, 0xe7e7ef7b, 0xc62a2c32, 0xbef74a1b, 0xfdd3f24f, 0x538a11ea, - 0xdd9e2d33, 0xf0fefacd, 0x5396a3f8, 0xcec5b559, 0xfe1a3be3, 0x74e3fe31, - 0xce2d73d0, 0x8f58f9c3, 0xf7140cff, 0xde799569, 0xafdf1e88, 0x16a1f2d8, - 0x4bd2094f, 0x3a748498, 0x08fdc976, 0xe22a0f1d, 0x1c686261, 0xad7c7233, - 0xd1adde2f, 0xf187e90b, 0x2538becb, 0x6e30d3d4, 0x67de17e5, 0xf741f411, - 0xecff1e66, 0xa3ce4736, 0xbf9ae3d2, 0xff53970a, 0x2f33c595, 0xc5b7ff07, - 0x52765f8f, 0xea78e1bf, 0x8f5910bc, 0x75f32dbf, 0xc5f7aaff, 0xbe4305ca, - 0x7bc9b941, 0xa2b1f904, 0xcfcc98f5, 0x52f3f0a5, 0xb53b7cfa, 0x97ced1bc, - 0xad778a44, 0x7a40396a, 0xe85f5c3c, 0xf0e1a6fb, 0xade0d09e, 0x44ebe36c, - 0x5fbb4ee7, 0xf73a7e81, 0xae7e26ef, 0xe28c7edc, 0xfdb6876d, 0x5908ee5a, - 0xf09d7157, 0xf9dfc087, 0x1e5cbeca, 0xec79e5b7, 0xd19ce3e1, 0x9ed561f4, - 0x6d54e3c8, 0x4e30c2ff, 0xe645af99, 0xc7a5fdeb, 0xefb92d3b, 0xb74efec1, - 0x79e6199b, 0xa7116e9e, 0xf5173a47, 0xea6eb6ae, 0xbd707ee7, 0x23fd7ca4, - 0xf8cc5cfc, 0x1f28a3b7, 0xe991f97e, 0x63c4c61f, 0xfe878409, 0x9f396b5a, - 0x9dc4feb6, 0x3d6ef48a, 0xeb88af72, 0x6fc42ed4, 0xf79f9d88, 0x3b14f54e, - 0x8fbc85e8, 0x5d91e33c, 0xc4cdf5c3, 0xfc0326a3, 0x5c60ce30, 0x1fa1ea07, - 0xf982a73c, 0xe88f086e, 0xf08e9c28, 0xb549aa88, 0x61e7fd09, 0x5e743c56, - 0xacd7ef40, 0xb003cf1a, 0xd89ce30b, 0x1e4cd24f, 0x8bbe4c47, 0x3cfd3e97, - 0xbf94714e, 0xa059e60e, 0xf02cd378, 0x7d7d927d, 0xe78641c6, 0xde5126bf, - 0x78c59676, 0x554bac6e, 0xdfd0267c, 0x596ce4cf, 0xf949d937, 0x4258d707, - 0x20580ff3, 0x6f51f917, 0x587defd7, 0x7e1a427e, 0x1a88fd02, 0x7e5a597c, - 0x21d610c2, 0xc9bd7da0, 0x0e27cfce, 0xf84de255, 0xbd9af3fd, 0xec3f9fa9, - 0xec315e77, 0xcee5e29c, 0xc94fc627, 0x05d43a5f, 0xcf7ab4fc, 0x8f5fcc14, - 0x477f27bf, 0x12798aaa, 0xe7829e7f, 0xc85fe257, 0xf50c931f, 0x9c1fab13, - 0xc8fff54a, 0xf50e931f, 0x8dff1a6f, 0xca04cbd7, 0x3d582d57, 0xebf22a7a, - 0x2cf9cb55, 0xce5188c0, 0x75bc40ef, 0x7bba3e79, 0x1ff31391, 0x5f8e657a, - 0x4376c1e6, 0xa5bc7126, 0x40ed1f29, 0x75350d3c, 0xfe7f22d4, 0xb157ef7c, - 0x4c9c17a8, 0xaca8fc25, 0xc1fa455e, 0x2f1749a3, 0x9e174791, 0x93eba64f, - 0x01f78acd, 0xf991e384, 0xe05ce823, 0xad332533, 0x98cf5f3c, 0x78d4c0c7, - 0x469167a2, 0x1ad3844f, 0x58bf8f92, 0x5cfcc9f4, 0xafa6934c, 0x9e38aaa6, - 0x2f172be0, 0xe1edf75e, 0x4be7507a, 0xc8695ced, 0x1087c679, 0x7de29f5e, - 0xffd092c8, 0x161de33c, 0x9f7c0acf, 0x1d3e7c5c, 0x9f3f5bf9, 0x91ce7e18, - 0x48a6bd49, 0x76b35ff6, 0x782071ce, 0x2aef563d, 0x77f3371c, 0x41879dce, - 0xc91746be, 0x1ccd4c2e, 0x827c62bd, 0x5215cfc4, 0x4695439e, 0x971324bf, - 0xa310f643, 0x8b1ed67d, 0xb9bf46e0, 0xf49541e7, 0x6dd15a77, 0x44f557e4, - 0x3e60b467, 0xfcc3cf50, 0x4c66295c, 0xd90d1ca3, 0xbf401313, 0x5ce0e40f, - 0x339c1c98, 0x71c673ae, 0xdb3a2e7b, 0x553fa83a, 0xb00c0feb, 0xe0b9e0c4, - 0xe5eb911e, 0xc1271a9e, 0xf6f98431, 0xa57efae1, 0x18b56de3, 0xde02fdcf, - 0xe8bc405f, 0xc0e5ff78, 0xa3457bf4, 0xe8912bdf, 0x74fe7e17, 0x6bfbc5be, - 0xf8aa7f6c, 0x15742ad0, 0x869dcfc3, 0x6a4ab5d3, 0x78ae88da, 0x682f9ee2, - 0x36e9d19d, 0x412b857a, 0xe3a0641a, 0xe8efd8eb, 0x10985f3d, 0x4f7e9d5e, - 0xfdef900f, 0xcf5f0b07, 0x9c4bc7c2, 0x8de291d3, 0x1060feb4, 0xcf58212e, - 0xf8d1e6b5, 0xde3c4d83, 0x10bdbfd3, 0x7fd03e71, 0x30f2a5e6, 0x2fde5573, - 0x50fdffe0, 0xf110ffbe, 0xfe22223f, 0x03bc463f, 0xf6c63ffe, 0x4fff8057, - 0xdd7f852e, 0xf4d32fae, 0x2bee1942, 0xc5fcff01, 0x13313339, 0x15142dc6, - 0x5b25ffe2, 0xd21f6d45, 0x62725b7d, 0xb92c8f50, 0x199f7abe, 0xb3c970f8, - 0x9169f102, 0x73fd5e76, 0x784b5ced, 0x1cf15f5e, 0xcbc9e91f, 0x49f9f7e7, - 0x336d950f, 0xe410bf3e, 0xc7ca74db, 0x93f3f1f5, 0xe11726a2, 0x68a33ff8, - 0xd628a2fa, 0x0e9c2ed0, 0x864daa43, 0x29e4f03c, 0x9f90fd7d, 0xbe726497, - 0x3fb5f14f, 0x07c61998, 0xf8fc52dc, 0xbc63e200, 0xcdfb1530, 0xef56e4d7, - 0xe30ae86f, 0x33e19f3a, 0x6acbfb9e, 0x1bfb9e34, 0x686294de, 0x4c86cd7f, - 0xfe91fbc3, 0xafef0d6b, 0x50d636db, 0x8372d51f, 0xb6e8fda1, 0x4c7d4302, - 0xfb4316e0, 0x1a678771, 0xefda13ea, 0x789fb435, 0xfde18174, 0x86a51df5, - 0xba7e37f7, 0xa9bf50cc, 0xed0d5ff7, 0x5eb88b03, 0x94935fdc, 0x740ae786, - 0x2a5fecbc, 0xbe7c549b, 0xe6a4db34, 0x744f3e86, 0xccb1733b, 0x357fa373, - 0xb14cbc90, 0xae85a726, 0x6cccf9cf, 0xac536bd0, 0x55817ac6, 0xe07497e3, - 0xcdfe2017, 0xa55ca356, 0x026bcf56, 0x2ca59bb3, 0xd2f94619, 0x58b75f20, - 0xc5bb7eb9, 0xedfa657a, 0xaa7f6c4e, 0xece74032, 0x444be5c3, 0xd2a2caf9, - 0xcca9fb47, 0x1b96f945, 0x4d3e466d, 0xccaf401a, 0xc3cf1ab3, 0x9b61ea8b, - 0xfd139064, 0xd0a8f9f9, 0xdbe2c2e7, 0xa0676f28, 0x05a4e57e, 0x7d016eb7, - 0xa97b2729, 0x9aaf9fd4, 0x97988a63, 0x3bf590f7, 0xfa1b49fa, 0x210f4fd9, - 0xde92bb7e, 0xccf30a7e, 0x92f5e72a, 0x316c94bf, 0x775825e2, 0x5479e60d, - 0x508e7e4e, 0x54dcffe5, 0xae2b78d3, 0x173cfaf7, 0x1133307d, 0x06d203f3, - 0xd55e9ff0, 0x4d5cf1e6, 0xc345adc9, 0x14d53fb0, 0x7a45bf7a, 0xfd10aaa0, - 0x1e5aa198, 0xc8a653f4, 0xd53f4af9, 0x0a8c19fa, 0x5503ed14, 0xaba0fb21, - 0x048723f8, 0x9377f8f3, 0x17c8a7f7, 0xe7b7460b, 0x6ecb73f1, 0xabb24cd7, - 0xd75f8254, 0xe78ae943, 0xe92bd429, 0x66731249, 0xf06787f4, 0x06636f3c, - 0x338fafbc, 0xf7aa14b9, 0xe59e380a, 0x820d8cc7, 0x5bffeaf1, 0xf7eaf824, - 0x3cf94f5f, 0xe29aa516, 0x993cfaa7, 0xc7afdfb6, 0xcd26cf8b, 0xd63c418a, - 0x6e77db5f, 0xacfd6187, 0x7ec76de2, 0xd337aecf, 0x8205f5b8, 0x6f3ebde1, - 0x741dc369, 0xe15d2b1e, 0x79862ef3, 0x3496dc23, 0x73fd570e, 0xb8234b02, - 0x43d2f7fe, 0x8aecbfe8, 0x0dbc6176, 0xe889b1f0, 0x6738ceed, 0xf30f27d2, - 0x34a418aa, 0x25fb21af, 0x96fa1fb2, 0x4cdbaf95, 0xf688959d, 0x4635f254, - 0x66f5c5b8, 0xc51707f2, 0xe0af942a, 0xd1a159af, 0x55ef38d5, 0x9cef3349, - 0xbdd4f00b, 0xfd4c3223, 0x2d347671, 0x15df043d, 0xfcbb46b7, 0xef78fece, - 0x01387272, 0x6e10b7ee, 0xcd214371, 0xdc21da9b, 0x33d8173f, 0xde77c819, - 0x14ff44e9, 0x977dc313, 0xd3fff870, 0xefc4e3ca, 0x879a5558, 0xeb7c549c, - 0x16584196, 0xb51ddc91, 0x7fceb80e, 0xfcebe568, 0xeb08d687, 0xfdeee5fc, - 0x7ed39f28, 0x6dd14b08, 0xeadaecd2, 0x197b50ec, 0xec49d6f4, 0x318baf57, - 0x7ec5ce3f, 0x3ccbb607, 0x9719d94d, 0x1ed0cbb7, 0xedd3fe43, 0x8d5abfb1, - 0x9e886476, 0xb3d34afd, 0x9ea15d5f, 0x4eed80bd, 0x68881bdd, 0x91c824c7, - 0x1b38dcf5, 0x2a957fc7, 0x1be3ca33, 0x6d9f9e20, 0x0e1f6c8b, 0xce5d0eb4, - 0xd68cc8cf, 0xefd754f9, 0xc560dfdc, 0x9c2fed32, 0x247fe0d9, 0xe329f71b, - 0xedde5187, 0xaea4fd40, 0xf10d83f8, 0x886de3ab, 0xc04f88cd, 0xf9c6d3a3, - 0x648b69c4, 0x1e03960f, 0x0e3c064d, 0xd903f6c7, 0xdfad5783, 0x6ee78c4b, - 0x837c35ba, 0xbc71979e, 0xce3ebbae, 0xe545b8c3, 0xe7a473ec, 0x399c7aaf, - 0xf74475c6, 0x011c61bf, 0xd77ddfe7, 0xb7716b7f, 0xd5178a0e, 0x0c4d7abd, - 0x0a2aa7c6, 0x9586f4fa, 0xa49985db, 0x5976bb07, 0x576708dc, 0xece7cf1c, - 0x10f135da, 0xaf3e39c6, 0x85299c39, 0xaf5d2dd8, 0x4333c91c, 0x8f3b5d7f, - 0x209449e4, 0xd17e27e7, 0xfc5c57df, 0x128f3ccf, 0xc7d0273c, 0x0ebe566f, - 0xf8f1b7ad, 0xc798d3c9, 0xf7b19a36, 0xfaf963a3, 0x1c7a6891, 0xe3bf479f, - 0x7f7ea1f3, 0xc7e57054, 0xdd262b00, 0xab664c55, 0x00a68de5, 0x6e0a8f96, - 0xbe55e311, 0x4d3cfc91, 0x911b1652, 0x4728fd01, 0x8e0803db, 0x8dd7a3a3, - 0xa7ea29db, 0x0b2c3eea, 0xc402ef14, 0x2baf5c7b, 0x37fc7d09, 0xa1b38d87, - 0xe14d215f, 0x7e77b77a, 0x29ef1f94, 0x8fb9344a, 0x6767aa80, 0xc58c2f0e, - 0xe68b7ff7, 0xd258f2f2, 0x8e5c2689, 0x38a03970, 0x5a669bd4, 0x710d96df, - 0xef822f27, 0xe7884d97, 0x9805e97e, 0x9639c87d, 0x0967e3c7, 0x00b90714, - 0x14e78178, 0xb53e02fa, 0x3317cc4b, 0x89b0f416, 0x0bf055b9, 0xee4293ec, - 0x68ffc1d9, 0x4d60fc76, 0x4d38f6ff, 0x45e0333e, 0xd5db1976, 0x5c0cee09, - 0xfc81774f, 0xb4fa030d, 0x7ca958d5, 0x184d46ad, 0xa7b8f206, 0xafea8926, - 0x0ca938d7, 0xe7a08cd4, 0x545c6bfb, 0xa7b5368f, 0x552c7ad3, 0xfe879baf, - 0x0b12fdf5, 0xbc23b7bd, 0x8e567bc4, 0x97f9c887, 0x0093e62e, 0x3d352fae, - 0x38d6fb52, 0xc6a7afe2, 0xfd31d400, 0x8ad9ffbf, 0x054d643f, 0xa3fa983d, - 0x415359c3, 0x78129f8e, 0x181e02fe, 0x552e748e, 0xb7329f2f, 0xf0a9a2c4, - 0x4df31b6b, 0xc8bcc24d, 0x8e153fde, 0xe8f6cc61, 0x1d4ea69f, 0xfdc7f309, - 0xf6c614fe, 0xc7abdeda, 0xfba9d873, 0x818bab3f, 0xfc6dc8f9, 0x82899f3e, - 0x7d4056a7, 0x0bf39b33, 0x98b53c93, 0x3773d9cf, 0xbefee273, 0x1b5ece3e, - 0xdb7613b7, 0x51399db8, 0xe6c1fce0, 0x411e5aca, 0xbae86e6f, 0xef3ede11, - 0x8f74d7c0, 0x2fb78c0f, 0x2f5e30d5, 0xfa0711c5, 0xd7ff752e, 0xe95c8eb4, - 0x491f3d77, 0xc4847cfc, 0xe6ba2bf3, 0xfda66e26, 0xba1f6878, 0x4723da8f, - 0xd2ded7b6, 0xed0681d6, 0x659fb7be, 0xa68372f0, 0xf5c62457, 0x05d16bff, - 0x61b947bf, 0x5fda38de, 0x09e2d3aa, 0xe57a3a93, 0x2f7e76f9, 0x13d43e5c, - 0x3c04784e, 0xd1a5d70f, 0x1e605533, 0x6048ffcc, 0x28028433, 0xdbcf36dd, - 0xc2d24fd8, 0xd197be4d, 0x7165d85e, 0xe3a3d9a2, 0xd903eeab, 0x6121fa8a, - 0x8fda31cf, 0x643a13aa, 0x8f97f7a4, 0xcb714d7c, 0x3275733a, 0x1b176dd5, - 0xbdb4feb0, 0x99d6237a, 0x6fa9ebef, 0xd60c3f00, 0x13e3e1ce, 0x90bb63d4, - 0x3b5829e8, 0x7e06ef57, 0xf5e665d8, 0x4b391f2f, 0x5ccbb1fc, 0xe18d9f3d, - 0xef987af5, 0xaa6f58ae, 0x52905409, 0xe1fd65fb, 0xb7aeb09b, 0x77da92ff, - 0x3f6e54db, 0xa40cde2a, 0x855d5f7f, 0x2ea43dba, 0xf2b33af1, 0xc55f9f52, - 0x7f29af81, 0xe70f72b8, 0xce1bc447, 0xc3cdef13, 0x7a8ce975, 0xa4eb51d4, - 0xd73673b8, 0x9f0301d7, 0xb753e7e9, 0x2a2cbc98, 0x085ecf44, 0xce42ff5b, - 0x84a8b1d9, 0x38b4fe90, 0xbb033a76, 0x6f182b34, 0x2a2e64cd, 0x950f3187, - 0xee96dbd9, 0xbb2db447, 0x7a89d5af, 0xfad73e2b, 0x68e89780, 0xd09e1ff4, - 0xe8fae2f4, 0x01a31bfc, 0x7782f59e, 0xf17a888d, 0xe74ab365, 0xb2243a2f, - 0x35b53b37, 0x5330ad8c, 0xf73b5cbd, 0x5de95e6d, 0xeef51233, 0x19ab9322, - 0x4f0cb3d7, 0x2fbe19be, 0xaae19ddb, 0xe7bcc165, 0xc496d8b2, 0xef304ab1, - 0xaa3faf59, 0xb546d9f1, 0xd2f786c9, 0x9543fbe8, 0x71d2eb6d, 0x7db3fb7f, - 0xbd3c901f, 0x7c41951f, 0x447ad15c, 0xbf69daf6, 0x29f3c64c, 0xd6fad99f, - 0xbef75a3f, 0x0b74196c, 0xeb2ff5ea, 0x79b8744d, 0x06f43d20, 0x38373fe8, - 0xac6a87c8, 0x5dc2fe54, 0xde9a2d7d, 0xd3295105, 0xbfb4606c, 0x9156e990, - 0xb9ade68f, 0x7c0ac1a6, 0x8eac82f4, 0x179b3e44, 0x5b7c4b95, 0xbe722b16, - 0xdd07b964, 0x0dcfb692, 0x6535d4f5, 0x3c53bed3, 0x6f68c8be, 0x88526d54, - 0xc80ec00f, 0xdca83e47, 0x7ee1f260, 0x4edac9a2, 0x45e77de7, 0x368fcd31, - 0xaf5c4f9e, 0x6cdf3be9, 0xdcbddf1e, 0xf392c539, 0x511e7451, 0xe51fbfaf, - 0x9128be24, 0x55ffb47c, 0xe741de72, 0x38fbbf18, 0xc879c356, 0x0428e3fe, - 0x794e3e87, 0x57d21c70, 0x27ec1fe5, 0x6b8df83f, 0x4dd67b75, 0x3be5ac71, - 0x9b05fcb4, 0xf3f6307b, 0x1827a6b4, 0x7780b1fa, 0xeeafa329, 0x1ccf4093, - 0xf933d3ec, 0x90d3530d, 0x6cf7c1be, 0xb90f4192, 0xc1d3a025, 0xfbeead28, - 0x51f6e47e, 0xf533ed61, 0xa986ccfa, 0xf3c3fb93, 0xb7582db4, 0x1be97b42, - 0xe11d5f4b, 0xa1f573a3, 0xe3e9c5fd, 0xe9fd4bdf, 0xb51a97fc, 0xf80fa0f0, - 0x27ac60ef, 0x7a7cf31f, 0xca273367, 0x8d4966e1, 0x21d08572, 0x37af8a35, - 0x35afe725, 0xf7883fe0, 0x4ffd035c, 0xfb0d38d5, 0x968b8b8a, 0x549879d1, - 0xc7cc5e9d, 0xca6d77cf, 0xfe27ec32, 0x16ae387f, 0x7000f70e, 0xc307fd4c, - 0x5e30c231, 0x031c8e10, 0x870b577c, 0x7a6b3b18, 0x8f6bda06, 0x280f2898, - 0x66b3e4d1, 0x6ff65da2, 0x0ca78a26, 0x880f3c67, 0xfb0de329, 0x2c7b99b4, - 0x9efe31f3, 0xd2c3b129, 0xb7279458, 0xa9d716b3, 0x5f64489f, 0x39ab73c1, - 0x726e870e, 0x204ffde3, 0x665fd495, 0x1f82b7b9, 0x82fbe6f2, 0x70d33efa, - 0xbde3e595, 0xe7a39ba0, 0xfb8d18df, 0xaa1e7366, 0xe7983cc2, 0x352ff195, - 0x92bc8330, 0x2c20d21d, 0xabe33b25, 0x701b87a8, 0x147076bf, 0xf6045bb7, - 0xe4e1c370, 0xbcb9ef48, 0xf0f35b9e, 0x341b8c34, 0x8b5e74af, 0xcdb353fe, - 0xf31fb2df, 0xe8531e76, 0x47acd6de, 0x50998dfd, 0x6899d717, 0xfd6314bd, - 0xdf719adb, 0x176cc9fd, 0x68cd11da, 0x47fb60bf, 0x566bf214, 0xf0d338d5, - 0x6d3a927e, 0x76b2d81d, 0xc1798ab2, 0x87148af5, 0x732addeb, 0x773c5cf5, - 0x8dd1ee31, 0x51ebd60d, 0x071ab98f, 0x949ebca9, 0x339aeb8c, 0x7b463ad3, - 0xae68c80f, 0xb1a8a675, 0x6ff0fac1, 0x3d20fac0, 0x9dc1b1b3, 0x2b2efd86, - 0x883bfad5, 0xe2178a71, 0xef68bc34, 0xd2f4fb33, 0xcbcc06c6, 0xf5836b12, - 0xaddf30a9, 0x353d72cf, 0xfb47fa18, 0xc3e3e60b, 0x877b057b, 0xca4e744b, - 0x603b6306, 0x9991b67e, 0x0cd7dfb4, 0x2bef117a, 0xdfc91dee, 0xf234fbeb, - 0xd3ed1370, 0x6f5c7b60, 0xbdbcc96c, 0x57df833c, 0x8a15db20, 0x307ac037, - 0x149ef315, 0xf371ffa6, 0x8fb6a4b8, 0x01f78511, 0x75a3f084, 0xf73a32ed, - 0xdc661d69, 0x8cd3979f, 0x16798975, 0xaa27bfa0, 0x4637e7c6, 0x8341f96b, - 0x6dda0a58, 0x133e4dc3, 0xfcc91bb6, 0x02c75e54, 0x628d8f64, 0x8d1f541d, - 0x1e16635e, 0x41d2725b, 0x2dcc71ab, 0x47aa38f2, 0x71313b44, 0xf2471eae, - 0x74be414e, 0x61766b47, 0x7e3fef0a, 0xf7ca2cc6, 0xcdef69f5, 0x313d8633, - 0x7eb5e60d, 0x50ceddc6, 0x2f5f4efb, 0x48adfb75, 0x68cbf983, 0xa0bda221, - 0x364575db, 0xe5984f5e, 0xc6147a7e, 0x26cddb11, 0x58ad9fbc, 0x6f16638b, - 0xbb444fc8, 0x5cdf68ac, 0x44d787b2, 0xd16cbb73, 0x77b219fa, 0x9af79e14, - 0xfe7f764f, 0x183109ba, 0xb9b06fa7, 0xfe47ae62, 0xdfbf23fd, 0xb1ed4af5, - 0x0a6bc4e6, 0xc19b1e50, 0x8ffbc6af, 0xcadd9a0e, 0x758be418, 0x6ccec8c3, - 0xc7d6f28e, 0xffcdbf42, 0x41d574ea, 0xf73667fd, 0x4e3823f8, 0x8f7f1443, - 0x6f2126f7, 0x3ff7edf6, 0x1e8c5c2f, 0xfdf0fc78, 0x91b183fe, 0x43bdf1ef, - 0xfed05fc3, 0xd9dd90f0, 0xdcc4f660, 0xcbbdf087, 0xead679e7, 0x112f5189, - 0x86b4fb67, 0xd67603e7, 0xe64058b8, 0xbd62d1f7, 0xdd3f68a4, 0x22d25caf, - 0x097cdc50, 0x3a3d226b, 0xeed5894c, 0xc5e631a7, 0x4dbd1696, 0x795b4bed, - 0x42d632fb, 0xe17a75ed, 0x8301b5bd, 0xf0ce3a1d, 0xdcd11dfd, 0x78acdd6f, - 0xfffb431f, 0xc4d91991, 0x1167c04f, 0x07e22df3, 0x31b977d8, 0x371faf9a, - 0xf6c8db62, 0xb863f128, 0xe05cb87d, 0xc207b3e7, 0x9379d553, 0xde0a3d61, - 0x7ad3219f, 0x49f9add4, 0xeb7c9387, 0x7ff9846f, 0x244af59f, 0x23bddaa7, - 0x425f8275, 0x33befaf9, 0x2d1bdeec, 0xa6ba680f, 0xcb43fe25, 0x6b3ef9ef, - 0xfd0dc379, 0xf402cedc, 0x9eed61dd, 0x48a41412, 0xafd01979, 0x3adc1f41, - 0xddbf58c2, 0x39dfac65, 0x7d3df229, 0xb4d46b6b, 0xd6aa7bd0, 0xf38e700e, - 0x575e8d2d, 0x0b12df7f, 0x0b7bebcf, 0xf9815ee9, 0xc17fb494, 0x1b14faf3, - 0xd91ea0f3, 0xfb46cfbf, 0xbc8a5521, 0x55164319, 0xbde2efe0, 0x9f9d8af0, - 0x17ff4037, 0x998a05e3, 0x97de0fb7, 0x1251f7c4, 0x3c5a493c, 0x633495c3, - 0x1b87b7d4, 0x0bca2afd, 0xdc46d896, 0x27e60d77, 0xe8edef1a, 0x0f38fe8a, - 0xcf9863fd, 0xe84f8c6c, 0x3e7d5a71, 0x2c7f28ff, 0x39cfbb5a, 0x346b6e9c, - 0xa30ba8f9, 0x39d23d73, 0xb973df07, 0x87bb52f9, 0x43c129ff, 0x26896879, - 0xb3ac171e, 0x9c528eb9, 0xea0ff344, 0xf306b8b4, 0x56ef5d7d, 0x1095ecc2, - 0xed7d22ff, 0x39f5f5d7, 0x38f377e4, 0x156a2d88, 0x360dc3ae, 0xfaa66ebd, - 0x00a6e6d3, 0x5aaffdf9, 0x831f189c, 0x6718ddef, 0x411dcdf3, 0x065d5d7e, - 0x0e7bc14b, 0xb4cbb0de, 0x6abdd6fe, 0xd8f5c669, 0xdb76f36d, 0xba49f242, - 0xf9d1efec, 0xf9fd08a6, 0xf90dfd0c, 0xf8c1fd76, 0xfd7788ad, 0xa7f61bfd, - 0xceff2202, 0x691bf949, 0xa17b1fed, 0x42cbb89e, 0xf7fd4f71, 0xe7cfca0f, - 0x7a8cfdd1, 0x4e14137f, 0xd51ace87, 0x8e5d8f90, 0xe507377a, 0x67f49da0, - 0x8320cb45, 0x69f5d4de, 0x681bf9c5, 0x57482cbf, 0xb5212e2d, 0x38aa5e93, - 0xbc68bfff, 0x349e903b, 0xf7e9124e, 0x3549c781, 0x38e0e3e8, 0xf7700c93, - 0xc132671f, 0xdac38fa1, 0x9fe70ca2, 0xae3ccceb, 0x33986672, 0x1e823626, - 0x83714bd1, 0x60ff70c9, 0x62b2e49d, 0x4eca75ff, 0x287f3435, 0xef005f7c, - 0xf02164c5, 0x867ac1d5, 0xf30b72c1, 0x3d405e52, 0x072213f6, 0x62a5d9a2, - 0xf8c262bf, 0xc62ef9e9, 0xbdb945fe, 0x33727d10, 0x8bd82df2, 0x7e3b583f, - 0x49ec0f95, 0x4769ecc9, 0x93764aba, 0x6b68f313, 0x45c51315, 0x64ac92eb, - 0xca12adff, 0xbd739455, 0x2243a95f, 0x8f7df438, 0x9f29e681, 0xc33cd077, - 0x9ffb3bef, 0x76a14f1b, 0x3b57eefd, 0x0f93d730, 0x93545bfd, 0x4e5d450b, - 0x2127d853, 0x47ef0ff4, 0xec4520da, 0x8e9dbc27, 0x6ce901ff, 0x3d2070ee, - 0x88a5e3ba, 0x951b1079, 0x310798ef, 0x271f4c2f, 0xe00ecd1c, 0x238742f7, - 0xe5f48323, 0xa5f50546, 0xdc9fccfd, 0xb4cbd24e, 0x7fafadef, 0x56a984e6, - 0xbc6c4f9e, 0xfe206f57, 0x7d62f1d3, 0xf3c641f3, 0x7f94bd53, 0x483c3972, - 0xfb43cb82, 0xe2297600, 0x425836be, 0x4938fc86, 0x354fe631, 0x63e21e48, - 0x56d54df3, 0x5b4927da, 0x927dc569, 0x063392d5, 0x37ded8fd, 0xf983fec1, - 0xbe793a35, 0x6bff786a, 0xb4661ef0, 0xc4531573, 0x06a379fb, 0x34baafb0, - 0x77d9acfa, 0xf501fe69, 0x3775c1e1, 0x71524e2a, 0x399b35dd, 0x4bad03bc, - 0xe103bf7a, 0xfc7dd1eb, 0x392c1bf7, 0xffae3f56, 0x4a35e3e1, 0xbc3e4f1e, - 0x7078046f, 0xcd31acdf, 0x546df84d, 0xd5fd1525, 0xcc5111e8, 0x656fea1a, - 0x67f7a2cc, 0xccf1e3e2, 0x8f8c6b22, 0xe3a3979c, 0x1df2b769, 0x186f1ded, - 0x8f7f0e5f, 0x7c21e8e2, 0xe84ca9d9, 0x91bb97cf, 0xfc381317, 0x5aa6f7a1, - 0xbc458633, 0x7f1fb27f, 0xde4df186, 0xf7e74664, 0x19b94306, 0xeed56efa, - 0xb5c0aa43, 0xf2f4fc0b, 0xc2a6147b, 0xe477e6fa, 0xc939405f, 0xcfcfdf6b, - 0xf026b4d1, 0xefb51e7b, 0x625dc7c3, 0x12c8fee7, 0xcc654abb, 0xf12ff751, - 0xdb5a37f7, 0x5e789ca3, 0xb22e35b1, 0xd763931f, 0xb49a68f3, 0xb41d0873, - 0xcfb7a14f, 0xcddcc79b, 0x1b3dc50a, 0x257fe0ad, 0xa9ffb5f4, 0x82023fb6, - 0xf9dce30b, 0xf99aebdb, 0x7f3e51f9, 0xfb62ab8c, 0x5c8ec4c4, 0x740efc41, - 0xf70cc6db, 0x3b5855db, 0xe7ce51b2, 0x7699bc9a, 0x68eaa718, 0x5bd62247, - 0x4e9d3edf, 0xb71d6f7e, 0x47777b37, 0x3fa0dc53, 0x79f96a7d, 0xcc29f3f2, - 0xdd3fa837, 0xad00a5ca, 0xd3e7e5ab, 0xcd1c6f99, 0x0b8d67db, 0xc2d3bfbe, - 0xc8b1a4d8, 0x884f1c00, 0x30f4489f, 0x7a064ddb, 0x675e3c80, 0x7881e8d7, - 0x76b7a3ea, 0x76a74bef, 0xcd71e0bf, 0xf72a615f, 0xa5fbf5d7, 0xe5f7678e, - 0x5b7dd05b, 0x13f736e5, 0x3b0b4f78, 0xe6be5222, 0xfefc29c2, 0x771685c4, - 0x0b57da0c, 0x6a1453ff, 0xf3937f69, 0x7f0d22fd, 0xf745cc9d, 0xdad6f80e, - 0x984ebef8, 0x54f1967f, 0xc23fb8fe, 0x44da8bf7, 0x305f1bca, 0xbf61f145, - 0xbf05ed79, 0xe2f9fdc4, 0x773a68c6, 0xae7bf0be, 0x2dd76893, 0xc4e6c27c, - 0xfe597bdf, 0x327e6641, 0xc9fcbbf4, 0xdf07d50c, 0x24f0af45, 0x27a05d59, - 0x8853db1f, 0x3083457e, 0x0630be7f, 0x0ec7cafc, 0x98b8c2ac, 0xcf94cdf4, - 0xf47f506d, 0x615677b1, 0x18b7e9bc, 0xf63b26e7, 0x63b442dd, 0xf4d0425f, - 0xc1c03ffd, 0x5a4d874b, 0xa9aac4fd, 0x4daff2a0, 0x2a293568, 0x562765fa, - 0xc4d939e1, 0x1318f738, 0xfd8ef78c, 0x6fec42b3, 0xcea313c1, 0xe7f7806d, - 0xbec817ed, 0xdf693a00, 0x014f370b, 0xb278bbbb, 0x582d975e, 0x86668f8f, - 0x3339be38, 0xd9da3e38, 0x8b7c7aad, 0x718cdd45, 0xd505e3f7, 0x3fe82453, - 0xceaea1c3, 0xc4d8c919, 0x1baaf9f5, 0xc476cfc6, 0x98f18cdd, 0x837dbed6, - 0x1f18d5f8, 0x03de656b, 0xd37f7866, 0xb66e43e3, 0x07e36202, 0x30a8c679, - 0x29d641ff, 0xf4dfa7ab, 0x4463e41d, 0x0d59f3bf, 0x939204f6, 0xf4d28843, - 0xc2defc15, 0xe34ef93e, 0x1f57db7c, 0xc3cfc1d1, 0x5e24f5e8, 0x59195d6f, - 0xc312dc5f, 0x2a35baf9, 0x4d66fbf2, 0x03be003f, 0x8b6d7f14, 0x08cf0ff6, - 0x1f900fea, 0xa79224eb, 0x807f5c75, 0x93b4cd1c, 0xefec46dc, 0xab6bcadb, - 0xab79af76, 0xf8c68ee4, 0x30c7ae82, 0xcce38682, 0xfa0d3bb5, 0x017daf39, - 0x3151d7e9, 0xc9c7872a, 0xc53093f1, 0xb59847a8, 0xdf743b3d, 0x3cda77fe, - 0xe3d3ae33, 0x7439013f, 0x8ef969df, 0x9f9e4bfc, 0x7f38c72d, 0x9c1dbd88, - 0x678a54c7, 0xfa17ebf4, 0xbbfd6a73, 0x5f04ae72, 0x15f065ea, 0xdcbaf84f, - 0x19fd833c, 0xfbfd2fe3, 0xc17db593, 0x223ae326, 0xa4f38647, 0x7f8027ce, - 0x2cfe8853, 0x9ea9f4d6, 0x6bbdd107, 0x064fe524, 0x31e7e5c7, 0xc4bfbe81, - 0x81f25ddf, 0x963d453e, 0xc56fb927, 0x71ed79f6, 0xc0efda2a, 0xbf1af56f, - 0x3a6fc849, 0xaae35b9d, 0xebbe69f3, 0xfa4bb204, 0x3ada41d9, 0xd024d79a, - 0x9e0d99ef, 0x87e715e7, 0x7beba7c0, 0xeb55bfe8, 0xe7e73c7f, 0xf9f8fb67, - 0xcd1f943e, 0x0eae679f, 0x1c3d5fba, 0x732885fe, 0xd5eb2109, 0xeb8a36ab, - 0x5abb78eb, 0x85edd7fe, 0x25d701f2, 0xf8377d07, 0x84e1c068, 0x1e518b76, - 0x7cb55f50, 0xb664f742, 0x7f0c89b6, 0x8de700b2, 0xd74f237a, 0x8795be93, - 0x5bb2240a, 0x49d97a82, 0x37ae8bf6, 0xb06b5603, 0x2bb5b9fd, 0xaf51eb0b, - 0xc7ecf76a, 0xc7c5a08b, 0x7348e106, 0x9277bb70, 0xddfc4597, 0x5dbb1cb8, - 0x8f3423d7, 0xe80a2b8d, 0x6d2a855e, 0xe1d49d3d, 0x345378a3, 0x104271e2, - 0x7d7afa1f, 0x15e3a5a7, 0x8197bced, 0xd83af51f, 0xaca69525, 0x7ef8ff60, - 0xe7df0866, 0x841f3839, 0xeabbe7d3, 0x0f83c027, 0x0d43f0f1, 0xc75009ef, - 0x04982d7b, 0xfde617eb, 0x6b5c50cc, 0x56e04232, 0x104e3eb8, 0x5d8f5c4d, - 0x07e22e46, 0x58f7ed31, 0x41cf24ec, 0xe5bb707c, 0xe7168701, 0x3f29eed5, - 0xa1390268, 0xcf3e367d, 0xd4c95dee, 0xddad6cef, 0x6f2f4bdf, 0x7496f2d6, - 0xb5e2b17b, 0xf846cdd4, 0x1cbb7f79, 0x47792f1c, 0x8ed063dd, 0x5c51ee19, - 0xb5e41fe8, 0xf98fdccf, 0xf07bd924, 0x7c820407, 0xe5c2dd9e, 0xc34bb814, - 0x43db9bcb, 0xd874adfb, 0xbbfb3975, 0x28fb23cc, 0xcba457e7, 0x5a72217d, - 0xbe3850e3, 0xc4167e60, 0xa3d464a7, 0x83f7f97a, 0xcf1fb3c3, 0x3e039525, - 0x78eb6d50, 0xbf996d6b, 0x7c7286d2, 0x8e50b994, 0x9be65bbb, 0x315d2146, - 0xa219cc11, 0x79f3d61f, 0xf02876e8, 0xe5f20b65, 0x1a10c73a, 0x7751f86f, - 0x1fbc0e74, 0xc613768e, 0x7eec5b7d, 0x0efc23f4, 0xe2072eef, 0x14ef5673, - 0x8cad4fdc, 0x85b5aeae, 0xdf6bef3c, 0x8f89ed06, 0x1fee22bd, 0xf8c03f95, - 0x7cdaf1bd, 0x02cfa9a0, 0x20c855e3, 0x0f5459a7, 0x655ade20, 0x3ef7bede, - 0x5611a5fa, 0xf97bf229, 0x95befd60, 0x536df3f8, 0xfd17d21c, 0xcb93b424, - 0xee1a4f45, 0x16c1b27b, 0xe003ae17, 0x1fbf1077, 0x06c931b4, 0x4a1efffd, - 0xc4d3d3d4, 0x6b8e74a5, 0xfb40965a, 0x8f7fba44, 0xa4fd0b7a, 0x4d17bf3b, - 0x3c2ec8fc, 0xd3e30c38, 0x4e9cd109, 0xeb558fd0, 0x1b1d6ac7, 0x48ffbf94, - 0x8efe491f, 0x141dbebe, 0xe0e7ea04, 0xd735d74d, 0xd841f885, 0x83ffea1f, - 0xa5b48cc2, 0x1f9affc8, 0x7c61f647, 0x7b45dd70, 0xce21ac65, 0xebe0d3e6, - 0x0a3e4748, 0x3ed147b5, 0x7d67b3ed, 0x0cdf57f3, 0xf4e2767a, 0x715e0096, - 0x6e8acb5f, 0x6fe817fe, 0x36b3d81a, 0x8d3ec3c0, 0xf8660e2f, 0x3d4fdc44, - 0xfba05c38, 0x79450fdc, 0xe095aa73, 0x5c5a8938, 0x33cb5120, 0xe5e28c4f, - 0x1eb8620f, 0xaf863cfc, 0xbca837d7, 0x1c88e89e, 0xbdad9847, 0xeb89a9ff, - 0x91f935f7, 0x684fd1f3, 0xedaaf5fa, 0xfc211cde, 0x8e13eebe, 0xdd7dda09, - 0xe3c76f94, 0xfe340bfd, 0xe8873b06, 0xf8abb414, 0x876e9d7e, 0x4d9f6d9e, - 0xf78213f5, 0x2c047bbd, 0x9f904f3d, 0xf148aef4, 0x6f58e2a1, 0x55a5e622, - 0xcb8e4544, 0xf4f0d20c, 0x38a30d59, 0xcfdc29ef, 0xb7bfe6cb, 0x1b25f585, - 0x1d7ba49e, 0xe29f994a, 0x1a1b45bd, 0xc8aebf68, 0x80a7302f, 0xc78799fe, - 0x943a3581, 0x710d116e, 0xb552c5e7, 0xe4139b1c, 0xae1dfc5b, 0x9b25f7d0, - 0x57ea19c6, 0x1816976f, 0x7a823bf2, 0xbfec90a7, 0x3e757ef0, 0x8f4fb70f, - 0xf10d38d7, 0x861b05ee, 0x78cdf217, 0x73217ede, 0x36177cd1, 0x11ef1966, - 0xb2b84c6e, 0x1ec1827b, 0x538445f5, 0x3fa8fd26, 0xf7f80e3f, 0x17f7c485, - 0xe08c3a7c, 0x7bc38bf8, 0x8e018c5d, 0xc433e668, 0xdff326cf, 0xf8f1b429, - 0xef8ff023, 0x7e407652, 0x07f577cc, 0x1fc01dae, 0xfa87fdc8, 0xb9937903, - 0x024d65fe, 0x9c4ce0e5, 0x66cfb46a, 0x6e75f0c7, 0xc1b44c76, 0x679a2b3e, - 0x6b57376c, 0x776b5737, 0xa84a38b9, 0xa164265d, 0xe9fde33e, 0x71951fbf, - 0xffca6dfa, 0xedc310dc, 0x6eaa9fd7, 0xbbf40c6f, 0xd0773b56, 0xefdade6f, - 0xf735ad4a, 0x5e5285e5, 0x1e6fe6e0, 0x09dfc3ac, 0xf601dde9, 0xfcc1e83f, - 0x7ba0df67, 0x6eeff4ba, 0xb432d15f, 0xa954f008, 0x8bb973c9, 0x15dcafcf, - 0x3f418790, 0xae1ce529, 0x827d96b4, 0x5a5df214, 0x22b76f09, 0x2ff06cc6, - 0xffd5a27f, 0x6549c635, 0x1840495a, 0x3652ed06, 0xec24116d, 0x0b577f0f, - 0x66a949e0, 0x93dfd0fe, 0xedcf194a, 0x6fc7db9a, 0x04e61616, 0x9a68d0f1, - 0x5c62a391, 0x85da3135, 0xaa47cceb, 0x50f10eb7, 0xce8051fe, 0xa8fc4c49, - 0xbdbb425d, 0x23d7755b, 0x7078eb7f, 0xae0a6a8a, 0x711fd1a3, 0xfcfa9b38, - 0x30bebe62, 0x4766a8f6, 0xe976eb37, 0x42edc661, 0x5712a75a, 0x3efc308e, - 0xb69c6261, 0xef32244e, 0x37da854e, 0xa327a232, 0xccae24f9, 0x2c76e66e, - 0x2cb4f7a7, 0x3e7c16cf, 0xb1c8f06d, 0xd647df78, 0xbf8480da, 0x26dafe3b, - 0x51fbc453, 0xc3fc359a, 0xf9c59e3c, 0x9cb8f3e9, 0x99dbd05e, 0xe84f8807, - 0x3d3d10f2, 0xd8c1dfb2, 0xff3ef4e3, 0xe97bf8d9, 0x997acafe, 0xc74e4f7e, - 0x69eab77f, 0xb4a6bc41, 0x3708166c, 0xdc7a78da, 0x5ca39f0e, 0xe78d971e, - 0xfb94073a, 0x16873b15, 0xbd7dca85, 0x1cd9f44c, 0xdbafe796, 0xe1887ff7, - 0x5890eaeb, 0x4bc43ecf, 0x8a3adb65, 0xc2d92cef, 0x4067f77f, 0xfe215cfc, - 0x07ee1284, 0xfbe1cf94, 0x4acff95e, 0x7ab2ff44, 0xe5acfbfe, 0xb8f077db, - 0x0b998fce, 0xcb7943f5, 0x0728a10e, 0x8773077f, 0x9f0428b0, 0xca7ee5a9, - 0xaec6bf83, 0x5bd71fcb, 0x718efce1, 0x0e53b462, 0xe87eb8d9, 0xb87c57cc, - 0xf669dc1f, 0xcebb6396, 0xe61768e4, 0xfff8e977, 0xe99b8efd, 0xa77db5dc, - 0xa3658025, 0x8ac939a9, 0xcad70efb, 0x6eabe42e, 0xe9127bd5, 0x5a792713, - 0x78d8fbf1, 0xbe16abbb, 0x58d85a75, 0x3c72b955, 0x8fe30c4c, 0x72e63f89, - 0xf43aa493, 0x24b186bc, 0xeb9daa37, 0x67d7132d, 0x1e7ccc87, 0xf787193b, - 0xb3ee3107, 0xe3878724, 0xf294dc68, 0xca1f9d00, 0x70d3bd38, 0x5fc830ce, - 0x1b7dbfee, 0x2c3fff7e, 0x00284ba1, 0x0000284b, 0x00088b1f, 0x00000000, - 0x7dd5ff00, 0xc5547c7b, 0xbddcf8f5, 0x0dd90afb, 0xdc3bf79b, 0x24280c10, - 0x01049e6c, 0x878424d9, 0x28026e20, 0x47796bc8, 0xd2026c92, 0x6dfad0fe, - 0xe5318316, 0x16d46b6b, 0x882ea945, 0x835ab696, 0xb80d06a2, 0x47d62228, - 0x2d8aa523, 0x2220a5da, 0xfb1b6484, 0x6fcb56c0, 0xec9999ce, 0x0f0d9bde, - 0x7cf9fb6b, 0xdcc98fe1, 0xe6739f79, 0x9ce7339c, 0xb5331d99, 0x228ca8cd, - 0x389aa6a4, 0xfd2d34bc, 0x84e90ee9, 0xf00b9085, 0x8321226f, 0xf121326c, - 0xbd3ca484, 0x582c524d, 0x1c5a7fbe, 0x052627d6, 0xaed84bbe, 0xa0af9686, - 0x84225ba9, 0xa0e4258c, 0x31cc7881, 0x2ae8b484, 0xfd68d947, 0x7b488496, - 0x663b2d13, 0x68db4573, 0x9d63967f, 0xeab4ac07, 0xa33e6398, 0xda4bf68b, - 0x4264c7e9, 0x121230de, 0x8c1ddb41, 0x6dd3ed60, 0x42229074, 0x07891b26, - 0x233d1bbf, 0xc1dfda14, 0xbfb083a1, 0xa6eab797, 0xc37b697a, 0x19d8b220, - 0x9b74ef32, 0x6ca5db0e, 0xe8e921dd, 0x5a48b8f7, 0x513f321e, 0x595b01ef, - 0xcc67cc26, 0x43844ed4, 0xae3d56dd, 0x1ce8c2a7, 0xb05466b6, 0x8fe868de, - 0xe6ed7bd6, 0xfa7e8c4f, 0xbd2fc7fd, 0xbf50246f, 0xc1b47255, 0x37df5bfc, - 0xa9a1c9ce, 0x4932e7e7, 0x613a6420, 0xf0bf36ff, 0xdfa151be, 0x70a6efa7, - 0x76eaf5a2, 0xa32fd2ef, 0xc5a95769, 0x24268d23, 0x8b6bccf3, 0xdefd2148, - 0x74112266, 0x5736dd6e, 0xfbce8d91, 0x0e535dcd, 0x58845149, 0x20f9339f, - 0xc421f015, 0x06b4e19f, 0x3a5225e7, 0x722fce30, 0x10b3fd2a, 0x55ef46b2, - 0x95ddf099, 0xb7eb4559, 0xccf830c6, 0x42e0cc1f, 0x157bec2c, 0x0b80975f, - 0x8c0a7f1d, 0xdce5915f, 0x2454fd01, 0x329bd846, 0xaff99e61, 0xebdc2999, - 0x823d92ec, 0x672b8d56, 0x579d0cf0, 0x79b84e65, 0xe2f1c06d, 0x44f8d963, - 0x7180cfef, 0xefb2f109, 0xf9216932, 0x3873f6c1, 0x1f77e9be, 0x3a864efb, - 0xd7f38273, 0x4d836fe2, 0xe861fac2, 0xa3ac116c, 0xc7cf98f6, 0x0f53ace8, - 0xe6799674, 0xd043e230, 0xeab6cfcd, 0xd5fd1531, 0x5fd88cd9, 0x708f4d9d, - 0x1a780cd9, 0x2c03534c, 0xcc1ba69a, 0xc7850f5e, 0x1f26f39b, 0x7e297292, - 0x20fa316e, 0xb4b7437d, 0x48dfca16, 0xe8b7e361, 0xdf216b74, 0x34859772, - 0x6e1d5e21, 0x376bcf98, 0x6a7e2147, 0x26bd1ae7, 0x9f8fcfda, 0x63de5897, - 0x67fa12f1, 0x72f66bad, 0x22e24768, 0xfe024fec, 0x738c075c, 0x4ae9fdac, - 0x51bf6e79, 0xb7a7dfa1, 0xf027fdb1, 0xe8c6db50, 0x0107ec4b, 0xbd3c20d7, - 0xf024fdaa, 0x8db07f31, 0x17a505d1, 0xcecd7780, 0x3349db08, 0x0102eb1b, - 0xe5568cfa, 0x6d93dbeb, 0xf3044727, 0xd007f035, 0x81620ec1, 0x79f2d679, - 0xeeb9d3ce, 0x6755fd83, 0x50341ff6, 0x0d1f16d4, 0x881f7ee0, 0xffd66b7e, - 0x0164fb3a, 0x0e93ab21, 0xadf62a61, 0x7f7aa861, 0x6f78e56f, 0x7bb69482, - 0x4d4dd382, 0xcbee1b61, 0xb80d939a, 0x19532d9f, 0x231cb35f, 0x133c508e, - 0xdebe43f2, 0x457db17b, 0x9964db64, 0x71e2bdc2, 0xfa44d6c9, 0xaba44fcf, - 0xa36ce224, 0xf5b67dfd, 0x0025a8f5, 0xc82eafdf, 0x37ae98a4, 0x3777ad82, - 0x3b5d3be7, 0xde91c029, 0xcc248c1b, 0x3fb72f7a, 0x01223be2, 0xec386b3c, - 0x1f2e9ebb, 0x17a529fb, 0xf6c1cecf, 0xcf92e8ab, 0xf6eb3d3e, 0xbbbce94f, - 0xcbb44c76, 0x4e4d3640, 0x7c409fa4, 0xa53b7d84, 0x4c99389f, 0x37de2895, - 0x351ebdb4, 0xfcfbb68e, 0x81f3a397, 0xf7cdbf6f, 0xe5e799fd, 0xbb9700f5, - 0x75ecf67e, 0x95e35e50, 0xce304d62, 0x95ffc7ce, 0xdea9fb42, 0x26100f51, - 0xd57cbf4d, 0x74f5a7e8, 0xfbec6dde, 0xa836c1ce, 0xf713f9f7, 0x6ef0075f, - 0xf2c26b6a, 0xc36c4f33, 0x7b3f6bfc, 0x683fdf76, 0x94675abd, 0x799dea1d, - 0xa5e23f7e, 0xc077a5d6, 0xeba2077a, 0x33f6bbcd, 0xe126d97e, 0x1973237e, - 0x2d74131f, 0x9ff3f7e8, 0x2a1b1e2d, 0x16f7c437, 0x833b9723, 0xcb391c98, - 0x994d6ff7, 0xb3d205a5, 0x85cc44cf, 0xfe8dbaf5, 0xcf9868ec, 0x1f174628, - 0xb6d47871, 0x2db831ad, 0xf9fb1ed8, 0x487bee80, 0x9e7d2873, 0x6b4ef4a2, - 0x0050b8ed, 0xeb0afde3, 0x11257ad3, 0x2f37be14, 0x7cc12e38, 0x18354722, - 0xbf9e706a, 0xd574e564, 0xebc5e5a1, 0xe96a3d18, 0x059b0be0, 0x907d8beb, - 0x4d32bbb2, 0xb2603e41, 0xd6ce3e33, 0x6aed5297, 0xd7efd2b2, 0x65d973af, - 0x4f97c78a, 0x4a9c9e1f, 0x211b3ff3, 0x65fe2015, 0x8f39c989, 0x5ba9c705, - 0xd04e465f, 0xd9a2eaf9, 0x11b0497e, 0x07c8b5fd, 0xd7ba31b6, 0xf205bd13, - 0x89f200fa, 0x072e16ba, 0x1279b077, 0x96632073, 0xae59db15, 0x83ce098d, - 0x3058b3b6, 0x29b8c81f, 0x678ee407, 0xc51dca2e, 0x233df388, 0xe4f101f8, - 0xee09cc2e, 0x711d04b7, 0x8c13fe01, 0x7e30b534, 0x4ffb4953, 0x8a4d2e8f, - 0x09a60a2e, 0x16b95883, 0xf2f0b74e, 0x923b451f, 0x3b5e01a2, 0x60f25563, - 0xdaf2be20, 0x6e4cddcd, 0xe91c72bf, 0x08740dd0, 0xaa4ebbe3, 0x6472f6e4, - 0xf70e94ae, 0x5c3a471c, 0xabf8cede, 0xb8d4bdbb, 0x259ba68c, 0xefe61732, - 0x7404f4e6, 0x9bf9a764, 0x7d71a3a2, 0xd9fcebee, 0x39baa7c0, 0x61ef75dd, - 0x4e86f6f4, 0xbcf801e7, 0x36e47db1, 0xf95a0790, 0x113b5528, 0x6f8a6edf, - 0xd67a0493, 0x67a0c3ba, 0x3b1355d5, 0x6ef757ec, 0x081a1fbe, 0x7b7707ee, - 0x2fe872e5, 0x5d9a6e35, 0x992f5096, 0xeef34a9c, 0xfb04525a, 0xd96b652d, - 0xd20ba01e, 0x20ab912e, 0x0ddced5f, 0xab8fafed, 0x2099cbb3, 0x9927b6f7, - 0x47ebfd69, 0xcdfb6314, 0xf4294ae9, 0xb620a9e7, 0x706f2127, 0x9cdb3ca1, - 0xf20ed23c, 0x88daedce, 0x0651177a, 0xb89ca1d9, 0xbea16bf4, 0x6c80b3db, - 0xe3ecc292, 0xcb03923d, 0x08de91bd, 0x3b7a7eda, 0xeddc7fd3, 0x139f1f6c, - 0xa1a911f0, 0xd78c1173, 0x788982fd, 0xbd9d20a4, 0x930a67b9, 0x509a2fb3, - 0x746d9ece, 0x34541390, 0x10568c8f, 0x358e02af, 0xa03a99ad, 0x9966425b, - 0xf8cb1e60, 0x4c0d5a3c, 0x3973446e, 0x9b2f7590, 0x1fbe72c7, 0x78eb4796, - 0xaffbe46a, 0x9b05c995, 0xe0e41727, 0x921e3e39, 0x73970245, 0xe5bae874, - 0xb527dc3e, 0xe2feb34f, 0xdbbc8e4c, 0xe855e842, 0x6c7a5a47, 0x6ca6e3e2, - 0x3301203d, 0xa55ad949, 0x57d7e7da, 0x5d3d5f13, 0x755bf5e7, 0xa8b989be, - 0xfc82dd37, 0x6c91837c, 0x77f7fa97, 0x5be3344f, 0x3cceb115, 0xcdd7e409, - 0xfa3fd416, 0x8720e9f6, 0xb8f4022e, 0x84dec97c, 0xea1670ab, 0x09d3bd68, - 0xede03b56, 0x5a8e1c47, 0xbdafab7d, 0xd19c0f46, 0x4325c9ea, 0x4186e969, - 0x549e0173, 0xa198b75f, 0xa7b68d9d, 0x8fb612f5, 0xf213627b, 0xf7ec26ab, - 0xeb1b68f6, 0xd859d627, 0xcb2e2c00, 0x27c98eb9, 0x7adc3dab, 0x9e85a3d2, - 0x074f28bd, 0x82db33f4, 0xafc7e1fb, 0xbd194b48, 0x01284151, 0x41fdb23d, - 0x5278fee8, 0x3d447a41, 0xf4e0ddca, 0xb647a786, 0xaf54dc5f, 0xd29b3d02, - 0x27a65ae3, 0x4fdb085b, 0xa7232e8c, 0x7c007932, 0x159f542b, 0xefbb54fb, - 0xedf6fd05, 0xefdccbfb, 0x1fb606dd, 0x801c29bb, 0xfce8fbde, 0x9be74665, - 0x48fdd036, 0xfdd137cb, 0xffc214d8, 0x981fe7b5, 0x04079c27, 0x73663dbf, - 0x745f0076, 0x19ab7f6f, 0x47f396c9, 0xc83fcbf7, 0x65de98be, 0x5fb4ca86, - 0xa1afdd33, 0xe0a663f4, 0xea63e6b6, 0xb9113901, 0x8947ad5e, 0x266883f4, - 0xdeb1bebf, 0xa3d24238, 0x55f1c3de, 0x007d73ab, 0x46f41e7c, 0x6324114a, - 0x131bd33d, 0xde00e640, 0x417a47b6, 0x20484e3f, 0xccc2e7ae, 0x67df3f67, - 0xfce29f02, 0xeac51090, 0xff7df2f7, 0x4ff7af29, 0x4b9c869e, 0x3a283f70, - 0x0f2271d7, 0x3b448f2c, 0x172c2f3a, 0xd73be9f3, 0x137cd998, 0xbedecaee, - 0xc18f0429, 0x3e75757d, 0x5eeb37e0, 0x25a97e9f, 0x8b908e38, 0xf981ba5a, - 0xf581fc83, 0xb81a8e54, 0x7e7eeb5e, 0x71d0d33e, 0x7b5fdf04, 0xb482b8a8, - 0x2bfbe0d5, 0x5635c7ee, 0x2522fa02, 0x9d2c4707, 0xe1befd57, 0x088d1f6c, - 0xeafb4364, 0x314dd758, 0x9331dfb4, 0xdfa0fef8, 0xa09ce0ab, 0x0c531e27, - 0xf5e0dde0, 0xd3f9e087, 0x8f7fd618, 0xe991ecd5, 0xd623b8fe, 0x3ded0d15, - 0x03eec465, 0xe5077339, 0x896fb027, 0x4df808af, 0x0147f13d, 0x5d58c79c, - 0xbf4031f1, 0xc9366772, 0xf257fca2, 0x63f7c2e7, 0x84b95111, 0xfb71f3f6, - 0x85799f6f, 0xcaf85ab6, 0x03df85b9, 0x22317afa, 0x18e2e803, 0x513b97d5, - 0x830656df, 0x944bddbe, 0xfc30b6c1, 0xcc0ba457, 0x20beb33a, 0x55663f98, - 0x7a442f9f, 0x6fc30c4d, 0xe214f9fd, 0x09fe8589, 0x627bbf9e, 0x1f5df614, - 0x56ea8230, 0x78833e7f, 0xeb1f7f68, 0x985b7548, 0x30c53771, 0xc84ddb7a, - 0xf7e570d4, 0x0f7671f1, 0xb030fb65, 0x7f02f24d, 0xe1bf5eac, 0x07e532cf, - 0x3eacebd5, 0xe831694c, 0x8f36d56f, 0xc7f3474f, 0xd11f8c0c, 0xc5cdb37f, - 0xeb47b941, 0x0e03c7e9, 0x4b20f43c, 0x2e52e0f9, 0xbc3596b7, 0x13d825f9, - 0x3cc4f5aa, 0xdcb3f69e, 0x4a983cec, 0x2cb33e8b, 0xbfb6028f, 0x25b73bf2, - 0x5c4a5c80, 0x32eccad0, 0xf40d9264, 0x4331c95e, 0x317910be, 0xfa8f4b3d, - 0xe29fe231, 0xe7188beb, 0x82f7c04c, 0x80f504c1, 0x7a45b705, 0xd07c213d, - 0xa5a1e1cc, 0x7eb84f9b, 0x767feda5, 0xfe81196c, 0x739ca23a, 0xdc163e81, - 0xcfc54e76, 0x53ff25ba, 0xad5d028f, 0x649fdab1, 0x433865dd, 0x623bfee8, - 0xc43af3bc, 0x675e4f53, 0xa04cfaf6, 0x87c640df, 0x30eacf60, 0x940a3cd9, - 0xa2cf111b, 0x291a9fdd, 0xe60ecbe3, 0x361e9e97, 0x196be819, 0xde0337b1, - 0x1244b597, 0x033f084f, 0xc3e81805, 0x3f609e7d, 0x3cde3b4b, 0xaddcfc0a, - 0x2c9d23f7, 0x8f105b35, 0x9c7af3ee, 0x74316907, 0x8a7b45f9, 0x8e5123fb, - 0x9e7d60db, 0x9f47c67b, 0x263f491a, 0x7eb8efd2, 0xfdf0edd7, 0xe228c8a1, - 0x4b78fa00, 0xf3a70ef6, 0x832b35ef, 0xeabc2863, 0x460e948d, 0x734e3763, - 0xd243fe88, 0x77fc6aac, 0xcc25f5bc, 0x65d9b967, 0xc2be3904, 0x32a7cf41, - 0x6457c9e0, 0xef8a151b, 0x9185f2f1, 0x45ef8f97, 0x6c7fbf7c, 0x661ff4a4, - 0xe1c7dd1f, 0xa5ea23df, 0x71f27db0, 0x0e7ea906, 0x4a686bd2, 0x943c7ddb, - 0x3e79f3e7, 0x604bd79b, 0x9f7c1df9, 0xeacb9c7c, 0xc5f1c769, 0x3b36fe30, - 0xe015b1d6, 0x8cf9db45, 0x22fb1740, 0x16b7a8bc, 0xfc077e52, 0xea3a6d6d, - 0xedaf94ad, 0xc4d97ac0, 0x4cf58d17, 0x03485728, 0xcfb07be5, 0xcf84148b, - 0x274a52a6, 0xd7b03cb4, 0x04aedb64, 0xa9f02af1, 0x8c7b63c5, 0xc3c9eff4, - 0xd43e9251, 0x61e5428e, 0xa3b30c7b, 0xd27f6118, 0x9e991899, 0x85f10c36, - 0x3e5f2274, 0x608c6ebe, 0xf4fba078, 0x7bd418b5, 0xfba1397d, 0x97c704e5, - 0x0f1f67e0, 0x8ab5e352, 0x5e6de1e3, 0x8d8c516f, 0x007b4fc9, 0x31c7ddf7, - 0x165c7eac, 0x0f424393, 0xcb8703ff, 0xc8549a4d, 0xd5533195, 0x1c4dc5fa, - 0x44c5379f, 0x087ebc09, 0x88f215f3, 0x345f17f2, 0x5e0b0fdd, 0x217f2135, - 0xb0d9031b, 0x63bd68ff, 0x2c0a6e58, 0xe472a58a, 0x18dfaa26, 0x22ddb1f3, - 0x3cefdf68, 0x85d04a3f, 0x3e9c8095, 0x1853d625, 0xe54f7e40, 0x296bae1d, - 0xba437ca1, 0xd037fe34, 0xd694c93a, 0xd8560c87, 0x03a64ef9, 0x208fed02, - 0xe147f40a, 0xb850e7fe, 0xc63bc76b, 0x319fe0e9, 0x96f11e92, 0x9f70f247, - 0x7585ffbd, 0x9cf2ed21, 0x51d1eccd, 0xceb8ffbe, 0xe9fa0175, 0xd42dfdba, - 0x7d198fcb, 0x3096add9, 0x63df46e5, 0xf2c1490f, 0x3d973fc5, 0x762fca46, - 0xe4fd7677, 0xa5eeba66, 0x861db29d, 0x5fe77a5c, 0x7a031ddf, 0x0ec1a775, - 0xdf2a46e7, 0xbcc3d5ef, 0x791e981b, 0x83a6a74c, 0x9f55dfb3, 0x1962d273, - 0x83dea8be, 0x3be09cfa, 0x4adf7e42, 0x5c81577c, 0x461c465f, 0x66b4ff48, - 0xe1420cd5, 0x0eb2c2b7, 0x6be7d1f9, 0xbc1ea1a7, 0x7cb07892, 0x4fe18b59, - 0x4561f2a1, 0xeabf3aab, 0x56fe7561, 0x67df3aaf, 0x2f0f2e7f, 0x32c7a7df, - 0xd94b3e3a, 0xb03fe03e, 0x3d05e4c1, 0x98af5b48, 0x3ca4cbd7, 0x24f813b1, - 0x4760fb95, 0x48e11758, 0x6ebebe04, 0xc5e2696f, 0xe7f57cec, 0x10de21af, - 0x37a8237d, 0x6c6f12e4, 0x63cb7eff, 0xf4238415, 0xe071f0ab, 0x2cb671bc, - 0xc6263afc, 0x10653d0a, 0x8bbe27f6, 0x45e3827e, 0xcfea3ce1, 0x8f98079b, - 0x5d9fdb05, 0x1b9c7e19, 0xa9b1c6fa, 0x7db064e4, 0xfc6b931c, 0xa3e82d1c, - 0x7e127cfe, 0x07a17917, 0x31a5db07, 0xd9a48afd, 0xf906454e, 0x8b63b094, - 0x224270fd, 0x3bb464e6, 0xebcfcfdd, 0x5fb05cf6, 0x083d009f, 0x6514e3f6, - 0x714e9f9f, 0x66c6f7d9, 0xf70687eb, 0x941d768b, 0x43f8ceae, 0x58b2eef8, - 0x6b8e1c6b, 0x57187627, 0xdba2fbd0, 0xe8bb062b, 0x6778ff7c, 0x546ba279, - 0x30f53f28, 0xe85189bf, 0x9c95165f, 0xbc391a25, 0xd42dfdac, 0x95bea8bb, - 0xd3e74c0d, 0xbd23b7bd, 0x04ce24af, 0xbd9ef3a0, 0xff5c33c3, 0xf315fc86, - 0x6259e599, 0x9ba79820, 0x2abfee98, 0x1d599f3e, 0x99d3ef4c, 0xc71c061d, - 0x025b1441, 0x7cd9a51e, 0xd3d4f329, 0xf9be84fc, 0x908e9183, 0x12fe7cf1, - 0x9df0a7b4, 0xd4b253c0, 0x36f30495, 0xbc74b8c1, 0x824de208, 0x5dac69b4, - 0xe4a27481, 0x3079b3d4, 0x0d264f3c, 0x675f5069, 0x9d6ccbf6, 0xd0090674, - 0x985e0fbe, 0xc6fcf2b7, 0x568bbdd9, 0x158b77c0, 0xcf9188f9, 0xe52c4763, - 0x2fe46687, 0xc9b75866, 0xfd1cfbe2, 0x94f53c64, 0x3d8fb829, 0x3bda0943, - 0x02369106, 0xe72c5ae3, 0x1b58b03c, 0x8f9049b1, 0xe0faf5b0, 0x66ce70fc, - 0x2346e8f1, 0x0b19dc9f, 0x677a527c, 0xf285e025, 0x19ff6665, 0xc3ef5ca8, - 0x73e0b773, 0x4d7e7c31, 0x1325cf9c, 0xe2588706, 0xb01ef1c0, 0x40419cae, - 0x49d65984, 0xd44b7ed0, 0x25eff454, 0x7969e000, 0x8abd54ec, 0xd53bc56f, - 0xeab9c4f9, 0x9d4bb27c, 0x3f93d337, 0xcf928be8, 0x16217499, 0xc02359cf, - 0xfce062de, 0xebcf99a2, 0x3d74a408, 0xfd3e71ef, 0xbb13f58d, 0x8eeebcfa, - 0xe3b41231, 0xd0cd9825, 0xde57d53f, 0xcafa658b, 0x97281e27, 0xf3cfc803, - 0xc0f9b626, 0x837cd3ae, 0x7e8bbf64, 0x1b2ab66f, 0x3d5494f4, 0xc76624d3, - 0xf54adbd1, 0x865b7cb4, 0xe689becd, 0x1d7ec1eb, 0xd5b7f30b, 0x49f68d3c, - 0x0247ab13, 0xdc8fe0cd, 0x8366c9b6, 0x81e5717a, 0x8bd046c9, 0x76db1057, - 0xbfbe8612, 0xce86fba2, 0x53c809f7, 0x5e9c48bc, 0xf3290f22, 0x7cbc0d71, - 0xc59dfc07, 0xe18b13f2, 0x65feca5c, 0x3a75e475, 0x90e0eec0, 0x77d62e51, - 0xa16ebde4, 0xcecd65e3, 0xb3bc3b43, 0x0973f99c, 0x3463f7df, 0x905c6afb, - 0x8f3cb1ce, 0x707587e7, 0x899c6ebb, 0x746d6bf9, 0x36666288, 0x8c71fac0, - 0xfc44edfe, 0x5af2fb63, 0xfd07fc12, 0x47fb0795, 0x5829343e, 0x7467dc1c, - 0xbdb37ca8, 0x1bd696a9, 0x87edf7a3, 0xa78e3c7d, 0xa37d3c79, 0xbf9406f4, - 0x628b3a9d, 0x6d7db1d4, 0x861302ce, 0x14b80653, 0x04d07edb, 0x7c904cfd, - 0xbd4c6698, 0x5fa609bf, 0xd147edc5, 0x06ef4649, 0x12a68eba, 0x77b4678a, - 0xd820f9fc, 0x4907e5a5, 0x88e9e001, 0x0739c841, 0x7a15d39e, 0x3a1afb1c, - 0xfd406c98, 0x2a932ffc, 0xd5013bf0, 0xd2bbce8c, 0xbe2116c6, 0x755f2c0f, - 0xe36a3f28, 0xb337e464, 0x6abf32a6, 0x57b35cfd, 0x10ce4092, 0xbbd277e6, - 0xb10a6f32, 0xc43f0897, 0x773206fb, 0x44f39857, 0x4fd31c6d, 0x3b3066ab, - 0xa346fd6f, 0x1d537fca, 0x335eecc7, 0x8c8f26e3, 0xfcc47943, 0x5c7179a7, - 0x46411b6f, 0xe10a9f00, 0xaf504523, 0x81edf4ab, 0x9cba8cf8, 0x8e3999f3, - 0xfdea0302, 0xbe08df9c, 0xf6c41cee, 0xd2423cf3, 0x9367ae81, 0x87ffe406, - 0x7e456f4b, 0x18f11373, 0x951f6f00, 0x310278b1, 0xd55359ef, 0xa71cd27a, - 0x5cf37f3a, 0xf0c51ead, 0xe79dc621, 0x09579752, 0x5aaa783d, 0xfff05e0f, - 0xb9468abe, 0xdd54f89a, 0xe7e02185, 0xc000f660, 0xe873f30b, 0x1bdc6e91, - 0xbebc3f99, 0x388def3d, 0x127767d8, 0x4976cfbe, 0xb2ffd1cb, 0x82115a4b, - 0xaf5ad4ff, 0xb8647204, 0x987dd855, 0x7934e4de, 0xc3df83f7, 0x91128359, - 0x49e3cebc, 0x493c400e, 0xadbe907e, 0x57165665, 0x30b51c41, 0xa45b349f, - 0x16fef41d, 0x65da3e5d, 0x2aaca25b, 0x0da6fa3b, 0x13d4054a, 0x44c558f6, - 0x6e9c6df2, 0xd7779dc2, 0xbafe31c5, 0x71766259, 0x9e333ccf, 0x9cb3e32b, - 0xbc413f2a, 0x9d828e4c, 0x229c6470, 0x63fda3ea, 0x5c95c1b3, 0x44af5340, - 0xd2171197, 0xd11b265e, 0x4fe1a8ae, 0xb476b1f1, 0xce0fc7eb, 0x9cfd3b41, - 0x2fb43c8e, 0xfd844b12, 0xffd8292a, 0xf4dbd99c, 0xdf53a710, 0xdcbf4db1, - 0x7bbba412, 0x8d5cb8e2, 0xaf409124, 0xe7ba767d, 0x7ba7684c, 0x5ffce75c, - 0xa35acba0, 0x2171ed0f, 0x07df8af4, 0x38ab8b92, 0x9cca18bd, 0xf9d056f3, - 0xb46bbcf5, 0x1d19f9c3, 0xe7ffb46d, 0x9da344f7, 0x50455f51, 0x652c6d3e, - 0xec07a47c, 0x9f1d745f, 0xf9e35745, 0x8ad4a360, 0x663ba3f2, 0x6af1d232, - 0x073c01cb, 0x74a56f57, 0x569f2218, 0x6be750ef, 0xdf9e2748, 0x47ee9f6b, - 0x0517c8cf, 0x56ef761f, 0xd4c323b7, 0xcb8f377c, 0x7da77c8b, 0x7d4c0556, - 0x9d8b3dae, 0x8641e9c3, 0x1de8a3ae, 0x2eefb723, 0x008a9db0, 0x7494fb56, - 0xc7adfd31, 0xfb665a7a, 0x2283c99f, 0x6e568e3e, 0xedbd7115, 0xe0bfca3a, - 0xb0f42afc, 0x07f2c222, 0x92721d74, 0x42df382e, 0x7fe84ede, 0x7c084e42, - 0x52109695, 0xa743f742, 0xc9434fe0, 0xed37c050, 0x0489f71f, 0xd8314391, - 0x7dce07bf, 0x9478f8e3, 0xb7203c1e, 0x17b33a3d, 0x6a59abe8, 0x06693940, - 0x9ba69f3d, 0x83ca1724, 0x323daa97, 0x692c7bc0, 0xd6833598, 0x8cee6f1b, - 0x3a513804, 0x3f4a1239, 0xb197c44d, 0x11d1524b, 0xbf457796, 0x848e961d, - 0xc47df33c, 0x74e998f4, 0x054fd0c5, 0x7a687e38, 0xc8e76240, 0xeb1f9629, - 0xbadbfda1, 0x53274869, 0xf30f5789, 0xf1a9b0ab, 0x9d49253f, 0xa3f4a69f, - 0x70c38c0f, 0x1f4e7870, 0x08772ea1, 0xfcd4477e, 0x857c932e, 0xc1f9187a, - 0x5d80efc1, 0x193d7221, 0xd50dfa01, 0x6a1f7144, 0xb8ebe0e9, 0xf26fdd6f, - 0xbf185c75, 0x13b70f49, 0x2bfc4b5f, 0xd3fa969f, 0xeb1bf759, 0x7a10a4e5, - 0x65e2fb14, 0x907f8b03, 0xa9fe655e, 0xe5193312, 0x642afa03, 0x3fb14576, - 0x8cfa05ae, 0x315dd209, 0xcf119eff, 0x19086ce9, 0xa1367402, 0x5327c23d, - 0xfef1e4bc, 0xcbba05ae, 0xe223ea0f, 0xd254d15c, 0xa532be8f, 0x705fd42c, - 0xa47d09df, 0xd26b6a40, 0xb91f0267, 0x1be609a7, 0xe3434f42, 0x512f808b, - 0xda7dc27a, 0xcbaace4f, 0xf026f435, 0x52e5f42e, 0x367480d2, 0xea60a75b, - 0xf2855cab, 0x5b32dcb5, 0xacdfed0f, 0x0936f462, 0xea0b31e8, 0xdca5e9ab, - 0xe96bceac, 0x0ba88e91, 0x9f4b571d, 0x10dbd103, 0x5f2137a0, 0x6f4d2f63, - 0x75bfe3d3, 0x7f1e9b7a, 0xd2d37a11, 0xbb5fe099, 0xa0e56c22, 0x4b57d73f, - 0xde0a0f28, 0xf904d61d, 0xa89975e1, 0xb68aef4f, 0xdf5d7ea3, 0x3b0bcac0, - 0xbdc4321d, 0xe5e3ad64, 0xc872ce99, 0xe5a7afd7, 0x23a2ebb4, 0xd8662e2c, - 0xef3cac9d, 0xadd786ae, 0x587867a0, 0x6f3f97fb, 0xb968a396, 0x2fb799b7, - 0x7c872d6d, 0xff6b0b7d, 0x46a9f819, 0xb79a7c43, 0x7d5fbe09, 0x1d9da66f, - 0x3efe99ab, 0x9777af91, 0xd8ebdcf4, 0x5bb595ae, 0x883cd075, 0xe99ff9e0, - 0x75f1d7e5, 0xd6cadc4e, 0xfae27719, 0x8ba50aa9, 0xea0f0115, 0xb574a76f, - 0x06dfc8c5, 0x4a973f38, 0x4e9069ad, 0x5217eca1, 0x22ded987, 0xcc7e650f, - 0x7b8874ed, 0x45fd99e2, 0xce20fff8, 0x9f4432a0, 0xd99e27b8, 0x84bd4563, - 0xa0018a18, 0xa8ac4787, 0xa4ff0b5f, 0x812221ef, 0x723587bc, 0xbfac243d, - 0x03564a72, 0x865311ea, 0x5fa53f08, 0x9b8e94bf, 0xc98be177, 0x3f43ece1, - 0xe69ee3e2, 0x7a7d1371, 0x075337b2, 0x880bb174, 0xf4800524, 0x7f41afde, - 0x487e05db, 0xa43ca426, 0xf2caf004, 0xbd7fe35b, 0x853c65a9, 0xef41aeaf, - 0x2196a101, 0xccc9dc61, 0x1c1be24e, 0x53fe7fd5, 0xc467c4f4, 0xff362638, - 0x1e544d95, 0x7e31d123, 0x8fe38736, 0xe90abf8c, 0xd3c73677, 0x2a7f05cf, - 0x9fc00520, 0xddbc70e6, 0x347aa664, 0x8356c3f2, 0x133c6f86, 0xcb6a720f, - 0xbabbfa80, 0xaa57c35c, 0xb92bb8f9, 0x092b7ede, 0x4a727ea0, 0x7a7a62f2, - 0x6bdbd30b, 0xbf50472c, 0xe98479e9, 0x8fc4b5ed, 0xbed68ffa, 0x9d53b359, - 0xe7536baf, 0xf9d5dbeb, 0x8e0f1c9e, 0xaea5b3d3, 0xd58aec18, 0x768bbf0f, - 0x5fc16aec, 0x42fe6abc, 0x5fc67115, 0xed06ba1e, 0x6f98df51, 0x6f4f4d3c, - 0xd0b8aac5, 0xfa9c02df, 0xb22f35ec, 0x613714f8, 0xeb1e8276, 0x4e70f988, - 0xa4791a25, 0x9c7927e5, 0x86fb089f, 0x84792fe0, 0x8e7a23c9, 0x8241d77d, - 0xd7ab5c7c, 0xbd73c4f5, 0x84d39f97, 0xfa0793fe, 0x35d3d00f, 0x4164480d, - 0xdb7f6439, 0x9fc88724, 0xc0668579, 0xee99be73, 0x6c978067, 0x545971c9, - 0xca05f0f4, 0x7bcf8199, 0xbd0d72ea, 0x2dd6f388, 0x81665e9c, 0xff8e8527, - 0xe781c97b, 0x32b7c3ba, 0x5963997a, 0xd1faf487, 0xe22f466a, 0xe7e577dc, - 0x4dfc873c, 0x747d79ce, 0x5ef54112, 0x17491e9a, 0x8fe67ce7, 0x1d1897af, - 0xf87d55d4, 0x82cfe818, 0x246e1c2f, 0x3e10faf1, 0x64cd34d1, 0x934a3b06, - 0xaa839d81, 0xbc5c7fa6, 0x38cf8434, 0x13134a22, 0x88ee5940, 0x5d6cfb47, - 0x669c7aa4, 0x7fbbf3a9, 0x4fd2f380, 0xd44ed123, 0x954130fb, 0x70eb77a4, - 0x6b3edb8c, 0x31527e60, 0x7707559f, 0x7ec3f3ee, 0x08ebff5c, 0x359f953d, - 0x5ac5f792, 0xe4c4b65a, 0x6a7186ca, 0xb3233e74, 0x5fa27663, 0xb03b8c57, - 0xf283d65d, 0x931af8d5, 0x106901c3, 0xefd2e1c6, 0xb5fea1d9, 0x4f8c89d1, - 0x2aeb11df, 0xca0f8848, 0xa43f614b, 0xc6a49652, 0xc126fd04, 0x376606f8, - 0x5c710bf9, 0x6361be32, 0xb69e7d88, 0x568f1b0f, 0xf5f8c096, 0x61ce29f7, - 0x1da307de, 0xd39f30e5, 0x9a7b8fdc, 0x474efdfb, 0xcce03f31, 0x752cfabe, - 0xf734f4f1, 0x518e9e13, 0xbd4487fb, 0x8ecc09a5, 0x6cd1b272, 0xbf07a8de, - 0x1c6f313a, 0x21ec4946, 0x93c60353, 0xea78602c, 0x6dbd13d9, 0xa5ff8853, - 0xfbf4a12e, 0xd87f9f30, 0xba43379c, 0x31b8f5bc, 0x23df0ed4, 0x0f77f3b1, - 0x089e97a7, 0xeb718a96, 0x0fbf2a12, 0xe799ec78, 0xe5f63c47, 0x13bc8ac7, - 0xc099effb, 0xfe5f6bf8, 0xb84f2c3b, 0xf5d843dd, 0x69f7f207, 0xd0547bfd, - 0x044073b0, 0xfd6bcfb3, 0x3f050bf3, 0x05f9fee3, 0xec2d1f9c, 0x45827e60, - 0x4a9cd266, 0x247717cb, 0x946e73b2, 0x9fe55b27, 0x515e44f7, 0xcba0863c, - 0x3ecef49e, 0x2123f67f, 0xee3aecfe, 0xeb13accf, 0xdf5eaddb, 0xbadf0903, - 0x8481fb3f, 0x6d6cfe30, 0xa08bc3dc, 0xe20b0c47, 0xc18dad61, 0x2dae42ad, - 0xef6f7b07, 0xe8718272, 0xd65adf6b, 0xb5e0f604, 0x2a0b003f, 0xa7d431f2, - 0x079c38eb, 0x53bc575a, 0x9d951447, 0x4251107d, 0x8aec9fe6, 0x4351e551, - 0x4d03890f, 0xb5514ead, 0xaa186f4f, 0xfd643faa, 0x4cf2aa35, 0x9f2abe4f, - 0xaaad72d5, 0x65ad55fe, 0x87f0fcaa, 0xcfd557af, 0xa3074323, 0x0c90ecfd, - 0xb57221b6, 0x3e554ab7, 0xaa2de772, 0x86919ff6, 0xbd69e3cd, 0x79fe42dd, - 0x8aa39d1c, 0x39ce7183, 0xed554b6d, 0x62b6a49b, 0x9f46f01f, 0xbd6893e4, - 0xcb5f1c15, 0x62ff993b, 0x556afb74, 0xd8a367ff, 0x5fad183d, 0xa32e7696, - 0x912ed61e, 0x7efea447, 0xfb8eeada, 0xa8ee219b, 0xf296bfbf, 0x356eda4d, - 0xfe80bf3d, 0x8e6fd5a6, 0x5d3f7026, 0x7461490a, 0x0b0ba5ad, 0x5bbd7fea, - 0xe627b465, 0xc687ec91, 0xc40cbc23, 0x5fc7f4ab, 0xae76612f, 0x76ada7de, - 0xf559ff88, 0x47a432d6, 0x2e9a9253, 0x5d351422, 0xd3508e44, 0xa6aed585, - 0x6a25c183, 0x3dc2d03a, 0x0ba6a1da, 0x43ffa7e2, 0x2ae02de0, 0x553b1ee0, - 0x785a374d, 0xda0093e7, 0xc95eddd9, 0xfc6123ee, 0x70dbede2, 0x1fd2975d, - 0xf86a89f5, 0x34701c16, 0x2c6e1059, 0x61e84cbe, 0x68ffae26, 0xaf4213fd, - 0x7ae44b89, 0xf847ef15, 0x0f259a17, 0xfe7d51ea, 0x865f12c2, 0xa7f4132f, - 0x44ecc206, 0xf0c4a4ce, 0x3efc4676, 0xc0519d90, 0x2620f675, 0x03886b2f, - 0x882be1ed, 0xc9ddf90b, 0x3ed15bca, 0x63f2cab4, 0xad9ebbf4, 0x35527a62, - 0xbf9f22f1, 0xaa02b8e2, 0xfb109287, 0x528e16ab, 0x02b3e487, 0x20f2e1bf, - 0x79087485, 0x1378c2e0, 0x62e6864a, 0xad471f95, 0x30df82e7, 0xbd097f84, - 0xe0278c57, 0x189af829, 0xe41a44cf, 0x1a17d824, 0x6846473e, 0x3b6a48fd, - 0xe0f3b08d, 0x22fe2160, 0x44265dad, 0xe9916e0f, 0xcc90f238, 0x57f14226, - 0xdda07360, 0xce7488af, 0xe625ef87, 0xc2bd26b6, 0x935713ed, 0x80c4fb3e, - 0xfe12eaf2, 0xc91e59e8, 0x7f6668ff, 0x6bf0b43f, 0xf89fe5d3, 0x5e3c6d03, - 0x55ef1052, 0x078f0f2f, 0xa76fea7a, 0x857d1fb4, 0x02eb23f6, 0xc3f6a1b1, - 0x9206fbbe, 0x1373d71f, 0x424ddc71, 0x693710f4, 0x133f3c9b, 0x4e54c4ec, - 0xecca4146, 0xab5da458, 0x8ed1eb07, 0x012ba3ac, 0x2121afba, 0x60ccda7e, - 0xfee5e639, 0x74371179, 0x42e27d29, 0x3fc78da2, 0xc22778b0, 0x5f38a0f9, - 0x139e740e, 0xcf701471, 0x2221fc16, 0x9139a84e, 0x4973839f, 0xf74ff42e, - 0xb444a6db, 0x29fdd01f, 0xbec7ee85, 0xef2c22b8, 0xeb351fb7, 0xb2147117, - 0x42ed10b5, 0x7bd742cb, 0x7a10f019, 0x3ea86fcb, 0x1234f780, 0x0dd7a615, - 0x0381f63a, 0x553b0b8a, 0x46f59e71, 0x7b01807a, 0x8e3c8bc1, 0xafad4daf, - 0xe3c89b3f, 0xe739f893, 0x181af052, 0x4eee3c1f, 0xf532e3e0, 0x27771130, - 0x7f42f8e0, 0xc151efb8, 0xd8bcefb5, 0xe13df707, 0x72e02ee0, 0x29f3a8ae, - 0x3d6c97c0, 0xeef00092, 0x83ee7288, 0xfd47e9fa, 0x705d24a7, 0x1772155e, - 0xb6f6cbc6, 0xcf3f78cb, 0x5bc5813d, 0xc8c8f7b9, 0x4c3bba1a, 0x6ead37e8, - 0xc2f51d7f, 0x68ca46ae, 0xa6761ea9, 0xbfa90e91, 0x0340bd88, 0x47ce81ef, - 0x681f3d62, 0x75e22fd6, 0x7f7f3ae8, 0x3efc3809, 0xe42a1c1c, 0x9ee18351, - 0x919c5f57, 0x1551903e, 0x75da1f42, 0xb0f4e66c, 0x013cef56, 0x4cef1dfd, - 0x55fd0cdb, 0x53071dc8, 0x24eb3e00, 0xd1357fbc, 0x26cbeec4, 0x2574fbf3, - 0xdc3b06fe, 0xb34a4e37, 0xe1a9fde0, 0xe09d91df, 0xdd78fe17, 0x4f70316d, - 0x5c3ff44c, 0x4efde1d2, 0xe4fb9e42, 0x57f0428e, 0xa26fb02e, 0x162685b9, - 0xddf99197, 0xe5165f48, 0x891aaf23, 0x61a3f619, 0x6bde0368, 0x68cb4409, - 0xc9938cb7, 0x313ba024, 0x561f716f, 0xfafb877c, 0x7c52ef70, 0x2814d89f, - 0x0ed34b58, 0xdd620f4e, 0x0503cb13, 0xfc20960d, 0x16a65c45, 0x3c385b3e, - 0x66c6f1dc, 0xcdbb17d0, 0x52c9fce2, 0x9f23d362, 0xfb666759, 0xe255d8e6, - 0xc2b3edfc, 0xe11dd4b9, 0xf6063c18, 0x7932fbdf, 0xb17f2692, 0xe3470639, - 0xc7d415fa, 0xbb58d9d7, 0xbf071e6e, 0x44b2a3ee, 0x6f8e5f88, 0xa66f1f0a, - 0x5c73b124, 0x8beff72d, 0x1f7ab5ef, 0x42d58dc6, 0xf04176bc, 0x6bc695fb, - 0x01fc788b, 0x27ad10e1, 0xef78d1fa, 0x7ab179dc, 0x0e4bfcaf, 0x3ebebe7b, - 0x0fe22749, 0xcf4defd1, 0x0be3615b, 0xf9d8934b, 0xe807182a, 0x7dc37bc7, - 0x4a7b85f1, 0xce45c913, 0x0ef3eefb, 0x889fdc55, 0x9f9f7737, 0xfd7e7184, - 0x29fda5fa, 0xe15c6096, 0x92dff040, 0x86e5e6c8, 0xd082bf78, 0xdefb0aef, - 0x8f1c4e37, 0xc147f3df, 0xbb45fd3e, 0x7feaf78c, 0x75374871, 0xd779987b, - 0x5db83127, 0x7dc7af13, 0x1c47d233, 0x2f8cc2db, 0x35fb89ea, 0x76aa9ee2, - 0xfccbbb7e, 0x10fe608b, 0xbc6e1c47, 0xc48e9ca5, 0x30c777bc, 0x99f7b87c, - 0xed059ef0, 0x77bde317, 0xe257f8c7, 0xf1a9b0be, 0xd7b73b7c, 0x9fdebeec, - 0xa6bcf781, 0x40c33b31, 0x728de0f4, 0xd8f504fd, 0x4a65699b, 0x06fac53f, - 0xffb216c9, 0x410f452e, 0x7854ebb8, 0x23770fed, 0xfbf457e2, 0x4fbe61f9, - 0xe702c389, 0xbe5c25b7, 0x8351d92d, 0x1f38affa, 0x8cb0fe7d, 0x139f17f1, - 0xbcf927e6, 0xcff3c255, 0xeb211752, 0xf95a1f29, 0x88334164, 0x844925b9, - 0xbec3175c, 0x46e909df, 0xf97c9fb5, 0x87ecfdbd, 0xaeae5424, 0x57280d20, - 0xdd58fe56, 0xfbdc9aae, 0xb49fd067, 0xdce1fbfe, 0xb1d6272e, 0x479e8939, - 0x2629ef40, 0xd61f20c5, 0x3185f93e, 0x1f78194a, 0x777ca69c, 0xaff81e98, - 0x46aed319, 0x48bfa61b, 0x44963c72, 0xc927b7f1, 0x9ed20db5, 0xbdff59f7, - 0x7e4cbdb5, 0xb9438d6c, 0x2efd64d5, 0x087975f2, 0xc0f7ebe3, 0x1e14093b, - 0x97d31326, 0x720d7412, 0x5e2dea14, 0xf1e387a4, 0x6266aa6b, 0x74049ede, - 0x29cbf71f, 0xefce3153, 0x800e9197, 0x4752a6f7, 0x3625d81e, 0x997bb255, - 0xb3f31366, 0xf6317f7b, 0x0c837035, 0x0cbfbb6b, 0x8eb6c1ce, 0xf7b03efd, - 0x7cfee8b4, 0x5a57e210, 0x8bf163ae, 0xfeff3a09, 0xe2f190d4, 0xe049bd23, - 0x691f8f87, 0x388f38c4, 0x21af34b9, 0xcdca5e24, 0x9edbd171, 0x1ec27685, - 0xb61bb083, 0xa8bde045, 0x8183a1da, 0x18435c8f, 0x1bdc459e, 0xdf5421cc, - 0x8470a2ed, 0xbf914ba0, 0x19f24da6, 0x12fdf0a2, 0xded4e3f4, 0x0f984be5, - 0x7ae7ea72, 0xf98983f4, 0x5c9abdc5, 0x212efe06, 0x364be69f, 0xfae34766, - 0xfe223cfc, 0x5cd97f31, 0xb8f3274e, 0x923f3f1e, 0xb1297bc1, 0x5bbb4067, - 0x474a24cc, 0xf2fcd4b7, 0x675c22b6, 0xf41a218d, 0x19f7e105, 0x6f08cf58, - 0x653f72ff, 0xa58df765, 0x72743640, 0x62e7c286, 0xf9c030fb, 0xdd9b3bb2, - 0x88c323bb, 0xee8cfc03, 0x81b7c37d, 0x8834c27d, 0x7f29aff9, 0xa3e49732, - 0x73866d5e, 0x44afadd4, 0x2f22f8f0, 0xc8ec4fbf, 0xfa9cf883, 0x8c7cb4aa, - 0xc01a3913, 0x0dba3777, 0xc7dc0cfe, 0x5448ef94, 0xf2da0e36, 0xb87a19fd, - 0xf54299af, 0xd92f9a35, 0x0fcb2f72, 0xd1d4aff5, 0x4f2d92fc, 0xfdd3d0cd, - 0x7fc6bee1, 0x5b35f20a, 0xbe7cb176, 0xf34ca57f, 0x655e5bcd, 0x4960e1f5, - 0x2dc1ec09, 0x68786707, 0xb9a267ff, 0xf1fbb7bc, 0xe5fbb59e, 0x3b50bae1, - 0xe332636b, 0x9db8675b, 0x59264cf8, 0x1ef0055c, 0xb2febe11, 0x5a0f1d64, - 0xac54c569, 0x4927b457, 0xf325dbe1, 0xf7e56e71, 0x924627a3, 0xb7e60896, - 0x3c5144f3, 0x8e18e81c, 0x93afc77e, 0x6e9e9862, 0x38fbe3f3, 0x4f011fa2, - 0x77189fd1, 0xe067c835, 0xac789acb, 0x3f8664ec, 0x1c46ce3a, 0xdd839867, - 0xcb4aae2b, 0xbc51fc03, 0xf4de39e9, 0x8dbbfcec, 0x1bf68fcd, 0xa0728b9d, - 0x07f8ec00, 0x33f5a2be, 0xd2d6f383, 0x93324149, 0x3136b72f, 0x3a206b7f, - 0x6269e90b, 0xa5677f24, 0x668ebd50, 0xe4c6870e, 0x466f7e68, 0xc2512bc0, - 0x1c389a71, 0xcf78fcd3, 0x5dd74af2, 0x775a1ff1, 0xf01cbe08, 0xf681ca5e, - 0xf5b3b7ab, 0xcd7bf0c4, 0xd4188cfe, 0xf557eef7, 0xa6836677, 0xb8c1097d, - 0x164c7736, 0x8227bfb6, 0xd93bf198, 0x332ed7de, 0xa0ade997, 0x2c778acf, - 0x123ae788, 0x7bec47ea, 0xc58da2af, 0x39d70667, 0xd3af90a3, 0x6369d7c6, - 0xe8aaf4eb, 0x64091c95, 0xa7f6b6cc, 0xf7f83ee3, 0x9f2a37f5, 0xe7daa7f7, - 0x7d83fae1, 0xd65e103d, 0xd6f93a73, 0xa9e622f0, 0x9c1f6781, 0xf013f335, - 0xed8dfd84, 0x52e9a946, 0x5926b3cc, 0xfb35939c, 0x8e1bf33b, 0xd5daca57, - 0xb9e2cedd, 0xeba6a289, 0x3a99ddba, 0xed102b88, 0x1027c16a, 0x3dffb41f, - 0x89edcc9a, 0x806d2469, 0x93c7c4f8, 0x0ddac28b, 0x9cf6bbf1, 0xe2cd13d8, - 0x8af6b5d5, 0x277b789e, 0x9cf4afdc, 0x8c0aef63, 0xc06fd8d3, 0x259cf4cf, - 0x5f282ed8, 0x9c73f9d4, 0x3fb7f63f, 0x7e603205, 0xe7b2a685, 0x47d53b15, - 0x7e431cb6, 0xecb8385d, 0x7f9a4cb6, 0xc88ff935, 0xcb530bcf, 0xfca4c8be, - 0x9fb27f7c, 0x7d9647e5, 0x5bf21431, 0x44feacfc, 0xefc0f3c7, 0x633fc789, - 0xaf507252, 0x41592d78, 0x3ae5c9b8, 0x02647402, 0xc7ae8625, 0xe309aaf4, - 0x075c04f6, 0xba4d0b4a, 0x6ff77086, 0x07a3eedf, 0x812957e6, 0xf3b0153f, - 0x5f803b71, 0xf403b2af, 0xdf7bb144, 0x8eff7b3d, 0x483e5df7, 0x1e027576, - 0x16bb23ea, 0x5dfcd265, 0x1fa09f91, 0x3dd0724f, 0xc515f601, 0xf9d01646, - 0x9c9b5d4a, 0xd5913fa0, 0xe11eb376, 0x745eedca, 0xfc28178d, 0xf3f7d95e, - 0x61b2a5ef, 0xb18f309c, 0xefd40f9c, 0xe06ff2fb, 0x633fadf7, 0x7af983b1, - 0xdb96c76c, 0xdb1aff40, 0x4c97f6f1, 0x39fbb30e, 0xc163de62, 0x97bf49ae, - 0xfe709bb4, 0x5eae3b63, 0xfdc7f501, 0xe80b23b6, 0x5f31c264, 0x9e85b013, - 0xaaa52fbd, 0xcf90e5ee, 0x39d71a2e, 0xc04ddfa0, 0x54aa53e3, 0xf478460d, - 0x857c7832, 0xf1dd67f1, 0x68fd9b87, 0x7fdf54fc, 0xfa3afaa2, 0x20c97b91, - 0xc433f83b, 0xbdad7a7d, 0x5d2568f4, 0x213efd1f, 0xa2106740, 0x6f3c4f4f, - 0x98248ca6, 0xaad1252f, 0x5939b97c, 0x96c2bf55, 0x929f2aa9, 0x7caab574, - 0xcaa7929a, 0x56311f4f, 0x7b06ff55, 0x637f2aa9, 0xfd5534c9, 0x2aa5474a, - 0x536be79f, 0xd4382fd5, 0x423f2eae, 0xfe43c064, 0x90ebfb51, 0xa0749d16, - 0x74f8b5d9, 0x8e90ebc3, 0x87030bfd, 0xed7c5ed6, 0xe1d7b6f9, 0x6b17b0bb, - 0xfb0933ef, 0xc5b2cdf1, 0x276f0c6b, 0x0567d24e, 0x75901fdf, 0x18d33eec, - 0x94eaebab, 0xa67de0a2, 0xa62f6089, 0x7c58a848, 0x00e347ee, 0x3d980b4f, - 0x062028ed, 0x68adbee3, 0x686a3c87, 0x2c0fe678, 0xf81d200e, 0x5cc084de, - 0x9e27bad5, 0x5dd6a977, 0xe0d56e4a, 0x5f2a8d69, 0x555dbb61, 0x06d24a7f, - 0xe534f955, 0xdd3c1a07, 0x60dfcaaf, 0xd3c1a2df, 0x7e9e0d36, 0xf4172aae, - 0x5aedc1dd, 0x451ec0fb, 0xcefef1d3, 0x75c3c072, 0x8f8803a7, 0x72d6ce92, - 0x47b5d3c0, 0x855f10db, 0xb039673e, 0x0d43e2cb, 0xa3ea43af, 0xf76831e7, - 0xa612635a, 0xb4151a07, 0x1c6c1d6b, 0x46a1e981, 0x75ff7e3b, 0xefa60963, - 0x7d303a34, 0xa62a71af, 0x4c4e8d9d, 0xb0db1adb, 0xed8d73fe, 0xdb162ecc, - 0x3a45def7, 0x75ba07d8, 0x8278377e, 0x77923f17, 0xeecbf003, 0xc86efe41, - 0x37ec45df, 0x25f9a24c, 0xbee844c0, 0x374f29fc, 0x80023aa4, 0xca1c3757, - 0x18f1828a, 0x1e473a6d, 0xa477e1e8, 0x3ea1f84c, 0x37bb909d, 0xd16c9338, - 0x79a66f2c, 0xb3c63644, 0x83a1f84d, 0x2033d712, 0x33a9d04a, 0xf7c806e1, - 0x7772b044, 0x401b84ca, 0xfec6ff0f, 0xff3f4773, 0x61291df9, 0x9ccfe7fc, - 0xd760ac56, 0x70d5fc39, 0x30e3c02b, 0x48396fb7, 0x4d09619e, 0x0679f54b, - 0x0747b390, 0x80f0b7b8, 0xe009b4ae, 0xcfb3a6d0, 0xebef78c1, 0xb7e8040d, - 0x5fe7624a, 0xca95cf51, 0x0dcf41e4, 0x1d4f3c26, 0x605639d1, 0x7814995c, - 0x3dbce00c, 0xdee112a5, 0x00640d63, 0x4e29bcfc, 0x3c0f8f96, 0xf243d926, - 0x079f0606, 0xb6fc6e52, 0x3858f3e1, 0x62913cf8, 0xcfb6fa63, 0x807a0e91, - 0x74a91fc8, 0x3e7ec1d4, 0x0ab8ea52, 0x4d38cfef, 0xad3aff6c, 0x3ed0abde, - 0x139a28e4, 0x9219e762, 0xd1f7606a, 0xd82262e1, 0x71916f3b, 0x39e16b9f, - 0x7be99521, 0xce702748, 0xe789179c, 0xf63a2382, 0xfeb6819e, 0xb3d70e02, - 0xe3dbc283, 0xbd32a616, 0xdd566ca2, 0xfed02f33, 0x6045d67a, 0xe1ce3dd7, - 0x34f58fa8, 0x342ae850, 0x8e70dd3d, 0x1cec9b95, 0x9dbfe824, 0xf2d17f0f, - 0xfb6e3a67, 0xfd68efeb, 0xda45d64f, 0xaed88651, 0xc2ddf841, 0x358c2f2b, - 0xb0b4fea3, 0xe40cbd2a, 0x07ee7ce2, 0x27d5645c, 0x1f503ba0, 0x1727846d, - 0x9af25b97, 0xcac90429, 0x3c234ab8, 0xb69d5525, 0xd5d219a6, 0xc237eec3, - 0xa3b52913, 0x1a833576, 0x70b7475b, 0xff3ff211, 0x5e748dbb, 0x0acbd78b, - 0xfb89cf3b, 0x145735ae, 0xf7e822cf, 0xa23b8f08, 0xeaf3c040, 0xd16f0e22, - 0xd787116e, 0x3fae1489, 0x0b9c90e6, 0x67d63f6a, 0x0b5def40, 0xc01ecddf, - 0xe72ea0cf, 0x4607e3fa, 0xfdf6ae36, 0xe2ee3112, 0x3afe7654, 0x0994a462, - 0x4c2de4fa, 0xfdcee40e, 0xba22aee2, 0x9b0edcfe, 0x1615e30e, 0x7800bdd7, - 0x78e76de8, 0xd8769034, 0x4b3cb34f, 0x221df93e, 0x8f754e26, 0xd2f252f7, - 0x0f2b69de, 0x7e859795, 0xbca87967, 0x96b4092c, 0xf2145c83, 0x7d4ff851, - 0x2f9cd58d, 0x3d3f2037, 0xf31eb8d0, 0x983d1b07, 0xe16c6a1e, 0xcb15b97c, - 0x987c69df, 0xe72f65f3, 0x7bf13bcb, 0x4c5ce347, 0x58ba35f7, 0x9519ca3e, - 0xecc4fb0a, 0x37c4f8c2, 0xf80898b6, 0x4c3b7ae7, 0x77419f18, 0xc68f63c4, - 0x0991fc41, 0xe36a71ef, 0xbe7cb490, 0xf7761e8f, 0x0525377b, 0x1f8be9c6, - 0xc8717d02, 0x9874f4c0, 0x4be05628, 0xe4fe8ff9, 0x0fafd006, 0xf4158a2b, - 0xcdd482e9, 0xac50ef2c, 0x7c2f9a06, 0x8a5de794, 0x22ac04d5, 0x5be421f5, - 0x358a3d87, 0x1f8be682, 0x7b95887d, 0xc7f33a09, 0x06f5ba3d, 0x2259f00f, - 0x51fd801d, 0x449cce6e, 0xd79505c5, 0x5f6007a5, 0x325a494c, 0xcec5f609, - 0x63e90514, 0x00e1b29a, 0xd88fa7e4, 0xfaab87a6, 0x46de4b0e, 0x57165768, - 0x937687a9, 0x846cd6d2, 0xdd879376, 0x376d0faf, 0x8daed475, 0xdf619f90, - 0x74fd07a6, 0xf8b1f027, 0x2f223f60, 0x169f05ca, 0x3ba37271, 0x720f289c, - 0x0f289ddb, 0x66ca5c04, 0xf60dde57, 0xc976facf, 0x663cc126, 0x0a417d4b, - 0x86e89310, 0xbf2949f7, 0x97f53ebe, 0x5db40dd6, 0xc5afe43d, 0x7c370ffc, - 0xa6fbfcbb, 0xfbfc30d4, 0x41dfbe43, 0xfbdc43de, 0x0ef64687, 0x2e1c33cc, - 0xac4b1df5, 0x712a8ef8, 0x7acf4159, 0x97f3cb9e, 0x9fe5a520, 0x7f8bb4f1, - 0x70e7407f, 0x52ab38c1, 0x3fb21fb9, 0x6549a87f, 0x8f735ffb, 0xce728064, - 0x6d52ea1f, 0xea3cf7aa, 0x76bfbb08, 0x6d3b38a9, 0xee36b89c, 0x3b693564, - 0x1fecc8e8, 0xf70b526f, 0xc7fab2dc, 0x6a788b7f, 0xdf781c6d, 0xe3106ab9, - 0xd78173a7, 0x496eba50, 0xde4f901d, 0xdc38097b, 0xfd0e0e1b, 0x9c5843d6, - 0x2438bf7b, 0x5daeef1e, 0xb3c57117, 0xfc798d77, 0x827d76bb, 0xafaffa2e, - 0xcf5fc195, 0xbbf54fe0, 0x157e60c7, 0xec04ad8b, 0xe7fca156, 0x3fe11777, - 0x6df67e5a, 0x179bc9f1, 0x65bbe1d7, 0xf3d8f861, 0xb898f8e1, 0x854dafcf, - 0xf3f70a9e, 0xde121e20, 0x7e738239, 0x1f6ba265, 0x1653d3f4, 0xce0e9bf8, - 0xddec71a1, 0xaed183f0, 0x325df0fd, 0x1106b8b2, 0xe75a7c97, 0x6de815f9, - 0x19fa3def, 0x106eb3f2, 0xbc8f7416, 0x97a0f341, 0x7ce6c3fd, 0x4647e013, - 0xefa18df8, 0x7f140f8f, 0xff2e1bfb, 0xdf6ca7fa, 0x9ed43889, 0xa0665f6d, - 0xfb12eefd, 0x54782062, 0x70fde3c8, 0x24b7a43f, 0x9767e512, 0xdef07c44, - 0x02695771, 0xe95d2dea, 0xdfa43d46, 0x2bb8b9f6, 0xd7fb1b3d, 0x92bb8f9e, - 0xdc6ccc4b, 0x7d2153c9, 0x2154f92f, 0xf0dfbdc8, 0xa376cbf8, 0xb03de0a7, - 0x408d8f0f, 0x928dfeff, 0xa0e010bf, 0xbd77573d, 0xc94ca0b5, 0xa6be7fed, - 0xeb049beb, 0xbbae3dab, 0xe95dbe1b, 0xfd76bb79, 0xb9c408df, 0x15ff5b8f, - 0xaeeff781, 0x19ddfcfc, 0x5e80ab93, 0x12026ae1, 0xf545d319, 0x54bf9a09, - 0x8939d6fc, 0x4333d39e, 0x6f25e5ce, 0x9e2e38b3, 0xfde7cf6a, 0xed5c09de, - 0x960dc751, 0x5e308afa, 0xe147f645, 0x7b1d60bd, 0x73c4436f, 0xf3cfc9bd, - 0x243ebcf4, 0x9d70ed0d, 0xfaf3aa19, 0xfa2d1f1d, 0x0881f21e, 0xa678ef8c, - 0xcc3c44fd, 0xf19d8ff5, 0x0945793f, 0xedbd77d2, 0x9df4246f, 0xbdf5dac0, - 0x86d77caa, 0x7056fbe0, 0x5ff6ab1f, 0x2a25ca32, 0x4f105ac7, 0xdae335e4, - 0xda4af910, 0xef07dcfe, 0x55df94d1, 0xbe50c002, 0xd074cf36, 0x3cfc9576, - 0x8de44844, 0x92aeda0e, 0x67891f9f, 0xe78f2b25, 0xb09f3df5, 0xff28ba7c, - 0x7fac4ce3, 0x1c6fe895, 0x79164f2b, 0x22d5dfde, 0x9623789f, 0x25f68a67, - 0xc6239f2c, 0xaded64af, 0xade4feac, 0x7a099cff, 0x33f7e08d, 0xe09cb8d2, - 0xfe5152ef, 0xba2b4cef, 0xba8ebc68, 0xf107cb9c, 0x1dc5550e, 0x85df22d3, - 0x6126dc7d, 0x9ded61ec, 0x9fe7b406, 0x0dcb698d, 0xe22f2fbd, 0x56e59c7a, - 0x7baaf38c, 0x9976f871, 0x1e813bc7, 0xe9fb9cb3, 0xfa0b642b, 0x65ef7a61, - 0x3d207e7c, 0x97fae570, 0x57ecf855, 0x46d3dfce, 0xef1d2547, 0xf1130fdc, - 0xd619027e, 0xee02f189, 0x27c44934, 0x116abde0, 0x45971757, 0x8e7e701c, - 0xbd82297b, 0x13b27aa7, 0x97caeff9, 0x6ebb7d98, 0xef28ebcb, 0xda0aca96, - 0xea1ebe97, 0xe9f0075a, 0x2f77b2b6, 0x87dfae57, 0xc531f4fb, 0x8160fdc6, - 0xbcf0a151, 0x3dfc3fb3, 0x8517f169, 0x3ffcbabf, 0x5dad7f0c, 0x5fd7dc5d, - 0x7ff1857d, 0x07e656dd, 0xfd3c73b6, 0x7314a749, 0xf0023d78, 0x33a2b73a, - 0x20865a3b, 0x778c4eee, 0x29df90ab, 0x6f56f382, 0xde009583, 0xdccea5bb, - 0x5fe0c30f, 0x9f38ae7b, 0x69715441, 0xf7c3fb3b, 0xf7d04be9, 0xfa4dffd3, - 0x8dfbd44e, 0x1f1bf076, 0x15e5ef65, 0x18c9fe77, 0x4ef41f1a, 0x0f073b1a, - 0x317e676e, 0x2c171711, 0x713c32b7, 0xd55d53ff, 0xffc1e33b, 0xc4c3f624, - 0xfe06d248, 0x76d74a04, 0xa076d74e, 0x41bf416b, 0x176d143f, 0xfa41be06, - 0x912e2c25, 0xfdb7e9c3, 0x25e1fae1, 0x7fe1fae0, 0xa9bbae13, 0xdbfe8c3e, - 0x4ed02217, 0x3ff385a3, 0xbc055c38, 0x0e2fd323, 0xfff4c8e7, 0xd3239c0c, - 0x439d9515, 0xf9207bc0, 0x988fc5a4, 0x5a7d9877, 0xe9f64df4, 0x4f9c1923, - 0x8f18fde9, 0x4c7bc5ab, 0x27bc3f7a, 0xef1c5fa4, 0x30fff2ea, 0xd370b5de, - 0x9fdcb5a6, 0x985efdab, 0xfbbf203e, 0x7ff8e056, 0xb0b04fcd, 0x7caabf61, - 0x54b7faf1, 0xef3c4be5, 0x415f965f, 0x5bfffbd8, 0x57e105fe, 0x2afcf998, - 0xb51ff81d, 0xc43741f2, 0xc7a023f9, 0x7afe5f1b, 0xf93087d4, 0xb78c6cea, - 0xe5af8dba, 0xff7ff18b, 0xbe947be4, 0xf66068be, 0x3ffb63d6, 0xfd392837, - 0x79e165e9, 0xd084711d, 0xeff5c2d9, 0x5acf401b, 0x54fbd848, 0xa60ffada, - 0xc6307b33, 0x30be5149, 0x710c4cd7, 0x9dcc1f94, 0xcf4beecb, 0x0c630705, - 0x2d173ea6, 0x3e27a99f, 0xd2bb8f78, 0xd099f7a2, 0xffbea9ef, 0x75efe26e, - 0xd558b893, 0x21d9783d, 0x9cdf9c63, 0xbd2fe612, 0xf786d2c5, 0xba1de787, - 0x60f7dceb, 0x14f46f2f, 0x7177b8b1, 0xbaf7f0ff, 0x3e83f12b, 0x9c2a7a08, - 0x5fee24fb, 0xff40635f, 0x2addb6ba, 0xca669fbe, 0xd9a38b12, 0xc533e2c3, - 0x3beba4fe, 0xf767ca64, 0x48f7e060, 0xbe0c1b2a, 0x67a0b9e1, 0xbb3d47ef, - 0x2e4364be, 0x927eafe0, 0x1b94dc74, 0xafd4ef3c, 0xd7b60bff, 0x7a6d67f2, - 0x4fd5f6b9, 0xbd210f1a, 0xb1d17388, 0xb5e61f46, 0x1305d6f6, 0x93fd17ff, - 0x6de2ff63, 0x57dc7482, 0xd0c70f8e, 0x3b1bfb75, 0x827b2dff, 0xbb0823b0, - 0x214ed682, 0xbf7888f8, 0xe36e97d2, 0xa296b2ef, 0x59e883df, 0xc1edf82a, - 0xd7f9fcfe, 0x27d717e9, 0x61ffe5d5, 0xf4b97cfe, 0xe4c49b5f, 0x8fee96aa, - 0xed0cfd56, 0xb5be82cf, 0x6200bff4, 0x0bf8e852, 0x27bc25ea, 0xab55773e, - 0xcdf49c61, 0xe5b57de9, 0x9b830664, 0xb15c2e46, 0x3c78503c, 0x0be78c87, - 0x0ec6bc93, 0x87810f76, 0xefd5d3af, 0x48bc5303, 0xab971719, 0xfafff2ea, - 0xa2e4e039, 0x8917266f, 0xcb489f4a, 0xe56eb7e8, 0xfe56eb12, 0xb90eeb9b, - 0xd648b4a7, 0x40e3ef05, 0x81c435fc, 0xfdd978f6, 0x56ccead4, 0x5203ddfc, - 0x7e028812, 0x995eeb77, 0xde8e9efd, 0x790e4fa1, 0xf88bad3f, 0x5c7a003e, - 0x3bbd9e35, 0x769b8da4, 0xd5ea78f3, 0xbf78dd96, 0x9a0efb51, 0xf376cb88, - 0xa1efb4fe, 0x9de2f689, 0x687bed03, 0x1c783253, 0x67c93e76, 0xe7172971, - 0xcf20dda3, 0xdd35fc43, 0x5da2355f, 0x4ac7c6e1, 0x05a4f3ee, 0xa32732f1, - 0x9799df1f, 0xa3be7171, 0xd32fff2e, 0x81dd6caf, 0x94aed8f7, 0x3a64477e, - 0x827f40dc, 0x9bf1f72f, 0x6fc84c57, 0x3df33bc4, 0xf7c19e6b, 0x24be7a87, - 0xd4bd97e8, 0xbb13e33b, 0x09c435d8, 0x564dbd27, 0xc771d78a, 0x1baf683c, - 0xf785c47b, 0xe3bcc776, 0x927f8880, 0xc329c077, 0x233e85bc, 0xff209bf4, - 0x78d9f7e2, 0xf2e5d59c, 0x37f52bb9, 0x8cfca7fe, 0xb75d5ee2, 0xbf0457c1, - 0x13d9e0e7, 0xa103bf81, 0x1993ff9d, 0x93be8bba, 0x7ae511dc, 0x8b34f012, - 0x5ef109cb, 0xdecc8572, 0x94edef49, 0xeeb85ed1, 0xabfb7e7f, 0xdb4b9547, - 0xbd6dea15, 0x2265cf61, 0x7bb1d7ad, 0x0ae5f92d, 0x79c249c6, 0xc287ec0d, - 0x7fada89e, 0x297b294a, 0xe35bed03, 0xdeda3df1, 0x067cd987, 0xfafd57c2, - 0x603f8e00, 0x7ebf1f39, 0xf42d916f, 0x19f3959d, 0xdb43e77d, 0xdf107329, - 0xff174b97, 0x332dced7, 0xa891e265, 0xbc91cd7c, 0x4c25ef4c, 0x3a405dff, - 0x02445d31, 0xbb08ba98, 0xd894b0cf, 0x9c4e5d31, 0x5c55ae98, 0x3718195d, - 0xf8c04814, 0x39ff17d3, 0xdce6e80a, 0x215ae375, 0xf2dbf146, 0xbef56923, - 0xbd853c9e, 0x3fc2f497, 0xd9f4077f, 0xcb863ff3, 0xa2471be2, 0x1848641c, - 0xa57bd33f, 0x54d7bb32, 0x17dc5df2, 0x325dfde2, 0x96e1f989, 0xfee26627, - 0xc4cdf209, 0x826f826d, 0xb8e7393f, 0xdcc3c58e, 0xc67be12a, 0x6e1d7eed, - 0x99159cb1, 0xb9ddf85e, 0x3cacddf6, 0x2bda2ea7, 0xd8ce7cd1, 0x26be5608, - 0x4ff70bda, 0xee3f1216, 0xfb70c5cb, 0x4bfb8644, 0xdf8a2f8c, 0x8227a00b, - 0xbf6d12a1, 0xeeccc3a2, 0x30ff1051, 0x70b9ffe0, 0x4f170a7e, 0xf1f18433, - 0xbf1943d1, 0xb6a65d1f, 0xe5e50c87, 0xdf6529f7, 0x0cb47807, 0x810d6471, - 0x9b9d31fa, 0x3b042c1e, 0x9f808e90, 0xb7b1b3e6, 0xb4535fa3, 0x1b29517b, - 0x959ff501, 0x67bfbc58, 0x4c6fbf2f, 0xfea10902, 0x794ab5b1, 0x1a2bd42e, - 0x40d3f8c2, 0x51df8570, 0x2f398674, 0xd1d1f88a, 0xbb436670, 0xd277c13c, - 0x7e58959e, 0x6f5be3f2, 0x5f4168dc, 0xe3f40782, 0x44d71517, 0x91b46f18, - 0xffcc0b10, 0x1b7efca7, 0xbb00c869, 0x4cc7aae8, 0x3e2fd03a, 0xee18e2a2, - 0x9e81fcf7, 0x98fd21b7, 0xfd219b9e, 0x43373d23, 0x9b9e9c7a, 0xcf413d21, - 0x38ae90cd, 0xccc7876f, 0x8e2189c9, 0xf0bfd0b9, 0x5be769f7, 0xd7f18439, - 0x1af7f1be, 0x14fbfc71, 0x0fb7c217, 0xfe087bdf, 0xd1b3edde, 0x8b989481, - 0xdecf5bd0, 0x749fa3bf, 0xff08b820, 0x0a7cb6a3, 0x6eee6bc7, 0xdcffca3d, - 0xcad47f76, 0x872b7a90, 0xce7db118, 0xa0a3270b, 0x1f5b6eff, 0x5d121d7c, - 0xcb1d4cf2, 0xb9fc7caf, 0x828e371b, 0x0fbe3bf9, 0xf9f74174, 0xdb73486a, - 0xfc00fb7f, 0x1fed2a5e, 0xa47a24e3, 0x2f3c66c0, 0x85a1d668, 0xb3d75883, - 0xa09b9dd1, 0x0c2fb3fd, 0xbe509585, 0x01bed843, 0xadc2923a, 0xe7ae0377, - 0x10a05346, 0x78dd0bee, 0xa71b0e41, 0x8a529f7d, 0x7a064e70, 0xcaddfe43, - 0x025f4653, 0x7f74df6f, 0xe223fb6b, 0xa5e015fd, 0xafa5c80a, 0xac2f40a2, - 0xed04f1e4, 0x06fd87bb, 0x2439e9d6, 0xdabdf813, 0xfdea31d1, 0x49e38bb7, - 0x8d7b39a4, 0xb3d7c04e, 0x830d4f7b, 0x7e2989f7, 0xc57bc186, 0x455c86db, - 0x31ef7f42, 0x8f97ec67, 0xf587183c, 0xe769f7f1, 0x10156d91, 0xbcdf3337, - 0xd2580dff, 0x0af1db42, 0x9c599b88, 0x74841d24, 0x19399289, 0x7dc465e2, - 0x4a236583, 0x9a96c20f, 0x7d44af61, 0x4c9814ae, 0x37287c88, 0xd847f247, - 0x558a3c85, 0xa524a7e5, 0x534feaaa, 0xd3e554b2, 0x95548c47, 0xd867718b, - 0x46f5540b, 0xc28604c7, 0x83ae8e79, 0xa4ff03bd, 0x3986f18c, 0x7eb91c2f, - 0x7ccfcd24, 0x43be0e6a, 0x9f2f2cf9, 0x17b95cf9, 0xe143d1f0, 0xd50aa469, - 0x6c1f92e9, 0xd33a107e, 0xf76a179c, 0xa1d0713e, 0xe179c65c, 0x8184e712, - 0xed164fde, 0xca04e7b5, 0xbe001f37, 0xd9c5fa39, 0x3edbf036, 0x14cbf63b, - 0xcdfd4788, 0x0caefe10, 0x440c3f3f, 0x43fb7d37, 0xbcdd1852, 0xc3279325, - 0xf2440dd0, 0xe9643a32, 0x7eecc3cc, 0xb5f295de, 0xa1af814f, 0x4243c0bd, - 0x6b577f7f, 0xb46d1bdf, 0xb036e6ff, 0xc32bbd47, 0x7bbea50d, 0x6fe12b93, - 0x64ef4839, 0x93bbb6f9, 0x07bbf0e3, 0xb73761f4, 0xb8520df7, 0xffbb553e, - 0x60c2e4ee, 0x5c775939, 0x29dc9f55, 0x1bf2ab35, 0x7bf9d533, 0xdb439b4b, - 0xad8fa40f, 0xd189787c, 0x6ef70395, 0x37bfb0a5, 0xfff3e62c, 0xd5800901, - 0x00800020, 0x00000000, 0x00088b1f, 0x00000000, 0x19b5ff00, 0x6554540b, - 0xcef7bbfa, 0x7860190b, 0x77421028, 0x840a4498, 0xb0285789, 0xd71ea08d, - 0x8f4c1ada, 0xe5935654, 0xe04d7903, 0xe3d8f4b6, 0xb68fad18, 0x695b6d07, - 0x9656356b, 0xb139e4e7, 0x36254644, 0xeb495bae, 0x66a254d6, 0x42d899e4, - 0x7a26704c, 0xf75a9d6d, 0x5efffefb, 0x5b602e67, 0xe74ed69d, 0xffffef9f, - 0x27ef7ffb, 0x70ca1490, 0xf60800ce, 0x9970ccac, 0xd6f70601, 0x8018e41a, - 0xe2eff4d3, 0xf9b8daf0, 0xcf03837a, 0x3a380057, 0x01cfe3cc, 0x031401d6, - 0x7b81295c, 0x5914f3a2, 0xff60e760, 0x2fbdf165, 0x00490801, 0xde8d179e, - 0xe38456ed, 0x6e67065c, 0xf08d9ef8, 0xd918064e, 0xbfefff72, 0x25f5c22a, - 0x8c0ee3b0, 0xbd0d43c4, 0x5c75d79b, 0x9fcd7114, 0x77d1d704, 0x98809679, - 0x55706b80, 0x00e207b4, 0x3c636a9a, 0x679e3e62, 0x2e990e86, 0xa6f1c804, - 0x01529bb5, 0xc0228a8e, 0x78074439, 0xe3ef14a0, 0x245f041b, 0xa4ef39a7, - 0x67c8b9df, 0xe7c72fcc, 0x35b03245, 0xe99432bf, 0x7ed77bc6, 0xbf1ce787, - 0xce91a203, 0x8f4a803f, 0x2e5c4c03, 0x19bdbb04, 0x3f233ffe, 0x1812bd4d, - 0xf0619f90, 0x605aba1d, 0x25a9ccd7, 0xa7e92b00, 0x061dfb4c, 0x196fd890, - 0xb2957f70, 0xe57cb2bf, 0xf08b10a5, 0x2040fd56, 0xa70fbd9b, 0x7fd5fff1, - 0xf198376f, 0xda53f57c, 0x530f427d, 0xfbe52f90, 0x77b3f03a, 0x3de277eb, - 0x235ef853, 0x8499fddc, 0x697636ef, 0xc7245fbf, 0xe0e60d24, 0x3828028f, - 0x916db12d, 0xf1366bde, 0xdf4ae6f7, 0xea097bbd, 0xc925e9b1, 0xd1adc46e, - 0x00e2d3dd, 0xa83983f9, 0xf2f1d4e4, 0x7a8cda6b, 0xa7c30c2a, 0xbdf34b76, - 0xca175f74, 0x5e319ea8, 0xe2c960ce, 0x5f1c2cf8, 0x0bd7c573, 0xf735f101, - 0x7ed0d0e8, 0x1146cf00, 0xcf3c08e4, 0xf2ae31ed, 0x07f4c39a, 0xfcc79c2d, - 0x66132f9e, 0x1d75f2e7, 0x1ced01d1, 0x98bf702f, 0x093e8021, 0x60b541f1, - 0x5f4b8edf, 0xc925724f, 0x9f004fbf, 0x589ec05c, 0x5cfd4264, 0x7da39fc1, - 0x8fe02433, 0xe11d6c94, 0xfdc8a859, 0x7c7fd28a, 0x8b77e023, 0x434f167b, - 0xd750e00a, 0x0cd43eb2, 0x0c6d906c, 0xe8f012df, 0xf17d2f49, 0xa416f4ce, - 0x604932f3, 0x1f17dff6, 0x7f10161a, 0xd0b4455f, 0xeff7b026, 0xbe55f7a4, - 0x74cef4fa, 0x8e6be337, 0x26f51065, 0x4e902e38, 0x47978f47, 0x183aae58, - 0x712bf554, 0x9c7f2177, 0xfb3edd2b, 0xd1dbf412, 0x223160a5, 0x684b97bd, - 0xabc30838, 0x49ab8fdc, 0xae5133d6, 0xe8813f82, 0x6e17966c, 0xe4bbf191, - 0x97417bd6, 0x1d372118, 0x2f5533f7, 0xd3c71caa, 0xf72de2a1, 0xd1bf903b, - 0x9fb3021d, 0xecccbb46, 0xe4fcb1b3, 0x7f104b83, 0x0bb25fa3, 0xeeb2cf48, - 0x7e4847bd, 0x403b6b1d, 0xe7401e77, 0x2eb66eda, 0x527d9933, 0xd98be31e, - 0x414688ad, 0x6056ad7c, 0x7c35a7c6, 0x0c7be61e, 0x7c3f51bc, 0x3804ce06, - 0x9e7ceb18, 0xfbf35bf8, 0x1096fbcf, 0xe3ca1bb5, 0xad901f99, 0x3fa61b9d, - 0x466000df, 0xa3db43fa, 0x3c304fbd, 0x6125af68, 0x27b13d7b, 0x9e0b70eb, - 0xcf53789f, 0xc55f75cc, 0x416ea7c3, 0x68f6cd78, 0x0913e726, 0xf3a549e0, - 0x3d7ba627, 0x18a56178, 0xb9216fea, 0xb7d8c677, 0x47f1f9e3, 0x13bb3fa7, - 0xa767dae1, 0xf24c89d9, 0x7de5191f, 0xda011d3c, 0x7d953e7f, 0xef1c2907, - 0xa52fc50a, 0x57dc6667, 0x24cfe74e, 0xaa8f09da, 0xa347a1bf, 0xfaf2801c, - 0x16797c12, 0x8293bd34, 0x87c45067, 0xc79dc4eb, 0xdbcbb404, 0xc483ae0c, - 0xfe47eaf7, 0xf90ca87a, 0x37e67aa9, 0xfa44cf0f, 0x0c9bdf6a, 0xaf584ef4, - 0x6c40e2e3, 0xdffc9720, 0x915ffdc6, 0x288edd4f, 0x7111c7cb, 0x5e23a1a6, - 0xa7753703, 0x888e3e5a, 0x65c07537, 0x8e82f50c, 0xfc57a9f8, 0x1d745eaa, - 0x201aba25, 0x8422e3c0, 0x0557640c, 0x78a0e092, 0xc8c7ba10, 0xced63fe4, - 0xd1916546, 0x8b822f51, 0x224179e2, 0x6fc85298, 0xc17e5c5d, 0x713fa67b, - 0x9266ca17, 0xfbf54135, 0x223385ac, 0xf1bfb3ed, 0xcdcfb215, 0xc39f6646, - 0x8d2f3c51, 0x391ff3c5, 0xc2bf7d9e, 0x87f305f4, 0xf5a4f933, 0x17385adf, - 0x0aef141c, 0x9bc2e4da, 0xf4516d70, 0x29c52c72, 0x1dee4958, 0xc03aeff7, - 0xe6f5b9e4, 0xbf7784a3, 0x0e0fe999, 0x0507b970, 0xf7d5279e, 0xa0429856, - 0xb77a242b, 0xfdd57a31, 0xf3872dc1, 0xe0fef85c, 0x8079390b, 0xf24cbcf6, - 0xe505fe0f, 0x7fc62a73, 0x3b5c36ec, 0x853bbff7, 0x7a58e0f2, 0xd9475beb, - 0x2c3c2a7b, 0x4f5438f0, 0xf7fee07c, 0xa264ce99, 0x8b08c313, 0xcd77030f, - 0x2b9bf260, 0xfe91c6e5, 0xf4b42783, 0x7d53a58d, 0x7d4fa55f, 0xcd37bd5f, - 0x8e39322a, 0x9479fc18, 0x90cc5ff7, 0xc48d7c35, 0xcde2f3fa, 0x75e16fb4, - 0x11c20244, 0x3f4356f6, 0x2635bf51, 0x5f48db8c, 0x6f608d4d, 0xa1efb603, - 0xcfab89b8, 0x29f5e785, 0x03722b2f, 0x78ed09a7, 0x906762b1, 0x6eecc894, - 0x5ebb7011, 0xabedc4ac, 0xe80f43a0, 0x75c4472f, 0xfda035bf, 0xa03c770d, - 0x5dc64577, 0x74f151cf, 0xbb8f4fce, 0xa6c84a9e, 0x31623df8, 0x9e66bab3, - 0x7bb1d055, 0xf74e90e9, 0x43eedcf0, 0x1a74f03b, 0xcf486ded, 0x8173a2e3, - 0x6f53e515, 0x1f91e5f0, 0x2e3ddfa8, 0xb0fed8ba, 0xe9056070, 0x3cbe741b, - 0x1bc4ef56, 0x233ac040, 0x77eed938, 0x25f65d50, 0xd412b8b0, 0xe2274d43, - 0xdd12aa2d, 0x3c70e69d, 0x5167e354, 0x5ca3ee0e, 0xf55f682b, 0xa29bb457, - 0x30fded7c, 0xb8f85a3f, 0x515dfb95, 0x98eee8a2, 0x576e5fc0, 0x1d06dcf4, - 0x9e67f712, 0xb914cb47, 0x4522dd63, 0x4a8d2dd6, 0x9ac60f9c, 0x53f2123c, - 0x82f51bb6, 0xb7ce9970, 0x028c5697, 0x9dfa8ad0, 0x5efe3e05, 0x539e36b7, - 0xf2ca590e, 0xcbcb0e72, 0xaf7514b3, 0x7a40dc17, 0xc2fe5135, 0x2fc12ef5, - 0x082bfad1, 0x1601d5b1, 0x06a8ad1d, 0x2701ceb6, 0x9b81e75b, 0x9da1f3ad, - 0x83a00bad, 0x9f8297ad, 0xaf8170ad, 0xb83e580d, 0xf98832dd, 0x52bd7e18, - 0xb45cbca4, 0xfc7ae264, 0x675e4571, 0xf9460797, 0x8f2f9f92, 0x614ae079, - 0x2e4d9d74, 0xdd99b353, 0x923172ab, 0x5177e27d, 0xb5a14de0, 0x9dec0202, - 0xf190c98b, 0xeb20d99d, 0x0702ae08, 0x48fee783, 0x5c069479, 0x04ee573a, - 0xd89aa972, 0x7628764e, 0x5d364c52, 0x87d7d61c, 0x54171e56, 0x49d201bd, - 0x3ebc60f9, 0x2ce88321, 0x5cfcae8a, 0xdaf190c6, 0x3a9df7b6, 0x8545a38c, - 0x84362d95, 0xe53f590f, 0xf3e55970, 0xd91f0899, 0x9ba9d276, 0x595e7649, - 0x1563b7a8, 0x39d86eba, 0x184dcf07, 0x4e50a3fc, 0x52824d92, 0xb1515d5c, - 0x677e8079, 0x74ebac94, 0xdbc657e8, 0x5719c580, 0xd59f8014, 0xe46568b3, - 0x7ebc3527, 0x7ae1635d, 0xbd706bdb, 0x60da7e4a, 0xc8cac5f2, 0x73759ad3, - 0x6e5f2993, 0x3ff7f030, 0xbce72c9a, 0x22327282, 0x9841533e, 0x44f73c4f, - 0xe4101c21, 0x186b5696, 0xf7c08fff, 0x77c21fcf, 0x5deb8a6b, 0x594dcf16, - 0x534ffa40, 0x676779f2, 0x245d8a59, 0x3f8616fc, 0xd2d59310, 0x5207478a, - 0x7bd21f9c, 0x776e18c1, 0x5eb95a1f, 0x329ab6ce, 0x27581f1d, 0xfbae0fd8, - 0xe28f977a, 0x084827d0, 0xd599f3be, 0x34744035, 0x428c8189, 0xd11dd7d4, - 0x27640cc7, 0xa80b1daa, 0x7fc8a5bc, 0x06bc039b, 0x96e51fe6, 0x2d98f533, - 0xe5c107ec, 0xa5ca1ef8, 0xd2ace9c8, 0x8d4971e3, 0xa5ad1f7b, 0x3c2af6ae, - 0xa2413c21, 0xad0a49a7, 0x1538bb20, 0x13e19eff, 0xb953a7e6, 0xabf12a3d, - 0x6def4f67, 0x42741c69, 0xed361f84, 0x0fabe6f9, 0xa34ddf50, 0x0f5d3b66, - 0x1696dffb, 0x1ab00bea, 0xd517c4d4, 0x1b75672f, 0x955fd47d, 0x397f3eed, - 0xaf78abdd, 0xfa7146df, 0x1b40fee2, 0x9ec1cb95, 0x2fdc69c3, 0x6bfe3ad4, - 0x93e4e7e1, 0x750512b9, 0x905ecbac, 0xabe446bc, 0x050bea99, 0xdc7c20f6, - 0x47137684, 0xa9bf79f7, 0xbd0d95f6, 0x2fa819af, 0xc43c67c1, 0xff42ad6f, - 0x5c37adaa, 0xad62f54a, 0xd62fdb57, 0x13d77bf5, 0xb43b75dd, 0xd9bf6afb, - 0x4f5f7ca4, 0xea8d9af5, 0x26bded3e, 0xa8f337ea, 0x67eed3fe, 0xa6fd2a66, - 0xa940ff92, 0x772a5733, 0xeb333f88, 0x235e0cff, 0x68fcd6f2, 0x7042dd8b, - 0xe2ced9ba, 0x6606fd6d, 0xd87deac7, 0x446cc89a, 0x8ddadbf5, 0x5567eac0, - 0x1b4ff98e, 0xfc8fa41d, 0x5d5993a7, 0xab3cf58c, 0xf09e3047, 0x22651efe, - 0x173ddda0, 0x1114ca1f, 0xd93d73cf, 0x5fb7aa76, 0x7f80eb5e, 0x4fa6179d, - 0x4ae7f7ad, 0xd40cab3b, 0x7d88dd47, 0xf7356e14, 0x4266d93e, 0xd01379b8, - 0x3b2d240d, 0xe2a6ea8e, 0xe97812fd, 0x503ef01d, 0x1a976b8e, 0xbeb0524f, - 0x9447908f, 0x09e4093c, 0xa2a379fa, 0x04ece8b7, 0xfd8c79cd, 0x71f7cd1c, - 0xefda99a5, 0x6e7f0e3d, 0xfe73c509, 0x02e3bc7d, 0xc136fdcd, 0xcd91f76d, - 0xbc3ff004, 0xb188ae57, 0xcd82bfc2, 0x17e7121d, 0x886fee68, 0xec9fb79d, - 0xdd0bfcbb, 0x4b703b18, 0x01657764, 0x2f504780, 0xe7b586b3, 0x21db07c5, - 0x1d47f116, 0x57998dd4, 0x16ea8078, 0x5fddaca3, 0x54c5daae, 0x4399aa98, - 0xb73b919c, 0x9121d1fb, 0x9c0945d9, 0x117970f7, 0x5e0f59c9, 0x46dcbc79, - 0x66fba569, 0x598bf303, 0x8a762dbd, 0x5a9d9347, 0x68d727f9, 0xd2ea9fe5, - 0x956d3bca, 0x6ee9de56, 0x6dcfbcad, 0xead7cad5, 0xb6cfcad1, 0xfee69671, - 0x0d4af6b4, 0x02f37d3c, 0xbdf3fdcd, 0xce70350b, 0xf734ab8e, 0xd32c7467, - 0xaf77e79c, 0x76ab9cd6, 0x2e0ed636, 0xb18f35f4, 0x08c41133, 0x567aabfd, - 0xff70a0ed, 0xff3c1aad, 0x1f6ffd6f, 0xc8a7ffa3, 0xbdde31d7, 0x37743b15, - 0xd165ebb9, 0x999dae3c, 0x59eb9427, 0x9cb6f6bf, 0x77431558, 0x54e6fc95, - 0xff941bf2, 0x0e16c391, 0x7df6fddb, 0x8e0acf14, 0xae88ab38, 0x1f7b80a2, - 0xa192f385, 0xba38aaf6, 0x32d900ef, 0xe89c8f85, 0x02a5e5fe, 0x857e34e8, - 0x3cb094f0, 0x93acf0af, 0xd972f0e2, 0x1636de77, 0x4be9c96e, 0xa120f3c2, - 0x6a85e794, 0x22e81447, 0xeca152e4, 0x29e92503, 0xf3abf961, 0xc007ec23, - 0x6880fd40, 0x2759b6f2, 0x9bec77aa, 0xb98f5625, 0x86f67d58, 0xa57362e0, - 0x067f2645, 0x25dff7c5, 0xc4cedebb, 0xb44a76b8, 0x139eaccb, 0x54c46d02, - 0xa4a31890, 0x76afa9e5, 0xed871f50, 0xff2bcd2c, 0xb56d4774, 0x6f919727, - 0xb6f09409, 0x67f5fe99, 0xa2648eba, 0xcb0407fc, 0xf6fc42fa, 0x332759ad, - 0x25197f28, 0xcd014494, 0xe9471c4f, 0x24dcccfc, 0x78c3f919, 0x0f65101b, - 0xab73c289, 0x9390fac0, 0x08ccd8f4, 0x67a8ddff, 0xbe940b79, 0x5e451aec, - 0x54b65f6a, 0x4f803fc1, 0x7e78c2ac, 0x4c1bf74d, 0xc329752e, 0x6dca1cca, - 0x37fbe0b7, 0x5017354c, 0x428e0a5f, 0xd5e7ef3b, 0xfa4d2d3e, 0xed557929, - 0xbf76cf6b, 0xd348652e, 0xc4cec32f, 0x6391e709, 0xbe615ee7, 0x9b03fbf9, - 0x1a1e59a2, 0xe6ce94d8, 0x4ff7e18b, 0x71aff7b1, 0x93b1a3bf, 0xd7df5aeb, - 0x9ef5dfd8, 0x81e7348f, 0x0d3e90a4, 0x4aec0ff9, 0xca35779d, 0x6305e46f, - 0xa8abf509, 0x715b38b7, 0x3dc0fdf8, 0xbe10e7d3, 0xa7e7cdff, 0x6bfdbe4c, - 0xa6ee6cfd, 0xed6c79f2, 0xd6070611, 0x963ad806, 0x55bfb54f, 0x20dfc357, - 0x90e5ea9b, 0xd13ec930, 0x1b31e6bc, 0x67fa83ef, 0x7ca4a94f, 0xd06e9fdc, - 0xc38b35f1, 0x0e26a5a9, 0x6b4f9bcf, 0x48de6f50, 0x00bf6dfd, 0x61ed010e, - 0xec7ce0a9, 0x3abbe47a, 0xa36b95d9, 0x2875727a, 0xd0fe874f, 0x56b81f94, - 0x1ebe7d40, 0xfe27caef, 0x53062c05, 0x599d1813, 0x890c37d4, 0x63013c9e, - 0x764f4dc1, 0x3ffd5357, 0x8a73c934, 0xadad7632, 0x83fa9aab, 0x8ff70321, - 0x847c9e5b, 0x16b7c3f9, 0xe77a4cd7, 0x31f24113, 0xf0497e7b, 0x16f6676e, - 0xf88c2c30, 0xaf3a82bb, 0xfa9b7ea1, 0x5f14609b, 0xdff8db67, 0xacc72a5f, - 0xae3c6d4b, 0x316b42dd, 0x2ceee5e9, 0xe8ca7bfa, 0x5f902366, 0x48873e20, - 0x5cf87af8, 0x40f20a76, 0x6f560d75, 0x78285fac, 0xf8a3e8d5, 0x1675cea1, - 0xbdecacdb, 0xd79f1b24, 0xf467dd24, 0xeefcb1b6, 0x3a46a8cf, 0xef58f5db, - 0x1070df50, 0x846d1cd8, 0x7a1161e6, 0xfde36c59, 0xc008dc17, 0xd1b793cf, - 0xc0ef4379, 0xdf278a31, 0x24aeba67, 0x72880c39, 0x8693c509, 0xdeacbdd8, - 0xecc9b66b, 0xf197a43b, 0x4ee1718f, 0x382fcfd2, 0xfa455c0f, 0x7805306d, - 0x03ccaadd, 0x91b726cf, 0x7287fee5, 0x9ecbfcd9, 0xf4a9f441, 0xb6cdfd22, - 0x4a9db988, 0x1f9df87f, 0xae750bf6, 0x5b83c2a5, 0x9f916436, 0xbcf85ea1, - 0x5bae1251, 0x0ff7c138, 0x963efa2a, 0xfe10f4e2, 0xf73e6ed5, 0xfb4ddb0b, - 0xcf4947cd, 0x271666bd, 0x58fdf6cf, 0xf4f61b3e, 0x9f207932, 0x117f12d7, - 0xc91bde7c, 0xe1cf48e7, 0x9fe57287, 0x9d305fcf, 0xb8291dff, 0x190c9bed, - 0xfdd86fbf, 0xbbb211c6, 0xdf1e7506, 0x18339da5, 0x9aff6127, 0x1d1cd130, - 0x5d444fb3, 0x9fbf5466, 0x8f7ed3aa, 0xa9cd3905, 0xa9dfc9bb, 0xbff0717e, - 0xb8f9a98b, 0x846be94b, 0x1f2cebc0, 0x87f23e10, 0xe58782f5, 0xd18e7545, - 0x23de6026, 0x585abadd, 0x35ce909e, 0xbb9ec9db, 0xe4fd06d0, 0x34473a07, - 0xe98f5f9b, 0xb835bfa3, 0xd6fc9176, 0x4c9953bc, 0x9be7767d, 0x8d7e940b, - 0xc562a9e7, 0x3f098b2e, 0xc71b9fd1, 0xa148b5ec, 0xf584c4af, 0x7c852650, - 0x15e7c48f, 0xd363fcca, 0xef3e9aeb, 0x685932bf, 0x001e0053, 0x00000000 -}; - -static const u32 usem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x1915c58a, 0x19d44418, - 0x18344c18, 0x20685618, 0xb58969c4, 0x9fd329b8, 0x90c0c2c9, 0x40b9c40d, - 0x7cc40f9c, 0xfc0c0c4c, 0x17ebc44c, 0xf5b04514, 0x84181904, 0x026ffc80, - 0x85d70c0c, 0x8bbe1818, 0x03083030, 0xf1402ef9, 0x01ce2004, 0x58a06f62, - 0x045e900b, 0x2c40ddc4, 0x7cdf8a22, 0x6bf20251, 0x37f95185, 0x847bf8d1, - 0x1057ebf0, 0x47af2fc1, 0x161b1e40, 0x3e3f22d1, 0x3bd02922, 0x015f5810, - 0xc7265f95, 0x0f27d0c0, 0xb8a87f8c, 0x4bfc9201, 0x0e5cbb20, 0x6096f6c2, - 0xf2062860, 0x9bb0150d, 0x2f9403eb, 0x857dca01, 0xcc0003ca, 0x688cbacc, - 0x00688cba -}; - -static const u32 usem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0x4514780b, 0x74f570b6, 0x9924ccf7, - 0xf2124c99, 0x00493de0, 0x210e0311, 0x9970c044, 0x46a2c024, 0x141a020d, - 0x84920275, 0x7e889790, 0x33feaeec, 0xa8a08901, 0x17acb9f1, 0x376141dd, - 0x0c06e8b2, 0x60e03518, 0xba2eb300, 0xe7c045c1, 0x36bc8026, 0xb9f04324, - 0x9d6f5ecb, 0xdd33d553, 0xc7c4099d, 0xffef7fde, 0xa55f9f8f, 0x71ebaaba, - 0xe9d4e7de, 0x278f3242, 0xdf210a64, 0x9f968fc1, 0xf890848b, 0x206f5950, - 0x8841922e, 0x6df466d7, 0x88cfa64c, 0x68e67a23, 0xd11d985a, 0xef435837, - 0x9ed5cbe9, 0x186934a4, 0x1c790f21, 0x23e21258, 0x5ab54e84, 0x16f50520, - 0xe0933ba8, 0x213e3a7d, 0x0ff8e8fd, 0x30f8e246, 0x1a18992d, 0xe0311067, - 0xf9ad537b, 0x421eb089, 0xc3e6476a, 0x213b16fc, 0x9f9f7bfd, 0xa7eb888e, - 0xf7c10def, 0xb59efa24, 0x6529efef, 0x13fd0e57, 0xf66ddff6, 0xf108146d, - 0x71c7fcef, 0x8699ef58, 0x5d130e39, 0xd9b7766f, 0xbeea053f, 0xb6899f6c, - 0xc0fb6ee7, 0xe5fed126, 0xda0944db, 0xf0233b0d, 0x8275cefd, 0xa695ea0f, - 0xa4ae47d6, 0x9136c0f5, 0xf8d30f3c, 0x4092062d, 0x613371c8, 0xeb15873f, - 0x5aac1145, 0x6dd77ebe, 0xa3495f30, 0xf7d04489, 0x2e88378f, 0x28d92fa8, - 0xaf9d08f8, 0x8c07b5fc, 0xc578e803, 0xc23ea13e, 0x1f1beb41, 0x3ee83a33, - 0xd8fcef97, 0x7ce146d6, 0x0e2663da, 0xa4a3ee23, 0x52908d3e, 0x03e996df, - 0x9ba5fbe8, 0xbe802705, 0x4ed9dd74, 0x83695f58, 0xe3a45c3c, 0x228bae2d, - 0xee6c918e, 0xd7cc08ef, 0xdbe7147c, 0xf9830f26, 0x65dfce4a, 0x6ee52404, - 0xca2e9193, 0xdf603ae9, 0x3da7bcca, 0x053e716b, 0xd22fe59e, 0x8abf68f9, - 0x6c270597, 0xdc40c2b1, 0xd7ce8eb0, 0xb05e0a22, 0x8daafec0, 0x7deaac23, - 0x7d876e14, 0x1bd6fa94, 0x7d605ba7, 0x69458deb, 0xd716f1a1, 0x7d76a7fd, - 0xdd13536b, 0xf3e3bd69, 0x748287b4, 0x4a5ea844, 0x4fe90b88, 0x8e8119f2, - 0x85e7e795, 0xe2f7c418, 0xcc38913a, 0x3a15f1a1, 0xe9c07ef0, 0xf1958774, - 0x12dbc701, 0x842ce03b, 0xc73b6eb7, 0x54c814a3, 0x8f94af8f, 0x7ae83e00, - 0x2c763d6a, 0x6124f71f, 0x81c7a4f9, 0x33da7b70, 0x1eb5cb12, 0xc67f3e27, - 0x75cb0133, 0xcf96171e, 0xe9606679, 0xbf63e4f3, 0x58053de7, 0xf1b8f06e, - 0x253d6ff9, 0xaa79d658, 0xcf26f9f0, 0x7b372c32, 0x65fcf8bc, 0xeb2c2acf, - 0x6e58b53d, 0xb2d17c05, 0x7ec3e3c1, 0x58753ddb, 0xf1ea7a36, 0x469eebf9, - 0x3870d72c, 0xb648b2da, 0x7360e144, 0x3b453b11, 0x6573cd89, 0x9b1eb4cb, - 0xf309eacf, 0x5a46d9bc, 0x3ad3704f, 0x3280cb85, 0xd689b67f, 0xf6b15407, - 0x1c92f721, 0xf10fad33, 0x3594f6b2, 0x5a089cae, 0xed65a94f, 0x7379d623, - 0x847d6922, 0xda8fb58f, 0xa289cfec, 0xacf551f5, 0xc9134c7d, 0x18fad0b5, - 0xefa7ab3f, 0x695ae573, 0xd595bd3d, 0xe6f13f33, 0xb33d68da, 0xa93fbd8d, - 0x2c3a27c3, 0x55b0f13d, 0x14202c76, 0xb9de4d57, 0x9bca892e, 0x5dc746ad, - 0x7bc849c4, 0x892ef9de, 0xd90687ca, 0xde6ded85, 0x746eacc5, 0x77b77b61, - 0x2edff629, 0xaa5db1bb, 0xb7db0fbe, 0x9ed8dd1b, 0xed835d50, 0xdb17b28d, - 0x8a3f5647, 0x2f468ded, 0x5eaa4fb6, 0x65d7f58b, 0x55e7b61f, 0xaffec7af, - 0xfed87d1b, 0x5c9bfdf8, 0x05fd6953, 0xe41dbdc1, 0x5dc10ade, 0x9e815242, - 0xee4093ea, 0xf9f970d5, 0x6d1d101c, 0x446fe9af, 0x6efadc3e, 0xbfc00be6, - 0xf507ebf8, 0x983edfa2, 0x89bce38c, 0x1c74c8e3, 0xa4e3e2f1, 0x334137bf, - 0x257bfa4e, 0x382d38ca, 0xc6df444e, 0x24defad9, 0x2bde7aed, 0x0fd9c655, - 0xdac2b4fc, 0xffa57db7, 0x9ebb4b39, 0xe329973f, 0x89eb847c, 0x1a7adbe9, - 0xa7c2d03e, 0x7c2083e1, 0xf138e28e, 0xc64f5b7d, 0x327c2d41, 0xd3e1060e, - 0xeff4e381, 0x070d38db, 0x3869f0b5, 0x97cf8418, 0x7dc19f08, 0x21c657db, - 0x0e327c2d, 0x5ff3e105, 0xbee49eb8, 0x53fdb38d, 0x7fb67c2d, 0x498f841a, - 0xef0cf580, 0x3f32bedb, 0xf327c2d3, 0xec7c20b3, 0x7da5ce38, 0x67fb671b, - 0xff6cf85a, 0xfe9f082c, 0xbee8ce38, 0xaff32bed, 0xfe64f85a, 0x149f0835, - 0xb633e001, 0xfc69eb6f, 0xc69f0b5c, 0xb9f083cf, 0xdf19c70c, 0x384cf5b7, - 0x84cf85ae, 0x64f841e3, 0xf626bee0, 0xe3c69c6d, 0x1e34f85a, 0x3267c20f, - 0x6fb9338e, 0x42709afb, 0x27099f0b, 0x8e99f082, 0xebbb64e3, 0xc7465198, - 0xce3ef6b1, 0xf0b467eb, 0x104cfd79, 0x38e3d73e, 0xa938e8d3, 0x52671f17, - 0x933e16a7, 0x29f0833a, 0xeaae71c0, 0x77af38db, 0x7af3e16a, 0x853e1067, - 0x7db5ce38, 0x2ea4d7db, 0x75267c2d, 0x3b8cf831, 0xa36b9550, 0x3a1754ed, - 0x95cafa45, 0x40972e1d, 0xd59da2eb, 0x8093bb45, 0xf62a225d, 0x89756906, - 0xe6cb7df4, 0x8907f498, 0xb9c8eeda, 0x4ac7e813, 0xddb531ad, 0x52213d11, - 0xb8c4e763, 0xb8f53562, 0xfd340319, 0x3453f3e3, 0xa30589ed, 0xddfded34, - 0xc0fa9ae9, 0xfe9a4992, 0x3472ab83, 0xaecba1f5, 0xf64ff4d6, 0xa7a9a0de, - 0xd359baae, 0x7ced787f, 0x6b25fb4d, 0x97ed354b, 0xea6896fa, 0x42fdd597, - 0xfd747fd3, 0xe5fb4d72, 0xda6a0f8d, 0xd71ffac7, 0x3cb5c7d4, 0xbe3fe9a3, - 0xfb4d79f5, 0x69378715, 0x6db627da, 0x3cafd4d5, 0xcecebaf9, 0x5f8fd8b3, - 0xd022ebc6, 0x7f76613d, 0xf8f7e67f, 0x1bac46ad, 0x8ed05807, 0x722d65df, - 0x35f8a31c, 0xd1c0b5be, 0x7017e28f, 0xf6457e0a, 0xda4b9280, 0x267bf3e8, - 0xd3b12fb9, 0xdd18f7e7, 0xd8c3db97, 0x041e94a7, 0xc3a50492, 0xfdbea500, - 0x63d19901, 0x23f3c0ce, 0x95fbe9da, 0x1888c086, 0xb312cf5a, 0x777e811b, - 0x8a2fcc0a, 0xf4154914, 0xf411348b, 0xce481e0b, 0xa2abc17c, 0x298355d7, - 0x71a10a1f, 0x24eec957, 0xaade33b0, 0x1d82f76e, 0xee983352, 0xcd21006b, - 0x4bdfbb42, 0x0607b4fd, 0xe9b92517, 0xb5232678, 0x1bf3d5d3, 0x3869fce9, - 0xebd00b7f, 0x7c7f307b, 0x294df9cf, 0x9bf33413, 0xe6689487, 0xfce91b37, - 0xafde4276, 0xa7e7c53e, 0xc8449848, 0x3853845f, 0x094869bf, 0x9180ffce, - 0xf9ea2bfa, 0x1ff38323, 0xd67ffd86, 0x2653fedb, 0xa43ff769, 0x237fbb54, - 0xea91ffdb, 0x48fe7cb3, 0xe151ffdc, 0x90ffdb2c, 0x137fb652, 0xbf38371b, - 0x93ff082d, 0x2f677f30, 0xb3529bf3, 0x5a1ffbb4, 0x89bfdda6, 0xfd5ddfcd, - 0x82df9f2d, 0xbe139ff3, 0x5a1ffb65, 0x4d1bf386, 0x8fd0276e, 0x95646071, - 0x1d4fce8f, 0x04490761, 0x40f3a172, 0xfd163239, 0x148497e4, 0x913dc75c, - 0x8abede8c, 0xf286f4a4, 0x58fccbc6, 0x996c951f, 0xb4e2efd4, 0xb67378be, - 0xb612e411, 0x21657f53, 0x8d1dea5f, 0x7937d222, 0x4e1be4d2, 0x28d9dbd7, - 0xc77ea17a, 0x207d9393, 0xe44d2aff, 0x4f787cf6, 0xfe787e22, 0x9fa353f9, - 0x5f4bef57, 0x8f95ac2e, 0x2df8a9b7, 0x90e547e8, 0x98165591, 0x1fa9aed7, - 0xa1107ea1, 0xd427c5fe, 0x249420cf, 0xbe6cca8f, 0x04bfa8cf, 0x2fea36f5, - 0xd5213b41, 0x75e25fb8, 0xae8c307d, 0x3f289f3f, 0x26f3ee17, 0x9e3a2964, - 0xc8f7f8c4, 0xf807c11a, 0x14597db8, 0x3d687e05, 0x4d38de85, 0xfb0fee9d, - 0x7c12ae07, 0x86380bcf, 0x9333e01b, 0xbd60478f, 0x67605eb4, 0xe8a21cef, - 0xb0514fef, 0x8a40d560, 0xb338d08b, 0xa44e4b88, 0x5a59cfef, 0xa2e84328, - 0x2f061055, 0x2059fa01, 0xe0119753, 0x69278de7, 0x7ae8389c, 0xf1b3b66f, - 0x63e4ba67, 0x14f5aa6d, 0x3e5766c8, 0xa1414f5d, 0x359feb88, 0xd1fedb43, - 0x619728ce, 0x3d572d0c, 0xc9ccf381, 0x54dfb6d7, 0x75cfada0, 0xef54eb6b, - 0x6ef7a0c9, 0xa73fd129, 0x9cfba160, 0x5d2b8417, 0xade75d28, 0x56b70e1c, - 0x5e0d5ec9, 0xda556dc1, 0x26e0a021, 0x5f7c2fb8, 0xf6ffd9ec, 0xa17ada65, - 0xb05f5b57, 0xa73e374a, 0xff1ce39b, 0x683e8047, 0x83e80279, 0xa718f3c2, - 0xd55c908f, 0xc18dc7d2, 0x50fa306d, 0x625c71f6, 0x8ebe3828, 0xdac2c7d1, - 0x50f4f0a8, 0x9707a418, 0x7a14be9a, 0xc3d38db8, 0x8a1e9ca7, 0x6ae96ad7, - 0x4cadf12e, 0xb2dfefa2, 0xe9e21766, 0xe8c850a0, 0x3d0a97e1, 0xc1e869b4, - 0x8f41e9cd, 0x3d38dbbf, 0x4673f6dc, 0xb67c7a0f, 0x5b687a71, 0x29264e7b, - 0xf14af13d, 0x3c53a9a0, 0x376ef0e8, 0x7c503d02, 0xf987a584, 0x8dd37dc1, - 0xde02fad3, 0x9c5f03d6, 0x053db01e, 0x4e104ec0, 0xcf6a7ef8, 0x684e54fe, - 0xc36bc5ea, 0x31b2bfe3, 0x6a98ee3b, 0x57f5e55d, 0xf5531dc5, 0x53375c5b, - 0x9be45f53, 0xbc5fe9ab, 0xbed350b6, 0xa69176b0, 0x3baac17d, 0xef42f535, - 0x6ffd35cf, 0x69ad565f, 0xb56ab5bf, 0x9296fda6, 0xb9f534c7, 0xfa6b5fee, - 0x5eb054df, 0xff273ed3, 0xacfb4d45, 0xf5345b19, 0x34d7ae99, 0x2f3b0dfd, - 0x31e81ebd, 0xc048a0eb, 0x71e638fe, 0xf71fdd20, 0xa4f2c48c, 0x717c89c7, - 0xcb0133da, 0x4fcd8d7d, 0x7cbb495c, 0x26882819, 0x91167f4c, 0x2cf64218, - 0xcaaf5777, 0x504e7d02, 0x7971feef, 0x1077b551, 0x07065395, 0xad6f39c2, - 0x11c7f891, 0xe2528022, 0x50c407f3, 0x6d1b567b, 0x3dbdeb8f, 0xb614ad6f, - 0x0a4dab3d, 0xe3e56e3b, 0x61ed4385, 0x7e2133e2, 0x3ec10326, 0xb9f6e2ea, - 0x204cbdbe, 0x84e7eaf9, 0x8ffe472c, 0x5cfd3031, 0xa2726466, 0x1cff6b6c, - 0x7fba8362, 0xe685d544, 0x95cca7ab, 0xaa91f408, 0xb5e2e3e1, 0x3ce46997, - 0x3c6de881, 0xcd38d9d0, 0x5775c5f3, 0xd8ebde6a, 0x2bbae225, 0x7d508640, - 0x07e48c3d, 0xfd97a00c, 0x8d6643cd, 0xceba7586, 0x355e401a, 0xd8fda3c6, - 0x771199e1, 0xe63c024c, 0x53d27963, 0x8f71e580, 0x9e63cb1b, 0x788f2c12, - 0xf36cb0aa, 0x33f2c32c, 0x4fcb178f, 0xfcb0ab3c, 0xe58b53c8, 0x2c5acf61, - 0x587c7a0f, 0x61d4f01e, 0x1ea7bef9, 0x234f56cb, 0x171e9d96, 0x29bf0a96, - 0xddd3d0f0, 0x4fa7ae49, 0x805dfd03, 0x07c4e2ce, 0x0a0d57aa, 0x8ae259d1, - 0x59bdab87, 0xd6f371a1, 0x249d389a, 0x0861e868, 0x81e364f8, 0x5e9c4c5e, - 0xade7b7c2, 0x9ed82f95, 0x1d8726d5, 0x7ff9f2bf, 0xf9cdbd0d, 0xa216f491, - 0x7a3a81a7, 0x3d18bd4a, 0x87c7124d, 0xc18e69e8, 0xa71ff4ce, 0x1f6087a7, - 0x628ffc61, 0xabc6ea30, 0x14573aec, 0x73f3678b, 0xb2d16a07, 0x7b9f3678, - 0x15ae1d05, 0x48df3fed, 0xc8f773c0, 0x78808fbf, 0xaa61f77d, 0xdf7b9328, - 0x7a5e9e9f, 0xfd0bbb87, 0x551f22a0, 0xb67ae3a2, 0xb8324447, 0x0cc81846, - 0xeac84e92, 0xce75bfe1, 0x44bac34f, 0x9f7de162, 0xf3986673, 0x4f670228, - 0xeb871789, 0x6357eb0a, 0xcfe3bc60, 0xca1323fc, 0xe6148639, 0x688b34df, - 0x0bff13df, 0x506f804e, 0x499c991f, 0x0c0f0710, 0x3ed1da37, 0xf0b459f0, - 0x667ad2f3, 0x29ab7e08, 0xdf515a8c, 0xfc2126d7, 0xa2357d86, 0x77e01f7f, - 0x317f3931, 0x0df7ce78, 0xf3c097f8, 0x62f1f262, 0x1cb89172, 0xfdd2372f, - 0x9d1ced77, 0xe403a0fe, 0xade185e0, 0xd7e95f9c, 0x7d28bcf3, 0x4aee3a2f, - 0x75b8e850, 0x88f3a108, 0xefc71da2, 0xc984b86e, 0xdbeec52f, 0x05f5f266, - 0xb59267af, 0xf9c53de3, 0xbbaf194f, 0xf81b05e5, 0x0c924b5b, 0xf06163f6, - 0xf5e594a0, 0xda8b76c9, 0xd6d46cfe, 0x19856bbb, 0x3a2768f5, 0x068f67a2, - 0x1fb7613d, 0x3b72061b, 0x9c654b09, 0xfb464925, 0x4ef72a31, 0x3346a5d7, - 0xe4c7cf3f, 0x9418e6c1, 0x663da717, 0xaf53ffec, 0x9471b7a7, 0x40d210f5, - 0x1e419a8e, 0xded4b6d3, 0xcf4af7fb, 0x3c4617d2, 0xbf926df7, 0x4cd0fb02, - 0xfc0effff, 0x5d61220d, 0x5eb2b719, 0x872e9af4, 0xf3359be7, 0xca1cf7d1, - 0x2977eb19, 0x891be217, 0x96e8571c, 0x5c638bea, 0x8bae2c9f, 0xcfed6bb0, - 0xb2bd4d18, 0x635dbfb1, 0x541fc28f, 0x412a92fe, 0xe329fa02, 0x5925d3e4, - 0x7d740956, 0x1090426f, 0xfd6056e8, 0x466dcdca, 0x95ce03b7, 0x5b7ade19, - 0x4cdfc51f, 0x897c9289, 0x61cf16b9, 0x9d2fea4b, 0x4ce67a0a, 0x88048ac3, - 0xbb162c1b, 0xf30fc9ef, 0x79312cbe, 0x0727c8bf, 0xa73df6b4, 0x55c7420f, - 0x945c639e, 0xeaab8e58, 0x8f16061d, 0x009b8fd1, 0x1c5fc6e3, 0xf79b153e, - 0x413b074f, 0xc68aa70f, 0xca3746b3, 0x665ffa45, 0xfc0a4e08, 0x13f314de, - 0x697e3a24, 0x2dc63b5d, 0x11deca4e, 0xbc80bcbf, 0x4b3fb9ec, 0xd528f1d2, - 0x15a4bcbe, 0x813f99e6, 0x371c444f, 0xf8e54c7d, 0x04c93fa9, 0x4f3910e4, - 0x4862657b, 0x063bfb86, 0xf90cc862, 0x161bf33b, 0x4fbc01e7, 0xe547bf81, - 0xdf241de6, 0xb5207886, 0x9cdfe099, 0x00198621, 0x7de433a7, 0x1e1538db, - 0x87232572, 0x94829533, 0xf1c14c1e, 0xefc1fddd, 0xb4d41532, 0xb9e0638a, - 0xc23ff8a4, 0x72471877, 0x50b7980b, 0x897b9ec0, 0x97e81ab9, 0x3f1a51fa, - 0x9a51fa8d, 0x34a3f53a, 0x437222f5, 0x1425e402, 0x9f13293d, 0xb4d27080, - 0x88ec928f, 0x555262c7, 0xafd1f603, 0xbe6dfc79, 0xe903489d, 0x7d5fcb3e, - 0xee90b336, 0xc5896ae7, 0xf57394fd, 0x0e0cb145, 0xa33e25a5, 0x7f73d2cb, - 0xddc61b47, 0x8c3f2548, 0x6fcfcec7, 0x051e6236, 0xdc994ab4, 0x7de949f4, - 0xa20d89ff, 0xfd06c22b, 0xbd6573e8, 0xff7fdfc9, 0xf212fdfa, 0xb4a3ee38, - 0xfa01266e, 0xc02791eb, 0x09d723f7, 0x7e185f2e, 0xaf74e42a, 0x013ba7e8, - 0xf143e37e, 0xf574fbac, 0x4abe1cd5, 0xfb5d29fd, 0xfd2f960f, 0xbcbe4688, - 0x93efba29, 0x027933c6, 0x00a417f0, 0x1e0fd7f2, 0xf8c7a93f, 0x7f1f81ab, - 0x6907f1b2, 0xff8e9ef9, 0xfeba4fd4, 0xbfd63d61, 0xcbfadc3e, 0xbb697d5f, - 0xd297ea97, 0x23653c3f, 0x494edf94, 0x8a4e09b5, 0x2b8db2f7, 0x3b902e6d, - 0x7c06d792, 0xce27ca71, 0x870f4708, 0x06a57cb8, 0x78804588, 0xc749fc2b, - 0xa1e9bd3f, 0xf89ec0eb, 0xc76ca36a, 0xc99d6a38, 0x5cf4a26f, 0x8f28b0d1, - 0x3b7ac18c, 0x16703fab, 0x51b2bfe8, 0xd3a6a23e, 0x953ddfd2, 0x94357900, - 0x921a0652, 0x7fa3f4a0, 0xf3e1b152, 0x546f60e9, 0xabf20092, 0xff983dfe, - 0x87d4589b, 0x9ee8c685, 0x499818ed, 0xafd9f780, 0xb3a1e1b2, 0x6afe0da2, - 0xbe9038c3, 0x37f7097f, 0x3f6b245a, 0x82b9273c, 0x54f2015c, 0x31f10781, - 0x8bc5637f, 0x4ed31abf, 0xe1b1d3d7, 0x0541364f, 0xea4fc527, 0x9bf05fae, - 0xcbbd1dd7, 0x87ca4eef, 0xd156bb6a, 0xee468e4f, 0xb2b13527, 0xaedbf64c, - 0x6ca4f2a4, 0xd2f4ecbd, 0xbd2f65c7, 0x2067dbf0, 0xc9a1fd7e, 0xbf8e9c39, - 0x073da5f8, 0xe2fad127, 0x3cbf722d, 0x908b0db6, 0x254bc210, 0x7a597ffd, - 0xafa50f08, 0x463a31ec, 0xc6f7e7b3, 0x78b1f086, 0x19232ecb, 0xb91e13dd, - 0x6d8cbbf5, 0xa9783096, 0x760e9f6f, 0xbf178adf, 0x3bbc8236, 0x892053b5, - 0xb9e061c9, 0x85da0f7e, 0x23c42700, 0x6f1053c7, 0x1495feba, 0x145fa02f, - 0x37dbe93c, 0xe3027971, 0x9e90d239, 0xce9d7e5f, 0xc991f25f, 0x792ffb09, - 0xec1b2ef9, 0xc55484e3, 0x95d9fae8, 0x4adf2009, 0x1d826f64, 0xe4bcf64b, - 0xde91bbb9, 0x9ddff78a, 0xae92e2c0, 0x95d406fe, 0xbfb0fede, 0xe0e6eb85, - 0x1b888afe, 0x59e4aee9, 0xcb47df31, 0x6332252f, 0xb8be184b, 0xf2726656, - 0x2354f3c4, 0x509dfdd0, 0x22fbc0f4, 0x627703d7, 0xbe6ef3dc, 0x62316a17, - 0xc3334bfd, 0xc0d930d3, 0x2bd32ce5, 0xf0dd7a41, 0xd38bea00, 0x70895d83, - 0xd21956be, 0xc437a80f, 0x1912d3fd, 0xc19e987e, 0xc99ea8f7, 0xbfd0e785, - 0x8c457655, 0x7a87bcd1, 0x297f9945, 0x3bae9f9f, 0x13b5ec12, 0x8ffde109, - 0xdf0acb9f, 0x4542bb53, 0x66fe2a5f, 0x3561befc, 0xdf856fe3, 0x4067337d, - 0x180717fb, 0xa07bc0ff, 0xfcbae967, 0x6bbed889, 0xc0f280b6, 0xf8e1fc44, - 0xf9cc837a, 0xd0aedb5a, 0x24b75d09, 0x05e8ab44, 0xf8458fc6, 0x7a2f5ea3, - 0x92a7be92, 0x9f309597, 0x0a78e7ad, 0xfe7316df, 0xf96b219f, 0xef8bac9f, - 0x99653e53, 0x33edfbec, 0x3f94afc0, 0x57e00ebd, 0xfdf61f39, 0x07cdcdb7, - 0xfa7ca66f, 0x4f857ab7, 0xcf53f2b5, 0xef5b25a7, 0x7a9f4026, 0xa0dbfd3e, - 0x4f96122a, 0x7cb0f3e9, 0x7feda83a, 0xf02a7e54, 0x45f802ab, 0xc8a7e085, - 0xa8e0dec3, 0xd9568797, 0xd21e5611, 0xd99201df, 0xba14fe93, 0xf4ade853, - 0x4143e5f7, 0x52e904ee, 0x5d20bba1, 0xdfa7742a, 0xfa7e16af, 0xc13249f6, - 0x26bfe575, 0xd65cffa3, 0xe942f2c4, 0x66077b7b, 0xa85c9c20, 0xdeed48c6, - 0x75d4fd81, 0xaf5eae9f, 0xd5d2efeb, 0xddfd75f3, 0xa6957aba, 0xb363597f, - 0xfdfe2091, 0xb2e27e9a, 0xb8d1c867, 0x63eaf470, 0x59c3597e, 0xc2e817a3, - 0xe5f7c012, 0x790bc4e5, 0x221d8186, 0x28ba05c6, 0x7e206b8c, 0xe7d939b1, - 0x656372a5, 0x743f8b04, 0x58b603d9, 0x618cae5a, 0xb1bc40f5, 0xf29ee406, - 0xe2c1103c, 0x01f95d8a, 0x9fca8c5b, 0x51126f6a, 0xc8f9b76e, 0x167e708c, - 0x47c828d5, 0x76b7a46d, 0x4d35ee76, 0x06590cb4, 0xd15aa571, 0x1df83609, - 0xe0d937d5, 0x29aba9dc, 0xfa02faf5, 0x451fe17c, 0x8ae97b4c, 0x75818db4, - 0xea4baf11, 0x4e6ff2af, 0x59d3ef12, 0x9a0b7f74, 0xc7739f98, 0x423d9d1a, - 0x153d20d6, 0x411a9659, 0xe27f529e, 0x86bcf688, 0x1f2945f1, 0xb69d64af, - 0xd29f795d, 0xa5f3fa01, 0x6eedb41b, 0xa07f0fee, 0x3258c9f0, 0x2ca3fb96, - 0xf2e5c30e, 0xfaed3134, 0xae8f8a02, 0x68989116, 0x4449bbbd, 0x166f747c, - 0x234f107c, 0xb7e478de, 0x7940120a, 0x03a9c0a8, 0xbbd8c9f8, 0xf6d8eabc, - 0x812fe669, 0x3c7fb66e, 0xd9693fe6, 0x11c3fdb1, 0xd5fd406f, 0x263e4343, - 0xeee7fb3d, 0xff73c08c, 0xa4569dae, 0xef1daef7, 0xd425f90e, 0x6139335f, - 0xbf3b5d9d, 0xd3f4031e, 0x0254dcb5, 0x306baef2, 0xd8aec78b, 0x3698f5f1, - 0x33f7afd4, 0xfe6461fd, 0x3fd37761, 0x41fa133e, 0x76057749, 0xe428cec3, - 0x23d7caa7, 0x6bbbdf30, 0x6e99d7c7, 0x9fb74fcb, 0xd1e79e0a, 0x5b052565, - 0x2c317d61, 0x8df2a18f, 0xd3542f89, 0x761bcbf9, 0xf6d01719, 0x39ff37dc, - 0xd768e406, 0x750f6656, 0x41cf6dca, 0xf194431e, 0xe29972dc, 0x8a9813ab, - 0x33bfcd3a, 0xdf02e466, 0x3fcb84f4, 0x57d63e31, 0xaffca478, 0x62e08781, - 0x33eacef2, 0x6fefb00b, 0xe318fb3f, 0x4ba4269a, 0xab7fbf65, 0xe57b46af, - 0xfecefb62, 0x82df6e7f, 0x76fb2fbf, 0xfbef9bff, 0x7abbd738, 0xe749e83e, - 0xfac1ee3b, 0xae27564b, 0xeef48fb7, 0xffc7fd85, 0x7bffeefb, 0xc52b7de3, - 0xfbe2edbb, 0x5affcdfe, 0x36f1ffbc, 0x7e3b778e, 0x3fe6f3d7, 0x57df7d71, - 0x6ff9bdce, 0xf6def78e, 0xadf5d8af, 0x067b2a86, 0xa9015f5d, 0x316182b5, - 0x92dbbe37, 0xd76c80e1, 0x8f30fd73, 0xc34bce0e, 0x23014df8, 0x904d0bf3, - 0xfb7e0747, 0x0b89411c, 0x1d751fa2, 0x1bae1fb7, 0xc8768254, 0x9987ae75, - 0xb55520dd, 0xadfed366, 0x989c0b39, 0x0fd24973, 0x7b3ea1bb, 0xfd6baf32, - 0xe204f7c9, 0x7f1da812, 0x2d35ce5d, 0xef5ed760, 0xa5eed112, 0x1fbbda25, - 0x9ece990c, 0x3dfad04f, 0xfadadd73, 0xfada054d, 0x8dde3e1c, 0xc6ffad84, - 0x7107c17c, 0x13f65355, 0x356710f1, 0x9089942d, 0x5542f90c, 0x98bfc12b, - 0x7f7daf93, 0xe3c1f81f, 0x531c3c7f, 0x971c0a4d, 0xb6485c20, 0xfa48dce8, - 0xeebe4700, 0x7d63d9d6, 0x244ccf90, 0x8de38327, 0x838c4ee5, 0xe65b7f73, - 0x5596cbef, 0xb2cfc0ad, 0xfc56cfce, 0x4de0dee5, 0xe38dffb8, 0x2fe084a4, - 0xbff444bb, 0xadff9d65, 0xe2fbe5e0, 0x8fe3c143, 0x3a97cbc5, 0xb8b20cbc, - 0xccabf008, 0x16a985fd, 0xca0fab27, 0xc8de7827, 0x9fa905fd, 0x42d3788b, - 0xcc8bdf79, 0x5f386ce6, 0x30148f33, 0x1afd71de, 0x3983f511, 0xe575c04d, - 0x8f31904f, 0x7e4373f8, 0x6f3be026, 0xbf1515dc, 0x0270cb60, 0xb871173c, - 0xb42a9117, 0xeff9c95f, 0x84cacbbe, 0xf6820673, 0x211722ef, 0xadbf52d7, - 0x47f04b28, 0x4b157852, 0x0e9d1bc4, 0x1c816f71, 0xb5bdc4d1, 0x47fdf875, - 0x8b9c6842, 0xbe4deff5, 0x5fe5d4fc, 0x323b3ca9, 0x1e41fa8c, 0x5849bb9e, - 0xaff156dc, 0x70626f6f, 0x7c132cac, 0x7e774829, 0xee755f39, 0x83e71cf8, - 0x0e3bdebf, 0xa3f664e5, 0xefd1a3a3, 0x6fd03977, 0x437ee4a8, 0x0d11d7b7, - 0xa6eeae71, 0x9b3e7e54, 0x55cb536b, 0xfdcfdca5, 0x7e40bfee, 0xa6bb2d21, - 0xf822b50a, 0xf1802471, 0x08d4ef5c, 0xfe4c31b2, 0x1931ffeb, 0x6154fd38, - 0x627e001c, 0xfd91e026, 0xd1abe98a, 0xadbc2ab1, 0x3494f6b9, 0xe01e27a6, - 0x0e754477, 0x0be163f9, 0x75c03e7e, 0xf4db447f, 0xadfb30fc, 0x5638b135, - 0xe2df5bde, 0x34379c77, 0x9700cb25, 0x9a8aa61b, 0x2655fb73, 0x238d97ee, - 0x795d60e3, 0x9b655d6f, 0x11697808, 0x66ddf09d, 0xa359d365, 0xb079cc3b, - 0x3e309e1e, 0xca8fd5c4, 0xe78022ce, 0x082387d1, 0xf2efd1f8, 0xf834c673, - 0x430d226e, 0x2b882e3a, 0xb5c39afe, 0x72c764d3, 0x1cb65e56, 0x6b4de74f, - 0xa3858fb0, 0x7fbc01d4, 0xe3211827, 0xbd878921, 0x501bf4a7, 0x1bb5fac6, - 0xf6e115ed, 0xed823c3f, 0xef3898bf, 0xfbfc2099, 0x51fb2de1, 0xec073fab, - 0xae3ca983, 0x09ae83d2, 0x0cf747f2, 0x1bfa07c1, 0xe7ac61fc, 0xdf84efb1, - 0xbeb3be55, 0x8559e981, 0xde70f5ee, 0xccace1cb, 0xe2c4dc7f, 0xfce27faf, - 0x8159c0a5, 0x4abd7eaf, 0xa6af2a7f, 0xd751e3a8, 0x197d8e37, 0x268a9bec, - 0x43a06ec1, 0x466d4855, 0xc6cac3e0, 0x6f3864c7, 0xe360eb99, 0x8c7f2912, - 0xd3a09f3a, 0x9a3bf2c4, 0x0dbcafd3, 0x1adce4e8, 0xe242e813, 0x0dace3ba, - 0x06bbf0e4, 0x7be19fe7, 0x227bef6a, 0x790178d9, 0xcea7b1f5, 0x8f525535, - 0x9ceb8c9b, 0x432d9655, 0xb296ecf8, 0x8aa2725d, 0xb14d3a9e, 0x1f3caed8, - 0x8748e650, 0x5c3e74e7, 0x1311f787, 0xd242ef81, 0xfbf15bea, 0x62aa5bd4, - 0xd4961d18, 0x3d6232ef, 0xf32bfb19, 0xf9e8f329, 0x369e7669, 0x6e4178ef, - 0x4b8020db, 0xd4bfc99e, 0x1f4e8619, 0x8ee72b33, 0xb84f53df, 0xf98edd28, - 0x2c4f48ff, 0x1b44f455, 0xef2bb9e6, 0x3e3335cf, 0xc489e957, 0x49627a70, - 0xf01123b5, 0x6a4764b0, 0x92c93022, 0x084b4e3f, 0xf03e27a7, 0x43e373b0, - 0xaeeebbfc, 0x5c4f54d9, 0xb313d2ae, 0xf44e9023, 0x959ae5ef, 0xe88b8d73, - 0xff6f0509, 0x03e6f2c3, 0xf86113d0, 0x56b346fb, 0x54d8dc4f, 0xc6e27a88, - 0xfbe6a2d9, 0x17cd6baa, 0x09d913d3, 0x3b2eb173, 0xcfd0c2a3, 0x39bfdc07, - 0x61fbf3c4, 0x6b17d01e, 0x9b8476cc, 0x26f46f5e, 0x55f6c7d7, 0x825fffae, - 0x97d722b3, 0x43f761cc, 0x8243a4f4, 0x2e64bcf4, 0xd002eb95, 0x4beb9323, - 0x4e71e56e, 0x07cd9c9d, 0x96a19b39, 0x0afdecb3, 0x950bd337, 0x9abfc98d, - 0xae6fdb47, 0xda669d95, 0xdc90e6ff, 0xddcb54cd, 0xe1096635, 0x96ee43dc, - 0xae7bb930, 0x4fda1c69, 0x53efedbd, 0x3ca96f2e, 0x430ce61b, 0xa2f3051f, - 0x1ddfdf34, 0xda76fb1d, 0xef2fc02b, 0xfb7e788a, 0xf603b739, 0x033b7d8d, - 0x7c53e9ec, 0xfcb8db3d, 0x5cf8f4eb, 0xc81ca953, 0xd3d983bd, 0x84459be5, - 0xe303455f, 0x91618aff, 0x4fad073e, 0xcf16ff4f, 0x60ef1761, 0x0774b0e7, - 0xfc2ad979, 0xadb77e2f, 0x1605ce06, 0x1cf017af, 0x005fbe19, 0x78731678, - 0xe3173916, 0xdaf14a39, 0xe53fe7f0, 0xa6a2dfbc, 0x5f0f18f5, 0x2bf6d3e4, - 0x29f5761f, 0x4cf247f0, 0xaf790f0c, 0xc9f5be08, 0xeba0cf90, 0xe78d5ce7, - 0xdaf5e547, 0x7ef907e7, 0xb4fe8a17, 0xe4fbe857, 0xd3bfcccf, 0x1ea0fbc3, - 0x123f252e, 0x5c29fb2e, 0x70f5fe32, 0xd40e0de9, 0x01f3c7be, 0x2b0e3c3d, - 0x649d2572, 0x6e7e1f00, 0xf15ca170, 0x42e143be, 0xb1e3bbe7, 0x40fb9ae1, - 0xbcb8738e, 0xf4d7706b, 0x02157e87, 0xb75e2bf6, 0xad024f65, 0x6327abcf, - 0x78a178e1, 0x070f56ad, 0x03837ef5, 0xaabcfaf5, 0xc7e4022d, 0xfbdfe42e, - 0xc31ef895, 0x5d6e547b, 0xed3cf546, 0xe4dd20bf, 0xfdf07386, 0x9b940111, - 0x47c6dd0a, 0x8e25fb30, 0x03a3a1cb, 0x3f515302, 0xe4760a35, 0xd3047f47, - 0x704f1457, 0xc4f34bbf, 0xbc73a7af, 0x2352b8b0, 0xc52563c3, 0xf4f3f01b, - 0x63af5e26, 0x4a2de076, 0x39f05ebd, 0xbbab9004, 0x8c5f7664, 0x8e04e240, - 0x847e9504, 0x04ecd5f3, 0xb4779e15, 0x28dffa33, 0x8f81f138, 0xf043f7fe, - 0x33dd2bdc, 0xf4afa63b, 0x3e29c0ae, 0xfde78b42, 0xe379ad11, 0x9bf9c1fa, - 0x737bc4e0, 0x9cf0629a, 0xbb2d58e8, 0xbf9525ff, 0xf00be7a7, 0xd1f7d43b, - 0x438584cc, 0x088cf37e, 0x79c50fcc, 0xa65d9853, 0x7bfa4f96, 0xfe6fbe80, - 0x45692551, 0xc7942c7b, 0x04de7ee8, 0x3410cde3, 0x09104ef9, 0x09ff3a03, - 0x7cd5bfc6, 0x9249f181, 0xef96f31d, 0xedcf2bb2, 0x5e2cbbec, 0x799c1e6f, - 0xef851e68, 0x13a255b9, 0x0c9ba85c, 0x2059838e, 0x09941e6f, 0x7db9cbf0, - 0x81e98bb2, 0x853bd428, 0xefc51eef, 0x0e590ad9, 0x8fbc291a, 0x7ca397e9, - 0xbd511f3d, 0x0a5882ed, 0xf70f1fa9, 0xee76cce0, 0x7880e69a, 0x95fec64b, - 0x2b39ce70, 0x20f07ed7, 0xbb3573e0, 0xaac8e907, 0xeed3f45c, 0x7e4053ba, - 0x06f14c3b, 0x9d99cfef, 0x9d20f07c, 0xf155d6f7, 0xcf396e78, 0x9c237f15, - 0x27dbce63, 0xdfb41d3a, 0x16adeb82, 0x66bcc738, 0x2adc48a4, 0x5a4adcf8, - 0xaf33be31, 0xb039ceea, 0x0faa12ee, 0xf72864c5, 0xfa844b4f, 0xafdf013a, - 0xf08dbaf4, 0xdaeb66bd, 0x3a0cc6b3, 0x07ed117f, 0xc75caf60, 0x106e55fa, - 0x5dfa909c, 0xca18f4d4, 0x020da2cb, 0x4ad3345e, 0x1b335fed, 0xe3a667d7, - 0xefa3aeb6, 0xbc317ad3, 0x886ee30f, 0x27ce11b9, 0xf13ae92b, 0x78d509fd, - 0xdf445d2e, 0x75a4cda3, 0xde389dc3, 0x810275a2, 0x264b03ef, 0x01323f24, - 0x3b27dbc6, 0xaed0fda1, 0xdd611b5f, 0xfaf9d1b7, 0x8817f1d3, 0x3fa0d36d, - 0xc760a5f9, 0x46ea87fb, 0x0baddc60, 0x542f0c36, 0xe63ac70d, 0x0c103b13, - 0x651f3a92, 0x4efb0447, 0x755968b8, 0xcdabec0d, 0x406c9f1b, 0x046b3aba, - 0xc28c7e3d, 0x3c874ddb, 0x2e79646a, 0xc6a3decd, 0xfd1c9536, 0xdf152228, - 0x1b31a3bf, 0x921626f3, 0x709bcc7c, 0xa47b3357, 0x0f84657d, 0xb2ed6ae2, - 0x6f3c087d, 0xe7c2695e, 0xfd312f9d, 0x0db839d3, 0xd627dbe3, 0x5fbe04c9, - 0xf52eb15c, 0x89e3c069, 0x9bd232cd, 0x1bcb2cf8, 0xc5897e28, 0xb1d79ac9, - 0x352c4f71, 0xa0b57bb2, 0x5f8bd69d, 0xb40af254, 0x51c8ac72, 0x2f4a728a, - 0x6b72f497, 0x46d593d1, 0xf21ed920, 0x9474e96a, 0xef54a557, 0x90f5a100, - 0x306a8357, 0x5797aa6e, 0xc8a2c495, 0x5f8874a9, 0xbe0f9616, 0xf1d02d6d, - 0x8183ecad, 0x5f6bff56, 0xb77a053e, 0x49e04acc, 0x5a7f6485, 0x80417460, - 0x6d35e65f, 0xa0f812f9, 0xde045e64, 0xf01c75c7, 0x26b37c00, 0x8bafcf0e, - 0x6f08857c, 0x78b72f25, 0x95ce96ad, 0xb75ce3f8, 0xfd6a5c48, 0x5c451255, - 0xee877eaa, 0xe74af4a3, 0xf051bdb9, 0x743ca881, 0xbbdefb5f, 0xc76eb033, - 0xf6e32d75, 0xd22b1ac1, 0x9f9fa1f3, 0x7af4095d, 0x0102bddb, 0xdd789d7b, - 0x2b0fa035, 0x880e0ad6, 0xcbdf170f, 0xefa62fde, 0xfd0fbac3, 0xa515d19a, - 0x7fd0076f, 0xf6c7bac5, 0x820dff62, 0xb43fc603, 0x89ed10be, 0xb048af12, - 0xfa3b437d, 0x614f540f, 0x57b3599e, 0xaffa004c, 0x0764dfb8, 0x23a14953, - 0xf9db2e85, 0xecc4087d, 0xbe8b331c, 0x15160ab7, 0xc51e93df, 0x4fa82102, - 0xbd2a4e81, 0x5fdace8c, 0x36409d92, 0xf64ba717, 0xae09fc1d, 0xe767c55f, - 0x74ef874c, 0x047ea98a, 0x975e6d3a, 0xe23b046b, 0xfcc04f84, 0x49749e8a, - 0x4a3b6a2c, 0x0567cba1, 0xd07baf26, 0x7b0e8ea3, 0x4ba71dd0, 0x5128fe85, - 0xb6595fa3, 0xfdf0264f, 0xdd1e9ebd, 0x908dfd72, 0x32f851ff, 0x6f5d0fdd, - 0xd1cfcd6e, 0x48e0575e, 0x2f5009eb, 0x8fde5892, 0x12e50fc2, 0xdefb0fcb, - 0xbfcdd3eb, 0x87e78229, 0x2c883f01, 0xe74fc97f, 0x0bf37b7d, 0x66792f98, - 0x6875fb53, 0xe941bcdf, 0xd9bfe000, 0x7fe8fc4a, 0x950e50f8, 0x6f988836, - 0xe67f244d, 0xaedf952c, 0xfe2cbfe4, 0x5de11583, 0xcbe4d5ba, 0x6e97efa3, - 0xf3063a3f, 0x30079611, 0x49bbc7bf, 0xde1fe760, 0xfdf031b6, 0xf2c4a950, - 0xc176f470, 0xe71648f0, 0xaa2d78ea, 0xa136ec00, 0x57b3dd8e, 0x6c937f5a, - 0x0775c552, 0x2f38ca45, 0x63e787ed, 0xb8678a5e, 0xa7d6011f, 0xc94ddfbe, - 0x9178e9bf, 0xa3695fd1, 0x695cf68c, 0xc84e96dd, 0x6c3d2cc3, 0xb2b73f42, - 0xfc11acee, 0xbc3fdcd8, 0x55f3f784, 0x3c9a8a36, 0x6ff91ebc, 0x04dfa275, - 0xe50d5bf9, 0xeb437e78, 0x0faf58ed, 0xb17a079f, 0x7fc5ad3c, 0x4bddb1d8, - 0x95f8b841, 0xbef0d9df, 0x368dd6be, 0xeea9eefc, 0x3da7f9c2, 0x57eaddf2, - 0xeddf305f, 0x0941fc34, 0x5d48baeb, 0x931d60be, 0x997d746b, 0xc4e261f9, - 0xa5eb7b41, 0x7c839f2f, 0x7fad8eec, 0x5bd60e7b, 0x9ee75ff6, 0xb21abc83, - 0xf60ec233, 0x0fa6e548, 0x79559f30, 0xd99224af, 0xfe2f9d7f, 0x3b80f30e, - 0x6139343f, 0x271dceb4, 0xd1bd8086, 0x04dbe5b9, 0xba5defc8, 0x73c61a63, - 0x4dcb6e96, 0x05e26124, 0xeb74094a, 0xb21e43eb, 0x0dcd5f1e, 0x73ff98cd, - 0xe41be286, 0xb17f3043, 0x83e59cbe, 0xe2de783a, 0xdef9f0e6, 0x1b14f23d, - 0x193f5d66, 0xb30362e4, 0xaf9a2e0b, 0xf1e28078, 0x6fe03ef2, 0x4f2e6af3, - 0x0cefe3c2, 0x54f141fc, 0x57cda913, 0xe161b2fc, 0xb6819e6f, 0xf35eb886, - 0x807dfd15, 0x3e4f929b, 0x58f5d22b, 0xd6cdf024, 0x287e63df, 0x01cf2de0, - 0x21cbf9f2, 0x293e1710, 0x10fe3007, 0xefc261d8, 0x1c774b2c, 0xdce9fe42, - 0xb5f31fb6, 0xeeebcf09, 0xcb1fc124, 0x9eb1e5c3, 0x96560dca, 0x0fe1c8e7, - 0x1b0e9079, 0x8ef9e73e, 0x3c958e8c, 0x1ff2dec8, 0xf853225b, 0x4f2c2a7d, - 0xc7c37cb3, 0x8430af3c, 0xe002612f, 0x7982fda9, 0xec1c0aa5, 0xd42b8700, - 0xf3e1bcf9, 0xdf79834c, 0x3f805f1c, 0x7cc1d390, 0x041f5a5d, 0xe13e9bf9, - 0x0f230910, 0x3cb3d73a, 0xfc394ee0, 0x7e4accf7, 0x4f9eb36f, 0xebcb7d7d, - 0xbffad8bd, 0x221a7c2f, 0x1eae381d, 0xc3e71d4e, 0x9ce3f1cb, 0xf7f07fef, - 0xfe826521, 0x81cf93fb, 0xda1bcb1e, 0x899f788d, 0xfdf13fe2, 0x5a78f076, - 0xf31126c7, 0x9bea6b3e, 0xe5eb8e51, 0x273f0545, 0x1bf7afd1, 0x468adebe, - 0xb63a27a6, 0x3a167d5a, 0xaf5bc74e, 0x6c573d21, 0xd3bcc76e, 0x18af75bd, - 0xcbe754db, 0xaa7c27a0, 0xbcbc77f5, 0x6dca0c6b, 0x7e98bf7e, 0x9b14631e, - 0xfc29b2a7, 0xcf9b953c, 0xec59e66a, 0x2dda37ad, 0xb4ef9f17, 0xc609bae4, - 0xeccadd3b, 0xe2f5d3a5, 0xf9985f0c, 0x49bd714f, 0x0f3b2d48, 0xef12faa5, - 0x7bb2b359, 0x245b44d5, 0xad4b5fda, 0xf7470e13, 0x7988d283, 0x79aa2b2f, - 0xce7dcc9e, 0x0af7c024, 0xd604d5eb, 0xabe012bb, 0xbb65e3f2, 0x26dd809b, - 0xa867e527, 0xf59459cf, 0x8819fb1b, 0xa5ff854f, 0xe08919d6, 0x3bc9127f, - 0x5d71d608, 0xe812d7ca, 0x8b0f56bf, 0x47f393df, 0x56f3c187, 0x8e27bec9, - 0x553adb8e, 0xb5e84270, 0x34fbdd27, 0x2e998671, 0xf8b17ded, 0x5fdd1c0d, - 0xf680d3b7, 0xb7e0d5a0, 0x1ac42ed3, 0x0e849ad1, 0xa43883ac, 0x0214fc04, - 0xf41e21f3, 0xfdc16798, 0xcd4236c8, 0x94e7e853, 0x449ff734, 0xf774904f, - 0xc30390a1, 0x385abd28, 0x39712abd, 0x8e9bfb2b, 0xacf786db, 0x6a91a4c4, - 0x5635df20, 0x4f0dda37, 0xe869fbf0, 0x41e4246f, 0xa74892c4, 0x3a26fefa, - 0x38fbe6af, 0x1ea6af3a, 0xe3d6d2e3, 0xc2c74866, 0xbe3897e9, 0x05a2e98e, - 0xcd3310e1, 0x796bf8a0, 0xeb4213c3, 0x4e27898e, 0x6b5fb43f, 0x2801efc1, - 0xfbd5797b, 0xebb458b0, 0xc8d3eba6, 0x36b4e889, 0x53ad81af, 0x1c4edcf3, - 0xa5dfee02, 0xabd74e7d, 0x714617a9, 0x09112779, 0xdcc59de4, 0xbbfc384a, - 0x5fbef035, 0x013837da, 0x5fb843f0, 0xcf9025ed, 0x41f7cd12, 0xb7f4d7e7, - 0xcd807443, 0x0c871daf, 0x43bfabb2, 0xbfeb9cbd, 0x25fc9651, 0x329e9451, - 0x62615687, 0x49125676, 0x9ba5efc3, 0x4a7ca1fa, 0x79839659, 0xa32d4227, - 0x086b61ab, 0x00b0cdf2, 0x3fba9bcf, 0x9351ed12, 0xd2237899, 0xe2367be1, - 0x1661d395, 0x7043cf1f, 0xa1d0372c, 0xd69455a4, 0x814d7be8, 0x8a42c31c, - 0xa2687a84, 0xb94657e3, 0x9f28a3aa, 0x2774ccd6, 0xf6c2c619, 0x3bb95ede, - 0x52f6b90b, 0xaa1a0888, 0x1969eef7, 0xef04228c, 0xbdde20f1, 0x6bc6807b, - 0xec153a95, 0x6d7f9df0, 0x32eeb064, 0x9b5f7953, 0x3e8feac2, 0xdc2577b4, - 0xcf6e9337, 0x49f6147f, 0x7851f6cc, 0xd58fe5de, 0x9bddf3dc, 0x39d6517e, - 0x173f8372, 0x3abe05ee, 0x1df5eec0, 0x777e0d6e, 0xa3787a8f, 0xd1fba945, - 0xd86fc88f, 0xbcad728f, 0x1bb63f7e, 0xa1cb4ea0, 0x81dcfe71, 0x472f9f74, - 0x74969a1d, 0xa1af1d29, 0xd93e0930, 0xd0ea357f, 0x30eef81e, 0x578f8704, - 0x82141eee, 0xc3fcb483, 0xd5932d3d, 0x0f70f870, 0x857d21d8, 0x7d0fabc3, - 0xebe87088, 0x6c5d29be, 0x935cbc07, 0xd6fbc06d, 0xc16c38ae, 0x45fd0af8, - 0xe3e23ea0, 0xbbe5efac, 0xa11fc56c, 0xd354ece3, 0x429ef297, 0x4dd1bd57, - 0x628fb12a, 0xe96a6cf7, 0xf5ca2ba7, 0x25abac36, 0x358f75ca, 0xf78ff71e, - 0x76e35c00, 0x0b8ea73b, 0xb8b135d1, 0xeefdc1c7, 0x5bf32ca3, 0xf2f254a3, - 0x6225ec9a, 0x81c9c40a, 0xfb43e217, 0x8de65f89, 0x19f74118, 0xde6032ef, - 0xfb8b28fc, 0x2b63cc20, 0x7721f808, 0x1ee20aec, 0xbe218827, 0xd9abe650, - 0x9af5fcc1, 0x396f8342, 0x6015ef3b, 0xb47d10bc, 0xc023e8e9, 0x1db1a3e8, - 0xa9a2a3e9, 0x6347d19d, 0x06644e75, 0x3f03373b, 0xc60496bf, 0xa23bde02, - 0x51269abe, 0x151a1ffa, 0x91ba01a8, 0xe5a6e7bd, 0x3d708a5d, 0x7c3f161d, - 0x7abeca7d, 0x4b6d6fc3, 0xe06943ca, 0xe033ee4f, 0x37029779, 0x858c5fa5, - 0x58b6c5e5, 0xfc035fdd, 0xedb4272a, 0x6d6fed85, 0x36f31f79, 0xd86efb6c, - 0x66dbef05, 0x42390c53, 0x5beed6f3, 0xd767f78e, 0xd87dd806, 0x05e024d1, - 0x3c3bdebd, 0xe104ff18, 0x1a4f7601, 0xf91da3c0, 0x5eff1365, 0x7051ab2c, - 0x1a1f9e81, 0x890deec5, 0xebf3b0b4, 0xd7111621, 0xcec2c439, 0xbdf7e259, - 0x95bf8225, 0xfb01bf75, 0xa69943c7, 0xbcfdffde, 0xaf89a4bf, 0xe854f82b, - 0x28d24a89, 0x4ce47fb8, 0xa2d13b8c, 0xa8d89fa1, 0xca78d514, 0x88788f7b, - 0x47aa0ef3, 0xff3dd8af, 0x94abd02e, 0xfc00be7e, 0x968dfb04, 0x4a6e0023, - 0x70cfa07f, 0x0defa1f8, 0x1e60f987, 0xecb617b0, 0x3de2225e, 0x6bc47d1a, - 0x491bdc26, 0x914667fb, 0xfdf4adaa, 0x425a68cc, 0x13d78e3d, 0x2b207d79, - 0x1a713f53, 0x3d7cfa04, 0xb64ebb8f, 0xc931fcf0, 0xd186ea3e, 0x5c766750, - 0xea245256, 0xe16f8505, 0xb738080e, 0x75f9f896, 0x00c5204a, 0x58f85378, - 0x56fc180a, 0x2452b4aa, 0x18f20187, 0x7dd0f1de, 0x9dcbbd4b, 0xdf652fab, - 0xcf9fea71, 0xc1f9ebe4, 0x3d17f5f6, 0x099eefbe, 0xb7372df0, 0xad03723d, - 0x0e7a5c57, 0x479707cf, 0xa1795c55, 0xebf42f7b, 0xdbfce77f, 0x4d874051, - 0x7ec298df, 0xe1c3550f, 0xc029e2d6, 0xbdf932f7, 0xc951242e, 0xb1e55633, - 0xcbb71b42, 0xf8299510, 0xffaced1c, 0xf8081140, 0xf0b14af4, 0x9e32547e, - 0xe5d14e1f, 0x9f87fead, 0xc132f9c5, 0x71250030, 0xcf3628c9, 0x324ecc37, - 0x9ce0ffd3, 0x173f1a69, 0xaf72477b, 0xdef1d2b0, 0x357cec21, 0x19aaae33, - 0xc6c4c4ea, 0xfbda26cf, 0x6b13320a, 0xb8c2c6a7, 0xdf18c9d1, 0xdaeb35ca, - 0xc812bd53, 0x8c9a9269, 0x88d38979, 0x7a633eca, 0x08eeed03, 0xe3902eba, - 0x742c8cd7, 0xe7ede54e, 0x4d43ffe8, 0x2a99f6e4, 0xc72ae37f, 0x8d54e75c, - 0xf78b52fd, 0x9fe9fd01, 0xf2e1ede2, 0xfce33e2c, 0x77c9e2df, 0x1eb3f9c2, - 0xe10e399e, 0x27a3ab7e, 0xd470f5dc, 0xab815dc3, 0x9fd98e1e, 0x86c6a738, - 0x2e1e9381, 0x48ed48d3, 0xdc0a63d0, 0xc77970f5, 0x9de2e8cc, 0xabde1334, - 0xe0c48ef8, 0x23350ef8, 0x9ba41ea1, 0x01ef1168, 0xf5e28cce, 0xbab04737, - 0x64a8ef82, 0xae1eb7c4, 0xc666387a, 0x58e3f7f1, 0x2f00bdff, 0xe202e509, - 0xcc9ba147, 0x31ddaad4, 0xec507a2a, 0x2e1c69eb, 0xfb46bed4, 0x8ade3739, - 0xafb02671, 0xe08425a7, 0xd6ce5b96, 0xf2dc3b95, 0xf4a9f83c, 0x72bfbc75, - 0xff3fe10a, 0xca2f3c14, 0xce0555e4, 0xdad1be53, 0xa69ad3c9, 0xc338829f, - 0x7efb9350, 0x1080cfa0, 0x1475e783, 0x707447ee, 0xd767bed7, 0xf870f5d6, - 0xb131fc03, 0x3a14bc27, 0xe3c2c0fb, 0x20c8034e, 0xbcc797b0, 0xf20d1196, - 0x86c5349b, 0x715c4b8d, 0x0e383f38, 0x63a457a7, 0xcf83b881, 0x423fa9ed, - 0x5aa3ed8e, 0x36c72552, 0x96d3ee8b, 0x4c729ef8, 0x8e64d3c1, 0xbbc4c987, - 0x934be20b, 0xd045f489, 0xed0e481f, 0xe7d95bbf, 0xf6103240, 0xc1c58379, - 0x67df3fe4, 0xbcd4df70, 0xf8b3f984, 0x0b6659fc, 0x02435f7e, 0xce104752, - 0x91df7829, 0x5a1b18d7, 0x4fbf9287, 0x66115486, 0x7bc3cdcf, 0xc85c29ae, - 0x75a15177, 0x8482ac98, 0x75f0fdf7, 0x7b33a99c, 0x5bad8f21, 0x9d814774, - 0x1bec21d7, 0xfc93fb83, 0xe9ff4023, 0xee35cfdb, 0xda7680ae, 0xf1fb08af, - 0x59162ff5, 0xc3b021fc, 0xb93e7be4, 0xb2953b77, 0x8509ea35, 0xfbe0b37e, - 0xde81cbd4, 0xdd6103fd, 0xd1d54053, 0xf659e772, 0x6376431d, 0xecf304ba, - 0xff7966e9, 0x8125c439, 0xdfa7ab7d, 0xa1a74bef, 0x08604578, 0x5d8a29f8, - 0x1eead536, 0x57cfa569, 0x9b66eff3, 0x05188ece, 0xf4c1f978, 0x4f4b4074, - 0xba511d0a, 0xecf00f1a, 0x69fcf8ca, 0xcddfc730, 0x7a009738, 0x43dfb151, - 0x026b8a76, 0x3b37a7ac, 0x3dd5897e, 0x3b017ac5, 0x2e67b15e, 0xdd9087e6, - 0x74a641d4, 0xcbc71b74, 0xccab733c, 0x600fcdee, 0x48eafdfe, 0x473b5ee5, - 0xb791d824, 0x54d94ead, 0xd586e707, 0x6b7efe2c, 0x83f1ac95, 0x86dd90dd, - 0x66fbb3ef, 0x6da65f6f, 0xfe604cff, 0xfb57a17e, 0x3412589c, 0x9cf6edf7, - 0xc035e0d7, 0x3123c3bc, 0xaf3f413f, 0x79fa7f7e, 0xe6adf3f5, 0x636ad57e, - 0xcaa748ed, 0x6560592e, 0xaaf750f6, 0xcae0ebc7, 0xe7e0deba, 0x93480f36, - 0xb5abf754, 0x082c8ead, 0x328c6f77, 0x79ef029e, 0x00e2cfc4, 0xc3dff255, - 0xe59b83dd, 0xde81f166, 0x98161de6, 0xe1a0768a, 0xf608bf49, 0x4100b0fc, - 0xe02b3bfb, 0xf8d02c32, 0xee4fcc01, 0xbdc007e1, 0xd65eb426, 0x01f98bb0, - 0x4fe8d5f5, 0x027f5194, 0x387accf4, 0x17c01e9b, 0x41fe8694, 0xfc85dfd0, - 0xcfb82ca9, 0x12c3fb92, 0x5ad497a5, 0xf5a37fd6, 0x096ae35d, 0x927755fc, - 0xe363294c, 0x98d7efc3, 0x93555fa9, 0xf508224c, 0xf8785eab, 0xc06be9fd, - 0x09758e5f, 0xad287f70, 0xf7fa58d7, 0xf8debfdd, 0xb81afef0, 0x65fa946f, - 0x7f2aaceb, 0x78fe37b7, 0x0b918c04, 0x3dba47f0, 0xa1f0237f, 0x8a68af12, - 0x111f7ce0, 0x8068bba4, 0x57274297, 0x7e8f9b2f, 0xe725c445, 0x589e4087, - 0x16ffc716, 0x46c38f2b, 0x129ff7b1, 0xbf905bdd, 0x023f3adf, 0x8cefcbe2, - 0x5cfe8a3c, 0xe7c59593, 0xd04a79f7, 0xb9f0527e, 0x3f702acb, 0xf8103fc9, - 0xcdf1daed, 0x6497e071, 0x43de02c9, 0x9efb24da, 0x7900cf4c, 0x82bedb34, - 0xa26b296e, 0x6b13bf11, 0xbc0ff08a, 0x35a7655b, 0x9b4cfbf1, 0xa81deece, - 0x661e63ce, 0x4565ddcd, 0x308bf3fa, 0xeec6567e, 0x7befa0c3, 0xfd212fd3, - 0x7f4012e1, 0x13fbf390, 0x61a8fcf0, 0x42e20d8f, 0x827efc1d, 0x09cd0d33, - 0xbe5969f3, 0xf0362fe5, 0x70e7ded7, 0xe2b52338, 0xdb654a3d, 0x83ffbc44, - 0x0b709bce, 0x161ba7c4, 0xf7efb264, 0x8a6777d8, 0x67ff4cfe, 0x167cc0f3, - 0xc8efc434, 0xb2727b14, 0xf583ebd9, 0x188b5535, 0xbbac9e2f, 0xbf0a6c37, - 0x5f6f4c37, 0x712ab49e, 0x87cc04e9, 0xf3676a5a, 0x594fc6f4, 0x9f12c4df, - 0x24b2df8a, 0xcfeb08bf, 0xc08126fa, 0x5a679715, 0x03c89e52, 0xcec89e3f, - 0x44ac30e1, 0xcafda376, 0x6fe89fcf, 0xbe43dc37, 0x6cde5793, 0x4aeb3738, - 0xfdfb6624, 0x77600997, 0xe0b1fbb9, 0x8a07d322, 0x1be5377d, 0x6f557c6d, - 0x8d34e6e7, 0x41207fbd, 0xa77fb378, 0x55eec022, 0x06ff61eb, 0x7bb587a6, - 0xe10c7909, 0xf52dbe90, 0x2947b81a, 0x3b068ffd, 0x7c02dbcc, 0x3cf80f11, - 0x54fcf787, 0xd08dff10, 0xda20d15e, 0x927eb0fd, 0x95f01971, 0x70283762, - 0x6cdf3c69, 0x91d7431e, 0x5f60d675, 0x3378874e, 0xcffa05f0, 0x2fbcfee3, - 0x5357f40e, 0x8273c240, 0xa3bbb3ac, 0x60e4a816, 0x3e0379d3, 0x5bfcf37f, - 0xd881e7da, 0x2dbde0cb, 0xef17e606, 0x28f7fbde, 0x9e6f4b90, 0x82f1c6ef, - 0xbb4f4376, 0x6b91e118, 0x67718315, 0xc44c5db5, 0xb79003ac, 0xaa9a2d35, - 0xbb77a131, 0x7213fb37, 0xb4f495bf, 0x1ec0721f, 0x11d8c311, 0x3e74ce1c, - 0x6f48f809, 0xe36e5c57, 0x24c1e6f1, 0x6ca3ee1d, 0x18b71f3c, 0x8a6e1fbf, - 0x7d472fb2, 0xaea5eccc, 0xbf1fa7dd, 0x13ef9e06, 0xe711fdd9, 0xb7a7e445, - 0xda1e2e76, 0x2a5be2a6, 0x5f4f1139, 0xf9db3ff5, 0xd5ffed06, 0x4716489e, - 0xa9979c97, 0xf50877bf, 0xf97871f7, 0x38f3b007, 0xd7b800ef, 0x2fdb07e9, - 0xfafc3d1d, 0xc3da1b3c, 0x1ea0e981, 0x376bac46, 0xac5bfe02, 0x90d9d7f9, - 0x00a3eadf, 0x33925e2e, 0xf3804c90, 0x7403927a, 0x7626a815, 0xb5b627f0, - 0x97800c18, 0x98c98d8c, 0x9f89b3a7, 0xafaa2e57, 0xe8ab2635, 0xef3f1162, - 0x877b293a, 0x1f9eaac4, 0x72f931b0, 0x6fe94f72, 0x43e34f30, 0xc61e1913, - 0x31b06cde, 0xd18afb7d, 0xe866cd7b, 0xdf80c477, 0xfbdeed0d, 0xcfb85efa, - 0xc761d178, 0x3dff8858, 0xbf607362, 0x6a9b7dc6, 0xf1b7cf20, 0x5452d013, - 0x14286caf, 0x37de740d, 0xefc58388, 0x1fd0180e, 0x893dc60f, 0xf9f60e2b, - 0x1bcf5f10, 0xf9cd062d, 0xdefc1bd8, 0x326d7bdd, 0x89b12fb6, 0x2dadc788, - 0x37a07139, 0xbbeeac5a, 0x8e2fa06d, 0x12c0d5b5, 0x629f7894, 0xb03c4daf, - 0xf4d19af5, 0x061d89cf, 0x71dba03b, 0xf61179e0, 0x484938eb, 0xd87a408c, - 0x8f3c746f, 0x3a37bc7a, 0x1d7478d8, 0x2abf016f, 0xff9aa7f0, 0x7f5a34a1, - 0x858a55a3, 0xfe052efc, 0xf9943eca, 0xb5c4f51d, 0xe4ac82de, 0xb8817ada, - 0x3a5f92b3, 0x7f944ece, 0xd2e9012f, 0x6a3d7368, 0xda0ef663, 0x30f727d7, - 0xae15e8bb, 0xe1524947, 0x829f8050, 0x8b1b7aa7, 0xe9eb2a33, 0xdbdffe6d, - 0xca549e98, 0x9bd74bef, 0xe9178764, 0x0fcb1b66, 0xe6fd7877, 0x6b23c854, - 0xcf7fc54c, 0xfb679549, 0x93e7a47b, 0x1b057bda, 0xf8060cdb, 0x8762ac0e, - 0x6de68310, 0x20ebed1f, 0x48f5499d, 0x09878d7f, 0xdd6971f2, 0x48ee2c9d, - 0x7fbf0de5, 0x81d1cf0d, 0x7a79f87f, 0x1396817f, 0x18afd69b, 0xdbf5f088, - 0x7042af80, 0x65037ca2, 0xe811ad55, 0x5652d175, 0xe973f316, 0xc8dd6b45, - 0x58eb459f, 0x5b1ee17e, 0x0ce7ae32, 0x886257a7, 0x27f9001c, 0x657f0e2e, - 0x6e9c79dd, 0xd13c354f, 0xfa52f30c, 0x73e013fa, 0x4f63e352, 0x7a1572c3, - 0xc641b53d, 0xb5224a71, 0x7cadf6e7, 0x18076dbc, 0x20dc4fbd, 0x5ffdc0e7, - 0x0ec4bd13, 0x3637ec71, 0x7e41146c, 0x9cf401bf, 0xf41cf8cc, 0x0f3dc9ed, - 0xf402fd46, 0x4081bb5c, 0x2315fcbc, 0xe2a2d929, 0x5febdd8b, 0x696ff0d5, - 0x1835f55d, 0x158b6f97, 0x7c2bce40, 0x15fdc0ab, 0xe42af3a3, 0xfc74ebff, - 0x2fbd953f, 0xdfb03b47, 0x9fff9c13, 0x9ff94198, 0x10d98a3e, 0xaf38c023, - 0x07dfc318, 0xa40ff5f7, 0x6d5ca0bf, 0xbf5721eb, 0xcdb57266, 0xafe74a96, - 0xe31bb6b8, 0x71f5c10c, 0xaa6279ba, 0x02c93742, 0x6296bfc0, 0x8bc01870, - 0x99e815c2, 0xdfb7cdda, 0xd95c8690, 0x0f39e122, 0xf9e2473f, 0x0277ca1f, - 0xe486bf0a, 0x6eb7c299, 0xd5d83473, 0x8056ab53, 0xe7971f5d, 0x253cfa45, - 0x52c687b8, 0xf80a767d, 0x383c8c38, 0x57c7e5c1, 0xf762fbb2, 0x7a000fee, - 0x221ea12e, 0x13ac87ec, 0xa51780ec, 0xdd8eb1dd, 0x5a3c3ac3, 0x2bbf9cd0, - 0xef0c1ff5, 0x41fb8f40, 0x7c634787, 0x3c84603a, 0xa63e11d5, 0x839088c7, - 0x570c40fc, 0x5b3e000f, 0xcdd7f544, 0x4a75fd2a, 0x553a45ae, 0x347970e0, - 0xc55f5f93, 0x95ff7db0, 0xe21585d3, 0x2f73aa85, 0x024890ea, 0x605167e3, - 0xf8c22e7c, 0xba4cf6a7, 0xdafde90a, 0x076ef4f0, 0xfe162aff, 0x48f5a73d, - 0xec33319f, 0x13cb1df8, 0x46223392, 0xb0f91f63, 0x57f1bddc, 0xfd01d7e8, - 0x46f7bf02, 0xff4025ff, 0xfbdd0c24, 0xf0abdd28, 0xa501d0a7, 0x55a26b8b, - 0x174f41f2, 0x02a379ca, 0xe7745797, 0x33474f95, 0x9780b079, 0x66f25e8e, - 0x60fcfd94, 0x81ec9f3c, 0xcf0cf9e7, 0x7c02be21, 0x67e1f22b, 0x3dafe117, - 0xaf6c76d1, 0xe60174f9, 0x73f2d4a9, 0x9f3e7aab, 0xd1a5eeb2, 0x4b7ce682, - 0xca34ee7f, 0x5a2bbee2, 0x48ea3e77, 0x34c7d10b, 0xd92ecf6e, 0xff73c268, - 0x7802d02d, 0xbdfecddb, 0xbb3de56c, 0x0a4f0d44, 0x4cd115ea, 0xe1f42b8e, - 0xc3246658, 0x55f2ffa8, 0xc86ee172, 0xab59f9ff, 0xdd346f37, 0x77a316c7, - 0x07e8b5f6, 0xf182af38, 0xd833caaf, 0xc6241f21, 0xde201765, 0x7c0a2481, - 0x33cd8fb8, 0x1979d52e, 0xe70ec9fa, 0x0f079038, 0xf8297c73, 0x9bd0e055, - 0xaf0deb9e, 0xe27c387b, 0x8e5ebb79, 0x9efe7314, 0x5c5dfbc2, 0xe045788e, - 0x2f711b27, 0x59fd6117, 0xe505fe4c, 0x73c11648, 0x727597c9, 0x5e9fe5e4, - 0x91acbc8e, 0xc2da1323, 0x0bfa11ca, 0x1bf1ffcb, 0x4b1da216, 0x63b7870e, - 0x3d334677, 0x93fa0f1c, 0xb2f78bf6, 0x3987def3, 0xc48a52dd, 0x0ddac9bc, - 0x5713cc26, 0x366d90e4, 0xaf7f81c9, 0x16fa06d9, 0x1f76cd7a, 0xc5e70c9e, - 0x9c074649, 0x03929f5f, 0xd453f788, 0xfa45af01, 0xc7fbc7c8, 0x0223c8c3, - 0x47ef12f1, 0x9cefd083, 0x9f213626, 0x5046992c, 0x78deee7f, 0x4955d205, - 0x74008a5e, 0x23175a5b, 0x54ec7b40, 0x94e401bb, 0x962b8fb2, 0x71b0c819, - 0xd40707c8, 0x6f0ae472, 0xcdbbfe15, 0x49dce343, 0x47210c72, 0x33fb3d1f, - 0x8da8bc75, 0x22f1d5d6, 0xfbe07f5a, 0x468e8bc4, 0x78801e07, 0xae6c3fd1, - 0x94779876, 0xea28ff25, 0x912ac4b7, 0xc5d6e4a8, 0x4a1fb7ec, 0x2e3c952f, - 0x34a95a45, 0x81c4d04e, 0x6073ab6f, 0x582bf81c, 0xe380c54f, 0x7870c34f, - 0x7b5846af, 0x1fa3ad9b, 0x13e40b97, 0x97e8f882, 0xfc42255f, 0x063b9145, - 0x2fe2ac7b, 0xa197900b, 0x037fdbf0, 0xd7b57d1c, 0x00008000, 0x00088b1f, - 0x00000000, 0x7dcdff00, 0xd5947809, 0xe77df0d5, 0x24cb2d9d, 0x7642c993, - 0x03bbec26, 0x4eb1ab09, 0x04906008, 0x8d441007, 0xb0900938, 0xd2910364, - 0x208196d6, 0x2b188a06, 0x0eb154b5, 0x4551fa14, 0xdb1ab61b, 0x1a4013a0, - 0xad563414, 0x61a5afd8, 0x80891d91, 0xe58ad3fd, 0x7bdce73b, 0x264ef333, - 0xe79f6a02, 0xcdcf0f0f, 0xcf7bde5d, 0x773dfb3d, 0x79632d49, 0x9b19223b, - 0xed50b390, 0xccc9a906, 0x831b163c, 0x43632f1f, 0x087a3e79, 0x6b9859e6, - 0xf26b6320, 0x01de7975, 0x9fc75d8c, 0xa269fd3b, 0x678e3e15, 0x30d6fe6c, - 0xb53349eb, 0x7fe1d767, 0x268c5d79, 0x649f595f, 0x9fc7d93d, 0x24bf8f9f, - 0x4c33ffc1, 0x2b1812cf, 0xe1a7e263, 0x70ffdfcb, 0xdfc7b418, 0x54dec655, - 0x805689dd, 0x12dcdca7, 0xd8ceddd5, 0x13c7f933, 0x52d491dc, 0x223ddf87, - 0xb97178c6, 0x71debde3, 0x55de798c, 0x0fc816d9, 0x4a3d1936, 0x64e2fc34, - 0xe8826b76, 0x06947e0f, 0x041967c5, 0x55437ff9, 0xfe97632c, 0xc5f4a3ad, - 0x32f2b89f, 0x7a8afbe0, 0xb439639d, 0x185068ab, 0xd1cc62cb, 0x19cd7995, - 0x4785d58c, 0x5fd0620d, 0xa748bece, 0x292fca01, 0x8329af66, 0x870800d1, - 0xa23fc241, 0xd41b7d35, 0xd8983757, 0xca5ec86a, 0xe119ac61, 0xd9a23bd5, - 0x077e3f00, 0x0fa67e1d, 0x6bca00cc, 0x630b2e1d, 0xff78c29b, 0x7b64c29b, - 0xb483347b, 0xecd192db, 0xd7a7c004, 0xf40d1633, 0x6983c481, 0x036e92f6, - 0x1f3099f4, 0x8018f33d, 0x3eadd94e, 0xadd2f115, 0x9163aed5, 0xadf471fe, - 0x4ddbe68c, 0x6039d76f, 0xf7813afc, 0x543b4d9d, 0xd873e03d, 0x156ada98, - 0xf728d2d2, 0xa8f3c458, 0x2c6aaaec, 0xa8f7cd8f, 0xa59f686e, 0x00b3ed54, - 0xe678d85e, 0xcce502d8, 0x848f8307, 0x18d616fa, 0x2398d905, 0x2828ce2d, - 0xd9c6751f, 0x1de60038, 0xf60a62ed, 0x1a32d8c7, 0xcba45fbf, 0x38b2fd85, - 0xfd0052a7, 0x2307fb0c, 0x767ec8bc, 0xec568d36, 0xf35c6f00, 0xc01ec518, - 0xe24d305f, 0xfeccf5ab, 0x73d7ec53, 0xba40e748, 0x7398ebda, 0xfaefb423, - 0x2c31bf72, 0xd2bedfca, 0xb778d0aa, 0x46b9ddbb, 0xd879f346, 0x9c8fdf0a, - 0x0067ddee, 0xf1cf8678, 0x03da33ec, 0x519733e6, 0x1e2d297f, 0x11d2479a, - 0x8ba60e77, 0xcfd4312d, 0xc6be33a8, 0x4baed001, 0xca07cc15, 0x543f9ad3, - 0x5569af10, 0x71d20acd, 0x825ed367, 0x3f79b537, 0xea11814f, 0x7201dd20, - 0x8f301755, 0xcd1d16c5, 0xa145b163, 0x99c5e574, 0x7fa82e89, 0x6c5eeac4, - 0xc79fea19, 0x62771cca, 0xbebff415, 0x7cfb5ba9, 0xb7bc027b, 0x278867c1, - 0xab72dfd9, 0xb269fa91, 0xf3847fb8, 0x72de9cab, 0x476f7900, 0x48a39fd3, - 0x88e21a2e, 0x8e8709be, 0x96123d13, 0x78a0ce00, 0x0a85a1fd, 0x85f5aa83, - 0x23a53340, 0xddb8279e, 0x8899318e, 0xf89f806f, 0x09311ac7, 0x8c62f2f8, - 0x91c706bb, 0xd91427ed, 0xb45f5022, 0xcf77c5e7, 0x598e652e, 0xfbcf003d, - 0x6eb2778b, 0x12f77748, 0xbb7b7ba4, 0x21878f81, 0xb38b313f, 0xa4bbfb16, - 0xce38e9b0, 0xf942984b, 0x979e064b, 0x95abfaf8, 0xeb11ebe3, 0x7896c5a4, - 0xf02b278e, 0xbc614bf1, 0x7a1eb05d, 0xb3bfcad7, 0xcd617e0b, 0x1e705f9c, - 0xbb64bfa8, 0xdbdfa2dd, 0x3d5cee9d, 0x08cd93e7, 0xde11c8e7, 0xc3b7c87d, - 0x90fb3cf3, 0xe098d3ff, 0x27ce3c93, 0xcfbefcc1, 0x467ea36a, 0x8865699d, - 0xb9852cf7, 0xd32ee902, 0xa1ae10d7, 0x89a3dfc8, 0xb61e407f, 0x52c378e3, - 0x800354aa, 0x13acc712, 0xdec67758, 0x5da9dab6, 0x3ee708e6, 0xd3ab37e4, - 0x207cf245, 0x2be54ac2, 0xc07f3833, 0xfc407ff7, 0x2ed3cb05, 0x7e01a394, - 0x7e438a39, 0x8fc8ec8c, 0xbcf013bf, 0x63a5e42d, 0x613feeff, 0x3acd71ff, - 0x0c9d02a7, 0x65e9123f, 0xa2f874d0, 0x8fe1152a, 0x00ffc063, 0x358e6da0, - 0xa52ce507, 0x5d20a1cc, 0x875c229b, 0x230fd4ad, 0x4732b9bd, 0xef86ade7, - 0x893b46e6, 0x3ed8df7e, 0x366667ec, 0xc01f6fcc, 0xe115fc1e, 0xb6b07b03, - 0x6ff4f508, 0x3d4469ff, 0xd7f2976a, 0x38a22434, 0x48ae3f80, 0xf7a7e0bd, - 0x410bd271, 0x73d60ef4, 0xebf6f4c1, 0x039ead05, 0xf4e05d7c, 0x9f226770, - 0x522f35c5, 0xead07eb9, 0xd1e8ceb5, 0x3a083f41, 0x7e708a5c, 0x0c5cf881, - 0x7ae38832, 0x583eb346, 0x0e1d99de, 0x76a4898b, 0x1c3b45ff, 0xd1df1316, - 0xadcceb0e, 0x47c01507, 0x576a8379, 0x8fd50a61, 0xff489cd9, 0x8714eb17, - 0x41a4e509, 0x71787e25, 0x4bd93865, 0xbb67ef09, 0xdbb107a3, 0xcff21520, - 0x8ec9dddc, 0xf188c656, 0xf18790ed, 0xd679592f, 0xc5277568, 0x1793e804, - 0x4308be1b, 0x644ff73c, 0x62c64e03, 0x0ed6a70b, 0xf0290883, 0x537f09bd, - 0x6b83af10, 0x69ac1454, 0x95269dee, 0xfb1dd6e8, 0xfe5ace1b, 0xbd700d9c, - 0xceb46dbc, 0xf537c81d, 0x05ec6757, 0xb8232bf8, 0xf7b4be5d, 0x33e42f5a, - 0x92f77f59, 0x3f7bd262, 0x13192b07, 0xeedf1fa0, 0x61eb8273, 0xd53d6856, - 0x2a76871f, 0x850023d7, 0x7a3ee651, 0x70d427f4, 0x27f5aa87, 0x7baa3988, - 0x7f107e02, 0xbf84e18d, 0x77209eea, 0x48e70419, 0xc5bf7fec, 0xfca092c8, - 0xb623c80a, 0x037f7093, 0xe2074778, 0xaa6f0fd1, 0xe08454f5, 0x5f0fd50b, - 0x0e905d3b, 0xd16abfd0, 0xb12e3cd3, 0xb3d20770, 0x4864e8ce, 0xe151cf7f, - 0x55ba081f, 0xd4bb9e08, 0x1b88f430, 0x91e2f7e6, 0x7f7e0754, 0x984afea9, - 0x46fd122e, 0x979c14f7, 0x851ad69a, 0xc35f70f6, 0x032dbe95, 0xc54dbf48, - 0x4e872bf2, 0xbe03dcd8, 0x8466fcd1, 0x7e7687a6, 0x9ac8fa95, 0x6150ff40, - 0x7cc17e7c, 0xfe3434a4, 0xf244194b, 0x7a1f50c7, 0x1ab799d2, 0xa072bde6, - 0x997ba7e0, 0x983ee51d, 0xabab46de, 0x6e402622, 0xaaed15ff, 0x9c70b842, - 0xcf342194, 0x741f9885, 0x41a66678, 0xc31bf387, 0x7f4a6ed0, 0xb0effd0f, - 0x4eff7e21, 0xfe7dafce, 0x3a0daf3d, 0x3fbe68c4, 0xf80071c6, 0xaf803ae5, - 0xeac18c12, 0xfb79c08c, 0x62e51e88, 0x48e6e57e, 0x61f30a9f, 0x5a170cbb, - 0xd6e81ea4, 0x4fa07e11, 0x19e7c20d, 0x46e238ed, 0xd235fefa, 0xd1f88d51, - 0x5fd15b37, 0xc6acf985, 0x28a2367a, 0x2fdfe711, 0xf505b9d2, 0x18cb4bfc, - 0x57a5f3f1, 0x4c137798, 0x1d7efb76, 0xd646cbf1, 0x9fbef88f, 0x570cf2ee, - 0x3af3c924, 0xb9ab3b84, 0xb77a8756, 0x43aed7a7, 0xb9b7da7d, 0x3e23a74e, - 0x8622ff70, 0x5799e4fc, 0xff5f00f4, 0x37ea556d, 0x686f07e4, 0xaf40ef7e, - 0x92f481cd, 0x7c16cb78, 0x43788d90, 0xbfaad083, 0xe3f662d0, 0x52c3e80d, - 0x63fb1d6c, 0xf11d25ac, 0xe9faf8d4, 0x5fd02d5e, 0x67a71bc5, 0xfe2a5e20, - 0x18262260, 0xd1be87f3, 0xe59fefc8, 0x2e67f684, 0xe872ad2c, 0x257a9fc1, - 0x85d91ba6, 0x446cd632, 0x6ebca13f, 0xa01f4381, 0x76ffa5cf, 0x8f9cd0c8, - 0xaa1a1ffd, 0xe78065b2, 0x5de18e2b, 0xd13b0858, 0xbfa12fee, 0x472fb006, - 0xafcf11d8, 0xff734567, 0x20f646d1, 0xa5a1fdb8, 0x7a631c73, 0xa1dfde74, - 0xbdd361c1, 0x907e7df0, 0x8634741f, 0x18b6b5db, 0x2141876e, 0x8bce113b, - 0x3d78b7bf, 0xc8717450, 0xfd0c5147, 0x641f5dcc, 0x2e8f807a, 0xfe47e6b2, - 0x35767288, 0xf971d692, 0x5cca3f83, 0xe5cbf166, 0xdcf8231d, 0x70ed78ef, - 0xe7da1d94, 0xe717df6f, 0x1ddfc009, 0x9db57f4c, 0x5c7033af, 0x7d33e346, - 0x07a42f4b, 0x04d9e3fb, 0xaff9a43b, 0xf9c715bf, 0x74874120, 0xdbf4245e, - 0xc028b0ef, 0x525fcedf, 0xf3247c41, 0xe6666de5, 0xebc80d8d, 0x04b88d9b, - 0x648b6f2e, 0x37b7685e, 0x7a4712c6, 0xa3259926, 0x5f14e99e, 0xe0cf8937, - 0x43cf8972, 0xa3a6cf83, 0x2759f15f, 0x1b6f70fe, 0xf7ced76f, 0xd74fc14b, - 0x7ceff3fb, 0x0aec3ea5, 0x8d845df1, 0x638ae9d3, 0xf7f41764, 0x1ebe8df2, - 0xe4ed10d6, 0x4f1832fa, 0x8d2b5f6f, 0xdf7f7ec0, 0x050bca66, 0xfba6de97, - 0x21ca7e76, 0x1fc02a80, 0x53baa6dc, 0x9c1fc26d, 0xbe8af90c, 0xbad1c657, - 0xd08bf25a, 0x4f30777b, 0x306fca23, 0xf77a487f, 0xfadd01b0, 0x296672a3, - 0x318bb748, 0x4237ce76, 0x047ca41e, 0x9d3831e3, 0x50ee6460, 0x62af80eb, - 0x98c35e24, 0x23e1f407, 0xdf640d1b, 0xf8fb5f0f, 0xf7e04cde, 0xd60c1bd3, - 0x9ce430e5, 0x3ea5f617, 0x0673f503, 0xe40aac9b, 0x3d7ddb4f, 0x5f4bee50, - 0x0fc85d50, 0x923c37a7, 0xf3d21330, 0x0065bf20, 0x0346e947, 0xf8d9cf95, - 0x159f9528, 0x42fa5d72, 0x97d47f7c, 0x4eaff787, 0xf9ce3a40, 0x486989ea, - 0x6b46ed97, 0x9690c1ff, 0x631c536d, 0x6f3df002, 0xbf269873, 0xe0e6c75d, - 0x995d243c, 0x47af6ee2, 0xa6d53f13, 0x1f7176fb, 0x04dfd69f, 0xa0aa72ff, - 0x3029c4e3, 0x57a18aef, 0x77dfafc8, 0xc9ec9c20, 0xf92a919b, 0xffc1be8f, - 0x20db9def, 0xde95fb9f, 0xa09dbe41, 0x674158f3, 0xb7a45cb0, 0x9f3ccc4b, - 0xfc9ebafb, 0x4a8b5ccf, 0x91f686f8, 0x7bfea163, 0xf40fbda2, 0x5321ca2c, - 0x848dd7b3, 0x0da36376, 0xf7d0ed0c, 0x19f2f37c, 0xdb3bc9d8, 0x025bc7f4, - 0xd59a33e6, 0x387f41f6, 0xca821987, 0xcf2c7a9d, 0xc7cb6b35, 0x2cfbb8f6, - 0xad630ffa, 0x77c972da, 0xfab4d88f, 0x7381df62, 0xf3009b3f, 0x92a4392b, - 0x7d237cff, 0xafc22efc, 0x5dbf3a47, 0x3bbe0db8, 0xf872b02c, 0x4915e9da, - 0x142357c8, 0xd3acf186, 0xe3cb42d7, 0x665ea41f, 0x7e3edf40, 0xe63816fa, - 0xdc51e7b6, 0xa0b119ef, 0xdff08f3d, 0x7afb1ebc, 0x8d9b753d, 0xed8233c7, - 0xfcdcb046, 0xfe46ecb7, 0x3dd2b7e0, 0x837f4a16, 0x5ced85e9, 0x89eb06ef, - 0xe1213b60, 0xbcb7860a, 0x0fb1a74d, 0x191ea15f, 0x8c27681a, 0xc3be2764, - 0x6d8370f5, 0x30f5c768, 0x2f8431f8, 0xad3d30cf, 0x6adfc1c3, 0x220376c4, - 0x0039b1ed, 0xb76b0ad2, 0x167fb208, 0x405b7ef7, 0xb6ffaa1c, 0x8dea1d5a, - 0x418cf8f6, 0xeb91a71b, 0x9d8477d5, 0x1cfa13a8, 0xceb4abd6, 0x4eee18df, - 0xc9b8e3d4, 0x8c96c746, 0x48f9f88e, 0xcfccefb4, 0xbeac7e95, 0x8fb1fb86, - 0x389a5d58, 0xa893eb19, 0x5fa2fb89, 0xd9edf28e, 0xfcf34e1b, 0x420d7154, - 0xe733d439, 0xf4016ddf, 0xf87036a9, 0x8f89e183, 0x319276e5, 0xb207f917, - 0xd0e8f67c, 0xd5895c7a, 0x679cfb53, 0xff474fef, 0x07c6d3ed, 0x7ebf51d2, - 0xede7141a, 0x169e1e4c, 0xb0a4faf2, 0x2e223123, 0x11ca14f0, 0x9dda41e4, - 0x55fbe1db, 0x57245d4b, 0x9d3a5d3f, 0x2e9667d2, 0xb613faa1, 0x9adf1a0c, - 0x775767f3, 0x35c9d3c0, 0xd989d92a, 0x18af5746, 0x59a4eef8, 0x1385f147, - 0xbb799155, 0xd19cb122, 0xb3f6727a, 0x0278b613, 0x6c277ee2, 0x6743a27a, - 0xfd8f8cf3, 0x9cbdfa66, 0xbda144b5, 0x23d7e76a, 0x2db5ec1d, 0xac7fe316, - 0x55db0125, 0xb6bdcd2a, 0xb7c71d29, 0x2c7c6732, 0xf59197f2, 0x0ba9b947, - 0xb828f6e7, 0xe72c4a5d, 0x1fa1bfc3, 0x8a7efd0b, 0x9e842b76, 0x2f3a0bb1, - 0xb1ed38b4, 0xc922efa4, 0x81b8275f, 0x728cbe5f, 0x60b84776, 0xd313d65d, - 0x7c785d61, 0x2ac5b16e, 0xf0a9c3f8, 0x5fab8e75, 0x5bf8886c, 0x609ef167, - 0x7811de38, 0xc9038e0d, 0x8681c654, 0xbcf9f2c6, 0xe26ab36d, 0x0eff1842, - 0x79f9ff15, 0x1ba3d72c, 0x2a3c5bc3, 0x7c03c3ca, 0xdb25de3d, 0x2b7c60a3, - 0x0736bf25, 0xc5775fe3, 0x2da5b8f2, 0xeb889dcf, 0xa344e4f6, 0x3736e303, - 0xea038f2b, 0xc05f7c9c, 0xd63823ad, 0x7ac27b37, 0xcd095c01, 0xa4231cee, - 0x0d317153, 0xaac2edf8, 0xa0dd2196, 0x6b23211d, 0x9157b87f, 0x92686c8b, - 0x4028f429, 0x6772861a, 0x454f728c, 0x559b0cba, 0xfa718d55, 0xffbe3294, - 0x77715670, 0x9c9f01b5, 0xa43c2b7d, 0xe8225c3f, 0xc9d194cf, 0x36b3fa68, - 0xacae081b, 0x819f3fcd, 0xf9b59f7c, 0xa012bd2e, 0x1ac79687, 0xdf67fe68, - 0xe295d79a, 0x58989f16, 0xea7a10cf, 0x1e5f8287, 0x69d87410, 0x8b7fcd0c, - 0xac6fbb45, 0x55405bcf, 0xe2f9f569, 0x5b3880d8, 0xd265f945, 0xed6393e7, - 0xfaf3ce34, 0x80c903ba, 0x3167e7cf, 0xe68a0787, 0xf148dd6d, 0xbac69dd7, - 0xe4efb8f1, 0xa431d0a9, 0x7f03fefb, 0x7e8c9038, 0x60fb2ce4, 0xbfda23f4, - 0x4ad2f43f, 0x0e7e7f2c, 0x4ff88c1b, 0x60ad3ef2, 0x619fe63c, 0x7faf84b5, - 0x65b1316e, 0xbf7db718, 0x210ffc6e, 0xc74cbebf, 0xcf04bf50, 0xe832461b, - 0x19f53112, 0xfd382374, 0xba4a0f51, 0x91190303, 0x886e921e, 0xee90edbf, - 0xc11af2df, 0x2a9ae12f, 0xb6f3dee2, 0x7c8f1f6e, 0x53665c92, 0xe1204e30, - 0x793d91ba, 0xd9dbf631, 0x0ed0ef93, 0x221b12bf, 0x0ec21d2e, 0x610d88ef, - 0x2fed8387, 0x637738b3, 0xe1d91bbb, 0x36ff82e1, 0x7fed06c6, 0x08597ee0, - 0xed8d0dba, 0x1fdf0f10, 0xe3ff621b, 0xdef0f146, 0x43ff72b1, 0xc97f0f1b, - 0xad6ff5c8, 0x293c3d8d, 0x1374bc84, 0xb5d6ebe3, 0xc67ed11a, 0xf5212835, - 0x518b62d9, 0x1c7e1fee, 0x125fb01b, 0xe0438fac, 0xefb628f7, 0x17b7cdbb, - 0xe9890d5b, 0x5bee8111, 0xdeb0ebbf, 0x29ce310d, 0x22fb3f81, 0xf6a6fb46, - 0x0afa462a, 0x141e5ef2, 0x371429f4, 0x934f38b0, 0xbec1badd, 0x1cd69dd5, - 0x3ee483f2, 0xd6ab54d5, 0x938b8c4f, 0x239f9ced, 0xd89d699c, 0x3c097f89, - 0x70dbfcc1, 0x4c45b8dc, 0xf7231fb3, 0x3caae261, 0xcd0b318a, 0x6af8a311, - 0x32f758d7, 0x1d6bb403, 0x209b1cc9, 0xcd685d1f, 0x9b6a7d41, 0xfdc468e3, - 0x7917959a, 0x02e57e3c, 0xfd4e5de6, 0x7732f9f0, 0x17ca2f37, 0x2e302dd2, - 0xe1c71110, 0x72e38888, 0x1cd27606, 0x8f0ae1c7, 0x9293b00b, 0x3e75ba1e, - 0x1adae895, 0xd0054eda, 0x77df46d5, 0x50efd742, 0x3771ed2e, 0x8cf71fe7, - 0x19be05bb, 0x7c737718, 0x4b4c14f3, 0x8f04dfec, 0x0ff38997, 0x2cf80f1e, - 0xf826ee2b, 0xee2deaec, 0x50881e8f, 0xa5dc5dbe, 0xc4275e23, 0x6b77d085, - 0x487d75f2, 0x4770b35f, 0x233abb28, 0x7dbff22e, 0xa086645e, 0x179d2df7, - 0x2d27f179, 0xdcb3a446, 0x06f090f7, 0xe591139f, 0x264a0d15, 0xf6733fae, - 0xc075a35d, 0xd37fc6a5, 0x79e3a03a, 0x42ee3e0f, 0x678003e4, 0xcea03aac, - 0x7977f207, 0xea56919b, 0x22ffb32a, 0x4df6e31b, 0x53b5e606, 0xefb6337b, - 0x7efb78c7, 0x633656db, 0xd31faadc, 0x547ac47b, 0xa8fdceb9, 0x7ee39468, - 0x8d5b2a4d, 0xbebcadf9, 0x6197998a, 0x847a3a5c, 0xf003d98e, 0x670ce319, - 0xc67c00f6, 0x7934d9e6, 0x2f9e4eb9, 0x25778dc6, 0x32efbe6b, 0x7da69bbd, - 0xa69fbb92, 0x10ce653e, 0x6aad3e4d, 0x577da694, 0xf981cfb0, 0x9addcf0c, - 0x266bddf6, 0x6b3df26b, 0x3fb4d01f, 0xcd9eaacd, 0x9c7a79c6, 0xce003dcd, - 0xdece0259, 0xdf358beb, 0x0dd5d7f5, 0xf920a1f3, 0xffee1f14, 0x326c16cd, - 0xfa73c44b, 0xfa69e77a, 0x5e6aff3d, 0x9df80293, 0x19386b5d, 0x7c219f18, - 0xea4b7e00, 0x8c1cf615, 0x5b5eba5b, 0xe9e1a73f, 0xce902995, 0xe7cb6af5, - 0x829cbee1, 0xdf2dadfc, 0x823d73ad, 0x71ed9deb, 0xe228ce22, 0x7f03ac3d, - 0x97b8d244, 0x9778f037, 0xc41de9ea, 0xb13a5a1f, 0x762fc96f, 0x44a62fc1, - 0xd984bf2d, 0x7a52fcb5, 0x1f30e770, 0x88ff88eb, 0xe47c413e, 0x78017f81, - 0xf895f897, 0x7cb438b7, 0x9de15df5, 0xdb91af31, 0x3ff96d0d, 0xb5f1b4e2, - 0xe3ee917e, 0xd4aeb7a8, 0xbf71522f, 0x7df1e58d, 0x57f52bfb, 0x6bb21d07, - 0xdb3ad7f6, 0x17173a4f, 0xfb175718, 0x3f709749, 0x137636f1, 0xfefb89fb, - 0xd900f885, 0x1f801b77, 0xb98708d8, 0xcc30ff7d, 0xac147fbf, 0x760a6537, - 0xb238cbe3, 0xd77dfe27, 0x587af86a, 0x085c5ff4, 0x9387dcaf, 0xf9e472e7, - 0xe7c91621, 0x3c01fb29, 0xf143f1a8, 0x022d9ffc, 0xf7dbadd7, 0x96f5a42f, - 0xc4c43f3c, 0x7e10bfb9, 0x3aefe93f, 0xfc8935fc, 0x6e78f081, 0x6d3123cf, - 0xf9c407f7, 0x3bcf692e, 0xb7ee47eb, 0x7b2a9675, 0x6c3fda55, 0x9b1dc255, - 0x5e93d842, 0xfd72dff1, 0x1c43a675, 0xe07c57ba, 0x2bd1ebfa, 0x00aed007, - 0xb962fbde, 0x5af602c5, 0x5febdbf1, 0xbf114444, 0xbd541eb6, 0xb2e0a1bd, - 0x036d1ed9, 0x6984363c, 0xab4c88ed, 0xf403c9cc, 0x3daf58b1, 0x11f727e7, - 0x6367db83, 0x27fd80fb, 0x8fe34ef8, 0xfdc21cac, 0x6e78ecb5, 0xe488bfdf, - 0x9114c1fe, 0x175a0caf, 0xbf70d655, 0xe9f8236c, 0x4cfd010d, 0xfb50b789, - 0x533911a5, 0xc08e29e2, 0x332bbbd7, 0x5627f214, 0x21f90a2a, 0x5347a267, - 0x9cb8b5fd, 0x623fc4c9, 0xbbe8299c, 0x6edaffc1, 0x38bb1e1c, 0x37fb238f, - 0xe6f6f3c7, 0x4e94d1f8, 0xb88ab789, 0xf21fb5b3, 0x93846547, 0xa1aa35fa, - 0xc7a6a5f7, 0xb5ad79f3, 0x6a27e930, 0x84e3fee2, 0xbf38c4de, 0xf9a3fb89, - 0x71fc1363, 0x7f66a67e, 0xf1138c68, 0x773e857d, 0x53ba9ea2, 0x78b3bdd0, - 0x758fb3bf, 0x75276e3f, 0x12fbf78c, 0x1dfbc643, 0x0fde28e3, 0x5e71ea5f, - 0xa47f71c1, 0x2fcd8443, 0xb7c48f3f, 0xd45483db, 0x7746f54f, 0x5abbae35, - 0x0eff8377, 0x2dbc7dc5, 0xf0301fb4, 0xae077750, 0xb06656af, 0xb7e416bd, - 0x7fa18c65, 0x5ba2df5f, 0x6bf5061e, 0xf58acc3c, 0x75f03723, 0xbb7ae95b, - 0x8069a703, 0x8865b075, 0x8bac1f5f, 0xd7bc218f, 0xc46e4cb7, 0xf73581fd, - 0xa19a1b32, 0x1b9b565a, 0x06d0fe85, 0xf8dd7216, 0x09b39094, 0xd4557b39, - 0xdfe8f117, 0x53d3a087, 0x0fa04e82, 0x879d22d6, 0xf0afbab7, 0x4fae38fd, - 0xfae22548, 0x1bcebf74, 0x373f3d6a, 0xf21d773a, 0xe86f40c1, 0x0b5ac3f5, - 0x1175b7e7, 0xdda8e7ae, 0xb5ee7e2e, 0x59dfea54, 0xba07a63a, 0x9d74114f, - 0xdf9f81b2, 0x5faed760, 0xc89fa557, 0x7a867fa8, 0x8b5ef4a5, 0xa543e317, - 0x821e190d, 0x7a38a5cb, 0x7868bea2, 0xd2f985df, 0xc62b2cac, 0x657f9c23, - 0xe43ea9ca, 0xbfae3262, 0xd494ecf4, 0xe3c76427, 0xb269df68, 0x16b5b7e0, - 0x0d473f3b, 0xfc008e28, 0xb6586e97, 0x7cefcf17, 0xfb466bf4, 0xd6d4474b, - 0x54d9d861, 0x2192ce40, 0x2159ea98, 0xfef82bc5, 0x1fa2bdd5, 0x5c61bfcf, - 0xa9dc7fb3, 0x3e69070d, 0x63cc0c47, 0xb4ba3e06, 0xfa3b3ee7, 0xcde32bdb, - 0xfb93c714, 0xf75547b2, 0xf48464e3, 0xda0815ad, 0x56110dfd, 0x43fc7f8c, - 0x82465df0, 0xc7d21f7b, 0x057c7cbd, 0x6596c1da, 0xa3c474a6, 0x1a92797b, - 0xd7ba7007, 0xd1ef342a, 0x788c93cb, 0x8ae6617e, 0x4f50e3c1, 0x95ce610d, - 0x2879df18, 0xd3948596, 0x9d7cf1f3, 0x60655c58, 0x849a68c6, 0x172fe311, - 0xbf8a146b, 0x015bfee0, 0x988e67d0, 0xf7aaf95f, 0xec3f88a3, 0x1e186ff0, - 0x733fe5cb, 0x1e494aaa, 0xe46bcec1, 0x19d58ca7, 0x799fa093, 0xdb39606b, - 0xf1fdec8d, 0xc043fe0e, 0x3af2ef79, 0x5b257d6d, 0x7f9d39f3, 0x5befe061, - 0xeb682ed0, 0xe8f2953f, 0xaba40e60, 0x8cc5b17b, 0x0b4684e7, 0x51ad14bc, - 0x665fa8ac, 0xbf8c68ae, 0x9b33f20f, 0xb4f20754, 0xe8eb0bc4, 0x8f39d3ef, - 0x693d4dcb, 0x6ed9703d, 0xdced82ef, 0x2bff5c51, 0x2c70f77a, 0x3dd6287f, - 0xadf1d71c, 0x9e18589f, 0x06d6399b, 0x1ec618fe, 0xc5106ccd, 0xd06cac1f, - 0x5a3b00a4, 0x6026b064, 0x16c3dfbc, 0xb7be3226, 0x779c0e65, 0xf90d79a5, - 0x07e89581, 0x1f91f9f2, 0x672c50f8, 0x15d7d6d5, 0xeac39f3a, 0x9a07e40d, - 0xd6781f85, 0xae009b5e, 0x6e3d7317, 0xde2d3920, 0x687e4316, 0x235c8af1, - 0xaef16ff2, 0xe043d218, 0x63d87e07, 0xc78e9f98, 0x481e6456, 0xeb8b7e84, - 0x96aa1c32, 0xb8ff5a7e, 0x5ba498e6, 0x4b4fbf47, 0xe8a193b7, 0x94d2f406, - 0xff0824a7, 0x3d8bd04e, 0x477e4b16, 0x7ab782e1, 0xcb9e019a, 0xee746155, - 0x83ff33a8, 0xbed1c6a5, 0xe6175c9e, 0xdfafb725, 0xcafcdf68, 0xb744a19a, - 0xfde57a60, 0xb470e667, 0x16afec27, 0xa1ec7a86, 0xc9e1ecee, 0xc2b0fe50, - 0xeaa1ebe5, 0xa72879f1, 0x6f5c0959, 0x6614b7be, 0xfdec6468, 0xece666a5, - 0x4b07d8c5, 0x68ff94ad, 0x3fe52269, 0xf4a76a5e, 0x287da593, 0x68e2293d, - 0x0180ce52, 0x25475f88, 0x951af970, 0x6cdee220, 0x8caa2251, 0x307cffbc, - 0xa1c56754, 0x4d8c27d2, 0x271eec63, 0xdfc02320, 0x046f7e99, 0xdf3db912, - 0x4b8eb062, 0x9571ff44, 0xd8befa42, 0x3da6bb75, 0x3c4625f8, 0x64facdff, - 0x9ce9cbfa, 0x1938dd98, 0xfcfef0f8, 0x69fb4d58, 0xfc9a2935, 0xcd3b04e4, - 0x775e527b, 0x8503f94d, 0xa2f935fd, 0x9e024036, 0xf8db302f, 0xb7d8aafe, - 0xd7c6cc67, 0xf6de56eb, 0x2ef0d56a, 0xaf7807df, 0x7d50321e, 0x5d243d30, - 0x31d7ad67, 0x73368037, 0xfa0dcc3d, 0x933b593d, 0x11fceae4, 0x95fdd90b, - 0x1ddf32db, 0xdb63f901, 0x7ebfb40c, 0x5aec456c, 0xb63e3fdc, 0x418a3e2d, - 0x32a95eea, 0x7ac1fa1f, 0xe80591ab, 0xcb15dcb7, 0x9156fce8, 0xf940e4d7, - 0xf9efda2f, 0xd1dbcc95, 0x5120441f, 0xbd543e3e, 0xe7e8853e, 0x14befc24, - 0xf902dde6, 0xf1afa033, 0x16ccf8c8, 0x8519d70e, 0xd9fcc0ad, 0xfaf5bfb0, - 0xb171c03e, 0x8744b6a0, 0x50f501eb, 0x1dcbe93c, 0x2dbe432a, 0xfda0605c, - 0xa91fb9bb, 0x94cf311b, 0xde9c2921, 0x64479d2a, 0x7fa8992f, 0x021c0ad6, - 0xd6fd16ed, 0x77d689b4, 0x0f77e44c, 0xfc16aef4, 0x26747c89, 0x08633986, - 0x3de08558, 0x46fc7ef7, 0xd3e3f7ac, 0xfde7083b, 0x32b5dea5, 0x5cebf801, - 0xe9107789, 0x49e2c7b5, 0x7ef182ae, 0x96f5c8d2, 0xf140e507, 0x9cbf4beb, - 0x9d3e272d, 0x38247069, 0x25655f48, 0xb93abea1, 0x98e740c6, 0x3519de99, - 0x3b3fd689, 0x38e58f88, 0x71f6f527, 0x9ac9df08, 0x96fb860c, 0xf2546bc5, - 0x78ff9007, 0xffe72f7b, 0x1b3755a7, 0x28d6fd0e, 0x23a5d66e, 0x60b23cdf, - 0x9a639d38, 0xc141d621, 0x9033e07a, 0x7f2f7755, 0x7e1ede7e, 0xb56586ce, - 0x181defe8, 0x7c158f38, 0xbfde44bc, 0xd650073c, 0xd1474fed, 0xd4dcbee5, - 0xf0ed1a3d, 0xe2550fd9, 0x6addb3b3, 0x3d022587, 0x0ef6e82f, 0xcfe43efb, - 0xe94e7817, 0xb854ff21, 0xae02677b, 0xd26b7457, 0x3e786e95, 0xdbdac4f6, - 0xaf73bbe1, 0xe6241c18, 0x7f49e24b, 0x6e697bcc, 0x8ef3c0d7, 0x2f97f51d, - 0x38bfef99, 0xe7c01493, 0x38dd7b7c, 0x775c00eb, 0xe21d84bb, 0xe6e3b1f8, - 0xbac5e02a, 0xc343c14e, 0xcb50c4ec, 0x3d773c6a, 0x3024c413, 0xec42784e, - 0x7a101f8f, 0x1109fa45, 0xa67e785d, 0x7b37f38e, 0x0dbf2155, 0xbffa347e, - 0x944f9c52, 0xebea5f7a, 0xfb4b5632, 0xf81247c1, 0x8ab9c639, 0xe055da97, - 0xa8a82ece, 0x420f2b12, 0x79356d97, 0x97d419bd, 0x480fd035, 0xfbe762ee, - 0x9e57c643, 0x652db645, 0x417e7ccd, 0xbc19ceed, 0x1d19cd25, 0x75894ded, - 0xf51b0ae3, 0xfc60706f, 0x69c854a4, 0xf5e2ad79, 0xdd9079f1, 0xd98af194, - 0xdb066ec2, 0x28f60ea7, 0x0ecd0ec8, 0x56acb3b2, 0xde01576b, 0xc2471c48, - 0x2ba70c1b, 0x987842c2, 0xbda17007, 0x0f7b712d, 0x15b8244c, 0x03b25007, - 0x35cca53c, 0x01e70626, 0x477b3ef5, 0xd5e782f8, 0xcf315e01, 0x1c4bb860, - 0xff70fb9f, 0x5187cf18, 0x1e6829bc, 0xfec11e92, 0x894ba49a, 0xa4b7e387, - 0x7e7a2141, 0x3207eeda, 0x7e491b8a, 0x9d500581, 0x44d77bf6, 0xeba567d4, - 0xf866ff40, 0xd3f247f9, 0x8517563c, 0x7cc152fc, 0xbe50932b, 0x46d3757c, - 0xe1bedfa2, 0x49ca237d, 0x53d7cda1, 0x5c288317, 0xb4bcd3fb, 0x1044f580, - 0xd7446f9e, 0x9c378a6f, 0xbdc65e95, 0x37b34f00, 0x41b0ceab, 0x1ce2769a, - 0x60e48791, 0xc463c78e, 0xb11cc6f8, 0x9c11bfee, 0x6e7e7a95, 0x76f086fc, - 0x5b7d27e2, 0x68baf3b8, 0x9fbf62fd, 0x943a33d5, 0xaff76a9e, 0xdffaec82, - 0x217e3c0c, 0xbd55f1f5, 0x5025e293, 0x2aaefc2e, 0x079b8f2b, 0x2cb4f1e9, - 0xc225e3d2, 0x4e71cbae, 0xf149dfad, 0xf768d9b7, 0x5d3fca03, 0xfee293b7, - 0x476657c6, 0x6a7dffa1, 0x78b5ccfd, 0xb6d4ebbe, 0x4be76499, 0xde76939f, - 0x1ff40c6d, 0xbd17d772, 0xdfe463f8, 0x9f1461ad, 0x16efd92f, 0xabd01eeb, - 0x9ebeced0, 0x8eb651eb, 0xb452d5eb, 0x1ec80387, 0x8b76c6f6, 0x51bddc4b, - 0xc9ca020e, 0xe99e2e4e, 0xe81eddfe, 0x11cbf177, 0xc2a10f0e, 0xdf91d3ea, - 0x3da1f56e, 0xf1f85f2c, 0x0ee73c51, 0x1fa3fff6, 0xd90ffb48, 0x92f77a8d, - 0xc26f282e, 0x1bab97ee, 0x27e8add3, 0x5ff13b08, 0x3439bfc0, 0xfe1087fe, - 0x01ff118b, 0x6bc720fb, 0x06679e38, 0x1ac4ffe1, 0xdb95974e, 0xfae147ba, - 0x774d78f1, 0x6f8eb3f2, 0x9ff849eb, 0xcff01ab5, 0x3f5a5fe3, 0x8ff006ab, - 0x3fc408eb, 0xdfbc5bc0, 0xe0eff02e, 0x78e1aff8, 0x3a786b67, 0x3d9e03ab, - 0xf1618e74, 0xf40e4daf, 0xf984ce1b, 0xb33a9fc8, 0x01d5655d, 0x83f4987e, - 0xbfb560be, 0xe24d7f42, 0xe6af6e7f, 0x0a7fa841, 0x1453fe9f, 0x76ee61d2, - 0x80efa41e, 0x82ece67f, 0xfc7fb8fe, 0x95e9bf76, 0x7e01f12e, 0xa9d24dd3, - 0xd918b982, 0x1d3f86c5, 0xe28375c1, 0x786d4f84, 0xd7dc468f, 0xd7ded7a8, - 0x851933c0, 0x382f8c36, 0x278466cc, 0x8a1ef835, 0xf91c619b, 0x9f3f3d9f, - 0xbce490b1, 0x6dbe7355, 0xba19f322, 0xa758ffa0, 0xf2c6fdd0, 0x39513945, - 0x55d4e30c, 0x2ee9c704, 0x78fce68a, 0xff23aab9, 0xfdc8ccb1, 0xf93fb948, - 0xde0ff0ae, 0x25d7c2ed, 0xd2b175ef, 0x18c29777, 0x164b81d9, 0x23ef17a3, - 0x112a7ac0, 0x31ecf7c7, 0x228edd11, 0xd57f804c, 0x6036e228, 0x1f4f9102, - 0x1f4f9c64, 0x38a26c8c, 0x5e54ac39, 0xd0f8bb40, 0xfc839312, 0x8a68b8da, - 0xf4203ed7, 0x2b9183dd, 0x1e1f685d, 0x313a348a, 0x783d7e85, 0x1a30ce88, - 0x0df18786, 0xafba46c9, 0x796e6853, 0x0fbe9705, 0xd4789e27, 0x06dea00c, - 0x55c637ee, 0xd75dd7e0, 0xc5d23b63, 0x9c6d1f4f, 0x743c32a7, 0xe055a3dc, - 0x293a714b, 0xbe82639e, 0x2b8e01c3, 0xdcb12f68, 0x9df1e56e, 0x8b27400d, - 0xe5c1be9f, 0x03f7c3cc, 0xe35cf0ca, 0x6419c628, 0x935fe104, 0xfaf2332f, - 0x26afc4f0, 0xec66cbac, 0x103ecccf, 0x3a8656e9, 0x45f7d704, 0x978c5ed1, - 0x25f183df, 0xe27aa61b, 0xe67ac997, 0x26b4f1d1, 0x89cccf12, 0x8144d378, - 0x9823a9cf, 0xeef01a2f, 0x778da83b, 0xf9d3e7dd, 0xef7e037a, 0x911afbd1, - 0xbb66753f, 0xb8e30ac1, 0xb82194f2, 0x7e5b292e, 0x25a6f073, 0xa5d7f39a, - 0xcfc75e42, 0x80feb585, 0x041e21c7, 0xcdbc4561, 0xeafdb3d0, 0x8807ce10, - 0xdd9b4a97, 0x2816ed43, 0x71950f14, 0xc1ff4936, 0x1d207dd0, 0x41f0141f, - 0xf851353f, 0xbd3431bd, 0xf5ca26fa, 0xabad1d73, 0x9bb90be7, 0x9b6de52f, - 0x27c6de56, 0x82bda9da, 0xede0307e, 0x26769141, 0xff44e317, 0x5cb912e3, - 0x78e2dd64, 0x9d35b22c, 0x7908b7ce, 0xfef13729, 0x88f7f8e5, 0x8da24c74, - 0x00f095fa, 0x7ec71ebf, 0x9001a074, 0x56d64f5f, 0x87347f93, 0x33b5c405, - 0x5f24edfc, 0xebb7cc77, 0x4c75dd11, 0x10b3ad8d, 0xc2f7caf5, 0x1f47a81c, - 0xacf5d634, 0x4ed8ec8a, 0xb214dbee, 0x3d230366, 0xc261e229, 0x23558cfe, - 0xa1407ce9, 0x5e0fefc2, 0x7478b1ca, 0x31a718d1, 0x630b6910, 0xf13f3a14, - 0xf27fb137, 0x89e2f450, 0x5185d728, 0x33a63d46, 0xfbf52b58, 0xe8b76b77, - 0x33de18fb, 0x0e763156, 0x77c88f03, 0xa8d5b8c2, 0x8d7e7877, 0x4aa29b33, - 0x21c77f22, 0xdee1e027, 0xca7f406b, 0x09df2f7f, 0x4b7a5ffd, 0xe93bb3d4, - 0x0b8f4bfb, 0xf2e4f63e, 0x7d65cffc, 0x92afcf1e, 0xff3cf9f5, 0xe45feca4, - 0x5faa0e9f, 0x4bff5416, 0x3ebc5f9e, 0x7e83df3f, 0xd2ce68eb, 0xd214a385, - 0xbe847b53, 0x23ee5c28, 0xf6ea16fc, 0xf33474f2, 0xdc6eb2e9, 0x6ba2536e, - 0xd51fda0f, 0xf682d272, 0x2764d5f7, 0x704f9fe5, 0x75c44b2f, 0x63c524d4, - 0xa1fb7d44, 0xc4c1ec97, 0xed1fce4e, 0xf8e3c2e9, 0xbfa0929b, 0x05fb7ea1, - 0x8c4eacfd, 0x1c7ef5bf, 0x80ae1c49, 0x26f99e7e, 0x23a7fcf0, 0x49be1b3c, - 0xb592b33f, 0x487f48fd, 0x86be7549, 0xe32763f3, 0xe645e734, 0x8d11c4ff, - 0xe78627f1, 0xf3f50045, 0x67a5d797, 0x5ff3ff42, 0x04bd3d7d, 0xe76125fd, - 0xcc74da2b, 0xdb34f789, 0x1be7a518, 0x7de2313f, 0x8d5d8ab3, 0xaed071c6, - 0x00dcd212, 0x9c04cab8, 0x93f4e760, 0x8373ec03, 0x3d8c1bd0, 0x5f37f7cd, - 0x7a47ab3d, 0x9dd5d7ce, 0xf6ed0e7a, 0x3ee42528, 0xddf166cd, 0x17ce4ed1, - 0xe87a15ef, 0x11b39a6a, 0x8c6bf9e7, 0xb73e4021, 0x60fb93ba, 0x855f1c49, - 0x1ccdeec2, 0x01db3166, 0xe43f43cf, 0x1b2554fb, 0x3c608632, 0xd184cdf8, - 0x6d7e24ef, 0xc795b53c, 0x3c781b53, 0xbcd6d0b5, 0x33379408, 0x31ad9526, - 0x84d8c1df, 0x0339485f, 0xf36f8591, 0x9d5f324c, 0xc79b263f, 0x767f30bb, - 0x506b63fd, 0xb9c29a6e, 0xf0d0fb1f, 0x17a8e181, 0x7422325a, 0x37e79056, - 0x498c8be3, 0x8efcb143, 0x639e5871, 0x222af4b2, 0x8be232fc, 0xc75de337, - 0x3db05f90, 0x46dc41c6, 0x307dfc5f, 0x2adbf70f, 0x0f75a79d, 0xda87708a, - 0xc087fa77, 0x4ac931ab, 0x19901369, 0x870917fd, 0xf9fc1f1c, 0xdfd0cd45, - 0x8349e5c9, 0x9f71db57, 0x3490c725, 0x467e3fd4, 0xe072fb82, 0xac7527f8, - 0x6e292e17, 0x024b8e16, 0x5dee030e, 0xd95dbe03, 0xac06732a, 0x898f26f3, - 0xcdefe4d0, 0xc0ce658f, 0x29bded38, 0xc2f4fc9a, 0x0ff69aee, 0xa9afeacc, - 0x6735302f, 0xb1f80555, 0x1e49fb9d, 0x62d2a782, 0xee7f4709, 0xfc5f0def, - 0xfff441e5, 0xf40eab36, 0xd9eee755, 0xa1db97f2, 0x4e3c65d5, 0x3b47f145, - 0xc9cecbc5, 0xa77a28f3, 0xe85f703e, 0xf3a66b22, 0x03ed9d3e, 0x7cee75c9, - 0x773a7eeb, 0x03ef5df6, 0xeb124af5, 0x086c21dd, 0x55cbc3da, 0xaebc511f, - 0xefcf9222, 0x8cc7ebe2, 0xfb8a0fb8, 0xdf81d78a, 0xd10fc2ef, 0x50f36c3f, - 0xfeb73b3c, 0x1d9bed18, 0xba7ae448, 0x1e817522, 0x42551def, 0x1c68768a, - 0xe068abe8, 0x3646e697, 0xbbee1770, 0x1fb85866, 0xb19936de, 0x1e2be458, - 0x884a69df, 0xf3d77ba1, 0xbca8f26b, 0xfa9c2da2, 0x1e6d4f7f, 0x5f09e747, - 0xa1ff6853, 0xe5a1e520, 0x29b87e78, 0x11e033dc, 0x77e0b718, 0xde21e577, - 0xf3f1762a, 0x9fea05b5, 0x5a4016b3, 0xdf479b56, 0x49aca817, 0x42617f01, - 0x05bfb72e, 0xaf21f368, 0x46acb30e, 0x7d1aabbb, 0x3d479ebd, 0x9e90b463, - 0x807b6e89, 0x336cafc6, 0x24f7f7d3, 0xd0d77f71, 0xdb1ae1c2, 0xc972a2e6, - 0xba93530f, 0x860fd669, 0x7c7acdf8, 0xc2d0c397, 0x6dddfda8, 0xf39528fd, - 0xafcfbb7d, 0x21ae3ee9, 0x14b8eafe, 0x71dbf798, 0x90dc958a, 0xa57c3d20, - 0x0b34786a, 0xc7daa7a1, 0xf4e7e369, 0xdcfc6d4c, 0x738a615e, 0x31c0127e, - 0x3d16b1f1, 0x48b107ee, 0x35f115b3, 0x7b60c471, 0xa97c8049, 0x2237ef7b, - 0xdeeb0c7d, 0x369da237, 0x501b9a41, 0x33ce2e5f, 0x05e9eb04, 0x2f4f5249, - 0x1dda54a3, 0xf9067576, 0x82ac33a9, 0xccfc8501, 0x7e54fa10, 0x1a6b4cdf, - 0x1e6ee3a0, 0xc5347fc7, 0x45f502bd, 0xbe9b0e73, 0x7366f483, 0x7cc3ee3a, - 0x9d03f057, 0x89f90acd, 0x751e742d, 0x0ebb08e2, 0x04abffe3, 0x6f8e525c, - 0xa2c58f34, 0x5b2a7bfd, 0x77befd82, 0x4ecd9de7, 0x47f1afe8, 0x0f689999, - 0x25cfb8e4, 0xcc297bf1, 0xd70d7ada, 0x446f9583, 0x0bde51d8, 0xfb863170, - 0xb44c7b9d, 0xda72814e, 0xc37ca8cf, 0x89ef09b4, 0x7ac14654, 0x7dcfc615, - 0x7c87cc33, 0x9866f8dc, 0xef46ed1e, 0x4873f774, 0x7b37dccf, 0xa1f5c18f, - 0x67a4c1b3, 0x9f38f7e4, 0x09db3d27, 0x5bd237bc, 0xe5267cc1, 0xe5c35dd3, - 0x69f048a5, 0xb73f90b1, 0x552ba390, 0xaf0e485d, 0xe340063c, 0xca63e93e, - 0x27e85dc0, 0x7ef42dd8, 0x02cb9493, 0x79410f5c, 0x3a18ff41, 0x8dfd2bff, - 0x6b2c3960, 0xe5bf52b3, 0xef21766d, 0xb94bca36, 0x6372162b, 0x2cc67e12, - 0x53bbe7c1, 0x5e20efdc, 0xee41aa0a, 0x3f1f68a3, 0xcfc9e50b, 0xf22b4637, - 0x624df017, 0x54fc8049, 0xd0cfde37, 0xb9c5313f, 0x41666f88, 0xcc9fe81a, - 0xac4ff76e, 0xfe0012e3, 0x74322b89, 0x9da9df78, 0xe6f9db7f, 0x8f7ff8e6, - 0x48e29790, 0x67f44f5f, 0x0e61550d, 0x397e873c, 0x2cf7ef8e, 0xb8f1c55c, - 0x45cae0d0, 0x2fe162ff, 0xa1978a15, 0x697a81df, 0x632a91d8, 0xfee51c60, - 0x0ecc41b6, 0xd6d29878, 0x1337d283, 0x0f1147dc, 0x04d36d45, 0xa37d06be, - 0x4ea1c5fd, 0x7832471e, 0x198d8e4d, 0xab724718, 0x6933e748, 0xe04cfacc, - 0x1d7ade7e, 0xbee4c3c5, 0x992b8ca3, 0x807cbcf0, 0x5f42fd1d, 0x37ef4e9b, - 0x7299c704, 0xb0bfddb8, 0xbf7640d9, 0xc3cff1ac, 0x2e7f5074, 0xed05d9c3, - 0x777a97c9, 0xbcf5f21b, 0x0d57dec9, 0xe4ff9f90, 0x7691a8ce, 0xf4eb3e3f, - 0x47689ebe, 0x188f00eb, 0xa35baaef, 0xbfb979e6, 0xc9f7c113, 0x7e4b7f38, - 0x79f3e60e, 0x9f88dd6d, 0xc89954ae, 0xbe015d0e, 0x48760165, 0xe7a91dda, - 0x7c91fda5, 0xfae7ae5d, 0xda323cab, 0xb408c9eb, 0x395c933b, 0xf87d77c8, - 0xddbf1a79, 0x1476b4d9, 0x38a5c1ca, 0xed28b73a, 0xbc1cb046, 0xd31c14b6, - 0x8eed1d5e, 0xcf52ebd4, 0xfa35bb4b, 0xfe772fe5, 0x8a55cd15, 0xe032407b, - 0xb73d6eeb, 0x2deb775f, 0xe3633fc4, 0x6f91e926, 0x1e8f5e6e, 0x98f47a13, - 0x74568f46, 0x27060762, 0x741c9adf, 0x4cf3ed15, 0x3d447fdc, 0xa3dfd81f, - 0xe0c7a329, 0x7327c63c, 0xc15dfb3b, 0x1ffe99dd, 0xfa6b7c9f, 0x88b2587f, - 0xff40ddf7, 0xfd732617, 0x99efac1f, 0x73a7bf95, 0x2f5f4f69, 0x0ca383da, - 0xc1da03ec, 0x16fb0886, 0x5ec80f61, 0xbf7b4784, 0x4d5c1ece, 0x7888599b, - 0x1e0f610a, 0xf616fe4a, 0x94a1f240, 0x5227291b, 0x48e5822e, 0x9f84c5ca, - 0xe9113ac2, 0x57bf1ef4, 0x6cf7ae50, 0x7b46fda3, 0xcf9460c4, 0x976e3f76, - 0xc1d6f242, 0xf1f9084e, 0x6ed68bcb, 0xf290b948, 0x5ca7e522, 0x20ecc5c8, - 0xd6a7d8b9, 0xf70a333d, 0x6bdd92cb, 0x72fde393, 0xd823b652, 0x57ca743e, - 0xb3645918, 0xf218aae3, 0x81a43955, 0x44ea657c, 0xbe499e1e, 0xd968bf35, - 0x6fd3f24d, 0xf4fcfbfe, 0xe9f84e9b, 0x3f0dbe7f, 0x3f63f475, 0x3c03b2ce, - 0xdf40b257, 0x6df9f866, 0xfb8c3bc2, 0x7af9dd0f, 0x0497d600, 0x8d319377, - 0xae133ee2, 0x2f8a2ab3, 0x7494be0a, 0x6cc0fe96, 0x93387711, 0xe1077ae2, - 0x82c0f5c5, 0x447bd39b, 0xb35c5367, 0xb327d711, 0x03f40d21, 0x9b7ff33a, - 0xbdef516f, 0x3e749371, 0xfb9dfc96, 0x4392c78d, 0xb1c78dfb, 0xb5d29bfc, - 0xf8899720, 0x300b8fde, 0x29e138de, 0x0acb6791, 0x46d38f10, 0x3c9ffac8, - 0xfa81ece9, 0x38b8c981, 0x53de39c5, 0xf4b3de45, 0x3f6818f0, 0x8fe619e1, - 0xd8fd439b, 0xb8f6e8ec, 0xedfcc288, 0x3b1fe795, 0x51e886bc, 0xddcce5cb, - 0x3ffbe7a2, 0x79059f22, 0x447e404b, 0x6f037e50, 0x616fa51f, 0x9045e781, - 0x9c21949f, 0xff00aece, 0x7fdf8601, 0x5585ed05, 0xa8d71861, 0xd6f8db8c, - 0xf56bd415, 0xb545ed0a, 0x14d581e3, 0xfbc55338, 0x735f94b9, 0xc23e09d8, - 0xbe78bb03, 0x93ed4a4f, 0x37e8bd1e, 0xa1bddce0, 0xb9d2714e, 0xb78a1183, - 0x7c47465b, 0xdad149f7, 0x6bd1fc27, 0x1e7867bf, 0x6fbe56ef, 0x8dd6cfbf, - 0x6e99f7be, 0xb2fbfc61, 0xfe7f9f43, 0xefe70a5e, 0x21d15931, 0xa8a5c7eb, - 0x37111fbc, 0x68a1f1a0, 0x7be85d4a, 0xb8c513b0, 0x425fb8cd, 0x24f6dcf8, - 0x28d9b7e2, 0x93f2fdf1, 0x196377c8, 0x60cfc4d3, 0x9fdfca7c, 0x8d4172f2, - 0x19d74f9e, 0x9bafaf84, 0xa91480ef, 0xf2f8fdbf, 0xf4cbd104, 0x8476f835, - 0xfb5db7c0, 0xe8ebefbd, 0xf7c3ac35, 0x48e76f82, 0xf86a763e, 0x22ef5a3d, - 0x538e8cfe, 0x5747e8ac, 0xe0d6c2b8, 0x9f2fc17a, 0x6cbe27bf, 0x1d03fb96, - 0x02b5efe4, 0x890abf94, 0x4febcf47, 0x74bafca2, 0x3cb9eded, 0x7335f3b6, - 0x52bc01f6, 0x7fbe0fc8, 0x27faf9e4, 0x7c092e31, 0xd794f541, 0x2c1dc007, - 0xf941758f, 0x15f920ec, 0x03fa47f2, 0xa9e001ed, 0xb8b7ea27, 0x007b4663, - 0xd04cfc9f, 0x27b8a2e9, 0xfb9a3cda, 0x78ddcd93, 0xfb8523ba, 0x7c09cf8f, - 0x9bed126e, 0x90f003c3, 0x1f1fe1aa, 0xe6025bae, 0x3fba784d, 0x93fbce4e, - 0x63d07c82, 0xbf5e36cd, 0x27a3e52d, 0x7cfed93d, 0xa6af7f70, 0x7880527c, - 0xf1fff7f1, 0xee23f461, 0x91db7817, 0x27b0e472, 0xc139d052, 0xf0214eff, - 0x5163bd07, 0x74a1fc8e, 0x761f8fe4, 0xd04f4fe4, 0x774ef4f7, 0x3a7bdf67, - 0xfa0cef7e, 0xea3de19e, 0xd05eff9b, 0xae883f2d, 0x1d744179, 0x942f9413, - 0xff46af79, 0x5c5cbd4a, 0x09e3f4ff, 0x54df1871, 0x9fbf38e8, 0xbd934f9f, - 0xfc956f99, 0xf230e67b, 0xcf9f9fab, 0xd7279e12, 0xce79ba09, 0x787a893d, - 0x51e1ea12, 0xd414fcfe, 0x5f3f9443, 0x7e61fb80, 0xea81757b, 0xed91abef, - 0x7afd922f, 0xefec8560, 0x3a4bca33, 0xb225cf32, 0xbd0bf777, 0xa4ad3cc3, - 0xf035e7f7, 0xfe7d3fef, 0x2b5fc3f3, 0x7841b50f, 0xf79410d9, 0x775fb504, - 0x22b6fb03, 0x82c7fbe8, 0xe504d7ea, 0x6be507d7, 0xcd17dfb4, 0x8b0e4852, - 0xc9fdf046, 0xe60cb960, 0xda522f8f, 0xf6ed63e3, 0xff24895c, 0x1357234e, - 0xfafe79aa, 0xa829fff3, 0xa7c80c89, 0xb21e89b0, 0xc05a30ef, 0xb9d041fd, - 0xc1f8151e, 0xbcde89d0, 0xecde99d8, 0x79ef6c13, 0xd7f03ffd, 0xd22fda24, - 0x54fb25f8, 0x9551be6d, 0xbbbd4770, 0x5f603228, 0xe2265995, 0xfdf3baba, - 0x6389889b, 0x22fc0352, 0x6744f84f, 0xfb653cc0, 0x575d5f71, 0xd4f8bc71, - 0x719b89f0, 0xd8b4687f, 0x14f1b4d7, 0xf68aa5ec, 0x6fc452ba, 0x5d39e1c6, - 0xebee176c, 0x0fd030b9, 0x70bd7562, 0x523f8d9e, 0xd550bbf9, 0x53c01f40, - 0x79d3b311, 0xea7899d3, 0x47d43bbe, 0x0df92f47, 0x47efb77c, 0xd3b412ea, - 0xd2c49747, 0xa945a639, 0x17dcefdc, 0x366135dd, 0x1e231be4, 0xf8db7d26, - 0xf74a58c4, 0xad95ceaa, 0x353ae856, 0x5f646279, 0x3c268fac, 0x4fc43639, - 0x9dfc065c, 0x38276a99, 0x426b36dc, 0xabdbfa3d, 0x085fb40d, 0xfc457e2d, - 0x3069a4f3, 0x968bb7ae, 0xb0fda7f5, 0x1a4f9fe2, 0x8ab0f787, 0x3ed0371f, - 0x4ace8b49, 0xeaf72271, 0x6a2e74b1, 0x7a910ad6, 0xcdf4a2ee, 0x1abafcff, - 0xbeb569ef, 0x0efbd0a0, 0x7bad5c77, 0x9b9e1067, 0xf74ee9ac, 0x7580de2e, - 0x3efb9e00, 0x17b7bebe, 0x089f21cf, 0xa473a2ab, 0x8bee9ed0, 0xbfb35e95, - 0xdb0b313b, 0xd0e5d6ab, 0xa39414fe, 0x956a7cff, 0x41ef09ba, 0xc2594515, - 0xa9f6fcf1, 0x75c518af, 0xa26e3d4e, 0x478e2277, 0x8fac67ba, 0xe8b8fba3, - 0x8a53b3e9, 0x3c014a3d, 0x67d0da4c, 0x96126262, 0xfb7d049b, 0x1e011544, - 0xfced748a, 0x24a4f643, 0xa527e786, 0x05b899f6, 0x97ea71e6, 0xd87ce9bd, - 0xe4e754c1, 0x2fd7c054, 0x52539cd2, 0x6e5e11e3, 0x0ffcdeb7, 0xe3fc8fdf, - 0xe404e285, 0x395287af, 0x56d1bf5f, 0xbef8109c, 0x3d45c977, 0x469bc1f1, - 0x277a22fb, 0xc14d3c30, 0x41f03675, 0x67cdc62c, 0xf00b7589, 0x219d92f3, - 0xa9e1abfc, 0xf1abd12a, 0x48d9f1a7, 0x0f5f3f5f, 0x19f5177f, 0x5f2037ad, - 0x2d7321b1, 0xa693b9da, 0x0f44ec25, 0x91fe7ed6, 0x3c230bed, 0x7985b619, - 0x7e3032c3, 0xfc871cea, 0x7aeb12cd, 0xc804b64d, 0x77ff68a1, 0xfbe73f0f, - 0xeb8f6877, 0xfe7bbfbe, 0x9fb812d7, 0x4697db21, 0x5ce83c59, 0xf458b69c, - 0xfaa38f48, 0x3cf0a7a5, 0x060bc95a, 0x2f2503b2, 0x8ad63fc4, 0x06f807fa, - 0xf3c16be3, 0x81aa63fa, 0x933a31c7, 0xad18cf4b, 0x1331b25c, 0xc99dbe71, - 0xdc86cd65, 0x3b239b89, 0x2b52cb97, 0x5ee34fd7, 0x9651efe0, 0x71e8b50e, - 0x0bf4737f, 0x7ba16d6f, 0x86c20b74, 0xd289bde0, 0xaf444c17, 0x63c58b16, - 0x13ef0dbd, 0x9031f458, 0xedca9b3e, 0x9f90bd69, 0xcde9955c, 0x7ba52843, - 0xf0df7212, 0x9e6792ec, 0xe797e3c5, 0x70da7798, 0x2765dfc0, 0xbbcbd3e7, - 0x063f8a54, 0x1f9623ef, 0x61cc69dc, 0x788fb137, 0x32c3fd83, 0xdfde22d6, - 0xf07dfd0d, 0xa9abe1fe, 0x0687fbc1, 0x2a5e4fba, 0x37730ff6, 0xe9770428, - 0x3fcf7e12, 0x8dc79637, 0xfa052e4f, 0x1ede691b, 0x0f3c10eb, 0x294eedcd, - 0xf866bc53, 0x0b0daef5, 0x13d98e28, 0x6e7184f1, 0x89e26ef1, 0xae3a4730, - 0x085e4bf3, 0xfe96fc23, 0x7e5fee6a, 0xfaf78599, 0xd702e20a, 0x2f91fbd5, - 0xde197e38, 0x9cfd941f, 0x7a63f65e, 0x45f731a7, 0x7cc31f58, 0xabd8634a, - 0xbd2067f7, 0x9f71d292, 0x5d2bb653, 0xbc5ea3fe, 0x61afac1d, 0x4ab45d1d, - 0xecc7efe5, 0x041d9136, 0x01644f59, 0xad672cf7, 0x72346838, 0x8712c63b, - 0xeedaff09, 0x1c769fbf, 0x6eeaf1ea, 0x2687b8a5, 0x51ef27f1, 0xfbf8e915, - 0x853a8574, 0x268157ee, 0x97497ba3, 0x7b5fb953, 0x679f953a, 0xd0774a28, - 0xb5f29cfd, 0x0cf2c726, 0x7dfb4fde, 0x95df584f, 0x684b9aeb, 0x26f7f33f, - 0xae54ab8a, 0x45867308, 0x3b17f3f1, 0x6af9d006, 0x51f011bd, 0xe2fae766, - 0xa56f98b2, 0x745dd27d, 0x8ecf419f, 0xdcbea1e8, 0x7963f5c2, 0x923de00c, - 0x186e8a33, 0xe8c767be, 0x9bf624dc, 0x7c602834, 0x3f439445, 0xbf7f28f6, - 0x83563a4d, 0xdf6c1b71, 0x31e21077, 0x8474da76, 0xe49515ef, 0x76b49019, - 0xaf7dfa04, 0xdeb899a8, 0x6fb55a2e, 0xf9dfea1c, 0x8de307db, 0xeaf45609, - 0xe63f6407, 0x88b7fa0b, 0x90c56773, 0x22b677c7, 0xb93cb8d2, 0x8a2f1e55, - 0xef345348, 0xf2fac910, 0xbf1e0655, 0x8a8f3d07, 0xc7d97ca5, 0xa5b96fd4, - 0x6ff50139, 0x30c36ef9, 0x6951d3d4, 0x978b2e5c, 0x011f65a5, 0x44362abe, - 0x6583bbd3, 0xe623029e, 0xca156acb, 0x4f8bbffb, 0xbf3d3e47, 0xe428b5e2, - 0xbe61139f, 0x5a97689e, 0xe8398417, 0xc795a1de, 0xe8afceeb, 0x6695f749, - 0xf82d9b59, 0x45acc19e, 0xbfa86ddd, 0x467d5a8f, 0x975a3fac, 0xd3bcc3a1, - 0xbcc6cd6a, 0xe51b7f53, 0x2df38bcf, 0xa57c83f4, 0x6d973a70, 0xbfc467db, - 0xcc44324f, 0x1f2be2f7, 0x4ff8c2f4, 0x2f737a79, 0x07c02bb4, 0xcf1052bd, - 0x9764292f, 0xf3f1b62b, 0x2a0f92ee, 0xee400f90, 0xa83e09e6, 0xf7daf5d8, - 0x902a1e51, 0xf23a43fe, 0x7ef3f011, 0x71b1df2a, 0xefdfe31c, 0x76913e47, - 0x0c2bf20c, 0xf1df8c36, 0xa71a667c, 0xe18f943f, 0xfc019ee5, 0x39fb5d1c, - 0x741c8d04, 0x1a575f46, 0xcbc587b7, 0x5d6fa44c, 0x5a1e5c69, 0x428eed56, - 0x657c5dfa, 0x67dc01df, 0x5601df29, 0x1e421eda, 0x712a3e04, 0x3f0451fe, - 0x389517f9, 0xfcff28df, 0xc85ef9db, 0xf3e32561, 0xd4adf393, 0x7acbf98b, - 0xc124fdf1, 0xe04c652f, 0x2e6f576b, 0x50ce4277, 0x0ebde98e, 0x4db73f31, - 0xf7e50efb, 0x22dcfcc5, 0x28bad665, 0x17d20fc4, 0x103e0ff5, 0x04fa9469, - 0xbedc5c9a, 0x4bf1ce91, 0x57f8497a, 0xdf403809, 0x7e6c6339, 0xf274b63a, - 0xe095644e, 0x778f639b, 0xfc07af49, 0xcf4adf9d, 0xeabf116c, 0x7c93c603, - 0x7dcbc723, 0x38ddd279, 0x87dfe86f, 0x8f71cbfd, 0xd8f4227a, 0xe5c651cf, - 0xe52fc243, 0xa1fab732, 0x614707bb, 0xee968bbb, 0x9cde7003, 0xacd2ab8e, - 0xfd13bdf4, 0x59def805, 0xfadc50af, 0x1fe75898, 0xa8b5fc7b, 0x7e7e01e2, - 0x277c427f, 0x307f0cf9, 0x6de1263e, 0x7038f1b2, 0x0f52dc30, 0x9f73b849, - 0x2c6eefb8, 0xbee3f097, 0x4a9f2051, 0x957e4a3c, 0xf982f5f7, 0xda4e7896, - 0xfe73b54f, 0x463d4cae, 0x943a77e7, 0xfc27f707, 0x5ce213a2, 0xe33c6b79, - 0x8915ff71, 0x8af735fb, 0xb40c8b18, 0xc08ed23f, 0x807d1acf, 0xa7bf69fd, - 0x8b3ce716, 0xd690bb74, 0xc73ffa8d, 0xd0398cea, 0xe699d96f, 0x9dcef871, - 0xb8ef43f4, 0x31a353ea, 0x9f8bb55e, 0x52fc9377, 0xc93f6176, 0xffb8b941, - 0x83eab454, 0xefc8e182, 0xbed035bf, 0x63e3d14e, 0xcfdfe88d, 0x187332dd, - 0x41ef01a2, 0xbb3f5ea0, 0xbf266879, 0x984d6059, 0x3621f786, 0x01ed333f, - 0xaf559f28, 0xd80dbbd2, 0xd16fca0f, 0x5f1499a3, 0x52d6113d, 0xf8fd0a30, - 0xf456a81f, 0x32df6fe3, 0x7f6c31f4, 0x0c6ba5bb, 0x39b1b63d, 0x7d4ef296, - 0xe907d934, 0x8073caf7, 0xc7dee2d5, 0x3fde845f, 0xe22a9edc, 0x2f755ffc, - 0xdd6f8fdc, 0xacef4618, 0x75ed1a14, 0x4f6f1c3e, 0x54675a17, 0x23eaf11a, - 0xbf255bdd, 0x99918e6c, 0xb9508693, 0x0fca0939, 0x451f9a1a, 0x51f0723b, - 0x3f7c60cb, 0x86d7a992, 0x9a7f7315, 0x6ac63bef, 0x70912ddf, 0x0fc6247c, - 0xdf7e4fee, 0x1b08eb84, 0xefa44fdd, 0xedf8aecf, 0x6783b434, 0xe1b4f6b7, - 0x09ef4fbc, 0xa703fba3, 0xcf77da0d, 0x57def56e, 0x79297df0, 0x9a74f56f, - 0xfc938fd6, 0x377bc37e, 0x839ed37f, 0xa5b9d1bc, 0xdd194b0b, 0x8d397efb, - 0x2263f7d1, 0xe789dabe, 0x4d6a4b08, 0x7307bc56, 0xf71ef912, 0xfcab76b3, - 0xcb99a5fe, 0x99ddc9c1, 0xe4b7bf74, 0x525f3c6f, 0x3ef178a7, 0x9fa7fef2, - 0xb30af3a0, 0xabc4cfc1, 0xf3feed09, 0xa1a7a7ba, 0xb8765c38, 0xfe7de257, - 0xf9f95bcb, 0x32ef0e8a, 0x2079dc1c, 0xdfb9dec9, 0xcbfb5dfc, 0x9f110e32, - 0x2fcfbdae, 0x4fd72cf1, 0x8c3f026f, 0xdbc7e218, 0x90e74b67, 0xa9617cbf, - 0xca4bd29b, 0x23b7b5b1, 0xe9a25b1f, 0xeb1fc0be, 0xbdf1519f, 0x835df2a8, - 0x783ae1af, 0xbd346454, 0xd2d9f293, 0x7a8fb425, 0xa5156961, 0x0e32de92, - 0x46aec777, 0xfab3eefa, 0x9fbc06cc, 0xb46446fb, 0x90b603b0, 0xdeeced74, - 0xb9d79cb1, 0x4afa701f, 0x9d6dcfb8, 0x6af38519, 0x61b63e7c, 0x2235d224, - 0x5f7e8ada, 0x724738a9, 0xabf73d6a, 0x7fa398cf, 0x3df40f93, 0x024a61b3, - 0xbb3737be, 0x5869def1, 0xb147b25e, 0xb1c07ae2, 0xae145267, 0xb7d53edb, - 0xa8fde144, 0x7bcbd74f, 0x3bfa5e55, 0xd8f2a354, 0xca3f6c14, 0x0cf667a7, - 0x7c8d75be, 0x9e82f232, 0x879ebfee, 0x5c938a72, 0x0938a70b, 0xb9e2c4fc, - 0xf3afd991, 0x3afb4af8, 0x6ef3ac57, 0x347ef317, 0x31f726dd, 0x04773ca8, - 0x61bd3f2f, 0xefec44e7, 0x158366ec, 0xb36cfee1, 0x079ffa81, 0xc01d33eb, - 0x5f2b667b, 0xd71e60f7, 0xf2b767cb, 0x3abccdf5, 0x5f29bebe, 0xfbf27060, - 0xcc7e5aa2, 0xef47680d, 0x5ef274fb, 0x9f273cc8, 0x97b03cdf, 0xbe60df38, - 0x7475618d, 0x9e9bec8f, 0xdbe60d17, 0x855f92f9, 0xd7e7687e, 0xe044f8ce, - 0xf91de513, 0xbcc3f255, 0xdedf7cf5, 0x07383756, 0x47f24ef9, 0xd5593bf0, - 0x57dfc646, 0x7bd385d4, 0xed2293b8, 0x530fb406, 0x20c65ae2, 0xe74e3e5a, - 0xab9a807e, 0x37bde273, 0xf90a6d56, 0x748acece, 0x744557ee, 0xdeefc465, - 0xcf3f2b74, 0xc97fee29, 0x86922614, 0x84527b76, 0x343b0bed, 0xaefd3a79, - 0xcfc0f47b, 0x3db76e93, 0xd8c1ddda, 0xee0bd32f, 0x267cc3d1, 0x7776da65, - 0xbff3fc83, 0xb7f3c09a, 0x201a86d9, 0x78994cbf, 0xd7c818cf, 0x4a9f3ba7, - 0xece7180f, 0x38692e96, 0x19ff283f, 0xbbc5d796, 0xa5698e7f, 0x49760fb8, - 0x24b41d69, 0xfdfedfc3, 0x7fa3963d, 0x2df3fbb4, 0x18ee9606, 0x7f097980, - 0xdd25b4e8, 0xf8f4abf9, 0x8cc5e58e, 0xf5e74e3d, 0x0e1efc3c, 0x09ccb8fc, - 0xf38a4f78, 0x97bcb15b, 0x2f741353, 0x9fefc1c7, 0xf252fbc9, 0xff5f543e, - 0xb70db27d, 0x92ec9f72, 0x2a1dff81, 0x0fbda9c5, 0x89fc34a6, 0xf6a9f9de, - 0xa23096b0, 0x4d9ef683, 0x7753be39, 0xa20bdd1b, 0x6f4c87fb, 0x57337d27, - 0xac683bfa, 0x29dff987, 0xfcfc8960, 0x1f82a3c1, 0x3d652f4f, 0x9fe8807a, - 0xca39b77f, 0x985c700e, 0xfa85ebe8, 0xfddc3220, 0xe9d7c427, 0x0ba9d50d, - 0xaa1ef0e3, 0xed0f91c9, 0x7df978cf, 0xb7e132ce, 0x42f1cdb2, 0x3bbea82f, - 0x46535da1, 0x87684ddf, 0x757c17de, 0xfe97c321, 0x192bd423, 0xed049d7c, - 0xde5d3ce8, 0xb1e2bbf2, 0x4fed85dd, 0x700d98f4, 0xbc06009b, 0xfa1e35a7, - 0xf7a3611c, 0xfb4a98aa, 0x7efe5ecf, 0xa2799e92, 0xd5eef86c, 0x3ee2e933, - 0x9413dd11, 0xeff89274, 0x1a181740, 0x999d59fd, 0xbeee1019, 0xfdfd036c, - 0xf91f492f, 0xddc2e2ce, 0x7742fe3c, 0xe31e4524, 0xe2cda748, 0xb0759fef, - 0xbf916f8b, 0xd1e9620a, 0x330d9fe8, 0x11c9db43, 0xf5d88d1b, 0xff2f6d77, - 0x92fc2e9d, 0xe0706cc1, 0xa2a5923b, 0xd0b558cd, 0x2d5bef8e, 0x7bd3378c, - 0xe85f0b25, 0x96c1fc4e, 0xb60590fc, 0x89621b63, 0xa866565f, 0xf5b9ff84, - 0x2a1dde8c, 0xf3a64fa8, 0x36f5f994, 0x12daa34a, 0x6fecfca9, 0x7ae2c9de, - 0xe0a7d389, 0xa68cba7f, 0xd3ff4b73, 0xd9d6529b, 0x6691a77b, 0xf0bbcfba, - 0x0b6bb720, 0xc7bfcaa7, 0xbbafefc2, 0xc8ae3804, 0xb90b8a1a, 0xe753dc3a, - 0xf0ba57ef, 0xe77e00be, 0x677d5034, 0xfc4a57ef, 0x82dd049a, 0x7a9cb3df, - 0xde913330, 0x59ef147f, 0x9aed174e, 0xceb3bdc5, 0x4fbcb5de, 0x6a227bb4, - 0xddf2135c, 0xc8696774, 0x9ef52d77, 0xcffa0730, 0x7a48d486, 0x373ee147, - 0xf59a97f8, 0xf11e8b4c, 0xbf9b2d30, 0xba753973, 0xfd90deb6, 0x4373e939, - 0x92778776, 0x4d8fa80c, 0xecfb6d2e, 0xf50ec2ae, 0xf6bf7d65, 0x2354d15d, - 0xbe3d4fd9, 0x69f90b3b, 0xf4515de2, 0xbfffd10f, 0xff10b4ec, 0xb83bc49b, - 0x112b2ccd, 0xbeadc2f5, 0xdbfffb27, 0xefc1b1fb, 0x03bf06c4, 0x42eb7fdb, - 0xdd607e4d, 0x6fed350f, 0xa9ae5fab, 0xad5bec1f, 0xfa6ccfa9, 0xb43f2699, - 0xfb4d39f9, 0x693647e1, 0xbcb647ea, 0xfdbfa9a4, 0xfe4d0ecc, 0x683fd68e, - 0xb6d9dfda, 0x61cf9357, 0xe7da68ef, 0xe4d03f9a, 0x57ff5ac7, 0xc4aefed3, - 0xf1fa9a13, 0xfa9af3f6, 0x68ae7d09, 0x2f8e05f2, 0x373fed35, 0x457757ba, - 0x0cea22bf, 0x433aadf1, 0xf944f861, 0x6629a6e5, 0xba6b07d4, 0xf8247d0a, - 0xd3b0b96f, 0x7ba307ac, 0x6cd563ac, 0x3d5ff11f, 0xc1a0bbff, 0xde7f4f76, - 0x1ff8c4e5, 0x6bdf8d7b, 0x527f068b, 0x8c7e301f, 0xff02ccd3, 0x9e6c5dee, - 0x778f9355, 0x77da6a25, 0xd4d76e99, 0x68fbb927, 0x38e653ea, 0xaab4f934, - 0x5df69a11, 0xf9353897, 0xa69e4f0c, 0x971af77d, 0x76b3df26, 0xef7da6ba, - 0x7d4d6ef5, 0x4d1cef5f, 0x55adff7d, 0xbac0fc9a, 0xb7f69a25, 0xf5347bd5, - 0x9a357d83, 0x5aa6ccfa, 0xf3687e4d, 0xe1fb4d7a, 0xfa9abc47, 0x355b2d91, - 0xa99fb7f5, 0x68efe4d3, 0xbfb4d7ad, 0xc9a7cdb3, 0x9a83b0e7, 0xf7e6b9f6, - 0xd6b1f935, 0xefed344f, 0xa9a63c4a, 0xab3f6f1f, 0xce7e97a9, 0x6b9f3e84, - 0x53df85cb, 0xe697f8e0, 0x6ef7f6fb, 0x1f742877, 0x6ed75cea, 0x96c57df2, - 0x24fd1530, 0x6c99c517, 0xf5111078, 0xb727de15, 0x8539f3f1, 0x238aaf14, - 0x944c887f, 0x810bcf1d, 0xab8510df, 0xf40c8cb6, 0xfefc23ab, 0xccf5ea5b, - 0xdadff79b, 0xd5dcff84, 0xf288beee, 0xfb6eaf31, 0x989f7a38, 0x1c225679, - 0x77bffdf2, 0x956dde83, 0x19f378e9, 0x17f00fa6, 0xa6d5860f, 0x389af90e, - 0x05f378c1, 0xb6c1ef86, 0x22e22bf7, 0x17bdc7f8, 0x16bff406, 0xf7f817d6, - 0x9a976b23, 0xffc76fe9, 0xf295a96c, 0x522696eb, 0x3a00fffe, 0x0047bf29, - 0x000047bf, 0x00088b1f, 0x00000000, 0x7dedff00, 0x4554780b, 0xeedd7096, - 0x9d248fdb, 0x777579d0, 0x493cdc9e, 0xf09d0848, 0x3a3e00d8, 0xc0406021, - 0x490435e6, 0x41a8c1a4, 0xf881ba43, 0xbb75744f, 0xb2021031, 0x10d191b3, - 0x0186c195, 0x099d1964, 0x09d1a32e, 0xe09af09a, 0x1c604c3a, 0x3719d9c5, - 0x8ee2a3a0, 0xcfe31e10, 0x7fc38fee, 0x937ba9ce, 0x380e9dbe, 0xf7ff3afe, - 0xb4fbfa3f, 0xab755538, 0x739d554e, 0x2aaa3cea, 0x89895ead, 0xde6d6322, - 0xf39f4a1c, 0xc99899da, 0x316f36d8, 0x0ebddbc1, 0x72defd82, 0x9d7a774a, - 0x5bcbbf94, 0xaf1ef041, 0xdebdd28b, 0x79f74a1a, 0x92fe543d, 0x9fe081b7, - 0xb6947d7a, 0xff299b7b, 0xc10b6f15, 0x046dbc07, 0x53f5eabf, 0x4bdde1da, - 0x76de1be9, 0x76f4ef2a, 0xb7a6fc10, 0x6f2ee08b, 0xbc87c10f, 0xf11f04bd, - 0x98f8269e, 0x1ed28fb7, 0xbe9467ef, 0xf2a7eded, 0x0957bc77, 0xdbbf8ebe, - 0xcd2afc19, 0x2631e49f, 0x7ae69730, 0xc9ccc21e, 0x00f63226, 0xff824bfe, - 0xcc8846e2, 0x8cfdd8c2, 0xb0d73eff, 0x9413769a, 0x3ff2fe77, 0x74c60285, - 0x1f8d8ca5, 0xf662690f, 0xc634c6ce, 0xe675b026, 0xd318724f, 0x63d75740, - 0x4e09fb07, 0xd6191319, 0x2d75dfc3, 0x58c7dffe, 0x94bffc3c, 0x834c78e5, - 0x14095369, 0x55befb42, 0x1a777f82, 0x3e20d755, 0xbf1c8dab, 0x95135a69, - 0xf82c3e57, 0x5563020d, 0x8be9f322, 0x587dfb18, 0xc11b0154, 0x2e8f25d8, - 0x2172c447, 0x04830edc, 0x443a8ff8, 0x2c5d7e0e, 0x9da5b18e, 0xd29b1d86, - 0x84aaf106, 0xfdf035ef, 0x0c1a562b, 0x3a3d64ab, 0x1df203c4, 0x9ec618da, - 0x4ba6b8b7, 0x8a60ff90, 0xf687a7c6, 0xed9fc999, 0x2dec648c, 0xe6066b8b, - 0x77dcf25f, 0xc07f1b0c, 0x7ec6cf6c, 0xe2ba1b66, 0xfdff4117, 0x9df6b5c7, - 0xe1f3f0d2, 0x6c67296e, 0xdfca0ddc, 0x02ec973c, 0xa2ffca3c, 0x9ffce175, - 0xf85645d0, 0x492f01f3, 0x1a4a78e0, 0xeadb3a55, 0x7cf8825a, 0x47b9e919, - 0xe5f85303, 0xacf6ab6d, 0xae552181, 0x82e11aca, 0x2582eeef, 0xcd8c1963, - 0x418e9265, 0x38e67cf9, 0x2d4d069a, 0x17822e64, 0x6fa51f31, 0xb1aabbc5, - 0x4fccc59d, 0x21b26bb0, 0x82b8d435, 0x78cb72f1, 0x947c65b9, 0xabab71f4, - 0x20e5e38e, 0xba4c4ebc, 0xa5c71b23, 0x5596f5e0, 0x58737aa2, 0xefc476ff, - 0x3f1783cb, 0xd2863211, 0x174077c7, 0xeb1e6826, 0x73ac3d31, 0xf7d18ea3, - 0x7e088f8d, 0x2e856ba4, 0xb791992a, 0x0be418fb, 0xf4027481, 0xd2fc8451, - 0x92373a9f, 0x0949e4e8, 0x92707c1a, 0x0b1fa7d6, 0xb3f8d4e3, 0x87d12d05, - 0x1efc005e, 0x48fa0388, 0xea0e9e1f, 0xe00d219a, 0x67afa01f, 0xaff3bdb0, - 0xce0e5dff, 0x49cdfb97, 0xa357ce12, 0xe801d606, 0xd6b6f7d8, 0x99925bbe, - 0x94ed6014, 0x6ba47e31, 0x73edda26, 0xb17ae0c7, 0xdfa84ea5, 0xfb0d65ad, - 0xfbf687f3, 0xb417ae2a, 0x2ba6c27f, 0x9cbb53f7, 0x9ff295cf, 0x63c5fae2, - 0x5eadebca, 0x16ad69f5, 0xe8713ff0, 0x131a5e9c, 0x6f0d1c62, 0xe00666e7, - 0x3338eeef, 0xe44261dd, 0x45e7f2fa, 0x949fe60e, 0x1fa144e9, 0xb5d23ead, - 0x178814c3, 0xf9e817ef, 0xd13744e7, 0x4419cf40, 0xe0f89fcf, 0x690639d3, - 0xfb4822c4, 0x20ba6a60, 0xd660bd75, 0x672cdd23, 0x99ab4a76, 0x6007d293, - 0x9d7e91f9, 0x38f4a7be, 0x76b20fef, 0xbe2bafca, 0x7cf482d7, 0x8a95c6bf, - 0xa5eb2d70, 0x2feb377c, 0x2dfcc1b3, 0xd47b5e6c, 0x6fcf5806, 0x025a6a79, - 0xff3cefcc, 0xce98a3b2, 0xe27c25dd, 0x7a3f8893, 0xc13eaf10, 0xfa113eb3, - 0x92a5fbbf, 0x3f9049f5, 0x85d7cb47, 0x175f2bfd, 0x8f047e45, 0x97a1f81b, - 0xe341cb8f, 0xab9546d2, 0x09f2a1f8, 0x9da010e6, 0xff0683fe, 0xfe00b4ce, - 0xdfe87e28, 0x898e5093, 0x7ae0f7fd, 0xc434dfbb, 0x083f7ae0, 0x29c71be2, - 0x806b1838, 0x2ad690fe, 0x882a8863, 0xe1621fde, 0xb9f7ac76, 0xa79fdf4c, - 0xcfefa230, 0x4060e605, 0xa67417bf, 0x5ae50166, 0x0456cbaa, 0xbe60acf8, - 0x6ee50626, 0x38054bcd, 0xd725234f, 0x1fd744a7, 0xa61537b5, 0xa7f7fca1, - 0xf7ff280a, 0x698dec19, 0x5d84fdaa, 0xe321408f, 0x3f9f3861, 0x0ec776c0, - 0x3e284bc5, 0x14429ff6, 0xf33d0663, 0xbf888b19, 0xebe444d9, 0x57f13d44, - 0x066d4e23, 0x3c94e3f6, 0x9feda1a6, 0xf9edf190, 0xef744b4a, 0x16ecf183, - 0xf7c3f542, 0x60f8432b, 0x2c3f243f, 0xa7d1fa8c, 0xfa563e71, 0x64bea663, - 0x6a75d027, 0x86974b84, 0xc716c182, 0xcb998be5, 0x4fb49e97, 0xe67d7133, - 0xc8a8de4c, 0xdd8f6a65, 0x09d1e5c6, 0xf843e49d, 0x1d9a4944, 0x9c80d724, - 0x97f8abbd, 0xbb8f11a7, 0x2d2ea68c, 0xdd16eca4, 0x7d94fa9f, 0xff707d30, - 0x7fd94bbd, 0xeffbe16f, 0xefb5991c, 0xf1babb12, 0x3aecc67b, 0xfd972fc4, - 0x6d8f995e, 0xf22adfb8, 0x0b7ec871, 0xf9c5eb03, 0x832b2513, 0xc7c0b574, - 0xdc253abf, 0x36c47c8f, 0xf4f8d2e7, 0xfe0cfcb2, 0x58c15ade, 0x13c651a6, - 0x19704bfe, 0x20ce6659, 0x5663549c, 0x9b1e29c1, 0x06c8feaa, 0xe69e5549, - 0x679551cb, 0x7055db34, 0xaab14b56, 0x8736a8fe, 0x97f5ce0a, 0xede7eaab, - 0x31e0aa75, 0xfaaa15ed, 0xaa5c3b63, 0x1aaec2f2, 0x1eb8f955, 0xd09e0a8f, - 0xffaaa0db, 0xaa7da777, 0xcd7d49f2, 0x9f29f2aa, 0x5be0a8b5, 0xf554dbfb, - 0x57eabf6f, 0x7fb09795, 0x354f9556, 0xd3c157ee, 0xeaabafcc, 0x16fb80bf, - 0xb61dcff0, 0x0cfe556e, 0xbbeab8e9, 0xaa4e733b, 0x75e417e0, 0x270e2df6, - 0xe72d68be, 0xfb6cd1fb, 0x5876aa07, 0xfebe68e7, 0x7b6f3c61, 0x510b1fcf, - 0xf4d76e4e, 0x4add21a7, 0xf222735a, 0xdcf16671, 0x2c664043, 0x14aab1db, - 0xf94e5bc5, 0x1d308753, 0x8a5fdced, 0x715f926c, 0x05a610f2, 0xd0a58bae, - 0x44d7b31c, 0xc8b4c61f, 0x8ad53853, 0x3dcc34a8, 0xdf44e98c, 0x5728a9aa, - 0x3f5c785f, 0x2a28f91a, 0x074fa146, 0x827d67d1, 0x7eb9f886, 0xf28fc9b1, - 0x24c532c7, 0x96139032, 0xb1d65a1f, 0x9a8b4c02, 0x1af66d31, 0xfa0f5f99, - 0xba519780, 0xfe666bc9, 0xaf67206c, 0x93fae08d, 0x43a795f7, 0x44ab233b, - 0xe699aa33, 0x48258f51, 0xe5f5bed0, 0x765d9c96, 0xb0edd6c6, 0x42e5d7cf, - 0xc59e19ff, 0x4e01a23b, 0x30058e63, 0x2398167f, 0x25b19936, 0xfa76df3b, - 0x97c287f2, 0x244d9d33, 0x5cf6c417, 0x7694ffd4, 0x6e7e9637, 0xdf2198d7, - 0x11e74bf7, 0xf1adf798, 0xc21df4e1, 0xa75f9925, 0xb60b475d, 0xf69ef90b, - 0x4cfc7c10, 0x977fdf1a, 0x0a7d73a4, 0x66eb8487, 0xacc6cbe5, 0x808ca7a0, - 0xa93adcb9, 0xf0ea0ce1, 0xa027d9a2, 0xe0d7627c, 0x892b907b, 0xe0832958, - 0x4e01c3db, 0x6c625840, 0xc7eb967f, 0xc5d5afd8, 0xfa00d9d8, 0xc351a849, - 0xcf9e615b, 0xa3e20e66, 0x89f1aa5b, 0x8fdd0630, 0xf43b769d, 0xc60aadb3, - 0x3d56f00b, 0x7a9437d7, 0xf68c34a3, 0xf8d32ff7, 0xcdaece7e, 0xf49ea3b7, - 0xe79e3ca5, 0x3e8bfdbc, 0xeb7b44ce, 0x3589a52a, 0xf205c11e, 0xb4e95acd, - 0xae9ea0fb, 0x8423e611, 0x348bf2de, 0x1dd7be91, 0xa090447e, 0x1269a7de, - 0x7e9589c1, 0x0d52771a, 0xbf801bb4, 0x6609f44d, 0xe63db7c8, 0x9b3f1013, - 0xf06769d9, 0x885a331d, 0x3cc8d7fe, 0xcbf86b61, 0x0f418fa2, 0x769d79d3, - 0x13bba7ac, 0x271f33e8, 0xb86663d4, 0x47e3c94e, 0xa3eb10b0, 0x0d3e86a4, - 0x9f40dc73, 0xd47d4a8f, 0xddc5fb43, 0xe80b2926, 0xa6c585fb, 0xda211d8a, - 0x9f9e54fb, 0xfeea310d, 0x1f3e5a2d, 0x6cbedc8a, 0xf0a8ebe6, 0xa6689af1, - 0x526be392, 0x846f5bc6, 0xc8cdb5af, 0x6ef8015c, 0xd0cc7e85, 0x55abe1be, - 0xe83f1c66, 0x4fea4ed0, 0xc764f2e4, 0x6ec8728f, 0x21c75e0a, 0x3f9408f4, - 0xa3e908a2, 0x7c08dfcf, 0xdbd2a868, 0xfeb26f51, 0x7b809343, 0x116b2273, - 0x5358be50, 0xdc447aca, 0xae5744d7, 0x793e8433, 0xd654ba33, 0x839fd94f, - 0x3d774bd7, 0x9c12fde3, 0x31d57fef, 0x1f56c7d4, 0x05718f8f, 0x3a4c53d0, - 0xd662cba7, 0x98fe45a2, 0xbd29dacc, 0x7a52f585, 0xd4a7eb1b, 0xa622ccc1, - 0x694ecca5, 0x3a527319, 0x2d28799d, 0xce942d67, 0xce94ed64, 0x8294bd62, - 0x93a9433d, 0x9aeec999, 0xa637fb07, 0xd293980b, 0xa50f31ef, 0x7e9ce999, - 0xc10b582b, 0x4a76b377, 0x24ef803b, 0x8c01fa3d, 0x9c827694, 0x904df4c3, - 0x79769873, 0xa3652625, 0xd287201f, 0xa53b5e23, 0x94c5bcc7, 0x541d78f6, - 0x396f6def, 0x9d78efa5, 0x56f09e94, 0x75ebda50, 0xde53bd51, 0xf5df4a1a, - 0xcf7d287a, 0x69e940db, 0xdfd28faf, 0x1d299b79, 0xc67e07a5, 0x2be9cdf9, - 0xf53e7d44, 0x0243bd23, 0xe591ecf9, 0xe68761d2, 0xb8f1dc99, 0x40661a6e, - 0x235b283a, 0x7359fd20, 0xa43f0e34, 0x0b56729b, 0xe1ba42f7, 0x0cdfd704, - 0x0fd248d6, 0x82f56dad, 0x0876ed04, 0x5808da7d, 0xa9e9e9cb, 0x9f208d73, - 0xbad93a4b, 0x19c23b08, 0xee81194f, 0xfd3ce876, 0x64bca03b, 0x08d734a7, - 0xc8e4d67b, 0x8fb1ff53, 0xe93e54c3, 0x03346b08, 0xfb3d2b3c, 0xe38138a9, - 0x7befc281, 0xaee6733b, 0x253c44cd, 0x34c5f3c2, 0xbf512c30, 0xfa44c47e, - 0xd9db6175, 0x93c00d42, 0x68454c1a, 0xebd40617, 0xae1fba42, 0xf2b9705e, - 0x9655b6dd, 0x0d879c46, 0x0e5a809f, 0x7d19a959, 0xd5f3ab85, 0x5ebe6aed, - 0x837b4cff, 0x09eb03fe, 0x7f6f6837, 0x7d32a396, 0x3a7effc2, 0xdd6fa60f, - 0x6bf68ff5, 0x8e640fc8, 0x5774fdc1, 0xfd339734, 0x04ee9fa0, 0xc8c577bc, - 0x1a4cc6f0, 0x5c43ca17, 0xd29b0db7, 0x77803efd, 0x1f573985, 0xd47ff2c7, - 0xd14277d8, 0xa6d770ae, 0xc933825c, 0xc621b13f, 0x8f931393, 0x97df3cfa, - 0x0d1f935a, 0xbff80293, 0xafcb9d39, 0xe95cb7ad, 0x447681dd, 0xc16586b3, - 0x979b3b77, 0x7681cc6f, 0xf419bc7e, 0xdc478007, 0x0b31bd5a, 0x6a37d3ca, - 0x19656a26, 0x78fc7887, 0x4d9ef573, 0x8f255fa8, 0x7686c98e, 0x99796433, - 0xb857db1a, 0x55bce806, 0x95a7b6af, 0x7e649ff4, 0xce6686a9, 0x954d6c82, - 0x3a1df4ed, 0xdfb81156, 0xefc64cfd, 0xd53c5957, 0x57fdcedd, 0xfee19186, - 0x25fc6027, 0xc3bfb923, 0xfe48ceb2, 0x7ff24b0e, 0xca03bc9d, 0x7634db2d, - 0x6b44e954, 0xea1d5aed, 0x3b598bfb, 0x810ee3f2, 0xe14bef7f, 0x0a28217a, - 0xec0373e9, 0xd3deadf2, 0xfc03328b, 0x9f0ab684, 0xc97bf680, 0x0fa15ac8, - 0x07e49ff7, 0x2dfbb405, 0x15c12e15, 0x8781f689, 0xb965cfca, 0xf80e927e, - 0xfbe12ad9, 0xb992fd40, 0xa15d7012, 0xd2768adf, 0x605158f3, 0xf8b3a77f, - 0x3b07ac3c, 0x75d5f499, 0x782bc27a, 0x97654ebe, 0x95f6c01e, 0xff2e0c75, - 0xabb7067e, 0x5d013d77, 0xe24c1f20, 0xdd89f376, 0xce3fa489, 0xa0770d69, - 0xa9e274fd, 0x6f0465d1, 0x3d40ec99, 0xc9eec4f2, 0xb39d31d3, 0x3bd52665, - 0xb41eb021, 0xb96ce787, 0xd4fcc45b, 0xdb0bc00c, 0x7a27a33b, 0x41e5b39c, - 0xcb47fbf9, 0xe358bcb0, 0x91da09fb, 0x22fb8dc5, 0x1c9e4ed0, 0xa6124af9, - 0xf57d3427, 0x5dffd0dd, 0xdc2bf666, 0xe31b9d9e, 0xfe1cb1fe, 0x74a9f731, - 0xbfd7ea1d, 0xf5a74f4b, 0xc41ccf9c, 0xec835007, 0xf6f65bba, 0x8a4d061e, - 0x3fded6dd, 0xe65ccc15, 0xc11f30e8, 0x5ecbb4b4, 0xd657d386, 0xe9823ce3, - 0x194f5ef4, 0xa7e52faa, 0xba608e5b, 0x3bf5d724, 0xff179f9c, 0xbcaf7be1, - 0xc7c8f008, 0x07a8cdeb, 0x37d13e65, 0xebf92763, 0x21f90c74, 0x45a7926b, - 0x746c048b, 0x787ca0c6, 0x835169f6, 0xad21b9fb, 0xc3610c25, 0xb41ae97d, - 0xb745770b, 0xb3b8d0d4, 0xe3ce19c2, 0x210fb0db, 0x3b45645d, 0x809f9063, - 0x3e1d692f, 0x10d3e993, 0x634731ed, 0x1fcf187e, 0xe1ce17a8, 0x5af503f3, - 0x27ea04c2, 0x13fb2046, 0xbfdc06d4, 0xddfef26d, 0x38093cc6, 0xcf48d61f, - 0x64ebf40e, 0x67fe7095, 0xb02e9c91, 0xfa44d37a, 0x96cd9c84, 0xb89dcf16, - 0xe897560e, 0x3ba40beb, 0xf40706d8, 0x19827491, 0x055bd7da, 0x219c830e, - 0x7e87f0bc, 0x42c98b0c, 0xbf828d7a, 0x0bda02b5, 0x1c7033d0, 0xdf834cf3, - 0x9b177429, 0x4235c7c1, 0x65acbfa6, 0xdf053dbc, 0x9f2e0cb8, 0x83496f01, - 0x7c6568f8, 0x009a1c60, 0xd1ea027c, 0x66f006f8, 0x05d21b76, 0xa7817a48, - 0xc703124c, 0x8471ad5f, 0x7a645da1, 0x4fe8fbf5, 0x02394289, 0xf753fe78, - 0x69f22324, 0x327238f0, 0x46df08d2, 0x6f5187d0, 0xfce2e99f, 0x11e958db, - 0x18423ec8, 0x3a2c9fc7, 0x35681fd0, 0x017416ad, 0xf326b5e3, 0xa5667a7d, - 0xcae51ba7, 0x3b08e2cc, 0xac9df7d2, 0xf3999d7d, 0xc04c91f7, 0xf81b146f, - 0x41c4d899, 0x4f47f0bd, 0x97127bbf, 0x97b59934, 0xf9fee2e4, 0x70b3fdf8, - 0x3a3eb6fd, 0x4ff107b3, 0x3baa79cc, 0x5e741a06, 0x197dd794, 0x6ca4ebf7, - 0x1c0e3f13, 0xe0079247, 0x8d44bf40, 0x41e81cba, 0x65742b05, 0x71a21a13, - 0xe444d1bf, 0x7a819ccf, 0xe486944a, 0x6129c83b, 0x33fd4841, 0xf9e4ae88, - 0xaee7d657, 0x375a4c8c, 0x03af89ab, 0x171bb7eb, 0x5583ca46, 0x6dfa09d6, - 0x011f3604, 0xa658df74, 0xd7680bf5, 0xac28fd62, 0x919de2cf, 0x8769d743, - 0x03399a4e, 0x1ac3f4e5, 0x74366ef3, 0x7edc815e, 0xc3ed7a4b, 0xf90e5471, - 0x7dfc91a2, 0x436af801, 0xb8f5eac1, 0xac6dfd59, 0xb48cee6b, 0xc989f9a1, - 0x3ee2660b, 0x68cb589b, 0x47cb83fd, 0x575ea63d, 0xa3c737b2, 0xbbf988ff, - 0xce7ac1be, 0x8655de4c, 0xbaf07cfa, 0x1a97742a, 0x105f7a1b, 0xa65f3933, - 0x954fd846, 0x92215e93, 0x114ce09e, 0xa2ed03e3, 0x1f7c190d, 0x1335fdba, - 0x23ec43ed, 0x5cb71fa3, 0x93ef577b, 0xa50eb0b9, 0xae683457, 0x1cefa3b0, - 0x484ce1fa, 0xddeafda7, 0xf50affd5, 0x1a657da6, 0xb06ff987, 0x10e819be, - 0x9d80f5f1, 0x2fdaf001, 0xa3a0b4f6, 0xd992b1a4, 0xfa55df71, 0xf3f723d9, - 0x49df9d0b, 0x645735f2, 0x820e493b, 0x2f401e65, 0x7e896900, 0x56731978, - 0x68dd90b6, 0x5907cccd, 0xf6bd6e8d, 0xfe5fb425, 0xefd0cf49, 0xd242af38, - 0xe7f8c095, 0x65ba4a55, 0x5917c7e8, 0xf311ea39, 0x3f94ec2b, 0xf3ced2bf, - 0x417f3c8d, 0x17f28385, 0xbe783a54, 0x3e61f209, 0x7bf85616, 0x42eed0bd, - 0x41a48c53, 0x93a5783f, 0x50355f97, 0x0f603bf9, 0x87c90264, 0xde49f987, - 0xe1a67cb7, 0xb84f12f1, 0x0d5c005f, 0x123d4591, 0x1a7ddfce, 0x8624167b, - 0x01999114, 0xe9c2b67e, 0xf3f942d7, 0x13809fcc, 0x6af546f9, 0xbfe43667, - 0x719a2c91, 0xc0386f7c, 0xabf9c66e, 0xe9de6915, 0x351bf007, 0xd8cf14c9, - 0x7dadfb21, 0x67e48c2b, 0xfc875d05, 0xa2456cac, 0xf2f0c7ac, 0x7ecdcb6d, - 0x0e40c7d4, 0xdff63ad2, 0x001e9227, 0x1cedf0f2, 0xca5e8bd4, 0x484987b4, - 0xb37e6ab7, 0xa12f2f54, 0x19992af6, 0x9559f2ed, 0x97c6bdbc, 0xea0d7e34, - 0x3379a655, 0xf71a0e91, 0xafda3b32, 0x2a9f56cf, 0x9b78458b, 0x87e5cedd, - 0x56342e5a, 0xe12e396f, 0x731a3c78, 0x7ee7d516, 0xe94f46ad, 0xc830ad2e, - 0xd2deb4cf, 0x2a18fca0, 0xd83dec6f, 0xa955424e, 0xb3d4137d, 0x8fd138c0, - 0xf3cf4dbd, 0x1488f77d, 0x8b54b067, 0x4182e65d, 0xa7914efe, 0x187c82d0, - 0xc545f245, 0x525fa35f, 0xf9923fc3, 0xc45df814, 0x3176f971, 0x5d95c93b, - 0x27207aea, 0x52af2835, 0x67f9d4da, 0x2fc504b2, 0xe0879aa5, 0xb87ab679, - 0xe71e0bdc, 0xc2bab8e0, 0x34b8d146, 0xd7285c7c, 0x74d73f20, 0x2b73f288, - 0xa124bb45, 0x853f6bbc, 0x92f51fe3, 0x9e00bac8, 0x13345d55, 0x66d669e9, - 0x6643b90d, 0x0b925eb3, 0xe2b71b37, 0x671e08df, 0x6436f8f0, 0x1cdf6968, - 0x1bd707d0, 0x7d6c1f49, 0xb8c1a4c4, 0xe15be822, 0x973857e8, 0x099e1a55, - 0x532230f3, 0x6bafd7d6, 0x34693cb9, 0xacea9d11, 0xfa04e58f, 0xa5d1841f, - 0xeebeb023, 0x72bcec7a, 0x68e91b8a, 0xac72c1dc, 0x93639658, 0x2a7c60fa, - 0x933873ff, 0xd6f7e602, 0x7c1518fe, 0x5544d5fb, 0x2e1012fd, 0x8d53e581, - 0x69f2aa79, 0xf82a71e6, 0x5514db0e, 0x54d219fd, 0xce677c15, 0xb3faaa9d, - 0xf055f3ed, 0x544bc55d, 0xee3ae7f5, 0x2fcf9555, 0xbe55487f, 0x0546b9d0, - 0x7bf8aa2f, 0xaec5fd55, 0x92f95546, 0xe555279a, 0x9293f6c1, 0x3f726696, - 0xe79b56cf, 0x8be483a4, 0x0e46704b, 0x14a967ad, 0x3dd703fb, 0x53eb822a, - 0xe51af5c1, 0xe04178f5, 0x48feb1fd, 0xe29df20d, 0x91ed637f, 0xd75cff2a, - 0x3ec6c9e4, 0xec72fa13, 0xb2dd23ef, 0xc51fdc13, 0xc53bfcfc, 0x04fdd57f, - 0x56f683d4, 0x715ba647, 0xabbf43bf, 0xf9fd0f4b, 0xb7bfe435, 0xb40bd736, - 0xe7ae6e0f, 0x7aab957e, 0xc00d8ae6, 0x7ef38583, 0x828e78e5, 0x70447327, - 0xcf1860ff, 0x95fb26df, 0x52bf439e, 0xb03f6336, 0x17787e28, 0xac509bb5, - 0x467fa1f7, 0x7a08f6a8, 0x662e5b94, 0x07284836, 0x97ff5397, 0x5823ec2b, - 0xd2567988, 0x398daf56, 0xbd5b7da0, 0xc61ead6f, 0x69399756, 0xbcd0b3cb, - 0x1fc8c3cd, 0x94e668f3, 0xe7816b2d, 0xa25321ff, 0xf9104975, 0xf75f3f3c, - 0xd03db9c6, 0xa5956b5f, 0x706ae508, 0xf3bb9279, 0x941bb1e2, 0xd5f2bf3f, - 0xd1bfee0f, 0x671d75f7, 0x87ca029a, 0x24568bf5, 0x1d004732, 0x7ed08648, - 0x74c81ff9, 0x27ac9ee5, 0x5a33d63f, 0xcfc893d7, 0xd7ff2617, 0xddf0bdc4, - 0x3dcae979, 0xfe43a7a8, 0xea1f300f, 0xcf9ebcd1, 0x29e744bc, 0xbf40f352, - 0x2c3bfd47, 0x941edd34, 0x95ad17db, 0x5a07e8fd, 0xd097a91d, 0x7e324fce, - 0x0eea7e46, 0x83abb71d, 0x07e7f7ed, 0xb276edec, 0xedcbf7bf, 0xad5396ec, - 0x8ccf7f99, 0xe45a263e, 0xf98840f8, 0x09b546d0, 0xab12af28, 0xf9024fc5, - 0x4f523ba2, 0x498b047e, 0x6a983bf6, 0xc5017e54, 0x791dd06f, 0x6f7480bf, - 0x7e415ae9, 0x6017f47a, 0x75e5077b, 0x2417f609, 0xe8b4ff19, 0xb51bd8e3, - 0x23f206cf, 0x04fd1084, 0x27f8a1e1, 0xa3f1fb82, 0xccfb813e, 0x27d270ca, - 0x397dc782, 0x6650e4b3, 0xff48f23c, 0x7e503bc9, 0x7ed1d29f, 0x84bd1c38, - 0x1fcce149, 0x266f7ed0, 0x7223efb7, 0x91f95462, 0x0fe644f6, 0x64b35ff4, - 0x321127f3, 0x48cc5b0c, 0x51c6df7d, 0xbcdbdfd8, 0xbb3a13bf, 0xd841f48d, - 0x7bfed0f6, 0xeee7e64f, 0xab69465c, 0x01b7976c, 0x9cfa631f, 0xd9fa4cd7, - 0x843fe036, 0x4a257bb7, 0x4a1cdefd, 0x54ed7a77, 0x4c5bcbbe, 0x83af1ef0, - 0x72debde0, 0x9d79f74a, 0xb792ff94, 0x7a9fe082, 0x7bb6945d, 0x15ff286b, - 0x03e087af, 0x5f8206de, 0x44507d45, 0xa533753f, 0xa85b786f, 0x46dbd3bc, - 0x3f5e9bf0, 0xbdde5da5, 0xdbc87f94, 0x6f11f04e, 0xbcc7c107, 0x78f7045d, - 0xdb7d287b, 0xeff94bdb, 0xdc134f78, 0xb1938f2b, 0xfa2f5ee6, 0x84a25c2b, - 0xaeb3ddfa, 0xd7ea336a, 0x331a65b6, 0x9736f38a, 0x39fa0566, 0x78f255b6, - 0x86956d9f, 0x87a040fc, 0xb39f51fa, 0xf8fa7b2d, 0x405f2a34, 0x49b15be5, - 0xabac4a30, 0x56cafeb8, 0x159ea9ea, 0x77c1020f, 0xfd2b6adb, 0xb25b805a, - 0xbadca9c3, 0xedbb244a, 0x3a278d79, 0x245deb9b, 0xae3aadbf, 0x1074283f, - 0x22e9fb21, 0x974a44b2, 0xa3fc7365, 0x23ef4232, 0xfc4a5919, 0xc707b9a4, - 0xf182ab67, 0xf555be21, 0x5a5f8c46, 0x49f183ef, 0x3aae3fa4, 0xc3247804, - 0xc07f1178, 0x6cc2fc87, 0xad97d719, 0xaf08eb55, 0x94f365e4, 0xda346778, - 0xfa9e6de9, 0xa56f84b9, 0x36cd7e48, 0xfbe8a1d7, 0xe7ca4e50, 0xe1f1ac7c, - 0x50fe7f4e, 0xf082327c, 0xddb8c6df, 0xd2fa0c90, 0x00e310fe, 0xc7a9478b, - 0x198f78fd, 0x26f1fa43, 0xb2627acb, 0x3d8ff9c0, 0x6dff122c, 0xc1f7a067, - 0x7e81cf77, 0x503943e7, 0xfa156fba, 0x72cd1eab, 0x3c02cc4d, 0x3f8d247e, - 0x531c0224, 0xaf4fdbce, 0x1ea0f717, 0xae7deb0d, 0x3e37f209, 0xb689d9b8, - 0x6966ec71, 0xdb5bb22d, 0xd01357b2, 0xa82c95ff, 0xcb4947d7, 0x3bb63c65, - 0xd5cf7b78, 0xb64fe48b, 0x76903aae, 0x865bf784, 0xfa8e26fd, 0x61ba187d, - 0x1a481632, 0x55c91914, 0x2fec45e2, 0xe5cda1ec, 0x66fc5fd8, 0x215fd287, - 0xe775f7f6, 0x65e3e469, 0xbc085756, 0x37279386, 0xb38b2393, 0x8e48e322, - 0x9424b124, 0xb8ebcf23, 0xe49df2dc, 0x861d24fa, 0x1fb43499, 0xc4ae7e25, - 0xe8e383d3, 0x243d3235, 0x61c74219, 0xfde80d57, 0xddb7aa3e, 0xe749c9b1, - 0x0b3e304b, 0x6c75ab45, 0xeaf3ae05, 0xdaf37092, 0xa4a0f410, 0x018e505b, - 0x468bdfdf, 0xb9b3b523, 0xe1a3b79c, 0x56cadced, 0x32625c11, 0x6bc842fb, - 0x6e5a7d25, 0x4e2c81e7, 0xbe0f49b7, 0xae18f1b4, 0x3a3adbef, 0xc69cf413, - 0x04ed11bf, 0xc92d09df, 0xfb6d44d7, 0x78013d8e, 0x79e3cb35, 0xb5cfef4e, - 0x7b40ff23, 0x915728f9, 0x7fc9f25f, 0xcc0566c1, 0x5addf2bb, 0xa3fd8fd9, - 0x29a21b6b, 0x2eb55cbe, 0x36a3f50c, 0xb07a2466, 0x85d13cea, 0x4560f401, - 0x1f410cba, 0x4af4b2fb, 0x3254d53c, 0x7c32e311, 0x728a9e5f, 0x583ef009, - 0xe1fb451d, 0xdeef65d4, 0x5be01639, 0xd47688ae, 0xe5ab9ecb, 0xfd2713e7, - 0x26e74351, 0xdb9c7cde, 0xb7fdb77d, 0x7bf41eb2, 0xb3e9c827, 0x7a41e768, - 0x77b3334b, 0x52dcbac1, 0xcdff226d, 0xb3c557ad, 0xb91a7681, 0x7da3c7a4, - 0x5335fdc1, 0x803ca1fa, 0xa67d26fe, 0xaa330fae, 0xa1233d45, 0xab6f9d4f, - 0x1a66703a, 0xcb56d3f4, 0xf6bb6e3f, 0x7d8471fe, 0x93f21af5, 0xf429f500, - 0x4dfe4093, 0xe78097d1, 0x191a3716, 0x32eb73c9, 0x41e519a3, 0xe49c25b7, - 0x1362db5f, 0x321ba1e9, 0x9ea18757, 0x8faaa86c, 0xdea474c6, 0xa77d03b7, - 0x7dffbbdd, 0xe4812d9e, 0x817f3f2d, 0xfa0c5984, 0xae7abdc0, 0xb6faf8e4, - 0x7944cb4c, 0xc3f2a1a9, 0x8b7dffbb, 0xac077d0f, 0x3490f085, 0x7e0f912c, - 0xe29bbe00, 0x2fdf02d4, 0x444e6740, 0xabae74f8, 0x4243e507, 0x8b1baf9c, - 0x56ce9ab6, 0xcae2f9d2, 0x5d33e238, 0x31e987b5, 0x18c8b2bf, 0x9f0ae7c8, - 0xfffcb5fc, 0xbbe71cb4, 0x59b81c99, 0xf7e337bb, 0xbe73a59f, 0x369ece19, - 0x154f230c, 0x9acf18fb, 0x4b6c8a63, 0x7d59eafb, 0xf6eafd48, 0xc567ce6c, - 0x643e7e7a, 0x72f4c54e, 0xfaf8c38a, 0x96c73c44, 0xa9f9cd93, 0x714912cd, - 0xd674b6e2, 0xdf037185, 0xf7f70d72, 0xdafff1c4, 0x3fc9d32a, 0xa2782ad4, - 0x3e78197d, 0xeb8695c2, 0x147306d7, 0xa6b7fd09, 0xfcceb972, 0xabc6331e, - 0x409a9da1, 0xf3dec1fc, 0x9198e9a9, 0x0bfe4c3e, 0xa49ef12d, 0xa3b7f00f, - 0x17fd1c5f, 0xdadddfc1, 0xbf6f86af, 0x984b86aa, 0x354f054e, 0x6669e1aa, - 0xe6c96c35, 0x361dfa7a, 0x490cfe75, 0x1ca7270d, 0x73f0d309, 0x7f01a6ed, - 0xbbf044b3, 0xa07e0199, 0x01769a0d, 0xafa525e7, 0xadb2fc96, 0x93dfdca9, - 0x73f6af5c, 0xb596b224, 0x6df90231, 0xfcb6f954, 0x73fa0255, 0x7cead56c, - 0x8c150798, 0xbff48acb, 0x9f95d724, 0x02e9718d, 0x4b3aee7e, 0xc5cde9eb, - 0x238b6875, 0xcf934a3e, 0x1fdd0d05, 0x95b8d0b7, 0x7c0f9076, 0xfa45e301, - 0xe62f840f, 0xc76726ba, 0x05f03e73, 0x7df997ee, 0xa503e43a, 0x41f8e1bf, - 0x3962c7e1, 0xab9ca26e, 0xa5b722b9, 0x97a9ab9c, 0x0475c7cf, 0x92b9c79d, - 0x81e7465c, 0x09aef4ae, 0xc877c50f, 0xce6cbe67, 0x946e9877, 0xdf20d7cf, - 0xef9cf4f9, 0xd5f0df30, 0xfd28672a, 0xafbcbcf0, 0xcc37b43c, 0xf8c071fc, - 0xab47b656, 0x82477760, 0xd3bcf039, 0x740ff843, 0x3a3337ba, 0x0f2b5a47, - 0xbf338be7, 0xe908d3db, 0x0b975a5b, 0xd66567d7, 0x338f3d59, 0xfe51ebf5, - 0xdff7979e, 0x38dd820d, 0xdb94c05a, 0xbb668da5, 0xccbdfd11, 0x57f2a19f, - 0xd5877e28, 0x31acd22b, 0x0188ff80, 0x4cd3823f, 0x33e34de7, 0x35118fc9, - 0x2b3771d5, 0xccf73c04, 0xa2046f98, 0x554e85dc, 0x658fc790, 0x97d0fd97, - 0x035e383c, 0xce02abfa, 0x0f441923, 0x3573b923, 0xe7014995, 0xff655bca, - 0x9b1f00c5, 0x7f609796, 0x7896cc3f, 0xd679863c, 0xda9fff72, 0x6ab8665f, - 0xd833b553, 0xdfaab27e, 0x722fd956, 0xfed5f6f3, 0xf4d5c337, 0x0ecfda61, - 0xb21cdf6a, 0xd576c1fd, 0x11afbc7e, 0x3e436f1f, 0xb5ffce18, 0x1ba7965f, - 0xf45e9e6c, 0xd818e97f, 0x06071495, 0x6a8898fa, 0xc369ff23, 0x5d5379f9, - 0xa60fdab2, 0x1f927e63, 0x90d647cf, 0x3e6048fc, 0x9859df8a, 0x47d7f287, - 0xbbf1e74d, 0x1371b960, 0x8798c179, 0xfd00dea1, 0x3f57f2a9, 0x46d3f7c2, - 0x3c42eec1, 0xfff3c783, 0x89abdd8a, 0xfa4bdf1c, 0x64b84a73, 0xdbde81b8, - 0xe32575ea, 0x3dc21bf7, 0xfeeb1835, 0x762ebb3c, 0x1b3de83d, 0x7c08c630, - 0x71bb3576, 0xfb84cfbe, 0xf58fa724, 0x27a21a71, 0x1d96ddcb, 0xb27a00da, - 0xa8695de8, 0xf2345af7, 0xa1fc2f39, 0x65bd6cbf, 0xfd10a6e7, 0x029bfa2b, - 0x8f002b5b, 0x956dba00, 0xfe81e6f5, 0xd0ee2496, 0x3163b406, 0x3fa90ab8, - 0xd2a35ce5, 0xeb37d35f, 0xf7ecab6f, 0xdeb3fa52, 0x559f1ea3, 0x59f1a1ef, - 0xe947fde5, 0x2f8e2b6f, 0xb4dd5f04, 0x1e8ed93f, 0x7aa96fe8, 0x8783567c, - 0x72d567c6, 0x7f40e1ff, 0xbfacdf4d, 0x931ef936, 0xe1d3e64d, 0x0e37fdce, - 0x1a76ab9c, 0x29b4ae51, 0x7f7940fe, 0xbfb414bb, 0x37f796ad, 0x714bfbe5, - 0xbddfe4e9, 0x18df33d4, 0xfdc35f6a, 0x247ac98c, 0x2648f593, 0xcf0891eb, - 0x3ea67a99, 0xf0b0e81e, 0x22f9b6c5, 0x1e73e3ec, 0x153e333a, 0xf62f19e0, - 0x5f6117cf, 0x99e2f39a, 0xc9f04903, 0xccbe2fcb, 0xe6787fcb, 0x9b94324a, - 0x2fcdef7c, 0x962a3803, 0xde0ac7ef, 0x8db7bf4a, 0xbba37ae2, 0xbfee73e1, - 0xfb8af904, 0x87aa6356, 0x42f17fa1, 0x32d47f72, 0xe94eefa8, 0x310f2cb7, - 0x6eea4a2f, 0x467e4f38, 0xff287914, 0x40bfe1e6, 0xee53cfb4, 0xefab9467, - 0x6d454467, 0x8c2ffd22, 0xef28cdf9, 0xba0e8c22, 0x28d6f84f, 0x642c1fbe, - 0x376e0af6, 0x39f25948, 0x31cfba0d, 0xd76e58bf, 0xb1cfcb7c, 0xb1c6a17c, - 0xdfd9ed1e, 0x478aaa4e, 0x173958f5, 0x7f783797, 0x1bf5d772, 0xbe0e1f9c, - 0x23e7393f, 0x23c2eb81, 0x3ba5bfb8, 0xb9f7e257, 0xa886fc02, 0x9f370ef7, - 0x7db8a3b5, 0x0e9f383f, 0x0e319f3e, 0xfee69f3e, 0xfeb0b5a8, 0xcb7ee8ee, - 0x5d9fc413, 0xc86be721, 0x5fcd06bc, 0xd8a628fd, 0xb7a45a79, 0x32b7cd9b, - 0xc1f9caaf, 0xa2ca4146, 0x794feafd, 0x3183fd2a, 0x8e2a14bb, 0xb819f483, - 0x4e6deabf, 0x5d19fe86, 0xcf073d9c, 0x45fe3795, 0xde5cf21b, 0xd63e796e, - 0xb9d38546, 0x3d28c6ce, 0x51dddbd9, 0x97fa1933, 0x9a74d345, 0x72a8b297, - 0x8da96f3a, 0x8f68ed65, 0xd7239f06, 0xce9bb88e, 0x68ad6901, 0x703a4041, - 0xa461d92e, 0xe8b989f8, 0xc5c8e786, 0x8f239d9b, 0x91cfc999, 0x7425e947, - 0xea45b459, 0x7f239e43, 0xf7df146c, 0x713c71bb, 0x278c3f88, 0xa21c706d, - 0x31d1c799, 0xf5f2023f, 0x7f231766, 0xc7de3cba, 0xea5075e4, 0x861ecc1b, - 0xb7ab40f2, 0x68a7a84b, 0x613ef9c3, 0x4e5869b0, 0xf7c8bf08, 0xfbe8e947, - 0x34cd724f, 0xd7231aaf, 0x5afce7cb, 0x7a4fe908, 0x4fe29475, 0xc3674d0a, - 0x0d3cc9d1, 0xf0a7473f, 0x9e9302e1, 0x302df7ce, 0x0fd14ad9, 0xef0800b2, - 0xfa8098b3, 0xf7e22db7, 0x0dbb4581, 0x5337e7e9, 0x6ff9ff6e, 0xb9f9ba18, - 0x43353e7c, 0x4ee3f747, 0x8f61cc09, 0xd57e7a19, 0x869e8ce9, 0x66bb9a6e, - 0xec87599d, 0xeff2e2f7, 0x867b6115, 0x167553e3, 0x779fec89, 0xa85ca146, - 0x0f1f5b4e, 0x42caa2f0, 0x94dfdd1d, 0x08ee44e3, 0xd19fc72e, 0xa28e4eba, - 0x51e7d178, 0x624748a5, 0xa3e22a7f, 0xea0289c4, 0x9e2a37bd, 0xd7e1cdea, - 0x18dea0c5, 0x7f67d394, 0x1eb462ef, 0x127a50b6, 0x302c4fda, 0x07cb236e, - 0xf302a3b4, 0x01627ed1, 0x2f2c27eb, 0x9085f6b6, 0x609a4a17, 0x0d5292db, - 0xd0909e7c, 0xff92a942, 0xee5b43ac, 0x57aeb10f, 0xc6fd75e5, 0x601b4c76, - 0x8ed0713b, 0x2ae5fb01, 0xd517dbce, 0x61e32ca7, 0x17657548, 0xe9b18ec9, - 0x88933e15, 0x1e6106bf, 0x45fb04af, 0xd5b0de75, 0xfba14beb, 0x6d38f2fe, - 0xa346d62b, 0x1c55031d, 0xbcdb9f48, 0x9965296d, 0xcec8e383, 0x8d13e991, - 0x17a889b6, 0x5c725ff3, 0x97f40ccb, 0x74349b24, 0x5326013e, 0x6e612f75, - 0x38b4f459, 0xccdd4534, 0x2ed0926e, 0x3f3d25ef, 0xf896bae1, 0x62f0e120, - 0xa4ab7186, 0xef0176b8, 0x23f40d03, 0x97ae6fdf, 0x5c57b9e3, 0x048e3465, - 0xcefec0eb, 0xf38d0ec8, 0x747945cd, 0x518e69e5, 0xe5d58fc2, 0xdcfc71c9, - 0xe1d5fdc2, 0x3ae8097e, 0x4057b6a9, 0x380c0138, 0x5c27c5f4, 0x426b4c6f, - 0x045af279, 0x6db58bf9, 0xf207cc99, 0x45745527, 0xfb3ce0e5, 0xc9a6ffa5, - 0xdf0b0790, 0x9c207cad, 0xa136b3f4, 0x25d90665, 0x285869f7, 0x1c98cf3f, - 0xc828c7ee, 0x609ffce1, 0x1ea94d6b, 0x44d3e987, 0xcf975f37, 0x1db39067, - 0x9f11d9f4, 0x1c58fa2d, 0x759a7bd4, 0x9b73e9a1, 0x7ec0efdc, 0x185fcf21, - 0x7f911973, 0x3b9382b5, 0xdbeef739, 0xce82cfb7, 0x55e74613, 0x8d7ac936, - 0x4e444ed2, 0xd846153b, 0x45cf0c1d, 0xdf07660a, 0x9b3ecc07, 0xf9abd60f, - 0x7b486d2b, 0x791cc1eb, 0xb26b491f, 0x4cb2fd61, 0x94fd0dbb, 0x1a55f7c1, - 0x70da26d3, 0x0c671a7d, 0x7031a9d0, 0xcb4ee85f, 0x53cf1f7e, 0x2c747a99, - 0x70591cf0, 0x2173c7aa, 0x972837b1, 0x1d3797cf, 0x9b42e7e2, 0x78bd454c, - 0x14c9a10e, 0xfec74457, 0xa99cfc4c, 0x3a64df52, 0x64def246, 0x1356f1e7, - 0xa2020fee, 0x3ba1e7c7, 0x83cd18ed, 0x0e5a6f52, 0x7b26ab97, 0x5bfbc317, - 0xd53f76e1, 0x3e9d130b, 0x161fe00d, 0x4ffee8c7, 0x55f39198, 0x318fac04, - 0x7e95ef80, 0xd1d1cb6f, 0x172535bc, 0x7e1096f5, 0x6704de22, 0x1b22b64d, - 0xdf38dbed, 0xb4636fd0, 0xaf9cdf42, 0x5be7971f, 0x3e51a769, 0x434f7aff, - 0x58b2fcce, 0xd73913f4, 0xa6bb60e4, 0x83b446e5, 0x6fe391b4, 0x6186ded8, - 0x285e6bdb, 0xf238f7b7, 0xc8b23685, 0x50e9ed8c, 0xc3a0845e, 0xfe76e467, - 0x30ede357, 0x97df74b3, 0x9f305a60, 0xa3de942d, 0xa38c46a4, 0xddfa1b8f, - 0xebbf9637, 0x90247ed4, 0xfc717bbf, 0x1ecf932b, 0xee1ca12b, 0xdb2eda3f, - 0x619d8a27, 0x2ededb91, 0x3ee87bf0, 0xef4edc21, 0x8776c836, 0x0f3d4c25, - 0xf941f783, 0xe0ae5c3a, 0xc72ee6e7, 0x046b8a31, 0x77e5f3f3, 0xb40e8a3e, - 0x73ef504f, 0x04bb7364, 0x1c4bb453, 0x610d9fb2, 0x9da01bf4, 0x80fdf0a2, - 0xfa42b75f, 0x3f005ba7, 0x0d6fc803, 0x7b242bb4, 0xc90dbe88, 0xe7c8697d, - 0x053bf2a9, 0x5cd7f643, 0x4785a72e, 0xfe434b3f, 0x4feb8b2e, 0xf982efc0, - 0xae4785fc, 0x5e78e026, 0xce703198, 0xab43e286, 0x7bf3a717, 0x1cffc7d9, - 0xfed10aed, 0x457feecd, 0x86b4dd9d, 0x5ce5c0f4, 0xdf5bfc0f, 0x8cbedb07, - 0x821d9deb, 0xcda4efda, 0x5fe77ae5, 0x7acc7de4, 0x2df7a455, 0x2eb965ce, - 0x0ab61f20, 0x7f28e5e6, 0xe7e11f53, 0x5e3f56e6, 0x2103d9ff, 0xed1841f8, - 0x804e73fa, 0xacdc5c3d, 0xa35a3f27, 0x8dc47d29, 0xafc31ce2, 0x71cb87b3, - 0x1e4b7d79, 0x24f3f235, 0x5b17ae2e, 0x39d3f75c, 0x23f3e095, 0x243bd5c3, - 0xbea53dcb, 0x7947db01, 0xfe479a62, 0x23684b80, 0x964dbfa0, 0x7678c17b, - 0xf3c864e2, 0x12b90463, 0x18456875, 0xed93abb6, 0x3f8aedb1, 0xe8c8a2a3, - 0xb75ef808, 0x1a58c8b8, 0x8c8d2f40, 0x6e0ddf9f, 0x01dcceff, 0xafa55a7d, - 0x459f70e8, 0xf89c50df, 0x433901a7, 0xcab8658a, 0x0ffa518e, 0x70163f3e, - 0xf38c2c5e, 0x5a67b729, 0xe818dcf1, 0x962b6bb7, 0x6df9c48f, 0x582f5d15, - 0x3ffa1e61, 0xe739d030, 0xecbe650f, 0xb872f993, 0x43b1f3f5, 0xf6318ca0, - 0x97823b04, 0xc64e80d6, 0x68fe408f, 0xfb94d4cc, 0x5cb38c43, 0xfd08671e, - 0xafdcd6fa, 0xe6975fa7, 0x51afd086, 0xc504767f, 0xd461021f, 0xf4211d9b, - 0xec8213eb, 0xedcf900f, 0x1d49d09c, 0x270f307d, 0x6f611d6e, 0x919ee894, - 0xf6045ec3, 0x32678bc3, 0x239f6f51, 0x23c7bc0c, 0x608c31db, 0x221623b0, - 0x6799735e, 0xc50203df, 0x48ee5a51, 0x5c04eea3, 0xa7ad9b8f, 0x3711fb24, - 0xdc613ac2, 0xb2daf5a1, 0x0ce2a119, 0x274038ff, 0xef02ba28, 0x042ac007, - 0xc48695c4, 0x63e282cb, 0x38194e18, 0x5a1dabff, 0x7562aeff, 0x35e36afc, - 0xac30bfee, 0x0427fe60, 0x2eaa1f3c, 0x0bae5f9f, 0xe2a9cf8e, 0xba9d0b5a, - 0x887c7c60, 0x6f8cb26f, 0x2907b6ca, 0x452d3e0e, 0x64acfde4, 0xc707cf64, - 0xbd850cbd, 0xc3ea2d0e, 0xf7f48c15, 0x9e363f60, 0x5eff2517, 0x09cf6305, - 0x7d5ade74, 0x59e9e4df, 0x1cfbf8e7, 0x8fd8e52d, 0x50c3532d, 0xafbe0e3f, - 0xf09bc4a0, 0x7de04c98, 0x22dde569, 0xe10d62cb, 0x53b77cc7, 0x8797e2b9, - 0x4b12a6fa, 0x55eeb9c0, 0xdd3ea06c, 0x1e85f2a3, 0x59d6d6f7, 0x1c4fef14, - 0x82ec29ef, 0xa33b24a2, 0x66aa4879, 0x3cc00764, 0x86fae2a8, 0xce345d94, - 0xc58c354b, 0xaaa038f2, 0x7076013c, 0xbf184fa4, 0xe30fce2a, 0x76c1c154, - 0x4deccde7, 0x0de64a43, 0xfccdf9e5, 0x5e39068d, 0x646e46f8, 0x633be91c, - 0x77d418d8, 0xa69f8b2c, 0xeb04b8f5, 0x34597e81, 0x03c54284, 0x68fb4337, - 0x5f90ba07, 0xc4dfd1e2, 0x30caef54, 0xc9f74887, 0xb38e6284, 0xf1e4eb10, - 0xfc467ce1, 0x9507086d, 0x9859f80b, 0xbce0706c, 0xc3000c1b, 0x333d0590, - 0x56be4026, 0x15af37f6, 0x33308898, 0x4fdc8ddb, 0xe36bbca8, 0x866d77a7, - 0xff7407eb, 0xcfec30be, 0xfa53bfc7, 0xdb8ef219, 0xfb27be0d, 0x7dfc1ccd, - 0x951df919, 0xff9b87fe, 0xfb6ddee1, 0x2777d4c3, 0x3267bf70, 0x20e56bd1, - 0x4cbc12bd, 0x1efc47a6, 0x4abdc2e5, 0x0c77adb1, 0xfb3c37de, 0xfd1d8470, - 0xf0e303e0, 0xefe5a9dd, 0xed75fdd1, 0x9361e00d, 0x8c0fbe48, 0xafef6e4b, - 0x02fd171d, 0xbc06dae4, 0x4fe78434, 0x279d192a, 0xcf4ab8b0, 0x000e7489, - 0x1392a0c6, 0x4013ef01, 0xf10e1b7b, 0xf15baf73, 0xb0710b9d, 0xd02bd45f, - 0x4255b06e, 0x483b087e, 0xbf19ab49, 0xd5e0ac1f, 0x1a3d07a8, 0xf5c352e9, - 0x3ea6d9e8, 0xe935cf11, 0xe445fae2, 0x2e68e71f, 0x37e807c7, 0x0bf9d19e, - 0xce7c926d, 0xdfc4a471, 0xfbe4cb4d, 0x84cfd29b, 0xfe591ad1, 0x47fbd2f7, - 0xd54e23b3, 0xf2c6764b, 0x442fc5f6, 0x11ecfcff, 0x00d3eaa7, 0xe167d82e, - 0x2ba9d270, 0xecc66669, 0xd10bacfb, 0xef3b3f9f, 0x807495d4, 0x78d9f68b, - 0x464614f9, 0x097df8ce, 0x319fd10b, 0xd559b461, 0xd7385bfe, 0xd53cdff1, - 0xcf21341a, 0x5a36df63, 0xe8c94f39, 0xf3b3ad3e, 0x2e31a797, 0x47f654e9, - 0xdf482e87, 0xde0b2281, 0x717f9323, 0x9d0f1451, 0x9dd9d329, 0x1452eef8, - 0x68bb2dfa, 0xfa0d477e, 0x6bfe9fe9, 0x4382f4fc, 0xccca9779, 0x1bff812a, - 0x2c2b981b, 0x99ee8023, 0x9f9d7343, 0x81b8a603, 0xffd28f82, 0x6960bc10, - 0xbc4098c5, 0x0a3b51b6, 0x0d0a175e, 0xc70587a4, 0xfd082e87, 0x549cf1db, - 0x2fd6cfc4, 0x10ba75c2, 0x002a9fd9, 0x9eb79e1c, 0x7c42edd6, 0x1ec176ff, - 0x3af8eb00, 0xa22bef56, 0xd6a3fc75, 0x027a3d51, 0xdfc5dbbe, 0xe396686f, - 0xbbc64f50, 0x019f687c, 0x32b9d1dd, 0xfc9e8a5f, 0x05e36548, 0xb03fa047, - 0xcbf7346e, 0x69d3925c, 0x49cf1686, 0x01f74ba0, 0xfa85ad81, 0xf5976bee, - 0xeecc9fa8, 0x3d47a33c, 0x19c0eeba, 0xad4bde3d, 0xa9da1843, 0x8477a6db, - 0x32feffd2, 0x97f2ab5a, 0xd1d77629, 0xe8f5ec94, 0x16abab77, 0xeade1ee8, - 0x6e1fb9d7, 0x251c32f5, 0xb2df7763, 0x55b8fc9f, 0x98f5eece, 0x477d652e, - 0xc588ddf1, 0xdceaad2e, 0x089a92c0, 0xcabe3c55, 0x9782ab13, 0xc0eac0b6, - 0x21b4bb3e, 0xc31df549, 0xef82cf5d, 0xd0fe0e28, 0xd790affe, 0x736db171, - 0x16bbfa2f, 0xcc7ad4bb, 0x62b5ceec, 0x11ede20c, 0xfece1aec, 0x84b77e12, - 0x00d2108f, 0x7de60abd, 0xa3d7075a, 0x648c2aea, 0x0c22549f, 0xab595af3, - 0x7393e3f5, 0x54f45347, 0xa810eeee, 0xbb972ddc, 0x576e046b, 0xa975f2cb, - 0x8392e38c, 0x75d1a727, 0x37a39f52, 0xa5df0033, 0x88e7e515, 0x437d651e, - 0xc4855719, 0x290d8df5, 0xddb0e9ef, 0x5817dfa5, 0x4b8d1a6c, 0xa92d47a5, - 0x1e55c351, 0xd59e905d, 0xbdf943a7, 0xff9d41b4, 0xbef2d1f3, 0x90f2c79e, - 0x2d18de9f, 0x07189f88, 0xbca53fe1, 0x81ef0277, 0x0f3ad25d, 0xead67d22, - 0xdf700abb, 0x1175a4bb, 0x7e4394ac, 0xb8afdf1d, 0xce01a2be, 0x751befc3, - 0xa7de330e, 0x8814adf5, 0x00b0976e, 0xb06d27bd, 0xa1dac13e, 0x7722bf70, - 0xe4f59cc3, 0x98283d0f, 0x13286f51, 0x83de221d, 0x8fc61c6f, 0x83e6517e, - 0x1f2fac13, 0x2246caf1, 0x9eca7585, 0x99f6823f, 0xf996b7ec, 0x3d948e30, - 0xc4bf204e, 0x4371809d, 0xc922a611, 0x37b03991, 0xad9a4184, 0xf920af6d, - 0xe66f563e, 0x58da62ef, 0xfc70bca0, 0xbe701333, 0x0bb27510, 0xfde87b93, - 0x9b6d39bd, 0xcc5ca22f, 0x3d1470cc, 0x193df805, 0xf27ffbc6, 0x16bfc175, - 0x3fcba9da, 0x0ad3f246, 0xd6fd81e4, 0xda3964d9, 0x5acff6a1, 0xc121ae51, - 0x7ea7cacc, 0x32f89413, 0xc3ed15d0, 0x9fa4a55d, 0x9f7ee558, 0xddb8942d, - 0x2e7ca0fc, 0xe2d6f98d, 0xd1befaf9, 0xf495f28c, 0xcaabfb1b, 0x5e283104, - 0xe61a3750, 0x4fada579, 0x5be9de75, 0xe901bf6c, 0x187db82c, 0x395e2abe, - 0x8a2d7b4d, 0xcc1d77ee, 0xfee8deb0, 0x3ea8d694, 0x8733a4b7, 0x53bbdd07, - 0xf6d99fcb, 0x777ba0a4, 0xeef74119, 0xddee82f2, 0x2df9efa9, 0xba094e74, - 0xe7bea777, 0x54cdb067, 0xe6930fd5, 0x9c88e0a9, 0x23f555bb, 0xe7d5cbed, - 0xbcff8eae, 0x77c74842, 0x2e7d7d06, 0xe0668798, 0xc198e28d, 0x0a2f247d, - 0x3e1a432a, 0x6984cc2e, 0x0ba1a173, 0x9139a4e9, 0xe386e7db, 0xa0badb0f, - 0x9788e31d, 0xfc6fe88c, 0x452fe089, 0x9f28c4fb, 0x18fd1953, 0xaf33ed53, - 0x52be7015, 0x5cf2dbd2, 0x7d61f3b3, 0x494af7f2, 0xdee01dfc, 0x463eb8d1, - 0xf9036c7c, 0xaf7e55e6, 0x476cac78, 0x5f3ced28, 0x0f353258, 0xcc7fcfbe, - 0xece28331, 0xf07efc1d, 0xa78f3d4e, 0xe7e55ef8, 0xfa3bf35b, 0xfe008e34, - 0xf5c7993e, 0xa59c6790, 0xeba91f14, 0xf9165d84, 0x1eaceda9, 0x75d465ef, - 0x7ee14776, 0xab3ce056, 0x60c9bf47, 0x89cfbcbe, 0xaf68e1fd, 0x743dacff, - 0x9e6d6d3c, 0x98e3f89e, 0x1eabd72c, 0x91bb72d6, 0xb9e16639, 0x575e4571, - 0xabe3e7ed, 0xe7e7a85a, 0x1d1a3160, 0x9c836e42, 0xc396ab3e, 0x707ef50e, - 0xca3d7f8b, 0xaadf900e, 0x4c174b7a, 0x12b7bb27, 0x31f236e4, 0x797573c8, - 0x17c91372, 0x7caae790, 0x3c80de77, 0xdf0ebfcf, 0x426a769d, 0x8170f38e, - 0xda78f348, 0xffe69535, 0xf4479819, 0x64333da7, 0xde7cf8de, 0xc65ebe6c, - 0xb7580fb5, 0x2ebf7ae0, 0xf2f6ebe0, 0x7dfaf230, 0x0a775d79, 0x4c2845bd, - 0xa270cedd, 0x634625db, 0x387b9e09, 0x1365f296, 0x7eaae1c6, 0xfd3dd02e, - 0x6e3eeb7f, 0xbf5ffd41, 0xfd05a8ff, 0xa3f6ee61, 0x594db016, 0x8b5a4ead, - 0x85d03c7a, 0xba9ef51d, 0x7fc22e8e, 0x6eb8fb65, 0x21d95fcc, 0xee3dfbd0, - 0xd3a71703, 0x135f5938, 0x0e770bc6, 0xf28fd783, 0x37befeb8, 0x307ee24f, - 0xfb89f417, 0xdf8301fd, 0x801d202f, 0x5ebc425c, 0x35e5f017, 0xb1a373b6, - 0xf51e9422, 0x1f7cf26f, 0xe867a8d9, 0xef85afaf, 0x52c71c71, 0x488de98e, - 0xb205fb47, 0x27edddb5, 0xfb604617, 0xfa863af5, 0x17df8285, 0xe21fbd29, - 0xd6a83ff8, 0x3580a7a1, 0xbe696b56, 0x52d7a83f, 0x74fbda3b, 0xc15e2f04, - 0xae1c55cf, 0x0929a8fe, 0x56a0fdda, 0x530c7ba0, 0x31f3fbef, 0xe0af1784, - 0x3d305afa, 0x4c1af42b, 0x3bf4c19f, 0xbe6b4e84, 0xc91e9d19, 0xe4d5ef93, - 0xe7dc02b1, 0x59a7dd61, 0xe11e7e91, 0xae2be3f7, 0x7fa1d61d, 0x6cc9bd33, - 0x31e0027f, 0x0b7aff5a, 0xbcc389ca, 0x8776b0bc, 0x748de5c0, 0x5261f237, - 0xbda19eb3, 0x971e7efb, 0x7ae3ef4b, 0xfad0e3c5, 0x31af8c05, 0xe51d37b1, - 0x4f1c9a52, 0x2ac7457a, 0x905c53f6, 0xaf319bcb, 0x96ef54d9, 0xbd71e537, - 0x40839143, 0xe4fdaee6, 0xc44f6d97, 0xcb2f147b, 0xe55341e7, 0xfa32b2f6, - 0xf485cfa7, 0x672f4caa, 0xf8143c64, 0x6cff4cb2, 0x1f68cfdb, 0x59c72d9f, - 0xd1743666, 0x833ccc79, 0x879453eb, 0xabdf52b3, 0x39ae7dc5, 0x3a7cedfd, - 0x25378d67, 0xc9fbe226, 0xd27877fc, 0x60d6dba7, 0x9c372fdc, 0xe0ec31d6, - 0x381e7453, 0x35bc6b2c, 0x49439c54, 0x7a2557dd, 0x6aeeb08f, 0x3c0aa53a, - 0x7d39d0f7, 0x1701d91f, 0x5c9f13a7, 0x2ddea9b5, 0x7bc654fc, 0x5d3ef28c, - 0x80f3f727, 0x8b8b169c, 0xf329eb06, 0x1c659e80, 0x2ed6586f, 0xab35af5a, - 0x75a92158, 0xcefe29ec, 0x0149ed66, 0xa458bddf, 0x304ce873, 0x608defdf, - 0xfc8b1f25, 0x3657241d, 0x748c4dc6, 0xd784fb2f, 0xd7af704c, 0xaf29f046, - 0x61ade944, 0x687c88ce, 0x4f11e167, 0xe1dbce16, 0xde275694, 0x8ef0bc57, - 0x336ba64e, 0xd32e2fbf, 0x2d4ee5da, 0xeb9c6233, 0xc2e3e800, 0x5cf7fe20, - 0xddfba44d, 0xa0fec3bf, 0xbf0d959f, 0xaf677921, 0xed1d38b9, 0x33dac2a2, - 0x1bbb084d, 0xf51d3cfe, 0xff610f89, 0xf41ebd20, 0x72809b7b, 0xd3bd24e4, - 0x8635795d, 0xd35979da, 0xcbf91d3f, 0xf740a6f7, 0xb8ec3e6f, 0xfdf2b7a8, - 0x7873dc89, 0xf2fd1c2f, 0xb9a3f2b3, 0xd42ce91c, 0x243afad0, 0xddeb3bd5, - 0x0a2bffa3, 0x20d8c3d7, 0x7e0a7afd, 0xc865a3df, 0xfb4a9bbf, 0xe421cca3, - 0xdff469ef, 0xb071f365, 0x15e5a1ec, 0x9e165f7a, 0xe990ac93, 0x3cbcb838, - 0xa13fc07f, 0xebefca73, 0xa1fe0108, 0x3fdfc62a, 0x2ba7bb05, 0xaab8f81c, - 0x67f92a73, 0x0dc23caa, 0xd1c333fd, 0xeb4dd7e1, 0x28cff718, 0x818dda30, - 0x1bb44d7e, 0x1f7faa99, 0x252b077f, 0x74f786f3, 0x14897ddc, 0x666bafcf, - 0x795aef14, 0xe7a53475, 0x2120df5f, 0xfbc318ff, 0x6b7ee95b, 0x8cec86b6, - 0xfeb53e95, 0xcb80a533, 0x7c052985, 0x60f95cde, 0x01b0e52f, 0xa2ec097b, - 0x5db9f37b, 0xa9887514, 0x7ce0a5ec, 0xf28c97b2, 0x13101d3d, 0xe04257ae, - 0x6941477d, 0xca977e0d, 0xd9ce885a, 0x72fefc3b, 0xe4d738f0, 0xf8553e73, - 0x35f2317a, 0xe7076fd2, 0xe776e0eb, 0x41ac9415, 0x4c38da3e, 0xe65cab7c, - 0x8c6d95fb, 0x16ddcbe6, 0x05f4f343, 0x0296736b, 0x78017e5d, 0x0bd23de0, - 0x3444674e, 0xe5c17f7c, 0x3df3c08c, 0x6ba81c8a, 0x36efa70b, 0xc58bce66, - 0x48cda373, 0xf9ded0f7, 0x9c46a98e, 0x38da7be7, 0x7dfd29ff, 0x1638b5d8, - 0xae8269f9, 0xf2876f5f, 0x5133cee4, 0x784df7a8, 0xf22c7e7d, 0xfe7870e1, - 0xcf1918fd, 0x1e12c486, 0x70bd8797, 0x004f6ca2, 0xba27ee7e, 0x87fa9de8, - 0x6fd1181a, 0x56ffabf7, 0xbe7c7c87, 0xfb8cc233, 0x230717e6, 0x0bcabde8, - 0x3de81a6f, 0x7df95a9a, 0x7d742fd5, 0x7cbf4873, 0x22f74b5d, 0x47fe6fdd, - 0xfba3f22b, 0x3b9d0355, 0xc373a87c, 0x6af7dc45, 0xc39c673b, 0x5f6b5677, - 0xc3f2dbfa, 0xd25486ca, 0x3ff8148b, 0xbe2746bc, 0xe45e7bf3, 0x8ea1e272, - 0xf77d217f, 0x0b976ba1, 0x17ca7cf0, 0x44c7ff07, 0xb7ee6b94, 0x79444f2e, - 0xe5c5fee6, 0x7eee5889, 0x4a13c22d, 0xc05eb95f, 0x7eca3efd, 0xa8aef699, - 0x90ad0ff2, 0x5d6d23e9, 0x3d07bd0b, 0x7b02e4e1, 0x130fbbe0, 0xac4e34b2, - 0x65b7e13f, 0x7c05f7b1, 0xa457aeb7, 0x93f8e338, 0x01d51165, 0x814f7974, - 0x7e2ff14e, 0x930ebf23, 0xf019c7df, 0x77f2f4e3, 0x8af6367f, 0x1aa37dfc, - 0x83a1ee81, 0x5ee432fe, 0x8affad1a, 0x88df7a58, 0xc73bce89, 0x8b38478c, - 0x3e6205de, 0x00ccd1e3, 0xaf71693d, 0x7400cba6, 0xe869d154, 0x57befd22, - 0xacb0433c, 0xf173dd3f, 0x2134c8d3, 0xe7267f84, 0xe39434d4, 0xf81a7ec1, - 0x8ade2245, 0x71e955be, 0xc1fe20a5, 0x15a59bfe, 0x287f9077, 0xd6937fd8, - 0x8f666a2b, 0xe9dff7c7, 0xf78c2f3a, 0x8bf22369, 0xfae287a2, 0xffc1081d, - 0x3970c66b, 0xbad5f0a6, 0x5dff1e5e, 0xcc6a5bd7, 0xe656b484, 0x9db003ab, - 0x75fda0fa, 0xa377f39d, 0xb5dd611f, 0x60631145, 0x3bbdd6be, 0xfc813d8f, - 0x66352e6f, 0xeed777e1, 0x1fcc2e30, 0xfee097a4, 0xf2e18ca6, 0x184f4072, - 0x97cbdf66, 0xed5bfaf1, 0xe463397f, 0x87ff6cf3, 0x87607fef, 0xedc31d8f, - 0x4fdc25f0, 0xe0f0edc2, 0xc791437d, 0x792ebb4a, 0x63ca879d, 0xc04877fe, - 0xec79265e, 0xbd51231a, 0xb1b9cee4, 0xbbbf4764, 0x0d325620, 0xb4433f6d, - 0x87f2626b, 0x71e8afb6, 0xa8e39f6e, 0x871ced11, 0x1749fb96, 0x99bef408, - 0x9db9f7a2, 0xeee3e902, 0xeb1f9d4a, 0x2ef57829, 0x85d57ee0, 0x4c3f9d0e, - 0x150fd418, 0xdca071fd, 0xa2b9502e, 0x637a2a4f, 0x71fb93af, 0xe5e78c17, - 0x16b986b7, 0xd87d7ce1, 0x13f94615, 0xc67cf126, 0x0093479c, 0x813df45e, - 0xfacbff11, 0xc1a742a4, 0xcea5e6fa, 0xd7be1b8c, 0x4fa64db3, 0x8352cf85, - 0xbfd943f8, 0xdd39f39a, 0x1dfee1d7, 0x7ff7fb8b, 0xe0f2f4aa, 0x7eff6176, - 0x466ff108, 0x1fbe121d, 0x19d15bff, 0x4aff3eca, 0x5efe0bd6, 0x23debf59, - 0x72af8825, 0x7db8764e, 0x6fd64eb5, 0xce6f2b86, 0xbcfc7aff, 0xdfdf1e47, - 0x8e779f8a, 0x9f43bff9, 0xf50bd01d, 0x4779c7a1, 0xc64fc941, 0x6b86bcc0, - 0x739e743d, 0x1ecdf7b8, 0xb055f595, 0x7c745573, 0x41af4534, 0xc35dc8bb, - 0xd1cd03fd, 0x7ec9afd2, 0xf7a5ae39, 0xef921e57, 0xd5783e73, 0xea2d694c, - 0xd92e90c9, 0xd9de927b, 0xc6a3525d, 0xb77d19bf, 0x34aafdf8, 0xb157eb8a, - 0x552bf232, 0xf19b4675, 0x7c737fbc, 0x2be431fb, 0xb4ad6edf, 0xc6feb03b, - 0x237d72d1, 0x44d5b7f7, 0x618fdfd3, 0x95407a41, 0x57df5827, 0x645305eb, - 0xfa70d13f, 0xc3ba2fc1, 0xd1e95cb8, 0x39d79f12, 0xd055dff9, 0xe0b97277, - 0xbf23086e, 0x886bda09, 0x820d67d7, 0x5f3ddf1f, 0x4cfbd729, 0x13ff25ec, - 0xcaa0d3c5, 0x2ca7ceb9, 0xd4dfb20e, 0xbb95a3f1, 0x33724b7e, 0x73148e38, - 0x0d0b8e40, 0xd2268dc4, 0x60959079, 0xbc9fe24f, 0x5dd24b72, 0x1f80ff38, - 0x71dc93f3, 0x9730fca8, 0xfb223e7a, 0x3cebc973, 0x7e2433fe, 0xc7933cd4, - 0x95ddf08f, 0xa5c87e10, 0xc51d8f23, 0xb374a3bf, 0xc75d51b8, 0x3247ba49, - 0xd208ff44, 0x518dae3b, 0x8a4719fb, 0xb23b8fdc, 0x7fa33053, 0x8f3ca46a, - 0x9c31b77f, 0x7fe9eaf4, 0x79458ea8, 0xf9d3aca0, 0xcf5e7cb9, 0x04a5707f, - 0x07f89bbf, 0xe3061cd1, 0xf507c5fa, 0xb0e249bf, 0xbbf09464, 0x63b408fa, - 0x7561ffce, 0x2febce04, 0x2fbfc520, 0x3169daf1, 0x2bd23fa4, 0x0fd82dcb, - 0xbfc80ba3, 0x45a5fb2c, 0x07230fd8, 0xdfc139fd, 0x6bbf976d, 0xfc853306, - 0xf8f3af98, 0x6b82737e, 0xa6cfc126, 0xa61efe33, 0xffcefc83, 0xfe8d7402, - 0x2c183ca2, 0x1a7f9fc6, 0xbc61d6ce, 0xf5de39a8, 0xb3d1f136, 0x08f9091a, - 0x9338a7be, 0xfb44bf6f, 0xc6194e23, 0xfcf40a73, 0x0cea465d, 0xbcb46bd6, - 0xc760098e, 0xb0093c62, 0xe6f18059, 0x53ae393c, 0x6c44ce10, 0x6b9d49ff, - 0xf997be13, 0x5f68b764, 0x8f604c4b, 0x83bf77c5, 0x83824be3, 0x3895c5c7, - 0x1f1f1293, 0x6024ce2e, 0xee9c053f, 0x8715b9f8, 0x25737180, 0xe7bec49e, - 0x635720a4, 0xf7ce87b1, 0x48c8533f, 0x718b7fae, 0x21f9259e, 0xc83548e2, - 0xd5cf2463, 0x394dc571, 0xfe9d10af, 0x3dc4f1b5, 0x1cb7d863, 0x13f3e2ff, - 0xe8f8f78c, 0xb7b2164b, 0x51effabe, 0x5e76cfb4, 0x42f0fda6, 0x8fbe41bf, - 0xecfdc7d0, 0x2ff23a9d, 0x2dbb005c, 0x3d9f603e, 0x3ddbcf9a, 0xe89539d4, - 0x596f40ff, 0x2f3fd604, 0x777c6fe7, 0x48d9fcc1, 0xbd22bd97, 0xe3e78b07, - 0xd03b0ed0, 0xbd404e2b, 0x975c5be5, 0xb1098fef, 0xd0f0c62e, 0xcbe44cef, - 0xc05f947c, 0x07ea63e9, 0xd772fedc, 0x598a38f3, 0x72ee0b96, 0x63c1c93d, - 0xf1411629, 0xc5435b9f, 0xa7ef5e59, 0x856aa37d, 0xbe1cf740, 0xa3a59c71, - 0x82b7de5b, 0xd3e5d3fc, 0xe70e6e49, 0x9b880eb7, 0x15b7caab, 0x23879c0c, - 0x815475ff, 0xe31dc699, 0xb3c12c29, 0xbff8ca87, 0x73b875c5, 0xfb3a086c, - 0x695fdb16, 0x9fdb6eff, 0xb6ddf792, 0x6e3be6bf, 0x77de6d7f, 0xf1dee71b, - 0xf57fe31d, 0xccff6e3b, 0xaf3f3c77, 0x73ffffe5, 0x70700300, 0x5cf83f9c, - 0xdfbc7040, 0x1f3efc70, 0x36106d96, 0x6a4177f7, 0x42b57a8c, 0x462d5100, - 0x0877a2ef, 0x71e24d66, 0x46658db0, 0xf0610eff, 0x5f32807c, 0x1db90b4b, - 0xe8bfce61, 0x4e79858b, 0xc596f475, 0x126c9fa2, 0x82fd877f, 0x132acefc, - 0x18cef4cd, 0xfbc04cd4, 0xa161cdf1, 0x7261aae3, 0x23edc37b, 0xdc9617cf, - 0xfe9e3631, 0xfbc8436c, 0xfec82f1d, 0x23077347, 0xa51324bf, 0xafd47984, - 0xd0fa8094, 0x3f3c2388, 0x76398baa, 0xda525e10, 0xa507b23c, 0x8b6fc434, - 0x998def1c, 0xfe869d99, 0x0bd018e8, 0x14f81e31, 0x8e2905c6, 0x4a7aa665, - 0xe58c1f7f, 0x31d16dfd, 0xe55bee81, 0xac4cf3f2, 0x9e2aa0f9, 0xebae8ef7, - 0xc50265e3, 0xfe2396f3, 0xe574d2bf, 0x89934cef, 0xff37e618, 0x8ce29980, - 0x48bd2627, 0x8956777f, 0xf331adef, 0x6ed1872a, 0x1cd63c06, 0xbbf4471c, - 0xf7a4d0e4, 0x7733e9f1, 0x750f68a6, 0x17f1514f, 0x1dfd969c, 0x8940bf8a, - 0xf65efd6b, 0xfe887c93, 0x221fba17, 0xab1dea51, 0x27f7b6f9, 0xfc10d8ef, - 0xfee045bf, 0xb8afdf21, 0xde9c687f, 0x6e78119e, 0xaf3cb372, 0xdc78bacb, - 0xecf7f142, 0xee33c793, 0x01976d11, 0x4d71d2f6, 0xcfb8f463, 0x094a6b8f, - 0xe1c0b4c7, 0xf07de0d7, 0x35fbd5c5, 0xa285faca, 0xb2b1d6a3, 0x9fa7a31f, - 0x12ff7ae2, 0x60ffe714, 0x30bf3f2c, 0xf1e390af, 0x0824d801, 0x1b12c9af, - 0x711c7d51, 0x2a1b598b, 0x7605549e, 0xacb9e231, 0xccade399, 0x34975577, - 0x7339fb15, 0xd309bfb4, 0xa9b49aa2, 0xbdaf6fe4, 0x9bfa84d8, 0x63e5dafb, - 0x4cbf93b7, 0x713da12f, 0xefda9f4f, 0xa5a30ab6, 0xfd2784f1, 0x0cdf5a9d, - 0x71e3ec91, 0x9fa24433, 0xb230aa98, 0x4c74635f, 0x2e78426b, 0xca8a8bd7, - 0xcc22a6e3, 0x3e934416, 0x4523d458, 0xe83f97df, 0x51998b07, 0x74f38f1f, - 0xe2aaf8b3, 0xcc35bb4f, 0xe7ae1af1, 0x5d5f1b5f, 0x74bbcef9, 0x971954ae, - 0x9c4a2f32, 0xaaf8b874, 0x5dc1ce72, 0x2e75457e, 0x4ff62dc3, 0xb8e3ff47, - 0xf2f46783, 0xfe334b39, 0xfe25611d, 0x8bf5ee3a, 0xe2557714, 0x45cf6eac, - 0x3be1abd2, 0x0e3f7e3d, 0x06213f96, 0xf1e217df, 0x9ef157d7, 0xffef1e94, - 0xd4bee999, 0xc5fdf21b, 0xe63f184e, 0xa1cde9bf, 0xa76bcbb4, 0x98b790f4, - 0x45e77752, 0x387ed78a, 0x53ef1d56, 0xb49779e2, 0xd56333ce, 0x0e0923e7, - 0xc369f78e, 0xddc6bfb9, 0x97bfa3a3, 0x48c77ee1, 0x73a4bbf2, 0xfaebdd19, - 0x246ba4f2, 0xf1875de2, 0x38ba00b6, 0xe187b0ef, 0x9de7613b, 0xb38c30f6, - 0xa73eeb8d, 0x752ff3c7, 0xfd1eaf62, 0x12718061, 0x1f744d1e, 0xf7cfc8b8, - 0xdfd09676, 0x5c69bae3, 0x136fe3ac, 0xe59ffb17, 0x00210141, 0x00002101, - 0x00088b1f, 0x00000000, 0x17b5ff00, 0x67534c5d, 0xb7b77cf4, 0x0bdf96e5, - 0x72223f2a, 0xa29862c1, 0xa740c2dc, 0xac741631, 0x4a8a5c13, 0x66b50102, - 0x2d09922e, 0xcbc2ccd9, 0x01893ad2, 0xb8b2c3dd, 0x26a9f364, 0x87b6e883, - 0x6ead93fa, 0x840b0b55, 0xc3e22e25, 0x52c9719c, 0xba33330d, 0xd8dc6281, - 0xdf39d85c, 0xd8bdb5bd, 0xa4da2cbd, 0xdf3f3d39, 0xfff9df39, 0x0730000a, - 0xb956e7da, 0xf84ce706, 0xffc6cfa5, 0x4fa43d0f, 0xbddde38c, 0x1726eb4b, - 0x3ebbf1c4, 0x036935c9, 0xce9c5df8, 0xf6002b94, 0x1c5ace87, 0xaccf1f04, - 0xedfc2176, 0x4ab5dfc2, 0xd2f7803a, 0xee202d4c, 0x96a666fd, 0xd2afdef8, - 0x4fe9027a, 0x8ed77bdb, 0x70045e97, 0x106b4196, 0xc12e55f9, 0xb8e08271, - 0x4546fac3, 0x25c06e5c, 0x80fce938, 0xe89b34ad, 0xd9a55cc7, 0xf5f4137b, - 0x00674539, 0xdaaf39e9, 0x09f489ac, 0x06a019bb, 0xc15c0ce9, 0x556bf624, - 0x7fdfdb81, 0x4a4f2ad2, 0xdbf11c7a, 0xe036cc1d, 0x3c8150de, 0xf7c71e59, - 0xfc028fd3, 0xd422666e, 0xb9e97402, 0xd77264b8, 0x3bafa8aa, 0x52816a3f, - 0x5c5b4ca2, 0xdf5e30ab, 0x12acfd4b, 0xbefcf860, 0x170568e2, 0xa0172095, - 0xe0373f4d, 0xb19c5bdc, 0x3d7fc010, 0x4698ca05, 0x4adf9113, 0x2a8e143f, - 0xa769da22, 0xb6e5785f, 0x4c27f7fc, 0xcdba11ab, 0xbdc268fe, 0xc3829dda, - 0x2eedc99a, 0x7920ce6d, 0x212fce31, 0xb74bd3a5, 0x51cc22ad, 0xf413e428, - 0x025ac217, 0x36ada8d2, 0x0406ef6e, 0x7ca1b07e, 0xa488539b, 0x70d69da0, - 0x6f50044a, 0xdf045395, 0xcd7b088b, 0x7c461281, 0x2be726f1, 0xbf11366f, - 0x042aae4f, 0xcbe7e3f4, 0x09417916, 0x3464dfbf, 0xf3aa8e21, 0x3c52fed3, - 0x953176af, 0x34ef6adc, 0x4193f1f2, 0xe3d6ee7e, 0xfc3433b2, 0x5ff72172, - 0xcb9e0136, 0x8e38031d, 0x18f67776, 0x756eedcf, 0x3f7461de, 0x337fa0f8, - 0x904d81ca, 0x6bde8907, 0x3b3aa394, 0x001ff18d, 0x43d62670, 0x0d41d537, - 0xe7e1c641, 0x45d513e8, 0x582a0615, 0xbf373f11, 0xf974467e, 0xf062faf9, - 0x5117f10c, 0xd80d567d, 0x024dbf28, 0xf5e10194, 0x9f412d92, 0x9eb9155f, - 0xfc01650f, 0xde17d728, 0x7e30c83e, 0x915f8f7d, 0x4a6e505a, 0xd2ca97ae, - 0x32f7b8e3, 0x401653d6, 0x036cf0f5, 0x9858fbc5, 0x794d1581, 0x28bef1f3, - 0x6eb17d57, 0xbc4ead9c, 0x31dfe6a7, 0x3a44f9cc, 0x0d9a81d5, 0x61205f9a, - 0x5817fcbc, 0x55ed1060, 0x491c3d35, 0xb2b9f8a3, 0xec8532d5, 0x23a50ed8, - 0x6b126dee, 0x3c2ee118, 0x160ef840, 0xf6e7f090, 0x005b9d2b, 0xd8b754ed, - 0x5bdc52af, 0x15aacc3a, 0x40dade88, 0x50596bf4, 0xff122937, 0xc4a97bc4, - 0x55aa672f, 0x9eb3be21, 0x445f8df8, 0xade7aa44, 0x7865a514, 0x8d28cbb7, - 0xeac1b37d, 0x551f500e, 0xf411a337, 0x3587476f, 0x84b5fe40, 0xce90cd9b, - 0xbea041eb, 0xedcf5b7b, 0x328f45b7, 0x099f48a3, 0x5f916757, 0x16d3cc0b, - 0xea356115, 0x7841c82e, 0xb005bee1, 0xb4e2bc1f, 0x73b94645, 0x05ac4c3e, - 0xc49f4be0, 0x8327c861, 0xd7c03963, 0xc30e7cbe, 0x2fd3853e, 0x8c39cafa, - 0x470e54f8, 0xa8356b7c, 0x959e3cca, 0xdd02fbe1, 0x7059a727, 0x7e6f9b25, - 0xf9623ebd, 0x29ef0baa, 0xba3e7ba6, 0x93962eea, 0x5a20c7c8, 0x6ad6142c, - 0x6730c9fd, 0x06c3e75e, 0xe881e3b2, 0x60a73a61, 0x460d61be, 0xef308421, - 0xaa6febbf, 0xd96f9b52, 0xf193b802, 0x04faf467, 0x3cd02287, 0xfad24b7a, - 0x5fc5787f, 0x48529e3c, 0xf31eb2b9, 0x413719e6, 0xd48fd20a, 0xbe7f736b, - 0x4f18eb9e, 0xc0ddb8c0, 0xcf9c1278, 0xcbf8b56f, 0x74ad1f28, 0xa7e7248f, - 0x0ac4faf4, 0xb432bb30, 0x4fbc329c, 0x600e6c47, 0x8f30b220, 0x4916211d, - 0x19df3ec5, 0x244774de, 0x96e0c3d8, 0xd73c7e71, 0x46e6d87d, 0xb6f389a5, - 0xf9268d33, 0xd54a5c13, 0x34592ce2, 0xf6d56fd8, 0x8b5d935a, 0xb56e0c73, - 0x9471756b, 0xfbeb059a, 0x381679e8, 0xa9e7fd88, 0x734ebb18, 0xd001cf2c, - 0x93c7c38b, 0xd1311e9f, 0xef990f3c, 0xd8e3993d, 0x0c8a791f, 0x3794391d, - 0x41f6260c, 0x24077e81, 0x63946dc0, 0x6e611c91, 0x192dca25, 0x9f7d259f, - 0x2f6e15d8, 0x01905777, 0xfe0450ba, 0x465f3483, 0x1a77502d, 0x639d77ed, - 0x3bfa9070, 0xf70502e0, 0x1bf1e8fd, 0xdd214f87, 0xb4c98e73, 0x5783ba8e, - 0x16ef9ef9, 0x78ff7827, 0xbc2d77c2, 0x3537831e, 0x0239887a, 0x403af249, - 0x6eed1dfb, 0x6e687f46, 0x05301f74, 0xc36ed052, 0xbdafad39, 0x41404b0e, - 0x1de8ac7c, 0xe79df091, 0x1cd1e419, 0xa5162653, 0x1980ff11, 0xafdc2502, - 0xfd84baa6, 0xfc855f84, 0xd8cfed8e, 0xf4c0f1fe, 0x6bd52158, 0x0a235327, - 0x8cb73fdf, 0x922f05fb, 0xed2fdf1b, 0xcd3361a1, 0x0643dc1b, 0x868eddb9, - 0x713f343b, 0x4be918cf, 0xf9e7df0e, 0x53af2880, 0x7e062fdc, 0xe1633d8d, - 0x58092c6d, 0x38731509, 0xca5536cf, 0x6eaddf3c, 0x1f18dcc6, 0x91757049, - 0xc991709f, 0xc7e76f34, 0xf5aed1ab, 0x419fa341, 0xc877e62f, 0xd0c7d5a2, - 0xa3f0163a, 0x94a2237c, 0x7b8ba1f7, 0x1cfd0cfc, 0x40aa62aa, 0x8c2120f1, - 0x3e3d16c7, 0x6e1f802f, 0x70a9fc4b, 0xe01aae6c, 0x2b61ac35, 0x5ea353d6, - 0x6e01000f, 0xd4e3f9a7, 0x8e23bd08, 0x2af9839a, 0xf9f8977f, 0xe055677d, - 0xe814d4fc, 0x6bafd649, 0x6ab375ec, 0xf33dc90d, 0x7b2ed3f7, 0x47d3f792, - 0x3b2276f8, 0x244ced7b, 0x2bbe30bf, 0x15efbfa9, 0x411ccb5d, 0xb5c981f4, - 0x5975ce8f, 0xbea9ab22, 0x1cdc981f, 0xee91f18f, 0x8b82fda1, 0x91f516ef, - 0x87cf8c00, 0xcc67e523, 0xa2769794, 0x125beec7, 0xe9b8e397, 0x0aa1fc69, - 0xa1efdacf, 0xfda79aca, 0x17fa867e, 0x7f57cfab, 0x1dbcb26e, 0xa497f9a2, - 0xe7d27e7e, 0x9912c01f, 0x3893cbf7, 0x6487b683, 0xaa3c75e0, 0xa67ef5ef, - 0xc87b48fc, 0x06199dff, 0xed5cf895, 0x7ff4d0cf, 0xc18beba6, 0x9bf61d51, - 0xf6f9b935, 0xfc39f427, 0x8a71c98b, 0xa4f2bdee, 0xdf824a00, 0xa0a982ab, - 0x195df824, 0xf6e031ca, 0x7c8362c8, 0x81a978f5, 0xc2b1335f, 0xbd735fc0, - 0x14bf80ca, 0x5f90675d, 0x01bd6bff, 0xc5bd30df, 0xcff1bf20, 0xd63c066d, - 0xb95875bf, 0x4936e789, 0x0ae41baf, 0x157e8d3b, 0x2afd18f5, 0x15fa35ee, - 0x37e25bd3, 0xdfacb7fa, 0xf64e5fe8, 0xde855c83, 0x91fcffa1, 0x2060fb49, - 0x34f3c33c, 0x13029d35, 0xa8c44734, 0x66c21fb6, 0xf0a617be, 0x84a2e2ff, - 0xd7a72c3c, 0x0919da3f, 0xb9d2b32f, 0x2b369d0f, 0x512edbbd, 0xfe3e600d, - 0x2e76d705, 0x000ee017, 0x00000000 -}; - -static const u32 csem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0xe3e3ff00, 0x51f86066, 0xb8d3c10f, 0x72361818, - 0x0143f821, 0x684333b7, 0x0606163e, 0xc77e2001, 0x9ef0c0c8, 0x38330491, - 0x207eec10, 0x27880abb, 0x7dcf5071, 0xe52f1143, 0x5f5d9fa1, 0x153d76a0, - 0x837f7818, 0x031083b0, 0x03309b83, 0x8408b483, 0x55045fbf, 0xc10851de, - 0x99412e7e, 0xfa819f5d, 0xbbeb8d01, 0x00038031, 0x00000000 -}; - -static const u32 csem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd5547c0b, 0x733ef7b5, 0x9993331e, - 0x420f264c, 0x084f0042, 0x21842a20, 0x38880840, 0x8d069009, 0x8808089a, - 0x420100ca, 0xa9113248, 0x676d5e97, 0x6ad11422, 0xa36d2d1b, 0x4101da97, - 0x180d45a3, 0x1d0340e8, 0x5abc414c, 0x5b4a0a8d, 0x3c3141b5, 0xe878490a, - 0xef5bd6c5, 0x33ef6b5e, 0x42667399, 0xfddfb6a2, 0x7f17dfbe, 0xecfb36fe, - 0x7b5ef673, 0x7b5affad, 0x231fb5ed, 0xd313c659, 0x057c8415, 0x7213d77f, - 0xf4842448, 0x0b3b4eeb, 0x108e3a68, 0xb0398e7f, 0xb4242055, 0x24edefef, - 0x4db39085, 0x267355b3, 0x98c7fb21, 0xf2d3d743, 0x80fc81b3, 0xdd4f9699, - 0xd121c479, 0x514ed57c, 0x3ed37282, 0xb1df7e2b, 0xde400851, 0xf1fd6e6b, - 0xb5df34b5, 0x699b2453, 0x376424d5, 0xda425491, 0xa9fd842d, 0x6a5f98f1, - 0x4daad965, 0xf682effb, 0x626683ca, 0x37b7dfa5, 0xafc86e89, 0x08042adc, - 0xf76aaf6d, 0x5a00ca83, 0xd080b2df, 0x7e695568, 0x1a8a63eb, 0xfb03c84f, - 0xb368ecfe, 0x67da7213, 0xfd82aa21, 0x491c6f28, 0x7b604548, 0x7dfa00e1, - 0x65c136c5, 0x6c57f5a2, 0xf401d73c, 0xc3c93455, 0x8adf5a44, 0x47511b06, - 0x22bfb6b0, 0x07cb5ed0, 0x794eded8, 0xfe57b428, 0x110a3de5, 0x1bb29fa1, - 0x74a2abbe, 0x76b5bf40, 0xb1eafb4f, 0x559f8d3d, 0xe8f6d1cf, 0x0a2fd57b, - 0xb562e82e, 0x8e807889, 0xb9d6dd8e, 0x7fa1db4f, 0xf8f0cab5, 0xdc2c7ec8, - 0x08a8fd05, 0xed0a526c, 0x6526df40, 0xfaeec8e9, 0x87fc3456, 0xacfabe9e, - 0x72889efe, 0x47da7a63, 0x3bbc3a59, 0xbb88415f, 0xa44bd691, 0xaa3a5280, - 0x4207f9fb, 0xa1e32122, 0x96a8917e, 0xe4a9faee, 0x23fe0711, 0x0f949ff4, - 0x81f1bdfe, 0x72dd99ad, 0x9904e95b, 0xbcedcb75, 0xea51cb93, 0x5fac8dca, - 0xf20c7f4b, 0xf9d4f4a0, 0xee3e989c, 0x8374c34b, 0xfdbe454f, 0xd30237dc, - 0x9f0b9f7a, 0xc3cbe93f, 0x8dcfa374, 0x22be53e9, 0x12be034c, 0x6fb36f7c, - 0x7c5ba62e, 0x8cfe7c1e, 0x06d31caf, 0x7f3e0d5f, 0xd31ab7de, 0x3e3f3e6d, - 0x1eb7d17f, 0x1d5f46d3, 0x5e403ba6, 0x05f26d34, 0xbe5dbdf0, 0xbe834c06, - 0xc7be7c46, 0x11f4c417, 0x64c747ce, 0x3e512f92, 0x49c4dc38, 0x8a924ec5, - 0xcd32f9dd, 0x7cb09527, 0x7cfe1dea, 0x3d53e685, 0x32f94f34, 0x6f9432a0, - 0x3501f9a6, 0xfdf07cac, 0xf342c0a4, 0x7cacfd83, 0x02ee23c8, 0xa90fcd2b, - 0x37c3e563, 0x68e20bfa, 0x9580787e, 0x542dbd5f, 0xabf9a360, 0x7679591b, - 0xa76a9933, 0xcb10ecf9, 0x9ee1bce7, 0x39f34f1a, 0xfb9f2cad, 0x83aa7f81, - 0xd8db73e6, 0x04ce93f7, 0x2d1ed544, 0xbab21d87, 0x6d595098, 0x4b70cff4, - 0x515e6913, 0xca2e21ef, 0x6eadff1f, 0x43f29d29, 0xc8796376, 0x9bcb1f3f, - 0xbf963714, 0xfcc32fe3, 0xe583d92e, 0x2c55fdc7, 0xfcb078af, 0x98bdff73, - 0x2c7eca0f, 0x58fad4b7, 0xf963f15e, 0x58f5da80, 0x80391eff, 0x1f6b23e5, - 0x4a3df2c3, 0x5f1fcb00, 0x1a7ba4fb, 0x3c11afcd, 0xd23c073f, 0x01649cb4, - 0x4ad31a9e, 0x09d69e28, 0xf7e02e64, 0x8a3a0007, 0x0ae975cb, 0x3f8ee1ea, - 0xfa0d3ee4, 0x90297f8b, 0xc3ccfa5f, 0xaffdf899, 0xd6991eb0, 0x4f5ef623, - 0xba799bce, 0x2cde727a, 0x8069ead7, 0xfb58d6f7, 0x378ecf56, 0x79e9e927, - 0x67ab42b3, 0xdf13d23b, 0xbce57eb7, 0xcf4f5935, 0x3d5a955b, 0xc49e907b, - 0x74d3d1be, 0xa69fcf44, 0xb4fe6123, 0xfafd3d20, 0xf7b8cf46, 0xf719fcf4, - 0x6f3f985e, 0x7de93d60, 0x3de9a7ab, 0xde9a7f3d, 0x08e7f30b, 0xdf506bf6, - 0x7dee35fa, 0xbdc67f3d, 0x47cfe61f, 0xdf664f48, 0xa1f5d9ea, 0x3ebb3f9e, - 0x04e7f30c, 0x6fac33d6, 0x48fdcafd, 0x8fdc9fcf, 0xc2e9fcc2, 0x5beaae7a, - 0xd23ebb3d, 0x47d767f3, 0x817cfe61, 0x5bea8cf5, 0xa2ff72bf, 0x5fee4fe7, - 0x0931fcc2, 0xbe98cf50, 0x54fc13d1, 0xa7e09fcf, 0xb0d8fe61, 0xa37df19e, - 0xcf5daf27, 0x30f6bc9f, 0x9004527f, 0xd5bec4fb, 0xf3d76c13, 0xe61ed827, - 0xe7ac20cf, 0x2bf5beba, 0x3f9e84ef, 0xfcc22779, 0xcafd8e19, 0xf40f7aa7, - 0x7c4f5a10, 0x39ecf5cf, 0x9ecfe7ab, 0x8cfe61b3, 0xd3a67ac6, 0xaf7ab27a, - 0x9e875267, 0xc23a933f, 0x7ac3c9fc, 0x9eadf466, 0xfe7a1d3d, 0xf308e9ec, - 0x73f91f27, 0x35fadf53, 0x9fcf53a9, 0x3f8c9d49, 0x4cd70f63, 0x3a72d075, - 0xfa44ba16, 0xdc67b5c9, 0x45e6816e, 0x4e8bcb27, 0x44bf0117, 0xd20dfcd4, - 0xf7e916ea, 0x39896df6, 0xbf48930f, 0xfa14a0a3, 0xb1bd4f15, 0x2123bf48, - 0xe7e74e2f, 0x7493ba24, 0x01a2e4f9, 0x95fbf7ba, 0xf795d10c, 0xaeb57b9f, - 0xa393dd3c, 0x4f9467cb, 0xa83fbdd2, 0xbf9740a6, 0xba0df562, 0xb7fd33f7, - 0xeb59f2ea, 0x3fbdd76f, 0xae916eac, 0x0afacafc, 0x8155f95d, 0x35fcba95, - 0x7baeff0d, 0x03e3547f, 0xc1d1f2ba, 0x63e57587, 0xf2eb8f42, 0xa93d0f63, - 0xeb7c7f7b, 0x84f95d66, 0xcaebcfa3, 0xd0edb627, 0xb93dafe5, 0xd9e7e0c7, - 0xf0d7ed9d, 0x27b808bc, 0x574fefcc, 0xc50bdfd0, 0x0657982b, 0xdf8fd1d8, - 0x3d54bf1f, 0xbcabe54e, 0xa14d58b2, 0x129905f2, 0x0fe7ae3a, 0x8db2bf28, - 0x9277bf3e, 0x7d274ae7, 0x19e2af7e, 0x9fe18ced, 0x24083c52, 0x04d5520d, - 0x41fcb1a9, 0x20b1e199, 0xc7e1cbe3, 0x535ef7e8, 0x9a44f0d7, 0xd7e62fef, - 0x129e5e03, 0x38d3884c, 0x7bc0d491, 0xf3826671, 0x73330782, 0xe047f69f, - 0xaa20fd75, 0xbd774287, 0x1a4f65eb, 0x6b9b19f8, 0x1f83f6df, 0xed106eb2, - 0x9e4200d7, 0xf90ede16, 0x07efd287, 0xd0f34d2d, 0xf50accfa, 0x57db23d3, - 0xb123fb68, 0xff6806fd, 0x37da1ec5, 0xb5d3c90f, 0xae5c196f, 0xd0a2df6b, - 0x1fd49df6, 0x6f23fda8, 0x12610a9f, 0x7f0b2f21, 0x83cdf6c4, 0x07fdb1cb, - 0x895f3a15, 0xdc2e3f6c, 0x77f4107e, 0x3e3fb41f, 0x4c87ff46, 0x707ff7d2, - 0x0affbe85, 0xb52bffeb, 0x71fb78c7, 0xe116ffd8, 0xe0ffeb18, 0x337fd60a, - 0xbedc37ab, 0x43ffcc23, 0x7b37ffd0, 0x64d67fea, 0xa8afff7d, 0xccdff7d4, - 0xf6a77fda, 0x8edf6f14, 0x9c2bbfed, 0xa2bffd62, 0xcc57db12, 0x47e0171e, - 0x09ab88c9, 0x40c9f6d0, 0x03fa986a, 0x903b685c, 0xa0a2488e, 0x6151e426, - 0x6f71d208, 0xe7dbc31c, 0x686f1471, 0x9cf8fc6f, 0xcb65a804, 0x8e2ef3a5, - 0xf2db15f5, 0x584bb015, 0x4b2be74e, 0x4165a938, 0x364df111, 0x28c30398, - 0xd1411dbd, 0x0db2f90f, 0xfec005d7, 0x4164cd79, 0x91277c09, 0xf4ff3c10, - 0x4736a367, 0x2e98cbf6, 0xdbdb93a9, 0x3c2df422, 0x23202a8f, 0xd37d286a, - 0xbbe30401, 0x79d31ff3, 0x8bf3a110, 0x833ce80f, 0x227e4850, 0xa23ef6b3, - 0xb7c825f3, 0x9412f9d1, 0xdf8b5213, 0xa70eead1, 0x384bfa51, 0x4c4b1ffd, - 0x43be3f5f, 0x7ea9f808, 0x31bdfe7e, 0xb05d4f38, 0xde9946da, 0x7f42c74d, - 0xfb4f2eb2, 0x753907e5, 0x360736ed, 0x155fc80b, 0xaa8a55f8, 0xf5e2c849, - 0xddd79419, 0xc54fbfef, 0x7f594e9e, 0xfdcb711b, 0xae77fbe9, 0x69390612, - 0xe6ddb3bb, 0xb84e361c, 0xd7a84c33, 0x4794c324, 0x634dadc8, 0x29035a64, - 0xb71fcb75, 0xb33bb445, 0x5d9f9f48, 0xc877cfa2, 0xe944d96e, 0xc81528ea, - 0x9cef5a26, 0xad72fab9, 0x8929bb1d, 0x57b799c9, 0x9be8ca92, 0x3c0e6903, - 0xe79ca276, 0x1ab7d93a, 0x32c5de3d, 0x3c82c29d, 0xc808fdfd, 0xef829fd5, - 0xfd64eedd, 0x573bd236, 0x684bb8b6, 0x142ee73f, 0x236f8003, 0x67da7ffd, - 0x69b29b73, 0x32a7feba, 0xc7f74531, 0x8f3cff48, 0x328d3fb1, 0xcbf3c38c, - 0x6e19cf8d, 0x3ffcb9da, 0xf4d07c06, 0xd283e004, 0xa3e39c7f, 0x7c32aedb, - 0x9b9ecd78, 0x4f5d0f01, 0xcae50488, 0xc71b72f1, 0x3d3a92cb, 0xc8f1082e, - 0x7365c720, 0x23879c85, 0xe3873070, 0x1ebd5960, 0xbf127737, 0x2e431e9c, - 0xfa6c36f3, 0xdd1a9a61, 0x6e390fbf, 0x1fb23fe6, 0x4fdd13f9, 0xb8bba726, - 0xd1acee9c, 0xe5c6df97, 0xeb97277a, 0x0ec7fadc, 0x6e41f350, 0xe8320357, - 0x4d3ef7bb, 0x793a6d9e, 0x8d3cb87a, 0xe5c5de74, 0x98f7d779, 0xb6f48d3c, - 0xd5b67971, 0x90c9905f, 0xf48d7a68, 0xd51d582d, 0xb9e4051f, 0x9e5b1fd0, - 0xf27e60de, 0x55e788f1, 0x8f92338d, 0x8ad9e847, 0x7e5d5286, 0xee9e6079, - 0x0bf565fd, 0xea4be575, 0x17caeb96, 0x975bbfaf, 0x9effe85f, 0xab05fdee, - 0x77e5756b, 0x2ba43cd6, 0x98fe5f9f, 0xf3cf3f2e, 0x39fdee84, 0xcae93773, - 0xa73c9767, 0xb4599f2b, 0x752f975d, 0x6fbdd6ef, 0x2dd577da, 0x8e37cf80, - 0x89fc0488, 0x30275ccf, 0x4b99f82e, 0xc73bc176, 0xbae22a7d, 0xd30237dd, - 0xe2173e93, 0x0f2fb4fe, 0x8b608ed3, 0x3a09c61d, 0x89252e2e, 0x6e9bccd4, - 0x103f5dae, 0xe38269c6, 0xacd316e9, 0x4264ff5a, 0x91526d7e, 0x0af5c5df, - 0x44258d09, 0xd386c180, 0x944625d1, 0x5e52f5b7, 0x727f0d4f, 0x5b717974, - 0xc7dee7ec, 0x8ce15e17, 0xd6e97711, 0x7e019253, 0xbbf7274f, 0x0295e58d, - 0x4e7c8929, 0xd7a803c8, 0x5bb8f8e7, 0xaffd30a9, 0x405e91dc, 0x0d0f901c, - 0x7b5cb9af, 0xfde4148d, 0x3a592701, 0x7f565e3d, 0x13bece8d, 0x03f6ca88, - 0x3dd58dbc, 0xad70d15f, 0xfb33bbee, 0x1abba445, 0x1844c56c, 0x375e4b16, - 0xb50e1d81, 0x0a399e0c, 0x61bf74e8, 0xd82a7182, 0x33c2fd0f, 0xe3e4a2be, - 0x04afc812, 0xb9be93d3, 0x3cfbb698, 0x95f71e98, 0xafb1fa63, 0xdf36d306, - 0xf23f4c6a, 0xc0fd31f9, 0x3fd31eb7, 0x3d30eaf9, 0xf4c7abea, 0xd3005f3d, - 0x4c06bec3, 0x6235f1df, 0x620beada, 0x6373e1da, 0x6f5de9aa, 0xc7c93bb8, - 0xbf80d3e1, 0x78eb3818, 0xfaed5560, 0x3b38ddc9, 0xd6afba6f, 0xcf9bb03f, - 0x8e66f5c5, 0x1e1d5487, 0x336080be, 0xf297ace2, 0xb0e3997a, 0x9763efa7, - 0x6bff377b, 0xc4de36f0, 0x8a6fccfc, 0x653c6eb7, 0xd594f018, 0x89fa9e1b, - 0x34f1bbe3, 0x7e64e4de, 0x8fd3c70f, 0xe6311fa0, 0x84e00515, 0xd7f08bf4, - 0xa71636dc, 0xd409ebe6, 0x6a716553, 0xfa1af6de, 0x75fa2b6e, 0x6e301181, - 0xb7f11f9c, 0x3f8710e1, 0x274cd47f, 0xcff73d7d, 0xf99e9388, 0xcdf9c6ee, - 0xbc1d00d2, 0x5b9746c6, 0xad5f18e3, 0xe8445226, 0xb0d0f6b8, 0x468b5c67, - 0x49225e62, 0x55c07df0, 0x5ea31f1a, 0x7f032bea, 0x9aebe37b, 0xa1b3cff8, - 0xff27f6be, 0x78e90b9e, 0xe397f313, 0xdbf4445a, 0x1769e849, 0x2e3c37f0, - 0x10695d99, 0xa61aeedf, 0x086fd138, 0xf3fcf5d8, 0x376e7cd3, 0x3ca21eff, - 0xb771c56a, 0x37f90d2e, 0xe9e1f3f4, 0x6f5fe07d, 0x7e37bdf6, 0xf80c0a2e, - 0x37b3f097, 0x5d9bd8fb, 0xc5f56e24, 0xe77fed20, 0x0f3951be, 0x870760ab, - 0x0f5a79b0, 0xa5d6d6fc, 0xff7cf48c, 0x33b8e26b, 0xeb71c355, 0xf9db4260, - 0xf9cbeb88, 0x40132ba6, 0x9c1eb42e, 0xe4ed741f, 0x722f7e7e, 0xafa99b3d, - 0x2fac6bcf, 0x68c22141, 0xa2bc6eda, 0x6a420490, 0x22a3cf44, 0x6d5c6fce, - 0xec1b887e, 0xa8d6b9b3, 0xfd3c6f30, 0x1a854866, 0xf385f1f5, 0xc0769e87, - 0x9a656c3c, 0x863c79c9, 0xaab4b51c, 0x8f69d331, 0xf504af9c, 0x4275f3f9, - 0xe7ce2351, 0xa35984d4, 0x3a719c60, 0xbb050f8f, 0x56a9869f, 0xc534cacf, - 0xddda9c79, 0x09590dd3, 0x6017fe6c, 0x225b64f6, 0x3ed39bda, 0xcfffbe0b, - 0x7aa7a7a6, 0x69087a34, 0xc0589f22, 0xacb2d39e, 0x51efdf9e, 0x0a8ba41f, - 0xb34937c4, 0x37cc39fc, 0xaffff4ad, 0x12bd4086, 0xbd7ab5e6, 0x3cdfa28d, - 0xd36f9e1a, 0x53bf47b5, 0xf857b5b5, 0x93bd67ae, 0x7b86bb48, 0xf957bf2a, - 0x068af0fa, 0xc7ef53ab, 0xdef2ea26, 0xe753ba60, 0xc03fc2d7, 0x2411af71, - 0x87255fc0, 0x5f64a75f, 0x0cda780f, 0xbf9843c1, 0x2abdec08, 0x51e29b4b, - 0x015a5d51, 0x34f28b9f, 0xfe73abfc, 0xa9d4ed4c, 0x7a0265d7, 0x54a4be46, - 0x20a9f2e5, 0x4c44cde2, 0xbf98bf34, 0x4569a8bd, 0xa75b8c31, 0x50fe6c4c, - 0x301c4a46, 0x75272e3f, 0x3d4f10b9, 0xa0454c4b, 0x3bc9679f, 0xfa11b18e, - 0xb0544e78, 0xf5ebc5d2, 0xdf9d3c7e, 0xeacbf2eb, 0xe4a5f9f5, 0x075854d6, - 0x2641ba5f, 0x86ec0101, 0xe898fcbe, 0x91977ac4, 0x6e30759a, 0xbbc79cff, - 0x94893916, 0xfaabe941, 0x17732fcd, 0x892e3a52, 0xd6d5fc6c, 0x31279771, - 0x05662bfa, 0xff7d3714, 0xb7b1a693, 0xbf440b51, 0x7583ac0f, 0x71297f6d, - 0xf2d1256d, 0x1bf4bafb, 0x81fcd5e9, 0x4e64f5a8, 0xe0834a47, 0x63b0c40e, - 0x3d30248a, 0x6aeef6e3, 0x838ba9c9, 0x223e42e4, 0xf18df20e, 0x78744294, - 0x067a2cda, 0x7e19e34b, 0xd4820f00, 0x4dbe78a5, 0xf55169fd, 0xfbf52d5f, - 0x903fd627, 0xabab9fd6, 0x4a9ff73f, 0xfa28d0ff, 0x5fd5620b, 0x76179bf5, - 0xa93da9f9, 0x0e67e978, 0x53c9c742, 0x8baa5d52, 0xeb72b5ca, 0x9a6e1d0f, - 0x0efc949e, 0x80a9ebc0, 0xde4b1458, 0x76f2c3ab, 0xbb8805db, 0xfd693fc1, - 0x11ff9fa7, 0xdf3e23c6, 0x9e313b2a, 0x990e60d6, 0x37563ea9, 0xd9262f2d, - 0xf2c63f98, 0x21139e0f, 0xafe3d41f, 0xa59fd9e2, 0x8a0afec2, 0x0a5f1e14, - 0xbd5b3fa1, 0x1c42d3e5, 0xea17489f, 0x683bf191, 0xda1252ff, 0x424a85bf, - 0x13a53974, 0xce5e04e3, 0x8fd36f17, 0xf80e89ce, 0xdfce1b57, 0x7397ef8d, - 0x14b974ff, 0xa36ed29f, 0x26409eff, 0xf8d43d80, 0x3fcc0241, 0x2fdcf35d, - 0x7a518fb2, 0xdd796cce, 0x49f04421, 0x8df3a3d3, 0x47b57f8b, 0x76ded9ed, - 0xf48b3d50, 0x4af1b483, 0xbabf720d, 0x7295a599, 0xd52d71c8, 0xb24dcafb, - 0x571f4fcb, 0x33f4f0be, 0xf31c424f, 0x30d7668f, 0x178aff5a, 0x8937bc0e, - 0x976c57e6, 0x37598a53, 0xb76a42ec, 0xfff4bc5c, 0x72dd39d5, 0x80f978a8, - 0xcf628ea2, 0x96ea4fef, 0xfbed8ac7, 0x9a2a3215, 0xf71b531f, 0x18f66d2b, - 0x563c6972, 0x9ac27e08, 0x814bfee7, 0x7da9e2f8, 0x199fe902, 0x0e9b9f83, - 0x7c001fa0, 0x39723942, 0x7866e585, 0x02e54bdf, 0x93935af6, 0x6e46fcb1, - 0x753ea04f, 0xc5f9e224, 0xf2fdb43d, 0xd05d993f, 0xef17f2ff, 0x4e3f4071, - 0xd70c3548, 0x2a61fcbf, 0xd972afd8, 0x94c4ea9f, 0xea7f2f3d, 0x65b788bb, - 0x15377f6f, 0x9dc449e3, 0xc7b1c26e, 0x5bfd0e9f, 0xf63671b2, 0x20f1296f, - 0x297fcaee, 0xfa680496, 0xb68a4499, 0x0e8bd0c7, 0x362717ae, 0xf68c4753, - 0x1fcc04ef, 0x23bf5ec1, 0x422abee2, 0xffa026ee, 0xa17de5df, 0x3fe6021e, - 0x1d3930b3, 0xaf5c4c90, 0x8919b7a8, 0xb60f2dd7, 0x0f4e7c82, 0x7587f772, - 0xfc912f16, 0x57c21f9c, 0xedf15eb4, 0x7c99fde9, 0xf2e52a88, 0x3f38e8ef, - 0xfbc39e15, 0x9adbb2ad, 0x7c8efbad, 0xfeddd995, 0xa53ede2a, 0xe7c60e3b, - 0xfdb1a913, 0xa6b201d5, 0x8e9c74f7, 0x7e8457c0, 0xf2df7d33, 0x4d6fd310, - 0x45a503df, 0x30f17e50, 0x0ef81fd3, 0x574a3fc6, 0xef963fa8, 0x3da0259f, - 0x58e6f3a0, 0xe645bd7a, 0xd72fad7a, 0x96e94270, 0xbc088484, 0xc849fd40, - 0x595f5c7f, 0x177e81ba, 0xd0bd2f61, 0x3eba239e, 0x71976f4d, 0xfa053ffd, - 0xfeb74d7f, 0xef4c8d93, 0xfc9ff67b, 0x07236e2c, 0xf412799e, 0x5fa7ea95, - 0x4b957d05, 0xdd7fdfa0, 0xeddef2d6, 0xdaff4f54, 0xdea9e9a8, 0xb4f51a7e, - 0x1278c77c, 0x6aff4f4b, 0x7a989177, 0xd4c79f4a, 0xe21b7b53, 0xfd94fff8, - 0x2897f8d4, 0xd9a7f9eb, 0x68f89ec3, 0x4a2f87b4, 0x68d3f22a, 0x61dfe90f, - 0x3f8d1b92, 0xde1a770d, 0x755d7e2a, 0x309dd805, 0x85dc352e, 0x2ee1a971, - 0xe3ab7e2a, 0xcffcb19f, 0x74a26b10, 0x4fd4b7cd, 0xa5847981, 0x2bbce08b, - 0xeb88967f, 0x048b96a6, 0xc880bef5, 0x7df06fb8, 0xf078cd53, 0xfdfca743, - 0x52f7b3b6, 0xbf13e77a, 0xebe5d6cc, 0xbfebf464, 0xc9abeafc, 0x73b73fb4, - 0xeca7cefe, 0x63ca89be, 0xe28424ae, 0x24f39d28, 0x82484fe2, 0x3e40acf8, - 0x7e63a08e, 0x7f0f3eb9, 0xebbb5253, 0xaffdede9, 0xa6f90f3b, 0xb63edbe9, - 0xa42ef576, 0x2979b143, 0x20a54f12, 0xef3fca57, 0x04302138, 0x549b52ed, - 0x7aaf3112, 0xb79ddb9c, 0x0f1ccda7, 0x9cfe4bfe, 0xe70c0951, 0xeb7e7183, - 0xbcebf6e5, 0xbb004d5f, 0x0b39be7e, 0x0fe7afe7, 0xb58f8e2d, 0xe385b26f, - 0x575f00ec, 0x750bb4e9, 0x277dc522, 0xc5ff42e9, 0xad92b76f, 0xbefdd631, - 0xe4f89b2f, 0xfe8dcb83, 0x736e5489, 0xd1e70e39, 0x2272134f, 0xa6eb36e4, - 0x5a239253, 0x71f7f00e, 0xdbeb3cc4, 0x0d7017f2, 0xb6b16dfc, 0x88c49615, - 0xf384fdd7, 0x5f2bca6f, 0x69d5fee0, 0xf012f9cd, 0xd45d9a71, 0xd41e39c5, - 0x192475f4, 0x794d7409, 0xe3a3f965, 0x87bd8e29, 0x57ec1744, 0x539f36f5, - 0xbbe6313c, 0xfd427e46, 0x901e47e0, 0x23afc89d, 0xe012c972, 0x56d991eb, - 0xef96eb02, 0x58aaae2a, 0xb3374e74, 0x523cc878, 0xe138d9f2, 0xe6fe3eff, - 0x150f89cf, 0xb79c7e50, 0xd1c0fdb3, 0x7f7a63f8, 0x6a0429de, 0xc8a1c005, - 0x004229f2, 0xc48564e2, 0x0164e8f3, 0x48fafdf5, 0x2c1f95fb, 0xd5f6017d, - 0x4e0b3754, 0x96af2d13, 0xb1c014da, 0x025db837, 0x9546fcff, 0x20de31b8, - 0x159a8cd5, 0x203ad711, 0x96afc84b, 0x277eddbf, 0x2cc2f7f0, 0xdcba0133, - 0x6039cf23, 0x3cd0bfdc, 0xa7a0f516, 0x47c1fd7e, 0xa0934ca6, 0x30f8821e, - 0xc530a1e2, 0x9ecfcba6, 0xa8ba064a, 0xdb98a6dc, 0x90c571ee, 0xe18532df, - 0xcdf6cfac, 0x7d99fff2, 0x1bed4c9b, 0x691cb5c3, 0x512b46df, 0x2c7fadf6, - 0x56b2b6fb, 0x58b80fed, 0x3fab37b9, 0x6be575c8, 0xb2c5fa4b, 0xd8faaf6f, - 0xbe35fdfc, 0x2073bb0f, 0x23a36fb5, 0x6a40dbec, 0x6dc462df, 0xffcd15d3, - 0x59bec5ec, 0xeff477fe, 0x316fb055, 0xd1523bfa, 0xe6a2b7db, 0x456fb45a, - 0x7edd4503, 0xcf852ca8, 0x6fb47ae7, 0x1b367f0b, 0x16cbb2f3, 0x57c03f03, - 0x71af6fb0, 0x80ed073b, 0x38a45b9d, 0xdabefdb1, 0xdabed2b9, 0x3e25ffb9, - 0xe56e766b, 0x239e7620, 0xcecc871a, 0x7664ccad, 0x665ee56e, 0x630e56e7, - 0xdf68ce76, 0x1beca20a, 0x047abefb, 0x8be71efd, 0x83b8bf99, 0x95cf1796, - 0x7efa165d, 0x5f9daab1, 0x691f19a8, 0x122916ef, 0xdeca39f2, 0x39e1ceb9, - 0xddecde90, 0x86ef605b, 0x0a1b1da2, 0xc7c4647a, 0xba6d430d, 0xbe4772fd, - 0x4bf5ff68, 0x107f2fa0, 0xbefd9e71, 0xf68bcd89, 0x163ed17d, 0xa7376ef4, - 0xc98551e7, 0x47e7c3b3, 0x24753a7b, 0x43aaf7d3, 0x544e3871, 0xbfac0937, - 0x15010bf7, 0x5dbf81c6, 0x9df2f9c2, 0x797cd97b, 0x83f1998e, 0xcec89bfc, - 0x2c16505d, 0xdcc3c08c, 0xd718154b, 0x0b112b9c, 0x0e0baff8, 0xfc0a70dd, - 0xd69705d6, 0x00bbbfa3, 0x89bec39e, 0x32eb6ded, 0x2e77bb68, 0xa1de7017, - 0x1798efed, 0x3f7a97b6, 0xec737e76, 0x38531a7d, 0x13ee533d, 0xa72fb002, - 0x2f107db7, 0x239bfd72, 0xc8bf21b6, 0xf8cc625b, 0x985ef6a4, 0x97c62e4f, - 0x6fcc55aa, 0xf289f30e, 0xf9a2154d, 0xbc5d2544, 0x2f9bb530, 0xfda4ee77, - 0xbfb9e94d, 0xf7a2df1a, 0x3e71b8e1, 0xd7bf80b3, 0x3e341f13, 0xf39ff547, - 0xb8a9fa9d, 0x8fc8c79f, 0x5ccecd46, 0x5e814643, 0x3cf26fbe, 0xf4701e3a, - 0x942f949f, 0x0de6dbce, 0xd9e79dd3, 0x9372f9c5, 0x54b4d8e7, 0x6a48f815, - 0x97b76700, 0x4a903f6f, 0x3b8b77fb, 0xe6420733, 0x78a6ffb3, 0x62d0fe20, - 0xa83b42ed, 0xcccd30e1, 0x8e57f870, 0x9c0323c3, 0x09bc70d3, 0xafd44e0a, - 0xf1cec190, 0xca5e647d, 0x6f5fd067, 0x144f8f90, 0x859fa09f, 0x720578da, - 0xa9bcffa1, 0x5bc5c999, 0x6e5ca023, 0x81075d26, 0x8229d5ef, 0x2aab442b, - 0x21ff6e0c, 0xd57ab7ec, 0x9e839f4a, 0xcdae0b97, 0xf4f61d8c, 0x963898d4, - 0x3718e162, 0x9b8c4609, 0x24bde00b, 0xc668b7d8, 0x1efceff6, 0x3f4647b3, - 0xf5b98a65, 0xe533d008, 0x09b264df, 0x7fe8061e, 0xfa303811, 0xf07a5131, - 0xa4fdf735, 0x2afdfb72, 0xfc0ec1c8, 0x1fc052ee, 0xf8d886f2, 0x257b95a3, - 0x4df21a75, 0x8e904393, 0x1c98e32f, 0xc8dfa960, 0x3cb45be7, 0x6fde1fe0, - 0x7ef86416, 0x324f9506, 0xfa6a9a2d, 0x7786a0e2, 0x2fcd1ab3, 0x47a42788, - 0x6fb00dd8, 0xd596eb91, 0x4f91b7c1, 0xeea2ac37, 0x27cd1a99, 0x07603e4d, - 0x28afc72f, 0x8fee09fd, 0x9bea7fb9, 0x599a4fea, 0xacfb3faf, 0x868faf5d, - 0x015eda38, 0x4e690aed, 0xf20fc5d4, 0xd65e6ccc, 0xce20f562, 0x5d935ebb, - 0xfb68d59b, 0x0b971573, 0xcf2257cc, 0x0e854def, 0xd3b1bac1, 0xfad13e4a, - 0x2ce1843d, 0xd5783c72, 0xf5f941ea, 0x5e04ff54, 0x98fe4f7f, 0xb40eff96, - 0x5516fb07, 0xf1c67b7d, 0xf5278b48, 0x6669afd6, 0x69be3f66, 0xbe76b4bf, - 0x9783baee, 0x4dfc62b4, 0x2cd87f5b, 0xc32e7e7a, 0xd048b8fc, 0xca5073ad, - 0x9ff2fd71, 0xe558ff50, 0xfc43f532, 0xfcf94428, 0x31a7b6ea, 0xf9f67d5e, - 0xfe833763, 0x48adf8ac, 0x3a9f542c, 0x1093c5b6, 0x80a207db, 0x24d1509f, - 0x91167ae2, 0x2333b942, 0xd6420cfc, 0x14bc7e30, 0x62a7768f, 0x4c503987, - 0xf5d8afbf, 0xddc43649, 0xf6601e3a, 0xc73cffcf, 0x1b2dbfa3, 0x242bfbd6, - 0x946f8eb6, 0x9f1cbdcf, 0xe6db7667, 0x1a16fd82, 0x8ad779d8, 0x39b239c6, - 0x6550ce22, 0x7b5c5996, 0x59f70db7, 0x70139ffb, 0x17d0329f, 0xdb52ce79, - 0x39e679ff, 0x822b9766, 0xcdce0072, 0xef6c3456, 0xc5783880, 0xaffa3351, - 0x0a7386de, 0x5f53a7f8, 0x23fd017a, 0xc5d4506f, 0x8fe2a341, 0x0cc8620d, - 0x2aa6b3f1, 0x7f3403b4, 0xb18df30c, 0xc5bdf0e3, 0xb4bc56c9, 0xb29f9777, - 0xcfcbc570, 0x6cdcf03a, 0xc60756eb, 0x1f2e1b21, 0x378a8fff, 0xd9743e36, - 0x8e69e378, 0xf5995f8f, 0x21a435eb, 0x9490e319, 0x1892dcbe, 0xee308b71, - 0x29ecf85f, 0xb33b0f58, 0x014fafe3, 0xb8ff95bd, 0xe07dd4f0, 0x3ab3ed8f, - 0x3ef6bc61, 0x13d7047f, 0x7376efb4, 0xee78ef3d, 0xe9875c59, 0x05d9a3f8, - 0x3dec75b5, 0x23d61831, 0x917fb63a, 0x55db710a, 0x3ce3a77b, 0xa9ced56d, - 0x798c49fd, 0x6e029680, 0x07587d03, 0xa5abca32, 0xd03065a9, 0x1bca9679, - 0xfc70b65c, 0xc58ab1b8, 0x371e55e3, 0xbd7b16de, 0xdc4e2a2d, 0xeb96f334, - 0x926efc60, 0x43e92a5d, 0x9530f8bc, 0xc83ee8e3, 0x9a43db6f, 0xbf298fbd, - 0x2a0ff0b3, 0xf20df7a7, 0xc969acfb, 0xb2849eaf, 0xe31ee4a6, 0xf03ea1c5, - 0xdbcf5b4d, 0x6c7f7662, 0xf1d9bd06, 0x83cf8c6b, 0x835ce8dc, 0xd9f0bc74, - 0x9cb38860, 0xc2eebb94, 0xcd7b33fd, 0x62aa2fb8, 0x3fa8fbef, 0xc6df3b1d, - 0xd7c232f5, 0xf8483ad5, 0xf083ad8f, 0x4b779c39, 0x73338b3c, 0x5a1c43fe, - 0x1e73e075, 0xd638666f, 0xc53dd0e2, 0x6c2dd39f, 0xceb6913f, 0xcfe5b558, - 0xf5c4310a, 0xd3903c85, 0x8baecbb1, 0x02707c6a, 0xae44261f, 0xf38ec4a7, - 0xb8ddd787, 0xe07e40bc, 0x4bd7857f, 0xc4207e68, 0xfbc203cf, 0xe83d8624, - 0x61d6c4d8, 0xfbd8e43a, 0x95f5b50f, 0x4f418b14, 0x575b7d03, 0xaffe8de9, - 0x26191fcb, 0xf9a3e39b, 0xd8cbe674, 0x45827c76, 0x61fb76f8, 0xf5a8852a, - 0xcfac0b7f, 0x60531d37, 0x638da1fe, 0xf0cf7f5a, 0xe799f279, 0xb1ef3c45, - 0xed05b1ae, 0x545ed1b8, 0x341f1613, 0xd3833bd2, 0xe3641d5b, 0xf11d99c4, - 0xe7ad3b01, 0x11bb2bcc, 0x8edbd5cf, 0xdf5a7e29, 0x959786c1, 0x52fd88b6, - 0x22044e30, 0xe2f33fe8, 0x7eb66cfe, 0xc6e5e6c4, 0x76f0e676, 0xdbb1cdbc, - 0xa73b6ef1, 0xbf85676b, 0x77e76151, 0x69dedf2e, 0xea073dc9, 0x132add3b, - 0xba7fbfd8, 0xc40a2c51, 0x45927f68, 0x4cf2e2d6, 0x8978e86f, 0xd9e31de7, - 0x493146f9, 0x557aff41, 0x84d1de7c, 0x15154814, 0x6a6b14e2, 0x35d2fed9, - 0x81a577df, 0xde24d7bc, 0x756deb86, 0x533afe06, 0xbf10f99c, 0x192b4e70, - 0xda357007, 0x49b7449b, 0xf8aaff47, 0x1e70fea2, 0xc7f72d7f, 0xf3c2e488, - 0xb0a3a297, 0x3a23fa08, 0x8c6b4e4d, 0x5ed905f5, 0x7c113c42, 0xf3fa9d91, - 0xb1cbe492, 0xeda3d42a, 0xb4b4a9a3, 0xa742c41e, 0x4b0ab71b, 0xfcddec79, - 0x77ec4e59, 0x4f3e36e7, 0x99d51370, 0xc183f6ca, 0x23b9d1b8, 0xc68c9b21, - 0xe29b890f, 0x0b9fc6d1, 0x07eff6db, 0x41d6b47b, 0xcf5489dc, 0x31555728, - 0x8e8dce0b, 0x805908b1, 0xfe6f73d3, 0x6d6bd696, 0xd0fe7116, 0x85f6d769, - 0xcf4113ba, 0xdc11e46c, 0xfe5007ff, 0x4e9bb92a, 0x0240bee3, 0xdf76a4af, - 0xb45d312b, 0xfce7bce3, 0x10071646, 0x98bfd5c9, 0x2470e2cc, 0xf1f3f400, - 0xf3a70564, 0x7ef0a43c, 0x3ae78299, 0x72f6bd96, 0x3930886e, 0xb92bf244, - 0xb4be7f48, 0x86c8eade, 0x77e27975, 0x9939c2b7, 0xbf5f5e32, 0x53b9fd12, - 0xd07e7eaa, 0x4f5c25d3, 0xf0b4baff, 0x32bfd810, 0xebb452cf, 0xcfeae7fd, - 0x59f71aa5, 0x2fb0bd21, 0x93ddea8c, 0xabbef442, 0xd6c7e6f2, 0x7a397cc1, - 0x011915ff, 0x482ac9fb, 0xe7ce0b9c, 0x97d068ac, 0x79bb03ef, 0xd893b015, - 0xebef172f, 0xc36dbf95, 0xdc79317f, 0x0aebf965, 0xe2dbfbc1, 0xecb2ae31, - 0x9f68c5b5, 0xfe7a69cc, 0x7f3d555a, 0x7c8c236d, 0xde39f3d4, 0x369be7a5, - 0xcf89ecff, 0xf3fa7909, 0x4b3e46be, 0x021bc784, 0xb5110e2c, 0x09b82dbf, - 0xd9f236e9, 0x0b76d7c8, 0x7ce2f75f, 0x96257fa5, 0x81b26654, 0x842974ee, - 0xa3d4617a, 0x80487b0c, 0x094a0f7f, 0xae57e2d4, 0x69efb478, 0x19423fbc, - 0x7a06cefb, 0x2ebd0224, 0xd13823d4, 0x46de7607, 0x5bb6703e, 0x909f5841, - 0x59e9aeaf, 0xfe94f79e, 0xfa22d8fe, 0xefc046d5, 0x762bd468, 0x0489376e, - 0x9e8264d6, 0x6e309cba, 0x6a2cfa37, 0x9ff70499, 0x286cb510, 0xc4e27bdc, - 0x1f7cc7f4, 0x8248e74a, 0x431b82fb, 0x3ec15317, 0xeba738fd, 0xde7bb066, - 0xec04a425, 0x6c71cde0, 0xa798b29e, 0xdc2ab77f, 0xed7b4eae, 0x59bef87a, - 0x785ce156, 0xcb56f367, 0x4507c830, 0x9bc47fbc, 0xb4157758, 0x332cd1df, - 0x812ccaba, 0xd8bf1061, 0x1dbb632b, 0x7cf19365, 0x6b6fd865, 0x3a40fb66, - 0x2c713f9b, 0x1de7b08e, 0x055e9fc1, 0x4c27acf1, 0x0c9ff7b1, 0xfdf89ab7, - 0xfc70df35, 0x7fda8c6d, 0xf6cadc37, 0x0878fdc7, 0xe97547ed, 0x330e3e79, - 0xcb96b87d, 0x6f4bf7f9, 0x6ceffec0, 0x47185416, 0x6e3bc50a, 0x39fb451c, - 0xe3c488f1, 0x392e2c30, 0x9bbfbf8e, 0x1f80d2b8, 0x0223af13, 0x3fc4f3e8, - 0x35b7dc12, 0xce2966ae, 0xa0eb7eab, 0x7586cf38, 0xb05b8a52, 0xe8ec6773, - 0x956f8fbf, 0x9c4cb874, 0x798169e6, 0x04a384e6, 0xa384eded, 0x123cf2fa, - 0x369db110, 0x4f6bf3fd, 0x5605f3ea, 0x49076f8e, 0xf86f7c05, 0x3aba4452, - 0x01eb88bb, 0xd9676f5a, 0xa6efbc00, 0xda9c22f3, 0x6297e9a5, 0x7e71ac51, - 0xf281e026, 0xe08509eb, 0x52c4f2f8, 0x5fefc63b, 0x05715a59, 0x7f9feb8c, - 0xac4573cf, 0x7611e073, 0xafed8129, 0xe2502772, 0x0ad7ae29, 0xe975df8c, - 0xebf63125, 0x70d6386b, 0x7d39e1ad, 0xd6279c69, 0xad0fc4be, 0x58290fcc, - 0x6050423a, 0x204fb65e, 0x078ed7c0, 0x373d973c, 0x640f27e3, 0xe0de3d00, - 0x2db3f405, 0x963b82cd, 0xeacab19f, 0x07bef360, 0x1fb0b5fc, 0x94aa5eef, - 0xae7b1f60, 0xabce0377, 0x2ba0876e, 0x5ba9677c, 0x9770e788, 0x8866c858, - 0xe9754b67, 0xee03c6b7, 0x4758cea7, 0xc4b27de9, 0x427e7284, 0xfefd2176, - 0xbe30422a, 0x03b5e3c0, 0x229b266f, 0xc0ff23cf, 0x95b0ff9a, 0xd5b0fbd6, - 0xf6497289, 0xdfa004b8, 0xe5ffdff5, 0xbceebd00, 0x0e394664, 0xed1ff3e0, - 0x4f9cadbb, 0x6bdce3a3, 0x3ca4ff01, 0xe5c3f505, 0xc965a871, 0xe5012f70, - 0x54758c7b, 0xf24d2fcd, 0xe946db50, 0xf09bb249, 0x76e22e7e, 0xdf6d4eab, - 0x45efe119, 0x090903e8, 0x69a5f604, 0x166854f6, 0xff14f142, 0x10f62ce3, - 0xca9233cc, 0x0929bf69, 0xf5616256, 0xc2674ab5, 0x9f71aae7, 0x2e65c53b, - 0xb8226e1c, 0xd2360daf, 0x9d9afd42, 0xdaf3ecd5, 0x66f68244, 0x605263ed, - 0xa367ad0d, 0xf88566d4, 0x2d5ba649, 0x4944ad80, 0xbde78a92, 0x7d339507, - 0x32fd65b4, 0x50afec31, 0x0ff31f65, 0xf5ac4171, 0xfcc38fba, 0xfc00bcf2, - 0xf5d43eca, 0x2e35b80a, 0x75cf6b2b, 0x79fe82c0, 0x3f706ed8, 0xbb8f90ac, - 0xb1353f13, 0xeba102fd, 0xb69dbf71, 0x1bb4668e, 0x15de0f54, 0x953eaf41, - 0x75cf9e08, 0xb572ffd3, 0xf611772d, 0xb9938f83, 0xf4169ac1, 0x2d91c4dd, - 0x5f6bc780, 0xa238bbc7, 0x3784c8ec, 0xde806b3c, 0x8c3f6a6f, 0xa2131878, - 0x33e5c8fa, 0x2a7b8552, 0x943ce19c, 0xfcf95ab7, 0x949bdb8e, 0xd1fd71d2, - 0x3338e5af, 0x6bd357f2, 0xace7bea3, 0xb198b576, 0xc13200d6, 0xba110ed8, - 0xc0b350e9, 0x8221bd1e, 0x4f99df7f, 0xbae942f1, 0xfc0ef417, 0x19818bf3, - 0xcd0d9b80, 0x7e82b1df, 0xa3f1e37c, 0xb11d7e99, 0xa227fabf, 0xf6cac3a7, - 0x0f803b87, 0xf22ffbd5, 0x728423f1, 0xea95cb0e, 0x443c6447, 0xe711bdc3, - 0x81ac5e9a, 0xf0b2330b, 0xf9011c7c, 0x0a234288, 0x3a364cd6, 0x7f9aaf81, - 0xcfec26bd, 0x9eb9e226, 0xded64e55, 0xcbf3591a, 0xefe8165d, 0xfe82f8aa, - 0xf5175b97, 0x97f3a25e, 0x5e30f388, 0x67e70ba9, 0x090a4bde, 0x7e0b7f24, - 0xb9eb6905, 0xc4a57e3a, 0x0757e0c5, 0xfff8d1e8, 0x6d93fb27, 0x6a83cfec, - 0x25ae7f77, 0x51b6df9e, 0x4f7b90bb, 0x05c33a7d, 0x89169c39, 0xd95ebe0b, - 0x51e77e93, 0x2dd706fd, 0x7a0d9f4a, 0xea99b13c, 0x8f5a29b1, 0xde09725d, - 0x6bdae75b, 0xd4677b43, 0x5fbc8beb, 0x7be31b5e, 0x1199e88d, 0x5371f307, - 0x5dc060d7, 0x8b924ab6, 0x41d9b129, 0xb6afad91, 0x91c6eb26, 0x8fddf1e8, - 0x2ff35276, 0xf8d2bf35, 0xe4afd85e, 0xcf1686e3, 0xff148214, 0xc7f7dfb4, - 0x5f01e679, 0xfcd938d7, 0x829a0e13, 0xab03fcbf, 0xcfa00ee7, 0x0710fb46, - 0x42231aeb, 0x125e2c99, 0x4f5be9d2, 0xe83365fa, 0xc248634f, 0xc74fcc71, - 0xcf4261b1, 0x4b8bf4f4, 0xab52f464, 0xc0ca7e02, 0xab1ac25c, 0x7bafb826, - 0x47bb3660, 0xbb0e6066, 0xe3dff1f7, 0x7dcc7ad8, 0xd0dc6c71, 0x4b581fd2, - 0xc97e81ee, 0x739bf112, 0x40dd39be, 0xef0fc42a, 0x0ddf738f, 0xb914b0fc, - 0x4e191fb1, 0xde2812e2, 0x0146a432, 0x552437f6, 0x1b8b02aa, 0x40ee3612, - 0x28cbeb4a, 0xdc61f356, 0x16b6a0ca, 0xcd1920e2, 0x6cf5cfb1, 0x5dbf9388, - 0xea29abbc, 0x3886ca3c, 0x541f6fe6, 0x8b937f68, 0x709479d9, 0x0f9286dc, - 0xbf88edfc, 0xf1db3b0d, 0xf50f5b19, 0x1b3e3227, 0x30205fe7, 0xf3c497e8, - 0x6488543f, 0x91f9c24d, 0x99df04df, 0xb23f382c, 0xd8235711, 0x58e297cf, - 0xe09d755c, 0x9ff90f5a, 0xb8165d48, 0xffc3476f, 0xeadf278f, 0x8e2be892, - 0xc367ceeb, 0xc3ea959c, 0x8eaf20f3, 0xaf87e7c9, 0x0d741ec5, 0x8b737866, - 0x9aeffdba, 0x4eb282dc, 0x8788566e, 0x78ebda44, 0x1df7e705, 0xe60b9c42, - 0x05cb1d43, 0xe160a746, 0x7d2403e7, 0x43db869c, 0x27781c6d, 0xb7e9132e, - 0xbc18ff11, 0xb2e2cc1f, 0xfd1a3d00, 0x86a473e1, 0x73c69e73, 0xe15969a0, - 0xee3a4db8, 0xe0512d93, 0xbe722f8e, 0x97fe86d9, 0xdff4c1d7, 0x60fe8788, - 0x6e732e3c, 0x15abf292, 0xae5fdbe4, 0xdb7b0449, 0x0ee3ceff, 0x0f91af90, - 0xcc7f829d, 0xfadf5841, 0x9f731c83, 0xa5a69688, 0x7f05280d, 0x0d3d2d34, - 0xbd79ed53, 0x07198a5d, 0xeef5cd3c, 0x9eb5e31b, 0xc3f30c58, 0xb39fd0d3, - 0x73de779e, 0x6177baa3, 0x8e3ebc7c, 0xd15ebbf1, 0x8026a8f8, 0x5de7759e, - 0x927eec09, 0x90ff7644, 0x8373c993, 0x492a52cf, 0xd1b9ef91, 0xdc47e91f, - 0x1181e633, 0xad9320d8, 0xbf166b88, 0x5065ced1, 0x97e4c743, 0xb9fae8c8, - 0xec294c6f, 0xcc6d919f, 0x30dc5d2e, 0x254bdb1d, 0x5387580f, 0x312d2ebe, - 0x73ae20b9, 0x1c9fd176, 0x517c1470, 0xe02e6b46, 0x91e888fd, 0xd431e36d, - 0x65b7f38d, 0x88409573, 0x9ea52a42, 0x9726241a, 0xb8eeb819, 0xff7314d0, - 0xe6c6ddb3, 0x4e71cddf, 0x06d2d34c, 0x8d8d9697, 0x39440fcc, 0x7aa47869, - 0xae365e98, 0xc5309cfb, 0x6fb40a47, 0x994ea7d4, 0x40dd6104, 0x9c2987b3, - 0xd63d9aff, 0xf40521f4, 0x4b01d60c, 0xe4d47da8, 0x9abf8439, 0xfc4af18a, - 0xfd5f9a13, 0x8e03e602, 0xded00aeb, 0x8f5ffd51, 0xd98232fa, 0xd3d82b6f, - 0xe7653888, 0xc107f7de, 0xdf87dffa, 0xeb0f10bf, 0xba917f40, 0x9e7ec1e2, - 0x78ddffbc, 0xe1f43738, 0x715e2cfd, 0x351e6197, 0xfaecc6c1, 0x6c92b6a3, - 0xdf02d7e8, 0x227ae77f, 0xb3564970, 0x01e58d75, 0x5c9e70d1, 0x554f2f7f, - 0x9ee1b263, 0x5bd63f1e, 0x32e7efc5, 0xcb92a1ca, 0x4db6f961, 0xed0a864a, - 0x7eb6dc7b, 0xa08f6e70, 0x14d93cbd, 0x8d11f38f, 0xc6db459e, 0xfa773028, - 0xaf99b34b, 0x6ccab77f, 0xc317705c, 0xf387967a, 0xc1e748cd, 0x6fac367d, - 0xfed8cfc9, 0xadb48594, 0x7abed4d5, 0x0b79d99a, 0x7c963f63, 0xa7f616a8, - 0x90f25bc2, 0x7862f380, 0x4e3a7eff, 0x883f5679, 0x7ec65eeb, 0x31cdef1a, - 0xe6d55f9e, 0xfcb8cb53, 0xf50788cb, 0x6b5cea2f, 0x369f5b33, 0x1fceffc6, - 0xff61b2ca, 0x91fe3c6d, 0x79c0264b, 0x86871de8, 0x3eee5c24, 0x1efc33e5, - 0x1a57b826, 0x823e93d2, 0x654db669, 0xbf3464f7, 0xaae02f7d, 0xef1db83a, - 0xf6bafb19, 0x94f9aaa6, 0x6b30f603, 0x91fa8776, 0xa43f01ab, 0x97f9d04c, - 0x282e9bd5, 0xf8cbbe6c, 0x7e7f0770, 0x1b37f407, 0x3fab59f6, 0x7ce54c9a, - 0x317ca547, 0xbf321ef2, 0xa6ee7f4d, 0xfad5fdaf, 0x2b5bf5a9, 0xd1fbe2af, - 0xf869df8c, 0x2c78e6cf, 0x6eba52db, 0x9ad16500, 0xf30627bd, 0x4e7868f3, - 0x1197c347, 0x4948cb3f, 0x8110ba61, 0xb147e693, 0xcb3c9a5f, 0xfef216ea, - 0xbaf8d3fb, 0x8fc41a5e, 0x118dc37a, 0xdb721d1f, 0x2367d060, 0xb87a3a3e, - 0x3627e45f, 0xa99427e6, 0x678842ee, 0x9d763751, 0x394fc233, 0xbc1dd529, - 0x0b6cf40f, 0xf8c479c3, 0xd7b99ccb, 0x57cf1c65, 0xe1fdabc6, 0xdb943d3e, - 0x6017d844, 0x5a7bc3f6, 0xb73eed3b, 0x7c04a86b, 0xb4f4c22f, 0x7435c4af, - 0xd2f97768, 0xc0382e27, 0x411cee8f, 0x11d38e30, 0x77f7a7af, 0xf9e91136, - 0xa543971d, 0x3f8ffad4, 0xd2da8d83, 0xda1dfb8a, 0xa071e4bf, 0xb145cd2f, - 0xfe27f9fa, 0x86f7e11d, 0x4cf5c5dd, 0xe02c979b, 0x99abbb72, 0xda2f67ad, - 0x30f28a58, 0x437ad7ee, 0xd0661670, 0x638d3caa, 0x51bf9014, 0xdf5c4b3e, - 0x51607dc1, 0xf08f2272, 0xdc1e017d, 0x2f5653a7, 0x28c3dc62, 0x93bb7cbf, - 0x6b57a39d, 0x42b71e70, 0x790ebd8a, 0xb5f4dda5, 0xc7ec63fa, 0xed0126c2, - 0x65fe91a4, 0x0dd76a5b, 0xd67fd020, 0x847ee8bf, 0xe25da206, 0x55fad4fd, - 0xff785c46, 0x50fad440, 0x7224f5db, 0xe6f2f53f, 0xbf2fb8c5, 0xb09ff69a, - 0x85c61238, 0x7a35fa34, 0x1428fd8d, 0x8816c8cf, 0x5c16aee3, 0xefa39f60, - 0xeeeb7327, 0xb0d85c3f, 0xafc8207f, 0x66fb625d, 0xce02fddb, 0x203f3b0b, - 0xbd607d6c, 0x3d69eb80, 0xed99afca, 0x8e59ea07, 0xe7dc0a35, 0x8851b657, - 0xf565c729, 0x11a1aef9, 0x60796a76, 0x8ea86b86, 0x1fdc46de, 0x54a1a2b2, - 0x9d807cf7, 0xfdb893c7, 0x48df4dee, 0x38cc624d, 0x9a5fa693, 0x97fa69be, - 0x3cd9576f, 0xcc1c0a47, 0xfebb04c8, 0xa84bce18, 0xcedabe5d, 0xd1e607d7, - 0xb89faa57, 0x581f5ba0, 0xb3e4c792, 0xe7c62c44, 0xca57d93d, 0x1e7d9d07, - 0x7fefd767, 0xd1fdb6f8, 0x85e9a1fa, 0x5ea33fd6, 0xc5aff918, 0x30728cd5, - 0x82e81ff2, 0x7b1bc1f9, 0x0407816d, 0xa74677d0, 0xe915af7f, 0x702b48ec, - 0x3fc839c1, 0xce9407c0, 0x31dbf4ea, 0x9496235f, 0xc75e71da, 0xfae34de7, - 0xe1c83f16, 0xab4ed67e, 0x473b2c7b, 0xb80c9254, 0x36db5298, 0xf8a4e2d3, - 0x2174647c, 0xe53a2bdc, 0x1099b6b1, 0xc8f25efa, 0x5fb84298, 0xb6d6ca7e, - 0xea2e2d77, 0x2d8ed5d7, 0x57e5fb84, 0xf680dd80, 0x10db9607, 0x89e53d57, - 0x9579f2e7, 0x5cce3fbd, 0xcbdd9f32, 0x292bcacc, 0x3c742d8f, 0xfc3c3cab, - 0x959fa0f7, 0x1045c5ad, 0x8884a9b7, 0xaacf1d37, 0x2d908edc, 0x93e78d9b, - 0x6cdb7be8, 0xf076559e, 0xc5ad2eeb, 0xb0f2adf1, 0x0e44fa84, 0x44a8b8b1, - 0xdfa56afb, 0x7ea38dad, 0xdaefe52f, 0xe60b8b24, 0x1fb9f4af, 0x936bb5e6, - 0xf11aaadc, 0x7c1f935c, 0x35ac7407, 0xfdfb75b1, 0x684f0daf, 0xbf78ccbb, - 0xc32647df, 0x67c5a43c, 0x9e58d4c1, 0x7cf138af, 0xc589be44, 0xbfe58c35, - 0x512cecd2, 0xd5170033, 0xaf161487, 0x4fe07fa6, 0x17a61156, 0xeb9d84d5, - 0xf04c3aaa, 0xa1f54b1c, 0x02c73c42, 0xd63ffcfb, 0x735ff0e1, 0x571ba58e, - 0x92054f8c, 0xc08a5930, 0x55bb34f5, 0x9bfb1797, 0x887f4046, 0x7382e718, - 0xa9866218, 0xbfed0766, 0x294d0578, 0x4ba7243f, 0xea5afb84, 0xe1114ea6, - 0x3235a9be, 0x62623fdf, 0xf6b5cce7, 0xb47f389a, 0x64bdb4f4, 0xecfdc807, - 0x36b9ad5b, 0xf3817eb6, 0x6bbfad61, 0x60113704, 0xe08075de, 0x149c80f9, - 0xb3fc02d2, 0xe01e7711, 0x127b3ded, 0x375b37e7, 0x90197fa6, 0x97a6ccba, - 0x57f78a55, 0xfa84591f, 0xdd304ae0, 0x6ff34993, 0x7cb197d9, 0x2642e986, - 0xf6dbf085, 0xc6bf9672, 0xcd086174, 0xce5f6bbf, 0x49c0b0f2, 0xf623b607, - 0x48ff428a, 0x7de38768, 0xc01afb9b, 0xf16264b7, 0x0515e917, 0x7db453d7, - 0x44e96b21, 0x1ef8f00b, 0xa7884dd8, 0xdafc16d4, 0x02eaf106, 0x3dfb0ab7, - 0x837bf336, 0xf1aa69be, 0x7099b455, 0xf02903fe, 0x4fce43ff, 0xc9a42e4d, - 0x8bec0d7d, 0x6bee8d25, 0xb4ed1d60, 0xf606d3dd, 0xad1bec66, 0x377ec053, - 0x5ca7f3bd, 0x0afc9fbc, 0x37d8cf56, 0xf6909ce8, 0x066fece7, 0x8f5c8a6d, - 0xffcf6d3e, 0x62a3be14, 0x5054ff40, 0xaa0ee49d, 0x44dc6b87, 0xbe60b255, - 0x362f9fac, 0xb69f6611, 0x82ce4ad9, 0x10c0c95c, 0xf6455b8e, 0x6bc84e92, - 0x26b49cf6, 0x9b5f69f5, 0x845abd92, 0x23293971, 0xd8117478, 0x7bb1dfff, - 0x1bb7043d, 0x14be73f7, 0xed8cd7be, 0xfec1b10f, 0x177fd010, 0xf2a7f349, - 0x2f8b17f8, 0x88dc9493, 0x07ef3079, 0xec1a7efd, 0x63609f37, 0xbf6807fb, - 0x63abb044, 0x58e98a88, 0x81656788, 0xdf983d28, 0xde8f1a43, 0xdc7feb47, - 0x9649e2ca, 0x0f8ba206, 0x38b3c766, 0x8b074ccb, 0x8dc9c60f, 0x10ff82b7, - 0xc1388e77, 0xa5fce87f, 0x22fee122, 0xae2379c9, 0x11341d8f, 0x3959f7a0, - 0x99f584e0, 0x7524abae, 0xafaee933, 0xab5bcb93, 0xbd4571f7, 0x7372e20a, - 0x7d3fcc1d, 0x7ee09f36, 0x4a53aee8, 0x934dd600, 0x91352c32, 0xf92b9ff1, - 0x0b390f77, 0xfe21e332, 0x408e37bc, 0xc5f613fb, 0xbf0e4099, 0x056396de, - 0x3c04bc3c, 0x32487ca2, 0xfa86ef3b, 0x7a502e92, 0xdb39f133, 0x63a92f27, - 0x277f2812, 0xe15760dd, 0xad67a9be, 0x7ee0378d, 0x784c17d0, 0x8a4beebf, - 0x2ff214ab, 0x609d579d, 0x6ccd9f7f, 0xbcfec38c, 0xbcfec260, 0xf575d714, - 0xc3f74a4a, 0x4a7c5823, 0xec0911b2, 0x502a64b2, 0x73cfa6ef, 0x493cd9e3, - 0xe3cbd3b3, 0x2e3cfe99, 0x200f3c10, 0x7f51f299, 0x9d3afdb4, 0xebf7045d, - 0x2ad59bf4, 0x4ae38e02, 0x4851b8b5, 0xe4cf7884, 0xdb7e8212, 0xe78cbb64, - 0x307f6072, 0xc29b1b9c, 0x0f94efed, 0x813d712a, 0xdc30e04a, 0xe762d97f, - 0x75f168f7, 0x4e39ebc5, 0x226d23ae, 0x5dd791f8, 0x07882e22, 0x8a497f5d, - 0xe74e47e9, 0x10233ef5, 0x97be8129, 0x0095517f, 0xef44f977, 0x2faf4de7, - 0xe0e3053c, 0x39e18b54, 0x8f4889f8, 0x4ff7cf1b, 0x4fee1a77, 0xd6f3e78e, - 0xe47064c1, 0x1d6d313e, 0xf238ba68, 0x8b53f409, 0x65f01714, 0x3efdddbb, - 0x5bfa7bac, 0x38b97265, 0xb63e33e2, 0xa5c46f9f, 0xa1ff5c38, 0x2e03b4f8, - 0xf3afaeae, 0xafbf695b, 0x07eaca1e, 0xb95d821c, 0xc92997f2, 0xf1cde760, - 0xa968decc, 0x97c03b86, 0xcbe18133, 0x3f5bba39, 0xe267c557, 0x01be9a7b, - 0x3d9ea0ee, 0xac7e6072, 0xd78a6575, 0xedd78055, 0xb3f38276, 0xe65ba51f, - 0xed699e82, 0xf86789ec, 0x6aeba637, 0x7587ee57, 0x6c67ff1d, 0xe03698bc, - 0xde391292, 0x3864e87f, 0x3375aaf3, 0xf3fda66f, 0xbf5c65da, 0x8be7e549, - 0x1e92f122, 0x770d1781, 0xef16761d, 0x7533f0d1, 0x3c22bbf7, 0x2119fa9f, - 0x9e124cce, 0x99f86887, 0x9c3867e2, 0x138d8872, 0xddc7e1bd, 0xe6069ce5, - 0x87370a31, 0x280a6e18, 0xb7f7f03e, 0x118fc07a, 0x8af54f37, 0x3cf12f9b, - 0x53bdaafc, 0x186ebb2f, 0x7df7e9f4, 0xb689d31a, 0x8f82fbd8, 0x56ef7e72, - 0x06cc6eea, 0x8993717b, 0x48937f9d, 0xe714adc6, 0x7bb4e3bb, 0x20b26be5, - 0xf6625dbf, 0x19b37b67, 0xbb76cfed, 0xd77183c7, 0xcb9e0b34, 0x0da79226, - 0x06bbf5f6, 0xdfc8d458, 0xc72ef8d1, 0x9a1ca361, 0xeffc0278, 0xf3fc98d7, - 0x1b81ca6e, 0x197a48ec, 0x93b8c393, 0xe21126ca, 0xfdfc8e42, 0xe04faf80, - 0xc3c02d4e, 0x25ef0571, 0xa0ae3eaa, 0xbecdfc5d, 0xbe210bb7, 0x9e1feda9, - 0xc2ede7b0, 0x3ef09182, 0xdc6bd9c3, 0x3c796aae, 0xd276014a, 0xc4fd2f70, - 0xfd2679f0, 0x8025f2bd, 0x72eeec9f, 0x73eb7de3, 0x1d1784e0, 0x736d6e77, - 0x60b3074d, 0x4e7d6fbc, 0x9b1f9d88, 0x1d3dd47d, 0x7dd4654c, 0xb70f1ceb, - 0x715dd691, 0xdffdf462, 0x163e7c74, 0xd7fbf10f, 0xc1c40a43, 0x6b9a951b, - 0x26a27cd8, 0xa68fec0b, 0xf947f877, 0x08e1f8d6, 0xc3ff7ddd, 0x88f3f8f8, - 0x38f7624b, 0x4eb829b5, 0xdf6128f8, 0xeb71f235, 0x39f7ae2b, 0x0f9c5eab, - 0xb96c70f6, 0x576dd71b, 0xfe7c4539, 0x64b21213, 0x125cbc81, 0xca3477ae, - 0x4213d4ea, 0x2a447bf7, 0xe5a76119, 0x8dc5fa7b, 0x70eff685, 0xf00e4c78, - 0x43aea42b, 0x4984ddf0, 0x6ec16339, 0x4dacc7db, 0xa34c7186, 0xb455d29b, - 0x874dded5, 0xc7275746, 0x858e1dc9, 0xf678c726, 0xe0a1d81d, 0x7c0b76b1, - 0x71a0e1af, 0xff2639ef, 0xfc803c08, 0x2c20f1bb, 0x07c6bc80, 0xfcb54f1b, - 0xa10f1f3f, 0x1e9f2081, 0x087100f1, 0x43c2b7c7, 0xc355f016, 0xaed7f503, - 0xfe68fe02, 0xf6c2a35a, 0x0d796a1d, 0x7cf64507, 0x10a5cf7c, 0xf6443fdc, - 0x6d39d959, 0x57ae224f, 0x6d64ecbc, 0x3ed87e74, 0x6498ba98, 0xebf983b2, - 0x8c89efda, 0x57e80909, 0xe106a18e, 0x06e3f40e, 0x71743da2, 0x4176917e, - 0x71377b80, 0xf806796f, 0xd064a197, 0xe2e6318b, 0x877fe010, 0xf8064a6d, - 0xc9b63987, 0x5daf8059, 0x0ebd5623, 0x01aed643, 0x516f2fe5, 0xcd27fdbb, - 0x6af0b5ee, 0x746ff6b5, 0xbd74fb30, 0x020f9d9b, 0x87491dbb, 0x2c41ff66, - 0x9a108740, 0x86cafa63, 0x0db9baf6, 0x41d039ec, 0x205fbaf9, 0xe41fe04d, - 0x5329dc9b, 0x17ebcfc1, 0xcece8092, 0x860c5fbd, 0xf3716538, 0xde8147ab, - 0xd43d6d62, 0x350f5fa5, 0xbf9ad1fa, 0x342bcda3, 0xcf9b487f, 0xe504df82, - 0xd3b9fcd9, 0x26add6cc, 0x6e782c87, 0xeaf3f1f9, 0xbfae6e55, 0x3147ed12, - 0xa42dc7ef, 0xeed2e915, 0xf399b91d, 0x9d10f8a3, 0x39436687, 0x3e513721, - 0x1defc4dc, 0xbfa5c9b9, 0xbc96e157, 0x688ef7d8, 0xbef6f4f5, 0xd6b87c71, - 0x6df46eb0, 0x763e43d3, 0xfa7fc8cf, 0xd2773cd8, 0xc12fd110, 0xce979a80, - 0x327069ee, 0x62521c3e, 0xb9fb578f, 0xb5324efe, 0xe5b9c365, 0x8efe7bfd, - 0x7b2be3e3, 0xf81efefe, 0x494f1389, 0x4eb5f604, 0x012e353a, 0xd2f3e7d7, - 0xab593d70, 0x9369fbd7, 0x88e7b08d, 0x5777ed1f, 0xdc7a520e, 0xc167d00a, - 0x1e67b7f4, 0x77d429ff, 0x2244b8f1, 0x2a144dcf, 0xc710a19e, 0xbfbfe42d, - 0xfe605073, 0x907e5692, 0xf3c5eeff, 0x21b0b71c, 0xc48fbb42, 0x9be7211c, - 0x9a193df8, 0x593a6f5c, 0x8eca4a74, 0xfdfc0f96, 0x5a0be233, 0xf399a15c, - 0x11fcb48f, 0xa77cb7cf, 0xfc096ee9, 0x89a4eff3, 0xeed11dc4, 0xe0ce950c, - 0x2f1ce223, 0x4a7e0c3b, 0xbd3f73cb, 0xde2b8e99, 0x4adc4437, 0xfede6de8, - 0x5be4367a, 0x8ff798c5, 0x9dfbf918, 0xfef1bbe6, 0x2a092191, 0xfb5bd3d2, - 0x38a6ae93, 0x27720d19, 0x65cbcfcc, 0xe51877f7, 0xff9ecafb, 0xd91b6e48, - 0x927bbf33, 0xbf0e51bf, 0xeb80533d, 0xc3c9bd4e, 0xb47ddb88, 0xbfda7e9f, - 0x9fa7ed10, 0xf8af63fa, 0xbdff989c, 0x1af30d2f, 0x9f7bbd5e, 0x4e7f064e, - 0x64f4e9c3, 0xbb899b86, 0xec4c9a7f, 0xf232f2dd, 0xf30773ed, 0xd710e66b, - 0x3fe99bec, 0x78ae0a77, 0xd27e17b4, 0x4ab3fb0a, 0x0e738d38, 0x41ffa217, - 0xe31079f8, 0x1c473638, 0x7bdee789, 0xa19bddfd, 0x5b9832f9, 0xbf0578e3, - 0x36b802c7, 0x6f45538e, 0xb2e049d4, 0x98ab4a15, 0xba7ee31d, 0xce519746, - 0xf6094847, 0x8d3a27a3, 0xabd23038, 0xefdae7f9, 0x4c7e50c0, 0xddf5a24f, - 0xff63e6aa, 0xce61c6a2, 0xdfc69e97, 0x9c95fa9e, 0x1cdee3c0, 0x4e4e17ff, - 0xdbd80b7b, 0xe519be93, 0xecd72c66, 0x90342147, 0xfc1fa983, 0xa9092191, - 0x97850fa8, 0xe3a6e214, 0x3fa8190c, 0xaf8a4eff, 0xe3ddbc40, 0xc27acf64, - 0x1325f55b, 0xe37724f1, 0x663e0e4e, 0x96eddc03, 0x1f106cea, 0xba5ecebd, - 0xda6f5406, 0xf0b305a7, 0x1336879e, 0xf4d99081, 0x102d73e6, 0x251ef047, - 0xa0a03e78, 0xc054ff79, 0x56a5efe9, 0x5e75479c, 0x08b1e424, 0xbcd8333f, - 0x587e06c6, 0x6f9d8530, 0x7448983b, 0x27f790fb, 0x8f06bc30, 0x1dd9bf9f, - 0x2f12fca3, 0x29dc499f, 0xc72e38d9, 0x70a3fc63, 0x3ffb09bd, 0x481d704d, - 0x9e65bf01, 0xce85f380, 0xa40e13bd, 0xee3b7a50, 0x333b444c, 0xdde0f83d, - 0xc6882a4e, 0xcf8b1eff, 0x780a16bb, 0xeaa140cf, 0x59617cc2, 0x98dfee26, - 0x99e48ff0, 0x433e50c5, 0x74cdf9c6, 0x788252b1, 0x2134d9d4, 0x7b8be607, - 0xf85ab684, 0x297f5c1d, 0xfd38876b, 0x7cff30c9, 0x0c7938a7, 0xaa9c76fe, - 0xefe187e5, 0x3cc31203, 0x0bced56d, 0x7cb4cdfb, 0xf7016cd5, 0x66774eef, - 0x7e047f10, 0x7953d70a, 0x6cb8a58e, 0xb8005fee, 0x3fa4599e, 0xc4bb3837, - 0xeb910246, 0xef138216, 0xf7c83b21, 0xfc097769, 0xe7ae7c5e, 0xcfbc7037, - 0xfbac9b99, 0x3f3094ae, 0x6453bbd3, 0xb3e471f7, 0xf4d6a1df, 0x87ae46eb, - 0xf1f9f037, 0x8e864f3c, 0xd288628e, 0x5b3f4088, 0x62e5be47, 0xa5cf0e1b, - 0xe78707e2, 0x1c6ef6d3, 0x8ad79861, 0x17116b95, 0x6f1d6c69, 0x1382ec36, - 0xdfea6ec1, 0x9f4f25bb, 0x97c7a18f, 0x3d9a13b5, 0xc457bd98, 0xf9d9c375, - 0x8902cf94, 0xaebfd3f2, 0x726098bd, 0xd078801d, 0x78dc97ad, 0xbd944e8f, - 0x1be8a0f8, 0x50df8bd9, 0x7aa3cc1d, 0x1f0264fd, 0x41910737, 0x8ba63760, - 0x380a7edb, 0xa6e3a4ea, 0xb48e0639, 0xef9b4771, 0x063d5217, 0x6c3390dc, - 0xa5fa659d, 0xa4efdc34, 0x76c3f7cd, 0xae25fa84, 0x6fd2fe18, 0xf774b212, - 0x4aed847a, 0xe7225f84, 0x64bf7b7e, 0x9547f53a, 0x206fa01c, 0x7b458ff1, - 0x42c97186, 0xf10518d8, 0x1873b4c1, 0x744af1e7, 0xf3e38afe, 0xb02f88d3, - 0xb752427f, 0x15fd187e, 0xd63cce2d, 0x7a53f9a9, 0x8de3849c, 0xa57dd8b3, - 0x810a4e1a, 0xb3ffa09f, 0xf4eb8c44, 0xfdad1b86, 0xa212f0de, 0x564c08f6, - 0xfae1788f, 0xf2f175f7, 0x197c6d17, 0x05f6864a, 0x343e1a27, 0x9bc718bc, - 0x83c434ff, 0xba6f1a7a, 0x0e6f197a, 0xaed1908c, 0x7cd7e6f7, 0xeaf3e4ea, - 0x37a62704, 0x7f1b355c, 0xd82c6897, 0xf937f011, 0x6b8e15b8, 0x1c9c33d5, - 0xc1245b68, 0xec1791fa, 0x1cb76647, 0xfff078b4, 0x81c4c600, 0x008000d5, - 0x00000000, 0x00088b1f, 0x00000000, 0x7cbdff00, 0xd5547c0b, 0x67b7efb9, - 0x332479ef, 0x49926649, 0x1d843c32, 0x09212108, 0x11bc210e, 0x11084937, - 0x88a80ca2, 0x1f01d68f, 0x4d092060, 0x6f53d5ad, 0x52812133, 0xbd583d6c, - 0xf4f47bd6, 0x41ed5837, 0x0108750d, 0x26702783, 0xd0f098a0, 0x7ac0f820, - 0x452968da, 0x5a18921b, 0xf5cf6a0f, 0xf6b7df7c, 0x8326664e, 0x73def7a5, - 0xd62e9f87, 0xf5af6b5e, 0x5ff9efad, 0x4a9b5adf, 0x500a9fc0, 0x982015b3, - 0xe1f95006, 0x06484a86, 0x01203be8, 0x96d40314, 0xfe1b41c9, 0xb1fdb4b5, - 0x0cdd45c7, 0x51df8956, 0xf5c02661, 0x950b7e20, 0x06e6c50e, 0xbc95e658, - 0xd6801672, 0xe1bfde2e, 0x62a82592, 0xf9af7afd, 0xe89b1ee3, 0x5fff35fb, - 0xb800c803, 0x197f7f51, 0x2ffb0ffd, 0x1860a4d3, 0x3b365d5f, 0x978dffba, - 0xa6913fca, 0x62d72c02, 0x3e4fc39e, 0x22f2a793, 0xac24becc, 0x8fb74457, - 0xcfb92673, 0xe32ff1d9, 0x32d7fc61, 0x65f3c5c0, 0xaff7516f, 0xc8ed77e9, - 0x523d48f2, 0xace80166, 0xdb1971b7, 0x7f016e5e, 0x4d2581c8, 0x0065c450, - 0x9d0a0152, 0x581998b8, 0x0d0164bf, 0x136308f9, 0x3ab9f7e0, 0xdf86131d, - 0x07e3883f, 0x8e30dc70, 0x3801c81f, 0xfae4ef54, 0xae1ef56b, 0x2f82935f, - 0x877fe3a4, 0xb8a8b0bf, 0xdfedc59e, 0xdf38fc51, 0x8f0a4be2, 0x93d69b3b, - 0x71830b4f, 0xf73f9eb4, 0x0de3fd16, 0xb6bfdc30, 0xbf8b33fd, 0xf9ebf2f0, - 0xa7e7f35b, 0xcd3f3ca8, 0xcf0c15ab, 0x180144bb, 0x9a5ceb83, 0x635fcd1b, - 0xc6f9589e, 0xfeb96fca, 0x56fcac7e, 0x90c7acc4, 0x32a2f40f, 0xffc38a8d, - 0xa6d0264b, 0x437e5e5f, 0xb3f8b1f2, 0xdb2305bd, 0x72c97e01, 0x974f1e1a, - 0xbe2b7417, 0x19974142, 0xb752baf5, 0x40efd40b, 0xb2b9ca0a, 0x4889c213, - 0x2be7f5d8, 0xf4a8513e, 0x9471f04a, 0x6c7c033e, 0x1e1e5bc8, 0xe425d17f, - 0xbcf0da6b, 0x7764148b, 0x0b1f3d11, 0xa8eb3881, 0xea1471a1, 0x6c39601f, - 0x155a61d9, 0x635c75c2, 0x547d3b81, 0xe0328a26, 0x937db894, 0xf6e3c4d3, - 0x8266c5ff, 0x3e5e01ab, 0x48025998, 0x3cead79f, 0x42011306, 0xbff7e066, - 0xdfb9524e, 0x240824e6, 0x74a0fce0, 0x945ec8db, 0xb45c8012, 0x25b4653b, - 0x364388d8, 0xd91f612b, 0x8157bf61, 0x2fdbb406, 0x050ef78d, 0xc914076e, - 0x4c738fe6, 0x7ef4598d, 0xf61e7bb8, 0xa8a4559b, 0xcb8bb0db, 0xda877eaa, - 0x9d580efb, 0xfeff5ef4, 0x699877ef, 0x1780bf9c, 0x0ed78429, 0xe7da8158, - 0xf241cc3b, 0xe3e48b1f, 0xfdeb09b2, 0xec560003, 0xb8557f3f, 0xd76e5014, - 0x13a37740, 0xc724b9cb, 0x8d7bf238, 0xfece9bd6, 0xe50a31c3, 0xd39740b4, - 0x956fdd02, 0x8fd9901e, 0x41c92694, 0x53f61ac8, 0x5a32ead7, 0x3a256c80, - 0x7ae1b416, 0x4bdafdb1, 0xb4bf5c4a, 0xe1771f48, 0x9321419f, 0x7ad1085c, - 0xf84da8bb, 0x14d012a3, 0x6d4b29c0, 0x97e4ed31, 0xce459e90, 0xc973e7e8, - 0xef5ea277, 0xf84bf18e, 0xf7bcd133, 0x8bbcc53b, 0xf726bfe4, 0xb65ffae0, - 0x43cdef68, 0x9a4e077a, 0x0e7c59e1, 0x6732b1e7, 0xd0da5f24, 0x973983ae, - 0x07fd8bb7, 0xe9153513, 0xc7f49979, 0x9ad1f541, 0xfdf2f53a, 0x940cf6a7, - 0xb9787760, 0x13028579, 0x7b4f1d58, 0x3df98632, 0xff3aaf82, 0x22d9f963, - 0xf91d9341, 0x5bddb0bc, 0x0465ae46, 0x8f913b1f, 0x80c95ef8, 0x295cf3c6, - 0x78fb0d1f, 0x46a25cf9, 0xb9f2fefa, 0xffcd1ad1, 0xfa6be92a, 0x3feffeb0, - 0xfe48983b, 0x2aa8f913, 0x2e0317a8, 0xd659f79b, 0xa1f7a15f, 0x6dc13951, - 0xf5d16f58, 0x81c4e5fc, 0xefc4f9a3, 0x67de4deb, 0xe3651a69, 0xe48515c4, - 0x9c96b737, 0x0d2477c5, 0x7ed107a4, 0x7709d524, 0xfb401960, 0xa40b7d21, - 0x1993eb02, 0x36f34042, 0x9534f06a, 0x29abe60b, 0x1c41efc4, 0xe341dbb3, - 0xe7a429a9, 0x338bd7f0, 0xf923857d, 0x0a8f52de, 0xd6b4f385, 0x1b2534db, - 0x93bd5f60, 0x1ef56deb, 0x57ad5f2e, 0x2c74dcb9, 0x8e20c1f9, 0x3459ab53, - 0x7df86d25, 0x8fb0aa57, 0x8867e805, 0x052005ae, 0x0b73a803, 0x5ef5d61e, - 0x249b8291, 0x27ae1392, 0x97289f82, 0x08dc9ec1, 0x4d2936fe, 0x35b26693, - 0xf28bbcb0, 0x063efc4d, 0x59f3e0ff, 0xdca3fb23, 0x4baaeaa3, 0xbae67e62, - 0x961724b4, 0x52f8743f, 0x6e916ca8, 0xb8017c39, 0x5bf512ee, 0xfe380be5, - 0x7842f0f4, 0x74c3e310, 0x15f10c14, 0xfd13b77f, 0x402c3a33, 0xca80c1f2, - 0xd3a45976, 0x492e7da3, 0x323e70e7, 0xe0c7af9d, 0x30cad67b, 0xe83ed1e9, - 0x17be2349, 0xb4767cdb, 0xc843a428, 0xf66e9355, 0x9cde3848, 0x26578b74, - 0xa6fa26d2, 0x75fe446f, 0xd884e3a4, 0x6323a3bf, 0xa6f68aac, 0x4fbc6f29, - 0x1cd9ad76, 0xcc2b8161, 0x71113dbd, 0x719e133c, 0x9f22bc52, 0xbdf235f6, - 0x01c977f3, 0x73886bf6, 0x9e758fc8, 0x7186f64a, 0xd92e6b9e, 0x7fd256bc, - 0xf5ed117a, 0x54f26260, 0x5dd0cff2, 0xd6b8ebc6, 0x6f91d626, 0xd8bb17f6, - 0x9f0f859f, 0x6dfef7c0, 0xe9fc8010, 0xca1fdd35, 0x9a94f480, 0x907b32f2, - 0xe4d2c3ce, 0xfc9f2a14, 0x9701725d, 0x897b92a7, 0x764d073f, 0xa77de695, - 0x46ce2d5e, 0x72ded17d, 0xd61d0098, 0x0a1cb782, 0xa1ea2795, 0xe5f51b38, - 0x971b7aad, 0x5c9deb27, 0x70f7aa9e, 0x49db1879, 0x76c75e9f, 0xb037b7d2, - 0xd85dea9d, 0x1c31e54e, 0xdba2ca97, 0x96bc7893, 0xb42c92db, 0xd0c9838e, - 0xfa4fcc6c, 0xb70c4e14, 0x3fe01782, 0xab6afb1e, 0x978c2aed, 0x34a17f56, - 0xb3f4f90d, 0xac142aaf, 0xee3c5b1f, 0xbb60bfa1, 0x1fa667f9, 0x9bde90db, - 0x8f5a394e, 0xaa9edd63, 0xfa41d8fc, 0x9d112c79, 0xb9b59923, 0xa63a434b, - 0xcd1c6f93, 0x3660d76c, 0x7af4d3d6, 0xd95d7cc0, 0xa595807c, 0x42e0f93d, - 0xaf597125, 0x577f21b3, 0xa3dffdda, 0xabb025ba, 0xaa2aeca2, 0x7b248863, - 0xb641cc97, 0x7b92b1f7, 0x95bbc605, 0x127fff0e, 0xd17b0dbf, 0x91a43fa4, - 0x49a9987f, 0xbcb372e0, 0xe1a49383, 0x95bf46e7, 0x49ff458e, 0x25debafa, - 0x98cd7db3, 0xc741692f, 0xfa35fb48, 0x96ab38cd, 0x9e66fc91, 0x72a26f2f, - 0xeb8b8559, 0x9ab355be, 0x1ccbfec8, 0x94bf7b97, 0x65d07fdf, 0x512dbd66, - 0x389c5fb0, 0x8e9bf468, 0x7bb8464a, 0xf8312ba0, 0x69f5e92c, 0xd612637f, - 0x8ab27917, 0x0337dd64, 0xb63b5dd7, 0xebe57b51, 0xde576cad, 0xf2e12f24, - 0x6990a899, 0x21d0bed8, 0x2a64c379, 0x4a6a3ff3, 0xe4a776a3, 0xd42db625, - 0xa6289da6, 0xbbd96cf6, 0xd5a7ea90, 0xa7510a32, 0x2ef38594, 0xb9c5bf60, - 0xbe1b5e29, 0xd0fc2a77, 0x85dfd245, 0x04de49b9, 0xf04af3f2, 0x7baa1ae9, - 0x9506dead, 0x6958f1d6, 0x4aa38d32, 0x5bd6135e, 0x1ffd286e, 0x2f894744, - 0xda892405, 0xd7e10a5d, 0xc3f77f27, 0x6bf62732, 0xd9012719, 0xde70a9cf, - 0x85fe889f, 0x026a899d, 0xb38b69f9, 0xb16bde8c, 0x5c4dce48, 0xff5295f7, - 0x7d598e40, 0x7e3dc71e, 0x41e39d9b, 0x8c055be5, 0x36df8e83, 0xe542e386, - 0xa84bf35b, 0x78126e3c, 0xcaadf2bd, 0x41376e0a, 0xe54a9c98, 0xf7e2dfed, - 0xb0fe97b6, 0x1fe38dcc, 0xdf62ef1b, 0x562a7282, 0xf624fc22, 0xbfde8907, - 0x77fb9abd, 0x9d0f9948, 0x0b17fec5, 0x38ac8a52, 0x213bb97f, 0x58c57faa, - 0x497d5457, 0x2562a8f6, 0x16564fc2, 0x6fd54564, 0xb38a9628, 0xe6fbfa23, - 0x57d54427, 0xb38ab994, 0x54dffa23, 0xbeaa2a39, 0xa8aca6f2, 0x1cd342fa, - 0x61ea3fe1, 0xf3b0997e, 0x20d965f9, 0xa9fc898c, 0x037df453, 0x3b26efdb, - 0xa9f812ef, 0x09f885c8, 0x55d652e5, 0xd8b971cc, 0x00affbae, 0x92667b74, - 0x2ebf17ff, 0x83de8f1c, 0x4999fe20, 0x16fc4878, 0x201e2376, 0xdc60a47c, - 0xcca7a08e, 0x2bc71d11, 0xff27cd40, 0x84b9d15b, 0x67b954f1, 0x319a1979, - 0xbdfa31f2, 0x8161f90a, 0x2ee86243, 0xa5c732ea, 0xf46c62b7, 0xabae06fb, - 0x316be9d0, 0x09529bf9, 0x6eb4058b, 0x7ac635c2, 0xb72e3a0c, 0x8ef90a9e, - 0xdfff1432, 0xfd2c575c, 0x7f791b00, 0xa0d74b11, 0x8881c74b, 0x760718a7, - 0xc43e32a6, 0x3e1e3b9f, 0x254f7030, 0xa45737fa, 0xee48737f, 0xf79785e5, - 0x97b8c66f, 0xb8c67bc3, 0x2cd0fbc6, 0xfbc6fcf3, 0x2955cf43, 0xd89df3fe, - 0x73ce293f, 0xf9ff14b7, 0x17fdd173, 0x03a36a28, 0x4828f8ed, 0xfbf100de, - 0x2410aab8, 0x35ad3d2b, 0x43e8b951, 0x747842bf, 0x1340d9f1, 0x837af395, - 0xfeb8adc7, 0x956572eb, 0x1e060df2, 0x8cd75d8a, 0x3a4fb154, 0xabb5497a, - 0x5012ded8, 0x68bfb4ed, 0xd3b55879, 0x8345aa3e, 0x6a2fda0a, 0x691b4d13, - 0x63e5a1bf, 0x549cf589, 0x52f3e7e1, 0xca318e05, 0x5e7f6567, 0xb6d5962a, - 0x8b09479e, 0x60317cd4, 0x94703021, 0x48c15e70, 0x0954779c, 0xa3be683a, - 0xbe1d070f, 0xa57e3f08, 0x29146f38, 0xa7e93a5b, 0x91fa45a4, 0x16825b52, - 0x391637e9, 0xaff5515d, 0xc7d8aa9c, 0xbd45467b, 0x159a9d77, 0x6bf10fd5, - 0x46a0e12e, 0xe42ae40b, 0x5e894d47, 0x7cb177c2, 0xfd7d17fc, 0xe093875e, - 0xaadd9813, 0x97138fec, 0x7f82a5bc, 0xa457cfb1, 0x6fea7d8a, 0x6e583d68, - 0x35f4154f, 0xe2013ec9, 0x3e933710, 0x4f71d6c4, 0xc3c68aba, 0x77a43d91, - 0x22e9bb5e, 0x4ef86f42, 0x29d7d5ea, 0xe9decfa8, 0xc44eefa6, 0x8ba923fa, - 0x699e7d44, 0xffac04cf, 0xd45cb534, 0x374d36af, 0x057e017b, 0xc32baf8b, - 0xe7dbba7a, 0xfb79c54f, 0x12ad8ecd, 0x24c519e2, 0x787b9141, 0x0588fbff, - 0x160a29e3, 0x21734c95, 0xd8ab76ad, 0xa024d72f, 0x25fea3ff, 0xaafc4a9a, - 0xdce43049, 0x1d714193, 0x9134ceee, 0x6ff630bf, 0x87be0b76, 0xfcd8e7ef, - 0xc25f42b5, 0xa5fa2ac9, 0xca2ff7fb, 0x9ed8bd24, 0xe7f5e4ea, 0x21e799ef, - 0x7d74857f, 0x7ffdfa97, 0x3c536ba4, 0x62cc9aba, 0xfc96de9e, 0xf9bb8a52, - 0xd21c51e3, 0xbb70bcb0, 0x4213cfcf, 0xcb8c2ba8, 0xf5848f35, 0x4bc59746, - 0x90fb7d38, 0x6cacaf7c, 0xb213f3d4, 0x9c8de85d, 0x1bb8da62, 0xfaeb9fcb, - 0x3bcd14f2, 0x1819e683, 0x01f51cb7, 0x56e3039c, 0xe93a8a14, 0x0d172c83, - 0xf81ede10, 0xf7979256, 0x7e0763c7, 0xbfac03fb, 0x97be4777, 0x8907f470, - 0x82ab3f82, 0xb07b1a13, 0xbc1acd3e, 0x3e748c2a, 0x967fe694, 0x6b36e0f4, - 0x9beb1270, 0x8d126363, 0xfbc0692f, 0x877f6310, 0x32d538fb, 0x1fee2471, - 0x88d82f39, 0x11ccb7cf, 0x45e6367c, 0xee28da9e, 0x3c5b37bc, 0xf9c0e837, - 0x06ff885b, 0xc074433d, 0x03c72758, 0x45a47910, 0x61e443b2, 0xbce260ff, - 0x1f192d49, 0x359cf7d6, 0xcfaebef1, 0xe68057d8, 0x9b933d58, 0x27399e78, - 0x6c4cc936, 0xd4ccff00, 0xb6af4859, 0xfa7de7ad, 0x7de8ee8c, 0x7f4eacfa, - 0x9bdf03a9, 0x7cfc7ef5, 0xdc7d3cc8, 0x299410d9, 0x89e9cf5e, 0xdf4f37ee, - 0x1f3bcfa7, 0x54cdfcfd, 0x868dbe3d, 0x8e7991d1, 0x33ff7d3a, 0x0a427c78, - 0x3af929e9, 0x516ef919, 0x3a9d9865, 0xeb5a37ec, 0xf90e5fb1, 0x85971b47, - 0x11779da7, 0xa8f56dfd, 0x93f216d0, 0x7b0d2e1e, 0x770d3c2a, 0x7988d4c2, - 0xf837bd74, 0xe0bef838, 0xdc9eb4e3, 0xbac7cf9f, 0x410cd3b9, 0x739d7875, - 0x820d3e75, 0xd3a0f3e0, 0xd99e7cc2, 0x61e9cbf5, 0x98f5647c, 0x5f588d40, - 0x6a089a82, 0xe7b53f84, 0x65d546a6, 0xce3a3e43, 0x9f8fae98, 0x351d1de4, - 0x0c37818e, 0x5a9abdf9, 0x643849de, 0xe31d63ba, 0x13d9948e, 0x3e2dc6a2, - 0x64272b1e, 0x2476e11c, 0xd7089ff2, 0x70a2569f, 0x80772cc6, 0x3fb30038, - 0xc9706254, 0x68ec9976, 0xe7e8d9ee, 0xc8cbb4e6, 0x84fc72ed, 0xef9f3fa9, - 0xe9f9fbfe, 0x99f9a2d2, 0xcfcd1156, 0x3f345f74, 0xf3455733, 0x9a3f946d, - 0x4dd6632f, 0x6abf6a89, 0x7d545163, 0xa37383fc, 0x006167fa, 0xdc4fac8c, - 0xffaa24ba, 0xa22beda4, 0xba9f93ea, 0x5e7faa2d, 0x7b544d70, 0x2baacefe, - 0xa8617f92, 0xb11faa2e, 0xf20df4d7, 0x1fedbabf, 0xeff9e6a2, 0x34a2ff96, - 0xcbaf2f3d, 0x438e997f, 0xc7fa1a5c, 0x4538e1a2, 0x93f215e9, 0xbe37f6ae, - 0xa04bfca0, 0x53bce544, 0x1b780960, 0xd909edb1, 0x1b5f9127, 0xa136ac83, - 0xc13268df, 0x8ff7f23a, 0x879c4c9a, 0x2abcec34, 0xaa8be04d, 0x9ff7e134, - 0xf8a69b46, 0xeccff066, 0x78449ede, 0xa0993643, 0xe29ae29b, 0xc671bf65, - 0x716be101, 0x7034793e, 0x7934ab5e, 0xa899b2f6, 0x329bf287, 0xd1e51fef, - 0x7d71507e, 0x3f1fc78d, 0x8b9ff941, 0xfa4a9b0e, 0x03faa72a, 0x7d70b714, - 0x2461e7a1, 0x3eaf795e, 0x49f6893c, 0x67957d46, 0xbfea66e3, 0x93858eea, - 0xf43aff68, 0x498e8efc, 0x88721165, 0x388adf5c, 0x697be8f8, 0xc4673f22, - 0x6aacdb87, 0x6bca0f63, 0x3ffc2c9a, 0xa5ef85c6, 0x903ffae1, 0x9c0b361e, - 0xbad33015, 0xde724e31, 0xba8085df, 0xe194cb0e, 0x8d7ea478, 0x84c1f54a, - 0x26f9dc68, 0x08fb4411, 0xffc72a5b, 0xbb7f0d5b, 0x36f98f2e, 0x3fee88e8, - 0xc144f778, 0xd7236fcf, 0x2c67df90, 0xdd061d62, 0xfc3f75e7, 0x7b87eea9, - 0xe446ffc9, 0x78edd79b, 0xf5f0893c, 0xa7815c99, 0xe8cfe78d, 0x4d267d72, - 0x3bf5e9e0, 0x79919c13, 0x2b90eac7, 0x36db5eaa, 0x423679ca, 0xeb1bd70f, - 0xad0a4bf0, 0x3f6e8363, 0xc93d9dd5, 0xf1e301b7, 0xdc70d3a7, 0xbf171d9a, - 0x37de8fbd, 0x3888640d, 0x6ef9e01a, 0xd7180f79, 0x4415f2df, 0xd297d2e1, - 0x25e57e44, 0x95cb0ba2, 0xdf513858, 0x776c6256, 0xfcc6f951, 0x7c3bb272, - 0xbeb0961e, 0x84cc13ac, 0xb3fb96d3, 0x53f4c4cc, 0x2f677de0, 0x9a5f6d2e, - 0x04dcf3ca, 0xc5c5333e, 0x9d5dbf77, 0xc686fd44, 0x4319c633, 0x2bd459b9, - 0x419cc057, 0x246b9af9, 0x9f380dc6, 0xeefb9e8d, 0xe299b318, 0xbbdf31af, - 0x0ef0bfe0, 0xf00ac5ea, 0xf8c6b8f2, 0x7e51a900, 0x90cb03f8, 0xbf24ed1c, - 0x98532eba, 0x677539f2, 0xd1fe7cac, 0xebf030df, 0xdfce9007, 0x57b17d55, - 0xbb7fba42, 0xfb57e07a, 0x4fadf9f0, 0xb5c5dfa1, 0x87fddb66, 0xc3ce22d3, - 0x917ddcce, 0xc8f10ced, 0x33924ff3, 0x25eac97a, 0xeaa0f8fb, 0xbc489ca5, - 0x616d227f, 0xb307bd27, 0x479ee2d3, 0xab2beec4, 0x6ed93f48, 0x8699c655, - 0xeba7de5e, 0x930bdd65, 0xd25d79f9, 0xfd447ad0, 0x57f39979, 0xbcac0775, - 0xd7477fbf, 0xbf17aa87, 0x9f991998, 0x54bd416b, 0x7274a873, 0x2a9ce749, - 0xf1cf66f2, 0x6fd4a9c1, 0x21efeca3, 0xe978393d, 0xefaa64e3, 0x5e4bf379, - 0x6574dc0f, 0xf323f7f4, 0x9b5cf922, 0xf92ef034, 0x567dea93, 0xa550f295, - 0xdd8ef2fb, 0x4e9af58e, 0x9eb83bf4, 0x239eae0b, 0x6a7ed34f, 0x979404bf, - 0xb02709aa, 0x9569af73, 0xaac79482, 0x65bddb6a, 0x9aabd60c, 0xba931797, - 0x3f0b26d6, 0x0522d356, 0xa7f03c69, 0x748a7f31, 0x357d28db, 0xb00b1fef, - 0x18a8efbd, 0x787d5cff, 0x4ff459ea, 0x9d9f2d7d, 0xb4363a23, 0x763f3959, - 0x196c292e, 0xd85ef383, 0xea02852d, 0xb9f6ddb0, 0x5d6a3ec4, 0xcd0b31e8, - 0xe5b9eebb, 0xfb0f04d9, 0x90b49df6, 0xfad75c7f, 0xbcfeb958, 0x20fb8458, - 0x9dfac5db, 0xf322931d, 0xfc21f749, 0x81f8c883, 0xf70805f4, 0x09e39082, - 0xdaab3e5d, 0xbb123627, 0x7dedafd0, 0xe6bf625a, 0x3bdf9374, 0xffdfebb8, - 0xffdde695, 0xff98932f, 0x7fc657c5, 0x4f1805f0, 0xc0f3e8d4, 0xda1653f9, - 0x9ab4d61f, 0x173bc5cf, 0x77dbbefa, 0xf0c67b95, 0x571636fe, 0x3880b16f, - 0xc10099b7, 0x381e29e7, 0x91ab2c06, 0x07511f9e, 0x0e7147a4, 0xdd60d658, - 0x71467646, 0xc608e3c2, 0xb9d717db, 0xf70f9e15, 0x9de31b08, 0xedead657, - 0x858f6aa5, 0x9e3570f2, 0x75e90b5e, 0x7113f84d, 0x51f6df5e, 0xbf6716b9, - 0x7e16ed5c, 0xc303d0d3, 0xa7d2ebde, 0x87985db0, 0xc6c860e2, 0x66b85f76, - 0xdd53e280, 0xda0ed47e, 0x03fcb817, 0x6f607744, 0x2beb4a82, 0xccc9f7dd, - 0xfe79889e, 0x5187dba4, 0xa3f979af, 0xe7e266a9, 0x2aa68f9e, 0xfbcfc349, - 0xe2eb1c32, 0xddaa55e5, 0x4e6f4e22, 0xb68f9df6, 0x186f0483, 0xb769ade7, - 0xda07f9f3, 0xe28e96c1, 0x75b83b48, 0xf3d20edd, 0x168bd976, 0xcb6d3501, - 0x3fdc0dfd, 0x91e24bc9, 0x480616db, 0x8fa7650f, 0x8afe13f5, 0xcfd4cdf3, - 0xae52267d, 0xe91b7fdb, 0x4f08e291, 0xd46bcc8a, 0xd17e7a98, 0xb75c9121, - 0xaf9a266b, 0xc96fd808, 0xef0f5f0e, 0x54338a9f, 0x9e1ec7da, 0xa7c40e51, - 0x38901e9f, 0xf54e6b5f, 0xf922cd6f, 0xbfb9951e, 0x010bf0e5, 0x9bee973a, - 0x9f44c506, 0x4e9fdeb1, 0xe38c830b, 0x2f042e6c, 0xff79bb4d, 0xdfd21e2d, - 0x611fa69f, 0x86f7617c, 0x234afc80, 0xe7ca06e2, 0x61420bd8, 0xd721271a, - 0x3ce32c57, 0xf3276e79, 0x7bf562cb, 0x4d941f29, 0x4d875c75, 0xfa23adf1, - 0xb144ee6c, 0x657b1e9f, 0xb23eba79, 0x1bce857f, 0xe92f9cfd, 0xed3d0b33, - 0x5f180abb, 0x399d1df3, 0xbe09a4d4, 0x6b2e76c1, 0x46a63adb, 0xf044dbc6, - 0xdf79e8db, 0x44bc5bfe, 0xd75139bf, 0xb6448cf7, 0xfff9d88b, 0xe499f499, - 0x35b35a6e, 0x7c4cf88b, 0x7bf64753, 0xf067ef5a, 0x2e7f1403, 0xaa922bd9, - 0x8d0fcbc5, 0x4e3c9777, 0xea9cdd72, 0xf01575cb, 0xc300acf1, 0x76b8c49e, - 0x57fffd87, 0xe91fff64, 0xf8a2dcfc, 0x4ddfc46d, 0xf16cdd7a, 0x7fb64ea9, - 0x0ff34a9f, 0xfc746fad, 0xf6e9b5f5, 0xff8265ba, 0x4fb7d71b, 0x15399f5f, - 0x4bc68df5, 0x4e67ee06, 0xff48060e, 0x78a0929a, 0xec3e3e13, 0xdd90f72a, - 0xc5f4396d, 0xa6f7b238, 0x2807af24, 0xd66075af, 0x2dfbb22a, 0xfd636fa3, - 0xbc85f4ff, 0x9e623922, 0xad256913, 0x697ebfe4, 0xcfe2cbac, 0x42fc75a5, - 0x5d6323d7, 0xabdf6ee9, 0x11bc88ee, 0x915f758c, 0x9fbe80fe, 0x17f1eaf3, - 0xff9c73f7, 0x2f4487eb, 0xd6ee279d, 0x3e02b771, 0x783b1bd6, 0x1a55c655, - 0x1f7ba31c, 0xd8261d8d, 0xe4a6cb46, 0x5d39c454, 0x36326cb2, 0xb70d9a7d, - 0x4c6c74e6, 0xebba6fed, 0xbd213496, 0x0b2021fb, 0xaf9d167c, 0xa4d24d00, - 0x6bc53cc8, 0x14f3f155, 0xc91bf8cf, 0x9e56ff2e, 0xb4d84e62, 0xf7f292da, - 0xbace2be7, 0x9f3df7a3, 0x2a2655ba, 0x31f42b94, 0x8a0c4e14, 0xa74c17bc, - 0xf133537d, 0x067bff12, 0x2df6cad7, 0x5cdae5f5, 0xfbee4f68, 0x8b1d6db7, - 0xd62d9776, 0xfa46f54f, 0x3dc0a77b, 0xd78ff943, 0x46ee30a6, 0xfef3273f, - 0x12d3a9df, 0xc462b723, 0x88f7c06b, 0x27f2a352, 0x265f23e1, 0x4aed7e93, - 0xb922df55, 0x7cc9740c, 0xe941244f, 0xd8e2b8b1, 0x03c23ed9, 0xd38bf7e8, - 0xd6c43ec5, 0x6d17ce26, 0x317ec6aa, 0x269ce9c1, 0x79c5d847, 0x579fc8b7, - 0x9c60f91f, 0x05dc3105, 0x02e4f1d3, 0xdec37f1c, 0xc34a6496, 0xf6f33fad, - 0x5392ba4c, 0xe91df8a2, 0xa54ffeb8, 0xc236391d, 0x53835ba9, 0xf0a13f89, - 0x93f21484, 0x94040a85, 0xf1f138a2, 0x14de22a9, 0x87c53cd7, 0x3ed850ff, - 0xe5e12d7d, 0x2f58b0da, 0xa6c661cd, 0x7ae036bc, 0x2a635b5f, 0x6ffb578d, - 0xbf934607, 0xe05d297a, 0x4d2f179a, 0xa02bef11, 0x74acff50, 0x41e7ae97, - 0x5f0be513, 0x7d8cf3d2, 0xcfdc4c97, 0x6db0bf98, 0x3d44eca1, 0x3f6f0828, - 0x76cd79c4, 0x4df24aab, 0x3f040e78, 0x771813da, 0x0c5c1ed6, 0x5dfae714, - 0x7db095e0, 0x6fc0e257, 0x0e061f49, 0x773a5558, 0x876e704d, 0x977f1c54, - 0x0f2b4f7e, 0x31c5b215, 0x2f98dcfc, 0x94e7fda1, 0xe0bd2413, 0x6504dff3, - 0x88e35c3b, 0xd31277e4, 0xd5eba25d, 0x89b0c4ae, 0x260645ce, 0xe9875ee1, - 0x7813a61a, 0x3cce835e, 0x2cbbfbf6, 0xe07ee703, 0xa49cba66, 0xe8207907, - 0x2ac9f684, 0xa704d1f9, 0x7048ebc6, 0x3480deaa, 0xa9daae92, 0x6ed0fc08, - 0x35e7251e, 0x6baed877, 0x36eb8713, 0x135d85b4, 0xff8f3f40, 0x8f3a36d5, - 0x8393aa1f, 0xfefc3d99, 0x6c2fe92d, 0xf9cb1a6b, 0xa28c80bd, 0x949963b6, - 0x7954eb4a, 0xb545e87d, 0x07c122f4, 0xb767afba, 0xfea1f689, 0xaa0ee7a8, - 0xaf3f443b, 0x925f69d5, 0x8742f6c5, 0xf07843d7, 0xee7c297e, 0xded7b45a, - 0x05297cc7, 0xd35eaeb8, 0xb19a07a1, 0x87569fdf, 0xe93ee872, 0x1aff5673, - 0x3e57cfd2, 0x2148f35c, 0x665ddbf9, 0x9df9256f, 0x18cfc09e, 0x5668bf87, - 0x1dd845b7, 0xe0c81d8c, 0xf33180fb, 0xf4d99ed4, 0xfdd7c233, 0xce9525fb, - 0x03cdfbbd, 0x9aee88e3, 0xe85a3ff6, 0xfeed64be, 0x4b4f188f, 0x9a1afe19, - 0x035b766f, 0x039b6bdf, 0x1b5ef9db, 0x9fbe43fa, 0x7f08f218, 0xe73a7832, - 0x390886d9, 0xec2e913c, 0xe3fc060d, 0xebb55e29, 0xf6907af6, 0xedee58dd, - 0x8d2275b8, 0x07cf57bf, 0xc035ef18, 0xf7c431a1, 0x971af04d, 0xa0fef3c6, - 0x967a4152, 0x4eedaeff, 0xa3ffa22d, 0x3dbf02e9, 0x66702e9a, 0x89bf8676, - 0xf1df5de8, 0xd69925b1, 0x8e343679, 0x4521b9f6, 0xf1c6714d, 0x1bf64323, - 0xcab54f63, 0xd7fa8580, 0x2bf6079e, 0x14a6ef28, 0xef4bdf94, 0x8d594db6, - 0x4ca2f7cf, 0xe2ae2852, 0xefe294fe, 0x0c6fb35e, 0xe7786ff5, 0xc7e4a9f3, - 0xe74f481e, 0x607e7ff5, 0x1be278fd, 0x22497fea, 0x606ed9d9, 0x69d866bf, - 0xbe29d901, 0x5ffa405f, 0xf63cf54c, 0xdd2cbbcb, 0xf72ed84b, 0x12ec809a, - 0x01ed9ff5, 0xf849dff5, 0xf689c0ae, 0x664fefc0, 0x6dd5df3b, 0xa32718d2, - 0xf5c49f5f, 0xbea91b92, 0xc9ccbbab, 0x05f74e76, 0xc35ec88a, 0x109c7887, - 0x9d1224c0, 0xfca8be04, 0xe9993b88, 0xe7e5fc36, 0x86e3d06e, 0x75c5e29a, - 0xca3965d8, 0xa4e2223e, 0xf4711ba8, 0x9edb33c9, 0xee817b40, 0x0fdc28d4, - 0xffbf0bef, 0xd5563d5d, 0x59773ebd, 0xeeb3ae33, 0x07edcc84, 0x585e7df5, - 0x7a4393d7, 0x86e2867e, 0xefdc5d3a, 0xb033e7a5, 0x675df74e, 0x094b1b6a, - 0xd8aecd63, 0xb9ca987e, 0x412950be, 0xbaabf9c8, 0x99859b0f, 0xb5fe93e7, - 0x9f2eba1e, 0x9ff5cdee, 0x920242b1, 0xc0e5fad8, 0xb5c45f6f, 0xf910703d, - 0xe14e271f, 0x10ff5872, 0xcf018d6f, 0xc97ef6c8, 0x4bbd23f0, 0x5afb1f48, - 0x123ae1e5, 0x4d8a8352, 0x3fd277f5, 0xbac016dd, 0x9f7b433f, 0x99c7e254, - 0x3f49f7fe, 0x997e4ffb, 0xf7b96641, 0xb7c7d8b4, 0xd27cb45a, 0xb809d69f, - 0xa7a38db5, 0x3c8ba5af, 0xe215b14f, 0xa57e4b9e, 0x009cc1c7, 0xfef1223c, - 0x5106765c, 0x655a17ee, 0xe7f882cd, 0xce56043c, 0xe7a37f23, 0xfd01ef6f, - 0x941fe1a7, 0xf57abdcf, 0x182bc21e, 0x627deeb7, 0x89bfb9c4, 0xbb6d69f4, - 0x6b84ff04, 0xfc4cf75f, 0x5e46097b, 0x1db6beeb, 0x3ca0c647, 0xee8b9eab, - 0x9ee861b7, 0xbdf7887b, 0xefa39a1b, 0xae957c1b, 0x308996e3, 0xea0b7091, - 0xb307fb13, 0xd4569d02, 0xfd3257df, 0x7e5e109f, 0x84f824c9, 0xf2ed957e, - 0x671eb713, 0x1a3f844a, 0x8f7c00b8, 0xe8676f28, 0x99d7dd30, 0xa5e59cdb, - 0xa22ae639, 0x165b6e7d, 0x825019c7, 0x9837dd32, 0x19cbf9ad, 0xd3b4075f, - 0x9d642f74, 0x89c127ee, 0xa3bf287f, 0x8e9d6baf, 0x460beee7, 0x82073dd3, - 0xdacf348d, 0xd1fee29d, 0xbff19dfa, 0xc7d5a813, 0xc9d4f0d9, 0xac0e9423, - 0xabf7450e, 0xdb53f9d5, 0x05bcfd16, 0x9f181278, 0xfccf7d11, 0xfc43ef4a, - 0xc5f02cc9, 0x4638fadb, 0xc219b5fb, 0x7920d67f, 0x410ddf24, 0xb37a4839, - 0x0b240a4e, 0xd58e0b7c, 0x865df748, 0x65f7e8be, 0x73f9d6ef, 0xbc2fae97, - 0xfabf7c2e, 0xe7482919, 0x24ff7780, 0x427bfe9a, 0x1f49cbab, 0x5d6af562, - 0x6df199b3, 0x10b46c15, 0xabd58dbe, 0xd97d21aa, 0x1638a16e, 0x7e354fab, - 0x0b7432e9, 0x4b7ffe5c, 0x98737af7, 0xffeb4cf3, 0x3ca5e4a7, 0xdfadbdd4, - 0x745e50b1, 0xf9087da4, 0xa27a1956, 0x5defebaf, 0x7c86edcf, 0x9614c0a7, - 0x15da456f, 0xf1a283ee, 0x50cb6ef4, 0x7cf3929e, 0x38139d83, 0x51e86e3f, - 0x3ae538ec, 0x14fc5f2e, 0xada17970, 0xa2f84ed4, 0x2bc9b8ff, 0x4c7f9ca9, - 0x4c3e442e, 0xe103203f, 0x89f6fe8d, 0xfe90078f, 0x37c513a2, 0xfa7cbe52, - 0xd83f8c09, 0xf8b3a7be, 0x115fe457, 0x7d91a4e1, 0x4ecaec2f, 0xc783bdfb, - 0x7fddf8e1, 0x4af1e8bc, 0xcbc7c3f2, 0x095c698a, 0x787ee9db, 0x1a871e91, - 0x7bd9178e, 0xfdd1e222, 0xbedf2219, 0x47fbf3c5, 0x78b05f69, 0xf94bd9b7, - 0xff66c58e, 0xafa404a6, 0xdbc905e8, 0xe91db380, 0x8d24f43e, 0x52a4f68b, - 0xeef166be, 0xf6a21def, 0xd3125dda, 0x28bedfdf, 0xc7c5177f, 0xb8a5eca0, - 0x577edfd7, 0x7384bdc1, 0x7053dc0e, 0x477cc457, 0x595f8552, 0xe399957c, - 0xfb68ef71, 0xcf292b2f, 0xff60eda9, 0x1eeafbd0, 0xb0577f0b, 0xae0f024b, - 0xf0e788f3, 0xbd0f89af, 0x085a4efb, 0x9eb697e4, 0xf1c4f4b4, 0x017946cf, - 0xce6171b7, 0xf0b76ebf, 0x7fbdca3d, 0x6b7ad0b0, 0xf388fb9e, 0x126d5569, - 0x67aaa7fb, 0x794aa0e4, 0x58af039e, 0x9a6b3f48, 0x8accc825, 0x3b73376c, - 0xffaa51f9, 0x65f859b1, 0xe8d7ef43, 0xbde86e7a, 0x746b0761, 0xd6d775ff, - 0x17bf3d68, 0xf1a32db4, 0x579a7bfd, 0x7ba03df3, 0x5ff7c7b6, 0x4b5c1f86, - 0x2b8c52fb, 0xee8a9f6b, 0x7e90df77, 0xc7bfd807, 0x3257c9fa, 0x3cd8f3f4, - 0x1efd23c8, 0xaf19af0c, 0x7e7d3da0, 0xc43c6ab2, 0xd71e3bc9, 0x8f1180f1, - 0x8e26c307, 0xfafdb167, 0x285a2eda, 0xfe76d68e, 0x796bf199, 0x872c67fb, - 0xbe0ef6ca, 0xf83d7aaf, 0xaf1f1037, 0x093bb76f, 0x08f65747, 0x6ed25fbb, - 0x6a25060d, 0x7c91350f, 0xef8a0ffb, 0x4aaf023b, 0xf740a38c, 0x7e756b7f, - 0xb7f9d5ae, 0x6367f716, 0xbe8adee8, 0x772fbeff, 0xe2ba11c7, 0xdf3fa351, - 0x993875d0, 0x8404b8f8, 0x12125a7f, 0x8790c9fe, 0xc6465f11, 0x936f81d1, - 0x5bb7d73c, 0x52f8bef9, 0x6d2d3fdd, 0xc593df16, 0x51fe8bfa, 0xddff9176, - 0x8d8de82b, 0xd1ad35a7, 0xd232bbfd, 0xea0fdfd9, 0xc313f878, 0xa8f2e8df, - 0xe53b001c, 0xb2a897e7, 0x756fc837, 0xe77f342b, 0x63cf8954, 0x2989d53b, - 0x194beef1, 0xce3a9be5, 0x28cbea37, 0x43fd864f, 0xc88eedce, 0x998dfc7d, - 0xcd54af02, 0xcf240391, 0xb2cf7d88, 0xfbb8aca2, 0xba44c81e, 0xd77b18df, - 0xee45a64f, 0x391db47b, 0xf23f67a4, 0xf7495e3c, 0x859b6a8c, 0x8d9be87f, - 0x8e10a6e3, 0xb5c5c607, 0xed20d6cd, 0x4f516a4f, 0xd2307bf8, 0x76bfb20f, - 0x07e91169, 0x991c1bee, 0x3a72cf48, 0x2ff5c4aa, 0x8e38c36f, 0xfb2f2fc3, - 0x2baaf58c, 0xf91bac5b, 0x1f6f1996, 0x6a1fec61, 0x6a9c092e, 0x7a51af3c, - 0xd3511f78, 0xb749ee2e, 0x5c62fa1e, 0x7fdbd216, 0xadc63fe0, 0xa64172c6, - 0x25adbf88, 0xbee98fa1, 0x6cbbe7cf, 0x90e8f171, 0xd89a97bf, 0x3dcc6a0e, - 0xf6578c19, 0x859c2e23, 0x4fedf37e, 0x7ad1df79, 0xca4ee128, 0xf1adf5c7, - 0x837e778f, 0x13601a9c, 0xd04ddae3, 0x9ee125c4, 0xd6b81c48, 0xdd0fee29, - 0xaa49c7ab, 0x7d7a8c3f, 0x505df62f, 0x03eecf14, 0x2349e65b, 0x1bf0dded, - 0xafbebad5, 0x85b1d82f, 0xf163e08e, 0x476eb551, 0x2e39fc88, 0x1ba2e2c6, - 0xb4f5a333, 0xc644ede1, 0xb25dfdb9, 0xc8c47293, 0x268c5fd7, 0x7ef887dc, - 0xeb3c9c42, 0xf65ebaa7, 0x0dbee7ea, 0x9be665b3, 0x0d288e69, 0x63fc851c, - 0xe93fe97d, 0xcb1c5208, 0x04caf83f, 0x9dfaff92, 0x2445e7d1, 0xdfdf3f3f, - 0xaafcb20a, 0x433e7643, 0x3a5fda32, 0xd214caf8, 0xbfb786b3, 0xf97211cc, - 0xbee2c722, 0x29467d3c, 0x6bff6249, 0x77fec492, 0x4c93d2af, 0xfddaaefb, - 0xfef22fb2, 0xbbe721bc, 0x4501fd75, 0x65d7f3ec, 0x686f5caa, 0x3a617a17, - 0x7f9c4a20, 0x98f3c8a5, 0xed11fe79, 0xdf2fa825, 0xe880b710, 0x9ad7d942, - 0x6aef5807, 0x9e989a4f, 0x198393da, 0x05ef11d9, 0xf24cdc68, 0x801b0d7b, - 0xc81d88fd, 0xefa52ebf, 0xf4beb10f, 0x59c604fd, 0x523c2647, 0x64adce29, - 0xc0f5bf20, 0x239355db, 0x3d05fffd, 0xc1f103ee, 0x09e72843, 0x87cebf31, - 0xcf42b04d, 0xae3d0813, 0xee2c71d2, 0x8ec89aaf, 0x5757f763, 0x0e1b938a, - 0xc7f28158, 0xf9581fb5, 0x07e7d03e, 0x1dfef2d6, 0x9327f92e, 0xffbf019f, - 0x381f2a6a, 0x3d3276b8, 0x7de0fcff, 0x53de7357, 0xaf9514da, 0x1e7d1008, - 0x797f51c2, 0x97c276f7, 0x90e30a5d, 0xefd3aea2, 0x9eeaf9d2, 0x9b7f3356, - 0xc677bd59, 0xc22481e3, 0xe94b454f, 0x9d3d9dbb, 0xe21feb0a, 0xd947032a, - 0x289d4719, 0xe3851c66, 0x165c82f8, 0x71a4ab1f, 0x5314944f, 0xc9db0937, - 0x1c274d9f, 0x55c618e5, 0x9cff3d06, 0xdfd9f829, 0x13f9c091, 0x3d082609, - 0xba28ec83, 0xcebeb437, 0x9b436438, 0x86bdf51c, 0x4ceedef1, 0xd7b0ae71, - 0xa490b3d0, 0x16ed1eb1, 0x3db686e5, 0xf58eb419, 0x49eb10e6, 0xb459b343, - 0xd02512ef, 0xfe0ccdf9, 0xfc4038d8, 0x508f4639, 0xc12c4b2e, 0x77db84b1, - 0xea079d0f, 0xe28239f7, 0xe7635d5e, 0x686efe44, 0x3b8f73b0, 0x4e39fc5e, - 0xda4833e7, 0xcfb12cd1, 0xf3af6d89, 0xd1c67c88, 0x1e2fc233, 0x1c9fe85d, - 0xa0063fcf, 0x25fbec44, 0xe6ad7e5d, 0x86e7788a, 0xdf223d1b, 0xe06c73b4, - 0xef71e928, 0x373e04ee, 0xfc8975ec, 0x974b696c, 0xac9fdf42, 0x5066956f, - 0xfb9f5a3c, 0x829f7f1e, 0x83f662f5, 0x6e7cfde1, 0xbbbcdd5a, 0xc7438b5c, - 0x1f111eb5, 0x01dfe897, 0xbd57d08f, 0xd37814fd, 0x23da7df5, 0xaa735e74, - 0xdf14ecd2, 0x4aef8999, 0xf9fdd06f, 0x199bd78d, 0xd5029d37, 0xc43fce2c, - 0xdd32c539, 0xfba0df2f, 0x3bdf11f9, 0xe99b033f, 0x7bf6229c, 0xdfafc367, - 0x02bf8fac, 0xf6371e34, 0x759bf5bb, 0x2fb3783c, 0x4ca5f9fa, 0x40e6071d, - 0x10f3f90e, 0x1fbe17c6, 0x71c09791, 0xa4e1697a, 0xbe8338b8, 0xeff55703, - 0xe434a9c0, 0x1ef790de, 0x1da3bfc7, 0xdfcd7e67, 0x80499c13, 0xc5ce7109, - 0xe19fe386, 0xf2126e3f, 0xaa2dcfd6, 0x4346829d, 0x077017ee, 0x331f9916, - 0xe7463ee4, 0x3df1ffff, 0x22505ca0, 0xcacf25f3, 0x3a1e31fe, 0x32f5b09f, - 0x7015c6fe, 0x8d75c41c, 0xce35d7d3, 0x2edf111a, 0x571d5a8c, 0x97d7877f, - 0xc471101a, 0x9e4765cd, 0x75627195, 0xfbefe248, 0x5f62c3aa, 0xf6265d5b, - 0x02ad39b5, 0x49bcaea7, 0xbb126a0a, 0x9f44d3c3, 0x6ccb3fa1, 0x7a180f02, - 0x5d2fc432, 0xf09da87f, 0x3e3a0dc1, 0xc9a3d588, 0xf94e5dd0, 0xc9345be6, - 0x472af74b, 0x6abf3f7c, 0xeee4ebda, 0xa83fa72f, 0x22effc6f, 0xf7d1eac4, - 0x0f12fe3d, 0x07bad3e5, 0xb8e21657, 0x38fef347, 0xe6a6f48e, 0x2df37632, - 0x3b13888f, 0x7ca3811d, 0x3f45a4df, 0x6bc96fef, 0x747e21eb, 0x5ec7e302, - 0x3a96f757, 0xbcf9ab81, 0xc09c3abf, 0xb75643df, 0xb0bbf9db, 0xc486d6ea, - 0xdb7fe429, 0xeb1daf65, 0xcb27ad95, 0xc5959f88, 0xad4a3ee2, 0xb38bdc5d, - 0x10b7fdb9, 0x3b7bd77d, 0x2df9cfa2, 0xfba8bf3d, 0xf58f3d06, 0xa3091b6b, - 0xf9f7ffa5, 0x5f3a8d9b, 0x662ebaea, 0xfea9c14c, 0x26afe690, 0xfd7fec7d, - 0xd71d0b45, 0xa5794ed5, 0x6d88ae9c, 0xefdca8f4, 0x268ee6fa, 0xf41af34a, - 0xf93a6477, 0x707351f9, 0x82d2e32c, 0xd30fbb2b, 0xa98dffb0, 0x3afaa714, - 0x225aa6ba, 0x0eb7bbf4, 0xf91c73fd, 0xb7498035, 0x494b855b, 0x25e3a15a, - 0x07b5c761, 0x3e50670e, 0xb7ec97a2, 0x9277ca80, 0xdeacb1b3, 0x12792a7d, - 0xa2bd96e1, 0xed19c21c, 0xa503f732, 0xa4e6e727, 0x3336fa48, 0x6242177d, - 0x9c9e801c, 0xdb230b1b, 0xdb5fff1b, 0x27a4d3ff, 0x289eb6d5, 0x84f837fb, - 0x3efe7cbb, 0xcad07037, 0xbce808f7, 0xc72115c6, 0x347f7457, 0x644b370b, - 0x7ce873a7, 0x3b41227a, 0xbaa0ee05, 0x95256102, 0xb2c38bce, 0x96377fb8, - 0x7d4cf7fd, 0xb84a59fe, 0xcee9ee83, 0xe737cfd1, 0x5bf73742, 0x6a5c0300, - 0x8befe4e0, 0xe5cbc04b, 0x29785b6c, 0x5082f1c1, 0x099fbf88, 0x73ae2867, - 0xe63bfd36, 0xe61ef238, 0x0ce7029b, 0x0e74c87e, 0xc51bee26, 0xd75ba7ae, - 0xf09a59c7, 0xe81d043b, 0x086cee7e, 0x35fbb9f1, 0xbf9fa3d0, 0x3cc75fc7, - 0xb9d1f7dc, 0x3b6835db, 0x208fcc89, 0xeb4f9ff7, 0xa7ade391, 0x198b2967, - 0x9f449cca, 0x7d30ce14, 0x75f2bf6d, 0x4d6dd3f4, 0x35df57ca, 0xe283f7d0, - 0x6f4b73e1, 0xd3ef1bfb, 0xd349627d, 0x97b1bef8, 0x7da6c7be, 0x1de9584e, - 0x001363f2, 0xe6b3ddfe, 0xc66f6437, 0x07e01af7, 0xfb11e7be, 0xf72d06bd, - 0x3df0c67c, 0xedfee335, 0x950ae0ce, 0x72ac6fee, 0xaddff8db, 0x9b8db229, - 0x87ca794e, 0x21bffcd2, 0x6a40fabd, 0x2883c49e, 0x638c19c1, 0x83b2bd75, - 0x2fd69b36, 0x22f7c669, 0xf432fac0, 0x006401ef, 0xb763b77f, 0x1e69ef8a, - 0xa5b43d41, 0x74abf6b2, 0x2e1e1a0f, 0x6f2f0955, 0xf4bcd971, 0xe895ae5d, - 0xdbd30fb5, 0x2ff71368, 0xb16bfb8c, 0x19b46c7c, 0x8daf4a79, 0x77cc7671, - 0xfcda773e, 0xbfe89bff, 0x9324a93f, 0xcbfe6070, 0x3f7c3df3, 0x7758c129, - 0xc3eb8d89, 0x37191af7, 0x6a7dd136, 0x1d31aba4, 0xe1e21ef8, 0xba149ca4, - 0x25d8d51f, 0xa63753ee, 0x9b7fd807, 0xf3fb12fd, 0x4ed2cec6, 0x0e83078a, - 0x6eabdf0b, 0xaa34f974, 0x4421d207, 0x3ef89ffe, 0x69bbe0df, 0xfd21ef98, - 0xed91505e, 0xde5157d7, 0x4a1b9a7f, 0x6169bde9, 0xc0f1126d, 0xe5061ef8, - 0x4e9519e0, 0x7befa3cf, 0xfbe4e281, 0x501c8617, 0x9d995831, 0xb90d7cba, - 0xf8ef8d38, 0x3bea2535, 0x8f5e437e, 0x98b90a24, 0x44cc26e9, 0x71a5577e, - 0xf061e563, 0x8f00bffd, 0x30b1ae40, 0x0030b1ae -}; - -static const u32 xsem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0x243bff00, 0xa3f0c0c3, 0x4aef811e, 0xf1303031, - 0x12d18aa2, 0x6064e3ef, 0x6062e010, 0xfbe20530, 0x330c0c3c, 0x204cf480, - 0x6066e516, 0x1ae20310, 0xc40dde20, 0x19f8807b, 0x1039fc50, 0x1be200ef, - 0xbefd103c, 0xfe0c0c4c, 0xc4081c40, 0x95fc40c1, 0x1be18181, 0x73f6f103, - 0x4c30330a, 0x2ff04715, 0x249fd903, 0xc1ffe7e9, 0xe90c4386, 0xa071df6b, - 0x10acf37d, 0x7b20467c, 0x9aaa15be, 0xcdf85605, 0xbf268858, 0x18bf8d08, - 0x0372fe8f, 0x4d5afe54, 0x81b5b334, 0xcd4909e9, 0x6efc4d3a, 0x40aac741, - 0x3101a9ff, 0x5ff1ad00, 0x000368ca, 0x00000000 -}; - -static const u32 xsem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd5947809, 0xe77df0d5, 0x9926665d, - 0x6c81bc99, 0x44d84eac, 0x4242740b, 0x61db101a, 0x8311688b, 0x9817054b, - 0x264f6408, 0xdac7f520, 0x0040cfef, 0x8b435151, 0x03b45a35, 0x341b0504, - 0x024180d8, 0x2d82e00e, 0x5d6ad8d5, 0xc8a0d2da, 0x1b80931a, 0xcefc5dfe, - 0xc9bef739, 0x82264efb, 0xf5ffffb5, 0xf8f8fefb, 0xf77bee5c, 0xce73ddb3, - 0xe28ef73d, 0x8b94c718, 0xff12fb18, 0xdd98c7be, 0xd71b18c6, 0x2356329d, - 0xcf2d4ad2, 0x03d058cd, 0xac62ccff, 0x9785addc, 0x653633a7, 0x5ef91a87, - 0x4837e412, 0x6de43b61, 0xde549d7b, 0x23e79ebe, 0xa0cfcd6e, 0xc83aa3fc, - 0xdeded04b, 0x5065c0f2, 0x6643b9de, 0x91dbb11b, 0xc2963671, 0xe30731d8, - 0xcf90597f, 0xc9c0ac66, 0xf61be5b3, 0x45f6c5cd, 0x84e6764d, 0x1577cafe, - 0xf20cbcce, 0x86550785, 0x2f37ca55, 0xbe43fad3, 0x60352c38, 0x9f3263be, - 0x1ca7685f, 0x3bf50cde, 0x37292d3c, 0x553b18b8, 0x8d5e60e5, 0x4b776ab1, - 0x18a3f5ca, 0xcf6f092b, 0xf52576c5, 0x3a970f92, 0x97e6c765, 0xb6bae1fb, - 0x97bb3e4a, 0xf12dd2b1, 0xcf923bcc, 0xfff84be1, 0xf91ca358, 0x862f941e, - 0xb7e83275, 0x32e4d590, 0xab5fc719, 0xf0dddd79, 0xd3a5553b, 0x7cbe4638, - 0xed038c2b, 0x7c969e2a, 0x1b0ac4b8, 0xf8c0340b, 0xb39cbbed, 0x7d70b937, - 0x6e11b4cb, 0x1addd75c, 0xe70c2bd6, 0x717a74ef, 0x5cb41b7e, 0xbf592f28, - 0xd5182b41, 0x96e95fdd, 0xd579d6be, 0x980d4d0e, 0x53d3a3ca, 0x47798c55, - 0x184be774, 0xbf4037f3, 0xb36b094c, 0xff7f7746, 0x96322580, 0xcccbfd8c, - 0x1feee8eb, 0x43df4920, 0x013fc16f, 0x6e3da15e, 0xb781ab82, 0xdbfc3ac5, - 0xb3b78ddb, 0xd2a3c0ba, 0xdfee6d99, 0x3c401f48, 0x106a7cc0, 0x11ae904e, - 0x644cf3f3, 0xdfe81493, 0xc4ba67e3, 0x918f5f7a, 0x9f2ca8d6, 0x420b58c1, - 0x78cafda3, 0x116c6bc8, 0x93f631f3, 0xa9fed915, 0x059fbf90, 0x57bce2e6, - 0xc4228148, 0x690d6313, 0x24abbf48, 0xffd71b36, 0x94349c03, 0xf407eaaf, - 0x99af7009, 0x9649bd96, 0x3093dcc4, 0xbdc4f05f, 0x214fd4e9, 0x3f42a3f5, - 0x8fdfcf43, 0xe9639b9e, 0x322dcf47, 0x7ea4a9fa, 0x4fd6179c, 0xeb04ee4d, - 0x8c4b727c, 0x7ea4ee7e, 0x2eb617dc, 0xd6898afd, 0x46515cf9, 0xf54e24fd, - 0x97d400b1, 0x2d607a0d, 0x5dca197e, 0xef6389f5, 0x98ba6665, 0xdff912bc, - 0xa6625c0d, 0x389c848b, 0xfa261d0b, 0xd0f258fb, 0x5bec7e93, 0x44830f22, - 0x5f1a3512, 0x5c91afeb, 0x41dfd498, 0xbbfa3bf9, 0x31dc2e48, 0x0eb17021, - 0x59b1c0f3, 0x816bc83f, 0xe831eb6f, 0xb129e61a, 0x36bd4c34, 0xefcba34c, - 0x261c3956, 0x88dbf80f, 0x683ed023, 0x08911ceb, 0xa4d2f5f9, 0x365c205f, - 0x27c11b33, 0x5895664e, 0x48cece2f, 0x9e9ddd3e, 0x826429bd, 0x8041ead3, - 0xdfbba97f, 0x0d206ad5, 0xbb2b6be9, 0xb6f48421, 0xa7ac106a, 0x854f633f, - 0x14848fae, 0x20a83f68, 0xd769e10d, 0xe3cdbf80, 0x28fe306b, 0x1c19ff1a, - 0x3f8e0777, 0xf6f8e7ae, 0xf1963921, 0x2c8b831d, 0x18343be3, 0x177de81f, - 0x0f8c55bb, 0xd8c09bf0, 0x685ba1f3, 0x22e0fb7c, 0x8d6eff1a, 0x8fc65915, - 0x05ff1aeb, 0xdea5f71c, 0x82643fd6, 0x4b83fd75, 0xf8d7ebac, 0x0b655ffa, - 0xb471f8c5, 0x16875ffe, 0x2e0ff5f0, 0xf3b7ebe1, 0xf7c6bb7e, 0x75ffc174, - 0xdeadf71c, 0xa2743fd6, 0x9517fd75, 0xe76fd759, 0xcacbbfe3, 0x1a2ef8c5, - 0x1950bdff, 0x6545ff5f, 0x0f66be34, 0xb48e90f8, 0x61957101, 0x040d9f18, - 0x19254886, 0x6474a7e5, 0xfda0c61f, 0xe084363a, 0xa71c4770, 0x80e2cfbb, - 0xf2dd5cde, 0xa381858e, 0x08559e40, 0x9fad2f9a, 0xa59ca1a4, 0x0b7b9072, - 0x341754c5, 0xb0dfb4c9, 0x70f0f675, 0x937b6f98, 0x82fcc21c, 0x65879775, - 0xbcd8efda, 0xb0a76c3c, 0xf0ff7e08, 0xcd1bd1a1, 0x174e8aeb, 0x5ac7a8d6, - 0xe7c47c2d, 0x46cc9a13, 0xa6fcc256, 0xeb8c1121, 0x39031fce, 0xbe7e40ca, - 0xd314720f, 0x078c2ae3, 0x9c828fdf, 0x6f999a65, 0x3c7df196, 0x991cdec4, - 0xff827282, 0xbc38531d, 0xc2912d8f, 0xd6cfff08, 0x3e50d22e, 0x0789ac2d, - 0x23cf77a0, 0xb9d4f028, 0x28de1ecb, 0x08bd3c11, 0x15891b9f, 0xa033fb19, - 0xb6801fb5, 0xa5afb6b0, 0xbc2c2ddd, 0xcfea0d32, 0x483f935f, 0x3cdff587, - 0xc6563edb, 0x07f983fd, 0xd98f88d8, 0x630e5b00, 0xaad71bb3, 0xe3732003, - 0x56fdf56c, 0x0139fb53, 0x22e6fe6b, 0x0d5dbe6b, 0x37d436ab, 0x01b6258a, - 0xd2b5bdfa, 0x938c6e5a, 0x78e1f528, 0x20fde315, 0x56f7cf85, 0x67e2c74c, - 0x573af09d, 0xf98d6de7, 0x5952ef04, 0xd6cbf684, 0x4ff84664, 0x9d017aa6, - 0xbe7a3baf, 0x3f875573, 0xf733e60f, 0x19e0994e, 0xbdd6ff3d, 0x18db7ef1, - 0x563f6b48, 0xd7a30491, 0x79ff3d13, 0xa3d7a34b, 0x1f961e93, 0xe9cefe8a, - 0x829e9a24, 0x1efa934d, 0x6f2bd535, 0x51efb2b8, 0x6e957d13, 0x17c96599, - 0xea58e787, 0x5be6d617, 0x14d617ca, 0xafe7ca5b, 0xe7c9645e, 0xd4b4ee87, - 0x9974b79f, 0xcad6fca5, 0x37e52c7b, 0xe4b5ad17, 0xb11e04e7, 0xf671bfd4, - 0x6db94b06, 0x20d725ef, 0x25bf551f, 0x3e37dc33, 0x007b1d75, 0x5d4fc1f5, - 0x71f10f8a, 0xf88d2aa2, 0x979554e0, 0x4ca6f6d2, 0xc1cb8047, 0x16715402, - 0xad086b2e, 0x9972889e, 0x5e2cfc91, 0x1a1433b6, 0xe4adda08, 0xb5c9f825, - 0x09008b1a, 0x174fac4b, 0xa6ca771d, 0x94f3d6f2, 0x67a302d7, 0x5b972cf6, - 0x6e0f7f63, 0xe508bfcc, 0x00f26f4e, 0x3ee006fe, 0xf7f621d7, 0x8932f2e8, - 0x33bf99e5, 0xfcf89cb6, 0x65b3909c, 0x6507971a, 0xcc9bf6cf, 0x8c8f983c, - 0xf1aafca8, 0x28a8001a, 0x4f3b5127, 0x2e007a46, 0x50cbd0b0, 0xedb77f0b, - 0x155e6993, 0xa3c61328, 0x235bc9c8, 0x1c899ca1, 0x68dd7c18, 0x7eff879c, - 0x29aef909, 0xb6f5f699, 0x8f7de9aa, 0x3c9f882a, 0xcd544f4a, 0x5558f4a6, - 0x55a3d280, 0x5fbe9445, 0x6b694955, 0x0f4a52d5, 0xfd288557, 0x4a6ad553, - 0xa1aaabdf, 0x5aaa9df4, 0x1550ff4a, 0xcabdb4a6, 0x0fc1a94f, 0x4937f25d, - 0xaec2abe8, 0xf2879d80, 0x565ac567, 0xe216dd40, 0xf21a5f73, 0x67d759f9, - 0x3f1f5023, 0xa19d8efb, 0xbc1bdfbe, 0x77ade9a2, 0x5f49fa3c, 0xfe030829, - 0x3b967b33, 0x9c9e38e3, 0x819d3636, 0xf867ba3c, 0x46dbbe13, 0x92415e51, - 0x37c90d81, 0xdfa31dcb, 0x75f08c61, 0x7f313c3e, 0x016b98e7, 0xfd1ec71f, - 0x7bf6366b, 0x717fec4e, 0x87da6407, 0x0f936459, 0x1b8265f1, 0x3b9d6bed, - 0x0f3fbc84, 0x82ea3efc, 0x0660cb5f, 0x274904e9, 0x68db3bfa, 0xb1c20a67, - 0xc40c3e39, 0xdc1ececf, 0x5c7e41e4, 0x8fd3669c, 0x918380c6, 0xeba43796, - 0xd3fef32e, 0xad9fcd64, 0x9037a691, 0x5c26f63c, 0x4ae91a3f, 0x430e8fd7, - 0x6a51a7fc, 0x4d38b3f4, 0xbf028fd3, 0x3432da9e, 0x61dfef81, 0x27d60fbe, - 0x5d82bd12, 0xd5fff548, 0x1fade9f3, 0x358c3e63, 0x281c0fb2, 0xe86ca00f, - 0x1e9dedf9, 0xd13e5778, 0xcd5f10f2, 0x2fa867ea, 0x5fffc1c4, 0x157ec10e, - 0x06fd1bca, 0xfd90e41b, 0xdebdf8db, 0xf3b41e32, 0xb637361a, 0x156e9deb, - 0x2ba0cc76, 0x1a1a5790, 0x3a2764cb, 0x92beeb75, 0x9b07c968, 0x7d96e9fa, - 0xfc01ff06, 0x4152820f, 0x541329ba, 0x56b8a1d4, 0x23bf304b, 0x2f013f28, - 0x2bd78941, 0x016ab477, 0x0b63912f, 0xe5b719ea, 0xbde77418, 0xef208ff1, - 0x6546fe4f, 0xdff962f7, 0xae505660, 0xf720c51a, 0x2f9f906c, 0x9635b772, - 0x77b940ce, 0xf9f7c6d2, 0x83cf2c05, 0xab114f46, 0xe73d46c9, 0x8e9b6623, - 0xfb11fff4, 0x64d3279d, 0x1a6cf86f, 0x6afe73ad, 0xfa0b3eeb, 0x585f2599, - 0xb017cd6b, 0xde90536b, 0x2ca9d60b, 0x5a5f212c, 0x9d36bdcb, 0x95642dfa, - 0x41dec8ab, 0xbdc6057b, 0x00ca674d, 0x73f95f98, 0x43e7658f, 0xae363bfe, - 0x7bf61ba7, 0xff3e1f71, 0xe6b0a492, 0x1a0ff287, 0x19707f33, 0x55e1f6c3, - 0x6e42a728, 0x7accdbe6, 0xceebefe2, 0xc6be7a3f, 0x8fc3d27e, 0x6f21e620, - 0x18e1fc91, 0x9b34da76, 0x10adf424, 0xbae037a5, 0xbe6b7a4d, 0x2f918380, - 0x19dfca8f, 0xe9a7ff95, 0xe859892d, 0xc81488ed, 0xfa7325b7, 0x52417d42, - 0x37c0b53a, 0x47ad3fe9, 0xd2ffe5ff, 0xff4207fe, 0xeffe96d9, 0x3ff697fc, - 0x57fcc7ac, 0xfcbfeac6, 0x433b6db9, 0x9e4a6f20, 0x60c3c879, 0xd4a93a1f, - 0xef00f8a4, 0x7a579b65, 0x284e0e90, 0xf3d20f21, 0x3d3cb0c9, 0x46ec3d16, - 0xa23f207a, 0x5da125df, 0xfe84ff85, 0xdf753d4f, 0x3e67dc4c, 0x64eaacdb, - 0x47b16d2f, 0x15afc0ec, 0xd833c58d, 0xe11fca18, 0xc8cfbbf9, 0xd2b26f98, - 0x0f93c967, 0x0dffa0a5, 0x13d84528, 0x2a97d211, 0xc5cc3eea, 0x3ac8287d, - 0xdba2cf89, 0xfae7f8e1, 0xd7cc7c90, 0xc3967a12, 0x0fcf493c, 0x1b04b80a, - 0xa3233bef, 0x72b593ef, 0xfd54683f, 0xd4ffa122, 0xc749dcdb, 0xdf6274c0, - 0x7941df61, 0x8583c069, 0xbd53feb9, 0x4731e1f5, 0x756d3e60, 0x2648f1bf, - 0x767c1938, 0x2ffe61b6, 0x2ef6f79e, 0x9d85db8f, 0x4c2eddd7, 0x424dbced, - 0x69e66b6f, 0xa0f11a99, 0x41b65c5e, 0x73e085f5, 0x4f4db6d9, 0xea768a3c, - 0x70df76bb, 0xdb74bfe8, 0x00987f4b, 0x6aedd2f9, 0x0cbe0cd2, 0x8dd29497, - 0xbffc2097, 0x1e376c74, 0x92f57e4a, 0xbfcd1de6, 0x374fb8ff, 0xefb74a3e, - 0x9ee8d8d3, 0xb0d298f0, 0xc5756b4f, 0x91c34bc0, 0xaaafd45c, 0xa1ae7eb7, - 0xaf72793d, 0x63d352c4, 0x4bc373c0, 0x9c2027a4, 0x4f028f08, 0xaa8b785d, - 0xa0bc041f, 0x14f0373c, 0x9080fe5d, 0x779fd83f, 0xd3f3d114, 0xf95fa3cf, - 0xd70fbb3d, 0xedf4f45f, 0x71c75c1e, 0xf5d392a5, 0xfc532b63, 0x1a916e30, - 0xe529d14a, 0xff1e8bdf, 0xe15bd121, 0xe14c3f1b, 0x9fbfa0f6, 0x50a6f68d, - 0xc2df5c3f, 0xfad037f5, 0xe880580a, 0x3931e8ae, 0xa7e90c2f, 0x3dbe9b0a, - 0xc8645f06, 0x6f8e2f9c, 0xd60b8504, 0x12ed1c77, 0x4efeb3f4, 0x7f266f0e, - 0xfc8622c8, 0x3fc343ff, 0xfe5316ce, 0x93c70753, 0xbe09b643, 0x4ccf6d02, - 0xb77775af, 0x0d4e7e20, 0x1fa2a7f2, 0x9094c82d, 0x25f48780, 0x31bf2bf4, - 0x87e3952d, 0xd16c9579, 0x2980f40e, 0xb7eb1df8, 0x18e77ea8, 0x65f63b4b, - 0x4bf8f77a, 0xef30f8c4, 0x8fbfdc38, 0x86a2b0a7, 0x55bbeb18, 0xf61ef836, - 0x997d1371, 0x7bf39bf8, 0xbf9c3ddd, 0xcf0f7e0d, 0x9fe58e9a, 0x07f9c9bc, - 0x08fee1db, 0x52a48af3, 0x25ebbef9, 0x16760792, 0x75d7c589, 0x6b6be0aa, - 0x302741b9, 0x304a456f, 0xdff60bd1, 0xfe4fe087, 0xd07582b3, 0x832f24ce, - 0x67a79e38, 0x16df067f, 0x251ffe0a, 0xad9ff95b, 0xbbdf7ce7, 0x7da2157e, - 0x3f0d4cae, 0x2bf228f1, 0x8bc867f0, 0xe1e6aafc, 0x1fd74fba, 0xc04dc3f8, - 0x0c1ba7a7, 0xcfcab53e, 0x7a2d3e68, 0xf484b376, 0xa7a7cd19, 0x891b408b, - 0x3df0a7c5, 0xb5169f26, 0x9f953ffe, 0x8faefc06, 0x0f219f82, 0xb463837b, - 0xf3633c3c, 0xe5a33c12, 0xc9bdfc21, 0x9fd27bb2, 0xbd067741, 0xfcb2fc95, - 0x1817f222, 0x5dd06974, 0x741a5d17, 0x62ffc3d7, 0xf9745f81, 0xa005a460, - 0x2a5dbc93, 0xcd6555d9, 0xda0c3cfc, 0x8b203cbd, 0x6da7e4e0, 0x3cbcd58c, - 0x0f9cc920, 0xa21be547, 0xf2a3fbea, 0x03f55179, 0x4b4af951, 0x03a6b2fd, - 0x47fc231a, 0x4becf52c, 0xc41f651f, 0xfd8c87b0, 0x4678d826, 0x0c5d210b, - 0xde50d4ec, 0x0541cba9, 0x1ee0ff45, 0x0ec5ec99, 0x182af180, 0x3d3ea3a7, - 0xb1b9021c, 0xf0edc9d2, 0xd3d3bd0e, 0x8995d207, 0xac99df3c, 0x67b942ad, - 0x7274ef7c, 0x5e47473f, 0xe4d127a7, 0x2cd238a7, 0x0d6edc93, 0xfcb1e9b3, - 0x10a3b020, 0x6f595bde, 0x39ffdce5, 0x5e0d764d, 0x8d68f68a, 0x771343ec, - 0x3d1bb2c1, 0x68e92ae8, 0x6ccd7a1e, 0x55f0bef8, 0x3a558e99, 0x70633ce2, - 0x57e42c5e, 0x89ec99fa, 0xb3f42c13, 0x6ccfe889, 0x82c576e6, 0x08fa5135, - 0x54f4435b, 0xa1a25ae0, 0xe03b053c, 0x973fab7d, 0xe88945f3, 0xb5bd68af, - 0x278f68dc, 0x95df685a, 0x03cb59d4, 0x65da3ec2, 0xcb0649f0, 0x86833920, - 0x42e7da0f, 0x47934f2e, 0xf01b335d, 0x665071d1, 0xb6799e78, 0x9c7c2659, - 0x97e7e7ad, 0xfc4c942c, 0x493ac156, 0x6a701a1e, 0x7ad27e43, 0x3b6d5797, - 0x177d9cfe, 0x3fcecdd2, 0xa439f98e, 0x1ddf3b6d, 0xcff31bb1, 0x8ff83dbd, - 0x29fd67ac, 0x37e49d7b, 0x26ebd8ee, 0xf3d8ef7a, 0x6177c1db, 0xfc9d977e, - 0x3f7b1d75, 0xd7f4831f, 0x845edcb1, 0x1063aef2, 0xf7aa87b7, 0x95a63e7c, - 0x8415d7f6, 0xc6b2a3b7, 0xbfe6a3f5, 0x3092961e, 0xdea15585, 0xf89e37b0, - 0x93bcf829, 0x7b1d0bfc, 0xb80ecf3e, 0xa9eb75fe, 0x1d39e710, 0x59fb366e, - 0xf7225f9c, 0x8f770783, 0xcf0cb4df, 0x69f71ba3, 0xca7ca1f3, 0x831f7f0b, - 0x59e3b472, 0xabb50fae, 0x79e38fad, 0xe1fc8745, 0xdce01532, 0x9fd54c8e, - 0x1194fbb1, 0x62a34393, 0xe4efe5c1, 0x7850b937, 0x4fb70a68, 0x21e1fdff, - 0x73bcb9f9, 0xae121d87, 0x7fc38bfb, 0xd7b0b944, 0xac69744e, 0x32c374f7, - 0xb7ce57d2, 0x7fcae1ee, 0xd0b83a17, 0x0b914b75, 0x7fd4f759, 0x5aff7c73, - 0xa2fcd2f6, 0x9d27a0f9, 0xf283b9ef, 0x9a3edcdb, 0xfbd205ef, 0x7869ff82, - 0xeef0167f, 0xabbaff39, 0xddd7cdff, 0x9d5fde3b, 0xe3aef02b, 0x85f07f79, - 0xbefcd3bf, 0xf4db9cae, 0x0dee94df, 0x9b15febd, 0xa80ccdf7, 0xb8d59d3f, - 0xb2b8b150, 0x19abff7c, 0xc0cafa50, 0xdf388903, 0x37e751c9, 0xc2a6fa46, - 0x92c9a6ed, 0x9641ec8d, 0x907b0928, 0x840351db, 0x496030fe, 0x0321e901, - 0xf5cfde06, 0x0ebbc506, 0x195f1fcf, 0xb147df3c, 0x3bec6c14, 0x97ebcc01, - 0x9ed5bc8b, 0xfcc4b9fc, 0x603a3478, 0xa20ff7f0, 0xa0703b5e, 0xa42f7a4c, - 0xe8beefa4, 0x97bfce99, 0xe7bb1669, 0x0ed5af4a, 0xdab24dca, 0x7f45534b, - 0xff9f18d3, 0x0e149734, 0x0f261c03, 0xfa1269fa, 0x570f2747, 0x5cf90499, - 0xf6815816, 0xb59754c5, 0xc33c06bf, 0xe1cdf719, 0x380d5768, 0x8797590e, - 0x93241c70, 0x70bcf49f, 0xdc1379c4, 0x2f18c232, 0x871f14c3, 0x1f729f63, - 0xbd859df9, 0x904d474d, 0x5aab5c57, 0xb4159f90, 0xc81c3997, 0xe5ec36ce, - 0x84cde0de, 0x2188adfd, 0x032bf80d, 0xdad3bf65, 0x06dfd91f, 0x3e2ebe5e, - 0x537e3c0c, 0x851bbcbc, 0x45ae8197, 0x74ebf20a, 0x62fa17b4, 0x1f9e0cfd, - 0xdce85218, 0x570bd84d, 0xa4291778, 0x50cc0cf7, 0x8e855f10, 0x1cf0aba6, - 0x6893e1c4, 0xd9b7171e, 0x64707f68, 0x91f70449, 0xdfe50ab5, 0x10e3e9b0, - 0x7b2f33df, 0x0c9df4ee, 0x8d7ee6fd, 0xf1e53dc7, 0x7dbf8ff3, 0x8c44e5f9, - 0x2c781417, 0x46afff84, 0x167aff3f, 0x2d380389, 0xa1285854, 0x25bdfa0f, - 0xefc5bef6, 0xdfe3cd6d, 0xfbba5377, 0xdefd5f39, 0x3abfcae4, 0xd8e40e7d, - 0x5df300fb, 0xe1a30e98, 0xfd5db315, 0xaf0e669d, 0x1e1621e0, 0xe42ae3c2, - 0xe139d33c, 0x9ffe821d, 0x99b3d3fb, 0xea4ed768, 0xe5c09518, 0x17b230eb, - 0x385ec282, 0x3e09bccb, 0xa1d7ca17, 0x79fe7409, 0x8ac77650, 0xec2adc2b, - 0x7c625fed, 0x751da409, 0xfb4646ac, 0x1f92758d, 0x60e75437, 0xb7c4639b, - 0x9f86abe4, 0xfe0de04a, 0x8f3c6ce4, 0x842fe3e1, 0xbc6609a6, 0xa938cdb5, - 0x0789e98c, 0x74df7bfc, 0xe14df51e, 0xc23df68b, 0x35b3ab77, 0xfc862f37, - 0x6fc05db8, 0xc82ffee6, 0xf36979ff, 0xefd21b06, 0xcb3675a5, 0x2aa96af9, - 0x6cb1b1ec, 0xe66bce2c, 0x0b3ba77e, 0xf65072f1, 0xb0673c61, 0x88168cf9, - 0x0d182e71, 0xfd1fec4f, 0x9d555be9, 0xdab76bf8, 0xbae11f30, 0x430723fb, - 0x56977a3b, 0x9e6b1a53, 0x9e7cec03, 0xedc3590b, 0xfdffd263, 0xc3a93be0, - 0xf68c9915, 0x7e131d67, 0x63fa688f, 0xb767c744, 0xafee30b0, 0x5ca2af68, - 0x68cf5b38, 0xdc90077f, 0xf037768f, 0x7eccf7fb, 0xb69b8b9c, 0x82f512ff, - 0xc749668a, 0xa50a8623, 0x6d3f4355, 0xc65129b0, 0x6bc3387d, 0xa3eabbc4, - 0xc5f137af, 0xf8215556, 0xfbb0981e, 0xe3f71c66, 0x9ea18d36, 0xd3b17fe2, - 0xc7f8fb83, 0x07c499cd, 0x57ebadbd, 0xa9aaec55, 0x972a3748, 0x30f4d187, - 0x92ce3eaa, 0xf40e4cbf, 0x699afe47, 0x8be25d6f, 0x6befbf81, 0xbc173892, - 0xfe16f940, 0xbdbe4cff, 0x80b7c869, 0xa3e2679c, 0xf90f5abe, 0xbe4b1a96, - 0xa9bc962d, 0x7bc5f708, 0x5e22a686, 0x26aabf17, 0xdb6f92c7, 0xe739f8aa, - 0xb94e2233, 0xdbe411a3, 0xadf24db7, 0x8c5be411, 0x5fbf9078, 0xff0b7ca8, - 0x36dff0d7, 0xd6316f94, 0xf9566bab, 0x08f9a636, 0x8d31b7c9, 0xaf3c4b36, - 0x7c9f3b5d, 0x47af9293, 0xeaa0f8fd, 0x3f418f8b, 0xfe3e84db, 0xc44b888c, - 0xe5ce5071, 0x7f8d3a6a, 0xe2ee72a1, 0xff73950b, 0xe4367045, 0x8c1de2dc, - 0xd27b9ce2, 0x8b739721, 0x939c8177, 0x9cb91e90, 0x7187bc5b, 0x7c945cbf, - 0xbe43d91b, 0x115faa31, 0x4d83ede1, 0x02df0fe9, 0xabf58dfd, 0x1fd4073e, - 0xc6ef2ddb, 0xae5de599, 0x7adc10a6, 0x1783bbc8, 0x0876ef26, 0x6c720779, - 0x68d7ca08, 0x5b35f0fa, 0x8f77c1e3, 0x2bff5e3f, 0xcadf97e4, 0x86f8de74, - 0xbd0f9f8d, 0x1678fe36, 0x6263d7d2, 0xdc848b3e, 0x510aaf6b, 0xe45e53ff, - 0xf1772beb, 0x468af138, 0xd4561fae, 0xfc2f614b, 0x17c27733, 0x78bfce1a, - 0x2152c48f, 0xebcecb3f, 0xf38d27b3, 0xc3233632, 0x720b0f44, 0xbfcfc94a, - 0xf40e6140, 0x72ba97e3, 0x5bfea24f, 0xfefdc39a, 0xf17be2a5, 0xd0abadab, - 0x88fc5dff, 0x46a5e744, 0xe711ab7c, 0xa26e23db, 0x77f91979, 0x6627e3a3, - 0x99a9b88a, 0x1bc294bf, 0x947fc462, 0x7fe6b16e, 0x966ff822, 0x62f04adc, - 0xe331cbaf, 0x5d7a8c38, 0xe0283a70, 0x7ed32754, 0x802705da, 0x27bd379b, - 0x33d3009c, 0xe1ba5232, 0x585bfc52, 0xebef566f, 0xbd16e035, 0x5d7fc36e, - 0x0de9fa2a, 0x7b9c060e, 0x1dc05fac, 0x939202ec, 0xa758f0d1, 0x33b5f975, - 0xe8094e31, 0xe84ce486, 0x181700d7, 0x70d26f2f, 0x47977dcb, 0xd664fd05, - 0xe1829a4c, 0xae30b30c, 0x6a0bca1c, 0x0fdcbd17, 0x1dee31e0, 0x4edc58ef, - 0x0f609b2f, 0x56ec39e0, 0x41c92767, 0x35db0e83, 0x141c07ae, 0xbfddddf0, - 0xf9d93272, 0x7a8e924d, 0x24e23048, 0xae0106b8, 0xa828ff78, 0x8106fc70, - 0x0eff911e, 0x8719f23c, 0x8bc91ee3, 0x635c9dfe, 0x40bc42bf, 0x8e66ccfd, - 0x22586097, 0x4eb164bc, 0xa8a97f3a, 0x84117c95, 0x8206d35f, 0xe19f219f, - 0x93c665cf, 0x58957e89, 0x4c954bf4, 0xa8a965fb, 0xf35ed337, 0x99e7a407, - 0x036caa4f, 0xfbfe1b81, 0x4f3e7a2a, 0x9e34501c, 0xb6bc04da, 0x085d3c21, - 0x77ae4eb7, 0xfba0be45, 0x50794650, 0x39e05909, 0x5f73d1e5, 0x0671af09, - 0x518e90bc, 0xcbe735be, 0x92682f98, 0x9ef4df58, 0x50f3c5eb, 0xef17bf33, - 0x7ffbc239, 0x18b1f24c, 0xba60beeb, 0x8b9e85ee, 0xbcf16e80, 0x8eba37a4, - 0xd23b5386, 0xe9bab7f3, 0xe76735f9, 0xe7a44ca1, 0x43f7123d, 0xce5a2734, - 0x1e763d35, 0x09d5b5f7, 0xeeeb0f74, 0x6df5557c, 0xcb90c6f4, 0x7ed1ee82, - 0xbb37df30, 0xf1821704, 0x141c5ba2, 0x18f347ef, 0xb353f5c2, 0x64e6de7c, - 0xf567d7c9, 0x2edbbfde, 0x37278cc5, 0x3f2323f4, 0xf8c3c71a, 0x6f1826f9, - 0xd178f764, 0x2fe183fb, 0xfabadf38, 0xbad9bfdb, 0x6ebe718c, 0xb590543c, - 0xb88d5e10, 0xe05223a8, 0x73ea2a47, 0xfc4b25d3, 0xc85ccc15, 0x7fdc6fad, - 0x7bdc96aa, 0xa74d2cff, 0xebb774fb, 0xe89d77c6, 0xe2674f33, 0xdbe26f7c, - 0xec7fefb8, 0x5998e7e7, 0x44d6f636, 0xab263fdc, 0xe3eae90c, 0xa1f92a43, - 0xe3ca9e3f, 0xedf9af6e, 0x3e5d0501, 0x3898f0d7, 0x8938cd76, 0xb037acec, - 0x87a8f1eb, 0x047f983b, 0xef132fc1, 0xd5d465ed, 0x5f02f14c, 0xae12dd8f, - 0xa537d4c6, 0xc435e933, 0x219924db, 0x7dfc5ade, 0x7f20b8a7, 0x032c87fb, - 0x1fa0a05d, 0x07b1fb50, 0x9bd63259, 0x33264fe0, 0x27e37c66, 0xf3075e6f, - 0xf6487f18, 0xacdea179, 0x03172e03, 0x7ae47a7d, 0xe0980b1b, 0xab858135, - 0xfe34dfd1, 0x9c3affa8, 0x3be81177, 0xa8a44f78, 0x07b54379, 0x6a25ebf3, - 0x72050c1f, 0x6d9eb03d, 0xbf7267b5, 0xea017285, 0xf5c13761, 0x4eb05ebc, - 0x728861f2, 0x8a5af341, 0x93a82a2f, 0xb6e142e8, 0xbc1cc4b0, 0xfa03b0df, - 0xda1eb6dd, 0x05fee167, 0xbadfb1ed, 0x875e6f33, 0x49e60772, 0xb9f9ebed, - 0xf3b4017c, 0x2dd4bf22, 0xd78afea2, 0xb3ef0c4b, 0x7df3d514, 0xea90e8a9, - 0x7dc6f2c3, 0x3b7ed08f, 0x97ebc603, 0x6450fb8e, 0xca0bdd2a, 0x2fba7494, - 0xf84c1a19, 0x7f1c60eb, 0xf220fa6c, 0xabbc520b, 0x98a0c097, 0x64fe63e3, - 0xb3f2421f, 0xeb4cb7c0, 0x96bcfd0b, 0x236e9c93, 0xe7433aba, 0xde0147ed, - 0x1bf78001, 0x40e55e22, 0xab5a07ce, 0xc2fc5f69, 0x9b9f943e, 0x38a24d34, - 0x8f2c858e, 0x8e6638e2, 0xebe6fae7, 0xe8c33b97, 0xed5d7be7, 0x0fdf881c, - 0xefa76e5c, 0x1cb8dbed, 0x4ad41f6e, 0xebe3f6fe, 0x58f78655, 0x24cbd7aa, - 0xabd78e2f, 0x7e563f74, 0x1431c78c, 0xc7fae36e, 0xdfbcf581, 0xe1b7a8e3, - 0x439607b9, 0x11ab70be, 0xb4e5c0e7, 0xe8167f61, 0x90c2fe3c, 0xdd62e5bb, - 0x75a1f63d, 0xd92434cb, 0x2e5b7968, 0x8b0971e4, 0x2d1cbd90, 0x1cf1cb77, - 0x197c83dd, 0xeae6271d, 0x0e9063b6, 0x5d105f22, 0x19521c57, 0x07d231da, - 0x9714b96d, 0x73a247b6, 0x92cdf18b, 0x8a1ae31f, 0x4987b1de, 0xcfe70eff, - 0x2fee11fb, 0x8619daef, 0x3c431f2c, 0xb1ca9c80, 0xa7e9fe77, 0x1be4fdf0, - 0x02088c0e, 0xb827c9ba, 0x59be711b, 0x4f3c799b, 0x52eb1bd6, 0x9b2f3ef0, - 0x40e497da, 0x02ccad61, 0x52713926, 0x13775ff2, 0xd4741fdf, 0x667c0c77, - 0xb8053569, 0xc1cb7ebf, 0x66ef55f7, 0xd8646315, 0x043d84ef, 0xf51f81f6, - 0x6b5de29b, 0x1d133453, 0x9b59ef14, 0x55f7c322, 0x1aa61e22, 0x576857f7, - 0x8a71f1ac, 0x06fa4af7, 0x3f4638d3, 0x2edabf46, 0x1ee86ede, 0x7fd6f69e, - 0xd68fce31, 0xf286a9f9, 0x1e9fba22, 0x4fd2f7e3, 0xadcfefce, 0x395e6093, - 0xac14cbaf, 0x8cc1f39e, 0x1d73e6a1, 0xcafc3523, 0x98da6fd9, 0x9cbf04df, - 0xbf31c53f, 0xe38ddf09, 0x7f01ef80, 0x61493757, 0x23f984a7, 0xe516795a, - 0x0af3e475, 0x98ae7fe1, 0x1aebcfca, 0x8158de33, 0x4b233f7c, 0xa1607a22, - 0x8937d680, 0xfa2f35f4, 0x78b30bfd, 0x8f6842fb, 0x08f8d8fc, 0x13904fe7, - 0x1523945e, 0x52e6d7eb, 0x8bc93afd, 0xc86e37fd, 0x28a47d27, 0x5e546647, - 0xa3f48477, 0x4923a6a2, 0xb7c0c7c8, 0xa81f50eb, 0x51d76898, 0x68fc1b8e, - 0xe2ebf7f0, 0xe8732b3e, 0xc67ef1a3, 0x8be646ff, 0x21f2d7c1, 0xf583d72e, - 0x39831f9c, 0xdf5f5f9c, 0x2f0ae2a6, 0x9f89bf84, 0xfce16f8f, 0x43763f2a, - 0x2f87de2e, 0xc3efccdc, 0x453f581f, 0x78fa7d43, 0xa6fda258, 0xbd737f27, - 0xabbf9a35, 0x7defbe25, 0xe0d2fd5d, 0xe18f836f, 0xaf1c6aef, 0xef14f80c, - 0xf5f3464f, 0x0fe1b54c, 0xaf7cc3b7, 0x03d61a79, 0xddf29df3, 0x26ad3d3b, - 0x14f90939, 0x3c2817cc, 0x2b90cb9e, 0xfb8f0ae5, 0x8bf3dafb, 0xb76c3f1a, - 0x677e47fa, 0xebf1e44f, 0xfdd12a75, 0x07b3f8f9, 0x7f205d9f, 0x9d5f285e, - 0xf18d3f8f, 0x7ed63de5, 0x2de8277e, 0x8076bfba, 0xfae0046b, 0x8a26fd4a, - 0xa9e8fdf3, 0x3f113323, 0xce81bba5, 0xddeabe91, 0x4e72822c, 0x557ed309, - 0x3dd328d2, 0xb244a601, 0xf99b73af, 0x956dc798, 0x7a26e33e, 0x1ed6792a, - 0x4bed019e, 0x86307e76, 0x779668e2, 0xe85a5c52, 0x872fa129, 0x1f20c75a, - 0x7e3c2894, 0x042e5a2c, 0xd70fdc1c, 0x367e2bb6, 0xc2da4fae, 0x69288fdf, - 0x9bb551b8, 0x746e25ce, 0x3a3d46a8, 0x1d010dd7, 0x9c5dfde3, 0x02ddf99f, - 0x6dac6e23, 0x2513972b, 0x81d92a4d, 0xb7b65b25, 0xc970fc63, 0x77f2763b, - 0xa19cb705, 0x9e5310fb, 0x94fe46d9, 0x396c9360, 0xb711eb7f, 0xd88e45b9, - 0xb1b0ee31, 0x211dce9c, 0x0df2847f, 0xcf97e3b1, 0xfa585f17, 0x219d9ecc, - 0xafe96100, 0x7ca0f49e, 0xd9b2d539, 0x7e877083, 0xba6e32bf, 0xc3669c47, - 0xa7195f3d, 0x01ff0a79, 0x438f738c, 0x9c4635d8, 0xa4be96eb, 0xb2fcc247, - 0x739c62f3, 0xdbe5e974, 0xef1c7d3e, 0x7b3db411, 0x6f9c71fa, 0x7e3e3fd9, - 0xd8c1e31c, 0x77ed275e, 0xa2dea7c1, 0xdda36c38, 0xb5dfb126, 0xe2927d6f, - 0xb5dfdbd7, 0xf6b7b0fb, 0x6307c73d, 0xf6fb603c, 0x6fd0522f, 0x34cf64b9, - 0xd92eebf2, 0xc5952531, 0x148c2fd8, 0x017c36e9, 0xf8d1f3f1, 0x8078d03a, - 0x023ed6e2, 0xebfca37c, 0x286dbb8a, 0x5ecc71e7, 0x1f5b6f11, 0x8f429efb, - 0xebc6daf8, 0xe51cb9ae, 0x1fd7237e, 0xfb671bcf, 0xdbf1e026, 0x7abf8017, - 0x1b102fc3, 0x3fe11f7f, 0xa2fb4f00, 0xe369f7f0, 0x8a3c5fc2, 0x7b7d8d65, - 0x5c8db38d, 0x7b8cdc00, 0xfc380f10, 0x88c91c87, 0x5c525fe7, 0x866de233, - 0x4f9ff717, 0x91fde307, 0x5ce76a13, 0xc7b85fba, 0x68bc63ae, 0x89b79ec9, - 0xbc77da7f, 0x26687e41, 0xb3b423ee, 0x3f1e3fae, 0xd675892e, 0xae7c79b9, - 0xefc63f80, 0x5df43d7a, 0x3a72e9c4, 0x7b77e236, 0x9d95db8b, 0xee36cf5c, - 0xfdd79467, 0x76c3c451, 0x41ca4be3, 0xcaf91d3c, 0x0e036878, 0xddc390ba, - 0xe3b1e871, 0x2beebba3, 0xfe217c08, 0x8aea1f70, 0xc0fc8733, 0x7a37e4b1, - 0x0790c59b, 0xfc781bed, 0xfb1abb7a, 0x9711b05e, 0x3e688ffe, 0x3c585f0d, - 0xffe6f9fa, 0x81d3e175, 0x4f724fca, 0x2dfdb538, 0x774f1cb6, 0x9eecdf4a, - 0x7d149961, 0x1cebca6f, 0x473b7187, 0xbb83b434, 0xdeb16cec, 0x6f57e136, - 0x78a64a7b, 0x070d55e5, 0xcb478e48, 0x2f7c0a8b, 0x337cc625, 0x9a2b7cc5, - 0xf6d13ef8, 0x82ec3bac, 0xeff6da7e, 0xa8ae7a22, 0xd2f1423f, 0x95f96f2f, - 0x8b8a6ad6, 0x6c227dc0, 0xd3db7f9a, 0xdc90c6fb, 0x44b2ef16, 0x8c49338f, - 0x3d8e6c13, 0x8cfeb04e, 0x50d29c65, 0xcebba683, 0xc529de3f, 0x77f6237f, - 0x83eb85aa, 0xe9e41aa7, 0x0fe318e1, 0x77d6aa73, 0xa4bf60a1, 0xfcdc67f7, - 0x13d919bd, 0x12e5fa47, 0x093bce77, 0x146a9849, 0x4cbd55af, 0x87fd77c4, - 0x5df10d2f, 0xe18abeed, 0x7c22577c, 0x551e7e4d, 0x4bd4300f, 0x2cbcb4d5, - 0xcb442bf4, 0xc6c92d1b, 0x2ffc26c2, 0xf54f4f71, 0x644779d2, 0x70f3e220, - 0xfb1571c6, 0x9f944bfd, 0x5b0a2fea, 0xfbf30a95, 0x2df2484b, 0xdfd97e83, - 0xe794183e, 0x977fd9ee, 0xd963f11e, 0xb0aa57e2, 0xbb461e77, 0xa4e0bd84, - 0xaf7906f8, 0x08f9de93, 0xf5a4ee3e, 0xf9f1d81e, 0xff5fa413, 0xb9f8cec2, - 0x202f580f, 0xde750aaf, 0x9f1df1c7, 0xd457fe3f, 0x8c31b19f, 0xd438f85f, - 0x3ea1bb47, 0x8e9cec9e, 0xa0c61367, 0x85f0a45f, 0x3ca266bb, 0xf4e78c2b, - 0x6a4cf858, 0x3bfa1ab8, 0xc7f3cc96, 0x77a20db6, 0x759f4a25, 0x81e8dc53, - 0xe055cf1d, 0x4cfed4be, 0xa97dc33c, 0xe7a105fd, 0x53bc52ff, 0xcd7aab55, - 0x4cc5e3f1, 0xf3ef9af1, 0x12de6294, 0x2fc8c4af, 0xfe847c41, 0xba04a6aa, - 0xaffa0407, 0xd48f9fa5, 0x447c3bce, 0xfcfea1c7, 0x3fa453fe, 0x7ae883ca, - 0xcebdf946, 0x395ee221, 0xd77573b4, 0x059d6a0f, 0x9fd35f3c, 0xaa1693cb, - 0xf853b0ff, 0xcf79458f, 0x87fd797e, 0xeeeefc84, 0x10afb787, 0xd344d0ef, - 0x6fd146ef, 0x5fbf96e9, 0x959deb1c, 0xefa7f318, 0xc858943f, 0x76ca7a86, - 0x857fbd27, 0x7de028ef, 0x3f1a9d85, 0x44f32ad7, 0xdd9b9de8, 0xc5971e42, - 0x9ddde845, 0x581e62fe, 0xd1ccf31f, 0x9fbd34fa, 0x61939cf6, 0x0bf9595c, - 0xbbe23f6e, 0xc7e7e77c, 0x71859e7e, 0x1714f189, 0xffc2fe5f, 0xb7283a22, - 0x3f22e647, 0xb3b76e74, 0xdbe7c88d, 0xfc8c1d5f, 0x0646a6da, 0xf38af9f7, - 0xbb06f2ba, 0x58bffef5, 0xdaaaa9c7, 0xbbbef0cb, 0xa4b6af71, 0x57f33917, - 0x5fa3d727, 0x725ffa71, 0xdf5bbf12, 0x35553a73, 0x59df133b, 0x3897ea30, - 0x77c5cb62, 0x137c5e51, 0x71eaee39, 0x9c5df53f, 0x25ac47cf, 0x153efd05, - 0x3ca377a0, 0x3e92d92f, 0xfb04fd10, 0x043bc69d, 0x8fdc04de, 0xb25eabf6, - 0xef3531a7, 0x7caa2733, 0xf430ca99, 0x54cc8cdf, 0x1b1d1d60, 0x67f414ce, - 0x9cea4718, 0x9dee4b1d, 0x3ad3c676, 0x98f61c4a, 0x09cf9df7, 0x8d0f7aba, - 0x1e3e64fe, 0xee3187f2, 0x724c357e, 0x2f388ef8, 0xbb012bd5, 0x6e97bf08, - 0x79699399, 0xa1a9457f, 0x04a7c07a, 0x4eb662cf, 0x6fc932cb, 0xa5e2bc63, - 0x264a9959, 0x4ffe577e, 0xddcabd17, 0x24a16678, 0x01150bd2, 0x9faeb663, - 0xa2887ee5, 0x7e1039e6, 0x15d3cb1a, 0x86a54919, 0x358e3df8, 0x7502ea50, - 0x5653bf8b, 0x9e4e50c9, 0xe8f6e710, 0x1bb4c2ef, 0xdc92775e, 0x6c620d0f, - 0x07be3a78, 0x4dd04de1, 0x10f153f0, 0x5763e61e, 0x1797192a, 0x93b47433, - 0x7d8050a5, 0x5d54f409, 0xe9133d35, 0x18fcfe11, 0x07a64907, 0xbfa3cfcc, - 0x41ea05fc, 0x3dfca740, 0x70b2efbf, 0xc3188035, 0x3aafc981, 0xe877f199, - 0xccc3bf56, 0x71a5c6f6, 0x68e77892, 0x1731c91f, 0x84ebfeeb, 0x94558a3c, - 0xff09d5b7, 0x4473c1c8, 0xa822ce97, 0x58bbc617, 0xd7521e24, 0x9994e528, - 0x90593dff, 0x3ea9d137, 0xcd1e5ad1, 0xa2d72017, 0xf8206dc6, 0x449fbf41, - 0x5449fbf5, 0x557c9fbf, 0x829c06bf, 0x7c3e8d8e, 0x556562a7, 0x1f1b809e, - 0x06e021cf, 0xef8919f0, 0x9c5b31e8, 0x13879c4f, 0x6cc4e35c, 0xf01f58ec, - 0x4e971e5a, 0x612fb978, 0x41c6276f, 0x865aa4b3, 0x890aef76, 0x97f0d3ef, - 0x63b532e7, 0xf0f883ba, 0xb94e311e, 0xc30af380, 0xbea3d53f, 0x1eaff493, - 0xd5bd9df5, 0xdf5d8b8f, 0xe27cdbdd, 0xb127cf63, 0xe26bfe97, 0x75fff663, - 0x0bc552e5, 0xe786bf6f, 0x49f25db6, 0xf55bd007, 0xd438f2cc, 0xfd8f1333, - 0x70be95a3, 0xd031d33d, 0xa438ef8a, 0xb8b7a06f, 0xd1efd661, 0x7d1bd274, - 0x40758be5, 0xe00fd5de, 0x7f189370, 0xf73f1d6a, 0xf70965be, 0xe87981d3, - 0x8b37fac7, 0x0a3937fa, 0xc470dfc9, 0xbabfdfc6, 0x91eb96a5, 0xa658fcb7, - 0xef1ee9f3, 0x803fe151, 0x2a5d6edf, 0xb1e92385, 0x7562d7de, 0x9e6e3f78, - 0xbdfa3f18, 0xe6f300aa, 0xbd6396ae, 0xd2e9c557, 0xfd1757b8, 0x9602c54e, - 0xb321de27, 0xd4eb3f7e, 0xcd67e4bb, 0x2c7deea8, 0x1ee816b4, 0x7ba04ff5, - 0xebc7973c, 0xe2171462, 0x485c78d1, 0x4f3a20cb, 0xd9dfe433, 0xdc04de91, - 0x307f99af, 0xeff3aeff, 0xa6f4af8b, 0x2a1def9a, 0xef2ce2e7, 0xbeab54f5, - 0xea6f9434, 0xc15fd039, 0x0dced654, 0x39535e61, 0xfcc4ade8, 0x7249be18, - 0xa3094d2a, 0x3cf4545c, 0xaf7a8856, 0xa8c3ef78, 0xd55d25af, 0x0ebe67a5, - 0x4b8e6fff, 0xbc5cbe26, 0xb6f74bd6, 0xdbcf8b3f, 0x7b24f489, 0x57017c72, - 0xed087a4f, 0xc6aeebe0, 0x5cf7a775, 0xf3e6b54f, 0x157dbe91, 0x6ffc8080, - 0x4fce073e, 0xf6df7bb6, 0xa37efce2, 0xf4bbf432, 0x44ef8f84, 0x86cfca18, - 0x887c5007, 0x0463309c, 0xbc46bf8e, 0x6ababa6f, 0xaa2ba524, 0xbc794898, - 0xaf2a8adc, 0xea447348, 0xaa74e917, 0x1a556f77, 0xf95557e5, 0xebe03528, - 0xfbd0d5f0, 0x7c618e93, 0xf02e877c, 0xf0136497, 0xe5fe900b, 0x73a4ab48, - 0x195ea745, 0xd8df77c1, 0x7077d840, 0xc10d7a59, 0xf919d357, 0xe53ea135, - 0x548798ed, 0xf8419dad, 0x564af452, 0xc56fe508, 0x5c228e07, 0x2d4bde9d, - 0xd3da5aef, 0x7fbd46c6, 0x836f051a, 0xb871b6de, 0x7a712fdf, 0xfdfb868b, - 0xe3178b6a, 0xb2bfee22, 0x82295deb, 0x1c43983b, 0xe7e6bfee, 0xdee13db4, - 0x09be7b32, 0xe9eceeee, 0x04fbf704, 0x7016ef9c, 0xa87816ad, 0x46acf016, - 0xa47e53b8, 0x3a44fbc8, 0xc47bd29d, 0x112bb7fb, 0x08ca901f, 0x7d878077, - 0x30c98854, 0xf179ba1e, 0x7412eecf, 0x1fc8dbab, 0xfcf2bb2a, 0x127b7708, - 0x05c3bb87, 0x06ba2078, 0x3cb17bb8, 0x5d54f044, 0x9f50ce1c, 0x15e441e3, - 0x7e267b84, 0xb800f8e7, 0x871f8df7, 0x058270f2, 0xe4d25ace, 0x23fb830b, - 0x124b7f7c, 0xbf0d1e7c, 0xafbf8d24, 0x6f77f06b, 0x88b571fa, 0xef16aeb7, - 0x511c2227, 0xe00879af, 0x4f0e34c3, 0xc8a47dfe, 0x164d28fb, 0xe0357ff6, - 0x161fcb01, 0x19c210fa, 0x73c51fd3, 0x56c93cfb, 0x38454fb9, 0xf2efe1f5, - 0x1b10a4b0, 0x6878cd98, 0x85a5fe2f, 0xc6f31798, 0x4ad7aff9, 0x44aeb23f, - 0x7de903bd, 0xdd6de918, 0xcf0daaab, 0x57a5e43f, 0xcb67ee59, 0x5e89fdb3, - 0x42407f82, 0xc13ee6bd, 0x5e916b87, 0x1edc7e68, 0xe0e8295e, 0xeefef16e, - 0xee7e823d, 0xa0fcfc17, 0x7e3e3741, 0x74cd643f, 0x9498c71e, 0x20ef1361, - 0x4e399846, 0xc0d7d130, 0xd9179834, 0xe94a5e36, 0x8ef64b9d, 0x7e36f89d, - 0x7d23f314, 0x6773be25, 0x9b43bf98, 0xa1f50fd7, 0xd9dde344, 0x39c4de89, - 0xa23d3174, 0x6520f788, 0xc4b64f6e, 0xdab5df7c, 0x7e81dfb7, 0x13e6de99, - 0xafa7f3ef, 0x6be2f184, 0xf54764dd, 0x59cde40d, 0x2d577908, 0xcb0c55d8, - 0xc1707cb9, 0xf44d0bbc, 0x5f8bdf11, 0x595d7547, 0xf64af480, 0xa93fa438, - 0xf844ea1d, 0xe8bdac02, 0xcd487abf, 0xc1fb87eb, 0xfdb18943, 0xb9e2b370, - 0x7593c4bf, 0xb09fc5a9, 0x3b53f54e, 0xde55a27d, 0x43fb13ac, 0xfe56a99f, - 0xcb83f630, 0xc59f7f44, 0x0f147e07, 0x6e729674, 0xa4cfc92a, 0x0fef636b, - 0xc216aad5, 0x47aa39f7, 0xe50ebe73, 0xee6f5c6b, 0x9d187721, 0x8c0d9c83, - 0x2ffe88d8, 0x3396be83, 0x8c42e72e, 0xbac693eb, 0x3ef4867e, 0x9d01f702, - 0x01f71ee8, 0x34c3cbcc, 0x5b949ba2, 0x587fe46c, 0x5eecf825, 0x046b5fc1, - 0x7c803d5f, 0x81df0235, 0x13fa51f6, 0x90eb4fc1, 0x12dd20ff, 0x78f5ce9f, - 0x6197bef1, 0x8c772cc7, 0xab1cf7a5, 0x0fda365d, 0x61ed7794, 0xfb05da17, - 0xf7e8ebc6, 0x7a59dd91, 0x59e58dc0, 0x43c03f0e, 0x91d2cc4a, 0x2f733e5e, - 0xe2abe8b8, 0xf4fd015b, 0x72a2b0ae, 0x949ea47f, 0x451fdec7, 0x9ef453a7, - 0xcb5faa80, 0x70fd3fd0, 0xe113a552, 0x8f3c70fc, 0xcfcdaad3, 0x3e03b826, - 0xe29bc5b6, 0x5f6752a5, 0x1f1ef5d5, 0x2f70ff76, 0x12ec12ef, 0x0c0d82f2, - 0xf92661b1, 0x7bde2b50, 0x1b10de64, 0xcb139269, 0xf432e787, 0x0f94f5eb, - 0xcdcbc8bd, 0x90ae5e5c, 0x434bcb62, 0x65e4377f, 0xd2315cb4, 0xb74d1795, - 0x5d54a7dc, 0x66f2463e, 0xc1ff6c64, 0xfcede3ef, 0xf3e66a1d, 0x2cf7a7e5, - 0xdefd7807, 0x83d42f0c, 0xf7c57f0c, 0x5a27ac62, 0xcab89e3e, 0xf40357d8, - 0xcd02d03e, 0xaff8f0fb, 0xfbad57dc, 0xd5b9e141, 0x9c140fa4, 0xa8b4a1cb, - 0x11f13a76, 0x9318d3c3, 0xfd7c7c9d, 0xdf883d0f, 0x7ce2b5e3, 0xc61abd7c, - 0x1b7da4b8, 0x0e607aef, 0xe3c175c0, 0xe38f9d32, 0x14d90d3d, 0xbcb2c2df, - 0xef1ba7a4, 0xdf0f1e23, 0x31c731ee, 0xe9d4fc14, 0x37bffd47, 0x1f582c7a, - 0x8d537fdb, 0x83bb44ff, 0x5da246f9, 0x675dfa01, 0x9fbff504, 0x18dde938, - 0x18da1f23, 0x8fc733ef, 0xf15be918, 0xdc21ced3, 0x33f78adf, 0xab9dd217, - 0xf4d79d0f, 0xdc7c17ce, 0xc733e863, 0x4547d273, 0x7dc0359c, 0xca7fc596, - 0x098f49cf, 0xf473187f, 0xca271e52, 0x7b94bdbd, 0xd3133c78, 0xd3ff9763, - 0x3d51a47e, 0xb821b4ec, 0xd3daf2fe, 0x2fa5deab, 0x6280f3d6, 0x60bdc711, - 0x79787c63, 0x2059be0c, 0x102f07ee, 0x7d065de7, 0xd0df7f15, 0x465d39b3, - 0xd4f4add3, 0x1fa74425, 0x5fc9541f, 0x87f4015b, 0xd4f4987a, 0x698f7a78, - 0x3d9713d9, 0xf9c00b78, 0x95324393, 0x10739d97, 0x87ffb65d, 0x3bfce28f, - 0xefd2ab7f, 0x70727c26, 0xb7ebc51a, 0xbb9ef78b, 0xedc5cef8, 0x5c5c1bda, - 0xbb9c14ae, 0x8bbbe897, 0x35f3c2ae, 0x7382dbe4, 0x565e900f, 0x4ebdef80, - 0x788f75c0, 0xe8229279, 0x1fb60277, 0xea1cbb92, 0x3e72b615, 0x15431361, - 0x10de8fe4, 0x0637bbef, 0xf2e0df3f, 0x0b45e25a, 0xff50d75b, 0x24c3f40c, - 0x02c85c53, 0x8507fbf1, 0xe584b878, 0x21a5887a, 0xd6f908df, 0x77d6ff4d, - 0xd69ddbb0, 0xc2e91a75, 0xb04e75ae, 0xebdd61d8, 0x73e72efc, 0xb6146fa1, - 0x7579f0e6, 0xe3e7e7ad, 0x7ba7ad63, 0x7da9131d, 0xf1ec627b, 0x1fe317ef, - 0x9bc22aab, 0xbc44ac5b, 0xbe105bb7, 0xd5f7c35d, 0xf627d60a, 0x2aeb4c91, - 0xc4b52dac, 0xe6d4152b, 0x857afbd3, 0xdbb5f3eb, 0x1753fb4c, 0x97fe425e, - 0xc6eb0d27, 0x2e6bfdcb, 0xaea8bc23, 0x7e913bbc, 0x7c553d8f, 0xec5e7bc7, - 0x84e9e397, 0x49531a16, 0x4f76eaf2, 0xf74dfbac, 0x56a9e347, 0x80ec09e0, - 0x0c9e132c, 0x3fb744fc, 0x8efcb9b6, 0xe21cf0f7, 0x509afe11, 0x0a2bf2ef, - 0xe1b1e97f, 0xd7a0a4f7, 0x040fa063, 0xdf7e082e, 0xf5cbc4b2, 0x6f813f0a, - 0x77c63e03, 0x08c2e7d0, 0x379127b7, 0x4e3fb193, 0x5b83e70f, 0x1e82f8f7, - 0xcf5ec526, 0x59eb5d6b, 0xc7a042ca, 0x3eb8d49c, 0xee7afbd1, 0x05c72162, - 0x4f8ba7ac, 0xfa7c2df3, 0x385b9ada, 0x9ffc0a9f, 0xd10f7fdc, 0xbc70b1f5, - 0x7a54e30f, 0x486bcf5b, 0xd062e307, 0x1b10b0c1, 0x8f7ffd95, 0xfe684e0e, - 0x3ee08f11, 0xee15fb02, 0xde4fc5d3, 0xbf3cc63f, 0xfd27e2b7, 0x9aa5f69e, - 0x0ea73b0b, 0xf41df64d, 0xfb277ed2, 0x434961aa, 0x633f815d, 0xa3cf12fb, - 0x6e9fa19f, 0xc6cfe245, 0x578bd2c4, 0xc72e0556, 0xaaea8bf3, 0x8fd1cba2, - 0x973d0aaa, 0xce9b9ea1, 0xd623177f, 0xcdcc7d7b, 0xaab2bbf1, 0x983fce92, - 0x94f4c423, 0xd80077ee, 0x47f24c89, 0x7eab2e2b, 0x1d01a9a6, 0x789adffd, - 0x025540a7, 0xd0b3d3ab, 0x1194945f, 0x1fefc132, 0xb2ee7e2e, 0x8ebf6d26, - 0xe8761ae7, 0x8e60fd1f, 0x8b59ca81, 0x6545ecff, 0x93c05f41, 0x1c731cf1, - 0x124bf06b, 0x46cf13f9, 0x5acf13f9, 0xf30491e6, 0x5b3b0afe, 0x1ce87871, - 0x8fc26152, 0x5f01e02c, 0x5bbb1f68, 0x1e5cebe7, 0x607d21ef, 0xb23645d5, - 0xff09d6eb, 0x2fd0cff4, 0xe851704d, 0xe0c301bc, 0xc096beb0, 0x73c4e1d7, - 0xaded190c, 0xf8dde508, 0x4f4c9762, 0x4f984a1f, 0xf3095e64, 0x1564597d, - 0x931d0fda, 0x3f20ef5a, 0xe69033a0, 0xd67ebc06, 0x84b0e5af, 0x817912e7, - 0xb5ce118b, 0x0bc32872, 0x77217ff5, 0xc1bd6066, 0x1f4ef450, 0xf7845e9e, - 0xf3a60212, 0x8eb421ce, 0x33dcbcee, 0x2552d17f, 0x6feffcea, 0x5fcb9b17, - 0xc62ffa71, 0xf93b5479, 0x1f4960fb, 0x57be7448, 0x94ee75dd, 0x64f2fb47, - 0xd123c737, 0x41d5d205, 0x559d37ae, 0xc87d09bc, 0xf3323d9f, 0x7c3ccb45, - 0xec22bc96, 0x53a03ad1, 0xe832a73c, 0xb7e29863, 0xaf0d1d21, 0x3c66ef81, - 0xfb77d0c6, 0xf079e8b8, 0x31b9fa98, 0xe897183f, 0xcb973e55, 0x7a28e3f7, - 0xf9f12dd8, 0xdced8a87, 0x1921646e, 0x20c73af1, 0xcf05653c, 0x8fe33227, - 0x8d77b5ec, 0x82b62773, 0x0b9e75e7, 0xb9cfc6de, 0xa733e7a3, 0x3c16eef9, - 0xdcd399ef, 0x7b9e3e6f, 0xf8ba29ce, 0xab774c43, 0x51e3fb9d, 0x2250fc5e, - 0xb7a6f67d, 0x21e3545e, 0x46e6f1dd, 0xae609f7a, 0x73bfef9b, 0xf88aa759, - 0xe35d300f, 0x5a6156e7, 0x27cc6ddf, 0xfa2a0df2, 0x84896e1d, 0x721ab86f, - 0xbe18beb7, 0xb9bdd51a, 0x425f3b07, 0xf41a05b4, 0x321b3a5c, 0x5ef935da, - 0xaede79e6, 0xf14e0e0b, 0x838a47fb, 0x6ebdd5d6, 0x58c1c107, 0x7c24d427, - 0xbc49c174, 0xa5c066cf, 0x37f1dd6b, 0xf8fe855f, 0x1cdce4de, 0x790fe8c7, - 0x579f3c9c, 0xc13e9c34, 0x0b939022, 0xb91ffedd, 0xb77afca1, 0xcb4c2eff, - 0x95839d1c, 0x5537c421, 0x0390af98, 0x1c00a517, 0xb8141a3e, 0xd1e11938, - 0xf482f7d2, 0x2e4ec3fe, 0x1ba70e0f, 0x1bab6d7a, 0xc8bd9be9, 0xf7e35af5, - 0x38ed5632, 0x008dff7e, 0xe55e8f9f, 0xcb95cdef, 0x22ee6bde, 0x62ccb2ff, - 0x7a4621d9, 0x1e0df858, 0x7bc4db76, 0xf39d7cd1, 0x79ef0e14, 0xcf74f18d, - 0xd952de6e, 0xbcfdbef2, 0x957e3ca5, 0xae632d29, 0x2b09d8b7, 0xecf75d04, - 0xd11afd07, 0x3a5fccfd, 0xd92dde99, 0xc893e9a9, 0xa738f1cf, 0xfd53f9b3, - 0x4ffdc632, 0x1f912d58, 0x6f51fc69, 0xe7e42b53, 0xc87d1387, 0x5ceff3ae, - 0x97ef899c, 0x3f70b454, 0x28bcaa67, 0x7d203fe3, 0xefdf3f68, 0xe108bf31, - 0x5d7bf2e4, 0x369af3a6, 0x474332b5, 0xe5d5be7a, 0x7f907947, 0xc45dffbd, - 0x30e7e1a7, 0x40e7ddf6, 0xce38c00f, 0x39bc5bfc, 0x0df91f48, 0x0ea53f4e, - 0x5c81c4a6, 0x039857cb, 0x298d54d3, 0x98e34c4e, 0xe5ecd303, 0x9daa7f42, - 0x2783fa45, 0xf7c34f27, 0x9f9bf3c4, 0x17db14fc, 0x927d912a, 0x9bf29e89, - 0xee82fd5f, 0x28f3f9c3, 0x5b5bf74e, 0x39dd8b34, 0xff9ac1ba, 0x9f359376, - 0x33e6b111, 0x03f35a0f, 0x7d266d70, 0x1e1eff73, 0x9a7a529f, 0x1e7defdf, - 0x3c22a060, 0x3e49d9b6, 0xce6d294e, 0xd38778c6, 0x586dbb4f, 0xdceffbbe, - 0xeadceeee, 0xf72577a4, 0xe2c717bd, 0x6a1df092, 0x3f2c46e7, 0x8d90d71d, - 0x4fa845fe, 0xbbb04b71, 0x71bb408e, 0xbd06a5e7, 0x69be2986, 0xfdf83fe7, - 0xf6adce94, 0x9c51c630, 0xd3e4f5de, 0xb7a79f48, 0xec7d200e, 0xc3642979, - 0x70f7437e, 0xf3884ffc, 0xe954e458, 0x7e3dab16, 0x1d01e842, 0xe879b527, - 0xd6b8ba17, 0xc24beeba, 0xa8a77cd6, 0x7d331b7f, 0x10f8c74f, 0xdc34aaef, - 0x7ec53767, 0xc173fdbf, 0xa53d4f17, 0x8b2b7419, 0x37991ef7, 0xe2befba5, - 0xdb73eeee, 0x8e800325, 0x4316114a, 0x4697bfba, 0x0f85db8d, 0x38927fd1, - 0xadfceb2f, 0x5539f04c, 0xef896455, 0xaafbd2e8, 0x4d53697c, 0xed4151fb, - 0xd27c94be, 0xdca5f757, 0xca67da66, 0xb9481eb6, 0xdb6bfa19, 0xebefd0a2, - 0xe279cd95, 0xf8490981, 0xf9c06e5d, 0xe7fa3962, 0xf25e1ada, 0x8bd03d60, - 0xbde39ac7, 0xa5c76b0a, 0xe9f1354d, 0x834ba5d7, 0x0e74ca9f, 0x5a72e79f, - 0x461ef172, 0x1dff2d69, 0x1b86d2be, 0xe11abbae, 0x4fdf9ebe, 0x9e5856cf, - 0xb653fc0c, 0x8fef86fd, 0xc7c1ef86, 0x3e70f9c6, 0x2d24f8d9, 0x3fadbbde, - 0xee76f743, 0x44ff71b5, 0x7b465c34, 0xfdef7e38, 0xe508ab81, 0xa2f7f412, - 0x3fb52c6d, 0xe47d0368, 0x6bd0e4c4, 0xd3954337, 0x570fe1ac, 0x95965c53, - 0x253e809e, 0x373ab7d4, 0xf48dbe4b, 0xb5f67975, 0x97fb5aa8, 0x943a3c51, - 0x8a37b4c7, 0xa27ed6c3, 0x47a57cf1, 0x68f77e32, 0xa25e99a4, 0x119df5eb, - 0x2ab7dfa2, 0xcd720a5b, 0x1d97efa4, 0xd878a1ad, 0x19c871e8, 0xc13b8a68, - 0x7c4bd1fd, 0x027a14ec, 0x22d91c93, 0xcf287c5e, 0x48a7bbd3, 0xa5104097, - 0x5ea9b297, 0x6cb5eb84, 0x4bcfa63a, 0x99640791, 0x33f203cb, 0x79278b6d, - 0x3eb7a6d0, 0xa3a473f1, 0x1e74d1fa, 0xefdc5fd6, 0xe846f36e, 0x77e358bd, - 0x9e74da71, 0x5276692f, 0x8fe9d53c, 0xcb979234, 0xeb138e30, 0xd9b4ed3f, - 0xbd3b5f40, 0x8c64efbd, 0xe06b6e0b, 0x6a9f8aef, 0xfb593be8, 0x9a37fd8a, - 0xf17d8def, 0xdf13fe08, 0x8bf8f54f, 0xacdfb83d, 0xa9d371e0, 0x2a332b7d, - 0x68c9e063, 0x6655a497, 0x79d2bda0, 0x91b7cbab, 0x0ae953eb, 0xc8d3ddf9, - 0xfc2f92af, 0x79e9f749, 0xbea07877, 0xe1faea1b, 0xe5073eff, 0xfc77e88d, - 0xa1ddf640, 0x1f3eed0f, 0xa015905f, 0x03f4e3fb, 0x7cfe3036, 0xa0144585, - 0xafb8f9b7, 0xc93ca18c, 0x25ebf9cf, 0xb05c238a, 0x7c1ebac6, 0x1fbcdae7, - 0x292fe116, 0xb0b8c50e, 0xd68b4a06, 0x718bcb5b, 0xbc50f0ff, 0x94cbc517, - 0x19cb59d4, 0xad1f908b, 0x7b4bfeac, 0xca7db82c, 0x6bf9f58c, 0xa3b9163c, - 0x50f9dc92, 0x95f5a3ce, 0xd20037a2, 0x1cfec49b, 0x6d2733bc, 0x4b1da401, - 0xc82da427, 0x7cee7bc4, 0x8ed3231f, 0x8fbf98f8, 0x45953a57, 0x7177f106, - 0xa58fee18, 0x346452cd, 0xe42c1de6, 0xe3bfcb19, 0x6eb820fb, 0x63313df3, - 0xf35eb8dd, 0xc726f677, 0x10cf71ab, 0x2f2e6bd7, 0xab287013, 0x3afc5bb7, - 0x90a5ea13, 0x7f78dbfb, 0x55da95a9, 0xb7697e34, 0x5ff62bf4, 0x1399b7d8, - 0x68a135f0, 0x798b8c83, 0x878e4ba8, 0x0f75892f, 0xdf80b0e5, 0xf4143743, - 0x107d7e43, 0x02fecff5, 0x9f2439c0, 0x45809f84, 0x5c5e301c, 0xca9e5766, - 0xfcf397b3, 0x8ae04f3e, 0xaf6081da, 0x873a01a9, 0xbde72f9a, 0x471bf78c, - 0x425e0626, 0xf9b7ccbc, 0xb7c42b07, 0x17e411fe, 0xf0e1ca5d, 0x4bcad8f0, - 0xc5d9632a, 0x933fbf02, 0x3e5ce81a, 0xa3ef8bb4, 0xd54eacee, 0x8bfef7ec, - 0xfb094790, 0x4f5ee95b, 0xee890ee7, 0x1d223f13, 0x8fb6fba1, 0x6865e95c, - 0x9e01a7c7, 0x223eee50, 0x5ef815b1, 0xace3565e, 0x9e212f45, 0x787ce2b3, - 0x38de5fde, 0xd1772e49, 0x15beb9fa, 0xcf01b95f, 0x8de75283, 0x0e748b1c, - 0x2d779eeb, 0xe3d0ff7c, 0xb9faf1a5, 0x96d3de38, 0x8f17d287, 0x16f3f1c2, - 0x387c84bd, 0xa1ee8e3a, 0xdcac02a7, 0x8d5d287d, 0xcb1a547a, 0x60fa87d8, - 0x58ef0cda, 0xe43fb9f4, 0xdb24e3e1, 0x50b379e4, 0xf3cb1bcf, 0xf92c7e7d, - 0xae111237, 0xed5271a5, 0x17ce3a6c, 0xe85ea3bf, 0xcb823f40, 0x9529ef84, - 0xea7e3819, 0x69269e50, 0x3c0f8a11, 0x99bde064, 0xd12de9c7, 0x25e9c919, - 0x454a4c5f, 0x1b50ee3b, 0xbf20d418, 0xec340d0e, 0xf48b88cc, 0x792361f0, - 0x2df7617d, 0x5ff7e0c9, 0xfa1b0692, 0xa1d7af0f, 0x513213fa, 0xf5c1beae, - 0x7e5c4ff1, 0xa65f57f2, 0x4fbf8ec5, 0x0a78e048, 0x61638b9e, 0x3838ff93, - 0x13d233fb, 0x2c3ce783, 0xf027da6c, 0x1c734dbd, 0x7ed15977, 0x72841dfa, - 0x01f742d6, 0x71ac1bca, 0xc5c597e7, 0xf3a0d71e, 0x0b1b39e0, 0x1e3225f5, - 0x21d7f688, 0xc2d573a9, 0x4b17ba24, 0x73c13be7, 0xc6990b1a, 0x63eb9e0f, - 0x33cd77cd, 0xaee9fa85, 0x9af5acc7, 0x2c7aa73e, 0xe383d5a7, 0xb4adebb4, - 0x29cf048f, 0x6fd8ced4, 0x90b6c23a, 0xeedcfc0a, 0xe21de5e5, 0x6fa8cf3c, - 0x5b3ed7f4, 0xf8def713, 0x556de8bb, 0x2e007820, 0x219f368f, 0xf359747f, - 0x418b823e, 0x89f0dd0f, 0x7c132167, 0x225baa52, 0x69ede036, 0x7bb86e0f, - 0xc990d814, 0x871f05fb, 0x9feddd36, 0xbbf8e508, 0x8ebe260f, 0x73e2eacf, - 0xd90f3312, 0x42172e64, 0x9d4f7775, 0xfa8bca68, 0x9b43ed5d, 0x340a98af, - 0xb78a3595, 0x27c1e6bf, 0x4e4e595e, 0xdf111a8b, 0xcf3839df, 0xa23bca6d, - 0x8fc82ef2, 0xa8f5e536, 0xf2a8a4f2, 0x40fca8b4, 0x1dcdbf5e, 0x40fb2c19, - 0xd4f83fde, 0x9efbf815, 0x7322fd6d, 0x358f05f1, 0xf02bb6f2, 0xb3cb7cf7, - 0x56d3eff8, 0xc93e4b34, 0xba2b3f24, 0xb55bf3ce, 0x0e10a3f9, 0x1ca32f2d, - 0x74926b28, 0x0d5debd4, 0xc79423db, 0xbb535e76, 0x963f6e06, 0x76a11c35, - 0xd23ff6bd, 0xef7c7c46, 0xdea9f7c8, 0xd89fcef9, 0x5befeb0c, 0x751e76f5, - 0x4e2c0a44, 0x7f7eee48, 0xdbfb6dbd, 0x0a2fbfdd, 0xf9fbdbdf, 0x8d1c900f, - 0xc41e07ba, 0xf9bab8f9, 0xbde380c4, 0x7bd2cf23, 0xdd1c7fb4, 0x03aa16fc, - 0x2cce4bf1, 0x9fdda053, 0x438f8fcb, 0xb4df0b7d, 0x67e37dc5, 0xdc12f852, - 0x81651e8f, 0x5bdc704b, 0xc3ef87cb, 0xac384c9f, 0xef863eb6, 0xf0786f95, - 0x98142be5, 0xeb7761df, 0xb709fc20, 0xf06f094d, 0x7f2b727c, 0x1dff4551, - 0xa0f0e7e1, 0xc83641d6, 0xa6c0993f, 0xeb787e53, 0x3d7f9863, 0x3faf04e1, - 0xac9075ba, 0xf27209a3, 0xdf90a98a, 0xf7e6c7ac, 0x37ae04da, 0x369bf31b, - 0x8453ffdc, 0xfbe32b0b, 0x76335e0d, 0x5b9d3c80, 0x66db6a72, 0x1fdcc780, - 0xdb9c93c5, 0x55dd76dc, 0x50870479, 0xa611c61e, 0x7ed3780a, 0x215d7248, - 0xee1fa27d, 0xf1ba7d81, 0xe2dc1ee9, 0xd2e2fda5, 0x37a8edca, 0x451dcea4, - 0xc7a145fb, 0xddc9e92f, 0x52193869, 0x3ae92fa8, 0x8db2eb97, 0xef5223e2, - 0xf51e9372, 0x033df8a0, 0x0fa23be0, 0x36cbc097, 0x096d9eb1, 0x80f6bfdc, - 0xf3f51a67, 0xc47fe49e, 0x42ca6321, 0xc5a7f24e, 0xf372be91, 0x202b9006, - 0x7989d7d7, 0x097b5baf, 0x466e29f9, 0xfc28f13f, 0x67d7efee, 0xbffeb754, - 0xaef2032e, 0xdd6ebb6e, 0xf33f7f2c, 0x0dbaf6b9, 0x5b90dcbc, 0x7b79d2eb, - 0xad4abf63, 0x3ea4e3e6, 0x5c46c978, 0x28c2bc47, 0xece17b7e, 0xd1971b11, - 0xad2d7ffe, 0xfdfdf99f, 0x5a3f0ed0, 0x7a86c43c, 0xc29f81a9, 0x1257fee1, - 0x89373d60, 0xf035efdf, 0xb74f8c64, 0x907f51e2, 0x3b407f41, 0xeb403135, - 0x0c627d07, 0xfae06e0f, 0x3316d204, 0xad2997c1, 0xfffbf0e3, 0xfdb53820, - 0x4ff4e02b, 0xc947779f, 0x0c379021, 0x7a5f2ffb, 0xedff72dc, 0x23d1013f, - 0x8000702a, 0x00008000, 0x00088b1f, 0x00000000, 0x7dc5ff00, 0xd554780b, - 0x733ef0b5, 0x9992bcce, 0x924c2664, 0x84e3c849, 0x71100840, 0xf0444312, - 0x51888431, 0xd4503b69, 0x20717ad8, 0x9926023c, 0x4b62d5a8, 0x79120cff, - 0x22341809, 0x0281c150, 0x06f55bc5, 0x701a8c45, 0xaf7a8a44, 0xb7ad8ef6, - 0xff7f6c57, 0x4a8f8808, 0xd2f5a232, 0x5ad7fd97, 0xce64ef7b, 0xb6b4a924, - 0xdc3ef9bd, 0xd9cfb3ee, 0xd7b5ed7b, 0xf6b5af6b, 0x4cf5a61e, 0xd8c05c0a, - 0xce6a2566, 0x7c2c64ae, 0x61edf148, 0x67cf07f0, 0xf7fb193b, 0x95d5a0b4, - 0xf19fd8c9, 0xe6c60aef, 0x2729bf7e, 0x8ded0658, 0x61cb1823, 0xcfbbf52c, - 0xd500ded4, 0x7a3f4bb9, 0x3f7c0f7c, 0x8ca97bf7, 0x43ef03e9, 0xf7c18c8f, - 0x5b6dbcef, 0xd2842ecf, 0x793519d2, 0xf986bca0, 0xef7bc056, 0x27435898, - 0xbe0ef7f4, 0x5563097a, 0x35e5bbdf, 0xdbb19136, 0x93632a5d, 0xf8ab5b18, - 0x258a9873, 0xbbe0db0b, 0x644b2cf0, 0x7d63114f, 0x0cd85311, 0x23b875fd, - 0xb8c1175b, 0xf995d71d, 0x1f5fd0c2, 0xef867e63, 0xf7a54b2d, 0x4c3ddc3a, - 0x744bf6c3, 0x0ec24017, 0x19faa17e, 0x5a37e3d4, 0x7814bb22, 0x76c2ce5e, - 0x3e325f6c, 0xf3fa8612, 0x7f7d0e30, 0x0f644a63, 0x8f82cfb6, 0xa371dea0, - 0xfe861237, 0x47622cec, 0xfa763a78, 0x8c1c3273, 0x05acaae5, 0x8228efe1, - 0x2b59943a, 0x0701cdd9, 0x713fcfe2, 0x0f007396, 0x6899775f, 0x3d95a93e, - 0xf437ff4f, 0x7ddbd6c7, 0xe1b0a063, 0xcf6f58ab, 0x3b997826, 0x66f88558, - 0xb803fc1a, 0x89c81fea, 0xcce7c3ac, 0xb1eb8557, 0x479fe9da, 0x5520fff0, - 0xb61ff847, 0x0ab635b3, 0x66d61528, 0x0bfc00cb, 0x43fb5878, 0x37630c00, - 0x978000e3, 0xd670d7ff, 0x2bf3c3a9, 0x07ad0a5d, 0x556df9fc, 0xbc67cd8c, - 0xd4f2fe7d, 0x58899577, 0x1a6b51aa, 0xa5735b3c, 0xef46c7bf, 0xe28f3fb1, - 0x0bfa0da5, 0x25b7f132, 0x09ba44ee, 0xd86977e2, 0xba9defff, 0xfdf0eb03, - 0xf8765c44, 0xfbe074be, 0xf9a3173a, 0xfc3955cf, 0x475535ac, 0xc8fc4afc, - 0xd7c24eb2, 0x713f90fe, 0x724e393c, 0xfcbaf7bf, 0x00be2237, 0x0f74d1ef, - 0x75a545e2, 0x63d7864d, 0x43b06f89, 0xd556dcfb, 0x33e0377d, 0xf349ccb8, - 0x9cdef095, 0x158cbf1d, 0x74ffee0f, 0x8695736a, 0xe9c65ff3, 0x02b72d9d, - 0x62f112e2, 0x5d03a819, 0x63f1642c, 0xe7886526, 0x8445f45a, 0xc247517f, - 0x2fdff4f7, 0x49ef89ac, 0x92ba617e, 0x2ba0bf04, 0xdd70d15d, 0x375f0a82, - 0x373e258b, 0x6e183650, 0x82d5cf89, 0x245d24ee, 0xe2357be3, 0x7c60d27b, - 0xf93d2c7b, 0x99706fd8, 0xdc94f095, 0xfa11633f, 0xf03b21ee, 0x16ddd00f, - 0xdd7a2145, 0x646a5772, 0x3da7f225, 0x19f117be, 0xad157c3a, 0x1492ef77, - 0xdb2bc19d, 0x9441302c, 0x9c9d8733, 0x4a7a4b8f, 0x617a9f90, 0x9f587ece, - 0x9dd5d7de, 0xc1024561, 0xeaebf358, 0xdeffa42e, 0xfde6af67, 0x19d548ac, - 0x618843d4, 0xfe143718, 0xbc032b43, 0x2cc5349e, 0xe0175e34, 0xff09c257, - 0x435fe17a, 0xe8bc80c5, 0xbf1c06c3, 0x9807cb8b, 0xe71a12e1, 0x1d6c29db, - 0x526cdb8c, 0x6f6826fc, 0xb23e3a5e, 0x4361c392, 0x20146a3e, 0x9b589b35, - 0xf7c03152, 0x2513a6cd, 0x36f195b7, 0x85bbde0d, 0xf78175f1, 0x5f002a8e, - 0x4c7d6da3, 0xfa45ba45, 0xd8a5f687, 0xff80345e, 0xf9bff5e6, 0x7cdfc213, - 0x8d1748c0, 0xb1e7198f, 0x8a9e9134, 0xb524e806, 0xd589e392, 0x8018c8b0, - 0xa9ea29d7, 0x8a88b1b5, 0xcd565a78, 0x66e9024e, 0x8199e91e, 0xecace3f4, - 0x0ca1f364, 0x11fcc07d, 0xf74a7b80, 0xc24697ce, 0x58daeefb, 0xb4374e3e, - 0x4e8bb6ec, 0xbeb0345d, 0xba4bce12, 0x41cca937, 0x0077d1e3, 0x83bf7f8a, - 0xfb371bde, 0x6ef2c482, 0xa4d32efa, 0xe0f6bd12, 0xcd1be423, 0x38c0a39f, - 0x328c979b, 0x82a67ae1, 0xbcb9437c, 0xaeec7db0, 0x7f678415, 0x07b7ca09, - 0x09ce80d3, 0x942abe9f, 0xeaeea52f, 0xbfa0bb5f, 0xffd5dca7, 0x138e258d, - 0x47f4e270, 0xa648be90, 0x23bd64e7, 0x6e2ecbdf, 0x0c716f29, 0x17f01eff, - 0x35be2de1, 0x4d0fcb9d, 0xffa2faa1, 0x475cef30, 0x374469f0, 0x222f6db7, - 0xdac0dc79, 0x591ade89, 0xbbf482c4, 0x69c2c6c8, 0xe08b1740, 0x172874b5, - 0x3d32b16f, 0x4496fd61, 0x2146f58c, 0x31616e0f, 0x7d96fefa, 0x2c35ed49, - 0x26f684ea, 0x62a68b1b, 0x6f6c69d9, 0xef417166, 0x3e26b67f, 0xbe7c1d67, - 0x77758b37, 0x20d444d7, 0x1dab7bcc, 0xbe065774, 0x33eb4ed0, 0x5a4ef965, - 0x7f0af4cf, 0x4fa83dd1, 0x76fb355e, 0x27bedd01, 0xe7e24bd6, 0xbbf5575e, - 0xd514f788, 0xdf8ff344, 0x9cfc2563, 0xeb8dbd02, 0xdd9b9f7f, 0xdeca1b3c, - 0x7a3bdd56, 0x55c9a234, 0x1839db30, 0xb39eebcf, 0xb8dd2037, 0xb7c226dd, - 0x65cc7e7c, 0xddd57aa6, 0x522bff02, 0x088abb23, 0x9e9113dd, 0x7d4946aa, - 0x82ce26ca, 0x5666bbfa, 0xe6f509d7, 0xec411deb, 0x07ed07af, 0xb9b817a8, - 0x5b7028de, 0x2eb27e68, 0x06e92be7, 0x52fea1c6, 0x84a5e22e, 0xc85b8c63, - 0x7f89b641, 0xe6eff427, 0x493b2925, 0xafd3f6ff, 0x96fd1189, 0xd7882c05, - 0x795c84e7, 0x3695ca4e, 0x9a2b972b, 0xa832ee6b, 0x9941f73f, 0x95e01d6f, - 0x83de8295, 0x4a3f1bef, 0x5e9e91d1, 0xef5fe8f9, 0x9fb419fd, 0x5ba2c0fd, - 0xd2017da1, 0x73dbac18, 0x6047970a, 0x8fd4307f, 0x38f6c08d, 0xb1c1e36e, - 0xb41c7f64, 0xc846fb08, 0xe0b4c6cf, 0x4fd085d6, 0x3e9993e3, 0xbcf664a0, - 0x5ee8f239, 0xf7643f6c, 0x1b7e81ed, 0x1b5e3853, 0xdf491b9f, 0x4e0f613f, - 0x733cc377, 0x3c9f91ad, 0x05e37281, 0x677bd92b, 0xc2117459, 0xaed3b67f, - 0x70277be0, 0x4250e95e, 0xeaf3829b, 0x043d9276, 0x10b39a7c, 0x36b93bbe, - 0xe04bcf9b, 0x0986e4e9, 0xcd9b17c4, 0xb3f0bc7c, 0xc27fbd0a, 0x0391981c, - 0x974f13f5, 0x534056fb, 0xb512c05f, 0xee873d00, 0xbd5e76e3, 0x7881df49, - 0x09538762, 0xa11eb95e, 0x62678b8d, 0xf2e9687b, 0x1c7ca3af, 0xde51cf8e, - 0xd9b904b3, 0xc805e2cb, 0x461adb4f, 0x9f514675, 0x91f38f74, 0x585e655a, - 0x171ba07c, 0x9994f77f, 0xc87e35e3, 0xbe7cf44c, 0xb57ce3fd, 0x707fae2a, - 0x65c8109c, 0xe48ff926, 0x1d5d4272, 0xfec8ceaa, 0x2d973d0c, 0xfb633aec, - 0x1de0ceeb, 0xe6bfa06e, 0x9de7fffb, 0x38df8465, 0x9ed645c9, 0xca797c49, - 0x748b9fec, 0x5a89aeeb, 0xf3e827e6, 0xeaaf820d, 0x63fec2ad, 0x1f224b51, - 0x6aaaf6ca, 0x72cbdd23, 0x677fa0bd, 0xc1f7cb8c, 0x1fc126ed, 0x1ea2b4df, - 0x6641c29b, 0x1c47a885, 0xfd4ebfd8, 0x6a20f94f, 0xe17a87a9, 0x9165a8f2, - 0x004f9128, 0xcc1b51df, 0x2756d4fb, 0x03406fe7, 0x3268b3f6, 0x48b97d23, - 0x02b5fb05, 0x3d5deb9f, 0x9fa72eb0, 0xfafa7376, 0xf0056023, 0xf7898f3d, - 0x82ef60ac, 0x4da67b1c, 0x607ee289, 0x2eeb16de, 0xb5f2117b, 0x7ae2755f, - 0x8e48576e, 0x569b6bcd, 0x4bea15b2, 0xeb405c0f, 0xd399369f, 0x9b88d2e5, - 0x2114e2f4, 0x11adeb1f, 0x3fdfd90b, 0x01f21851, 0x74764ff4, 0x53947c23, - 0x280f1831, 0x10f40dd7, 0x5d83a849, 0xcb93a534, 0x9cf20655, 0x524bd825, - 0x671ca3de, 0x919ff649, 0x1f52c23e, 0xf4c7b971, 0x527b946c, 0x0aebdf2e, - 0xae49b974, 0xf5c6ce8d, 0x72e4f585, 0x7842bf73, 0xa42d626d, 0xe81ea44f, - 0x91e8571f, 0xeb986ad3, 0x2a26eb2b, 0xd117775f, 0x27594b78, 0x57a913e9, - 0xd783a386, 0x7e0e84bf, 0xed007486, 0xe8b01f8d, 0xe35e3065, 0x9a6d1672, - 0x44e74bc8, 0x4f5c8fd2, 0xc49eb8da, 0xf43ce532, 0x4c7eb265, 0x7ac987d6, - 0xf5c2db30, 0x69675c9d, 0xe74f64cf, 0xe594c076, 0xfcc19511, 0x3ff9a636, - 0x60349cce, 0xb2de84d7, 0xb10bf4d9, 0xe0a3601e, 0xd369c5bd, 0xf686ca6e, - 0xc8fcc690, 0x9780a957, 0xbb7cf09d, 0xb36b7bb0, 0x2d7bdd39, 0x5acd7e9c, - 0x703b9580, 0xcfb4625d, 0x1732678d, 0xe7c4a3d2, 0x577c2776, 0xfd71df81, - 0x8dbdffd4, 0x7c24a5b5, 0x9d9cfd5f, 0xcfe7eae4, 0xb256233a, 0x6e858247, - 0x57eb2fe8, 0x7b53b256, 0x3e92739f, 0xd0fa15ed, 0xd128f683, 0x5fae2acb, - 0x21275d71, 0x648f5535, 0x35cafb48, 0x4a045123, 0xcdc9acfb, 0xf6c1aced, - 0x8a2f6890, 0xcae9cf5d, 0xcfccfb4a, 0x62773ddd, 0x6861e01d, 0x588fff9f, - 0xe981d0e7, 0xe787dfe5, 0xc7c380a1, 0x472c1fb1, 0xdfaab57a, 0xf406deb9, - 0x1e5d4335, 0xd1e60bbf, 0xa170ef94, 0xfc29ab9e, 0x846f2ff5, 0xcc0787fa, - 0xbceb8acc, 0x1b1d7a67, 0x5dfcbc35, 0xe89f3112, 0x5b97e049, 0x4deb19f6, - 0xa87ac69d, 0xc82f58cb, 0x4f4e7a70, 0xfbe1d920, 0xd5b5d033, 0x4ec1f2da, - 0xbcfad780, 0xa7d1f495, 0x067160ee, 0xfc535bca, 0x5ad9e218, 0xf444f1f8, - 0x3fba846f, 0x02b4b051, 0x38cac4ed, 0x3faf91fe, 0x742bcfb7, 0x01b7810d, - 0x899b31fc, 0x3ad60cf0, 0x85ce492f, 0x2c789f04, 0x845f0ffe, 0x9d9a2ff9, - 0x9e9bbae2, 0xaa4e67f8, 0x60927b42, 0x572da164, 0x2dfb887f, 0xae096f78, - 0xf059e9ff, 0xb0d5c01e, 0x46c3eb85, 0xbe434b16, 0xd3bb066d, 0x477c4b06, - 0x5b875f06, 0x5155e2da, 0x8c8edff8, 0xa70871da, 0x802d27f6, 0xfb1ab1f4, - 0xaf93b04d, 0xe07ae0cd, 0xd7767d96, 0xdd1e0329, 0x2ba87a86, 0x912a75c7, - 0x61fc84ff, 0xb8968a79, 0x09577a1f, 0x6bf88b5e, 0xa658f5b2, 0xfc57f8c1, - 0xf79233e9, 0xa7cd978b, 0x5d80c47d, 0xb4f9256d, 0x3d20aef8, 0xdf2b697f, - 0x6ade9e17, 0xa7ef11d7, 0xe3fdf3b7, 0xc4473ce2, 0x857bff06, 0x8bdbdb9b, - 0x19453be1, 0xbc64c78c, 0x55f0ffbd, 0xf7a3a45e, 0xdc2f1f19, 0xf78fedc9, - 0x62af805d, 0xf7f60efe, 0xefd8177e, 0xaaf9e20a, 0x2e2e510f, 0xd0faaede, - 0x9c87604e, 0xbc598fe4, 0x0b71cafd, 0xa7dfd81d, 0x5fa1a623, 0xe895c768, - 0x02f7c289, 0x89d7ee11, 0xb5cf015d, 0x1d93171d, 0x95bb7477, 0xedb6e9c3, - 0xf15c79c5, 0x4af89527, 0xda20b133, 0xff161dc7, 0xfd67e438, 0x70333de1, - 0x959fde5d, 0x1ff7a26b, 0xf10b9857, 0x85965ee1, 0x5a2b17cf, 0x61b7f900, - 0x899992cb, 0x866a4ef6, 0xad35eb4a, 0x8f567970, 0x7ae9f883, 0xdb4da3d4, - 0xfc707f81, 0xf2ff6fd9, 0x3f224f46, 0x4cc55edd, 0xc3cbf609, 0xc27a235f, - 0x6be028bf, 0x57d7c0b1, 0xaa6b2be5, 0x12968be4, 0xef8ba394, 0x0d71296e, - 0xf3f45761, 0x0f9cc3c5, 0xb850cbef, 0xc32f20ff, 0x6e18cfb0, 0x3528e65f, - 0xf9b15e91, 0x940f7f98, 0xc62db0d9, 0x0c81f7fd, 0x640fda8d, 0xfb5f7b70, - 0x5efb6ddd, 0xcd4d7987, 0x80cf6e08, 0x97f3217a, 0x71ebbae3, 0xb1983557, - 0xbbb26288, 0x6e56c3d8, 0x8edc6ac7, 0xf6c99cde, 0x8fd84bae, 0x997f6277, - 0x62f61724, 0xffc7bd3f, 0xdaf10c78, 0x44f1f05c, 0xe7420fb4, 0x1fa0b33e, - 0x90add1cd, 0x02f8773c, 0xd425e90c, 0x282d8b3d, 0x21c3901b, 0xc913d71f, - 0x0653faf3, 0x3c84efdf, 0xfde7ea71, 0x3b7f9c11, 0xb73e9cdc, 0x3f214b2d, - 0xc44f36e4, 0xb5ff408e, 0xa5ed2a7c, 0x67efc225, 0x5f94fddb, 0x288efa45, - 0xd75831ae, 0x35f47f39, 0x30a88dcc, 0x8bbb87ce, 0x77d9dfc9, 0x854f9a60, - 0x1feec736, 0x788519ad, 0xf0fb32ea, 0x27af877d, 0xe1f7e70d, 0x386993ee, - 0x2add86bf, 0xf221bbcd, 0xb2c2d649, 0x33f0b901, 0xca3af825, 0x1c52e601, - 0x0f94be38, 0x34feee1f, 0xfb83816b, 0x567f480b, 0xa7978d0e, 0x8e7ed3dc, - 0x39715fdf, 0x1e8f975f, 0xee5046b7, 0xfd07647d, 0x3f6f2096, 0x777d7272, - 0xefee432a, 0xdf500b3a, 0x2a6fd7f4, 0xf89ca135, 0xdfcf8b8e, 0x402ce963, - 0x628dfc7e, 0x1ae967ec, 0x6c808b13, 0x5006b25f, 0xa3e8f203, 0x40299f47, - 0x9ee1ff79, 0x27e60a67, 0x9dfc97c0, 0x78e57b2c, 0xfd266fc2, 0x344b1ea8, - 0xef9bc70f, 0xe57f72b3, 0xf9547e30, 0xfdc2db3e, 0xab3e7da1, 0xbf28748e, - 0xf1486beb, 0xc7db7da3, 0xe6ff246c, 0xacbf0b77, 0x83da3fdf, 0x7df918fb, - 0x1e15ff52, 0x974a4f4e, 0xd483fe42, 0xe3c938b2, 0x7bde59bf, 0xe4133d60, - 0xbff3ac3d, 0xd9345f21, 0x3246c7e2, 0xe20b0fa2, 0xd0ecd2cd, 0xad653f50, - 0xbf15f4e4, 0x2afb44c3, 0x81d7ae4b, 0x928aecf2, 0x30133694, 0x6d2527a2, - 0xf201c622, 0xfde94b73, 0xfba73570, 0x7f231670, 0x516b0e5b, 0xb8bb5e48, - 0x326f3edf, 0xea83ad73, 0x9edc11ac, 0x16df32f1, 0x5dd698b5, 0xc490ff41, - 0x480bd487, 0x3f1f283f, 0x3f446c52, 0x7642b74a, 0x9cea6aa7, 0x470efd8b, - 0xc847134f, 0xa7a73ffd, 0x893ffafe, 0x188f269e, 0x3a829e8e, 0x36d793d1, - 0x3f093d34, 0xcfbf79f1, 0xbfdc01c2, 0xdd7c0b66, 0xfc4ee427, 0x9bf49b0e, - 0x99df382b, 0x3699bfa2, 0xfd455447, 0x9c7f33e1, 0x187dffe8, 0x27dc5fec, - 0x0efda0e5, 0xf395c8e5, 0x16375a74, 0x417f41eb, 0xd236c5ea, 0x629af78f, - 0x64af6845, 0x8fd96f8f, 0xb73d9174, 0xed2562ac, 0xa8dcf2ff, 0x92b7500f, - 0x7559741f, 0x0488d4e0, 0xdf10e17b, 0xe5df34cf, 0xbbd3e7a7, 0x1a107db9, - 0x387b216d, 0x7184a5d4, 0x96039b9d, 0x6b41da08, 0x095fee15, 0x3cebb06f, - 0xa0afa3ee, 0x740fcfb8, 0x488a171e, 0x8ecf6fff, 0x35bd23ef, 0x91efc838, - 0xf83a3f1c, 0x1fc7ca85, 0x8efc68c3, 0xeaaf1e72, 0xfee75ab8, 0x1d7eb115, - 0x6e39fcb3, 0x18d607b4, 0x85c659f9, 0x18809cfa, 0x7afe6f18, 0xae43ad3b, - 0xd2ccf1ca, 0x0cff5c6d, 0x67e40b96, 0x162c9ace, 0xfa6fc446, 0x05241cf9, - 0xbb4573d6, 0xcb39378c, 0x79684502, 0xb7e9bbbf, 0xbd00a4af, 0x8e9fa166, - 0x68c2ca6f, 0x987f93f7, 0xfc7dc9d7, 0xc90009a0, 0x5cffd6c5, 0x42697357, - 0xf03fbc5d, 0x6b6bdcfd, 0xf6ef48f2, 0xa0d823b7, 0x6fdd658f, 0x351e31d7, - 0xbd81aed0, 0xf852eb6b, 0xb5c761f7, 0x3c068e57, 0xfffc7228, 0x7f47eb5c, - 0xc6199da1, 0x4b4f844b, 0xfd0cdfea, 0x7ef9743b, 0x784af6bc, 0x590ac1e1, - 0x1fad66bf, 0x6ccfbbe0, 0x2a508fec, 0x1c8ac7be, 0x6dacd6ef, 0x0de7d6eb, - 0x276005d8, 0x39911aec, 0x7eac1f60, 0x85fb667b, 0xebaa5630, 0x5dea0b53, - 0x1e43e7a9, 0x648fec85, 0xe4203d7e, 0x572cdfc3, 0xf47641f5, 0x57241181, - 0x4b20667b, 0xe483fec2, 0x80796876, 0xf6073da1, 0xdbc21748, 0xd3e3fc7b, - 0xef7b422f, 0x1b1fdfec, 0xb77be3a9, 0x37bb45ce, 0xba234e74, 0x2353ed0d, - 0x4dadd00a, 0x71e80bf0, 0x7a480b8a, 0x7412ea5a, 0x8c330eea, 0x521c7473, - 0xbe898526, 0x83ae0a5a, 0xf8f7ccb5, 0xe438425f, 0xde7932be, 0xf7c11ebf, - 0xead2a10f, 0xffd825ad, 0x9da1856e, 0x44f4aeb0, 0x37da02d6, 0x30b59bbd, - 0x5d25bbe1, 0x973e120f, 0x890f33ec, 0xe08f5fc7, 0x67e6de71, 0xdca3f69f, - 0x90a228f8, 0x22d0684c, 0xbd40a76b, 0x9684c1a1, 0xcc8cab20, 0x1ce291bb, - 0x06361675, 0xed0477e6, 0xdf638426, 0x7053c337, 0x814ff0de, 0x8b02db47, - 0xab6e9f48, 0x4e2839b3, 0x56ff3a54, 0xc52b83c2, 0x5758788f, 0xe3839d5a, - 0xe19acf34, 0xd808f8a2, 0x7cded871, 0x2fc8b7d7, 0xd75ae124, 0x3b45ae65, - 0xb9ec0aa7, 0xfcee00a7, 0x7d6a6b8c, 0xd523c7c0, 0x3bb7e5fd, 0xb43e5e30, - 0x266eff1c, 0x25368ba7, 0x2546fe10, 0xa25941f9, 0x8bb0b35f, 0x8d9f8ddb, - 0x2be218b0, 0xf6e08d9f, 0xd8e1a5ec, 0xc39f2474, 0xda2a4f5a, 0xffe621d3, - 0x2ccff704, 0xd0f7d0e0, 0xe479713a, 0x3fc9d569, 0xdcf4f366, 0x5fb6217b, - 0x85fed1aa, 0xe00f3d69, 0x3d6bbdb8, 0xf04c75be, 0x2aefd601, 0xbd4f7da3, - 0x3278a827, 0x7d70bcf9, 0xaabd9f7b, 0xd288fd1c, 0xa8fb5aee, 0x5ae6f49d, - 0x2d7f7ea7, 0x69dfd3ca, 0x16c01f3c, 0x7e874d8f, 0x833efe96, 0x8f6b5dc6, - 0x0ff5c5ac, 0xbda954ef, 0x607411d8, 0xb9be4bbf, 0x2bd22265, 0x504a4473, - 0xed3d9a8f, 0xb618e90c, 0xb12fe42b, 0xe30c0279, 0xf3c3d3c4, 0x45f50534, - 0x1d333d92, 0x5fb455fd, 0xb6bf90f1, 0x18c7f05a, 0x36d382a0, 0x3fb68562, - 0x6fb0188f, 0x1ce3f95e, 0xbb4a1f0d, 0xfee364c7, 0x14ba9af3, 0x5b2df686, - 0x42663f15, 0xc627bd7f, 0xea6e0ed0, 0xa69c6854, 0xb82d27d2, 0x93a5b96f, - 0xec4877f3, 0x057f0033, 0xf18c5768, 0xa07b0aa4, 0x5839fb8d, 0xc448d8ec, - 0x3d7c63f3, 0x12f78319, 0xad8cabfc, 0xf440f2e0, 0x86711167, 0x0257e126, - 0x3eed484d, 0xef5bb48f, 0xf3b7fd16, 0x59bb8c52, 0xc455f989, 0xf062b96b, - 0x2af2cb87, 0x91fa7df1, 0xdfe40cf8, 0xfa17d038, 0xb32ab697, 0xcc29fd6e, - 0xf1a4eb6f, 0xbcc1343e, 0x056a4e40, 0x0452073e, 0x7d7657bc, 0x86e90332, - 0xd7e232d5, 0x6a69aee6, 0x6fc78393, 0x4ec85ed0, 0xed89d96d, 0x929737d9, - 0xc8f8c67e, 0x35fe786c, 0x1cb3e70f, 0x79d7f707, 0x61170eef, 0x48fd33bc, - 0xe29fd6e0, 0x90a417f8, 0xd61b35bf, 0xe54199c6, 0x796ff41a, 0xa88bf959, - 0xf533bd7f, 0xc647840a, 0x382e30f5, 0x38e48cab, 0x8a7c33d5, 0x3794177f, - 0x0e34dc78, 0x116aefec, 0x711e7c5e, 0xd119c40c, 0x62e3876f, 0xdecb0f1c, - 0x7e46a89c, 0x7be7d07e, 0xacbb4e90, 0xccd7c42e, 0x42df97ae, 0xc6d33b7d, - 0x9aee293a, 0xd3c4b764, 0x3a4419be, 0x7a733bed, 0xd7083dc7, 0x947d0775, - 0x8f6492cf, 0xb739715c, 0x93da3fcb, 0xec3f23aa, 0xec1b7212, 0x797f1e47, - 0x9323ef9c, 0xf6efc8ed, 0x23b72faf, 0x777febfb, 0x17c3923b, 0x28f3c3de, - 0x890f7ca4, 0xc35f5f7d, 0x5fd434d9, 0xaed23d2b, 0xd8f7ca4d, 0xba3df22d, - 0xd0f7ce87, 0x0ff8f276, 0xee494186, 0xae222dba, 0x43cef7e5, 0x84bb87ff, - 0x7b2bc0e4, 0x3748c353, 0x64ed3b67, 0x4b6e6997, 0x7b6ae114, 0x3cc11ada, - 0xe0453688, 0x578890eb, 0x2c1c4459, 0x834744a3, 0x4025a0e2, 0xa4fc3f72, - 0xd2abc799, 0x85ee8f22, 0x1ce1e37a, 0xd462cf11, 0x54d9f87f, 0x8a6377c2, - 0x37fd8e9e, 0x8608fbfe, 0x183eaa71, 0x09f9d70f, 0x87bb707b, 0x7fbc5ae2, - 0xe75582f6, 0x8968b3f1, 0x33b0f01b, 0x93bfedc2, 0x05a8a6a5, 0x8993bde6, - 0x32f59f3c, 0xd9e7c5ae, 0x8f2461b7, 0x8231a0cb, 0xdcb5b2fb, 0xe32f545f, - 0x1fb98755, 0xa5c45eae, 0xf45ece4e, 0xb458a608, 0xb8b52d29, 0xdd7cfb4f, - 0xdf9ff234, 0x2a2cff79, 0xfd18d7eb, 0x3fd08bfd, 0x3f103c5f, 0xf9f77e96, - 0xf6e167cc, 0xd0ff80f3, 0xbe8cf604, 0xfd46ab46, 0x775cc459, 0xc3d03ea3, - 0x43177ab0, 0x1a2506d9, 0x19600af1, 0x7ad6d3de, 0x57bd7052, 0x6f4899b7, - 0x7e4cdb85, 0xcbd24f7c, 0x67ae1eab, 0xbd70f5df, 0xe08ea803, 0x336cb238, - 0xe883788b, 0x4533056f, 0xbc2934b1, 0x6ad2ed5c, 0xb2dfd287, 0x8b7336bf, - 0xcdda1a6d, 0x77f226f9, 0xd7f16e7f, 0xa338bf91, 0xcda9d684, 0x96a6b2d9, - 0x7d2f13b7, 0xa8078f6e, 0x1b8d32fd, 0x40cf4c96, 0x8782fa79, 0xf19217c7, - 0x58ddb0b6, 0x2cc38e4f, 0xf5eb1889, 0xa736382c, 0x120dc798, 0xf420bf9f, - 0x8aebe7c4, 0x167dbe04, 0xfe72bb94, 0xde38f22b, 0x1cbcf94c, 0x875d5f95, - 0xe30a3074, 0x725845ca, 0x84cc2abf, 0x99751fe0, 0x48fa2147, 0xcdcdb782, - 0x96bc29e9, 0x5aff21fb, 0xfee193f8, 0xf82593d0, 0xb8c5efd8, 0x42cbbd65, - 0xf5f3e871, 0x1a64a497, 0xf5fdb7f7, 0x96feffbf, 0xaad7e7ef, 0x45c6bf22, - 0x8bbe6972, 0xe2a4e5cf, 0xe7c51bdb, 0x701fb00e, 0x0ad56b1e, 0xbfd32394, - 0x3479a0e9, 0x8239061f, 0x3de5ac71, 0x9bd7a805, 0x304a7bab, 0x5f8c935e, - 0xf2935684, 0xef9bde0c, 0xda08fd81, 0xf18c6b0d, 0x55f1c1b8, 0x2666617f, - 0xee4e7bee, 0xd7f5197f, 0x2fe93b7e, 0xad17bff8, 0x16cfffc8, 0x388b5c91, - 0x2e316383, 0xee894a14, 0xda1171f8, 0x6a8edc31, 0x44eeb6ea, 0x5b7e713b, - 0xff0f7c42, 0xef18deb3, 0xc8326b63, 0x8c3aceef, 0x4e1e1bcf, 0xfc506efa, - 0x65d69daf, 0x0e3825b3, 0x10f41df9, 0x599c1de5, 0xbeb86262, 0x116faaf5, - 0x7633a92a, 0xc67e7da3, 0x466bd7c9, 0x3e3fd4a6, 0xebfabfb2, 0x57d9d683, - 0x6f5ceb82, 0x7ec4c162, 0x619d709a, 0x3ac51b7d, 0xe2fa799f, 0x8fe75c12, - 0x825c5ff7, 0xdcd9bceb, 0x29be47ee, 0x41af0775, 0x32ba9cfc, 0xe615f640, - 0x9d1f20ef, 0x94de3d2f, 0xfd378f44, 0x2eb1e8e3, 0x59321f31, 0xe3f4363f, - 0x3d1fa8cb, 0xe50f3d16, 0xf59b7cc1, 0xfc49ea2f, 0x679fd21b, 0xe3ff92b3, - 0xdd3f1ff0, 0xdd18f948, 0xb227d92a, 0xb05ac3bf, 0xc3a3ed18, 0x617d796f, - 0xd3fef865, 0xb5e5fd85, 0x59fa30b1, 0xda40bee4, 0x78f2c997, 0x03cf98b9, - 0x8cdffe99, 0x3ce21bf8, 0x20dc7fd2, 0x3e45b1de, 0x6eef76e5, 0xc7fdc7c5, - 0x6e4fe49d, 0x85cf343e, 0x220fe2fe, 0xfcdc7fdc, 0x8ff93974, 0x8a5e4497, - 0xeb193e62, 0x1fb85c56, 0xddfbb259, 0x9003cc34, 0xe7d85efb, 0xf9499fde, - 0xeffdc635, 0x69939107, 0x70003798, 0xa7708fbf, 0xa416e27a, 0xffd866fb, - 0xb360de61, 0xfd863f16, 0xd9187b36, 0xc65d9505, 0xef8ca0fd, 0x48580b6e, - 0x56eb6eee, 0xb3af2822, 0x3ca2c12c, 0xcf2c6bd4, 0x80753a75, 0xfe9922cf, - 0x077e9017, 0x5dfeeae2, 0xa7fe9758, 0x44e9ad9e, 0xe6663dbf, 0xdb3ca177, - 0x4cf214ea, 0xdbf6f923, 0x7591dd87, 0x6fc37609, 0x584edc23, 0x34c1f322, - 0xbd60d516, 0x1ff1cd16, 0x7946f5c7, 0xf7924d1f, 0xaf197589, 0x494585bf, - 0x9eb1352f, 0xc4b0bcfe, 0xf9e392f7, 0xf4370718, 0x75ca5ac3, 0xe4dd93f4, - 0xab9c51f0, 0x6356cfeb, 0x9bef987b, 0x55961f81, 0x5cafd00c, 0xcdbf4907, - 0x6a1d1fc2, 0xe90ab138, 0xb8a5d437, 0xe8dd7f70, 0x08dbf4e3, 0x9bcc2ffb, - 0xd677e64d, 0x1d13cc69, 0xdd7fff8e, 0xff9c77cf, 0x9cac3d7f, 0x5bf8c7fa, - 0x3f97efdf, 0xfce5ef9c, 0x7fbeffa5, 0xe70add9e, 0x2579a4cb, 0xfd935bef, - 0x79df72ee, 0x8bf0f2be, 0xf17c7c24, 0x70c7c60f, 0x6b2530f2, 0x7242fde8, - 0x96afe35c, 0xf8e0ff87, 0x1e8723c6, 0xa881334a, 0xf6145258, 0x6fcebb72, - 0x50cf1788, 0x371e7e1d, 0x453e7955, 0x9f5ddc72, 0x9ceee221, 0x5a7a5f9f, - 0x126af5a5, 0x43a6e1f1, 0xdabe1f4e, 0xf14c58e0, 0xe9f8e4d9, 0x067fb652, - 0x1c72512e, 0xb8f911b5, 0xa9e3cbf8, 0x3d396517, 0x56749f24, 0xc90a7984, - 0x392f5a79, 0x4c111d3e, 0x32eaef58, 0x410c08d8, 0xcc2d36d7, 0x4f9e1232, - 0xf4f6e2cb, 0xc89f224b, 0x05e7e16b, 0xfaa673ee, 0x35e31f71, 0x7ca77cf1, - 0xd67a604f, 0x02ef9424, 0xc0decf9f, 0x4797804c, 0x4f249dcc, 0x1f0e4dc2, - 0xc7e93fca, 0x10effd91, 0xa5f38b71, 0x19676ff3, 0xfebfbce9, 0x85fbe24f, - 0xdaffbe92, 0xc016ddb8, 0x181f818d, 0x186befd1, 0x4c1a2a67, 0x33f5c3b7, - 0xcb2efd1c, 0x459edc0a, 0xa44ff178, 0x94f3e6fc, 0xf195a92f, 0x622fe893, - 0xfa3aac07, 0xfce26d37, 0x239f5b0b, 0xaabeebf6, 0xcd979459, 0x73c88fcf, - 0x8fd9c336, 0x9ff9fb1b, 0xf5fd8fdb, 0xc8fd93bf, 0x9c7681dc, 0x7e69a9e7, - 0xed5ffbca, 0x5f71f804, 0xc875a8f8, 0xdcf22cf3, 0x5df997c5, 0xcdc3f6f6, - 0xb0ef6ae9, 0xe563ff70, 0x34ff93e7, 0x34fbf9f9, 0xdf0ea3f4, 0x7be4584f, - 0x9e22fcc6, 0xf82576c6, 0x9e3143b7, 0x8092f7af, 0x447f3e57, 0x6cf4c5e8, - 0xa75c51ff, 0x6cdb8f8f, 0x9e4c1d2c, 0x9b172e4a, 0x2f8a0e03, 0xbcf27734, - 0x8ce5e697, 0xfa3377e4, 0xafd0cb4f, 0xbda18b38, 0xf8233537, 0xf57efc33, - 0x9ab08edb, 0xd9f77e8e, 0xdebbed0c, 0xa9febce3, 0x6c73f83b, 0xa1ef2d0f, - 0xecc74678, 0xaaef288f, 0xae9fcfea, 0x7824adaa, 0xb1e08fc9, 0x7cadcf1a, - 0x0fe3c591, 0xbf43fcb2, 0x5f93f13c, 0x9e06e3ff, 0xf8f21d9f, 0x908fe85d, - 0x3d54f17e, 0xe6a67e46, 0xab68dc03, 0xd87cf952, 0x9e88f3f7, 0x2b4c0f9a, - 0xeb29ff47, 0x9da397b4, 0x072bf55b, 0xbe3ef7ed, 0x24f2972b, 0x0fc13dea, - 0x2b3a3e51, 0x5da35723, 0xa0e3085a, 0xfef1fbbd, 0x6e11cbab, 0xa336ff29, - 0xdfc61cff, 0xc7fa34ec, 0xd9e78d99, 0x4f9bdd2f, 0x4762cbfb, 0x6fec53f0, - 0x11c39db3, 0xa3ce23de, 0x3279bf08, 0xcfbe4bff, 0x4e344d56, 0x146db7f6, - 0x6172972f, 0x6d0599b3, 0xe4f203c5, 0xf22e9678, 0x635e444c, 0xa79e2cf7, - 0x8f0eea22, 0x81f3bf31, 0x238f2bcc, 0xb4b3c73c, 0xe61f96af, 0x402f9418, - 0x187e62fd, 0x9c5805c5, 0xe7a92dfc, 0xca3d1db8, 0x727a2165, 0x9c51df02, - 0xed09e806, 0xb1e34bf9, 0x6b9e78e9, 0x52f44774, 0x73e1f3c4, 0x3693c226, - 0xd38a35eb, 0xbc7c2ba4, 0x6b3df5e2, 0xc61fa2c7, 0xb865e6f5, 0xabbb7aa4, - 0x353a511a, 0x4d9f9023, 0x52968cfb, 0xbffaaf1c, 0xf29f3ccc, 0x17f92a50, - 0x291a0a3a, 0x6df7b29f, 0x4e3ce1ab, 0x77661972, 0xa8e4fe53, 0xbc505fae, - 0x194079c0, 0x72762f32, 0xd6f083b6, 0xa0cd8e1c, 0x3d4b9b1c, 0x43b56724, - 0xb538a2bf, 0x094356b6, 0x7eccdac4, 0x0b439e13, 0xefe460af, 0x32e1d31c, - 0x8a157ae1, 0xc3be98fc, 0xa418987f, 0x0f8c8afd, 0x937e7844, 0xee1567b9, - 0x3d15b4c3, 0x3d718797, 0xcd4db80e, 0xbc5fd865, 0x872dfc99, 0x4fd21952, - 0xddf15761, 0xb85ea153, 0xb0f145c6, 0x296ee7be, 0xcc2aff24, 0xf310cc73, - 0xf336ca2c, 0x9aa50ffe, 0x9b699f50, 0xd5470f98, 0x04d559dc, 0x875083f7, - 0x3c8a467e, 0x453f1955, 0xa9ea143f, 0xd7e0ecf4, 0xffb63f30, 0x14b2d21c, - 0xe3490e7e, 0xb2e712fe, 0xf3c71fb7, 0xfc2c3b3d, 0xc391e79c, 0xdf936613, - 0xe0a6ad6f, 0xe6ee7c3a, 0x663794f9, 0x42e70c9b, 0x847ff006, 0x1d4756f2, - 0x6bd705fa, 0xaff61630, 0x68bd3999, 0xd13b3d6b, 0x2d38b8bf, 0x97ba7948, - 0x8a5545b5, 0x3d4eb99f, 0xec27ab50, 0x3d70b673, 0xef8fbcd3, 0x35f793cb, - 0x6e5fa65f, 0x2dda36cb, 0x927ff5fd, 0xfe83f2dd, 0xfdc6fff1, 0xf3ee330a, - 0xe497ed92, 0x3b20dd7d, 0xe1bfa93c, 0x8f9918ec, 0x0e303d52, 0xd29da7b7, - 0xf21b0a4e, 0xe21daa75, 0xd8cda17c, 0x5c23e5ff, 0xbf995f34, 0x5f52b593, - 0xf1fa7981, 0xd7f2301f, 0x70a23cc9, 0x09f7cf35, 0xee746c9b, 0x29dacbd0, - 0x8b24687f, 0xd3f90a2a, 0x6d7ce87a, 0xc111e636, 0x47b2eb77, 0x99dbbf51, - 0xf24a8d6f, 0x6e105752, 0x509fe63b, 0xeb646abe, 0x3ae71c22, 0xc7638d07, - 0x308b93fc, 0x15bfc085, 0x06f4ebe5, 0x05c85f1e, 0x9bf48c7d, 0xa1d39a3b, - 0xa1e78ebd, 0x99133cc8, 0x50f12217, 0x3b9bf02d, 0xca115176, 0xf04ab5c1, - 0x99ae7151, 0x4e0dffcb, 0xec195e71, 0x79c0cf6b, 0xfbc63ee4, 0xf898370f, - 0xaf376479, 0xf9d18c77, 0xf82fa079, 0x728ebb39, 0x2832779e, 0xaf09253f, - 0xc9e53f32, 0xe411e0b4, 0xcbf3e497, 0xd6124e92, 0x6f47ce8f, 0xfaedc43b, - 0xcd0b06ea, 0x35c96fa3, 0x5bec97e4, 0xffa86262, 0x9cadbbab, 0xdbc692ee, - 0x51616756, 0xd88b57ec, 0xf5ca7e51, 0x16bb32ff, 0xfd14b5d6, 0x6b5a47be, - 0x38053a2f, 0xa01ada3e, 0x74aecfb2, 0xf9d217aa, 0xa928b9d2, 0xf9f2d89e, - 0xe60e5ab5, 0x140bc4db, 0xb7e79920, 0xea93347e, 0xb077f199, 0xcf16eafe, - 0xc39034d7, 0x3be2637d, 0xffff7814, 0xdbc47f79, 0x19731691, 0x87a1f77b, - 0x5f1d8666, 0x91fddf41, 0x9c71e725, 0xc4d3bd41, 0xc8c5567a, 0x5df4245f, - 0x5e879725, 0x25ec8587, 0x653fc8af, 0x151f2235, 0x5f503b23, 0x714e5399, - 0x0fd3077b, 0x8f3db0c4, 0x7682cf9f, 0x6395ffa2, 0x26da7fb8, 0x49e582e8, - 0x184f54bf, 0x22cadbe5, 0x2fdf7d37, 0x23580f8f, 0xc7c63fdc, 0x0be9e37f, - 0xf325be28, 0xe573196a, 0xf280b9cf, 0xfbf50c6c, 0xa61ce2ec, 0x73c7cae6, - 0xc2cd2bec, 0x36f515ee, 0x8bc53067, 0x043e44f3, 0x2b8dee7b, 0x7c865bbf, - 0xf7e0e674, 0xbb5ca347, 0x82fb02ca, 0xeed8e421, 0xfac72e1c, 0x0a358ecc, - 0x0ce3577c, 0xfac2f08e, 0x773a95bf, 0xa8291e06, 0x82cd311b, 0xf8581747, - 0x9af11551, 0x3dc4e829, 0xaee7c387, 0x77982809, 0xc7ced2ba, 0x7e6a0ccd, - 0x9c10f73a, 0x70075ca3, 0xbcb854af, 0xc9d28f86, 0xd3d52a8e, 0xa3611cf1, - 0x0aaad738, 0xe74971b9, 0xf5ed1526, 0x35beb79f, 0xe006d355, 0x878885fb, - 0x78c8a2ff, 0xcbdca23e, 0xce5962ed, 0x900bf556, 0xf0ad56fe, 0x12f336bc, - 0xf8e9ce7c, 0x9565b4ca, 0x557da798, 0xfa254b6a, 0x4f3d0769, 0x0965e787, - 0xaf7f2b75, 0xc02f16d1, 0xed0be673, 0x8f8849c1, 0x7bbde7cf, 0x3b87ca27, - 0x0778df73, 0x30de24f3, 0xaf91390b, 0x98eef588, 0x79eb069e, 0xf22dd8ac, - 0x0f446c3c, 0x3f72c6c7, 0xdb1e7f64, 0xfaf28538, 0xe7e1ce66, 0xb165af49, - 0x9ef81eb6, 0x3ed0159c, 0xd9117263, 0xde453391, 0x02b78cc5, 0x9817e869, - 0x435c4371, 0x5d9c3a39, 0xacd79574, 0xc3f024f7, 0x7eb1bad5, 0xfeb1a96d, - 0xfeb19f35, 0x1a7fc98d, 0xd97f589b, 0xf48d9fee, 0xf3c2bcf4, 0x3097c33e, - 0x47bdd117, 0x32fda309, 0x715c99e1, 0x27e7970e, 0x77d8abfe, 0x5199333d, - 0xdb3ed67b, 0x20373c2e, 0x68aad7fd, 0xb665e09f, 0xef7e0cc2, 0xb8bbea03, - 0x3d1cf222, 0x0761d314, 0x3f71756f, 0x816bbc2e, 0xd3ce0e7e, 0x46aa3f89, - 0x4e9052da, 0x76261cb2, 0xa552f239, 0x239aec8d, 0xb9e4ee82, 0x058d2aea, - 0x8602cf30, 0x1be5839c, 0xe88bd766, 0xc87f0ea7, 0x69dbe718, 0x8a5be51a, - 0x415b1831, 0x5d0487f5, 0xfff2911f, 0x57589a07, 0xef1840e0, 0x1e5cfaec, - 0x74652e87, 0x656cfe5e, 0xdd25d509, 0xae01fe4b, 0x41a18d1e, 0xe927f445, - 0x0b4ea7f9, 0xbf7a83d1, 0x34bbf849, 0xea590213, 0xb8807092, 0xc93d42c9, - 0x7195fec8, 0x6c9b7cba, 0x7ef8fcd7, 0x7e75930e, 0xd44b2bde, 0xaa6a29a1, - 0xf2fcfd40, 0x3b7f48ef, 0x879c417c, 0xe746cd25, 0xa3e38693, 0x767f825d, - 0x4b91f125, 0xe8f89abb, 0x3b92cea7, 0x9c6bee08, 0xa5afd42e, 0x0cba9730, - 0x2a23fd2a, 0x4fce3bf0, 0x474f8a6a, 0xed66f9be, 0x825aa9f1, 0x9bef869c, - 0xc6a9f7f8, 0x7df0bdef, 0x69f7c246, 0xe0d97df0, 0x6d3b77ef, 0xec44d351, - 0x21ef4aa7, 0xc9a5187d, 0xade6235e, 0xaeeff166, 0xa3b17911, 0xd47de0d3, - 0x3cc6a55b, 0x67d93613, 0xa4e4fca3, 0x94ab92bc, 0x57c839e5, 0xba9adb57, - 0x97bfa07b, 0x655e3ac5, 0x82e67e0a, 0x2dcf2fe7, 0x57fc8a39, 0x98688b6b, - 0x8b2d77d7, 0xedc5c2ae, 0xc47c169b, 0xe1f24c5d, 0x6693e459, 0x03363835, - 0xedcc67ea, 0x222d6fa3, 0x9bce79fe, 0x495e1839, 0xa45e1227, 0x493fa417, - 0xf770c92f, 0x3bd7e7af, 0x3b6f1129, 0x4a5851d8, 0x16b18abb, 0xe7ad779e, - 0x880bcc0f, 0x65ad8668, 0x2f35da34, 0xdc93092f, 0x00fdcab8, 0x9cbd65e5, - 0x944ffc1b, 0x7e177567, 0xcbe1a052, 0x716379de, 0xc6f000df, 0x95e137fe, - 0xbca0e3f6, 0x862d0fe3, 0xf8e1e3bc, 0x421b8e4c, 0xfcc550bb, 0x47949de4, - 0xf0e39a1c, 0x109179e1, 0x5256c1e6, 0xc2ec8afc, 0x6f6e14e7, 0xb09b1587, - 0x3f37cee3, 0xaf7b7199, 0x33dedfa9, 0x9477d7e4, 0x6e3bb873, 0x35fde5d5, - 0xc79c5edc, 0x4b393db8, 0x51742fb4, 0xefc3ccbb, 0x86fdc9d8, 0xd58f4f1d, - 0x03b05fb1, 0xe9607ec9, 0x322ccec2, 0x7f839bde, 0xde40d64a, 0xb73366f8, - 0x7c99b75f, 0x62e79455, 0x9ce2f7e1, 0x318cfe91, 0xff64fc7c, 0x628e6e62, - 0xd7f74f88, 0xc5fe4eff, 0x3f307752, 0x585bfa07, 0x4c502fe6, 0x33f71708, - 0x1c3e7d02, 0xd6fe9863, 0xfeed1a32, 0x9bcb59ab, 0xcfa262a6, 0xcfa41ce2, - 0xc59f4009, 0x9d1cfa06, 0x24e5c993, 0xb3e925c2, 0x934b2e9f, 0x1782caf3, - 0xee1d3f60, 0xa3355fce, 0xf56ddcbd, 0x9e5abcf1, 0x072c9827, 0xa059e012, - 0xaa3c7871, 0xc24cf04a, 0x39e19371, 0xa4493e1f, 0xf9c66ccf, 0xc97e3861, - 0x59d858d6, 0x2f2fc031, 0x083583db, 0xacdf3f7f, 0x41a3fbe2, 0xa20eab70, - 0xe46febaf, 0x2a509471, 0x4f1847d7, 0x67f181c9, 0x5faff189, 0xfaf0e9cb, - 0xdd10b17f, 0x8451f802, 0x9f68b67f, 0x7944ddd5, 0xcc6bb354, 0x00ed1227, - 0x13a9b719, 0x94f1cdef, 0xe605919b, 0x4bc634cc, 0xf1e26eea, 0x8b58eb9a, - 0x7ebde119, 0x3a9fb18e, 0xcc13feb6, 0xc9bbab0b, 0xd3983cf8, 0x8b19671f, - 0xc2a39671, 0xfc07d08f, 0xd3f4fc82, 0xdf0fc5cc, 0xf63bf40a, 0xe8156587, - 0x6b32ba77, 0x504deec9, 0xf1b6f1ff, 0xd669ff54, 0x06f3bfb7, 0xa128efb6, - 0xb9260d7a, 0xf9083ee1, 0xd54df511, 0xc114d78d, 0xa2ed47b8, 0x39f95bdf, - 0xb04a6f02, 0xe7bc1663, 0xf28a389d, 0xbc846b21, 0xdbc85be9, 0xc9d0bdaf, - 0xd66f5e53, 0x9358dfc9, 0x79f5efc2, 0x2bbffcad, 0x66b73f30, 0x3c57a894, - 0x47eb1e3f, 0x1ee84f95, 0x8726de80, 0xce6ff886, 0x09da7ee5, 0x1c744aa5, - 0x4326a5e0, 0xe7c4dff4, 0xd1e2b335, 0x9a8fe45c, 0x04cfde6a, 0xc5b5b4df, - 0x2ce99ef8, 0x6d737bd5, 0x250f2869, 0x70e7b59f, 0xa9ed2cfd, 0x67fbe080, - 0x8db6effc, 0x36037e80, 0x0c5387c5, 0xdf977e4c, 0xe7e0e55f, 0x22fe02cb, - 0xd3bcfd0d, 0xb37f3cfd, 0x0722b6da, 0x0f5fe7f7, 0x5e712a5a, 0x51f95b2e, - 0x27d26fb4, 0xf9449b4f, 0x466636be, 0xdf74073d, 0xf1787c41, 0x48690527, - 0xdd230e6c, 0x259aba4b, 0x48c6bde9, 0xdbafc0d7, 0x5cbf3272, 0xdae81b5e, - 0xc3d7403e, 0xd700b9d9, 0xa9ae098f, 0x3fd5fd46, 0x265f124e, 0xbc9c3b8f, - 0x7944bfc0, 0x275f003a, 0x661e5ff1, 0x7f2315c5, 0xecfe4bb6, 0xa62c3842, - 0x29b39d18, 0xe9e37c54, 0x7630ea60, 0x1f2f8486, 0x8315ae7d, 0x4d3fc2e1, - 0xcffc7fda, 0x3cf2fb83, 0xf9df0ed1, 0x5c00c659, 0x242bfe30, 0x7871570f, - 0x5c2d2bb6, 0x5c7b08be, 0xe59be7ee, 0xf38cbb7c, 0xe7e14aad, 0x77e8bdde, - 0xf97bdf21, 0xcfb87ef8, 0x7ce41d63, 0xcf6f4242, 0x169c05b1, 0xee75db98, - 0x1b9fa27a, 0xb469f858, 0x8339968f, 0x74f117ff, 0x843e14c4, 0xcc859cfb, - 0xa057f14f, 0x1272778f, 0x6f090dec, 0x879a9e32, 0xf3c9a791, 0xc0cfc649, - 0xbec8c5ba, 0xfad8e793, 0xf39e7be7, 0xc7897694, 0x6577f462, 0x8654ff08, - 0x452147f0, 0xc99e7ea1, 0x2fb87c52, 0xc853ee98, 0x6cc998be, 0xd6679724, - 0xe19e7d72, 0xd487f6e0, 0xc7f1c3fb, 0x92339715, 0x991b3357, 0xe7c73738, - 0xd9874c95, 0x2c0ee7ac, 0xadf4da67, 0xd1ef900b, 0xe007d14e, 0x7ee0e99f, - 0x215cecec, 0x24cf583f, 0xf5fdf3d4, 0x67be7a41, 0xe49fca12, 0x9e66c9fb, - 0x8cd2fee3, 0x99ca8c73, 0xa12777be, 0xeda8cf9e, 0xcc728499, 0x737bf2e9, - 0x1fdc0d27, 0xd1c78c98, 0x871926b9, 0x4cfa2f3b, 0x3f191fe6, 0xc706736b, - 0xcfd238e2, 0x55894671, 0x1e154be1, 0x583fe897, 0x76ec7484, 0xff434d15, - 0xe81b1cc5, 0xcbba1823, 0x1730bc15, 0x008fede9, 0xf10e6e0f, 0x75e3c055, - 0x347bc135, 0xe1e12c3e, 0x2b878136, 0xfb3d5e85, 0x89f14ab0, 0x43e97f1a, - 0xbd084218, 0xe2116662, 0x45e93f57, 0x59d8bf79, 0xf8a2a030, 0xb24e63fe, - 0x5abf1633, 0xb195f14f, 0x4f4c4c5b, 0x22e393d0, 0x327b8629, 0x30cbec26, - 0xcce82fd4, 0x617fbc35, 0x7b4328d7, 0xa1bc7479, 0x2a57a2fd, 0xb149f50c, - 0x2ff78629, 0x50daab7e, 0x1ae7a4bf, 0x3f53fbc3, 0x83a86d98, 0xde70d0c6, - 0xd8559f7b, 0x65f79836, 0xbe196ff1, 0x19b6cdff, 0xf3bc60af, 0xb2f7d8a4, - 0x0a563fb0, 0xe9205878, 0x637cdcf6, 0xaa25517f, 0xf3df2154, 0x79eb05bf, - 0xc034f6be, 0x0bbf625c, 0xc4f68ddb, 0x7ac62de2, 0x55a6f743, 0xe7071b28, - 0xe354b479, 0x79c93955, 0x79ae351e, 0x50cfa426, 0xe317d82e, 0x62ec1110, - 0x8e1b33cc, 0xfd6cbfcf, 0x2fe8d84b, 0xfefe7f5b, 0xf5d90b16, 0xaa7d5f8b, - 0xac8f0a2a, 0xdbfae35e, 0xa7fae375, 0xdfd71a96, 0x7fae33e9, 0xfae364fa, - 0xf5c6fdbb, 0x5c6b511f, 0x7180ccff, 0x8cebb3fd, 0x34139feb, 0x06c8ffae, - 0xb7e7fae3, 0x70bbd718, 0x8b3d7199, 0xed0d4bc2, 0xe52febc9, 0xdb9af165, - 0x7a01ef8c, 0x2074094d, 0xa04168e9, 0xc677f281, 0x30cf7fb4, 0xc03d324e, - 0xf744d1be, 0x6e3ec1bf, 0xf4fe729b, 0xfc8ad201, 0xf1f4c9bd, 0xeec2b96f, - 0xfa017414, 0x0ae513a8, 0x614f17d8, 0xd8563759, 0xeda181fb, 0x12bf290b, - 0xbee279f5, 0x36b93878, 0x7d894f48, 0x0a7ab0f2, 0x81f6c9f7, 0xf470f27d, - 0x8fb31c7b, 0x4f5a8ec8, 0x5d1ba57e, 0xf14f8e1c, 0xcfe825d1, 0xf2f4827d, - 0x32700071, 0xe71c7bc0, 0x4f1fe303, 0x8dfe4099, 0xd928b36f, 0x1982ffed, - 0xcdd83096, 0xe2ada898, 0x953a4f3d, 0x2f6f42f5, 0x858ffe14, 0xb95be0f6, - 0x9851efdc, 0xc5e6e385, 0x7b14bce8, 0xdd79c46d, 0xe3027123, 0x4f782008, - 0xca011c61, 0x9ba73b5e, 0xf8ae52d3, 0xc049ee99, 0x4ae9fce7, 0x6ab5d929, - 0xcd3de50a, 0xfd2141bf, 0x787fff34, 0x2cfa1719, 0x4cb95cb9, 0xd85db3e2, - 0x482edc03, 0x149ac3c7, 0x07416277, 0xc2e7cde1, 0xb8fe8675, 0xfc47ff1f, - 0x0ae3cd7c, 0xd06726d3, 0x675a3331, 0x0f3c6f5c, 0x9c38daa5, 0x0d999b8f, - 0x058139f1, 0x57bc0ec9, 0xfbc6d103, 0x7bfbcf1b, 0xd3fa1463, 0x7cfff554, - 0xcfe306ad, 0x9ffa2e38, 0xfe863e1d, 0x63ebd566, 0xf41abfe8, 0xba14c0fc, - 0xcebfa324, 0x87f87bf8, 0xc27e9178, 0xbb2f413c, 0xbdfb8c9d, 0x2386fc92, - 0x98c09055, 0xe7e663bf, 0x16dabdc3, 0xe63c9fbe, 0x984d635b, 0x37666337, - 0x32fbe79e, 0x6df3087b, 0xc7e4274f, 0x790cbac3, 0x3cb4e98f, 0xb657efae, - 0x71865c36, 0x07115ea2, 0x7835a7bb, 0xaab7ae19, 0x0e2f28f9, 0x277257ef, - 0x40f16f7c, 0x6a9f027b, 0xdd43068e, 0x5e1008ec, 0x10b6b556, 0x3dc598dd, - 0x6ef3ab50, 0xfc130573, 0x148e1712, 0xcc2d86f6, 0x984c595c, 0xc1f7f0c6, - 0x55f38674, 0xc4e9da5d, 0x0bd5a87d, 0x2bca25fd, 0xfa2590ad, 0xb6b4d7ad, - 0x94abdc10, 0xb33b1060, 0x3b51668e, 0xe1aadbe0, 0xbe785459, 0x67922af5, - 0x3e6de716, 0x3867f7bc, 0xdabd59fc, 0xc87289e7, 0x8728d23f, 0x5db56fee, - 0xd95af88e, 0x93c68cba, 0x756f6b78, 0x8df58e5d, 0xbed15ead, 0xb54dda82, - 0x71f482ba, 0x8621681a, 0xc7ad1671, 0xb03d7189, 0x03c61933, 0x045b5ecd, - 0xe1eac899, 0x05a3b2f0, 0x5d731f44, 0x8df4061c, 0xbc7d03e5, 0xfb4cccb3, - 0x1df3dbd3, 0xafedfef4, 0x0fd1798f, 0x1e01607c, 0xf98aff51, 0xf0238ff4, - 0x88721167, 0xf200c169, 0x23572595, 0x6b86747f, 0xdfe3ad36, 0xbbc49fda, - 0x1f28cec5, 0x20ef92d4, 0xe17cebbb, 0xf7148d0c, 0x27bc0950, 0x44f00fe3, - 0x8176f472, 0xe2efdba7, 0xefdbbe7e, 0xcec79460, 0xd55fc196, 0x148d5d00, - 0x059b25f2, 0x056f6ca8, 0xeb8252c1, 0x0b416365, 0x49d675e8, 0xbfd1db2f, - 0xcd7eed83, 0x4deaa18d, 0x58599e35, 0xaa7c9c6e, 0xbef1d91d, 0x618b3f4b, - 0xc474be89, 0x4581ab97, 0xc51fccf0, 0x1d783d8e, 0x89a7af35, 0x5e3ab4f6, - 0xe9ed174f, 0xf7cf5e01, 0x20d4a93f, 0x97f14960, 0xd5c6477c, 0x2dbe51a3, - 0xb27cfc60, 0x3b60e7b8, 0x91c2f213, 0xdb06ab31, 0xbe74626f, 0x50ffb640, - 0x4e38e7b4, 0x394629ac, 0xfdf8c73c, 0x6c878156, 0xe9f689c7, 0xb6319f14, - 0xa64af8cb, 0xf42bece3, 0xfdb1997d, 0xd3bdf141, 0x1d363671, 0xc71b47db, - 0x53da20df, 0x08ef3c1d, 0x473f21c4, 0x15efda2f, 0xc76c76ed, 0xed8d4bf1, - 0x2bf8c56b, 0x43ad0095, 0xf8899f3f, 0x9d568ee4, 0xf67cc9ea, 0x7e0cc8ea, - 0x99f0598e, 0xf21b196b, 0x23abfcdc, 0x9a4cbe79, 0x0ff7e3de, 0x7b650f21, - 0xb8a34b86, 0x10b5eaaf, 0x421d591d, 0xec3e088e, 0x8b4a2397, 0xf717138f, - 0x3d197f97, 0x8e7ee103, 0xfe00acf2, 0xbef39e90, 0x04c16263, 0x98db9679, - 0xef0982c2, 0x1864177b, 0xe53759ea, 0xccf7de1a, 0x77686519, 0xb4378e54, - 0xf13e58b3, 0xae826dc7, 0x0c2aca52, 0x02bef2ed, 0x923e73a6, 0xf479b576, - 0x677bc314, 0xa474f54b, 0xcb57d3ed, 0x367cabfb, 0x39b70b94, 0x1f236547, - 0x3275a4fe, 0xef20df1a, 0x8974a26c, 0xc9474bd2, 0xa2eab656, 0xc7f54a5e, - 0x7aaf3cdc, 0xd78fab65, 0x6f9d188b, 0x4b5ad95e, 0x2f81c7f5, 0x56d7fcb1, - 0xa07b953f, 0xfb0e160e, 0x43aff411, 0x7fa13b3f, 0xfd023fac, 0xfa1db963, - 0xd087f2c7, 0x856fb63f, 0x10feb17e, 0x83e585c0, 0x7f3e0fd0, 0xfac7fa00, - 0xd500d6a6, 0xa3ad6bef, 0x20d686fa, 0x36b6f795, 0xadb5f3d0, 0xdd5f542d, - 0x7bca8cba, 0xae54c35a, 0xed435d6c, 0x1f37a116, 0x1f1fe713, 0x7dcfc69b, - 0x467faf27, 0xeed5f29e, 0x4504a8bb, 0x93c8655e, 0x7dc3c8c8, 0x2f31a775, - 0x7047f110, 0x931e39d8, 0xe02b18e1, 0x2b62cf18, 0xa0dcb952, 0x2e98eb38, - 0xc0a9dddf, 0xf85b23a7, 0xc57517ba, 0x81a73da9, 0xcc56378f, 0x2cc27993, - 0xef1f8aaf, 0x957af7c5, 0x8f2a7558, 0x831f9337, 0x553f0179, 0x9133dce2, - 0x7084c479, 0x7f419369, 0x1fb3cc27, 0x270e6e5f, 0x78286de2, 0x7c78f22b, - 0xe4ecad43, 0xb6d49bf7, 0x52cd9147, 0xbf742dfc, 0x102ead89, 0x04f4a0d5, - 0xc24f7482, 0x603373f8, 0xed720593, 0x874ce5dc, 0xb8d1af32, 0x505dcaff, - 0xa8e7d861, 0xfd3236e7, 0xccb7e822, 0x194a4fb8, 0x3be19b7d, 0x0cf7de5b, - 0xddcf16ed, 0xb7f9f686, 0x22f2ad14, 0x8a32473e, 0xafd7593b, 0xd7003960, - 0x044d8ec2, 0xbde05057, 0xfdf9d157, 0xefc5fbed, 0xfffb0844, 0x2f812ec7, - 0xd7da7adb, 0x6af3758e, 0x84d87a49, 0xa7e3e7fa, 0xee8e49d2, 0xfe44c47d, - 0x622c71ed, 0x01337942, 0xbf6c48cc, 0x56726f00, 0x151ccae9, 0x574ce5eb, - 0x8b117eb1, 0xec08bed3, 0x17a43aff, 0xb11fffb0, 0x7e4cfd43, 0xbf3cc7f0, - 0xba7a4a2b, 0x8967ac44, 0xd16d07dc, 0x73c3fd92, 0x635fc8f3, 0x26d6073c, - 0xdc2b01f6, 0xef18d955, 0xff261ded, 0xd6fde9ce, 0x1eb005d4, 0x2a3a9cce, - 0xba0df3e5, 0xd173c869, 0xbf2abecb, 0x623d016c, 0x086597e4, 0x9fca99ff, - 0xaabba167, 0xf89c7479, 0xe52ccda6, 0x728e9e98, 0x4beea06c, 0x3ba2bb27, - 0x89a3f087, 0x1adbd9f5, 0x3900fca4, 0xd377ed4f, 0x560f985c, 0xf74ff222, - 0xb53adeb5, 0x661f2126, 0x52dfa0b7, 0x3d45ab16, 0xf2665a5a, 0xaf27a845, - 0x1f617fc1, 0x73c7eedd, 0xf3055afa, 0xc71e18a1, 0xbabce9da, 0x794a85f6, - 0x4b91da40, 0xb0760e98, 0xe16511c3, 0x997e81b2, 0x477c83f0, 0x5ccff5c8, - 0xad0f3435, 0x3e47da40, 0x33ecddd4, 0x74863f87, 0x998759f7, 0x6309e5b3, - 0x9183a97b, 0x6a545b9e, 0xa60ae889, 0x3dd3b423, 0x850eda8b, 0x1c2115e5, - 0x50f3bdd3, 0x254c1f8f, 0x52dd4dba, 0x7bc35745, 0x79f5c14c, 0x1e99c700, - 0x1a49a0fd, 0xd35ef057, 0xb42ecb04, 0x5e22c71b, 0xa5d19c70, 0x6285c784, - 0x575afbbe, 0x159e9e10, 0xefcb68f3, 0x87873bc7, 0xcf78fcf9, 0xe90ea2e9, - 0x73ce31bf, 0x37f56543, 0x95c6def0, 0x74d85531, 0x33ae7c46, 0x53ce26c7, - 0x3802e006, 0x5538459f, 0xbffc9b84, 0x8f4d7e7c, 0xc819bf70, 0xbb8a5ab1, - 0xc4b1324e, 0xa32cabb8, 0xc8cdfe42, 0x4ebc1173, 0x0ba9dcef, 0xdfac4a2e, - 0xb8fd7444, 0x761fe7c2, 0xcd2f3c6a, 0xfd13d7ef, 0x7ee4ebc4, 0x487f9c59, - 0xdff6f011, 0xe79e36e3, 0x6c583a61, 0x0d2de60b, 0x25fe1fb7, 0xc4a4ca2e, - 0x18e830fd, 0x649d5718, 0x759f3ca3, 0x7f4b8f32, 0x337cc743, 0x8afcf12c, - 0x6ae9d04d, 0xe4af31a7, 0x77b71e5c, 0xe8f589ce, 0xc6be71b3, 0x567964b8, - 0xdd17bdc2, 0x91ffe4f5, 0x6ebecc71, 0xfd2e0f9e, 0x09044b6b, 0x78e51df4, - 0xa5587be8, 0xee92e5f8, 0xa17df96b, 0x7ba01e87, 0x1d2fa156, 0xbc5ea1e9, - 0xe8c6bf5f, 0x3bb059ef, 0x1f452ab0, 0xc45a57ec, 0x48d7e4c2, 0xfb2527f6, - 0x279b7e91, 0x563e69f6, 0x93ca718e, 0xa58f8beb, 0x88a67ee0, 0x91dbb9d1, - 0x8f7493ea, 0xedfb5831, 0x2b294f78, 0x24f4f7e3, 0x0525fbaf, 0x3ef3c216, - 0x1c63aeb9, 0x37d867e4, 0xbefff389, 0x7d7ecf17, 0x96f3f40c, 0x81ce18ae, - 0x099ba5bc, 0xae81e38f, 0xac64ecb1, 0xa0fba876, 0x5f4df3b2, 0xa5c0bced, - 0x68d7dfc6, 0x9639eaea, 0xcbbc93aa, 0xfa7807ca, 0xad3efd8e, 0x4e27f88c, - 0x575107bf, 0xb841e1c4, 0x7ecbfcf1, 0x137327d3, 0xbe7c60e9, 0x7c83edc6, - 0xbf9357d3, 0xceb84635, 0x7599bd94, 0x1c6b870d, 0x3d1bd5c2, 0xb7689591, - 0x0ff6b848, 0xa5fabf73, 0x934f155f, 0x0120fa8d, 0x12ff534f, 0x865bf69e, - 0xc0966786, 0xf28e4fcf, 0xb70642fb, 0xd5fd457f, 0xccf78461, 0x51ebb163, - 0xb3bc023c, 0x53de7f08, 0x15331459, 0x14acebf8, 0xe42959f4, 0xa8ce8f8e, - 0x17dbd0b0, 0xa75e7e53, 0x7743dbc6, 0x79e08a2e, 0x0b8bdf02, 0xe0dfd10a, - 0x7ba56e3c, 0x7949429e, 0x2f5cb222, 0x573fb1e6, 0xab0f1219, 0x78bcb9f3, - 0xd4f9b5f1, 0x596fbddf, 0xed83ca19, 0x5ef5df22, 0xef0da757, 0xc47895ef, - 0x2194057a, 0x2a117c4b, 0x3f2b7bba, 0x218ee9b3, 0xf1f133c6, 0x1be24bee, - 0x572c9e39, 0xbb7297e4, 0xe2aa3954, 0x2efb8739, 0xd9ee937d, 0x2352afba, - 0xe337fb99, 0xfe127d7f, 0x7d666fa3, 0x8acbd39d, 0x2aa3f47c, 0x037da5ef, - 0xfe2521ea, 0x9fc432b3, 0x0ff34825, 0x3b656dbd, 0x6a78c195, 0xe72bf414, - 0xe12fe727, 0x80b65e76, 0x7ae099ce, 0xc5abe020, 0xa44f52fb, 0xf387bd0b, - 0xa9713d22, 0x4c89cfc6, 0xef5d68d2, 0xce853c9b, 0xf917ecf5, 0x2c4bf114, - 0xc32efe43, 0xf76f0233, 0x0c45fb9e, 0x770da9ef, 0x055ee99b, 0xbf78f5a6, - 0x7a147409, 0x9a7ba35d, 0xf16a9e81, 0x5f17a8de, 0xfb869b3b, 0x66f903e8, - 0x3e40fb82, 0xe77d8797, 0x6f3a5ad4, 0x2e67daf3, 0x9ffe8135, 0x5d8557ce, - 0x39e18b12, 0xfc158d9a, 0xd84380dc, 0x4ed78e01, 0x8efc2035, 0x2ab3dfc9, - 0x4f767a09, 0xdbbe95be, 0xf9678968, 0x48740e30, 0xdfee5165, 0xfaeffba1, - 0x38ba0bcf, 0x8f2b9a1e, 0xe8e09d92, 0x3de2f7e6, 0x5c13af9d, 0x7841f708, - 0x33ee329e, 0x57b63d57, 0x06a378c2, 0xf8ba77be, 0xe24ca67a, 0x77dcd0f7, - 0x785dcfe9, 0xc2ba5eef, 0x4be8fee8, 0x3906cc0a, 0xd7c45f5e, 0x1632b3a1, - 0xe5fc851b, 0xb6af28d2, 0x0d9b7a33, 0x17c97aed, 0xf4a947a3, 0x97916add, - 0x29727abe, 0xe3a499f1, 0x57c105b9, 0x02366e91, 0x76493c5f, 0x9d302c4e, - 0xc72ae3f0, 0x95c7e3fc, 0x3fb71d58, 0x2fd42e2c, 0x819326a5, 0x380b8adf, - 0xec12c8dd, 0xee77b252, 0xf52cb410, 0xc6c45b7d, 0xb7ffbf30, 0xa3a566e7, - 0x2796da5d, 0x0dbf3ced, 0x095db5f1, 0x38e117a4, 0xbed2a5ff, 0x4ed7c5ef, - 0x6db8e034, 0xdbe42f30, 0x58ea7e7b, 0x9b49f68f, 0x2a7c4fcb, 0x26dcd7c7, - 0x9fbc1eb1, 0x2bff16fd, 0xbb8c6fe8, 0x47447df9, 0x43635ca6, 0x4cf787fa, - 0xad7bcfd8, 0xd81a0bf8, 0x07f90d4f, 0xcf66ba16, 0xb116efc0, 0x6bb42ae0, - 0x86a87517, 0x11ee177b, 0xb9e162f2, 0xd84d1614, 0xfc9c2c1f, 0xb6373a2d, - 0x8b1a5cf0, 0x8f75bd82, 0x8f7d1738, 0x0ac45738, 0x443b3d38, 0xdfe515e9, - 0x24bef7cc, 0xcbf995bd, 0xdf39f3bd, 0xb7e802b3, 0x14b1e949, 0xa71b10c1, - 0xebce9efc, 0x62ead7bc, 0x780492d1, 0x0473cd07, 0xd38c268b, 0x1b39deff, - 0x7d6067cd, 0xcc0efd39, 0x787841d7, 0x784bd5af, 0x91ffbe1c, 0xf40e3c06, - 0xc780ca3f, 0xd097fdc1, 0x96b5eff8, 0x13ff497e, 0x375fe986, 0xefd03fc0, - 0xf7b71a68, 0xa71ffcc8, 0x891ddf02, 0xf9edbdde, 0x331dfc4a, 0x017efd2b, - 0xa6aceaeb, 0x338f8473, 0xe77a673a, 0x83bddfe1, 0xee779af9, 0x8c70f8b2, - 0xae7c733e, 0x333d086f, 0x78c2b99a, 0xc72c979f, 0x7cd31417, 0xb4db9f92, - 0x32f30b88, 0x0b9aa56d, 0xc6d11f7f, 0x71bb9162, 0x236952df, 0x42e32739, - 0xe53fdfb2, 0x3b3cf2a9, 0x6f7907c9, 0x979112cb, 0x5e08ec57, 0xd4beeb81, - 0x13fcded4, 0xd283f6f8, 0xcc373a36, 0x33f69b98, 0xe1a36e32, 0xa315bf2f, - 0xf0c0305f, 0x7a13cdfc, 0xf77e0670, 0x18271043, 0xd82f51c7, 0xb5bcc41d, - 0xb8df620d, 0xfaf31ec1, 0x0de6e412, 0xb357da05, 0xe893da17, 0xf72fd276, - 0xdedd3946, 0x227e8050, 0xfcc4f635, 0xedb7cc22, 0xe976f711, 0x55778a16, - 0xfefba31e, 0xff7dcbe6, 0x8ebce49a, 0xd1da377c, 0x8694ce32, 0x6b687779, - 0xbef7e46c, 0x7af2a7d5, 0xa08c7ffd, 0xffb01073, 0xf9432d49, 0xfee55fb2, - 0x3adf1120, 0x67d0e62b, 0xf94058db, 0xe41f22f7, 0x744bf76c, 0x35d9e4af, - 0xebfd6863, 0xdd3ef85f, 0x973fb70b, 0x43beb1eb, 0xf563d24e, 0xde155f56, - 0x973fb85b, 0x5a9dabdb, 0xc122ad34, 0x579d5d7e, 0xe3f9f24d, 0x894c6335, - 0x0aef8ff1, 0xfa51b079, 0x1578b537, 0xb8f9679e, 0xd233fa32, 0xf4ec07a3, - 0x83a6513b, 0xfba2abbf, 0xe95a372d, 0x0faa0177, 0x875cdb8e, 0x8d34c3fb, - 0x074d91f2, 0x99cf04ed, 0x2d7efc75, 0x5de516fc, 0xf491c1d3, 0xa9f556fb, - 0x6c27ca71, 0x6095f14a, 0xe0feafdc, 0xffd7ba54, 0x057186e4, 0x644eff28, - 0xaf7405ea, 0xf43c06f1, 0x6343f509, 0x17b5f3f9, 0xe75579d3, 0x50e0d4c6, - 0x8fa9107e, 0xdaefef92, 0xdbde5b9f, 0x6719f885, 0x7dfca1f3, 0xb8f1f14f, - 0xd9f12bef, 0xf915c53a, 0xd77ad2f9, 0xbc7dfa69, 0x6f778efa, 0x43dcf462, - 0x73f72b74, 0x0bd5e3c9, 0x12dfb57d, 0x4bbf8b9f, 0xe052bf56, 0x624efc5d, - 0x7e9ca9bd, 0x7de24faf, 0xb73dd263, 0x24fd084f, 0x69af93cb, 0xd8205f74, - 0x1fe80511, 0x4ad8793a, 0xe3727674, 0x2eaf3a04, 0x9c07abc7, 0x4f2f80b8, - 0x7113e864, 0xf2169f5d, 0xdf257eaa, 0x30e7caa7, 0xe77f0c7e, 0xa5487e30, - 0x573eaebc, 0x92e30d3c, 0xef593df2, 0x4ab74f9f, 0x3fb597bf, 0x6f5a45f7, - 0xf48627a0, 0x49c17a64, 0x82f43a7a, 0xe7ae1775, 0x8c2c95c7, 0x5bf0cffe, - 0x8ec7f7fc, 0xfd92b21c, 0xef9c77dc, 0x9fdd076f, 0xe01788e6, 0x17a1a1fd, - 0xeb1c9246, 0xe0ef8fcb, 0xdf9db6f6, 0xf046f8ab, 0xcdff1162, 0xe611f711, - 0xf9f79da0, 0xed147b21, 0x9e29283c, 0xbdbb6610, 0x2a70fcf4, 0x940fff43, - 0xca63cf14, 0xeefd2f01, 0xdf176b0c, 0x3bfbe8c7, 0x5163820b, 0x0c59df2e, - 0xfbf03bfd, 0xe7def453, 0x521782a3, 0x5cb18a0c, 0xf52e5e31, 0xa42c1f9b, - 0x5e67cae7, 0xed2a7bfe, 0xed463da2, 0x62f06b21, 0x9cafc79a, 0xf310e76c, - 0xeef7aafc, 0x41182d1d, 0x06e128eb, 0x98dd933c, 0x05b3978c, 0x3b7bf126, - 0x74c91f1c, 0x5f9ebfd9, 0x5ffa1f02, 0x21f6bce8, 0xc6eb8ebe, 0x591cb859, - 0x63ec813b, 0xc86296d6, 0x88715b9f, 0xbbd0c3df, 0xdceb49c1, 0x843ff667, - 0x86fe28fa, 0xed7bf199, 0x3f4022c0, 0xf9a1e4c5, 0x4f9123e5, 0xcf2d64bf, - 0xd1e8fbb3, 0x39e60bf7, 0xfbf25cf0, 0xd2c97386, 0xa49d085f, 0xe1c63fa1, - 0x97e6d3d3, 0x255d7b71, 0x7aeff8f8, 0xf4eb346d, 0x0de16bbb, 0x711fc8e3, - 0xa41fa2d2, 0x775b87df, 0x4ae90981, 0x77f2172d, 0xbc9f9f13, 0x7bde4b2f, - 0x8a9f8c95, 0x7f9262c2, 0x33782c4d, 0x827ea1de, 0x61c259e9, 0x91fff746, - 0x6984df7b, 0xe29f9a88, 0xf485acb6, 0xf67be0c2, 0xbbf25f2c, 0xf5bbff6c, - 0xf42b5c2a, 0xd38795ef, 0xe07eaf50, 0x3a46fbe2, 0x5d7a8f7d, 0xc36cf3e5, - 0x83af300f, 0x4e14a605, 0x879276a2, 0x5dbc281f, 0xf341b9ca, 0x7ec17a47, - 0xebe83df0, 0x7fee429a, 0x710cae63, 0xc16c2bc8, 0x9fa94d3c, 0xc2668a42, - 0xdca7f373, 0xe3d21a7a, 0x19c5b5a9, 0xc60f302b, 0xda2567ad, 0x8ca3a1d5, - 0x78eb8bce, 0xf8c5f8df, 0x89fe32fb, 0x9fdbf7e8, 0x243bf461, 0xb4e4f3c3, - 0xed89b99e, 0x9eb90a73, 0xf6285f9b, 0xe44c8599, 0x8de32657, 0xb162fbaf, - 0xf0796aee, 0x2687da72, 0x4b78b7bd, 0xa487a0ba, 0x7fcfede7, 0x1ea0f297, - 0x4913de36, 0xef185fb1, 0x612c5783, 0x532c42e5, 0x61bdaf28, 0x0d739713, - 0xb92cceaf, 0x5ee9d78b, 0xef3b6985, 0x59e3dfa1, 0x12caebb0, 0xad16e5c6, - 0x05c7a483, 0xb412fe05, 0x555be2e3, 0xc345f217, 0x51e09516, 0x56d73ecd, - 0x8b7a7e78, 0x06bbec99, 0xbce9cf01, 0x9bad1a60, 0xe00b34c6, 0x4c16b4fd, - 0xab75fb23, 0xa4a1ddf8, 0x6f7bc079, 0xe043156a, 0x99d7c6c7, 0x043c53f0, - 0xa261bc1d, 0xbf805a75, 0xec70890b, 0x79bfc854, 0x33783f3a, 0xfec14fd6, - 0xabe9cf1f, 0x7dd0969b, 0x3ef8c936, 0x7d120b6d, 0x91f3162e, 0x471e4cf8, - 0xf10fb3e2, 0x2bd2f689, 0x85ef4853, 0x6291541e, 0x9fdd8bd9, 0xda7cbed2, - 0x99df2ba1, 0x8137cf8a, 0x9ea3a2dd, 0x6fb3f51d, 0xa35b9ea3, 0xfe7a8c52, - 0x962ce2a1, 0xff71afa4, 0x39f5ff39, 0x3d04a669, 0xf1c83ea9, 0xa4e73aa4, - 0xcff7a42d, 0xebe91d7e, 0xaacbee84, 0xf1ef7848, 0x83b8fec2, 0x37eabd61, - 0xc70d21fd, 0xa66f5869, 0xe975c979, 0x7ca079c3, 0x208d4f6b, 0xc5e5f7fd, - 0x4eb95fa9, 0xeb8df4fd, 0xde09e920, 0x9742affb, 0xf24c2718, 0xb05154e8, - 0x9d0437ca, 0xc6007a2c, 0x38b6fec5, 0xf3d2fee9, 0xa3e2571d, 0x5f05bd7f, - 0x71d71d53, 0xd1f91147, 0x74686f4d, 0xfb44e0c8, 0xc7c80555, 0xd02fa0f5, - 0xc4af516f, 0x647ba1df, 0x1ee9590f, 0xb74dfae6, 0xd5e38cdc, 0xb09ab71f, - 0xabe1d4fd, 0x495c1226, 0x2a780aeb, 0xfbde8a18, 0xbe05e28a, 0x3d81fc04, - 0xe72dfc41, 0xc1370093, 0xba29fb01, 0x08afa88f, 0x0e4133d6, 0xedc859bc, - 0x65df782e, 0xf7e6fa21, 0xd7cff561, 0x575f3495, 0x64df7cd2, 0x17ccdf44, - 0x782cf9a4, 0xe7c26adb, 0xb6bfee0b, 0xa73df704, 0x79a74dd6, 0x4ff0ca9d, - 0x553afe44, 0x210ffd00, 0x0fdc172f, 0x0bfb2cf3, 0xd3b76cf3, 0xcf3b0d7a, - 0xf60ef88c, 0x89f9e617, 0xcf3943a0, 0x0d3d34f7, 0xcf43f9f3, 0x2efd0caa, - 0xc6c0fca1, 0xbf4ebca9, 0x73321713, 0x4a6d087a, 0xdedf7ca5, 0x04fbfe6e, - 0x78c00e52, 0x260f49e7, 0xd55387a2, 0xd0c9e6fa, 0x3f07ffdf, 0x00b71737, - 0x0000b717, 0x00088b1f, 0x00000000, 0x7dcdff00, 0xd554780b, 0x733effb5, - 0x64932666, 0x08124c92, 0x3c984081, 0x49849009, 0x768a8802, 0x02d10478, - 0x89794f0d, 0x42100793, 0x69b5a05e, 0x0240cd6b, 0x350d45a2, 0x01d45a2a, - 0x0da2a281, 0xbc150a0a, 0x45622a03, 0xb68b57c5, 0x514026e5, 0x5ea0c679, - 0xffd7b5ae, 0x4e7dadfa, 0x5490ce72, 0x7dfbdedb, 0xdf1f7cff, 0x5afd9f66, - 0xd7b5ed7b, 0xe7bdaf5e, 0xcbaa3dc2, 0xe4e216ef, 0xff6f05dd, 0xf7a517bc, - 0xfc812eaa, 0x02cddf58, 0x2cc38ff9, 0x934a14fe, 0xfe70a68b, 0xa56b9b65, - 0xa689c422, 0xa141fdbf, 0x367d85fc, 0x0bf2a0b7, 0xcef74529, 0xea8f7e46, - 0x2fed415a, 0x259f680c, 0xd8b97386, 0x5deae544, 0x2e509a23, 0xcae61e1e, - 0x0df2f2a0, 0x09644261, 0x6856fbfe, 0x3be9237f, 0x6ba50b52, 0x34786f55, - 0xfd2f4da5, 0x6fa5c944, 0x578f3756, 0xf724abf3, 0xb97e34dd, 0xf9ed5855, - 0x399edca8, 0xf388472d, 0x03136d7b, 0x233f32d9, 0xb03fcb87, 0x5d8d7952, - 0x7bf85af8, 0x0e6a7dad, 0xd2b6e28f, 0x0fa98b38, 0xfae94a91, 0xea60ef18, - 0x938d317f, 0x8b7de342, 0x0e5c1fbf, 0xe7cb0edf, 0x9fa88a0b, 0xf6626d7b, - 0xf55dd973, 0x4ddb34f4, 0x6d46f61d, 0x553b577b, 0x3cc62588, 0x2422a1e1, - 0x477914bf, 0xa432be57, 0x7ca42abc, 0xa7cfbf47, 0x1f2f3914, 0x1fc6037f, - 0x12c785d1, 0x2c3b8f0d, 0x72eb1df4, 0x44d8128f, 0xbab12dff, 0xfe09cbed, - 0x9b88c6e7, 0x55a94fd1, 0x47cdae38, 0x5f9e0ebd, 0x86345589, 0x87bbe3e5, - 0xa6f3e9eb, 0xe2c31afe, 0xced11f28, 0x89bd53e3, 0xda9e4376, 0xab9ae09b, - 0x4ba7a3c1, 0x4ebb85b7, 0x7fa0f3ea, 0xa6b12d55, 0xbeeecd7c, 0x7c0693ae, - 0xfa7fc52f, 0x3449bfd2, 0x8bc091fb, 0xdddaabfc, 0xe892307a, 0xcdf14da7, - 0x17bf5375, 0x9d1d7e0e, 0x1f75e6ed, 0x9beb4459, 0x7f3ea6af, 0xbedbe698, - 0x426cf547, 0xfdd86fbf, 0xe7fd0c4a, 0x6e0f8b9b, 0x2fd5efa7, 0xddbb89a7, - 0xc50ff35d, 0x17dd85e3, 0xfbe953a3, 0x08f643f9, 0xb9e68c31, 0x9dac7e37, - 0x5c4762e8, 0xaf78b77b, 0xef5dd6d5, 0x35b5bcef, 0xdea1aa7a, 0x3d1ad179, - 0x252f40cd, 0x8bd62fbb, 0x5f9fc65c, 0xefc2efcd, 0xc7bd7d89, 0xf4bdf4aa, - 0x5ac6fdf7, 0xc35fbd28, 0xf736bddb, 0x6e096b13, 0xcf309eff, 0xfcfb8216, - 0x682db31b, 0x728dfe7f, 0xcbcdbd2d, 0x244f5fe9, 0x8b68fc63, 0xbc7d77a4, - 0xf70b6e35, 0x7b696a53, 0x8fda1aec, 0x93ebbfa5, 0x55d290d2, 0xcfc96a5e, - 0xb76f3ac4, 0xdc002fb5, 0x46b115e7, 0xe7eaeb89, 0xdb9bb77e, 0xc9f3df9f, - 0x270fe063, 0x4f901dee, 0x41f94d64, 0x3f2a3eb9, 0xa64151ff, 0x7f3dfa8b, - 0xf80f5f4f, 0xfb9b76c2, 0xbbb7a636, 0xf7d83ca2, 0xa7187f7a, 0xb9effd16, - 0xe90fa462, 0xca5e1247, 0xb8e4fae7, 0xabbf257e, 0xfb8b68df, 0x17e0d1be, - 0xb679b7bf, 0xeffcb250, 0x31627d69, 0x6ee7ec3f, 0x4d74a1d6, 0xf89b7098, - 0xbb864ac9, 0x22ec7844, 0x030b964d, 0x228995bd, 0xc9b0befe, 0xf1117dfc, - 0xbc5f7c09, 0x5cbdfcde, 0xa56ead34, 0x98092df9, 0x3fda0bbf, 0x6bec04fe, - 0x5ec5affd, 0xff7a0514, 0x4f54cc36, 0x40fe35f8, 0x255f091f, 0xc7c11fb4, - 0x8102519e, 0xbbdf5895, 0xe8679e54, 0xa775debc, 0x2287bb70, 0xab4167ff, - 0x5b8f5d61, 0xf0913584, 0x1c2edc7a, 0x47e8f989, 0xf5fa8508, 0x6c0b0bef, - 0x0f7726a1, 0x04b92afe, 0xc231af7c, 0x5bbe0822, 0x427ce05d, 0x49f7d8ac, - 0x5d29fa32, 0x356de853, 0xe6c177c0, 0xd4e7e87d, 0xe25dfdbe, 0xf8ef54d7, - 0x58d340d8, 0xddf8eb82, 0x1ba1a7aa, 0xb1af4eb8, 0xe1014088, 0x02212ee3, - 0xf27f94f1, 0x5a62e493, 0x7cb6cf97, 0xa4625c92, 0x36cc457f, 0x129ea3d2, - 0xef3ebc24, 0xfcd2ef61, 0x305cd38e, 0x5d7ad09f, 0x57866beb, 0x2ab867c7, - 0x87a3bb6a, 0x54f740cf, 0x5577f59e, 0xf7efb178, 0xcfa002d9, 0x3c5f8dc8, - 0xb9f40f38, 0xa14ae6d7, 0xa9f66bb1, 0x2de6955e, 0x0c81a8f6, 0x4f7b639c, - 0x9ce05744, 0x52e053d9, 0xd9aef30d, 0x7ce116a3, 0x62fbbf39, 0xf7366942, - 0x44edc533, 0xa03c07fb, 0xf8e09edf, 0xf7fd5b9b, 0xccd79ff8, 0x7f65ceff, - 0xf8037090, 0x9953c6c0, 0x07c4efe0, 0x79a6e6ff, 0xc6fccf9e, 0xad10bc8e, - 0x047f4123, 0xe09bb45f, 0x2af810bc, 0x8e5c105a, 0xd037aabd, 0xa5443acd, - 0xff4f19d8, 0x09137c32, 0xf82e84be, 0x94a89e08, 0x56705d11, 0x38eddbbb, - 0xa2382f67, 0x694fc173, 0x12f29342, 0x0dc9f3b4, 0x493a5afe, 0xbf1d7f10, - 0x70cae167, 0x8a4d0bc8, 0x97be8c27, 0xdcf955ed, 0x191bdb2a, 0x3f1816c0, - 0xd2f9c9c8, 0x1840d547, 0xa3a827e5, 0xea9b30ff, 0xf547be2f, 0xfb148ed0, - 0x07f6de37, 0x8375d61b, 0x881ca04d, 0x344b5c03, 0xfdec96b8, 0x8d0a67e1, - 0x2ddf78b3, 0xe2ce3007, 0x170f1407, 0xe8edf3a8, 0x8a43c977, 0x67405788, - 0x3a46e3b6, 0xce64d85b, 0x0bad122f, 0xc1fc1554, 0x9ef09dfc, 0x96fd415c, - 0xdd730eef, 0xa102f18d, 0x4abc42e5, 0xff68d4f0, 0x3b58cacf, 0xcfd500f7, - 0x3c6768da, 0xe2170f9c, 0xb5abf608, 0x0d204135, 0x1d6326b6, 0x6bf9efcf, - 0xe6b1d632, 0x2995ff77, 0xcebf59ba, 0xaa37b4fd, 0x2148a9d7, 0xc4514eae, - 0xfba0a9b7, 0xba8a538b, 0x201b6fa9, 0x9b36c5f7, 0xca879fbf, 0x8afc6c0f, - 0x3d85c1f9, 0x6eae81be, 0xbf6bb7e8, 0x892dc3fa, 0x02e18348, 0xd716f0e9, - 0x2427d80d, 0x35be620f, 0xdb4f569b, 0x97f0f944, 0x44b9386c, 0xf793864d, - 0x42c7f60b, 0x3efabf43, 0x80be06d9, 0x0fe48474, 0x1cf201b6, 0x7b9daa3d, - 0x4c77f6db, 0x9e06e8c9, 0xd71b6ea3, 0x5c100db3, 0xd17759ef, 0x845bd05c, - 0xbe0d1fc5, 0x775ebc2d, 0xa2b3c22f, 0x5d4357d1, 0x89ef82ad, 0xfed389a2, - 0x47d385a2, 0x5139f085, 0xc05c785f, 0x620310b3, 0xf3de3f81, 0xccbecf8c, - 0xadac7f37, 0xe8357821, 0x022b1fc4, 0xeaffe85b, 0x63508746, 0x46b5ed20, - 0xce5451a3, 0x5206fbb4, 0xd503edb9, 0x1dde40a2, 0xc7a7afa0, 0xa5f7fd85, - 0x718c4673, 0x2e1ff6fd, 0xaafe8899, 0x8c22a976, 0xd3b73bfa, 0xd44e8226, - 0x7c02fda7, 0x9ec2fe1c, 0x57b4be02, 0x6b979011, 0x35ef8f28, 0x80deada3, - 0xa4772f01, 0xd50f18d8, 0x9cf29929, 0x4d0f7ab6, 0xbbcf7ea2, 0xeb90ec4a, - 0x26cb876d, 0x25b1bce2, 0xd701d896, 0x1d63c3fe, 0x58b75829, 0xd59bef2b, - 0x8f71f57b, 0x547fd0b8, 0x6f0c07ec, 0x4445b663, 0xa3c6bb53, 0xa6460161, - 0x30a1f243, 0xc18daf0d, 0x37770ef1, 0xe317e3eb, 0x2a28c493, 0x044ea9df, - 0x255ce79c, 0x2da3ac2e, 0x0aeee896, 0x4ef36f6a, 0x0dfa9abc, 0x078b8d8b, - 0xd2526b7c, 0x8abf3d78, 0xbf3865ad, 0xcfc2f122, 0x08b6b7fb, 0x65fec6f9, - 0xe9bee32a, 0x35cfde21, 0xd47e390e, 0x51cf953e, 0xe343a571, 0x4abbefdb, - 0xc9059c69, 0x0f4147be, 0xc46dfc9d, 0x39fc02ab, 0xf96162cb, 0xe735f1ac, - 0xbd21f05a, 0xa48a6cfc, 0x563d7d37, 0xc0bab2f5, 0xe8d51e3f, 0xc8ab9573, - 0xa7986f91, 0xc345b7ad, 0x78039157, 0x3a2f61da, 0x9da5f384, 0x3cdce3be, - 0x01cd3890, 0x59ea853d, 0x7aa9cfd0, 0xf47631da, 0xfc01c33b, 0x3255ea2e, - 0x8b16ed01, 0x6fd8d5da, 0x22abd78b, 0x8dabe068, 0xa2ee3936, 0x1822114b, - 0x22ee35df, 0x7f6e3f5a, 0xe9045a29, 0x970c6ddc, 0xe4a31af5, 0x452379fe, - 0xb50f9fee, 0xf969b4f9, 0x7baf997f, 0x5cfd7ccc, 0x96b61fec, 0x46fefe48, - 0xa55bf50a, 0xa1484eb4, 0xec4eadf9, 0xa7bf03b0, 0x98225dea, 0xb2f78069, - 0xa08bc679, 0x7acedc61, 0x9f3c1c97, 0x3370f5ae, 0x75f35dfc, 0xd54e1e32, - 0x7b1e3227, 0x84c93fee, 0x53feaec7, 0xbcbc784d, 0xff1e4cff, 0x77d67d54, - 0x87b43ff4, 0xf826ddfe, 0xe74dfabb, 0xdf6ec571, 0x3b97f040, 0x980fc45d, - 0x505f886e, 0x3df15db9, 0xdbe4357e, 0xe404c28f, 0x7dc2afbe, 0xfe065c83, - 0x65ce0df0, 0x4982e7d6, 0xd17eb7e0, 0xeecd69cc, 0xded0138b, 0xfb017c4d, - 0x11af2f49, 0xf8270ced, 0x3583e885, 0x7cb9bab4, 0xf4106fb7, 0x4e8e1d22, - 0xa775e679, 0x20fb42df, 0xa3dfdf6c, 0x582f8fb1, 0x2878a7db, 0x46abd96d, - 0x7c75f71a, 0xb1a7a4aa, 0x6dc8be03, 0x68d5efa5, 0xb6ef7c47, 0x020e9797, - 0xdac3aa7e, 0x81f70173, 0x8b96ff97, 0x7dabe473, 0xfbe2074b, 0xf2cfaa36, - 0xdabdbd87, 0x5d2fe863, 0x5196fcb8, 0x5533a95d, 0xefd0ffee, 0xf435f6db, - 0x89db1c03, 0x0b9209bd, 0x0a2aebab, 0x0d83c64e, 0xff07ef79, 0x58b7c412, - 0x5d3dda1f, 0xeef9031d, 0x28799243, 0x948f7c3f, 0x100f861b, 0xe40a4b01, - 0x83670fbe, 0xb08f544f, 0x470aa0bb, 0x79611de4, 0xc384623b, 0xbffd50a5, - 0xdbe397f7, 0xa1a42f21, 0xe83c617d, 0xf164caf9, 0x1b6dc9ef, 0xf04ff642, - 0x34edeabd, 0x3ada955e, 0xfbc29c65, 0x7c153f28, 0xde2fadfb, 0x04d7f4d6, - 0x9c01cfac, 0xfbcf046b, 0xa9653f5a, 0xcf502bbe, 0xe7bd68e7, 0x7337aa0a, - 0xe864df56, 0x7e9ac547, 0x52112626, 0x947e64ae, 0xe5c83b03, 0x83d4b6e7, - 0x3e7c525e, 0xd7dfc1e0, 0x35f9c1e1, 0xfa384934, 0x62455e12, 0x8d1a7520, - 0xa2d5213b, 0xc0140fdb, 0xe39b443d, 0x965afd33, 0x1939f2c7, 0xfd1d0388, - 0x4b4ee3b3, 0xfc064ef5, 0x670ffd7a, 0x75f1cbcd, 0xf2e86e73, 0xb2deddbc, - 0x57b6700c, 0xfc7f5939, 0xeed44500, 0x41615989, 0x8a7a1a35, 0xf9f40d73, - 0x0e0b91a3, 0x8c7c26f6, 0x43cdf28f, 0xbc6fb3ff, 0xcaf2357e, 0x72f77881, - 0xeb7173d0, 0xc2efd648, 0xbca3377d, 0x981be1d2, 0x373c5340, 0x062837c0, - 0xbc517c87, 0x9451275c, 0xfc2dd453, 0x45629e12, 0xe518df8e, 0xc53f472b, - 0x5d8f2396, 0x23d66f81, 0x8d106f6c, 0x739fb9bd, 0x9dde5176, 0xe1e3affc, - 0xfd8f3698, 0x25ed7136, 0x75fedf9a, 0x82069e31, 0x1bceecb7, 0xba50d417, - 0x109452d0, 0xdf704d54, 0x575d4a96, 0xf6078bfa, 0x9cee7925, 0x4ebb834d, - 0xcaeadb83, 0x50e7ee34, 0x79741bb8, 0xeb0a17e5, 0xf947fc83, 0x81b1fd17, - 0x661f29bb, 0x74c1f8b9, 0x16395b9c, 0x886c93b6, 0x7a45bda0, 0x9c1a3be4, - 0x73bed28f, 0x35f7f1c4, 0x21189ef8, 0x683e27db, 0x507ec009, 0xaf0f7634, - 0x4ed513d3, 0x15634a8f, 0x721db70b, 0xb2f0a950, 0x31d7fcfe, 0x4ad7db7f, - 0xf54e6af3, 0xddbc07dd, 0xfe496f1c, 0x0df0e180, 0x6b790a9d, 0x3fc79cb4, - 0x1e793790, 0xc6cb84d3, 0x6b589942, 0xcd31fc81, 0x50b2a725, 0xba63fb91, - 0xde30daf0, 0x7ae3e14c, 0x7bb79def, 0x07bc4fa1, 0xbee0885d, 0xfbf9f851, - 0x74e0111c, 0xfd72089e, 0xe72b449b, 0x7d137c75, 0xd24bdcdc, 0x547d27c7, - 0xc056ffc6, 0xee646efd, 0xc79a3a80, 0x650687d4, 0xdcd57eb0, 0x5df3f19b, - 0xe8d54f70, 0x6feff686, 0xbfd88eb1, 0x699fa833, 0xdfec8437, 0xf5f5bdf1, - 0xfb47f8cc, 0xa74748e8, 0x4bece4fe, 0x5b4eb878, 0x4bbcebd2, 0xc2127f59, - 0x8fd1f2c5, 0xa85b7db4, 0x5a2f453a, 0xd26e239f, 0x89960897, 0x62259663, - 0x10afafbe, 0x3ad0156f, 0x15463ebe, 0xcbd35c0d, 0xfd68a6ed, 0xe13fe94d, - 0x0f5bd833, 0xe1af608b, 0x92f0aed4, 0x8218d5ef, 0xbdba8a7b, 0x27ca9631, - 0xc6bd27f6, 0xefaeefc0, 0xfd0ac3b5, 0xf37486ee, 0x66d949f7, 0x68b267fd, - 0x94fe3152, 0xfb7ae6e1, 0xb3a22781, 0xfea553f7, 0x21888622, 0x0b7af2df, - 0x1d3e718b, 0x2fda2e93, 0x69111c10, 0x2eb18fbe, 0x75ff27cb, 0x5615c601, - 0xb7ea9f39, 0x1debb655, 0x288b7927, 0xa7ac9c50, 0xca532293, 0x4a7fc825, - 0xd3d203f2, 0xcf4e6ef5, 0xf28f79d2, 0xce1ef5f3, 0x9d15a417, 0x6b25bf40, - 0x7d62b73e, 0xf8970cee, 0x9a696f2e, 0x762ab000, 0x5a441cb7, 0x809a2c16, - 0xa1d17663, 0xef4883da, 0x6adbd4ec, 0xe1d3be59, 0xd3a345be, 0xfda6a25b, - 0xe1d68730, 0x87aa3d96, 0x4da603f3, 0x790bdc9f, 0xa27be71b, 0x444baaa3, - 0x54572433, 0x012fdeab, 0xdb6f7797, 0xdf9a78c1, 0x18a3f527, 0xbdeacfee, - 0xfa99f70c, 0x4a4e9c89, 0xe81bfa2b, 0x673e2bcc, 0xf6f26c79, 0xd5126b36, - 0x5e2af42f, 0xbd6bdbec, 0xfda01022, 0xcf26deb7, 0x0e74f581, 0xc98f1f60, - 0xade8f699, 0x67da7c02, 0x6671a34b, 0x10a4b0de, 0x55194ce3, 0x1bbd456c, - 0x201921bf, 0xbf4e8ba5, 0xf9f5ee8b, 0x76eb6957, 0xf18565ee, 0x2d33b1d8, - 0xf2c17206, 0x907d695d, 0xf5d4bf12, 0xade048dd, 0xe18592e3, 0xc11a38ec, - 0x6ede86fa, 0xe648aef9, 0xd807cb3b, 0xb760c203, 0x2ceb433c, 0x99e6f20c, - 0x36e27e67, 0xe2672b9e, 0x18fabe5a, 0x922fedfc, 0x736491bf, 0xbff011ea, - 0xa03cfdfe, 0x9c9af393, 0x24467a4d, 0xcd6abfce, 0x84fe08ae, 0x690899fc, - 0x6cf91dcf, 0x2fec58d2, 0x4e1c478c, 0xf32bfce8, 0x7f5287d9, 0x6f1aeeee, - 0x8fc2cb5b, 0xb9fca11f, 0xa36fc580, 0x689ce9f3, 0xf03bff39, 0xb64ecddf, - 0x10a9ddeb, 0xb77f383c, 0x967ce3f4, 0xc3a88d62, 0xbc022bf9, 0xb714b3bf, - 0x55f88eb5, 0xf70f73e5, 0x44bdfd03, 0xe5451838, 0x648bad2f, 0xcd92f67e, - 0xfd0eac73, 0xfbfb2a3d, 0x3d3fbdcd, 0x3de91bbe, 0xc53ff955, 0x31c5a4f2, - 0xb57ecbfe, 0xd3da0864, 0x52fa2ef9, 0xa8bf4f7f, 0x3f69c304, 0x5fef34e7, - 0x1be097d9, 0xd2cda1b6, 0xcdbcd28f, 0xa1d2034a, 0x04386e03, 0x690df3bb, - 0xb05f6e6e, 0xc24d453d, 0xf817ec36, 0xee7c07f8, 0xec81e59b, 0xf6c7cfe6, - 0xc1725d13, 0xf4e5a510, 0x2c358246, 0x8fbe68f9, 0xf3c4d7f1, 0xfa77b5d9, - 0xe604f3fb, 0xe0071241, 0xf87bb62e, 0x37f80a1c, 0xf9cf3d62, 0xd7ac3cb2, - 0x061ff915, 0x25f39d9d, 0xbd2e7078, 0x55fc7a40, 0xcacc7fa8, 0xf3717cf3, - 0xebb0d1bb, 0x1c7e90c4, 0x5e487f0e, 0xafd404fb, 0x7e16e01a, 0xb1e03f6a, - 0x3f0226eb, 0x6d773bd5, 0x1d2a7ee4, 0xe5b9e81e, 0x4c1e2ebb, 0xbd789c82, - 0x0e8064f0, 0x2ffcca77, 0x2a3d7bc7, 0xe37cb54d, 0xa47f3297, 0xa445f388, - 0xbf515a75, 0x0f47ca54, 0x689fe769, 0xc8fe65cd, 0x5aeeeda4, 0x31525faf, - 0xf8a7d7ca, 0xadaec2fb, 0xde749b9f, 0xab61a555, 0x23fb65d8, 0x3325e763, - 0x79e7be5e, 0x2dced767, 0xec87bfbd, 0xfd4e1fc2, 0x3b036cc0, 0x3cbb06fa, - 0x7f10b7a7, 0xe7e8bd01, 0x0bfb8d34, 0xef6a5fec, 0x524d3f05, 0x849d9c95, - 0xc287a48f, 0xbef8ce58, 0x598ecfe3, 0x2eb6e7cd, 0x4844d567, 0x0567c83e, - 0xe5185fb5, 0x5bf30bbb, 0xc2f39da8, 0x1c86ceea, 0x7bca2332, 0x3a57be37, - 0x073193da, 0x45ef3f3a, 0xb9255abe, 0x7720cd2b, 0xd7bee339, 0xe51759f9, - 0xbe7cc66d, 0x91b1fd6f, 0x520c6704, 0xad22cf5d, 0x9c7e5ba3, 0xfc05bdba, - 0xc93081f8, 0x980aa38f, 0x0bf3e91f, 0xda15ffed, 0x33e23ef7, 0xe279d1af, - 0x738fdc23, 0x7af2b18e, 0x3ca96abe, 0xa170e748, 0x6c84011c, 0x79ce1d8d, - 0x6fe1146f, 0xbe1553bc, 0x3d45f46e, 0x1e7af5a5, 0x2bd099f8, 0xb0af54d2, - 0xfb1dac57, 0x5bcefbf7, 0x8d47d6d5, 0xbba9f9d0, 0x37767097, 0x5bcf396f, - 0x01f447c2, 0xdf2ac65e, 0x5b0ebe6f, 0xc3ac41d1, 0x9f1e6738, 0x539ce38b, - 0xc304f98f, 0x43df187f, 0x1f3a19e7, 0xf27ef8e1, 0xe1158fd2, 0x7dff60b7, - 0xdafb676e, 0xd3eb5b5e, 0xee7c25bf, 0x81ed925d, 0xf005e89d, 0x68cff05e, - 0x7bb3cb3b, 0x7c1f84a3, 0x84d4ef65, 0x2f45ec00, 0xdf044f41, 0x79642de8, - 0x77bfacb8, 0x7f53950e, 0x5f68c2fd, 0x2f345ec0, 0x069feb42, 0x7d15fb46, - 0x52837db8, 0xda0e66fb, 0xbe6488af, 0xf9203473, 0x706c7378, 0x9bdf4a9e, - 0xa814cf3f, 0xd6045477, 0xeddea2a4, 0xe5435fd2, 0x6fd43549, 0x122192f3, - 0xf951ffce, 0xf3ce68dc, 0x32738df6, 0x4cfb671f, 0x5f6f54f3, 0x697aaff8, - 0x51bcd5eb, 0x3d83f796, 0x9429e514, 0x9b63f4a7, 0xab573fac, 0x974691f7, - 0x0f99cfb4, 0x5a44a6f8, 0xd2fde741, 0x99d2c24b, 0xc2fb7929, 0x5948f3ef, - 0xe728db06, 0xc29f5c56, 0xcbd9a3f4, 0x5b7c6b66, 0x1c0d0fef, 0xcb2f2123, - 0xb70b39bf, 0x679e8384, 0x41b78796, 0xbe5a3bee, 0xfb7a0a32, 0x0c1a9f4c, - 0xa3395c83, 0xaf29dbd0, 0xaf5c62a5, 0xd74cb71c, 0xc0a582ff, 0x0eedcbeb, - 0xf7cb3771, 0x3ea302c1, 0x556fafa5, 0xa37898cb, 0x27615cde, 0x2cf042fe, - 0x9a6df6d1, 0x7d3bd7d3, 0xebe9f404, 0xf4fa8de3, 0xe40f65a7, 0xc6d2fef2, - 0x8def5b3b, 0xb90e993f, 0xfaa7226d, 0x0f7a9d78, 0x57e74dd6, 0x25db97a0, - 0xfb6b08bd, 0xdf298b47, 0x07887b30, 0xd389eaf6, 0x1d6f4c1c, 0x1f2ce12d, - 0xf08ecc37, 0xb0d76ec2, 0x06ed8c2b, 0x83fb6b37, 0x1ba628f4, 0xee28beff, - 0xf32ed2a7, 0x3065cf95, 0x0f60bcdd, 0xe515b93c, 0x7fb3872f, 0x8e5a32b6, - 0x24bbf95b, 0x29bd2e8d, 0x5fb17aab, 0x32a5e98e, 0xe5c31dc2, 0x7a678fbf, - 0x57dc367a, 0x7d127c00, 0xd2bc5db2, 0x258ccc1e, 0xe8d31ffc, 0xfb237a0f, - 0x98a36af5, 0xf796856e, 0xf59e3cfd, 0x797f9238, 0x437ddf3c, 0x7bb3ef39, - 0x3ec42efb, 0xf0c91e5a, 0xf2c9731c, 0xbcb19563, 0xb7dfe60f, 0xc5fc30f4, - 0xbcec8ac7, 0x55ed8e5f, 0x73fade59, 0x9f841a9d, 0x9acfa75b, 0x86dfc725, - 0xe1baa8f9, 0xd4dde4a3, 0x5595fccf, 0x7e6ed093, 0x7053edc5, 0xf69af6de, - 0x4369fb29, 0x4afcf3f7, 0x97d47fb3, 0xf98c9dee, 0x760764d5, 0x1e7ea41c, - 0x116a739c, 0xee9fd3d6, 0x3ef5869b, 0xe17d6f6f, 0xeb77044f, 0x5eb23f8a, - 0x6fb47d74, 0xd85fbe26, 0x5fae1bf3, 0x16bff2bd, 0xb6afce41, 0xcfd17a4a, - 0x7e8d1ae3, 0x1e6f8645, 0x7cae57ea, 0xc881f59d, 0x7f9223ec, 0xf8fdfede, - 0x5bbde9ce, 0xdda8505e, 0xd5bd88d2, 0x5c81aa9c, 0x94676b9c, 0x0692b460, - 0xed3d4a7c, 0x8d182bac, 0xa459f175, 0x5b74b89c, 0x4b181f88, 0x7fd9a091, - 0x16d2dda8, 0xf242bf19, 0x19f41d82, 0x7d297f5a, 0xf3df7ae7, 0x9168857b, - 0xdf7763df, 0xf75cb57b, 0xfc387060, 0xb09b19ae, 0xfd76e7ee, 0x77e8d326, - 0x872f4d0d, 0xacffce57, 0xeace5fb6, 0xbdb665fb, 0xb9005ed3, 0x7d33fceb, - 0xfe76744c, 0x3f9cc1c9, 0x112bb4ad, 0x577f974a, 0x72465a78, 0x65b78d7c, - 0x07e7e424, 0xe34befb5, 0xaf82465b, 0x384e7ce9, 0xff59725a, 0x85c96acf, - 0x47f3abbe, 0xc992d451, 0x992d03df, 0x4582ff68, 0x8ff853da, 0x3a78a8e0, - 0xd2dde369, 0x0cb7e10f, 0x26e87e47, 0x1a71f5e4, 0xe91f25c2, 0xa58fbe69, - 0xf9e63b4b, 0xbd9bf639, 0x7ad07f54, 0x707ca9bb, 0x9adf9cc0, 0x03e7ed2e, - 0xfa6fe243, 0xc3fbeda9, 0x213c8e70, 0x3fd7f5ba, 0xd4f38da3, 0x3c719d53, - 0x0acfa6aa, 0x6e1f4eb7, 0x80dbdf29, 0xf13a8fef, 0xf1126b7d, 0x6398a5e5, - 0x9e5fcf2a, 0xfb494f67, 0xbe790bcd, 0xe7179c24, 0xff821781, 0x67ca5885, - 0x7892be43, 0x3e3af3d5, 0xf2bfe743, 0xb04945a3, 0xae947edf, 0x7d3cf9db, - 0xde3a9740, 0xefa46c1a, 0x2e3f4364, 0x8569382f, 0x2c49ecde, 0xdaec1ab3, - 0xd81cf3eb, 0xe4378b57, 0xd6748c39, 0x10e0adb0, 0xece21c49, 0x2007ab36, - 0xf7035837, 0xd86f7e42, 0x05f8b6a6, 0x54bc3b97, 0xc0f3acff, 0x68b7a8db, - 0xe43e6c43, 0xe2fdbd6d, 0xcb1223f5, 0xdd0e700c, 0x9c875e66, 0xd87e7316, - 0x04fe736e, 0xffde80ce, 0xa0bcbb7c, 0xc8705f39, 0x83e4ff9c, 0x9c81675b, - 0xbdff55cb, 0x3f89f42a, 0xf384384d, 0x5e17d3f1, 0x2cfac68c, 0x41d94bfd, - 0x71a149e8, 0x0a6eb422, 0x56ff08f4, 0xb2e3e985, 0xf81e9178, 0x810f1e81, - 0x93a4619d, 0x683fe10a, 0xfebcb94d, 0xcb32d119, 0x5955744b, 0x64e0bcb7, - 0x57bf5741, 0x43b3acb6, 0xb71d0bce, 0x9c2ffda7, 0x6aec375e, 0xd964a3c5, - 0xc5637555, 0xd62df809, 0xf4013bbe, 0x854bfc57, 0xe7e28ae5, 0xbe0abd07, - 0xce63b6df, 0x9ace9c0d, 0xedd0f8c8, 0x2af78b7d, 0xbbca28c1, 0x5dba4946, - 0x7d615eb8, 0x1cd1a4bd, 0x36b65747, 0xd9a6de24, 0xf778be5c, 0x9f86fffe, - 0x18f1dcbe, 0x1e5c33c7, 0x05781827, 0xa7c55b7a, 0x153ded82, 0x330dbf9b, - 0x2d79cb97, 0xbfe1e7d4, 0xaee1e396, 0xcf3a5592, 0xd0c893b7, 0x574bf0f9, - 0xe1066a51, 0x8de6aafd, 0xbd9b94aa, 0x7597ecc5, 0xb0ce39da, 0x918221ca, - 0x28a1cf04, 0xdf45d7bb, 0x628fae2f, 0x18516179, 0x9cf99fc9, 0x438e708a, - 0xdda0c4f4, 0x965477a9, 0x25e2aa83, 0x571eaa1e, 0x56c5b002, 0xfc8a48c1, - 0x04bf3213, 0xd25526de, 0x3f00d78f, 0x1798cdd6, 0xab6f524d, 0x03f706b4, - 0xc0e79d2f, 0x4abd7336, 0x38d1e79a, 0xefe659c8, 0xeb9da2d5, 0x36feecd7, - 0x60ddf8cc, 0x527d65df, 0xc8556bd7, 0x7aa70433, 0xb3cb0447, 0x402398c4, - 0xef14ab57, 0x29150ec3, 0xefa0e39d, 0x2f964e25, 0xe7946ee6, 0x838c3347, - 0x0dd78390, 0xae67b966, 0xbe04cde2, 0xd670bac4, 0x1fdca9a7, 0x64e58bde, - 0x4e484396, 0x7daa3966, 0x12e39d8e, 0x825af39b, 0x1f9ac790, 0x0ad0f148, - 0xf3e47f32, 0x96709ee8, 0x4aa79a7b, 0x5d79a7b9, 0x31ff6e1f, 0x390beb40, - 0xf9b9e25a, 0xb71e1c9e, 0x89db2a9f, 0x200f523e, 0x7a133ab9, 0x41e5c102, - 0x67472eb9, 0xb04afac5, 0x9bfcfaee, 0xe0a3db63, 0xf1e512c7, 0xd86e4bdf, - 0xed879da2, 0xf003c2eb, 0x8a549c53, 0xf60c5a0e, 0xe4325ba9, 0xac7231f9, - 0x8f56ab77, 0x966519fd, 0x80ff77a9, 0xd07b29e0, 0xe9486ee2, 0xf5e1075a, - 0x27fe6266, 0x83e785d7, 0x958e46ee, 0x7963a7f6, 0x0e479f92, 0x73bf1c17, - 0xedefd6bb, 0x9a531619, 0x48f44118, 0x942c9cfd, 0xe1a8edf6, 0xa4076c45, - 0xbbb9ba35, 0x19359038, 0xb32a9cf2, 0x9afefd17, 0xa4e9e06e, 0xde52f18b, - 0xd94cb93d, 0x72f2e124, 0x5fc8dfbc, 0xf0fdb385, 0xe8de76a4, 0x347441eb, - 0x8d71cf82, 0xe8d3ad9f, 0x74cf5d66, 0xb98ba263, 0x3741b790, 0xd8b9e473, - 0xfada5749, 0x7af0dd12, 0x485d13b7, 0x6be211ba, 0x4b742fb4, 0xdf443b79, - 0x7bb7d4ea, 0x0e88b7d0, 0x6de8c89e, 0x074217a8, 0xf1181ac2, 0x252cfc8f, - 0x2a4762a3, 0x564904b4, 0x2cdc47e1, 0xd7c646ce, 0x4ac0d65d, 0x55bfa782, - 0xab00cbae, 0x653a3ba4, 0x5cf911fc, 0xd9f88bdf, 0x0b17fbe2, 0x4e2fd52f, - 0x4ab76c12, 0x2626f927, 0xa409db8e, 0xb0aa0770, 0xf68a50e7, 0xffb231c5, - 0xc46fa262, 0x5e7f51b3, 0xdcc69c4b, 0x2a7fc246, 0xfb407e58, 0xef6e7ce8, - 0x5ef6c8b7, 0xd303a52b, 0x5f6a3ee4, 0x2bf8c615, 0x264073be, 0x58d264e8, - 0x66249d33, 0x4f41394a, 0xbadd331b, 0x7e0890dc, 0x9838d250, 0xf08699cf, - 0xd85daaa2, 0x7d48cfa7, 0x4df578a3, 0xbe004793, 0xd83de367, 0xeca7a7c2, - 0x494aff60, 0x7f1f9ce3, 0x5b653d08, 0x98df7f38, 0x780f7be9, 0x17b8ad3f, - 0x250fa2ec, 0x27b15f33, 0xcb5f7b52, 0xa3bf73d4, 0xc77f8a74, 0xa62390db, - 0xfeb950cc, 0xb9ed2114, 0x338e51a2, 0x35b9ffd9, 0x3c9bfa91, 0x94f0e15a, - 0xf25770b6, 0xb455f832, 0xd1a63df5, 0x98b84377, 0x70139cfd, 0xcd4cc80d, - 0x24821f86, 0xe4e46ed4, 0xfd5a9901, 0xc806ca31, 0xc9c70343, 0x47d7a7fd, - 0x2d37e83f, 0xcfb7ee53, 0xe7a77db4, 0xbf5caf09, 0x5b584d6c, 0x5b52345a, - 0xf3a51070, 0x039ec6b2, 0x2a94999f, 0xde07ac26, 0x4d8aaa7f, 0x317b6f0c, - 0x4ca885f3, 0x8f82f837, 0xfba65914, 0xee99836d, 0xb7b4c6db, 0xb6f949dd, - 0x7ed2392d, 0x0bf3e9a7, 0x82e5825d, 0xef9231b6, 0x64896fb5, 0xd5cc73fe, - 0xed27151a, 0x97dfac5d, 0xd7f1246a, 0xe17b86ba, 0xda752e37, 0x2c7e70db, - 0xfb3a607c, 0x499b4bfb, 0xfd5c47bf, 0x4f7eb35a, 0x6658787a, 0xa87afa37, - 0x019a0e5e, 0x55ad951d, 0x36070e98, 0x997dec78, 0xcc2e29cf, 0x4c19ccaf, - 0xf32fff07, 0xf05c7384, 0x37fb7a65, 0xb091f784, 0xba0e0b1f, 0xd7c83a1a, - 0x3716e30b, 0x1a7eb315, 0xfe63ed99, 0xbc255035, 0xd4cf1d10, 0xec126fe8, - 0xd64be0a0, 0x97d8bed6, 0xdf6865af, 0x4e995ce3, 0xbe70eba6, 0x7366d06f, - 0xb6be0265, 0x9c16e155, 0x4a5693b7, 0xe77da6fa, 0xbb80bdc0, 0xfc0222ac, - 0x7ed6b8e0, 0xd16b0afe, 0x77f7ca46, 0x1c546b08, 0xe98f2be8, 0xfbe5903b, - 0xe9f7eb0c, 0xc828c42f, 0xd76ba50d, 0xfa34b849, 0xe323d610, 0x4f9c69e3, - 0xc3e4a4b7, 0x53d3a0ae, 0x766c6b20, 0x5d0308e6, 0x1e9850cc, 0x60873e68, - 0x55979d9f, 0xfa728f92, 0x32f41fbe, 0x1d306c69, 0x6a85d871, 0x76abc725, - 0xe20f0a24, 0x3b443a87, 0x241d23cb, 0xea3f808f, 0x27e7467c, 0x475e1744, - 0xeb7ad742, 0x3d6b657c, 0xde784681, 0xf4e0ef56, 0xb0977aa9, 0x5ed84f12, - 0x67f9c89f, 0xb69cddeb, 0xf7f167d4, 0x9c3deae7, 0x8a3f59df, 0x7bd42ff3, - 0x7ebbbf39, 0xabbfa722, 0x84efe22f, 0x3a4be61f, 0x93f9d1df, 0x9f3a5f4e, - 0x05aba50a, 0x33dc6684, 0x0fccf6a0, 0x79883e75, 0xf8bbf258, 0xa9cebe93, - 0x113f914a, 0xceb450fc, 0x5428ff01, 0x22f33ecf, 0xdca3b9e1, 0x1da1f1c9, - 0x0ec1f242, 0x8dcf83a7, 0x0dd8bb64, 0x32c340fb, 0x869ddb6f, 0xb95e7873, - 0xba06ac22, 0x5c36a9bd, 0x7d740d58, 0x29ac5d73, 0xfdeebf3f, 0xff50fad7, - 0x2df18b3f, 0xbb1cfac2, 0x7fa3d4e3, 0xdf8fefa4, 0xeb033a71, 0x796c704e, - 0x1edee308, 0x2ad1c1a1, 0xceddbae1, 0x08c0d2f2, 0xcfe14fa9, 0x2d738861, - 0xfb7d894e, 0x31e70437, 0xda061d6d, 0xc146b35d, 0x754ab32e, 0x1f2aa4ad, - 0xfbe8bd63, 0x2af5b59f, 0x7c630ba9, 0xfb6a3496, 0x4cff18d4, 0x57de3cf8, - 0x78a75cb0, 0xe91f8085, 0x41ec2ff8, 0x71c41192, 0x685011c5, 0xad94851c, - 0xae17b0f9, 0xe428fd79, 0x10eea574, 0x873ed5cb, 0x8428e393, 0xd8d676df, - 0x9077529f, 0xfed689eb, 0xc8c838a6, 0xf83b5ee1, 0xeb1b6805, 0x40759256, - 0x268b9f60, 0x94f1ef85, 0xd6cbdf69, 0xe2f8a628, 0xe655337b, 0xac32878b, - 0x14ca0e9c, 0x89a5139a, 0x5e9d29cf, 0x3c707f89, 0x9e535963, 0x2f81917d, - 0x4bdf6897, 0x78a62cb3, 0x321943c7, 0x98106a2e, 0x6777a505, 0x3217daa5, - 0xdc7373df, 0x24bf5ebd, 0xea757f2b, 0xe883f470, 0x8ff6aea0, 0xddb95a64, - 0x84970ca1, 0x59e741c7, 0x74e9c714, 0x72e82e7b, 0xeff8a7cc, 0xeb3f0c95, - 0x3ecf1559, 0x7bfc2cfd, 0xe30a7f15, 0x9862a9f3, 0x0ec8df66, 0xf2ce9c8c, - 0x8ca9d78f, 0xd72dfc84, 0x7fd3fc7f, 0x547c4689, 0x57694ecd, 0x690db4a5, - 0x6ce5edf5, 0xd0f6ab57, 0x9f0388fe, 0x5fcdfb35, 0xd14ff67d, 0xf897acad, - 0x5bf8b493, 0xdeaaf78e, 0xc0e38279, 0xd0afb8f4, 0x37ca3576, 0x71eaa7ac, - 0xb63fba01, 0xf78d9f70, 0x851ecd4d, 0x5d9a98f5, 0xe7c01317, 0x4aadf66a, - 0x272e2ee8, 0x5e3d5fb4, 0xd5bfb740, 0xc39fb588, 0xc384487f, 0xffad0ff8, - 0xaf546676, 0x62054353, 0x3b60aed5, 0x1c705588, 0x8e2d72c7, 0xc19023b3, - 0xe49ee17e, 0xc4f59aed, 0xedbf49f0, 0x1063bab0, 0x88417caf, 0x53addd89, - 0x7e7920fc, 0x047da39f, 0xed85f0bf, 0x1791cb2a, 0x7ef147b6, 0xff7edea8, - 0x55dbc441, 0x8dd8566f, 0x308e2557, 0xaa77aade, 0x0fe061c2, 0xc50bb035, - 0xd2e70cf7, 0x416aa3a7, 0x145a4b5f, 0xadf816ef, 0xde98ee1d, 0x35da7806, - 0xd61a5afa, 0x45d79232, 0xf814ff83, 0x5cce419a, 0x8e7ef7b2, 0xe77aa413, - 0x6df9ae59, 0x51b3c724, 0xce036f0f, 0xd80a1b33, 0x65a4bd4f, 0x05cb3547, - 0x105d23db, 0xccdb4e69, 0xd1be29f7, 0x9346fbc6, 0x4fc0ced3, 0xaacff682, - 0x4e030f2c, 0x5ad3cbec, 0xcedeab3c, 0xb3b64832, 0x0dfb7868, 0xae88e7f6, - 0xda5a4bfa, 0xfea9d3a2, 0xe7dfbb27, 0xee4839d4, 0x23ce25e3, 0x3f4738b9, - 0xf7c919d9, 0xf9d93eed, 0xd12f09eb, 0xc65ae778, 0xfb0c52f4, 0x1b20e06c, - 0x41b73fd7, 0x25f301c6, 0x5a0fd611, 0xb6673e78, 0x27ac2927, 0x9f84df03, - 0x8f9f3b33, 0xf63ef0b6, 0xab717bff, 0xc86b15b3, 0xb2eb847d, 0x5bfe8047, - 0xed11fbb5, 0x7fe5fd9a, 0xed6affa7, 0xa4529b7b, 0x3bef238d, 0xc20e3d08, - 0xd53beda5, 0x796efbc9, 0x2fef9d94, 0xbee6182c, 0xe8f81e71, 0x518e329b, - 0x043f77f4, 0x3bc16ffd, 0x596f6cf1, 0x41f7736e, 0x36c38bfe, 0x282c13f6, - 0xa1f51cf0, 0xed9d8c7e, 0x75b1224a, 0x6dadec04, 0xa8be5229, 0x933b435c, - 0xe88fdc50, 0xacf84fcd, 0x8f84580c, 0xa50793f2, 0x523ebaf2, 0xd9daf16e, - 0xfbe413ff, 0xc2ecc792, 0xfe2f7b8f, 0x5d7ea4e7, 0x0efd2a99, 0x517f608f, - 0xcc17195a, 0x4edd878c, 0x69ca9ba3, 0x9fa06e54, 0x4cc14dca, 0xed674fc8, - 0x72891ed2, 0xf9954de8, 0x46835eb2, 0xfd07e8a7, 0xceb8a5b6, 0x2bbbbcb3, - 0xb0ef404a, 0xed2518bc, 0xdf09bf21, 0xaf386614, 0xe9241a6f, 0x07f341b8, - 0xf848b7fa, 0xf8e41700, 0x4ca6f625, 0xb8fab9c8, 0x789ba24b, 0x78dab3bc, - 0xa49a224b, 0xc78b44ff, 0xdf1e7d43, 0xd3bfd826, 0xcb1864fe, 0x1efba7cb, - 0x9fe30179, 0xc730727e, 0x04a5b411, 0xf2e6ed16, 0xaee38e70, 0x082c2a78, - 0x327b3f78, 0x9f58ed8a, 0xf61ca4d9, 0xcb025459, 0x1ea28761, 0x3afe805c, - 0xe0298736, 0xc2299fa3, 0x2df2889e, 0xa80e59bd, 0x3f63afa8, 0x17b10549, - 0x4e94afc8, 0xd9f7dc84, 0x276cc196, 0x950decfa, 0xf7d0292f, 0x13eef835, - 0xc67e0b4d, 0x3ff4bff2, 0x6fea7e9e, 0xaff3bb83, 0xdb366c54, 0xd7f5f4c3, - 0x2418efcb, 0x0c7703ed, 0xcac97a92, 0x7fe92e41, 0x30796c8b, 0xf929e795, - 0xeb03ad03, 0x131fb47f, 0xd63f6f60, 0x714127b2, 0xccc1cf02, 0xdbef035f, - 0x7a759ea4, 0x42fd8dbb, 0x79462f15, 0xe774fed9, 0xb0ef7c15, 0x78729542, - 0xdbde4585, 0x99eed0ab, 0xb2674456, 0xcdf08b7d, 0x16fb6d7a, 0x8e471b55, - 0x01d6d9fb, 0xd4109fd2, 0xf0e42ff2, 0x7149b83d, 0x2c69e6e2, 0x05c86d5f, - 0x8e6e2f5e, 0x1a79f8e4, 0x87b88bc7, 0x5cfd9f8a, 0x116633e2, 0xae7407eb, - 0xd4ae7f31, 0x9dd573f8, 0x5ee0c757, 0xe5477881, 0xad1712fb, 0xbfe03e9e, - 0x4f7af8a1, 0x5f4b63e3, 0x41f99478, 0xc417ed25, 0xfcd52d59, 0x529f4bcb, - 0xba5c9e58, 0x9887eafa, 0x136dbeef, 0xb6705fb8, 0xe368fee5, 0xf8d5ec7a, - 0x0f7b5767, 0xf54a5fd7, 0xa337fb65, 0x36ad9e19, 0x5d09e00f, 0xfeddefc7, - 0x6a5ff529, 0xf242d15f, 0xf3e5ee45, 0xdc8e28bf, 0x95f027f6, 0x676ce1ed, - 0x7be7f5a3, 0x2d6c6746, 0x33ff308b, 0xbf3384cf, 0xf72b1339, 0x9e7427fd, - 0xe780edfa, 0x5db1f787, 0x02e9bded, 0x80e2d0e7, 0xae1d5fb9, 0xafdf1afd, - 0xc0c4f78a, 0xeb45534f, 0x7d68fe81, 0xdfedc47e, 0xd0fb71b1, 0x768e3cf9, - 0xf4fb0c23, 0x9ba64899, 0xbae4fd33, 0x1076799c, 0xb16d679f, 0xde09de92, - 0x674be864, 0x1b8a6562, 0x0a87a03e, 0x3387a497, 0x1ed85a63, 0xc1d94670, - 0xb64d9b69, 0xfcd3a8ab, 0x897f44da, 0x26d01fa0, 0xb58ea9ec, 0x80c72047, - 0xe7cc8fcf, 0xcefb8834, 0xd07376a1, 0xbebfce29, 0x84dcf259, 0xcf3e0578, - 0xe3f61b7e, 0x733df0b4, 0x564f269f, 0x4fdcbf6e, 0xdcaa7588, 0xeb3fb0ae, - 0x02fe7692, 0xddba5eea, 0xa972e89f, 0x6e22f15f, 0xb2e3696b, 0xa5fba025, - 0x81e6ebb5, 0x2c79f5ee, 0xb75feed5, 0xd3c32a29, 0x27fb4e16, 0x74f1f2fb, - 0x8a59aafc, 0x5c279f1e, 0x7b45f9fa, 0x2dcb2c38, 0x4db288e9, 0xa3655fd4, - 0x49c796b2, 0x395bf5d1, 0xb84f1d3f, 0x5efb02cd, 0xb9df769b, 0x70ebf9a7, - 0x524f04f6, 0x6d4fe496, 0x6f9ef229, 0xbef25bfb, 0x0a6fc5f6, 0x81fee262, - 0xfa91c83c, 0x7f047f7a, 0x72106816, 0x96e7c68f, 0x704eaec2, 0xfb306e66, - 0x9b36b273, 0x9bb643f3, 0xcd3bd9f3, 0xe6bddcf9, 0x7355e7bc, 0x7b7185de, - 0xfa09e177, 0xa103e236, 0xbe85236f, 0xfa94ceed, 0xb7d0f236, 0xc6df4291, - 0xc8dbe877, 0x1e46df43, 0xd0f236fa, 0xdf4291b7, 0x1a39f7c6, 0x7b352a9e, - 0xe381d629, 0xeb84f6d4, 0x5fbc00f1, 0x6049cc2e, 0x52ac2a3e, 0x24b0bd1f, - 0x4ec7e59b, 0x0754d33b, 0x38f499db, 0x7ca2b7a7, 0xc37ab2e3, 0x75647b7f, - 0xc76e14df, 0xdf9ae7f6, 0x6573fb49, 0xf613b87e, 0x9f55d68e, 0x13d886ac, - 0x444df288, 0xf6b60bfd, 0x556fc0ad, 0x6fec2bdd, 0x7ee15d6f, 0xfd7207e7, - 0xc7a2eed8, 0xdce3152d, 0x7d26df03, 0x7b6fc649, 0x6a3b461c, 0xac485fa8, - 0x3f21e435, 0xa1f39b35, 0x35f0207e, 0x355f69af, 0x6e3c1d31, 0xbe0bef6b, - 0x0749e27f, 0xa13af3df, 0x6cc4edd9, 0xba63cb17, 0x8f29df3c, 0xc26ca3dd, - 0x2b24bdf9, 0x1c77db8e, 0xd3dd30ca, 0x2f4b4d0b, 0xdabcb3e5, 0x58ab5f99, - 0x8cd94e30, 0xaf59fb15, 0x73e68c4e, 0xb60d16e9, 0x0dff9041, 0x440e0f70, - 0xe868e898, 0xbf10b8b6, 0xfd533f65, 0x4353bb61, 0x4c4396fc, 0x16d7d3e5, - 0x17b5ef98, 0x1f2a6d5d, 0x878cef68, 0x96ff4873, 0xd64b9f06, 0xe7cce8b9, - 0x4bd686f9, 0x847f3c56, 0x25bc56bf, 0x9a32d3e5, 0x7b40b787, 0xfe1f239f, - 0xe014ef39, 0x16c5bcaf, 0x54bef38b, 0x9d44873b, 0xb72e5cf9, 0xae2bbf0a, - 0x5dcaee8b, 0xed4b1bc2, 0x2536b4bf, 0x71dd1d33, 0x14255934, 0x2472192d, - 0xe57d0837, 0x8246278d, 0x8dd4aaae, 0xbf2a2ec9, 0xc56c0955, 0x71d3ec45, - 0xa4ae123b, 0xf8b4fff2, 0x75a2c91e, 0xef05b64a, 0xba3e0f9d, 0xbde04d23, - 0x9f6b1391, 0x3cb8e68f, 0x6d92fe8d, 0xc1d008ae, 0xf59526c6, 0xd4cdd814, - 0xd93a2eb8, 0x011f14d8, 0x8c7ca6bd, 0x717297e2, 0x0bdf49b4, 0x9aa147c5, - 0xe69b8efd, 0x2a90f17b, 0xf36a40ef, 0xf592ee5c, 0xaf6cba45, 0xe7d7b3df, - 0x47d3527b, 0x96be362b, 0x3f7d0b79, 0x2e7f783b, 0xd65784ae, 0x2f79e6ef, - 0xdadf6cb5, 0x1d7bd297, 0xd7985dbe, 0x45c6b7f2, 0x7ce3495f, 0x87c65db9, - 0x89f9b5ff, 0x4fc4fcc7, 0xc27a6cef, 0x8541fb0e, 0x1e876035, 0x46e4fe5c, - 0xae18e23b, 0xbf91b6db, 0xcc56da2f, 0xbefd00f6, 0x7c7aa7da, 0xf28f86b3, - 0x1706cab1, 0x60ffb3cd, 0x23ca4fc9, 0xa14b1c64, 0xdc35fa3a, 0x4db8b813, - 0x66bcc3c9, 0xe3b0ed14, 0x1a3bff1e, 0x37dd09df, 0x17a7871d, 0xabbd86f6, - 0xdf20f145, 0x89993ed3, 0x0f4472cb, 0x39b92fd3, 0x0869719d, 0x0a1fd5eb, - 0x8e70bed2, 0xd7e88764, 0xcf695587, 0xad123c43, 0xd83db973, 0x85e43a6b, - 0x0ffbe597, 0x8d0e7455, 0x2ede87ca, 0x169455c4, 0x744d568d, 0xd23e335e, - 0x0b660fb4, 0xfea2bec3, 0xa67e8966, 0x69498cfc, 0xce37faa6, 0x67e21a18, - 0x672aefce, 0xe99575fe, 0xdbaa975d, 0xe3856efd, 0xbf9ac67b, 0xd33b7a53, - 0xf6a60dd9, 0xe99a6255, 0x9b25975d, 0x133c65df, 0x8fa1d995, 0x41f76b95, - 0xb4dafb66, 0x9dfcadef, 0xafda6226, 0x7f3cd303, 0x8da5e794, 0x1dba08fd, - 0x9ffe367d, 0x1979ddd6, 0x898f19d1, 0x3bd85bf8, 0xe479667c, 0x42a9eb08, - 0x669543ae, 0x92caaa8f, 0xff2aa8f6, 0x9be23b11, 0x24d6ff09, 0x93754942, - 0xaa46f6c2, 0x938a48ef, 0x7df1dbf9, 0x075ef9a7, 0xf284bbfa, 0xf6316a43, - 0x35796857, 0x42e71bcd, 0xb047ec35, 0x6bfde983, 0x19f4eafd, 0xb43ecf7a, - 0x3760df1f, 0x6d8ae7ef, 0x23f60e3b, 0x8a2f4cbc, 0x497c43cd, 0x5b54cb65, - 0x74e5f671, 0x8bfdf3a6, 0x7fb616e5, 0x857e1c75, 0xdca3ace9, 0xddf191ea, - 0xd51f18ff, 0x0d6f695e, 0x3445bfa5, 0x1799f81f, 0x013c54ed, 0x5e03d645, - 0x432e81fa, 0x0dd492f0, 0x753c74be, 0x7ca42de2, 0x1c33fe31, 0x004a11f1, - 0xbc32f27c, 0xfad478e8, 0x2c13e45f, 0x013c1267, 0x3fa42786, 0xff742a31, - 0x20efc2dd, 0x84506c74, 0x3c6ef94b, 0xed24bb4c, 0xe4d30336, 0x2977dbbc, - 0xb3ebc81e, 0x7bf9592e, 0xc914bd27, 0x9319f538, 0x93b3fbcc, 0x7ee48a7e, - 0x81297999, 0xd36ffddb, 0x8fd177d1, 0x8d099fee, 0x5defd6ff, 0xddac1a2d, - 0x46211a4b, 0xc44ffb7c, 0x4072ebaf, 0xe749e74f, 0xf0d2e379, 0xf6ed4cef, - 0x951e5e1c, 0x3edaf1ca, 0xf3a88ecd, 0x4ed69f63, 0xca98b71f, 0xefa005dd, - 0x17b009fe, 0x4b4c6eaf, 0xe317be36, 0x3b63655b, 0x788af26f, 0x5dc38b4e, - 0x8a473809, 0x4d77c857, 0x27d5df8e, 0xe388fe01, 0x26bd6cab, 0x7fc7d751, - 0xe4593c3a, 0xe9c85f20, 0xb3617589, 0x3d78768d, 0xed2c1a6d, 0x7e39fa35, - 0x7a3872ce, 0xaadff636, 0x0508d15d, 0xfdeaba5a, 0xcf3a2e91, 0x8f7c5957, - 0xef7f660f, 0x85cf3e46, 0xec2e636b, 0x513cba70, 0x0fb0aab1, 0xffcafdce, - 0x9c31e579, 0xb615befb, 0x9fa3c804, 0x840aa07d, 0xc679d0ce, 0xe1a7c472, - 0xdd3fae92, 0x10f7c912, 0x1784553f, 0xea25a6fe, 0xe9975cfe, 0x0b3bdd5c, - 0x41deffe3, 0xb8c08ee3, 0x1889ad81, 0xc4cfe3d7, 0x1915beb8, 0x57d9dd31, - 0xbd66b4f4, 0xeab6f394, 0xeecd64f6, 0x791ef90c, 0x6270f7c8, 0x1e47be41, - 0xc8523df2, 0x4dbef8f7, 0x6c0c2ff3, 0x7e83cf68, 0xb22b1fea, 0x75bcf96a, - 0xbf7e4166, 0x80f08945, 0x78a2dcff, 0xc1bc70fa, 0xc4def966, 0xd57590f2, - 0x49da6bd3, 0xedd03306, 0x84392e0f, 0x8c6e6e31, 0xc7e53588, 0xea9afa39, - 0x4c52ba17, 0x0e25d7e5, 0xef5f9536, 0x7fe533ce, 0xa9a57598, 0x18cf64fe, - 0xa347fe53, 0x9fd537ae, 0xca6a9dea, 0xc7389f4f, 0x51667f54, 0xc6fca9b1, - 0xe54c4bd9, 0x4ccb7c73, 0x3fe579f9, 0xa9bfd535, 0xdca98576, 0x9c565c2b, - 0x77a17b77, 0x865fde11, 0x2de945de, 0x8d38656f, 0x9c7a3aeb, 0x7977dba5, - 0x5072694e, 0x36dea1bf, 0xd7ee25d0, 0x68070e80, 0xc0be67f7, 0x7e1bd2b9, - 0xf522a0c9, 0x417d23de, 0x42f5a137, 0x1e4747cb, 0x35a6e8b8, 0x7a2a7a2c, - 0xc4f895a6, 0x140e2be8, 0xf57e51a4, 0xad338553, 0x5f465fc4, 0x54f9e07d, - 0xb53d37ca, 0x3b0f964a, 0x51e51170, 0xf320df4f, 0x1a8b05d3, 0x7af90c8f, - 0x31e69f86, 0x6ba907fa, 0xd26ed23d, 0xa769bc6d, 0x80f0883d, 0x01e04d78, - 0x13e89069, 0x4fa201e9, 0x7d12afa4, 0x710ba596, 0xe913e890, 0xf13fd221, - 0x7fa4f7fd, 0xfa4c3d22, 0x49b7d227, 0x847a44ff, 0xefa44ff4, 0xf4e6cfd5, - 0xb71f7a83, 0x397d43fb, 0x6beb47a7, 0xf5c7fbf9, 0xb9fe9c75, 0x5ddfcfde, - 0x433b7443, 0xba31ed90, 0x7e1aabff, 0x76edd847, 0xfd1acedb, 0x9e578ac2, - 0xb2bfbaa7, 0x46b456a1, 0x5ab69f62, 0xba394f63, 0xf33d90fc, 0x6538ab5b, - 0x0f5ebf90, 0xe10d26f7, 0x98bbfbf1, 0x8fdf6b6f, 0xf203e989, 0x520a9d69, - 0x9f28297d, 0x2aba5f99, 0x0fc7f886, 0x81b5a9be, 0x74b43e5e, 0x0bfb7f7f, - 0x87da4e8d, 0x8c873378, 0xebbbf2e8, 0xf8ceef7e, 0x1e5f831a, 0x8e3d6cfe, - 0xf3c7f747, 0x473e219f, 0xf1eb93f7, 0xef6ad741, 0x707ee923, 0xef47fe3d, - 0x6092f0b7, 0x1acd77be, 0x512dcb2b, 0x38c41156, 0x35cf9c7a, 0xc43c968e, - 0xe9535c3b, 0x3eb738e4, 0x23ef1df4, 0xde2f3d52, 0x25fcdb99, 0xf2edcfd5, - 0xe6d1f7bb, 0x8f3ce541, 0xb63e4bc2, 0xc5a35ed7, 0x43bda01d, 0x753bf396, - 0xfc831188, 0xe1db2941, 0x7da8551e, 0x001c577e, 0xfaca47ea, 0xfe97f441, - 0xdd178d15, 0xc4068fb5, 0x6e21e4b5, 0x93b5406c, 0x8c36c6e3, 0xb9bdf209, - 0xded7b1e9, 0x4e22aad3, 0xd8c7e638, 0xfaa74f47, 0xefcf0266, 0xf00f73ee, - 0x5c5a7e50, 0x53a46f5a, 0xebb5de43, 0x62e67d66, 0xe97c755d, 0x4bd7d778, - 0x9e21b7c7, 0x5dfcf18a, 0x6eba17eb, 0xafa5eba1, 0x2ea5e153, 0x977f03fc, - 0xfad74faf, 0xfffb3ec1, 0xb70cfacb, 0xcc7df0b6, 0x07874ab0, 0x7ad77d70, - 0x262edcdd, 0xf1783ee0, 0xa441f725, 0x5f7cd24b, 0x8a967f80, 0xc05c1331, - 0x81cd4b91, 0xdeb4279d, 0xef59eff2, 0x077a90e1, 0x7cd60ae2, 0xbd79769d, - 0x1af521dd, 0x7ed60b62, 0x374ced2d, 0xe43d7ce2, 0xed1fb1b6, 0x1e3d70cd, - 0xa3ccebc3, 0xf1a71c75, 0x96a243a3, 0xd7120fcf, 0xf1df58fc, 0xcb8f52da, - 0xee72cc5e, 0x6e59a778, 0x514df09c, 0xd09dc623, 0xd68e442b, 0x6837e1fc, - 0x9a275efd, 0x7bd0dfb8, 0xf26837f2, 0xf93de869, 0xf26886e7, 0x01488a65, - 0x3c2f1a9f, 0xbded2e12, 0xd92ef183, 0x2f46926f, 0x8c556e69, 0x9f083d06, - 0x55f1cc15, 0x8b9077bc, 0xbf9cfd71, 0xfd38045e, 0x3f7208a1, 0x22918993, - 0x6c2123ff, 0x79039df2, 0xf55ab33f, 0x2ce427fd, 0xc2e65efd, 0xd8abdf70, - 0x4e44af77, 0x28f78f99, 0x4b8c15c6, 0xe303bb47, 0x1c9f2cdd, 0xbcb1a470, - 0x8b657d84, 0x6f7fdaeb, 0x6e92f9d0, 0x9106f795, 0x3a60dee2, 0xe9d7966d, - 0x86fe41fc, 0xed0215ac, 0x71cdb826, 0x1ffb7a38, 0x6b0ac6ba, 0xfdfccf41, - 0xfa7bb987, 0x66f3aec3, 0xb0f1a0ec, 0x7b19bf83, 0xf7cc78c5, 0x163ed8cd, - 0x39d98699, 0xbd3179cd, 0xa74e793b, 0x26f1aee7, 0xcf7c6b08, 0x1af1d678, - 0xcf1d4f8a, 0x2f5e02ff, 0x2fd78774, 0x37290b06, 0xa23e4a47, 0xac2ab7e3, - 0x1f671ef3, 0xa5445c63, 0x33e9e243, 0xb87b8c80, 0x3cf15775, 0xfd17a93e, - 0x7545ef81, 0xd43cb8a3, 0xc736250e, 0xc77f5e70, 0xef83ccec, 0x7c122746, - 0xea7c39d7, 0xd9cbc250, 0x492660fc, 0x0d93e230, 0xfaef7c0d, 0x07aab3dc, - 0xeaa57ff2, 0x4f01eb5e, 0x3f655379, 0x95e6f8a0, 0xc509f864, 0xa3e3eee6, - 0xaf121d2b, 0x32b3feba, 0xa7f788ad, 0xca241570, 0x3de4d5f7, 0xe81e5d72, - 0x8be3261f, 0x3dccfbf5, 0x232307c9, 0x1feb1f24, 0xbeaef926, 0xf38ed49e, - 0x48cfd449, 0xf74953e2, 0xb03eb045, 0x1a4de5db, 0x78ca7f0a, 0x75a79261, - 0x97a3bfbd, 0x5af03f7c, 0x68d0f991, 0x643f8fca, 0xef2a0113, 0xf14c2f18, - 0x946f8564, 0xfa16bbf2, 0x44b098fd, 0xfc0cafd2, 0x611ddc20, 0x32346f7a, - 0x8f94ce2b, 0xd533f4f2, 0x6a95198f, 0x0ef58f2a, 0x4fc79531, 0x7be537cc, - 0xaa655d17, 0x58f667df, 0xefafbe53, 0xa4fd5306, 0xbca669f2, 0xe49297ce, - 0x76a03127, 0xc0fda9ae, 0xfd5312ba, 0xf9857f14, 0xf7bf54fd, 0x9e025648, - 0x697f9477, 0xbc87966b, 0x96116aaf, 0x90ef5d91, 0xde5a3afc, 0x5ce89907, - 0x6491efc4, 0x0cccfd34, 0x8a8dfa8f, 0x46292673, 0xae24f7e1, 0x60f99b73, - 0x3f39a261, 0x2af795de, 0x2b9c6e96, 0xa828fe34, 0x6a929e80, 0xf3efa6ad, - 0x347c6a86, 0x9eb2e457, 0xefeb5dfe, 0xff5a621b, 0x4e5d7c50, 0x05e7cf0f, - 0x6f9ed2dd, 0xf9ec179c, 0x9ec0bc46, 0x9ec3cc6f, 0x7b0fac6f, 0xf61cb1be, - 0xc179637c, 0x8c1d3321, 0x83a66238, 0xe99a8e2b, 0xd0cfa740, 0xd5b2baf5, - 0xa7c21f4c, 0xb07f94f8, 0x6a7f575e, 0xf5d09fa6, 0xd78b0921, 0x1153826f, - 0xfbfca48f, 0x642eb5eb, 0x87d73abd, 0xf6f90df0, 0xbe50e0da, 0x48785b27, - 0xe4b77815, 0xd79e6d51, 0x27e5ad0d, 0x7d5bb6c3, 0xae7de6bf, 0x5f4355d1, - 0x871d5749, 0x1f070f9e, 0xffa4347d, 0x02f9fbd7, 0xfe3b3fa8, 0xf41db262, - 0x45df2ed1, 0xee1f036b, 0x49b715dd, 0x77bcba7a, 0xe39533f2, 0x9a598e18, - 0x82ebf014, 0xf036df18, 0x6bb39bcb, 0x1367f815, 0x458ed145, 0x8ff9cb88, - 0x17e464b0, 0x77f7940c, 0xdf2b7645, 0xe2f9d07f, 0x17192482, 0xf35432d8, - 0xdc647af3, 0xa543f3ce, 0xe3ca24dd, 0xe2e338e2, 0x83bf796c, 0x05e499d4, - 0xe1c7c039, 0x47c041f0, 0x69df85b3, 0x39b9b56c, 0x86ffc46e, 0x83f7e02a, - 0x72f90b1c, 0x35df2680, 0x0070e47c, 0x85eb41fe, 0x1c1d9ce9, 0x5be29870, - 0x99736e87, 0x892d39f2, 0x76c3faa6, 0x79e54dbb, 0x79532cc1, 0x298f21c1, - 0x28c8e23f, 0x8e2bfd53, 0x2bf94d7a, 0xea9a275b, 0x9169fd5f, 0xda249f29, - 0x077e061f, 0x3e8f522a, 0xe2553433, 0x7e382dc9, 0xb19dc16f, 0xa6a7def2, - 0xba72eb5f, 0xd3ecf71e, 0xde5439e8, 0x71f7681f, 0x5f43751c, 0x187be1e1, - 0x129f4d0e, 0xa7c03d66, 0xde772dc5, 0xe39bf0a3, 0xe578f596, 0xd3417d4e, - 0xdd39740f, 0x35ecaf10, 0x082f2bc6, 0xe03dfeeb, 0x3dd6d2ff, 0x7681fe14, - 0x9f86df39, 0x88def9da, 0x3c28570e, 0xda38b533, 0xefee8e2d, 0x25b2d8f5, - 0x1465259d, 0xfef41dfd, 0xcad3cd98, 0x365fdd6f, 0x4fd5a79e, 0x0bf0d5f4, - 0xfba567bb, 0x305bc7bb, 0xbe67ce4c, 0xd4f372c5, 0x32cf8e6c, 0x3bdf83bd, - 0x51fdea5b, 0xf3b74ab9, 0xe323105b, 0xdd8c44a7, 0x79edfa0d, 0x44cf893c, - 0xfbe468bb, 0xff9c5a47, 0xee5b6b4d, 0xf3454419, 0x7bda4ded, 0xe81b0160, - 0x9258d261, 0xd884f2c3, 0xb35765b6, 0xc7a2e493, 0x3f6cacea, 0x35ddbfe9, - 0xceb8248b, 0x49031bfb, 0x407d01ef, 0xb4be81b6, 0x71e54721, 0x1b9ec1ae, - 0x4df6fd81, 0xfb3d9c67, 0xced08405, 0x754fa90b, 0x874c6f43, 0xaffe3cfa, - 0xf143ede3, 0x42adeba4, 0xd74c338b, 0xd7f1d2e0, 0xf0d07769, 0x707fdfa7, - 0x6d15b32f, 0x8a3df272, 0xd2db8889, 0x4725afd7, 0x86ad65d2, 0x3f03d40f, - 0xa15ea9ea, 0xfb031d9a, 0xc7708772, 0x43a1bab8, 0xc2bffd3d, 0x9eff8e8b, - 0xc4f557ee, 0xc2f9421f, 0xeab7dd77, 0xd9ff4e89, 0x3e06577b, 0xb468e321, - 0x5ba40975, 0x677d3fd8, 0x6f3f7994, 0x8d7696cc, 0xa2beda71, 0x6799ddf3, - 0xf60217e6, 0xaa5586f1, 0x39e42fc6, 0xc4529c5e, 0x3a8b11ef, 0xe533cb17, - 0xcfd62f1a, 0xc80f85d7, 0xf5aee0f7, 0x455c2516, 0x9b6692f9, 0x15a048d8, - 0xf38fbbfb, 0x1b93bf66, 0x449efe71, 0x3726cdc0, 0x49b4b71a, 0xb94fec09, - 0xc5ecbdfc, 0x5c7ef94e, 0x8bd9bbe8, 0x2f17fd35, 0x86df602a, 0xcfee65fa, - 0x8f6bced6, 0xe12b7cf0, 0x0ba5bd67, 0x02de8d7e, 0xe8311df2, 0xf3b4aac3, - 0x8e969c70, 0x24fc3737, 0xc2795df1, 0xce16446f, 0xb76b46f3, 0xf89d7471, - 0x9d2afdd5, 0x1cc3c27e, 0x171a1faf, 0x4affd670, 0x1a7e7774, 0xd3d37fdd, - 0xdff4e83e, 0xa85f877c, 0x1e8969c3, 0xff043e05, 0x57e8dbbf, 0x8248f3f9, - 0x3127fd90, 0x6ab48ff0, 0xb98d89fd, 0xf44fdddd, 0xf1c5d8ad, 0xbe2cab10, - 0xf25c40ff, 0xef1fea19, 0x3ce5deb0, 0xf8fb8090, 0xd3bb3493, 0xe4d6f3e5, - 0x7ef2d1b0, 0xe55f8740, 0x2898eef5, 0x1f1373ef, 0xba77d815, 0x08aa7f1f, - 0xfbaa42f6, 0x466b7c49, 0x3f75fe31, 0x14707149, 0x61b339c3, 0x484f0db1, - 0x7b7c3eb6, 0xcbbb8461, 0x403ad27f, 0xe4f4e7c6, 0xc97e9947, 0xb8cdfdc3, - 0x73f71574, 0xca453b2c, 0x2cf78d6b, 0xd90d9d03, 0x67986c26, 0xdffbadab, - 0x23929819, 0xf852d1f7, 0xe21b7bd2, 0xac28567e, 0x84572c07, 0x7cc4071e, - 0x6c5fcf5e, 0x3285f2d2, 0x992acb7f, 0xc5ded56f, 0x3bd9aada, 0x98a44f30, - 0xedf0f40f, 0xf3043d9a, 0xe0798a40, 0xf21af83b, 0x83c86be0, 0xbe0f21af, - 0x0d7c1486, 0x51444bdf, 0xfd2a9e72, 0xfb0de33d, 0xf19efe03, 0xfe09b906, - 0xfe1e631e, 0xf87d631e, 0xf0e58c7b, 0xe1cb18f7, 0xe1e631ef, 0x87d631ef, - 0x8798c7bf, 0x1f58c7bf, 0x1e631efe, 0x7d631efe, 0xe58c7bf8, 0xcb18f7f0, - 0xe631efe1, 0xd631efe1, 0x58c7bf87, 0x629d737e, 0xacdd07f2, 0xba503bbd, - 0xa3e98e3e, 0x2928b539, 0x3ff7d687, 0xc7e7ff23, 0xf3ac54b6, 0x6efc25de, - 0x47845560, 0x44d373ae, 0x2116eeb9, 0x0e7db9d7, 0x76edf3af, 0xf1942f99, - 0x03f4a1c2, 0x74f8cabf, 0x0a4157e9, 0xf8520abf, 0xafc29055, 0xfd2ade32, - 0x57e1482a, 0x55f877c1, 0x82afc290, 0xa4157e14, 0x8520abf0, 0xfc29055f, - 0xbf07682a, 0x55f8520a, 0x157e1df0, 0xe0abf0a4, 0x038231fb, 0x2e1d15fe, - 0x26e9f9c8, 0xd0e8943d, 0x4cba87a4, 0xc6f9c879, 0x8df390fa, 0x8df390e5, - 0x8df390e5, 0xc6f9c879, 0x8df390fa, 0x88f11bf9, 0xef296f71, 0xde41db1b, - 0x9a73e637, 0x86c1affc, 0xf9c37935, 0x46b69157, 0x2e298f29, 0x9e72eb92, - 0x58ff059a, 0x1c92b86b, 0x763921eb, 0x8d676fc5, 0x89f892bf, 0x2b976f16, - 0x6f582dda, 0xbad37bf6, 0xe38282f9, 0x3bfe7383, 0x7f75cb91, 0xbad1ff2b, - 0xac14ede7, 0x90cb6c37, 0x3dede970, 0xd522a5c2, 0xbbe577eb, 0xbe3a17af, - 0xa5f98f5e, 0x28520e01, 0x910710f3, 0x1f33bb77, 0x2d5bedf1, 0x5d0b8c8a, - 0x4372e329, 0xe349aae9, 0x3b2d5b4b, 0xbb50440e, 0x83c562f6, 0x5699077b, - 0x0f96c871, 0x43e6d53c, 0x89cba89e, 0x6b83e2d5, 0x903c42af, 0x7f6eb70e, - 0xf7c13e24, 0x0bb746dd, 0x738d197b, 0x8ec217cd, 0x64985bdf, 0xda04f297, - 0xea1cdf41, 0x0c9bbc57, 0x4732bdf4, 0xff3e7b9e, 0xe8caabb2, 0xb5edd0fb, - 0xdd1ee157, 0xeed908a4, 0x33478f37, 0x2a34a71e, 0xc9fef09b, 0x8bc2ede8, - 0xd4bfb1fb, 0xddba1ee0, 0x71e32f65, 0x4eff7c5d, 0x4378b7ef, 0x2c17df32, - 0x13e3ad16, 0xf0a127d9, 0xde3ae6fb, 0x62af7e68, 0x0fe2c47e, 0x2ffc8ec1, - 0x7121c3df, 0xc3dcfbf1, 0x6c7866b9, 0xc4dbe221, 0xe40ef95e, 0xabc5e1e4, - 0xbe5c137a, 0xf2077c80, 0x5f6a2f9a, 0xf966fce3, 0xcf93240e, 0xcf8f8648, - 0x857e41c3, 0xe298ffdf, 0xe5e968df, 0x15e0bdc6, 0xdfd404b6, 0x0b503c2e, - 0xaf790906, 0xb6579f55, 0x57096238, 0x95e22f40, 0x11fd0378, 0x7a0198e7, - 0xf8d8f3c9, 0x56a9907d, 0x46fc0d97, 0x5d8a7397, 0x7542ec72, 0xf7df0c74, - 0x2e13910b, 0xb8e6f636, 0x8e3d7f8d, 0x93ef83a4, 0xce15df2f, 0xf88f8572, - 0xb9e6f807, 0x5977193c, 0x91c3ecb9, 0x38aed496, 0x8129d392, 0xf3df78ad, - 0xe88eea74, 0x11cb0a51, 0xdb5fc087, 0x7be79f1a, 0x5eabc582, 0x1710fbe3, - 0x96881f1b, 0x7fa4aaf7, 0x9bc34ca5, 0xa85a6f6e, 0x16994fad, 0x5ebc743f, - 0xe74bcfbe, 0x71f7bf30, 0x72c6d1b1, 0x28bca846, 0x880feb84, 0xb46f2b73, - 0xc5d3ddf1, 0x27578b6b, 0x777eee8a, 0xcfe32bc5, 0x349771b5, 0xa84e38da, - 0x2b477b5c, 0x965877f4, 0xd2e8726a, 0x27efe66d, 0x4fe44272, 0xad44fdfd, - 0xaf5bf14e, 0xa83964cc, 0xee71c6d6, 0xb94857f3, 0x0110ec48, 0xbf9867dc, - 0xef059c62, 0xe5dfcc58, 0xd0dd28f5, 0x7c9a3bd1, 0x12830934, 0x8a5ea7de, - 0xed32be60, 0xcfce3f52, 0xe9c894ba, 0xe4b2978d, 0xd11dac77, 0xbca16b4b, - 0x26beff5f, 0x1c44cd17, 0xb2e40165, 0x1dd74c3e, 0x2218d744, 0x4357e357, - 0x302bcabc, 0xf9b24fc3, 0x734e2156, 0xf7c146d2, 0x7e432691, 0x90d982a2, - 0x2fb00aa7, 0x3ef90a52, 0xef8544c6, 0xbe1e4cb7, 0xb407db4c, 0x11f3042f, - 0x37c3f77e, 0xf1006a7e, 0x3b7db337, 0x7d77582c, 0x6dfcf83f, 0x64e60efc, - 0x7bc762bf, 0xcf4d3e81, 0x743de9d6, 0xd4882c5f, 0x694e63ec, 0x8fb4eaff, - 0x9c7e5801, 0xc446f227, 0x2d802eb3, 0xb0b69fb3, 0x6ca8aa84, 0x1b9c9e59, - 0x94236379, 0x6ed37fac, 0x9162df32, 0xfe489ff7, 0x717578e3, 0xe50fb0a4, - 0xf92ad78b, 0xe1d79788, 0xd8d87afa, 0x777ac349, 0xe74941d1, 0x03eeccfe, - 0x5df960bd, 0x4cff2619, 0xf84a5a68, 0x105a3ec6, 0xfc63fad3, 0x5c84d0d2, - 0x889f1de1, 0xf9f5c877, 0x02e2208a, 0xdbf96ae7, 0x8ff2bd9e, 0x278c9c6b, - 0xedcd8fce, 0x3fe22377, 0x38fe65fe, 0x7f1ab15f, 0xf14daa37, 0x3de57379, - 0xdf5809c8, 0x7e76ecc8, 0xa66660c7, 0x212f9e4b, 0x72db9676, 0x845df2dd, - 0x694b7b10, 0x846f3cb6, 0x8f3c9dd5, 0xb66e3afd, 0x3ef3ea57, 0x33df336e, - 0x5cead3d5, 0xbff83769, 0xa0f127ba, 0x7ffbde45, 0xf1d812c4, 0xa06bd122, - 0xe6016fb7, 0xbde208fb, 0xcf1f7e19, 0xa3477f4f, 0xef694f93, 0x74f4e865, - 0xdf22eeac, 0xda712897, 0x9e81aadd, 0x7c28d6ca, 0x4ea4b11f, 0xadf627de, - 0xfcbde451, 0x8f57ec1e, 0xdf9af9cf, 0x17fc7a51, 0xc350b211, 0x91fb7cef, - 0x5d291cd7, 0xdd53fdf8, 0x7f926caf, 0x6f103306, 0x9c36b73f, 0x7afe41df, - 0x018fd158, 0x87b6647f, 0xf11269d7, 0x1a9fd434, 0xbe29fbe3, 0x07238897, - 0xf05c6f61, 0x7df8b7f3, 0x29bd9ae1, 0xf161eefc, 0x78d5bcee, 0x61ebe547, - 0x89723bbe, 0x2e9d8b7e, 0xea90e43b, 0x973e58c6, 0xeed1f417, 0xf6768ba9, - 0xf3ebe9e7, 0x0794ae60, 0x9c723c8a, 0x453e9a0b, 0x354db308, 0x7fe793d5, - 0xedd43ee8, 0x95f6a1a2, 0xbe2af7d0, 0x7b029ecb, 0x5760dd89, 0xb631edd5, - 0x7073e3ac, 0x77b7cf9e, 0xaf8dbbff, 0x4d4776eb, 0xa9d85d9f, 0xe84f66cf, - 0x9d7fb903, 0xbd1d82e2, 0x11bee9cc, 0x8765f5f1, 0x14f0886c, 0xf2dce293, - 0xe4bb92dd, 0xb72525bb, 0x9b3f31e6, 0xc7c9358f, 0xbc5187bd, 0x9402cb8f, - 0xdfbcf7c6, 0x657bade7, 0x53d01ec0, 0xe0f7cbd0, 0x7b5e5ccb, 0x2a2e419c, - 0xef4c526d, 0x17f9e818, 0x721da573, 0xc019a93e, 0xa6b74ddf, 0xd086f1d8, - 0x108f127c, 0x46baf837, 0xaa3b7a27, 0x932571c7, 0xf941c552, 0x9dc114ae, - 0xfe33c722, 0x9349514e, 0xaa063df9, 0xfedd72cf, 0xafee28dc, 0x4ef345d8, - 0x3862ea41, 0xa78c0f09, 0x3fa87bf6, 0xebc38f37, 0xd80c1a51, 0x8f983760, - 0xcfca1678, 0x186c0575, 0xbe51a4a7, 0x2b5be28f, 0x89adf1c7, 0x2e40e7b5, - 0x03ecbab0, 0xa360f28c, 0xbe78cf7c, 0x0411fbf6, 0x65cbcb2f, 0xf3dc2784, - 0x867defd2, 0x8358abe2, 0xd629acbf, 0xad365f2c, 0xe67d61b3, 0xc35ef0f4, - 0x971d1a97, 0xfbe18e34, 0x2f5665f5, 0x69f097df, 0xb2ebfef8, 0x27e1bbf0, - 0x90fcd399, 0x8d79052d, 0x3c097d2f, 0x829e06f7, 0xd23efc19, 0x678e70b2, - 0xe26ae39e, 0xfbe276f9, 0xe40fc201, 0xe3115715, 0x8fc4e89b, 0x66b2c038, - 0xc176faf3, 0x65df2513, 0xfde62e6f, 0xb3eac8b7, 0xac708cbb, 0xfb819fdf, - 0xdf68735b, 0xe127fde3, 0xcc7df1f2, 0xc8dc0f53, 0x3806fbbf, 0x8f28e781, - 0x3bde027b, 0xba61ba22, 0x4167e9d6, 0xfacfdc81, 0xacc35178, 0xec3f0ed2, - 0xf7a9f6bb, 0x06f3e420, 0xffd86f5a, 0x76a7da7b, 0x71a4005c, 0xddf265ed, - 0xab7dd0ba, 0x9f7d57ef, 0xdf56fbea, 0x8ad98fcf, 0x174a8982, 0xbdf3a1df, - 0xf06eb9f6, 0x77834934, 0x84aeb6ae, 0xc18557d7, 0x986237ae, 0x53f3dfdc, - 0xfd1ffbcd, 0xbd54dfa1, 0x03306c7c, 0xfaf53df7, 0xe3f3b8fa, 0x03ec3b64, - 0x30ea5bd0, 0xe5fd674b, 0xe262df5c, 0xfc9da51f, 0x04aafb63, 0x0a1d8ff0, - 0xdf96e1fb, 0xe5bee523, 0xe17bc8cf, 0xf8bf9667, 0x77aa2cf6, 0x0b8dc1fa, - 0xca2ff78c, 0x2c5f9282, 0xfc0b7924, 0x0f269163, 0xe5f4cc6c, 0xe7ec330d, - 0xc99ffbb2, 0xdb98fec4, 0x6f0a7792, 0xf9bcd1a8, 0x3f3fa3bd, 0x5787d2f3, - 0x5dcebbb9, 0x6b251e7d, 0x3b15b5de, 0xf493788d, 0x0756777e, 0x38a55b9f, - 0x6953e8b7, 0x61f33163, 0x8f7a4891, 0xa1eeb5d2, 0xa8dc50f4, 0x5a579cb0, - 0xfea03237, 0xd2ebf22f, 0x8df953b5, 0xf4bd7d28, 0x73f45f77, 0xa67f8757, - 0x35734eb6, 0x4c3d9e7a, 0xe5b9c3ee, 0xbc45f629, 0xf8ec53ff, 0x5a39cdbd, - 0xf3329cf9, 0x72f5cef7, 0xd5fbf275, 0x9fb827d8, 0x58eaf584, 0xcbf6936b, - 0x57ad97ed, 0x1d02e432, 0x9d9ac58e, 0x6f66a172, 0xcbc9a45c, 0x8d8b5eb4, - 0x71f8b5eb, 0xcfa55eb9, 0xbc17f5be, 0xd3f34653, 0xef93a3de, 0xecb4940a, - 0xb39b75e0, 0x852d9d66, 0x5864fdea, 0xa8fe298a, 0x05cf36b4, 0x35dcfd3b, - 0x07e06d1b, 0xf126193f, 0xf3f74a16, 0x1d62f8b5, 0x148f38af, 0xaf473f83, - 0x83b83e0f, 0x5975b9c6, 0x77f1b478, 0x3d1a02ed, 0xc6c6d697, 0xdad2bc61, - 0x7fa17be2, 0xe840e7e9, 0x2e113bfe, 0xf50945f7, 0x6279fd87, 0x55ef878c, - 0x377ed7cf, 0x43feb42f, 0xdafddd1a, 0x4cbfdf26, 0x92796c8a, 0x226a3be3, - 0xe913e03c, 0x8c01ade9, 0xdc067a0b, 0x2f7c8b76, 0xf5b2bd33, 0xa241c073, - 0x20f5c73c, 0x105b7bc5, 0xbf2813ed, 0x79ef22c9, 0xdd32aaa5, 0xa607e1a7, - 0x5e8b9437, 0x5f1efcad, 0x2151bbe7, 0x9b176af4, 0x1fdde0d7, 0xefc12f7b, - 0xa9f4e9a6, 0xa7d3a3f7, 0xcd3dbf4e, 0x9cf7d76f, 0xcd1489df, 0x49e592ce, - 0x0bb8d076, 0xbfc41bee, 0xf35df16b, 0x35ef6bb4, 0x4c37ce76, 0x65c7defe, - 0xfa974df3, 0x6df3cf52, 0x66e84c2e, 0xd4f3a1be, 0x431e89f7, 0x694fe9df, - 0x1394fe92, 0xd4639d0a, 0x70b2c4ee, 0xe7d3ab8e, 0xbff5dba5, 0x8f87bdef, - 0xf669c586, 0xc828d6aa, 0xdfb5f397, 0x99411151, 0x86a9f7c7, 0xaff9faef, - 0xf3a75fbf, 0xdab593e9, 0xef5a28f9, 0x75167ec1, 0xf50f7c69, 0x2889d358, - 0x627313bc, 0x6f4f848c, 0xde4dab77, 0x76511673, 0xbbcfde37, 0xfe3cd6e9, - 0x8d8594bd, 0xbd9f587d, 0xf98d2ea9, 0x587e4dc2, 0x1ea74517, 0x83e348b0, - 0xaf16b791, 0xd7f502be, 0xc2eff0a7, 0x4e7a742d, 0x43f6e7ad, 0x2313903d, - 0x53daa79b, 0xfa961e59, 0xbb17ee82, 0x7c451155, 0x127c0d4f, 0x3fb2cbfb, - 0xe2cfe71d, 0x983f52f5, 0xe06b1164, 0x50d81d3f, 0xf82fa134, 0xfc8ac3c4, - 0xe60d9a3d, 0x0e86bcf7, 0x7c02fa2a, 0xbc5df426, 0x5e2d6d5b, 0xe482a7e8, - 0x16d1d80e, 0x9e588b3a, 0x93e345bf, 0xf8db9ac7, 0xaf1d7ebd, 0x78bfe08f, - 0x7ec42aa7, 0x1a276a14, 0xff07d9a8, 0x7b8faf1f, 0x0080003d, 0x00000000, - 0x00088b1f, 0x00000000, 0x7cb5ff00, 0x65545c0b, 0xce7bf8da, 0xc0cc2b99, - 0x1245c880, 0x85848b87, 0xd780c034, 0x508151da, 0xb9bba0bb, 0x658e21ba, - 0x500665ca, 0xd7775ddb, 0xa6a18cfe, 0x45fa7d66, 0x80ed65a6, 0x76c36a97, - 0xa8283448, 0x59990bc9, 0x6a37627f, 0x5b63b92f, 0xba402de6, 0x6dbfedfc, - 0xbcf3cf7d, 0x511730e7, 0x6fbefddb, 0x797bf9fc, 0x9f5ef3df, 0xcfbcf3fb, - 0x8c346339, 0x63181b75, 0x418e8b2a, 0x89486839, 0x8d8c9964, 0x615f6909, - 0xf6c3894c, 0xc645db25, 0x7cfb4046, 0x1962c893, 0xfa31d72b, 0x1fbf8f7d, - 0x3c1f7631, 0x42f3c337, 0x07d634a9, 0xcc37d7fd, 0xd6c972a0, 0xf1ae6dc2, - 0x2509258c, 0x606393b1, 0xb66ae3c0, 0xce258a07, 0x2b307719, 0x8da4d3cc, - 0x73c325d2, 0xc7292bb5, 0x496f9fe0, 0x0c4943e3, 0xd4699dc6, 0x7b4377cf, - 0x414e6981, 0xba5f8c14, 0x325b2a33, 0x6f5dfbfb, 0xc91b1811, 0x4673a558, - 0xcc614b1c, 0x67e1ddf1, 0x1fb0a94c, 0xf304d398, 0x7709e57f, 0xa38ba0bb, - 0x82492dae, 0xb3aa3c23, 0x7fa058a7, 0x6f31d895, 0x4e73cc12, 0xa04def70, - 0x5338e6fe, 0xe5a1fac0, 0xccc63ae9, 0xff398ce9, 0xcf3487cf, 0x3b89e2e7, - 0x8778c016, 0xce047f73, 0x1ff8f553, 0x6c3201f2, 0xb2cf689d, 0x8dbce1e4, - 0x1c124d7b, 0x56637b74, 0xbee39c09, 0xda46c7c7, 0xf79f2f33, 0xa8b668b6, - 0xdbcbda04, 0x6957c118, 0xd48ee85f, 0x5eeddc20, 0x696131a6, 0x28689a62, - 0x956c48cf, 0x52dbca07, 0x06b9a2d8, 0xe10dbb7f, 0x899eeb00, 0x025492dc, - 0x9f7b15ed, 0x79433248, 0xa5ebc8d6, 0x9c7a7f7b, 0xddff4045, 0xd5e20d5a, - 0x0b1a62ae, 0x25d7bb8c, 0xb250dcd8, 0x12c668f2, 0x7d6ea310, 0x59b19199, - 0xaf9a7096, 0x630e7b62, 0xc17dfeb9, 0xab3f6a73, 0x8fb8c562, 0xd903f531, - 0x8bfca1cb, 0xe21f7bca, 0x7ab52ff3, 0xf1192b8b, 0xfcbc2662, 0x84548b65, - 0x05fbaeed, 0xfac05636, 0xac1a637e, 0x6ac9165f, 0xf4a17c71, 0xcf049b57, - 0xb2101c57, 0x787b30b5, 0x1ee6b766, 0xd1169103, 0xd389b559, 0x75768ad9, - 0x7fe02251, 0x2d408b45, 0x3357950e, 0x2f2abe1c, 0x80e6664d, 0xb6b656fd, - 0x8eb0cc68, 0x09ce19a3, 0x539e1dfd, 0x5e78a59a, 0x7cb185b6, 0x89fe27c0, - 0xa53e6bf8, 0x3f0037b9, 0x2e1cadd5, 0xbede56ce, 0x3b900338, 0x1362b699, - 0x26dea0d2, 0x6b3ebd50, 0xaa35fcc2, 0xfcfe7ac0, 0x9a586935, 0x354c4e08, - 0xf0025490, 0xa3d194dc, 0xd73bfc41, 0x5d42f3ca, 0x0d5eb01d, 0xde48e512, - 0xf1c06a9e, 0x3caf1a66, 0xd146b677, 0x6c33af78, 0x3609bb03, 0x61506d51, - 0x4434ef59, 0x56b3b960, 0x715950cc, 0x09166173, 0x1611dfe0, 0x6122c591, - 0x3d5eaaca, 0x3b501240, 0xf6845870, 0x83fb48dc, 0x0c719f48, 0x33e802b8, - 0x06057991, 0xf9dfdff4, 0x7fce2e59, 0x17df18cb, 0x5eaeb60c, 0x017e7d33, - 0x8b26c3d0, 0x5f4c8e7c, 0xc8f1d22e, 0xb0af4043, 0x6cd5a7bf, 0xcf073e83, - 0x42e6c257, 0x08c2cc3b, 0xb984dfcf, 0xafdfc0f7, 0xce226f31, 0x54de74cf, - 0xcc9af71c, 0xc35a25a7, 0xf5f60106, 0x63fb149b, 0x053b8fb8, 0x116cf8f5, - 0xc58d2071, 0xfe6afd7e, 0xc2796d9c, 0x4ffc03a6, 0xa367e8e7, 0x4062e645, - 0xf1519aa2, 0xc163a406, 0x60ab6366, 0x0f3307fd, 0x2e80cbdd, 0x31d01e1e, - 0x5eaf9c2d, 0x7d3dcfcf, 0x0094ec20, 0x2a8f46fd, 0xf4165916, 0x2958ab37, - 0x29943ff4, 0x9fd8557a, 0x9fd8dce9, 0xbe6d0ae9, 0x8196590c, 0x7a88d0fc, - 0x78eff51b, 0xca011bf3, 0xe1e2e944, 0xe2573848, 0x3d4b052f, 0x3c1b29f4, - 0x85fff4fd, 0x5352f4b2, 0xfca1efcb, 0x19bda475, 0xb0727751, 0x501d94f8, - 0xa3c9b0f6, 0xf9f264b3, 0xf1dff702, 0xa2226fab, 0xfabeff45, 0x7bef4e07, - 0xcea58ad9, 0xe9b8c022, 0x9b57921d, 0xfa7ef975, 0xa9e361e3, 0x39e18fd4, - 0x5ba20dfb, 0xe1ffb010, 0xd37f710f, 0x14af0675, 0x17d4e381, 0x38ff3a7c, - 0x751d1e66, 0x284646fa, 0xb1913ef8, 0x8c3cdc58, 0x7068b81f, 0x6fb9c137, - 0xa14ff991, 0x488b1eaf, 0xf191e9f8, 0xe991c0a4, 0x7e9122b2, 0x5e8ad5eb, - 0x4cb385f0, 0xe8d67f3f, 0x5e0cff38, 0xff386d12, 0xcdd6b960, 0x8ec18a60, - 0x5727d254, 0x007fa792, 0xd740ca79, 0xfb6a97bc, 0xf90fc233, 0x78fc074a, - 0xc02f0c97, 0x25f9c33f, 0x64bbfe79, 0x1065ddb8, 0x127e9c39, 0x6e992702, - 0xf650ba14, 0x5863982f, 0x9f1fb469, 0x47ddd7ec, 0x8f099323, 0xe383ffe3, - 0xdfc213ef, 0x01d62737, 0xff51b11b, 0xfc784598, 0x579fc05f, 0xf80bfeb4, - 0x9fc50eeb, 0xe23d7f57, 0xd2d171ef, 0x0880fc84, 0x26d2a1c8, 0x0658f9c2, - 0x932ffe23, 0xe09b2cc2, 0xffe4767c, 0x8fef889b, 0xfc2bdf22, 0x37d8a63e, - 0x49e4f51e, 0x7dc19ec6, 0xb50f44f9, 0x10a766a7, 0xbac75f9f, 0xf01db013, - 0xf117379c, 0xe876d82e, 0xfb7d2c24, 0x5df5865e, 0x1ecb0615, 0x5bbf6f38, - 0xfe61a974, 0x8ef72886, 0xc36eb0a5, 0x1716995d, 0xd59633b6, 0x3ca07286, - 0xbe7a82cc, 0x85cb8a21, 0xa4e90586, 0x277e0f87, 0x73c2ad25, 0x34b3082c, - 0x6c86ff41, 0xa01323df, 0x6cd630de, 0x57d74171, 0x1dbe9605, 0xd1d1cfc7, - 0x38730d3a, 0x323c36dd, 0x057a8dda, 0x7af3cff4, 0x1e593fa8, 0x0d9cf0c6, - 0x6884b68d, 0x2297cba0, 0x61b3a3ec, 0x4e24a3ff, 0xd0c90dd7, 0xa136e50e, - 0x387dc164, 0x6fbe78df, 0x17b082df, 0xfa2cc2f7, 0xd0591034, 0xb195727e, - 0x42a5e509, 0x73a57797, 0x75c63779, 0xc9c2076a, 0xd4659d35, 0x937ffcc2, - 0xbb814be9, 0x556c6360, 0x0afe1fb4, 0x70c8c59d, 0x7a735617, 0xe5974d73, - 0xd7733562, 0xe65f080b, 0x96f8070b, 0x42414169, 0xadd93469, 0xe5faefb8, - 0xf7091780, 0x527fe1cf, 0x619ee564, 0x2847e7f8, 0x4c88f32c, 0x328fe404, - 0x0ca3f9c6, 0x6fe908e9, 0x0051d015, 0x75df31fd, 0x65c3a751, 0x6bf1823a, - 0x70d3258d, 0x3f85cfbd, 0x89e363e4, 0x87f34a7f, 0x3656675b, 0xf40b0397, - 0x9fd899f6, 0x51148eed, 0xf130ae5f, 0x7f644ef5, 0xc5f51a36, 0x79bd5fc9, - 0x23c7961d, 0x86cb6e4a, 0x7c16dbfe, 0xfce2845d, 0x353e096f, 0x0b6fe39e, - 0xb468fffe, 0xbf56ca43, 0x43fef449, 0x192859f7, 0xaf4e5032, 0x15a67d04, - 0xb074e4b0, 0x74463ef2, 0x896ac890, 0xfd65e36e, 0x47a30c05, 0x00f37539, - 0xbcca8ed8, 0x9747fff0, 0xce896c74, 0xa2c69f5f, 0x7433ea82, 0x0bfd4109, - 0xcf41c94d, 0x171f8d6f, 0x39a67cf4, 0x3b3ea83b, 0xff505263, 0x82d32ddb, - 0x9c4e77ea, 0x8e7fd419, 0xdd504e6d, 0x1f244cc6, 0x738aea3a, 0xe1bb013f, - 0xdc92bab5, 0xe397544f, 0xd0f6aa63, 0xe805b37e, 0x5f3bdb24, 0x91ea0935, - 0x43265687, 0x11cb537d, 0xf43c4f5e, 0x66e03245, 0xf9d1cb73, 0x53dbd02a, - 0x45f43c6f, 0x6d1fd40a, 0xa7cfe2e9, 0x40a362c0, 0x39bcb6ac, 0x9af805df, - 0x8adf629b, 0xa9779af8, 0xf98a28f6, 0xbdccd7f7, 0xb942592f, 0x06746730, - 0xc53727ec, 0xbf3e10fe, 0x759ef62b, 0x1ffb0091, 0x46ab5b7d, 0x5d98bf3c, - 0xa1e915b2, 0xf3a722ff, 0x91978853, 0x96097eff, 0x8a61d903, 0x3c92bd9c, - 0x03adf854, 0x1512c6f4, 0xa54749c2, 0xe544ceb7, 0x2a78baa1, 0xd999d48f, - 0x57638012, 0xc795065d, 0x7ed42cea, 0x95226ebc, 0x546cea27, 0x4c575bbe, - 0x095d7765, 0xb2ff0a95, 0x6a0d96bd, 0x2a974224, 0x4fceb4ea, 0x63d2578f, - 0x69d92820, 0xf9d09f05, 0x39adbd4d, 0x9d75ce9b, 0x6959e909, 0x81f9da3f, - 0x9dfa0459, 0x3d11d56a, 0x9b74354f, 0x475e5675, 0x22fbb8b9, 0xbc118af3, - 0x5fb02a9f, 0xfd1b278c, 0x030ea998, 0x841b4bf5, 0xefd8597e, 0xf79404cd, - 0x16356b53, 0x509e63b4, 0xf61e9733, 0x90df146f, 0x20e31d70, 0x05d86cca, - 0x903ad518, 0x6ba07157, 0x63f439f1, 0x0f77283a, 0x4746f5f2, 0xf9472ed7, - 0x60ccba34, 0x95f2e7a9, 0x08e24be4, 0x2fee026f, 0xda86a571, 0x198f628d, - 0x9d5f60e5, 0x69d21677, 0x0ae72c81, 0x30ef5c34, 0x80bde411, 0x576dfb7c, - 0xedf3da22, 0xd02f9edc, 0xfa44ec96, 0xfe7156ae, 0xf77a3165, 0xd5475c1e, - 0xf42cf15d, 0xb44d89eb, 0xc568426c, 0x6069641f, 0x14d617b7, 0xeddca267, - 0xaf885b61, 0x13fd5ec1, 0x338fdbd2, 0x9945df81, 0xf89e6048, 0x4da6f0e2, - 0xd7adda02, 0xce5d21e7, 0x300f9ad5, 0xf65f07e0, 0xdcfbd100, 0x7a1e7348, - 0xafecbe0a, 0x7cce3d79, 0x26e78040, 0x00bf3036, 0xe9cf55ea, 0xf0049f4d, - 0x1513d3a9, 0x4b69af54, 0xc0127d30, 0x07f855a7, 0x09b747fa, 0x0ebb942a, - 0x04a72b79, 0xb7c405fb, 0x0d73f8b3, 0x0680dfdf, 0xd98bd8ed, 0xb06fa266, - 0x0fef4997, 0x9bba34cc, 0x2371bf60, 0xa057b36a, 0xce6994fd, 0xea497ec3, - 0x63f40881, 0x1555bffa, 0x19efc9bb, 0x78c9f888, 0xd33d7d3f, 0x287b5121, - 0x70e6b5dd, 0xcd26af7f, 0x50f119b0, 0x51d3af1d, 0x88b171d9, 0x92569d91, - 0x4db97686, 0xd0cbfdc3, 0xb8737bf1, 0xaf5e491e, 0xa240b921, 0x0b6cb608, - 0xc5dd4a63, 0xf8d63226, 0xbf21b08b, 0x34c9c007, 0xc83f6563, 0x41476235, - 0x1b7f505a, 0x8e7a1ff6, 0x8ff31cf6, 0xbb49794f, 0x5e4aad63, 0x2965e90f, - 0x183fa373, 0x72abc72a, 0xc0b965a3, 0x8c74fcf1, 0x9cf111be, 0xe77d0126, - 0x504cc950, 0xb2338626, 0xd75f1337, 0x773e91bb, 0xa7fd39eb, 0x2ddcbc89, - 0x309afef2, 0x577a42e6, 0xb94d87fc, 0x79b929f6, 0xe6978f34, 0x91b25a91, - 0x879813ae, 0x24ec57d6, 0x43d81fa5, 0xaa02127a, 0xd7c47481, 0x161c4954, - 0xa672279e, 0x448ce515, 0x4fb1b0fe, 0x5f77e403, 0x40aac478, 0x78e355fc, - 0xe9b8e043, 0xef194e34, 0x4fb2255c, 0x245c9047, 0x89a6723a, 0x4b562fe4, - 0xfe8088ec, 0xa0d6eb16, 0xf5c6539e, 0x14fc1c82, 0x9047f0f0, 0x087e588b, - 0xffd710f2, 0x2c43c833, 0x10f20aff, 0x3c824fdb, 0xf207d2c4, 0x063fdb10, - 0xbce58879, 0xe4568dbb, 0x69b69a9f, 0x7e20d3ec, 0x017ddb50, 0xc369def5, - 0xa64391d3, 0xe1e4dea3, 0xe1cbaf9f, 0x2def457e, 0xa0fd9f1c, 0x00ffd1bf, - 0x8a6b5cba, 0xef1eb2be, 0x1ef9b237, 0x7cb6d380, 0x27f4876e, 0x1cd2faf0, - 0x226dd535, 0xb7e38edb, 0xfaf86be5, 0x3e396229, 0x79f345b7, 0xb245d37b, - 0x9e4ea69f, 0x9e0724b6, 0x3da162db, 0xbdef5fc7, 0x8db73f81, 0x7a43ede2, - 0x253e7e56, 0xeff8a4d7, 0x652fdce9, 0xbd012764, 0xff4afcd3, 0x3e7226f7, - 0x4eefed0c, 0xc3dd8b13, 0x992de3c0, 0xd02f896f, 0x483e469e, 0x6a8be00e, - 0x4285f133, 0x55fd0a87, 0xa73872e5, 0x073a6569, 0x43f042dd, 0x3a72831d, - 0x25f64f4e, 0xe0c6c5c0, 0x9905bb3c, 0x01f9425f, 0x0a07d44a, 0xa07c283f, - 0xf0227bd0, 0x3fed1099, 0xf421cdc7, 0xca8f94aa, 0x358ee8e7, 0xdaf09cfe, - 0xdfa136a1, 0x87cc3377, 0xc1c513e3, 0xfe46ef77, 0xd19a358c, 0xc87c2cf5, - 0x1c9c3b50, 0xc2effaeb, 0x570b9143, 0x7065c780, 0x5ff2f0d0, 0x39c90385, - 0xbf48e394, 0xfdadc8c3, 0x5db2d139, 0x44f7e9ce, 0xd21f6d8e, 0x57a0bf51, - 0xafd0dfa1, 0xd9dac367, 0x7f39f2db, 0x05547428, 0x89eb103a, 0xcbd4ce78, - 0x9e729ee5, 0x632e73a1, 0xc2d2ff24, 0x9e287b78, 0xc8057395, 0x0139c3bf, - 0xb8c61ff1, 0xd81d717d, 0x4d4fe817, 0x3ed335c9, 0x567e47fa, 0xcff995b6, - 0x6f0e477f, 0x88944a7f, 0x32fd141e, 0x8b482ed4, 0xe90664e6, 0x3f42661d, - 0xfc4b53af, 0xe67f05ee, 0x3e871825, 0x3fe49b21, 0x71e320bf, 0x1158fe70, - 0xafbebbed, 0x63d42e0d, 0x4e06a37d, 0x6fbe300a, 0x6436183b, 0x136ed897, - 0x07deef40, 0xd4f5063a, 0x2c7b9005, 0x7273b19d, 0x73cfa11c, 0x73fa24f1, - 0xa6243b35, 0x3b4a5003, 0xf4879abe, 0x6d53b4b4, 0xf6d0b8a2, 0x3d218ec7, - 0xcc156e9e, 0xb5f49768, 0xbfa1f1c2, 0xd6e8c1b3, 0xa822ff43, 0x0665ff63, - 0xd7ccdb8d, 0x4383f8a3, 0x7d53ef5e, 0x85c60a75, 0x1350ec66, 0x2f3e97dc, - 0x3b3ed1b9, 0x0aa57dbc, 0x02dda7eb, 0x4571838b, 0x04aeead2, 0x2d3e57a8, - 0xce30b458, 0x8b3a2861, 0xe7ca82f1, 0xf30bc599, 0xc918b657, 0xa0da5dcf, - 0x6017d8fe, 0xb7bb945f, 0x29eed06a, 0x5edc19df, 0x0eb83bb9, 0xeff922f8, - 0x00f68668, 0x8e6dfcf9, 0xcdec8631, 0xed1b2c71, 0xe3c0d64d, 0xbf7c8ab9, - 0x71756edc, 0xcb82ba39, 0x8cbec66d, 0xea5f7f45, 0x63e92afc, 0x91cfaf03, - 0xfea0a7eb, 0x2f1c57f9, 0xe5aa5c0a, 0x604f3fb5, 0xb79c0f56, 0x426f53ba, - 0xfdbabfff, 0xb71811ef, 0x51f309af, 0x22bd9f7c, 0xdbded099, 0x10b926d8, - 0xfd0ecebe, 0x56e0112e, 0x8d3de07d, 0x5f7088d9, 0xadcaf64e, 0xe31eb5cc, - 0x64515edc, 0xdd4744dd, 0xb666a714, 0x4f38a581, 0x84debb5f, 0x2bf54076, - 0x8ddd741f, 0xd30203f5, 0xfb471e23, 0xee964e88, 0x2da58640, 0xfbe426dd, - 0xbc4244e9, 0x913d9e22, 0x8865af84, 0xe033c477, 0x212cf11d, 0x51bc713e, - 0x2274e6e3, 0x73f4fd51, 0xde0abf1c, 0x1acda48b, 0xe46caf6c, 0x63b19e78, - 0xa230b6cf, 0xe9933503, 0x7a7ef080, 0xa6bbc727, 0x14669d73, 0x08636fd2, - 0x876bb41d, 0x77f700e8, 0xe0841d19, 0x8df002bf, 0x0e942072, 0x93dff142, - 0xd806e5c3, 0x429fa7df, 0x7e08dbfb, 0x23c7f301, 0x1ef55646, 0xcaf5818d, - 0x973bcfa2, 0xf8d8fb43, 0x08da5897, 0xe4157f8a, 0xe66bfc62, 0x5d10eb3b, - 0xc85eb33d, 0x57a97a46, 0x813cf6fb, 0x70a88b71, 0x27f4e38a, 0x32f9d9cf, - 0xfa20bb9c, 0xd816a49b, 0x5a6bcd7f, 0xc928deba, 0x35ec8715, 0xf129978c, - 0xc533c074, 0x5a1d9cc9, 0x2d6b171e, 0x73fa05b4, 0x5cfc09fd, 0xb2819a85, - 0xc017e8e5, 0x608eb87c, 0x555e7ee3, 0x28178f07, 0x1295597e, 0x8e0e6837, - 0x77a6081b, 0x2e455fa8, 0xc6a55f8f, 0x3b466cdd, 0xb3017ebc, 0x4d5ea587, - 0xcc78f03f, 0x74dfb2d3, 0x0af1fb45, 0x1bb1427a, 0x6e382b99, 0x65a9c8a1, - 0x8f1ef913, 0x6ab8e2fe, 0x76fdc604, 0x8a8f840b, 0x704f900e, 0xdab70ade, - 0xf802166d, 0x19ffee49, 0xedc01bd2, 0xa0f6ab8c, 0x19dd2128, 0x990ebf68, - 0x8e91ab3e, 0xd695bce0, 0x9cf02237, 0x38ae590e, 0x7f148dda, 0x8a5b64ab, - 0x612aee90, 0xf430ef3d, 0x0b5cf954, 0xa2d729f9, 0xaccec527, 0xb7ee0d6e, - 0xce487731, 0xe01eff8c, 0x396401bb, 0x992e7bd7, 0xf12332fe, 0x99906fde, - 0x879f9123, 0xedc09ff4, 0x5cfe4537, 0x3c581dbf, 0x6e71de60, 0xac05531d, - 0xa673e37f, 0x4f78faa0, 0x9bff507c, 0xcf41ccda, 0x4119bdb3, 0x598f73cf, - 0xdd79ea82, 0x4ffa8313, 0x5416d0f8, 0x0e2be49f, 0x4ce53fea, 0x307d5049, - 0x9573ce13, 0xe35bc1fb, 0x33fea085, 0xf9a0facd, 0x05446767, 0x320d07d5, - 0x52bb647c, 0xce5f77b1, 0x686ef6e5, 0x76f7c0a9, 0x8a3af04b, 0xc4e77ebf, - 0xd8e6f5e0, 0xa1fbd782, 0xfa0bd978, 0xc27e0554, 0xb15fa073, 0x13f81dfc, - 0x9a13f02a, 0xfac09fc1, 0x604fe08b, 0x027f01e9, 0x7f025fdb, 0xe0adeb02, - 0x20fd604f, 0x6f583ff8, 0xf2a62bab, 0x6a12ba95, 0xbafc16bf, 0xc98f75e4, - 0xd7971eeb, 0x74e177fd, 0x5def9e42, 0x9c6ebe79, 0xdcffcd2f, 0xbc563c59, - 0x2d3cfc04, 0x87c6acfa, 0x5f0ac37e, 0x062dc611, 0xc61892de, 0x7ddd99a5, - 0xf5062eac, 0x338a08d9, 0xb78192b3, 0x7d52ae31, 0xc9b4d520, 0x0fecfa8c, - 0xbef3e2ef, 0x7c8cc956, 0xefeda879, 0x85cf3811, 0x5f74614b, 0xef107a4a, - 0x5461bf1b, 0x31cf04df, 0x05b33a0e, 0x37e90804, 0x0bb7e90f, 0x4ddd4a69, - 0xcd25bdf7, 0x53c41a2d, 0x3c29f215, 0x0ea3cb7f, 0x635cfe7e, 0xf61373d0, - 0xe54ab287, 0xb9c238a6, 0x2f3e6536, 0xf1a477f5, 0xcf73cf7b, 0x053f5e1d, - 0xe2cb6ff5, 0x5e7f7811, 0xec5efcd5, 0xc7c157bd, 0xc85f07e7, 0x76cafba4, - 0x9fe0cf98, 0x96aed9cf, 0x8eff7ceb, 0x68a296b4, 0x02cd1c54, 0x05c50b1b, - 0x5fee85b6, 0x38f6daaa, 0x65556e50, 0x0066addc, 0x248f7e9f, 0xbdf837c7, - 0xb8c4c391, 0x22f9e71d, 0x5f57ef02, 0xc3bd1cf7, 0x38edf886, 0xf6eb811c, - 0xfe414ab7, 0xb72b68d3, 0x355b478f, 0xad0bbf84, 0x5ef02387, 0x30e7a377, - 0x4bcabb87, 0xd7243fe7, 0x7824a1fb, 0xfe7449b7, 0xd0624b8a, 0x5586763d, - 0xb66679a2, 0xb9e2358d, 0xbd7c3c7a, 0xb799ab1c, 0x825e2da7, 0xbf1e3ffb, - 0x7b224f20, 0xca350410, 0xef661bf1, 0xcaa43b41, 0xf386d923, 0x79e40aef, - 0x4e9cd4bb, 0xdfdb4adf, 0x78f8f285, 0xd26c88f1, 0x699f8a11, 0x916f76e5, - 0x7a869ec6, 0x3660c7a4, 0x583f9d22, 0xfc446a9c, 0xdb12c21e, 0xec69778b, - 0xe6c7bc06, 0xba98f5eb, 0x7aee9023, 0xb425735a, 0xf2f99477, 0xe88775e5, - 0x2e6f087b, 0xbbb953c2, 0xf8f380d1, 0x73dbc7f1, 0x7fea26ac, 0x3cdefddc, - 0x327aabb4, 0xe92ec9c2, 0xa7f230d2, 0x5db99aab, 0xd891d3dc, 0x924f7818, - 0xf2fd9563, 0xdaf0910c, 0xfb96a6d7, 0x0587bddd, 0x39d353f5, 0xde0eec2f, - 0xea7dc98f, 0x1dc7b451, 0xf50c4b4f, 0x1b5d43a2, 0x6cffe78b, 0xcafef067, - 0xd43b3865, 0x00d8d8de, 0x0fb4757a, 0xe8818df1, 0x13e15dbc, 0xc153e133, - 0xb7064f63, 0xf9e27ae7, 0x65a3a4bd, 0xe5f5d10f, 0x64eea4f1, 0x7f121ff4, - 0xe778a3a9, 0xc567fcb5, 0xaff0086e, 0xea8bfa18, 0x313cd4e2, 0xbc1f6fc5, - 0xb6ab6b96, 0xabbf448e, 0x1ecafc84, 0xac2cf606, 0x3a7b44e9, 0xb61ff292, - 0xad83bae1, 0x76bfba6a, 0x7d66daea, 0xa0d97602, 0xf6051805, 0x2d53b83d, - 0x0cd97bdf, 0x952ed768, 0xcccfdaed, 0xf4097cf6, 0x488d73af, 0x866473e7, - 0x27d31f91, 0x5bcfbdcb, 0xbb24ef92, 0x426498e1, 0x8786687f, 0x668ec1db, - 0x7b56d76e, 0x2a63ff92, 0x6acdedda, 0x8a60d4cc, 0xed94e21d, 0xddb2d390, - 0x80cd7a7b, 0x4e9bfc86, 0x8c963d81, 0xbb5b2a79, 0x33b9e112, 0xb3d91673, - 0xec99a94e, 0x83db6589, 0x6fb007ed, 0xcf55ea82, 0x7217da85, 0xdc13cb7c, - 0xdb87f8ae, 0xc67643ac, 0x0a67f438, 0xc871a9a5, 0x78c82f0f, 0x959bfc55, - 0xb7942de3, 0x9e6551b3, 0x1021c4a5, 0xfb9d355e, 0x6edf702b, 0xfc859847, - 0x10af558d, 0xe4bffb5c, 0x3c7f4c7e, 0x33f47823, 0x36fedf0e, 0x6a35e74e, - 0x48f98dc1, 0x34b64035, 0xaf704e9f, 0x6bb338c1, 0x13e48230, 0x17c8c563, - 0x7f70162b, 0x5f3186d5, 0x7e156b28, 0xb7abd108, 0x54527ca8, 0xb3689c80, - 0x02bf50a6, 0x3ea3b30d, 0x90b4695b, 0xe3a31b7e, 0x6ae17a76, 0xc3d2364f, - 0xb5c7f018, 0x31f8f101, 0xfb010186, 0xc7807eed, 0xc27895ff, 0x1d49951c, - 0x191fa015, 0x95fd435b, 0xf0a241f9, 0xdf9ad7f1, 0xfc1bf304, 0x23bc03f3, - 0x585fde11, 0x93b7a42d, 0xfff728e6, 0xca97c4b5, 0xbd002e79, 0x63181c61, - 0xc7378834, 0x9fc837ce, 0xf5eeb273, 0x8228ae38, 0xf708a3ef, 0x5e30f583, - 0xe79651fe, 0xbcbc79b1, 0xf9152e4d, 0x7b6790d5, 0x95f50adf, 0x593ff679, - 0x8899ae49, 0xb4ca573e, 0x9c4cf602, 0xbbf9186f, 0xf0891de2, 0x03f005fa, - 0x5ac2fbf2, 0x64169cc1, 0xaf3a712f, 0x3cec4de1, 0x454ef4f3, 0xdd6cb838, - 0xc6d79819, 0x5a2d7f38, 0x05a737a5, 0xbd2007de, 0x0251ffa3, 0x2fd1f2ff, - 0x5372bfe3, 0x57946dc5, 0x8cd62ab5, 0xc83517f7, 0xa6d7290f, 0x87ba50ff, - 0xb7a44edf, 0xa0b5a66a, 0x0b69a97e, 0xa1516e7d, 0x084dfe3d, 0x74c9245f, - 0xe81768da, 0x5bf1bd7e, 0x95a38f15, 0xbb37140a, 0x4e911a0b, 0xcafd87e9, - 0x7e71b9a7, 0xfba0b3cc, 0x391886ae, 0xee862bef, 0x9f227ee1, 0xf7952eff, - 0xa3efe40d, 0xc6324f6a, 0xf93a8e71, 0xe602d53d, 0x52dd7ba1, 0x6f654dd6, - 0x2f01f578, 0x8d1aee4d, 0x7607f87e, 0x1a91c52d, 0x511936d7, 0xb5b166ce, - 0x031fbc26, 0xfbee7936, 0x1bdb2bdc, 0x9468f7a1, 0xc7e7959f, 0x92bccaf3, - 0x83a03cf8, 0xf8a38033, 0x57c7cb9c, 0x02207fbd, 0xfefe7ee1, 0xca7ef3fd, - 0xb9020fd0, 0xd654f305, 0xbdd064b6, 0x67758b8c, 0xabf1fbe4, 0x1fc153e0, - 0xf08399b4, 0x0eb9670a, 0x0d9f33e0, 0xd36e63e4, 0xc0a9f0b5, 0xf03d4939, - 0xe8250463, 0xa1439231, 0x5ee05678, 0x3cd56acd, 0xeefb56fe, 0xb3ffe802, - 0xed19a2b5, 0x7ef0cbca, 0xf578fc0d, 0x28d791fc, 0x257b3f90, 0x5a78297c, - 0xff54bcc8, 0xfb8f8a30, 0xf144a170, 0x7c69ffc3, 0x4bd9e435, 0xb7c2aef2, - 0x257a7ca1, 0x2ab45cbe, 0xf8437f84, 0x2d2f8874, 0x7f002ff0, 0xc41155f6, - 0x1d7e0a8f, 0x5193f066, 0x2d1875ff, 0x3e39766e, 0xfdc5dfd1, 0xec0ab654, - 0xf087e149, 0xe3fc8fab, 0xad017c50, 0x541f50d8, 0xa9f305e7, 0xc92bc782, - 0x7dee452d, 0x4d47bcc4, 0x7067dd02, 0x9685fe3e, 0xfb94e9f2, 0xe2dee50c, - 0x6fae3cd1, 0xc08fcb42, 0xa27bc16e, 0x233d194d, 0xd5ebded1, 0x7bf0f328, - 0x74d68fd7, 0xcd7cc68f, 0xb2f1a68f, 0x4cf3c357, 0x8c2dba94, 0x4a3f03c7, - 0x6e10bad0, 0xa6e3091f, 0x91f01da3, 0x783bcbf0, 0xc6634e3d, 0xe9b882fa, - 0xaaf7a826, 0x83e1f895, 0x5376fcb2, 0x0982d1f9, 0x604fd405, 0x661e1047, - 0x3ad09581, 0x0c5d1082, 0xe7e8f9fb, 0x5ef07363, 0x03ff3940, 0xf48e3c79, - 0x431cf91b, 0x095ff6f1, 0x045f6f14, 0xf784c3aa, 0x289fd302, 0x93f6814e, - 0xa6cd4ebf, 0xc115cafb, 0x4dfea3eb, 0x56e538a6, 0x4b96e79a, 0x99c5ea03, - 0xe90d7dfe, 0xbc8b82cd, 0xa0d8c97d, 0xf45b667c, 0xbb27ee38, 0x8f512353, - 0xf06d7a29, 0x60437ed8, 0x1cacf51c, 0x8faa1e77, 0x5029247b, 0xf7b1be2f, - 0xa79c74e1, 0xb2cae35c, 0xf98f3018, 0x1fb424a9, 0x943ef7ca, 0xdeed764e, - 0x9fe8e98d, 0x9c3d3794, 0xb87aa36e, 0x1523fc9d, 0x7df9f73f, 0x0a6d7693, - 0x9d6fa3b0, 0x52fbedc0, 0x68851bdd, 0xf1bacedf, 0xb71875f3, 0x816bfb1f, - 0x590b70e2, 0xb7d43af7, 0xaf9c1965, 0xe48e8358, 0xf747cc3f, 0xddc67ba4, - 0xfee51bbe, 0xabbf8cf1, 0xcdfea097, 0x657cd153, 0x0e39bdcc, 0x041b6fe3, - 0xfbf9bf8a, 0xd77ba68f, 0x4d056bc5, 0x51ea0c7c, 0xc7fd779e, 0xe38228bc, - 0xbbb21b3d, 0x356cbdb0, 0x75a59f6f, 0x3ce0f6b7, 0xcf28684f, 0x4a65140a, - 0xf63dc049, 0x3df8f31f, 0x72cda2dd, 0xcebcb1be, 0x8db16dd8, 0xa3fce781, - 0xfe567f8c, 0x3b83c901, 0xb6dcbc65, 0xf123bdfa, 0xdaa46f30, 0x2b9467fe, - 0x3a7e3eef, 0x4159e50d, 0xa44cd9f4, 0xfb1ab1f3, 0xee781593, 0x2bc52d26, - 0x528959ad, 0xb9cff41c, 0x5863da7f, 0xf8bd5a2e, 0xfb8c0ac9, 0x1f91d76e, - 0x856feca6, 0x5fd11660, 0xd3f8dc3d, 0x676e107b, 0xa479e71e, 0x8faf1a2b, - 0xe2fe5abb, 0x1f3c75b3, 0x1d3af9fc, 0x99d42f95, 0xb88e1998, 0xea9e2eaf, - 0x5333afbf, 0xfa73e6c9, 0xaea6f252, 0xa5ee5f34, 0xb65bca30, 0x1e51d06e, - 0xf6d6ae7d, 0x6bc01e55, 0xa6ce0dec, 0xc6b9f28d, 0x576cf8c2, 0x83840cf2, - 0x2ef2e375, 0xe54f6134, 0xedeaff71, 0x64490d9e, 0xf53eaf87, 0xcf3c054c, - 0x0ef92fcc, 0x5e76ebc7, 0xe1c178a4, 0x10ca87f6, 0x5a4de5de, 0xdcf93e7e, - 0x8f4f1e67, 0xbce3127b, 0x7fc9a96f, 0xea79d9af, 0xde508d99, 0x26b979bb, - 0xe87fde90, 0xf795bf79, 0xbabe2d73, 0x75fe1c12, 0x89387abe, 0xf809a7f8, - 0xe7dff32a, 0x6bd59aab, 0xf3737e08, 0xc3e6c64b, 0x5da8cffe, 0x674fc849, - 0x744cddc6, 0x0814eaee, 0x571c8afe, 0xf3e6a7c6, 0xd12ae8fb, 0x48ec99b3, - 0x057f8e59, 0xf7c2239e, 0xd2cff68d, 0xaafe8ed1, 0xcf55c16d, 0x3d0eb07d, - 0xe99b8c22, 0x9e7d0ca8, 0x62a7b1af, 0xc8be715e, 0xe7d0e7ed, 0x712be7b7, - 0xc5b71e78, 0xa790109f, 0x458d84e2, 0x13fea346, 0x972061bc, 0x9eb76d9d, - 0x06ffa155, 0xc1c7e17e, 0x38fb2876, 0x695faf40, 0xab2ad7bf, 0x5f951e71, - 0x50f84eee, 0x3d00de64, 0xc617c93e, 0x0eeb01bc, 0xa6d02bf9, 0x049efba1, - 0x37880b92, 0x6bea87cc, 0xf584d71f, 0xc78e1ab3, 0x97e083be, 0x930cb8f1, - 0x3ce7fdf2, 0x0b3e7edb, 0x79e86ce5, 0x4f395fab, 0x7b68e1f4, 0xe740a2e8, - 0x9556799f, 0xbff3ed75, 0x167cf7b1, 0xdaacefe2, 0x57fe8f97, 0x8597c69f, - 0x957ea878, 0x157ff3cb, 0xc57b4a0e, 0x138f0d06, 0x23f2260a, 0x140ba50b, - 0xc63be807, 0xedd500e3, 0x0e9e48bb, 0x4c78f076, 0x145dd88d, 0xda8bf187, - 0xcf285d53, 0x5fb9e306, 0x28dbf306, 0xd65521cf, 0xa481aa83, 0x1ed72039, - 0xee07a219, 0xfe419e0f, 0x1e3ce0d5, 0x6561e507, 0x2bb43385, 0x433f21ce, - 0xe4aad97b, 0x67e748f5, 0x507323dc, 0xf59dbe3e, 0xdf8a6a8f, 0x926e1ebd, - 0x30958ec8, 0x4e0878c7, 0x4b70e743, 0x2987d13c, 0xb3387176, 0xd1abf405, - 0xbf24ef98, 0x9fbf38fa, 0xf381b9ab, 0xf3857b13, 0x1bed7393, 0xf980f89a, - 0x93f3257e, 0x7ace4f62, 0x97c41ffd, 0x9edae70f, 0x470cbe40, 0xc5f38859, - 0xb51e5247, 0x72871ef2, 0x90e8691f, 0x8962f8fd, 0x49b4d79e, 0x58e5ef0c, - 0x0af291bc, 0xca16d98a, 0x3cc59cb7, 0x8f5e7953, 0xf029d1ef, 0x52ebf67c, - 0x81a1e62e, 0xdbf74d3d, 0x34f66145, 0x15ead3cc, 0x1eae1905, 0x7d009ceb, - 0xf73e7ef6, 0x024aa757, 0x8481b1e9, 0x6653b270, 0xe29677ce, 0x5a7e957e, - 0x9833eb91, 0xe62cec87, 0x7bc2c81e, 0xc81de655, 0xa556fbc2, 0xc3d7bcdf, - 0x322f496b, 0xc05e758f, 0x79f3a73a, 0xbc0bf3bc, 0x5279071f, 0x16c3df23, - 0x436edf4a, 0x27456b7f, 0x15ec7fbf, 0x3cc03f93, 0x19c01733, 0xf01e7af1, - 0x63fd436a, 0xf21b3667, 0x6e91f8cf, 0x7d9a9fe4, 0xbd7cc302, 0x136d76ea, - 0xd5aa85c6, 0xe7a458be, 0x6bef6d8d, 0xf06b9e90, 0x8e3c765e, 0xdcbc7267, - 0x35bf7944, 0xf5efc626, 0x00ffaeda, 0x63ce76e3, 0x553a8b5c, 0x003c51ef, - 0x57ae36e5, 0xfe42dad5, 0xc97983bf, 0x073477ff, 0x3c60cdd3, 0xf287e78f, - 0x737ce9c9, 0xdccc7f10, 0x1e63f9ce, 0x681b73e6, 0x675fc538, 0x5d91c7c6, - 0xf1c71fe2, 0xafce9360, 0x3fa63b43, 0xfc7ca045, 0x5ad730fe, 0xe95c8fb4, - 0x7fe9aedc, 0xbd2b05ed, 0x5b73a3f7, 0x3cf98c7f, 0x733bddb2, 0x149556c3, - 0x1d999fb0, 0x1fd8de3c, 0x120fcac6, 0x21d7edde, 0x25b97c3e, 0xbe31f267, - 0x777819a3, 0x4483c60a, 0x3d0d1f1e, 0x6b8e5d87, 0xfdfc671c, 0xb3df6528, - 0x3cb91313, 0xa3a26e63, 0x5bbf392e, 0xc651d7c9, 0x504132df, 0x9fb8d1ee, - 0xfaae5824, 0xd7de1a5e, 0xde2b9e60, 0x3bf960d7, 0xef161f39, 0xa2feb06b, - 0xf78b0f9c, 0xf78ed835, 0x956f5835, 0xbef161f3, 0x5f78eb06, 0x722be583, - 0xdc71ec3e, 0x6df1e52a, 0xa2e90a7c, 0x946d790b, 0x1d1bdebf, 0xdc151f52, - 0x085a37bf, 0xa8128fae, 0xc6c269bf, 0x78ff30a7, 0xc52f9293, 0xc3b446cc, - 0xfbf9c22a, 0x7b06a91a, 0xf3f404ec, 0x45ed778b, 0x9bf81e7f, 0x882b9fde, - 0xef4a505e, 0x1968c497, 0x27dba3ca, 0x804f47d8, 0xcd8ec7f1, 0x724adb48, - 0xecf74f52, 0x31bb3fbd, 0x6f7ae292, 0x25824c49, 0xaee465a7, 0x9a7d42b5, - 0x85fa2041, 0x512a6ef9, 0x67984cfc, 0xab62c746, 0x1307cb8a, 0x9285cbda, - 0xb3ae0963, 0x8b9f4122, 0xd588f872, 0x51fb819e, 0x6a345de0, 0x45da1a59, - 0x07f36a5d, 0xbd759f18, 0x57e866a3, 0xa53c7129, 0x69d693df, 0x99bfb8f9, - 0x736ba919, 0x36607e70, 0x0d367794, 0xd9fdc66b, 0x9ea170c4, 0x855997e4, - 0x027f20f2, 0x66e99ba7, 0x357b1f6e, 0xfa345566, 0x62d361f5, 0x4bb75ef0, - 0x1931f3c6, 0x3c65c7cf, 0x81573de3, 0x6173df8a, 0x585cf789, 0x2da3e686, - 0x4db12fcf, 0x240f7820, 0xcdb3e605, 0x0097df92, 0xd4f7a10a, 0xf31c729c, - 0x34ee594b, 0xcadc95e6, 0x9e6879c7, 0x778e392a, 0x6f7c1d5e, 0x8ff38ca8, - 0xbdce5467, 0x166bcb89, 0xbf79e1a9, 0xe61731d7, 0x397dcf15, 0x7d50e281, - 0x06a5d16e, 0x5e05cfbc, 0x5ec67947, 0x8b2efee6, 0x77337ce7, 0xabf51c7f, - 0xcea9e397, 0x7c74eee8, 0xe64fa3af, 0xf07ea52f, 0xe4979e3b, 0x81ba81cc, - 0xf3a123de, 0xa776e739, 0x4fbd4147, 0x5f488bd0, 0xbcfe26ce, 0x673fe647, - 0x7c9f3c8a, 0x24f3a61e, 0x3bfa3e21, 0xf7c24e5f, 0xbc193710, 0xf7fcb94b, - 0x66dc93a6, 0x6fcc74de, 0x4e782f3a, 0xadf1be62, 0x98a5296d, 0xed5e7f6f, - 0xb3eb0679, 0x5d78d2db, 0x0a693968, 0x93d23e7c, 0xb7c8f984, 0x6296a5b6, - 0x91f9f23e, 0x5944cf2d, 0x97eaea02, 0xcd73e24e, 0x98a56983, 0xeb5b3c9f, - 0x7487563e, 0x5f4e7bf3, 0x4e077dfa, 0xdaaa7c23, 0x7d3efdb9, 0x2f0b81df, - 0x603e7ea1, 0x7582bca4, 0xdf099213, 0x6ecfedf5, 0x6beb7a46, 0x6c3f1351, - 0x99ff7e6a, 0x2d3f50df, 0x6b665985, 0xc90c563d, 0xba1db494, 0x3b35f71b, - 0xd625f3dc, 0x89bc4f17, 0x047b31f6, 0x13a5ebe7, 0x4f914a73, 0xfbec0efb, - 0xd9b3ea05, 0xe2d86091, 0x13d05e7e, 0x8ff72a7e, 0x40b8c02b, 0x0cbbb19f, - 0x9dfeafe7, 0xec1fe796, 0x718e9b8f, 0xc09cff82, 0x6e2a31f3, 0xfa8492d8, - 0xf9e57c56, 0xf8c1bfbd, 0x74f4efe6, 0xcd1353df, 0xa94abded, 0xe1397f31, - 0xcc5ed76f, 0x5e7be95b, 0x15aff74f, 0xe2b39318, 0x2963ac7b, 0x3feaff3e, - 0x78865eff, 0xee769428, 0x772ff6c5, 0x438445eb, 0x7916c68f, 0x8f61f233, - 0x0acefc9a, 0x3bd15eb9, 0xdc27ef82, 0x8bf84457, 0xfa8492d9, 0xafc472b6, - 0xcf7dc0ee, 0x833cb696, 0x567b0f7e, 0x670e774b, 0xc1b8079f, 0xd47bb3b8, - 0xfb034998, 0x5e90aa30, 0xca5b0bce, 0xf7f9c49e, 0xf5e77ef0, 0xae9e085b, - 0x5c33d73d, 0xd431fa0f, 0xad85e7c7, 0xf767ed41, 0x7e859b3c, 0xcddfb9e9, - 0xa154ff26, 0x2a5f8573, 0xf4836b77, 0x58824922, 0x3fca5b8c, 0x02198b93, - 0x0ee759e2, 0x927be8ee, 0x6b9fc7f9, 0x00357b56, 0x5b2d0aa3, 0x0acdf98b, - 0xde26543f, 0xabe78c5a, 0xd1d31b14, 0xf5c8a97e, 0x9c5f2195, 0x3c5d33d5, - 0xd65b7bf4, 0x6bad955b, 0x7c1da0e6, 0x45fcfda5, 0xc95f4796, 0x9b55f87c, - 0xdf781dde, 0xb5fe5a18, 0xa84f998e, 0xb585f5fc, 0x95e5b25a, 0x78d6def9, - 0x55afe81c, 0x71f97347, 0x8337fa12, 0xac93fb1c, 0x0aad16ef, 0x04eeffee, - 0xad594f9e, 0xfea3a5f1, 0x7b7fe653, 0x87db8982, 0xca3a5f2a, 0xb371d0ab, - 0xbcde5925, 0xa9bc9020, 0xd14e156c, 0xd20824fb, 0x2b3c3f58, 0xe6372e75, - 0x87870d13, 0x0f197cf8, 0x70f1e612, 0xd66caabe, 0x4f30f4db, 0x022f9855, - 0xd18725ed, 0x50768117, 0x6b122bdf, 0xa317d192, 0x5fe29fcc, 0x5653894f, - 0xfd36d478, 0x71c1eb70, 0x865e4fd0, 0x5628037f, 0x537ce44f, 0xeb4e16de, - 0x1f2f9331, 0x677cb6e9, 0xa73c38f0, 0xfb1f8029, 0x06c576da, 0xf70cebfa, - 0xa751f74d, 0xfffa6f88, 0x07bd31f9, 0xb5b2295e, 0x4e794f78, 0x4083efe0, - 0x3907de9d, 0x5677df27, 0x43086d7e, 0x95f739fa, 0x4fb8f883, 0x7b9c91f0, - 0x7246cdb1, 0x23ed4fac, 0x626bb739, 0xf947af11, 0xbd6e50ca, 0x24a7f138, - 0x7c12fa3f, 0xd29ef865, 0x2f8ea566, 0xd01d81cc, 0xe490b6d1, 0xe7896cc9, - 0x6a5db051, 0x71138f13, 0xe1932f78, 0xde86d8c4, 0xd443f23a, 0x3a97b466, - 0x42f72a27, 0x25f9ff1a, 0x31f53f3f, 0xe456bef3, 0xc50372cf, 0x6abec07d, - 0xc0ed097e, 0x8c16b105, 0x4dc287a7, 0x898c5fb9, 0xe22966fe, 0x7da31de9, - 0xbc3cc4ec, 0x9f91f4cf, 0xf64ed401, 0x5a6bf57c, 0xd5fb37f2, 0x7e517b03, - 0x71f68db9, 0x0e9e0113, 0x547af74d, 0xbed41771, 0x67ed342e, 0x1c91bd21, - 0x97d6f4e1, 0x07bf8bb9, 0x4e4fdf22, 0xfa00f192, 0x7d22358c, 0x87cf1c08, - 0x409ff6db, 0x9dd7d379, 0x943a724a, 0x3db6ce9f, 0xe3728116, 0xaeefd043, - 0x87c07880, 0x7ca59f8b, 0x0798f980, 0x6b3de502, 0xf837cf83, 0x2fc98fed, - 0xda039b64, 0x821b1e91, 0x4170a1eb, 0xf106f4ba, 0x7df68b81, 0xc01bf23f, - 0x777a6aa7, 0xa861c235, 0x52ea173e, 0x4850fd40, 0x2b3fa43d, 0xfdc3f6e1, - 0xebcd1813, 0x25eded18, 0xcf1f7e3f, 0xbd07adef, 0xe103f546, 0xee2d3f74, - 0xc315bd03, 0x8bea16f5, 0x8a6e88aa, 0xd01df55f, 0x83cabdd2, 0xe1259fed, - 0x291e81f9, 0xfed5534e, 0xf7fa2c72, 0x699826eb, 0xb18fd07e, 0xa0731794, - 0x11fd163d, 0x7a21dda5, 0x0cf7e5d2, 0x287e50b2, 0x9bc94eed, 0x42e5794e, - 0x5f3e1677, 0x8719cb27, 0xeb097508, 0x10e1ce8c, 0x76b3df38, 0x287ce489, - 0xf4c956de, 0x8b21f20a, 0xe15e39f2, 0x1e4503f1, 0xe572c854, 0x7267b610, - 0xf72937fe, 0x84cf7852, 0x9c8c3f7c, 0x23815af8, 0xcef8a5ab, 0xbccd13fd, - 0x79a78f2e, 0xe789fc79, 0x3e7abded, 0xc713252b, 0x45f79599, 0xd528f2fd, - 0x0e505f2f, 0x781c93c4, 0xe70b1d50, 0xb0467caa, 0x8a90c3d4, 0xd04535d2, - 0x2d532d9d, 0x1ab8a22f, 0x2e1ae7e6, 0x1d2857df, 0xf8e44e45, 0x1fb914ad, - 0xa057b95e, 0x6a73a5fb, 0xf2076f7e, 0x580fde86, 0x08a6b056, 0x18beeff9, - 0x5fd026a7, 0x4bfcd6be, 0xcbeb821b, 0xc514d76a, 0x95e7c30d, 0x8d76b6ab, - 0x57cf9764, 0x8a2c6f61, 0xaede5f35, 0x5e9cfbec, 0xf574e7d9, 0xcc7840c8, - 0x1234535f, 0x7fba65ca, 0xdcfc1e17, 0x5eb5dae7, 0x5d2d57ca, 0xb7c4f743, - 0x8a0daa5c, 0xbe6b5eb3, 0x7ba6e60a, 0x3fed2b90, 0xde0874b4, 0x312b8c5e, - 0xc43dafe0, 0x0137c067, 0xf4cbc5eb, 0x289f143a, 0xfd063c5f, 0x3c5f6653, - 0x113e3026, 0x339be25a, 0xb88ae522, 0x2c3e04a8, 0x0f030cb3, 0x89d1ffa5, - 0x3f1ace3c, 0xa8f1d391, 0x5e3b55d9, 0xe9d71462, 0xa57bf941, 0x22fe4cf7, - 0xbf07efef, 0x9c233267, 0x9bd4ebf7, 0xdfd3fe30, 0x87c50df9, 0xe619d7fb, - 0x03077bf3, 0x5de7804b, 0x029be3f1, 0x26abc0e3, 0xdc243b71, 0x9a9dedca, - 0xe3d5f50c, 0xa1c6994b, 0x1bd912f8, 0xdf74e199, 0x05f6d7d2, 0x8efeb7e9, - 0x8bde133c, 0x0dbb75f4, 0xff356fc8, 0xa8b17ffc, 0x3e3afb87, 0xbeb4bca5, - 0x7ca33f6f, 0xde728db5, 0x3936a1e0, 0x6cdbabdf, 0xe2fef6c4, 0xbf6117bf, - 0x8fe9724d, 0x98f8f02f, 0x83f12a52, 0x3bf9ff00, 0x4c7b53d4, 0x54c51f1b, - 0x2db0ca99, 0x7fc0bf24, 0xe1bd468e, 0xe3982b8f, 0x04c38b86, 0x54d215c6, - 0x2580ae3c, 0xd2d215c6, 0xeb015c78, 0x12c05718, 0x8ed80ae3, 0x63ac0571, - 0x18eb015c, 0xc63ac057, 0xb8c4b015, 0x297fb602, 0x0fd1e7bf, 0x3dc78b82, - 0x57f7240d, 0xc0337e62, 0xbf27656f, 0x47b95abf, 0x7c617ba2, 0xdff503cf, - 0xad3b7965, 0x678ede72, 0xd607dd2b, 0x882c901c, 0xc41f7c22, 0x3bf98e95, - 0x1e314703, 0x5822d354, 0x7db198d6, 0x6363ed3e, 0xa507de47, 0x6d47bed8, - 0x4f44cd11, 0x828d9f1c, 0xd57c8f5b, 0x57e287b1, 0x949d7105, 0x2cd35fef, - 0xcebb8c30, 0xd93f72d3, 0x0e6b4129, 0x1d92abdd, 0x9376d4ed, 0x9cf552ff, - 0xef7c0e60, 0x45e266bb, 0x7dca1392, 0x88fe52f5, 0xf37a3d39, 0x6b3d2092, - 0xf85779e3, 0x29c7ec27, 0x1d9377e7, 0x2d176012, 0x6c6c7bc5, 0xf7a5be97, - 0xe0e09c4d, 0x9dae108e, 0xd1d95577, 0xb5f31eb2, 0x55fe687e, 0xdef924e1, - 0x47bf9b3a, 0x92f8fc52, 0xbd60077d, 0xb25a2dc1, 0x609f6e53, 0x1e526dbf, - 0x28d819e6, 0x53b472ee, 0x27d67e4f, 0x8a0faf5b, 0xd74a14bb, 0x8563dc51, - 0x7dfd205a, 0x3b9f6ac4, 0x4672e809, 0x6f14bdf1, 0x246f1199, 0xf0e8563e, - 0x4fc96b49, 0xe315de70, 0x0a9877f9, 0x34e7ecb5, 0xa5cf9c9f, 0x5eb0a9e0, - 0x2cf7e370, 0xbd0b3316, 0xc008b03f, 0xe5517187, 0x188b1ffb, 0xe850afcf, - 0x8156c56a, 0xbcbe8ae8, 0x84bdf010, 0x103df845, 0x6af77fd0, 0x289bfdb9, - 0xc4f27bf2, 0xe28f3c4d, 0xfca7663e, 0x7d486591, 0xd7d7e912, 0x0f6ed07c, - 0xdb892ebf, 0x9c38e6f7, 0x3571f17f, 0xc61707e5, 0x276e9edd, 0xf9405f3d, - 0x6ef78213, 0xaf1bfbe9, 0xf3833f26, 0xb9aa8e27, 0x927801dc, 0xf485d59f, - 0x3b1ef14a, 0xcaebc795, 0xbf229ca9, 0x5efa161f, 0xcbe77f43, 0xb0be382d, - 0xf84160c6, 0xc03df15f, 0xffbfabb0, 0xebf394e6, 0x5c9ec512, 0x6be3c233, - 0x51e10583, 0xef49d718, 0xf3caa589, 0xb25b9c3f, 0x8b69f109, 0x1f5c2e60, - 0x00b669ef, 0x40f08b7c, 0x3dd1c602, 0x66cf7c36, 0x513053a0, 0x7265f53e, - 0xcc3aeb74, 0x1349a953, 0x2daf184c, 0x1852db0a, 0xa517f30b, 0x7677d324, - 0x1c78da6a, 0x4e4a0fb6, 0x92dc5307, 0x62aac7c0, 0xf1cf7e31, 0x3fb5cbe8, - 0xdfcf293d, 0xb3e65b3e, 0x782f8efe, 0xe3b5f11e, 0xfbe9bbb4, 0xef4f4c1c, - 0xf60fd3af, 0xd1c6fb35, 0xe855af14, 0xae39b068, 0x45a8e909, 0xa5a513d6, - 0x8ed1a9ef, 0x37b3cc68, 0x96ca1c23, 0x4b175c5c, 0x4e3e1ce7, 0x87dfe4a6, - 0xe502c9c6, 0xde46ffed, 0x5aba89fd, 0x5baddf2a, 0x9d776545, 0xe8079e8b, - 0xbf08238b, 0x7d6f101f, 0xf130d27b, 0x4733a656, 0xbe05be92, 0x90edf1e7, - 0xbbf02af8, 0x33efc018, 0xd9eea23a, 0x8348f680, 0xcdf782c6, 0xd2bcff98, - 0xfde1f240, 0x59c6c349, 0x2819f815, 0xf4c83b2e, 0xe9878839, 0x112aa919, - 0x926dff9e, 0x44e71410, 0x2273c1be, 0x7c8960df, 0xf9f952a3, 0xa30d69e6, - 0x7da194ef, 0x40fb22e0, 0xbf5df84f, 0xd40ae406, 0x20a665ef, 0x442172b9, - 0xf32380ae, 0xac5f7a33, 0x0936cb43, 0xe9cffcfe, 0x19ca5c50, 0xb878ce46, - 0xe61d199c, 0xb3be9e79, 0xf9461d50, 0x44efc0c5, 0xf2374767, 0xac25bdbc, - 0x461dd684, 0x3e7bd0de, 0x38188ef7, 0xbff414f9, 0xd90361f7, 0x9613eb39, - 0xe477ffe6, 0x71279fcd, 0xdf813c78, 0xed5d5073, 0x059b0e7b, 0xb15d8fbc, - 0xbe236590, 0xc439ef95, 0x7bf218c1, 0x39eff5ff, 0x123c988c, 0x0ae0e7bf, - 0xdc439efa, 0x30e7be15, 0x6171b26a, 0x461cf7e0, 0x30b11e4d, 0xc60e7bf8, - 0xb29df885, 0x39efc1ff, 0xbbce4fa4, 0x370e7bfc, 0xa0ff364e, 0x3d8039ef, - 0x4fe3899b, 0x63c6d8e4, 0x3b9f2899, 0xe3e5fdf4, 0x97643df2, 0xb2c52f68, - 0xa2a5c228, 0xc56dd176, 0x73d16df2, 0x5f03b63f, 0x1578444c, 0x037d963d, - 0x5125977e, 0xf2bca1eb, 0x49b6ad27, 0xb96bff38, 0x3cf8c9b6, 0x2f5fde34, - 0x73f60f9f, 0xcd0bf60b, 0xe2e8531f, 0x0e5cc9ae, 0xa9cb93cd, 0xc7bfc3f5, - 0xbf326f3f, 0xbed6be4f, 0xe077bf61, 0xd9feca7a, 0xdc56c596, 0x4ef7ec0f, - 0xb7ec27dc, 0x88664b04, 0xf80f7a0e, 0xc9757a72, 0x2e7462fb, 0x3fb38f90, - 0x9528f6e1, 0x14772ae9, 0x1ea30dda, 0x7ee14770, 0xe80e3547, 0xdf907df1, - 0x68f406ba, 0xf576fc3f, 0x7fdb1e80, 0xdaf9e36b, 0x9f6ff3a1, 0xf491fdcc, - 0x7e3403a9, 0x4dddfc0c, 0x1440c1fe, 0xe5e96dda, 0x14ae3447, 0xf66d4f7a, - 0x93764127, 0x8c7bf899, 0x01e636dc, 0x8c3d2191, 0x1e78c1d9, 0xe90c4163, - 0xef1d4ab9, 0xfdc0f95a, 0x38d1d222, 0x803bec37, 0xaedfaefe, 0xaf7e0c1a, - 0xaae34bd7, 0x5ec025e4, 0x64ee7a0b, 0x9474bf3c, 0x5ed08f2c, 0x39d9efc4, - 0x77d08fcb, 0x0b8ec0a6, 0x79be8f99, 0x594f9430, 0xe6bfb3ad, 0x62be5333, - 0x77a5bf50, 0xfa3d66ff, 0x5ba5e5b5, 0x2f17e435, 0xa58f5969, 0x269ef1c3, - 0x197d918e, 0xcbec1fd4, 0xfb65faa0, 0xf547d90c, 0xc7d717fd, 0xd02eb30d, - 0x13a456c1, 0xaa8e0e85, 0x4fd0e33d, 0xb30cea3d, 0x3c1df7f0, 0x269a5df4, - 0x5df4bdf9, 0xcadd39ff, 0x5d3965f3, 0x3f1df8c0, 0xa9ea8e8c, 0xaf1df2bf, - 0x1c8a956b, 0x8dcefa1c, 0x5e28b986, 0x7248cb39, 0xfff646ae, 0xc89897aa, - 0xbaf8511e, 0xb539e55a, 0x18c5fb1e, 0x8a9bfe79, 0x7aabf7d1, 0xcf9451c4, - 0xcfac3f4d, 0xacfba54a, 0x178f7ad8, 0x5db81de7, 0x15b9efa0, 0x5ab97384, - 0x9e389628, 0x4447e785, 0xa7815dfe, 0x98487e51, 0x37bfc147, 0xbf972530, - 0xf8cf103f, 0xca98db77, 0x369df21c, 0xed7a1e39, 0xeff1b4ef, 0xf7e7cd92, - 0x25510d72, 0xf9f1cba5, 0xf9e81b82, 0x1f52efc1, 0x2afee2b1, 0x71b4ef94, - 0x4e61bf7b, 0x557f3d06, 0x3d41af30, 0x5d807ae1, 0x7a6d3be9, 0xef80fbe4, - 0xf887bdb3, 0xd9f7d6ba, 0x1c0fef94, 0x23c3705d, 0xbd1c397b, 0x3355ef78, - 0xafe418cb, 0x3c3117ff, 0x56c0d29e, 0x000056c0 -}; - -static const u32 tsem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x3370278a, 0x45e39c30, - 0x8381e9f0, 0x5fd32918, 0x50c0cec6, 0x4055c401, 0x3f880bbc, 0x7c3032b1, - 0xff5e2566, 0xdb042935, 0x21818248, 0x88d7881e, 0x49a83031, 0xa41dc422, - 0x03261819, 0xb150a1f9, 0x5f3a4047, 0x0f77328a, 0x80a69c16, 0x872ae629, - 0x9163a760, 0x6819c647, 0x50e54bf2, 0xf40499f9, 0xa2be340f, 0xa2ffca8e, - 0xa013a10a, 0xe4d157e2, 0x3be542bf, 0xa6bafea0, 0x4edcdd8e, 0xc35dfd32, - 0xfc01a102, 0x9847b099, 0x009847b0 -}; - -static const u32 tsem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7dedff00, 0xd554780b, 0x733ef0b5, 0x7993331e, - 0x31e424e4, 0x1e4e1081, 0x03086820, 0xb78a8884, 0xf6301027, 0xd57876d2, - 0xaf0e2d58, 0x6b86f210, 0x7fb6bd2d, 0x78490806, 0x111fc1a8, 0x29e1d5ad, - 0x311d82f6, 0x0388b622, 0xbdabd228, 0x557c5837, 0x0bd11feb, 0x2a44908a, - 0xe5b5ef6a, 0x3ef6b5ee, 0x09939cc9, 0xafdb7b04, 0x7cfdffff, 0xc7ecee9f, - 0xf5ed7bd9, 0xfdad6bda, 0x8131c918, 0xe4230da4, 0x06fbfc22, 0x109d9221, - 0x9d37a132, 0xd72120e3, 0x66924218, 0x92ddfd2f, 0xbadc4214, 0xa349bfe2, - 0xe4febba9, 0x5f5f9a1a, 0xa4aff0ec, 0x4d1f5b4d, 0x2d096a78, 0x2fa1efbf, - 0x7cd04fc3, 0xad79ecfa, 0xce7eb4c5, 0x5d0fc924, 0x10ab1a1d, 0xd8e7ed02, - 0x520176c2, 0x9097e581, 0x927fa130, 0x45f8e8af, 0x9fe8b884, 0x37fe9724, - 0xa5b21c89, 0xd1e43e60, 0x99029ea0, 0x31364846, 0x7e6055fe, 0xf509fc36, - 0xd0677744, 0x779e75ef, 0x7fec13e5, 0xdb0a5f8e, 0xf27347e9, 0x4dc87203, - 0x6d08c6d3, 0xfb1dc749, 0xf908395d, 0xe4990cc0, 0xd8b68763, 0x0fca6ffe, - 0xd214754c, 0x080b67fe, 0x49d9f9ff, 0xcc82da36, 0x3be1eda6, 0x1a1f4e22, - 0xd99f67cc, 0xe0dfb8e8, 0x40dfdddf, 0x5fc0a7ff, 0xe5a1094b, 0x9e0c1ccb, - 0xc5d9d9e4, 0x1989ce30, 0xbf4316d7, 0x3213a673, 0x9d4d5688, 0x4490f63d, - 0x891aebf3, 0xcddb4edf, 0xcf1c0d29, 0xcbf8d981, 0xe80293a7, 0x60ee8e97, - 0xffc45f7d, 0x64ef38eb, 0xcc3fde3e, 0xfa102b1e, 0x8a97f641, 0xa0725da9, - 0x4bd153f9, 0x2d056a48, 0xee53191f, 0xd09a769f, 0xe6e9e4f2, 0x721340f6, - 0xc425211d, 0x1aea7293, 0xc91677fa, 0xad4228ba, 0xee8c0b6a, 0x4a6b0fe5, - 0x22f9fdff, 0x12fa01d0, 0x6a1fd6fb, 0xa0e9e99c, 0x7b375af8, 0xf4d08796, - 0x0f2cc0f5, 0xd9f5efe0, 0xd68f10b3, 0x676673f6, 0xfb5e0227, 0x06feef1b, - 0xfa08d03a, 0xb5b3c73d, 0xea48907e, 0x39fbf423, 0x31c3d13a, 0x9301dffd, - 0x0964254d, 0xb34d1b30, 0xd2a6d525, 0xe88d6cfa, 0x95e33891, 0x3b69b102, - 0x28994992, 0x0ff352e3, 0x2637bb61, 0x71c34ad9, 0xef0773e6, 0xb81a55c7, - 0x6fa50e67, 0x751274d6, 0x2912ba51, 0x75e2c6aa, 0x1a548a5d, 0xddc7038e, - 0x68425e1c, 0xe1c0cf7b, 0x02d86571, 0x47329fd0, 0xf5c2c40c, 0x42678003, - 0x4ca24a6f, 0x18f8e6ee, 0xfbbf72fd, 0x338f506c, 0x8e00bb8f, 0xecaa9009, - 0x0c8f0e3b, 0xb201937c, 0x43fc8296, 0xe02463c2, 0xb91eccfb, 0xe5070124, - 0x17f0a18f, 0xa42dae15, 0x1412d47b, 0x47ec56b2, 0x0324a4f4, 0xde1157bd, - 0x4f51290f, 0x42157e51, 0xd78b84ab, 0x129e6a5c, 0x35f06539, 0x193ba9f0, - 0x5e1cbfc7, 0xe518a048, 0x88d43152, 0xe307c078, 0xed4df92b, 0xbacba502, - 0x947ee5d1, 0x90218a6f, 0xe17e4333, 0x3bf457df, 0xbdccff37, 0xca91d29c, - 0xd3396b91, 0x2cdf8a8f, 0x8e92eb67, 0xc82008b5, 0x0f49b964, 0x40241210, - 0xeb6f0377, 0xbc78a2be, 0xfb5bbf04, 0xe7c86fdd, 0xc9983260, 0x053f9327, - 0x79bd07fa, 0xf0077ed3, 0x5edf3af5, 0x5d6bcc07, 0x7a825efe, 0xe8c7d38a, - 0x5daf95d7, 0x81d6ce52, 0xee808d7c, 0x9ea748c3, 0xc6a7d1f2, 0xa6767e02, - 0x748bf72a, 0x08933b7e, 0x6b75d9ea, 0xd02b7848, 0xb5e594b5, 0xb5e1696f, - 0x9d3b8e74, 0xd698bebc, 0xed06bcd3, 0x3adbbea9, 0x68870b49, 0x8d8b6b7e, - 0x85ab1fb5, 0x311f9a45, 0x8a148491, 0xc2c56d4f, 0xbe5a4e95, 0x17eaa375, - 0x34fd5eb5, 0x2d6725a2, 0xdeb2dfb4, 0xbdf00aa6, 0x3b23ad8f, 0x443849f3, - 0x39b1dfc7, 0x69239bf9, 0xf9b2143e, 0xf24fd387, 0xd945faf8, 0x022844a5, - 0x9c3a31b4, 0xae5c7921, 0xa9e50204, 0x7ecb7cbc, 0xa48ebfff, 0x5d363df0, - 0x45a0aff2, 0x4ccfd63b, 0x769e28d0, 0x3f048168, 0xc0f07f4d, 0xccefcc7c, - 0xdd00260c, 0x9f9c6e76, 0xc0f14c00, 0x461b99e6, 0xd2617b41, 0x6ce91d61, - 0x1f47ffd6, 0x00ec3a28, 0x9e994b38, 0x7e0d6a4f, 0xbcf9a253, 0x89b91249, - 0xadcf214e, 0x1fdbdc21, 0x4f5811b2, 0x8b6de8fb, 0xcdd44ebe, 0xb4eb5779, - 0x5d7f818f, 0x2009160f, 0x86353bda, 0x923741e7, 0xbeec8af0, 0xc85cefe3, - 0x5d2913ea, 0xbf2e0e80, 0x96675962, 0x4756f85a, 0x3c717079, 0x1c755ab9, - 0x897a488f, 0x578bd690, 0x62469ffa, 0xf07ae9f0, 0xe9f58128, 0x8163e78a, - 0x7ca05d27, 0x9cab830f, 0x1c1eb9ef, 0x6357caf7, 0x21b1f1e3, 0x7fa01eef, - 0x6177c522, 0x50eb0424, 0x0a24617a, 0x57c9e2fc, 0x9a0bb034, 0xc5c93109, - 0x7cfbd1a1, 0x1337201d, 0xaf583e22, 0x837e8dd7, 0x81568fc9, 0x6fe630f8, - 0xb7e4f7b4, 0xc1fb5893, 0xf87287a8, 0x697853ce, 0xcb87bb39, 0x847f4f59, - 0x732447ad, 0x4f75c21c, 0x5e7561e1, 0xc84c7d1c, 0x97cb940a, 0x817ae049, - 0xedcddea6, 0x6c06a751, 0x7900dfae, 0x910240b7, 0x134ddf38, 0x42d27ad8, - 0xe9a05d74, 0x162f44a3, 0x664b9d70, 0x2eb2d7fa, 0xbc9fd1f5, 0x16e9165d, - 0xd468df40, 0x8734803e, 0x23cd31f8, 0x92474c01, 0x26af4c56, 0x49f34c11, - 0xa405a63b, 0xaf43531b, 0x422a89f8, 0xfac4c47e, 0xa4e720c9, 0xe58b63da, - 0x3264d0bb, 0x3cce3eb2, 0x73782d9a, 0xf8ebf890, 0xe75f021d, 0xfc8aa648, - 0xf17af843, 0xe818b06e, 0xfc2854c5, 0xefccdbbb, 0x0ebe24e2, 0x693dea38, - 0xdd335780, 0xcd54548d, 0xf06d5a7c, 0x1c2444a9, 0xc41f32c7, 0xd6b8cc63, - 0xfb7356fe, 0x9c9f98c6, 0x491f23a2, 0x50cf666e, 0x71bdf438, 0x0828d1f0, - 0xab419e7c, 0x29b23adc, 0xb6494bbf, 0x6b9a5ac8, 0xe8764f74, 0x893f2f38, - 0x7ceb6747, 0xbe2af0ac, 0xa9b3c181, 0xcb0a9e07, 0xc297fa3a, 0xfea64ff3, - 0x1db24ca4, 0x86a20bd6, 0xbc56de70, 0x42def9f6, 0xd2e4fe8f, 0x57d66991, - 0x02d78a4a, 0x069f8587, 0xe37c7f68, 0xe47fea4b, 0x211bfac3, 0xa9ec2a41, - 0xe60101f9, 0x1a40ad7f, 0xc85e2913, 0xa0eda268, 0x6af5cd70, 0x698b8ecc, - 0x91f41937, 0x74c90b66, 0xee92cfbe, 0xe43ed023, 0xf41d9127, 0x6df367b3, - 0x7d695ba5, 0x63b69faa, 0x1e4005fd, 0x0b6d1dae, 0x9fd1b940, 0xf5329e4e, - 0x112efd47, 0xe836e1f0, 0xe4c3f163, 0x1fb436b1, 0x6fa27c95, 0xc75f2389, - 0x1d157cb9, 0x9eb0ea71, 0xb094cab8, 0x8ffa1b33, 0xb53e4314, 0x5d61f89a, - 0xe6cdd49f, 0x30e1c651, 0x59fa9de6, 0x6a7e0040, 0xc03b31f7, 0x3fd04855, - 0x74da3254, 0xb4dd1ff0, 0x7e42f50e, 0x50531754, 0xd83fa23f, 0x5f3d9e1f, - 0xd00bed3d, 0xb9d47d7e, 0x92be076a, 0x9fa0e9fc, 0xc8568f57, 0xf8bdfa60, - 0xfff63b3b, 0x1862a7b9, 0x47cf9989, 0x0bb1d10d, 0xa670c1a9, 0x67a618e1, - 0xed31da1b, 0xd30b786c, 0x594ae9fe, 0xebceda8e, 0xc0d7e27e, 0x3f0f101e, - 0xc00f3447, 0x5c75d51d, 0x12a21c17, 0x82802eb3, 0xd36fff06, 0xdaf0bcd8, - 0x086bc46c, 0x67d54de6, 0xe0367878, 0x9e000a5b, 0xc2223887, 0x77867cd2, - 0x01d03fc0, 0x3c8e8bca, 0x5cf102b7, 0x9e02c64d, 0x0ca4c937, 0x13e03cf4, - 0x827d89d6, 0x03800eed, 0xfe69f3f2, 0xc1fa8ffa, 0xf78659fb, 0x9e29978c, - 0x4b494e00, 0x8eadc664, 0x913b95f2, 0x27d7120b, 0xf9927abd, 0xbdf6bdd9, - 0xcf00eff6, 0xac894696, 0x68a6bc85, 0xf7b7114a, 0x15824a41, 0xdcdfc1d3, - 0x28fd3e56, 0xe2b90bd8, 0x5a648757, 0x3a5eb43e, 0x4f2311d9, 0xfd746559, - 0xb0c276a4, 0xecf2e6e5, 0x074f3990, 0xb7347f40, 0xc43e5cc5, 0x87aef5c6, - 0xad1e4078, 0xe8b65af3, 0xd3fd7157, 0xea240d55, 0x02f26396, 0x1791a7c3, - 0x423b13bc, 0x46cb7e74, 0x4c038c11, 0xb3f5b1b7, 0x7ca3be15, 0xd74f2f71, - 0x5231fa5b, 0x46dba269, 0x193d30c6, 0xddba7d6f, 0x46ce3c56, 0x4db06bfb, - 0x72a3671e, 0x042292e4, 0x5b9777ec, 0x93f9e3d1, 0x8e126dd3, 0xebb5209f, - 0xfbab8522, 0x4adfe23a, 0xee4cbef1, 0x2c7c828e, 0x21fcd62b, 0x30fe4750, - 0xd51263ca, 0x15f66261, 0x700253c1, 0x6c4a7850, 0xfb044e38, 0x0738a6e9, - 0xcc997dfb, 0x4a365dfa, 0xf6376823, 0x3655e703, 0xd80ce119, 0x34fd0904, - 0x1555974e, 0xa34df739, 0x9f554ed9, 0x2667fd05, 0x78c16705, 0x7e6fb946, - 0x1963fa29, 0x2bf4ccc3, 0x0167d477, 0x2206547f, 0x4e7f80d3, 0x926c5f7b, - 0x36b7bce9, 0xf144bf10, 0x702b9eff, 0x7357f41b, 0xb008fd7b, 0x5e06df7f, - 0x3b2a0098, 0xa5ac7a80, 0xa25fa564, 0x148972e5, 0xca3f2995, 0x25bf0f13, - 0x2a1a4017, 0x938b3886, 0x477d33d4, 0x35224bf5, 0xf5231cbd, 0xa27e218f, - 0x72d03c80, 0x60256f55, 0xdba8380f, 0xef863270, 0x1e734c94, 0x7cd8fa6c, - 0x72e37a7f, 0x27e79829, 0x09fe0387, 0x49dde9da, 0x26927fcc, 0xde000bfa, - 0xa6ffaf7b, 0xc4fcf006, 0x67f93366, 0x5a4d7f56, 0x79696ffe, 0xfee26810, - 0xd5fcb4b6, 0x80f1bcb4, 0x979c5697, 0x9432ca63, 0x24f0050b, 0xbf07f932, - 0xe41d67be, 0xcf5bf878, 0x572f58db, 0xf835bc37, 0xa720e1c3, 0xa43f831d, - 0x052d59c4, 0x3e42ff91, 0x1c28b5f0, 0x098f9992, 0x62134f78, 0x18176e52, - 0x5a9c9bf6, 0xdc947488, 0x988ea9d2, 0x8fc0ddf5, 0xc1ddfcb2, 0xf4878e1f, - 0x78ad4c6d, 0x0120a455, 0xd768d03f, 0xe018b713, 0xe234effa, 0x1fc479a9, - 0xa47338a5, 0x7a6a78b0, 0xf30a285e, 0x09fd5272, 0x233dd3eb, 0xf0c56b5f, - 0x3b0fc581, 0x3f20ad94, 0x61b68cb4, 0x7865b35c, 0xf90290e4, 0xd1406a0c, - 0x5dca677a, 0x4c6d8821, 0xe37c63cd, 0xd4f5b3f4, 0x7e8c3c35, 0xbdbfa198, - 0xad5e1f1c, 0x67b3f51c, 0x31ded9a2, 0x2b2701d6, 0xdb36f4a2, 0xa694ce51, - 0xbe82c54f, 0x9b539a7e, 0x69e51a76, 0x233fb9a4, 0xe36ed1de, 0xc96b8bf1, - 0x593768b5, 0xe1fd12e2, 0x71f86bcd, 0xdcbcd913, 0xfc1849d3, 0x5189f4e6, - 0xcfd79bc4, 0x9bd866f0, 0x9bbf3e1e, 0xfc04234a, 0xf3f89ebe, 0xeb6f0ccd, - 0x7fa28baf, 0x29ec7eb7, 0x85bd67b4, 0xce3f261d, 0xa1ca1ef8, 0x76c4fcfe, - 0x18f6a1a8, 0x23711bcb, 0x19e9a78a, 0x61ebbd69, 0xaddbb72b, 0x92275374, - 0x4763d062, 0x8315a747, 0x84b7bede, 0x3cab4ec2, 0x6297587a, 0x7ef2adf0, - 0xdf867cd4, 0x7cd8cb7b, 0xd3f47b69, 0x93989def, 0xf266e304, 0x7f11b0f8, - 0xebcbf1ee, 0x284f78cd, 0x2d85c4b4, 0x67eab77e, 0xcc4b52f4, 0x5f39abe5, - 0x57a7222b, 0xe8ce192a, 0x4f3e3035, 0x84bcf832, 0xdf3279f1, 0xd12f4837, - 0x921d010e, 0x4dff994a, 0x4df37e2c, 0x5e8c1d29, 0x00c88f37, 0xa9fefc3f, - 0x97663edd, 0x7126ba30, 0xc6efbc7e, 0x71c80211, 0x40268972, 0xc33e727d, - 0x13c53253, 0xa5c977ac, 0x4ef6efcc, 0x525db0d4, 0x0b5ba309, 0x5fe14c7c, - 0x898a7403, 0x5b4b3b1f, 0x6b7fa075, 0x741d4ef1, 0xe1c53259, 0xd4cf0a20, - 0xd81b0a52, 0x805fb49d, 0xc51853d7, 0x49525ab8, 0xfca5d870, 0x82a2427a, - 0x10f887cd, 0xe94b686c, 0x7e58253c, 0x20b26268, 0xa7ef7ed0, 0x80f1c07c, - 0x8f173c71, 0x785fdfa3, 0xfddcf512, 0xc8364df0, 0x1cebf6a9, 0x36a5279a, - 0xf707f83f, 0xf108e697, 0xbcc6e7e2, 0x2acb83fb, 0x35f812c7, 0x9572fc31, - 0x16dee3c8, 0x22475dfe, 0x57c82e6a, 0xa5f76f48, 0x830feaf5, 0x65e47aff, - 0xfecbe312, 0x87a189f4, 0xb21824dd, 0x1fd5f765, 0xdef8ce92, 0x7940179e, - 0x24ef03eb, 0x8a52afc6, 0x9136fcb9, 0x5e867fdb, 0x140792d1, 0x00a12727, - 0xd72277ae, 0x02da4f4f, 0xf054c50b, 0x4eb8c3bb, 0xae74c8b8, 0xca9f1937, - 0xe6a6ff9c, 0x4ae2bd33, 0x9776b089, 0x903aa78d, 0xa834d6df, 0xc65a1fa8, - 0x439ed5de, 0x7866b0f1, 0x73be1f93, 0xb9196b8c, 0x3cdbf68d, 0x2b70797c, - 0x30fdc00c, 0xac22bfd4, 0x8d5f8c83, 0x0e03307d, 0x61d21992, 0x7e09cc9f, - 0x2467e011, 0x24905fdb, 0xeb8fb512, 0x4795df1d, 0x6967cde1, 0x0dc19f28, - 0xb6ebc9fe, 0x6f9c2ae0, 0xa2946b7e, 0xc99bce9b, 0x42216acb, 0xebcc225c, - 0xb21e7c72, 0x9f8ebe31, 0x025df7f6, 0xe1c4d3ec, 0xdb22dddf, 0x472d59a7, - 0x7e085088, 0xf289ed1b, 0x6a6ceac9, 0xa381c797, 0xd56bf391, 0xc3f8672e, - 0x89ab7e18, 0x75f29924, 0x1fc233fb, 0x7711fac6, 0x514fb80a, 0x4358d1cd, - 0xcf00b23a, 0xf61a29ef, 0x48eb6b57, 0xe9177c83, 0x78025b4e, 0x8b8f0310, - 0x5277fd74, 0x90b8c4be, 0xd6eb607b, 0x81a7f0e5, 0x4085d10c, 0x0fa9e4cb, - 0x178e9879, 0x69e307dc, 0xd2bf2b2a, 0xf5f0e371, 0x4d7cb10b, 0x6a5957c4, - 0x147f6be5, 0x129ddaf9, 0x9fb77ac5, 0x8fc1b5f1, 0xad1f9c89, 0xbf8c687c, - 0xd6afc79e, 0x335f3e72, 0x708549a1, 0x9b51dadf, 0x2ce69e30, 0x7c015cda, - 0x25aa32de, 0x64de7c0c, 0x17df35f0, 0xdb2efea1, 0xa35ad31f, 0x72264eb0, - 0xeed456be, 0xeb7b9006, 0x38935d7c, 0xbe0534bc, 0x5f39b806, 0x93f807bf, - 0xae08ddfd, 0x076bd7c1, 0x45bad7cc, 0xfed39b6f, 0xc2d927fc, 0xf1891ed7, - 0xd7c067e7, 0xb30a4f00, 0x963edc63, 0xdfea7eca, 0x06e7e9c7, 0x6b99f989, - 0xe5ac1cb9, 0x1fb6b072, 0x223ff839, 0x9afe03f3, 0xc98b3072, 0xe5a24381, - 0x8cae9389, 0xd3b0251f, 0x9e7bc8e3, 0xe1b5fc24, 0xbc4334de, 0x27fe3c72, - 0xbe84cd30, 0xcfd234f4, 0xe4c0e744, 0x73c98f3b, 0x76be727f, 0xfe387c68, - 0xa7f46453, 0x26922ef8, 0xffbe395c, 0x7215705a, 0x43f0367e, 0xb728c582, - 0x3a667a31, 0x86a92bc0, 0xd304799e, 0x28ad79a9, 0x81be86a7, 0x2bfa0a58, - 0x3bc62b6a, 0x68ad999c, 0x98f3399f, 0x24fc31be, 0xb88d7ceb, 0x33d71378, - 0x02217949, 0x853d9feb, 0x9eaa3f70, 0xcc9951f9, 0xd5e2301f, 0x18a8fd86, - 0xbbd0d47e, 0x79a79f70, 0x97da3d78, 0x3bd637cd, 0x36c3ede2, 0xf077eefb, - 0x3ed35f4d, 0x0e5a1aeb, 0xbbc9aefd, 0xc3b3c49f, 0xfb18798c, 0x6e3e4e46, - 0xa8b51e73, 0x32df5c60, 0xc76adefc, 0xfeb26734, 0x7ae7be7a, 0xbbd1ee57, - 0x54768f2c, 0x6f9f8c6e, 0x03e0c7e9, 0xa343e885, 0xe4183710, 0x4ce7091e, - 0x3f04849a, 0x924dc7d8, 0x90729d20, 0x5aa97b1e, 0xff401689, 0x9cbc6627, - 0x3db2f685, 0xbce406b8, 0x0380abe9, 0x53aba9e2, 0x96c6f35e, 0xe6f19d9f, - 0xa56cc1b7, 0x7ee2d5df, 0xb148838e, 0xdc2763fb, 0x4b7ed1db, 0xe9c737c8, - 0x09ae149c, 0xcc13c402, 0xbf8f0ae5, 0x72e69928, 0xa45fc799, 0xe7394b14, - 0xbe34b90f, 0xeb93795e, 0x7602df15, 0x1cc4e74e, 0x713bd716, 0x30674f2b, - 0xdbc73efe, 0xc234f375, 0x535feef5, 0xf6e5251f, 0xe29befc2, 0x9922f8c7, - 0x3ebb4765, 0x2b9d852b, 0x26e7b120, 0xa26b5fe0, 0xccfc6244, 0xff9781a1, - 0x61d4f108, 0x06cabe0b, 0xea156b3c, 0xdb465861, 0xc79c6ca5, 0x28f74263, - 0x3ae6cf18, 0x02f5fb8b, 0x6a72e345, 0xdbf40b12, 0xef8521db, 0x3a52c0bd, - 0x91057b8f, 0x37c0ecbf, 0x8c29d022, 0xb1448ba9, 0x303a43de, 0xe61b089f, - 0x5187e0b9, 0x33c44bbf, 0xc61b614c, 0xf6cc7e8d, 0x7888d643, 0x03a8836e, - 0xedc9bfb4, 0x4297f82a, 0x1ae77e88, 0x40be77f8, 0xc4c8316b, 0xc608b2e0, - 0x7cedad93, 0xa039d853, 0xaffb7a3e, 0x5237df4f, 0x548f8173, 0x1ce8372c, - 0x694ef514, 0x5ff2df42, 0x12f38189, 0xdc58abc6, 0x2a5f5acd, 0xde4017e9, - 0x0bc2e5ac, 0x7e053a7f, 0x6467aaf4, 0x3ca7a3f4, 0x41bf4723, 0x045b35f3, - 0x076d53f4, 0x770fe89d, 0x51f2c23e, 0xfb43a28f, 0x8c05db73, 0xdbd9d507, - 0xe201bdef, 0x0488cf8a, 0x19708dfd, 0xe29d8bee, 0x59fb2673, 0x80079cbe, - 0x9a1cb66a, 0xec57df0b, 0x77d813b7, 0xf16e79a8, 0xf9a06fb7, 0xf464c7c5, - 0xac766a51, 0x657f6050, 0x40885849, 0xc1326bbe, 0xc4fb43f1, 0xbeda0ef0, - 0x369edbcb, 0x2bfb0dc7, 0x455da20e, 0xa7b4f6e1, 0xa9f4a6cd, 0x0d353f0c, - 0x2ddcabbe, 0x98ffc1f8, 0xa38eccf2, 0x9abbf419, 0xa73c0427, 0x45cbb550, - 0x9cba18b4, 0xdfa3136a, 0x9d33f880, 0x8bc5f827, 0xc034eb49, 0x0d8ecd7b, - 0xb713168a, 0x9230d33c, 0x7cdef668, 0x1c7413cd, 0x93ed5dfa, 0x58a61f82, - 0xe041236b, 0x9ce7ce8f, 0x30dcdb65, 0x08ca15bf, 0x59abcc0f, 0xc38b7681, - 0x7ec1f6f3, 0x8b78657a, 0x57d68d32, 0x2945b23e, 0xaaa7e18f, 0x2d10d75d, - 0x6d4e3f86, 0xd4bf4dce, 0xae867b7a, 0x54f0b15b, 0x88b7a612, 0xc4665614, - 0xc8767bec, 0x453f9c49, 0xdf06ff53, 0x18275e87, 0xef3d0ac7, 0x741abc41, - 0xbd32a65b, 0xbcedd060, 0x7528e9ca, 0xb388cd17, 0xd02f7aaf, 0x2af10ec1, - 0x1bfbd315, 0x6c6e987c, 0x9b3e90d0, 0xe1577f00, 0x7b9606be, 0x88629127, - 0xa275788b, 0x3c9f52c2, 0x21962f5d, 0xf960124e, 0x8283dbb4, 0x1bf98976, - 0x383926e9, 0xb75c820f, 0x964c4fc9, 0x49bebae8, 0x7e252e09, 0x77b4be3a, - 0x6075c972, 0xc8e705a7, 0x1d9fb0a9, 0xe8f160ac, 0xa2e40f88, 0x7ccbef89, - 0xd6f2664b, 0x7c60a194, 0x8bf7d364, 0x41eda1b6, 0x7d365e18, 0xec277cbf, - 0xe67ed1ab, 0x1aae54ca, 0xee4fda65, 0x9b49fbe5, 0x4fd4d13b, 0xa30adcda, - 0x8fd8c59f, 0x6cfd6073, 0x19bd7b9a, 0x4695b99e, 0x8fd8f53f, 0x4af36067, - 0x199263bb, 0xb1aa3b9e, 0xfddbf49f, 0x06881f68, 0xdc7690ff, 0x4eef7517, - 0xc496b71a, 0x1fe4d1f2, 0x2a1e78c3, 0x947cb155, 0x24c13138, 0xb27a494f, - 0x74a83f29, 0x6a7da9b0, 0x9f54c720, 0x85b5765e, 0xbfa8dd2f, 0x8a814f31, - 0xab38b126, 0xbd415832, 0x81d83c53, 0xbb06bbf9, 0x75dcef51, 0xb02af07d, - 0xd05600f7, 0xc12977f3, 0xbe1c6a31, 0x0812f3a1, 0x1b34cfc6, 0x32ec7da4, - 0x7939efbe, 0xde2357c8, 0xd9d7dfa7, 0xd12447ba, 0xf14a43fc, 0xadef3023, - 0x8de3b332, 0x9d824338, 0xce6bfea0, 0x8a16da2e, 0x50cb6bc1, 0x6f422fca, - 0xd0722dbf, 0x73b8fc07, 0x4a576ff5, 0xa1a6be14, 0x7a6e1e0a, 0xe1edfe5c, - 0x9b99b510, 0x00fb9687, 0xea8576ff, 0x15f1d88f, 0x8e3e7e3a, 0xdfc61bbf, - 0xd93b332b, 0x673dbe3a, 0x477c69a2, 0x7c698556, 0xa7c74287, 0xf56fb1f2, - 0x8a7c7c3b, 0x7909ebbf, 0xc7077e56, 0xe05567b7, 0xa90acdf8, 0xd09f8d30, - 0x9001fe33, 0xcdfdc39f, 0xf37ae73f, 0xcd2ab3fc, 0xfcd857f3, 0x80feae8f, - 0xf3809f8f, 0x80fe597f, 0x92ab3fcd, 0xfacedfcd, 0xdbdf19ed, 0x6157ff83, - 0x37f5affe, 0xe649dcff, 0x36ab0ff9, 0xc6cedfcf, 0x27f5637f, 0x8e377c7c, - 0x09fca6ff, 0x6ab0ff9b, 0x07b15f1c, 0xca47c0fd, 0xf07a8490, 0xa461a99f, - 0xa35d4061, 0x923a40e3, 0xc837a9c5, 0x5dc70839, 0x3eef8c09, 0xe6fca04f, - 0x24a7d5ee, 0xea90254c, 0xd3ce5acb, 0x158bbb55, 0xd0842fe6, 0x41c4585f, - 0xc45fb85d, 0xb46c8cf5, 0x78538787, 0x218bf73b, 0x78dc2fc8, 0xac5b9e23, - 0x77dc13b3, 0xfa3056a7, 0xc0f1ff1f, 0xf3b1ade8, 0x5a8ba6b2, 0x13fecb65, - 0xef38c783, 0xa6ab2454, 0xa78829fc, 0x127c3d50, 0x9e9a1ffc, 0xb478e996, - 0x83f043fc, 0x1b958aae, 0x768c2e76, 0xce9f2277, 0xfe1cbbeb, 0xf7c31253, - 0xdc053ba9, 0xc37cf847, 0xd9f40552, 0xc99756a2, 0x74e3a86f, 0x8ece7eea, - 0x79c68dfb, 0x14505bbe, 0xc1fdf909, 0xbb051d6f, 0x41e6f171, 0x276eefa6, - 0x1470d5e1, 0x79fac173, 0xff3a5543, 0xe3eccadb, 0xeb6b8c44, 0x9c1c5843, - 0x49b8810c, 0x7906db59, 0x52dccd08, 0xf9ec9b26, 0xfce6835b, 0x7ce6156d, - 0x6d961ca7, 0x112ccf60, 0xefda16c8, 0xcb65ebf7, 0x8e3600b9, 0x76e64957, - 0xbbef1b25, 0xb4198694, 0x8e90fbe8, 0xe9156283, 0xdf65573a, 0xddd4f01a, - 0xae28932d, 0xb8a91dc7, 0x454a140f, 0xb2a82dbf, 0x9de15b79, 0x00f43b2b, - 0x8fee6785, 0x15a7c444, 0x2e838efe, 0xf3ed46dd, 0x907fcd8e, 0x9d6c7e21, - 0x3bfe158f, 0xa3e75b96, 0xcc3eb02a, 0x19cb590b, 0xa9f9589f, 0x36f17f6e, - 0xf37b3db3, 0xb5fb58b6, 0x530cd76a, 0x56f8497e, 0x9bc5fb53, 0x17ea99e7, - 0xd5312eb5, 0x6a59682f, 0xfd0bcfca, 0x8efed4c8, 0xf54c2be5, 0x635fafdf, - 0x62adbfaa, 0x6b7f2983, 0xfb5321f0, 0x98b6ca5b, 0x47076dea, 0x68e4077d, - 0x9e22ebd5, 0x3ee0bdfd, 0x9bd82f75, 0xee12dc17, 0xed447e73, 0x33839015, - 0xb4815ed4, 0xf478ff73, 0x2c1ea9a7, 0xf9a24d87, 0x2d5598ca, 0x0997a099, - 0x6572cfea, 0x24d0aac2, 0xd7b0178a, 0x9b887ca9, 0x041d1215, 0x0f724cce, - 0x318b771f, 0xa9971df5, 0x7d054cdf, 0xb17adf7c, 0xdd797e23, 0xd4c379d6, - 0xaf6a7e38, 0xb02192dc, 0xce5975ce, 0xb569189f, 0xb1a73ce5, 0xeb817dbf, - 0xe9856ad9, 0x19bdea83, 0x86736193, 0xe223e5fa, 0xf9ec9b9d, 0x0db0223e, - 0x53feb048, 0x98861f81, 0x76aa6bf6, 0xfbe49ae5, 0xe11121ec, 0x409d05aa, - 0x5217eaf5, 0x72028d60, 0x35923d16, 0xa1c0346b, 0xef4055af, 0x75c54fec, - 0xe9436cfd, 0x3fafd836, 0xf4c010d3, 0x4c3286a3, 0x3104354f, 0x02a1b0fd, - 0xf50d93d3, 0x2c347698, 0x86bdf4c7, 0x36efa610, 0xbbfa60b4, 0xdf4c5686, - 0xe98cd86a, 0x4c610d1b, 0x4c741b3b, 0xd1e8790d, 0x0f6e01bf, 0x84d71b1b, - 0x2e7cc3db, 0xe73da98d, 0xf7ff70c2, 0x11f3fbbc, 0x7f9fef60, 0x6cfb8ecb, - 0xcacbe1fd, 0x51d3fd6f, 0x3ca57b47, 0x639d083c, 0x8133bd6b, 0x2369c9d1, - 0xec1c64a5, 0xcff4ecff, 0xc4bcc7cf, 0xfd84f52e, 0xfa713c33, 0xfa5d7885, - 0xf444e9e5, 0x949982ee, 0xfe1ea71e, 0xf7e822af, 0x607fac02, 0x71111c07, - 0x6dd1261d, 0x95d7a07e, 0xe1784de2, 0x2f1059f7, 0xbf83d73b, 0x8b882cf6, - 0xd8a8ab5d, 0x3b36f9ff, 0xf9d2f881, 0xcfbc2e03, 0x36d8fe75, 0x32e3c82f, - 0x3d8e189f, 0x6b4d6147, 0xb761d922, 0xe736efc9, 0xa50ab7cf, 0x689a1e78, - 0x0347b389, 0x3861a95f, 0xe0d9d20f, 0x67e8d4c3, 0x71c14f99, 0x65caecce, - 0x5e7e3371, 0x424eec83, 0x277ea57e, 0x869fffb6, 0x0c7ebfa7, 0x23690878, - 0x5e08381f, 0xdb98bb71, 0xf97efb7f, 0x814cfa49, 0x20392af8, 0x82f60e7f, - 0x1177fe9d, 0x6122651c, 0x2eb7e8de, 0x63ec8622, 0x69b77ca0, 0x669dfa3c, - 0x7317f4f8, 0xe6b7c52e, 0x042234fb, 0x9c46bf68, 0x80fe0aa4, 0x02f530f3, - 0x788cabc6, 0x6ee49749, 0xc6f4c611, 0xbc78ea4b, 0xa1d1c6b8, 0xb9d16904, - 0xee4bdcb6, 0x38699e9f, 0xaf39c2a6, 0x02ab470a, 0x64454fce, 0xb9e80954, - 0xd2ab6d73, 0x12ac1ec0, 0x2f15dfcf, 0x67679b7e, 0x6125bd71, 0x8ebcdbb9, - 0xb420fe72, 0x1d9ca35f, 0x8a9f7472, 0x31b59fc9, 0xefdadb3b, 0xf6c0fb04, - 0x1f776a2d, 0xd683769f, 0xfbb54f17, 0x3e30553f, 0x5c53112e, 0x7bdfc0c9, - 0x9d82604a, 0xd772a9e2, 0x7e8f68fb, 0xdc468724, 0xd4fd097d, 0x9f6e7e77, - 0x88727ce9, 0xf338c3b4, 0x8881f227, 0x743bcb76, 0x15f8fd3d, 0xe4db9d99, - 0xf67b80e7, 0xfebef995, 0xdf9b9e02, 0x84e78556, 0x8ff7de3e, 0x242dff68, - 0x81d22f01, 0x1d8116b4, 0x4ad88e79, 0xc8e74f01, 0x31f1de6b, 0x3a95b874, - 0x05ef404a, 0x863b662d, 0xfca6bfda, 0x7ce6cde2, 0x06999939, 0xa37ca4fa, - 0xce02c24c, 0xb37f54cf, 0x177ec55d, 0x5826fa93, 0x8fee2557, 0x348957cc, - 0x9ad5ea84, 0x34567f67, 0xb411c28f, 0x88c83f33, 0x66492cbf, 0x4a656076, - 0xc27d8158, 0x7fc6da0f, 0x832006f7, 0x7104dc3d, 0xfc489228, 0xfc5f483b, - 0x56fc295e, 0xbaf58d78, 0xc3881c4f, 0xe212ee21, 0xdad603ee, 0x86cf6e05, - 0xe7c03d30, 0xc705f86d, 0x7615f92c, 0x2452de7e, 0x9cfdd022, 0x12d908ea, - 0x851fdeb1, 0xbb5edc78, 0x7106957f, 0x7b6ac0fc, 0xdfdc6f6a, 0x0f649768, - 0xe159f962, 0xf73c72d5, 0xf00b4520, 0xef8f21de, 0xc41f9c2b, 0x9c016f04, - 0xdc40f523, 0x3a75ce1e, 0xdf215bbd, 0xf3c0a9e4, 0xef20751f, 0xbc7bbfb4, - 0x9c418ed3, 0xa35a41da, 0xbb5fe53a, 0xa01fb2cf, 0x902ef399, 0x5067d04b, - 0x09a2e780, 0x235cb9c6, 0x7e3cedcd, 0x2e31fe73, 0x4381748f, 0xdf39ee3e, - 0xe14770e6, 0x2899093c, 0xb7f1ed9d, 0x63dfc072, 0x56fdc3f0, 0xcaa77f68, - 0x7df2d7da, 0x9edf3bdd, 0x097c9e9c, 0xa5f7547d, 0xeb31c240, 0xadd49d48, - 0x7dd61f00, 0xd7f96129, 0x5d1a9bd6, 0xe6f46355, 0x59f04a2b, 0x27a604fb, - 0x8e813e01, 0x64dfbb13, 0x027087bd, 0x2f4261f8, 0x386d7c3f, 0x7f498852, - 0x8f04a7bf, 0x6be383c5, 0xd3ebeff7, 0xbbe009ff, 0xf3feb1ff, 0x11dff4fa, - 0x679afe0f, 0xd10becf7, 0x17f2b5f5, 0x10e1780f, 0x6b52c7d3, 0xacef9c1a, - 0x0bdab1de, 0x1491f972, 0x3f5d02f2, 0xef718b0e, 0x0c3ba6e7, 0x70ddd3be, - 0xf396b08f, 0xaf9f99dd, 0x2ff836fb, 0x5590ef9f, 0xb2ec0f8c, 0x2994ed47, - 0x3096db6b, 0x7f65d8f9, 0xf19be59f, 0x7edd53bc, 0x7ca8beb3, 0x0d3481fc, - 0xb885550f, 0xff451cff, 0x7ffb76a0, 0xabbb034c, 0xdea3748e, 0xe3077eb3, - 0xf68c997f, 0xb1253cc0, 0x0e71bd6f, 0xa5e38eab, 0xde1d6dae, 0xbb6baf13, - 0x9a1334f9, 0xad3bf40e, 0xbb7055df, 0x9f30e1df, 0x42f034df, 0x5feeccc2, - 0x0583c4f5, 0xceb853ef, 0x2bc57f6e, 0x29f2c7e4, 0x23e77fd3, 0xa5fb1e0b, - 0x755cbfd6, 0x6b18fd52, 0xb4eb1b5f, 0x2bfb9fb6, 0x2d5a5807, 0x0fe0bd47, - 0xf1916f56, 0x9ef57bbc, 0x861f3b6d, 0x76dbccf8, 0x7fda70ff, 0xde979ed5, - 0xabe69eb8, 0xa653929e, 0xe1b869b3, 0x9f41a29e, 0xf2dffa3a, 0xa8f4bd71, - 0x4525fa7c, 0x7fcacd1b, 0x974bdc9c, 0x290ea7aa, 0x7c5f7464, 0x521c894c, - 0x85b67ed8, 0xa7f7913e, 0xeab15f81, 0xd0142f89, 0x141f1f5f, 0x1c767a48, - 0x09796e7c, 0x13c063ed, 0xabd393d2, 0xf6967e87, 0xa82e9475, 0xb2f42d17, - 0xaf98fbb6, 0xc42fd007, 0x3f7f29e3, 0xb7d84bf9, 0x0fdd9df9, 0xf278a878, - 0x9f30bc9f, 0xe33d52d3, 0x4ead9ff3, 0x1520fb83, 0xc54d2872, 0x3c579594, - 0xbfe403fa, 0x907fc7c5, 0xeac5cec6, 0x575cfc19, 0xd173cc06, 0x9e707323, - 0x7c8824e5, 0x7633f158, 0x4482fccf, 0x238a9f4a, 0xd839f727, 0xab7a763a, - 0x4f11371d, 0xfb0242c3, 0xe189af18, 0x640f181d, 0x607f0de7, 0x65913fec, - 0x60e0bf98, 0x30e45af4, 0xa5d1f1ee, 0xb77f9624, 0x9d03b737, 0xd3d50cce, - 0x475c8e21, 0x87c710a4, 0x2bf69170, 0xce9a9f1e, 0x52681dcf, 0xea8eff11, - 0x0e5029ff, 0xdd65dbed, 0x8efa6059, 0x1deecc5c, 0x3e3e4eff, 0xec013b85, - 0xd469d3d7, 0xbf338c1e, 0x9d630e03, 0x0c5676a6, 0x3bc8c59f, 0x6bedff93, - 0xf21bbc98, 0x0a519e1f, 0x609d9ff5, 0x81df0472, 0x8ae142fd, 0xa1fd63a6, - 0x07ea02d9, 0x93c6893b, 0x9732edf3, 0x95bd7373, 0x12fc285f, 0x7c3dc7ac, - 0x2324e303, 0x2dbed01d, 0x8fbf48df, 0xae30abd5, 0x86bf6fb7, 0xfae62f1c, - 0x1f45ad60, 0x07524790, 0x2d5b7fb4, 0x0c3e7787, 0x35e54bf2, 0xcafc81a4, - 0x27c15ef8, 0xf1bc8fbb, 0x9fb72a3d, 0x35b90c44, 0xdcab55eb, 0x409dec56, - 0x27edc9e2, 0x2b893f6e, 0xae3cb4b7, 0x903bbadc, 0x7ad6ff9f, 0xd3e3c0d5, - 0x7a1a3c16, 0x5a7c3fb2, 0x1db7e4f5, 0x493d5c5a, 0x45209dff, 0xe0d1f97d, - 0x2aff8343, 0xcf06a5ff, 0xa9f0f50b, 0x7c3d87c1, 0x9f61f06a, 0x8f09a478, - 0xe1bbfad6, 0xc0853a6f, 0xcfc63273, 0xfdb00fab, 0xd1ddfa67, 0x2f888521, - 0xd239971d, 0x4a48747a, 0xc96c3e6c, 0x75ed2c47, 0x69603e4b, 0xebe4b41f, - 0xf7abed4d, 0xb9d8511f, 0x9da9a89e, 0xe4a7fcb8, 0x01f13883, 0x6baa1d63, - 0x010954fb, 0xf1bbb87f, 0x0925797b, 0xfe5e2079, 0xf2f188bc, 0x26e38a2e, - 0xeed74e3a, 0x608f7c6c, 0x57c593b5, 0x2f6ed4ba, 0x93ab93d8, 0x553bbe58, - 0x683d0269, 0x593b7794, 0xd02bafdc, 0xb18a4ded, 0x203fdeef, 0x08ef1ea2, - 0x7e78d293, 0xa140de28, 0xfd20edf8, 0x80fdb3d5, 0x61d7b02e, 0x30ac84bc, - 0xd154e3f0, 0xe21cb59d, 0xde22ad35, 0xe2b85b6b, 0x239c2f16, 0xfb903ae9, - 0xbe5a329d, 0xdb22d7e8, 0x52e90ca6, 0xf81f8c46, 0x9a6d0911, 0xf5fec024, - 0x059fe47a, 0xb85f9807, 0x797c7d70, 0x95dfe4a8, 0x4054efbb, 0xee7f52ef, - 0x87beec64, 0x23c54fd1, 0xff03f296, 0x15a6e5c8, 0xdb951fe3, 0x1e41f5cd, - 0xe4ec183f, 0x92c7bee7, 0xb77fdcb1, 0x9e0fdec5, 0xa77fe62a, 0xeba7d28c, - 0x3ce04898, 0x2203f9c1, 0x6efce7d2, 0xe3007e76, 0xbf01d7fc, 0xe7b12b77, - 0x7c82cea9, 0x1ebfd55d, 0xefccfb3b, 0x3e06ee8b, 0xc14ef7da, 0x767a694f, - 0x7e23dbdf, 0xdf67f905, 0xf4877acc, 0xa0e53f6d, 0xba55f713, 0xff907a0e, - 0x4dff9ebb, 0x7f90ddd6, 0xecf18ece, 0x145f83ae, 0xad753f00, 0x1e8057b4, - 0xefe7e2ec, 0x45ff3d56, 0xbfae0741, 0xa9c7488d, 0x9f4fe64e, 0xef5ff03f, - 0xf381fdc1, 0xc0ace807, 0x42e838be, 0xa5fbaaf9, 0x5d6fe313, 0x14517fcf, - 0xa5fc27eb, 0xfbe5a9f3, 0x521e5d9d, 0x4be017b6, 0x7544fb62, 0x1b6ebabf, - 0xd3512fbc, 0x40594876, 0xf0bca7eb, 0xafd002a7, 0xdd997b5d, 0x3c7729d4, - 0x8179fb0a, 0xca340f35, 0x209d5e94, 0xff698364, 0x0128de6b, 0x978bea39, - 0x715c613f, 0xfc58f8a0, 0x043e0d7f, 0x4f3fe99d, 0x29854c18, 0xdef8ff07, - 0x0e27a03b, 0x8d2f91da, 0x59127ef9, 0xe5ccf681, 0xfff4dde6, 0xe885bcdc, - 0x03bde640, 0xefe13de6, 0xc0d7de77, 0xbed4a1a1, 0xcf97d072, 0xf30bbf9f, - 0x847e3c7b, 0xfefc8077, 0xfcf9dfd2, 0x7bee98af, 0x97bddd29, 0x7f87f79f, - 0x9feef3e7, 0xcb9ebfee, 0x79c2aee9, 0xfe17ba98, 0xa95df084, 0xfe12939e, - 0xbfbde5be, 0xfef61bf9, 0x35bf9b5a, 0x93cf1b27, 0x70b0c03a, 0x40b6667b, - 0xc8ed7178, 0x9dd82a99, 0xd5ef3f62, 0x7e60484c, 0xf7b02895, 0x1650c821, - 0xcfdc240f, 0xf80d6382, 0xdd9b880e, 0x4ddc933b, 0xc9137768, 0xbc53aedf, - 0xbe7abdac, 0x911acf1f, 0x21056f71, 0x8fc9399f, 0xbf8b6ef1, 0x5d1028d9, - 0x74aef6a0, 0x818f37f5, 0xb48f23df, 0x9805ed45, 0x33690fbe, 0xaaca638f, - 0xdc87f262, 0x53bce6f9, 0xbcede733, 0xf061073f, 0x0c247c3b, 0xd4716cf1, - 0xd3ce1561, 0x02256389, 0x4938a54f, 0x0efc086b, 0x7dfccfbb, 0x7ee10252, - 0xc7865fef, 0xa716048a, 0xed718512, 0x9471e03a, 0x78dce30d, 0xe2f11b48, - 0x08baf7c7, 0xf17baff7, 0xf80ed4da, 0x663fc094, 0xd5fa17f6, 0x12d3fb84, - 0x691a42ef, 0x76e69dd3, 0x2cbe8fdc, 0xb25d189d, 0x969d39aa, 0xd062e899, - 0x4c7d0e21, 0x7cf03174, 0xd2b1f4a5, 0xebff8ac5, 0xf75f1813, 0x2e832f47, - 0xef1d6e99, 0x7fdcc9d7, 0x133f0128, 0x820199f2, 0x7fdcabfb, 0xbc745290, - 0x7eaa24a7, 0x7e0097bc, 0xe01a945c, 0x86deef2f, 0x3f73a4f1, 0x00dbff7f, - 0x44afd54f, 0xebf8a0e2, 0x5121eddc, 0x2b0a5ef8, 0xb6569fe0, 0x404fb889, - 0xacd168a4, 0xc3627d98, 0x85faa80f, 0xb953e707, 0x4e9e1ed7, 0xf7dcafbf, - 0x61da0141, 0xcfd1bb2b, 0x605cfd09, 0x14750f74, 0xa5703ec0, 0x2b11fcc4, - 0x6049acbf, 0xcfb396f1, 0xae20cab9, 0xe762ec23, 0xb7232b7f, 0x7398f6c8, - 0x9904a14d, 0x739e9bc5, 0x3d085ea1, 0x28f9e021, 0xdcf62f80, 0x9c87e1a9, - 0xf060427d, 0x9df197ed, 0x4f5dca98, 0xaa7c4275, 0x1fbb2df2, 0x5dbaf8cc, - 0xc87ee29f, 0xf1ec5f94, 0x2e1fa076, 0x7d12e29a, 0x44bb01e2, 0xb6da8fe4, - 0x6843f41a, 0x36a2f91e, 0x2beffdc2, 0x7eab57f4, 0xb83efcf1, 0xf4f55670, - 0x7f885ee3, 0xe1df699d, 0xaec0b8c5, 0xfae7c74b, 0x3591fff8, 0xd6ffffdc, - 0x3b4f7669, 0x067fffbe, 0xf176a0fe, 0xfb9609d3, 0xb106bbab, 0xb44914f7, - 0x71ef52e8, 0xf0b9ed55, 0xcfafc428, 0x51e4fdee, 0xcffabb80, 0xfc14787f, - 0xa9d0720a, 0xba827dc2, 0xf18ebf9f, 0xdfbbe33e, 0xf9d03d70, 0x2f18e3c4, - 0xfa9b7ced, 0xe75ff41f, 0xc0b3a7f3, 0xea7ceccf, 0x4f10698f, 0xa9f9f3b9, - 0x9dce6ef8, 0x27494ccf, 0x9189f471, 0x0786ff02, 0xd2b5af10, 0x11db48ed, - 0x51ce7ff4, 0xd9ff83ba, 0xd489d713, 0xc69978b0, 0xe3bb39e3, 0xc4fbc7c7, - 0x7d66da6f, 0x4842c6e7, 0x0646bf65, 0x4139c710, 0x006639e9, 0xe3cddc74, - 0x5d6f9175, 0x0e738e32, 0x3af4a0fe, 0x85e3a16b, 0x3d8f45b6, 0x836d750c, - 0x44e38dfa, 0x233f8007, 0x413fbefe, 0xe40122ff, 0x60bfef68, 0x37e80cfc, - 0x73b84e9d, 0xd82c85cf, 0xee48f8bf, 0x85ef8b9e, 0x21576f3c, 0xfcf9511e, - 0x9d4f289b, 0xf8c71ccf, 0xf071e136, 0x8ff3d24e, 0x99f92bc5, 0x1eedbacc, - 0x74e1ff16, 0xe690f880, 0x071e72c5, 0xc46d7c62, 0x0b8bfa87, 0x73b1718d, - 0x40bec627, 0x7877f6cd, 0x6e97a5bc, 0xd7a044c2, 0xcfdc97fb, 0x02a0f030, - 0x8d8dae1e, 0xc38fc67b, 0x2d3dc4f5, 0x427a0374, 0xae27b3bc, 0x7b13d849, - 0xcde16175, 0xcef47178, 0xda5e2c2d, 0x8f3fc729, 0xaf41c465, 0x9fe25976, - 0x3fc581e1, 0x2b8f372f, 0x9760d3c5, 0xf15afd86, 0xf8abf675, 0xae5bfdfa, - 0xe85f9d81, 0xdaad7f77, 0x3de61f7c, 0x05dd3825, 0xef6d6bfb, 0xa7cf042b, - 0x2b73b374, 0xf967be7c, 0x3fb3d3f9, 0xd62e3117, 0xfa823914, 0x8c3faadd, - 0xbc2b57fd, 0x6b787077, 0xe3f5b3f7, 0xd84f5eec, 0x7b39fb4d, 0xebe439f8, - 0x63efddda, 0xaee8ee5c, 0x988e95a7, 0x8fd616f5, 0xce7ccc70, 0x80a8793e, - 0xdfe379c5, 0x3171ab1b, 0x40eeb37b, 0x76ea71fc, 0xa71a6a7f, 0x9851142a, - 0xf1e9701d, 0x2dfa48ce, 0x7699dfd0, 0x3a4ddf19, 0xbee31113, 0xc9701c17, - 0x95a11f7c, 0x475d0fc9, 0x71c09ef1, 0xf0a77f76, 0x573c04b5, 0xd2f1e77f, - 0xb7fde077, 0x8358a93b, 0x82b6dfdd, 0x4fdb69f1, 0xef4021f4, 0x13dfe3b6, - 0x07dafd61, 0xffb18df8, 0x4fd44e8b, 0x50fd50f1, 0x10a06ef4, 0x77aad5d8, - 0x66cb7dae, 0x938e9f82, 0x2342eb0e, 0x83ee07ed, 0xbc39b9c0, 0x569dee57, - 0xaa88f00a, 0x7d0a754d, 0xf9bb21e7, 0xafde557d, 0x21ef9aac, 0x6bc6af90, - 0x266f8fd0, 0xcc664b8b, 0x9f165232, 0x87f7190c, 0xabc213ca, 0xaf7f7ce8, - 0x28bb3706, 0x8d9e7c5e, 0x78112fd9, 0x06a26a27, 0x2e63d3f6, 0x4bc1de7e, - 0x83bcecbc, 0x7aa3643b, 0xf6ff61fd, 0x9e08930d, 0x7c06d867, 0x819e73d9, - 0x2f800b44, 0xea7d768d, 0x321de72d, 0x5a2a13e1, 0x17338722, 0xfd5025ee, - 0x77866ab2, 0xf11fe42b, 0xb2cdf7b0, 0x3821f748, 0xdb8db0df, 0x1560d9a3, - 0xe77df6e7, 0x6fbeebec, 0x78a53296, 0x853f30e9, 0x535ff5d3, 0xca7c5ce1, - 0x0d4fc52d, 0x2d856951, 0xa3dc1a63, 0x78bc7949, 0xcfcd066c, 0x34f4ff5f, - 0xe2f7ffac, 0xff3459b1, 0xb20e7b93, 0xcf012afa, 0xaeb0bec1, 0xeff01a76, - 0xd9fb96d7, 0xb9663314, 0x77f0057f, 0x77eef02e, 0xae706917, 0xefe15ba2, - 0xdda00465, 0x7f0c89d0, 0x9f77ee99, 0x98657f02, 0xf00563ad, 0x7fcf63eb, - 0x16f78491, 0x2aa1fbf9, 0xdce15469, 0x789a2d15, 0xf3e712f1, 0xccfbbcfa, - 0x498dcbf5, 0x3f8177c1, 0xbc8de79a, 0xef1d1a6f, 0x0e718ae1, 0xf2d00e76, - 0x829aa34e, 0xe9c85d74, 0xcb3df84a, 0x8b3e7c45, 0x02c290c5, 0x7f5caddf, - 0x5751ef19, 0x1ef4578b, 0xdbab8735, 0x67fbefd5, 0x3378007f, 0x007f8293, - 0x3fdf59fc, 0xb815c57b, 0xe519f500, 0x5c7de25f, 0xeb333de3, 0xea4468bb, - 0xfb3efb8e, 0x5a2efe56, 0x9bfef07f, 0x69ba283b, 0x682f39ff, 0x39518f7b, - 0xf150b31b, 0x31cfd1c3, 0xd2fd0bcb, 0x0426c220, 0x1fa71076, 0xf788cf3c, - 0xb822ee1f, 0x1765db5f, 0xbbaff074, 0x7d4549fe, 0x3a70b99e, 0xae5d5ffa, - 0x339c08ec, 0xc35bbaea, 0x018a3d7d, 0xe869e401, 0xf828c481, 0x3e1e5487, - 0xe7c3c8b7, 0x8f37fe66, 0xdb5175db, 0xa9fd81df, 0xa06a3fbc, 0xed8bdcc5, - 0xee9e9912, 0x8e10d06a, 0x087424a1, 0x8e81fdd6, 0xebe6e397, 0x46cfa737, - 0x9eeb9e9b, 0xee1ff880, 0x28ffc18e, 0xcc74bf77, 0xe63a3377, 0xd1d0e3bb, - 0x7bdd6efa, 0x6858e0ae, 0x28fcba77, 0x7d675fbe, 0xdf4aceaf, 0x21f5a93a, - 0xed2b3b78, 0xfeb8a7c0, 0xb31bf418, 0x29d22c7c, 0x00939e86, 0x3e07318e, - 0x06bc01b5, 0xe7ec1f1d, 0x9ba9793c, 0xf1d673ad, 0x063acad2, 0x9fb4e307, - 0xf74cd6e5, 0x451c0a0e, 0x69ca897e, 0x87c58dba, 0xb7efb6fa, 0x9d4b9cff, - 0x59502cf3, 0x73ff14bf, 0xfe064f00, 0xfbf3756f, 0x7ff17dea, 0xf8a3b43b, - 0x3fe61dbf, 0xbbcffc00, 0xfb0dfe14, 0x87eb8abf, 0xa29fd82a, 0xda1ff47c, - 0x3a1cb4cc, 0x8dd134ee, 0x8764b072, 0xd931f7c8, 0x3e865ffb, 0xfd5d7259, - 0xb917b821, 0xf20267e4, 0xfefe42eb, 0xfdfc27e5, 0xc1b9eb4b, 0xea10b2f2, - 0x1f9fcbcb, 0xaa3ea30c, 0xff2e65da, 0xbbcf7767, 0xde785997, 0xad352417, - 0x2b4ebdf7, 0xb9bbcffe, 0xb4e858de, 0xd72f7bc5, 0xdbd68748, 0x33cce74c, - 0x83f4f4a6, 0xa6cfa0fe, 0xb8f189bd, 0xc409957f, 0xa5297413, 0x2019de10, - 0xf4094285, 0xd7e5cc5b, 0x72d86fe8, 0x1d9ffaf3, 0xcc43df32, 0x43df316d, - 0xbe6ade1c, 0x66d57887, 0x51c43df3, 0xc43df361, 0x338d766b, 0xae4747e5, - 0xb31fb537, 0x3f29b27f, 0x534dfa36, 0x66c7f1fb, 0xda13f29a, 0x7f6a67bf, - 0x4df35bed, 0x5475d7f5, 0xf86fea9a, 0x7f299968, 0x9b3ff763, 0x311747da, - 0x61b878fd, 0x5bdc1179, 0x7872f030, 0xa15362a9, 0x9b08e97c, 0x9e5b105a, - 0x90056ba6, 0x7fe0e916, 0x532f27f5, 0x8a2a3f1c, 0x898ba75d, 0x536fd26c, - 0xd47ce61c, 0x8f7dfe6d, 0x35722c97, 0xcb527ea4, 0xbc1d9a08, 0x63cf0f24, - 0xc63af953, 0x01b1dbf5, 0xa0dfb7ea, 0x9b46d57c, 0x2f956f20, 0x9a01bde3, - 0xad8fd886, 0x1f9f77b0, 0xd4f99a72, 0xf95e8fd7, 0x0738db9d, 0x53facad4, - 0x264bc6cb, 0x3fca3139, 0x172d8c2a, 0x73c74f16, 0xabf5fd40, 0xb35c16f8, - 0x3bbc107d, 0xa3530f3c, 0x16cca9bc, 0x67dfdcf7, 0x7fd0bfee, 0x8ec7dcda, - 0x7cf00cfa, 0x26daf7ce, 0x7b56bf38, 0x51fa377b, 0x5e337619, 0x5decf37a, - 0x479e0363, 0xac3e481a, 0xb6fdc6f7, 0xebe13445, 0xd177ce36, 0xe0d333db, - 0x3f66419c, 0x87a155fe, 0x1b47ebe9, 0x042cd742, 0xe98711c2, 0xb456795e, - 0x39f81a6e, 0xeb79f8c3, 0xe7f8b64d, 0x0c3c92a0, 0x48a0e92f, 0xdd505ec1, - 0x2b9c2f68, 0x4f0bd77f, 0x0f68dcc7, 0x38e87926, 0x17b4c7f3, 0xbad4fbb1, - 0x5ee8e67f, 0x947d0db8, 0x026c0ee5, 0x93e592fd, 0x17dd9688, 0x83dbf49e, - 0x788ef02d, 0xefcdb263, 0x00b77cc6, 0x4c7fd9e3, 0x5e3a20c8, 0x84459fe3, - 0x75f0f1af, 0xeec83e78, 0xabb8c7ae, 0xcfc24f31, 0xe6711809, 0x89d9be0b, - 0xabc6cf80, 0xe107ee7b, 0xdc17907b, 0xf7e876c1, 0xc71946c2, 0x982c9c6d, - 0x4b798dea, 0xf78dbf9b, 0x6cdcb2be, 0xde74e5de, 0x933db700, 0xa8f8d5c1, - 0xae113240, 0x28f4bdff, 0x5cfb35f8, 0xc507def8, 0xc7c010c7, 0x73fb3d39, - 0x3a79319b, 0xee419aaf, 0x9ed16bad, 0x4ea7ef89, 0x8fa1e637, 0xe33bd134, - 0xe2fc332a, 0xc6fd1946, 0x3c6e4945, 0x886e10ef, 0xe79afa72, 0xf99be4df, - 0x5c295b9d, 0xf8884eab, 0xd1d6b6de, 0xfd28f4ba, 0xe5cdbcae, 0xf17d6b0f, - 0xf0634e7f, 0x7ba7f852, 0x4f36de40, 0x79e3f9c3, 0x31ff806a, 0x0d9c3c81, - 0x452c17fc, 0x236c183e, 0xc7d36fb0, 0x7930f04e, 0xd951ed9e, 0x72be357b, - 0x85be8726, 0xfda76cd7, 0x5dfa7995, 0xb0f36ff7, 0x4f36ff75, 0x72ff759c, - 0x975707ef, 0x54851fb5, 0x37b445d4, 0x111fa908, 0x3d53476b, 0x1bfd0e56, - 0xc7f13179, 0xff6fd005, 0x65bf9a76, 0xede5f644, 0x80cfb034, 0xecfb0d0f, - 0xaed98f4e, 0x3fbbd18c, 0xfbbd30f4, 0xf4c0cf43, 0xfda18fee, 0xe345efe9, - 0x4aa935da, 0xb4f7bd7c, 0xac1fdd87, 0xe7821553, 0x0fd9fb03, 0xdae5c9d8, - 0xd6feef3a, 0x1ff9cba5, 0x4f832e39, 0xfcfefacd, 0xf4112d31, 0x4207ca54, - 0x86b777dc, 0x3c6dbf2c, 0xad9b6bd0, 0xf7cc3378, 0x78fe1667, 0xf59f4d68, - 0x18f1cc2b, 0x6ac78b8e, 0x099b478a, 0x973c3b8f, 0xb6bf0fb0, 0xdf30afbe, - 0xf8e4e9f3, 0x09bf7aa6, 0xeb373bc6, 0x6b8822bd, 0x1cf9ced4, 0x1ed7fef5, - 0xaebccca7, 0x1d397e18, 0xa1e00567, 0x799fd673, 0xe303ae7c, 0xb99eab4a, - 0x58e2112a, 0x7a0d9335, 0xaa7df044, 0x4839f9f3, 0xecfb7397, 0x2e79c03a, - 0x3d139d99, 0xa3daefb7, 0xa4f8f710, 0x2c7258e1, 0x793dcf7d, 0xfda648bc, - 0xbc7bdb9d, 0x7703c248, 0xd43bd361, 0x5b7f1735, 0xdef77014, 0x37e1e84b, - 0x368f5b07, 0xe57c593a, 0x37173841, 0x6abfda86, 0x7a65f212, 0x285eed9a, - 0x1dbf1d17, 0x395c21fc, 0xa62fe63f, 0xd04ab259, 0x7ec11633, 0xee373cd3, - 0xc972f967, 0x9dfa6cc8, 0xe387ad12, 0x6af9c4cc, 0x04efc098, 0xf1444eb8, - 0xef3c02f7, 0x3ef86076, 0x02b243f1, 0xbdffc29e, 0x78093c1a, 0x09ab3a4f, - 0x77c41a89, 0x471e6e8a, 0xd30a6953, 0x3ab7ddbf, 0x848cf7f0, 0x53aaaf05, - 0x3cdafea8, 0xdd8efd93, 0x920b63f9, 0x55691fc0, 0x0df2de99, 0xb463e1eb, - 0x6be7078b, 0xe6231737, 0x40577c75, 0x921d1955, 0x8a6b6c33, 0xf9c78c35, - 0x25fe98f3, 0x3dff1a52, 0x1eb7ca29, 0x1c43a6cd, 0xc5cef8d8, 0xfc522bbf, - 0x7803cebf, 0xf0fcdb46, 0xabfb8f4e, 0x92ca386f, 0x28ccfb69, 0x945e5fbe, - 0xc39de1c0, 0xfbef07de, 0xd345e34e, 0xd4b5187d, 0x27b74efc, 0xe214b4d0, - 0x6defd0fc, 0x8bcef8c9, 0x38a29eb9, 0x0bbb9691, 0x0aaee5cd, 0x47e18f9a, - 0xf6d677eb, 0xae925f86, 0x37f63832, 0xbf0f1038, 0x79fd506c, 0x340e8f94, - 0xb07f30f8, 0xda34c341, 0x0fcb1230, 0x2f31f837, 0x986cf4da, 0x7faffa4f, - 0xeebb1490, 0x9d54efc2, 0x75c3e18c, 0xf9ade472, 0x88df8f80, 0xaf15af88, - 0xdefe478e, 0x3a8e9a34, 0x7367bd86, 0xfefec632, 0xd257f2e9, 0x0d5f284a, - 0xd3afd1f9, 0xefc3c64a, 0x17f3b096, 0xf63a4170, 0x257aee1e, 0xe093f9a0, - 0x34c63477, 0xfbc2863b, 0xc95bc1a4, 0xfd239458, 0xbbf089c5, 0x6c337b0b, - 0x949a7eb4, 0x07f8ecd7, 0x64deab80, 0xe7e7afe7, 0x6c9f1f33, 0xbce3afd6, - 0x0a66ff4c, 0x71bce3c5, 0x537e09f8, 0x39acfd00, 0x3307b9c6, 0xbf54891e, - 0xeb8a76e1, 0xdfb3efe6, 0xc754485f, 0xf7bde1fb, 0xcec35ecd, 0xbec5f7a9, - 0xff99bee7, 0xe1e2440e, 0x29176825, 0x103bf63e, 0x0f7b0a29, 0x4d930489, - 0xe5cdedef, 0x0606ccfd, 0x1f57d09a, 0x15fde6cf, 0xfb0e791d, 0x8897df83, - 0xf087eff5, 0xccd8c3df, 0x3574d3f5, 0xed4dec50, 0x5bd4676d, 0x7759ebbf, - 0x0bd1216d, 0x890143f6, 0xed04bd80, 0xd4bb698a, 0xdc02030f, 0xd7ce33ef, - 0xcdf80b3e, 0x93ddfdef, 0xebc3027d, 0x8a7d3c93, 0xd4494eff, 0xe3079813, - 0x123c16fb, 0xca7603da, 0x6206bb3e, 0x8fe47452, 0xf8947ef8, 0xe701c53b, - 0xbc0f53fc, 0xd9e5eecf, 0xbf38143a, 0x7c5bd2b8, 0x4551c413, 0xf3033ea5, - 0x816f4ef7, 0xfa9e83fc, 0xdda3d887, 0x1f0137c5, 0x06f7f3a4, 0x01000408, - 0xe1aa080e, 0x43fd638f, 0x64654eb3, 0x2bf2cc9f, 0x873637bd, 0x3f5f2132, - 0xf208f80f, 0x7dbfb48d, 0xc021c149, 0x86e16e47, 0x423763e6, 0x037f68de, - 0x5789ffb6, 0x3b8ffe65, 0x4af60d98, 0x79a55e4f, 0x625e4c4f, 0xa960e279, - 0x239abf31, 0xd073c47f, 0x3bd807b5, 0x6607a95d, 0xd4cf3008, 0xff1033fd, - 0xbcb7d5e7, 0x878c342b, 0x04eb608f, 0xf41b978b, 0xa6e1ee30, 0x79f783d9, - 0x9d61f863, 0xc4c76cd7, 0x0fbc27dc, 0x1fd3ddf0, 0x36cbaf8f, 0xf74a9ef6, - 0xc6efd88f, 0x547b030d, 0x86b9b884, 0xa3dc2e69, 0x70c1fea7, 0x98395c12, - 0xcde35fd6, 0xb55e3a41, 0xa9cdfb3b, 0xa75f2f5a, 0x80772964, 0xf8b54e3e, - 0x3f5cd935, 0x7f8b508f, 0x372b4893, 0xf0b5c10a, 0x8f686c9e, 0x937de2ac, - 0x4728195d, 0x228eb967, 0x5f3183f5, 0xcbbfefcd, 0x476b832b, 0xc4591e81, - 0x76556ef4, 0xdfa658a0, 0x8d973d57, 0xf0670bbf, 0x2452555d, 0xf7bb9c6d, - 0x3791b75c, 0x21e4477e, 0xef09d5b5, 0x5afb18f2, 0x6437fbb5, 0xc7fd3ec1, - 0x3b46de87, 0x36624971, 0x76d359c2, 0x69df815c, 0x7ca36da9, 0xd8fbbf47, - 0xa3c763d9, 0xc887f25f, 0xbe026fa0, 0xc368d0fe, 0xd9fdddcb, 0xfd522f55, - 0xea85d3a6, 0xd3038368, 0xd5fd7a9d, 0xf09c0ae0, 0x49c9b82e, 0x1cf1e9f9, - 0xeafe055d, 0xf51eb7bc, 0x3a8ae3d8, 0xd3aff80a, 0xe066c3fb, 0x9124aae7, - 0x5f0febf3, 0x7ef8f3d6, 0xb9efcd3d, 0xbfa6edb7, 0xa160df68, 0x7ba9fed9, - 0x41fc8dc4, 0x02df92ed, 0xb66ed51f, 0xb3fd6085, 0xbef1da39, 0x1be82773, - 0xfbe65fd4, 0xa6051b99, 0x5873430f, 0xf772fa1c, 0x74be2b34, 0xfd8c7091, - 0xe99124bd, 0x84290aab, 0x5f1576fb, 0x2ffeb17a, 0xba69c71f, 0x1c77da0f, - 0xe31bd637, 0x838ef754, 0xf6fd527c, 0x5fcff461, 0xafb0dabc, 0x77ffd475, - 0x61cfc53e, 0xe874f538, 0xd0d941e7, 0xa4cfd427, 0x1ee78678, 0xf9243e79, - 0x47a97908, 0x2e6dacff, 0xf6fa04c9, 0x7eb313d6, 0xb74a25d2, 0x3e781297, - 0xc9737f74, 0x13ed38a4, 0x8c73ed2c, 0x7fb14ffc, 0x3a0f3c2b, 0xda0ef37b, - 0xbd93fa5e, 0x6df00f27, 0x4bfa59b0, 0x86dfc636, 0xb7fc19fd, 0x65fbbbc7, - 0xa5e9ef78, 0x10f140a4, 0x2068df66, 0x15245b87, 0xc0d1877f, 0x3ebe1ef3, - 0x8d797c55, 0x78bdff09, 0x9f95302f, 0xfb4cd06e, 0x2e178ba1, 0x7b3f7bc3, - 0x41563af8, 0xdb3eec42, 0x7da6b923, 0xc70fffd0, 0xb8a385d7, 0xfe4a381f, - 0x328c70c6, 0x385e81e9, 0x5fe54df2, 0x69310e17, 0xec366976, 0xa1b1ad53, - 0x0b66909f, 0x6ec07239, 0xf7ec5ffb, 0x0734201a, 0x61a899e7, 0xce57da6c, - 0x079f6039, 0x448e79c6, 0x40e3498e, 0x056d749e, 0x913f53ac, 0xe5a1afd0, - 0x8619390e, 0xfde1d56e, 0xd8952a2b, 0xb0754e5f, 0xe6f51986, 0xab876277, - 0xe5a258a4, 0xb879d5e3, 0xdd94e5ee, 0xfdf60755, 0xcfe17736, 0xbc931357, - 0x5ab27da2, 0xc7f68a58, 0x9b17c49a, 0x3d38df61, 0x0233d981, 0x58f9b179, - 0x267abc46, 0xbdf72daf, 0x31c41378, 0xaed4aeb6, 0xab6e7f06, 0x0c391c33, - 0x6e3df9eb, 0xdcaa3dfc, 0xf816e175, 0x83710abd, 0x314bd70d, 0x2b6bbc29, - 0x6078179c, 0x8bec1f84, 0x40d760ad, 0x5c6e35fb, 0x421a5bff, 0xe2af2f68, - 0xf5f6c0eb, 0xe7385493, 0x9296e8dc, 0x916bbd61, 0xb8056feb, 0x64efba5e, - 0xd03ae3b3, 0x4196fe63, 0x80cbef3c, 0x71cb4d75, 0x14f5e58c, 0x68575b19, - 0x3485c183, 0x44ffc3f2, 0x33d412ad, 0x6b0ed127, 0x04ab2f74, 0xbfd68e3b, - 0x7a78a0ec, 0x85e3993c, 0xe8f4e7d7, 0xa0cd93a5, 0xbd15c507, 0xef3a12f9, - 0x7a633f1d, 0x3fda09ea, 0xe7452bbc, 0x18778213, 0xe84947bb, 0xc1242587, - 0x74d0c76f, 0x9dfb0e74, 0xbd17aa5b, 0x3849c7e8, 0x491f635f, 0x0f7ec519, - 0x7ac3da1d, 0x83919093, 0x0cca98fb, 0xe2835ef6, 0x66fde371, 0xdd5677e3, - 0xb3a7f8c4, 0x67df2978, 0x43de5971, 0x895fae70, 0x784ee99b, 0x4f862137, - 0x0b7bcb15, 0x07cc0912, 0xcd544b7b, 0xe449bfe5, 0xd8834afb, 0xb70eadef, - 0xa32ed085, 0x35e98452, 0xd9f68a24, 0xf981d268, 0xe66de031, 0x0d2c35c2, - 0x278d8e2f, 0xbbe2c8ba, 0xc7ec1101, 0x788d5bb4, 0x44f5f04c, 0x96bfdeba, - 0xfc36e3c8, 0x66538c77, 0x7d7ee214, 0x5fab1266, 0x0fbbc815, 0x338dbcec, - 0xc69c61a6, 0xf58cefb0, 0x16dfb0d2, 0xab579872, 0xc17b5c42, 0x3a16ebb0, - 0xb6753e59, 0x8868e0fe, 0x0b53b66b, 0x2fee1b34, 0xf96af8b3, 0xb034e2e6, - 0xba1e16cb, 0x4ce4ed15, 0x8b65d995, 0x8250ce36, 0xdadee1a3, 0x8a07f43c, - 0x84484c37, 0x4ed5847d, 0x8575e27f, 0xfbe267e8, 0xc7b503b9, 0x355da6b6, - 0xab71e419, 0xca90128d, 0xeeb24bfb, 0xb17c0b1e, 0xcced0f21, 0xc6c109ad, - 0xd6efda24, 0xabfcd67f, 0x4ea7fe68, 0x8c38f0bd, 0xd5813ab3, 0xc051bbc3, - 0x12e73d9b, 0xc9bbe1b6, 0x3d6f8dfd, 0x1252f097, 0xa8ca7f7b, 0x7e536fff, - 0x80007d7c, 0x00008000, 0x00088b1f, 0x00000000, 0x7dbdff00, 0xd5947c0b, - 0x66fdf895, 0x666579be, 0xf263c992, 0xc2130922, 0x9e4e5e4b, 0x124c2280, - 0x4cb443c2, 0xe8202a10, 0xa79034f0, 0xbadc5d48, 0x30040cff, 0x5706b650, - 0x84ea2b11, 0xbbaac562, 0x351ba341, 0xb88080ea, 0xda446dd6, 0x8ffd16d2, - 0x4810154a, 0xfed2b58a, 0x39cf65dd, 0x7cccdef7, 0xb5f01993, 0x3efeb4ff, - 0xe7ddf7ee, 0xce73df79, 0x12e973bd, 0x2c614dfc, 0x5630a494, 0x51c1d8ca, - 0x618cf58c, 0x24dea98c, 0x064dcf06, 0x34e2d26f, 0xa37efac6, 0xf5e1bb67, - 0x926f6617, 0x25d8c6c3, 0x79fa2ed1, 0xa0b199aa, 0xcdb3b189, 0xc11c166e, - 0x336699d8, 0x1f966b95, 0x9fa0c698, 0xb9850e9a, 0xc55b19f2, 0x3f6336da, - 0x69923baf, 0x3d0155dc, 0xf4648e0b, 0x5bfe0977, 0xd528fcbd, 0xebc9dd5f, - 0xaa0eb2d7, 0x4f3192bf, 0xf76b3c07, 0x1cd0595a, 0x51df5fae, 0x4a1f69ac, - 0xd7bf51d2, 0x3b06fb25, 0x5bdd8c9c, 0x2abefc3d, 0x5d569f78, 0xfae1f662, - 0x13e38e58, 0x87afa8ab, 0xebe63af7, 0x77aeb188, 0x49de5c04, 0xac4e8a82, - 0x32b1d0ed, 0xe03ad6c6, 0x1ec62e9f, 0x6c7cd850, 0x15f7f6b7, 0xc2632919, - 0x9e2ad6ed, 0xf898c70c, 0xa8bc6a70, 0x88d48167, 0xc467dab2, 0x345e35f5, - 0x0ef3fbd2, 0x63075fb3, 0x3ff4c91e, 0x7fac2d70, 0x1953eb26, 0x909f53cc, - 0xcd5d8e38, 0x71258b58, 0xba673e37, 0x08a17d0c, 0x53333038, 0xf8337e71, - 0xc4ebf62b, 0x71944769, 0xed403ed8, 0xa98ed967, 0xc473400c, 0x8303735e, - 0x90b037f7, 0xce060aca, 0x28fdfa0f, 0x2359dfb2, 0xdd1be5b5, 0x09ecf2da, - 0x7e6332da, 0x9a4fd782, 0x1a4eca9b, 0x04fefdc2, 0x0311d6a6, 0x5802b72e, - 0x5eed7eb1, 0x0464e04b, 0x923beb1e, 0xaec6e535, 0x88c9c0ac, 0x1ff16a71, - 0x135ff059, 0x589d775f, 0xdf4607f7, 0x5bc00ead, 0x71190b3d, 0x46c140dd, - 0xacc658ef, 0x7c45e616, 0xf16fd81d, 0xcfe812b0, 0x00b76e66, 0xabbb1b7c, - 0xdef02595, 0x30ef876a, 0xe196273f, 0xfaf03569, 0x0e88058c, 0x39da8fe0, - 0x5bed99bd, 0xb713e415, 0xcdfedaab, 0xff00dde7, 0x4f0293dd, 0x24ac3d95, - 0x0ea3ac46, 0x5e1e91d6, 0x07eb39c7, 0x582f8865, 0xa5ec6fcf, 0xa6461748, - 0xf3d78524, 0x5cb5e1ad, 0x5dc6af0b, 0x1837a236, 0x1844bde7, 0xcea761a7, - 0xceb2846f, 0x7e4463dc, 0x3ce917b9, 0x1c72de06, 0x6f3c4c4a, 0xe0c73c43, - 0xfcaceda7, 0x1cc7e43e, 0xc7181fe4, 0x6527eeb6, 0x8f818b27, 0xfa1737aa, - 0x054dbea0, 0x547186fe, 0x08a9bff8, 0x6d3bd9c8, 0xe9d03255, 0xc3e73b29, - 0x7a2e890d, 0x0abc50ee, 0xe75d35e2, 0xd5fa47c9, 0xcc43b827, 0x66a3f1c1, - 0xcb601942, 0xf962c1ae, 0xefe81ebd, 0xcb1b9821, 0xf0098416, 0xcbc2c878, - 0xefca392f, 0x6ee308dd, 0x0de5e64a, 0xd5b9bd3f, 0x16ca093f, 0xe5439e59, - 0x416d0c87, 0xffdde03d, 0x44f5c982, 0x28f7b53e, 0x32305e58, 0x4d4c04f0, - 0x2365843f, 0x4226a65e, 0xf4b720e7, 0x9b769a2f, 0xeed05ea0, 0xa78427fb, - 0xfb39ff5c, 0x26363cf1, 0x4d7e7f66, 0xacdf797f, 0x53bf183f, 0xfbf87577, - 0x419dc4d4, 0xc2e76f3d, 0xe7a72c76, 0x9ff43f03, 0x6d89a2fe, 0x0623e285, - 0xda179b76, 0x632c5dd5, 0xd43908c1, 0xb679f023, 0x5b7241d9, 0xf943afbe, - 0xa9f9063d, 0x7d70e487, 0xfe46aa47, 0x7f5cb94a, 0x7f4d5af1, 0xc27c8e39, - 0x43dabd57, 0xe2feadf2, 0x121efa64, 0x736cf4f2, 0xf889e926, 0xc8d20ce3, - 0x1338f0f5, 0x72f8b059, 0xefa24ce3, 0xcbe61c72, 0x06bdb922, 0xa4240ce7, - 0x87bc8237, 0x750c2e71, 0x465f2525, 0x0276d99f, 0x67ac4591, 0x63341a9b, - 0x07dcdbff, 0xfc18be1c, 0xb844e520, 0x1edb51bd, 0x811b23f4, 0x4863edf4, - 0x7aacffb7, 0xd4fa91cc, 0x5038f066, 0x8af6a86f, 0x34372e23, 0x86647e4d, - 0x5169280a, 0xd97f3d39, 0xd1e881b6, 0x411f706e, 0x3aeddafc, 0xafbe1f97, - 0x483ce9b7, 0x730e2d27, 0x51bdf100, 0x7281c1b9, 0x076bf643, 0xb8f38f31, - 0x7a421b60, 0xd57ade3d, 0x0f54898b, 0xa9199266, 0xc6f7ff1f, 0x0f17c583, - 0x31bd8f1c, 0xfa0b88f1, 0x6e744b57, 0x910be00b, 0x1d0471fa, 0xdf63f744, - 0x779cc6a9, 0xff093d74, 0x8436f8b8, 0xe7fe1112, 0x8119ba6d, 0x4d2ef318, - 0x9e9bbe56, 0xdf25145a, 0x3c3b7f93, 0xd095ed88, 0x49f20a0f, 0xa32696fe, - 0x90bc2dfc, 0x3922e958, 0x73b5ee9f, 0xb6e385b1, 0x7d9a8ed8, 0xed988fa4, - 0x3ebfd913, 0xb849fd3e, 0x64aade18, 0x04601f88, 0x4ae37a86, 0x412bb070, - 0x1597e22f, 0xd3e50caa, 0xa76f3a40, 0x77d7f4f9, 0xeb11e743, 0x0edd516f, - 0x75fd6ba4, 0x99ca331e, 0xe6398ef5, 0xaa379410, 0x20f9d9ae, 0x02defa87, - 0xb7d6127b, 0x1cc8ad29, 0xc15a8f8b, 0x2df9c46e, 0xd669d64d, 0x1d669f23, - 0xf7e8dfe7, 0x9eb9925b, 0xb13fdd68, 0x9f1253c7, 0x79d2407e, 0xcb9b8f51, - 0x5856c754, 0xe7c0de9f, 0x0763896b, 0xc1e37eca, 0x0b7ecb6b, 0xa87569c9, - 0x44f68039, 0x549b78f4, 0xbe078f77, 0xf8f9826f, 0xc7c39cb1, 0x3aa254df, - 0x16d74376, 0x47330257, 0x4b3837d4, 0x6c17fe08, 0xdf0f4c69, 0xc63d2137, - 0xd3849798, 0x68efe4bc, 0xe8a2f93f, 0xc3b7f732, 0x5d0d10d9, 0xcba2c6b6, - 0x4b37a879, 0x3999fcf9, 0x9343fe72, 0x8c7c8ebe, 0x49b29ba6, 0x977c83cc, - 0x5876cf01, 0x66caa76f, 0x807d43ec, 0x9844d6b6, 0xe636cddf, 0x393e9900, - 0x32677cb5, 0xe7acb7ac, 0x3f219180, 0x1d693a74, 0xf47da275, 0x8e14a6b8, - 0x838a533f, 0x3dc7499e, 0xf8014f4f, 0xb824f676, 0x99d4f814, 0x0630fa02, - 0xbc088f7c, 0x9fc6d633, 0xf21c686a, 0xb65fac8f, 0xc3767988, 0x6b0250f3, - 0xb2bd8335, 0xc607c84f, 0x154fe7ee, 0x99c61718, 0xdde8cafd, 0xf58a2f64, - 0x80b5021f, 0x43d3d3f5, 0x77fd14e3, 0x585edbc0, 0xeade047d, 0xdbc221cd, - 0x6bdf46db, 0xe3c69f08, 0x772c74a1, 0x87933d1e, 0x70b670f8, 0x25efb5fb, - 0x6ee9006b, 0xd3d67e20, 0x0e2eeafc, 0x81e2fe62, 0x8353ab78, 0x2eeb5fa4, - 0x5877d1e6, 0x129cdfb7, 0x6c1b3efe, 0x2eb00986, 0x4270e666, 0x47c2c4f8, - 0x896be0bb, 0xa3eb500f, 0x081f02ed, 0x3ec48fa7, 0x4eef1fa7, 0x780666e3, - 0xefe66b3f, 0xdf246799, 0xfe7d0987, 0x005e4251, 0x0d1f33f7, 0x7a46ce07, - 0x91e95d50, 0xe2cea77a, 0xac3e6fb9, 0x67abbd9b, 0x5963c04f, 0xed15ada5, - 0x4f2665ab, 0xcb5dda12, 0xeb2bd3de, 0xc48409f3, 0x3c042b07, 0x5df732cf, - 0x36ff3f88, 0xc209e38b, 0x97ff769f, 0xf8bca3bf, 0xa2bf681d, 0x9346ef4b, - 0xcda56971, 0xf596fd8f, 0x876d3c54, 0xad5b2bf7, 0x2efd062e, 0x04fee29b, - 0xf765bded, 0xf21b5c59, 0xa438bf71, 0x5dfa0b3c, 0x03be60fb, 0x9d7581e5, - 0x06ecd337, 0xeb7ee093, 0x6de02b4c, 0x8964b293, 0x7dac0852, 0x1516ca7f, - 0x57feacf0, 0x281667e5, 0xc17f755f, 0x8c75f316, 0x1cb282bd, 0xd0ff59ed, - 0xfedf6899, 0xf646a712, 0x7f6fb72e, 0xca274479, 0x82a65bc5, 0xece5180a, - 0xce60d9d4, 0xb78a532b, 0xf4fc6198, 0x0ea14f14, 0x32935bc6, 0xb7f62661, - 0x7fb1bef4, 0x77df09dd, 0xa99acca4, 0x44de13e6, 0xcaccef7b, 0x926ed0a1, - 0x54b3cf2c, 0x56697f42, 0x27a7b616, 0x090fbf00, 0x77f68f8f, 0xbdfdbf67, - 0x1cd4e660, 0x53454bc0, 0xbffd0aa5, 0x96db729e, 0x36315731, 0x877281fe, - 0x983fc607, 0x15a664b2, 0x9469dff0, 0xf16d97f5, 0xcc9d58c0, 0xbe0186f7, - 0xbafef1ff, 0x9fa86699, 0x742dea96, 0xcd53fac0, 0x91996ff7, 0x65f81dfb, - 0x4fbd12a4, 0x1271482c, 0x90461cdf, 0x33ebade6, 0xf82afd72, 0x71d3873d, - 0x9424797f, 0x4ce511ed, 0x10dcee5e, 0x4e9c7e5b, 0x33b972e5, 0x8f77f621, - 0xef004b90, 0xb3e90ea0, 0x96181acb, 0xc027961f, 0xc409e64f, 0x3cb9db5f, - 0x639abe01, 0xd98e3e27, 0x5fe537df, 0xd3f53b80, 0xe8ac7aa9, 0x0d7290bf, - 0x71c56666, 0x69764cbe, 0xcf5975e4, 0xbfb79252, 0xeb7c154a, 0x5671f0e2, - 0x330ae56a, 0xb8470cf7, 0xc58b76c8, 0x4b47f33a, 0x88d052ff, 0xe2d6b9fc, - 0xacf9c0c9, 0xc19e57dd, 0xd787632e, 0xf8d72c5d, 0x98ebc24b, 0xf407ef4a, - 0x44b9fd0b, 0x5f31eeff, 0x57c95e07, 0x7d1a5780, 0xc33ad2bf, 0x3bfd69fd, - 0x7ee3fb03, 0xc57a019e, 0x1b9e7b18, 0x415eb853, 0xe422ebf8, 0x5f214ada, - 0x3d916a41, 0xabc5fe7e, 0x8fcd6f76, 0xf503771c, 0x7a7df80f, 0x412fee0a, - 0x2b1ca2be, 0xb0b33d53, 0x8a4f597e, 0xa079ed03, 0xde828db7, 0x8937a454, - 0xa694cee7, 0x76ef5a72, 0x863bb1c5, 0x3913f81d, 0x83c536af, 0x22c649f6, - 0xc4497e9f, 0x87fca4fc, 0xff453bfe, 0x1f9e9c25, 0xc5e7a7ed, 0x2fc23fc8, - 0xdf40dcc4, 0x5fce0763, 0x08ce36c1, 0x2582f5fd, 0x7091f380, 0x2ff4b6fb, - 0xb8ba87ed, 0xda912a7a, 0x260f1c65, 0x219ea0ba, 0xb9f9c5c5, 0x6bc4e3e3, - 0xe9755f51, 0xebe2e299, 0x2651b946, 0xe7bfa4e5, 0x764a8548, 0xbb2e584c, - 0x72919ec8, 0x87366833, 0xbdbfdfeb, 0x9446c667, 0x2fbe26ab, 0x1483d34f, - 0xe3cf0a2f, 0x2fae14e5, 0x2798f827, 0x24781d96, 0x08e52ed9, 0x75e1e3ad, - 0x5863ec95, 0xd7e85d9f, 0xf93f2109, 0x664c9eb3, 0xf0e13ec2, 0xb67bfa90, - 0xdcaff429, 0x47a5a64f, 0xa53b0659, 0xee105741, 0x89cfbf1f, 0x8263fba0, - 0xf3f1a20e, 0xc013e55d, 0x48708fc1, 0xc872e14d, 0xed056509, 0x17f4150b, - 0xb55cffc0, 0x3f35bdcd, 0x2e36de62, 0x1d7a9d8f, 0xe0576397, 0xfe54b48b, - 0x3b25efbd, 0x1e1873f1, 0x2ff98edc, 0x1d76f701, 0xc17dc1ab, 0x09f01d21, - 0xaf8da2d2, 0x598bfcf3, 0x29e7efd4, 0xeffeb93a, 0x1bb72e45, 0xd7ce3c61, - 0xbfd63f64, 0x3b5da83c, 0xdcdfde7f, 0x658f4e54, 0x68853dc7, 0xdaf30cc7, - 0x285fb8dc, 0xc07399eb, 0xdde1e500, 0x4b6b038a, 0xc1de1f3a, 0x4ba814f9, - 0x67ade5c0, 0xa5b5fb22, 0xbefa3a72, 0x38fc31d6, 0xcbc457a7, 0xcd3e08e2, - 0x7871b54d, 0x084cfac1, 0x472b554f, 0x9bfbf3e5, 0x0180f787, 0xf0075bd6, - 0xe12db140, 0x64b1d9d6, 0xf8f90583, 0x1f237338, 0xa258ef9f, 0xdd788b1b, - 0xebbec8c9, 0xf00f0f97, 0x147b4875, 0xe903b2e8, 0x5cd4eaf2, 0x71d86f1a, - 0x7c0c758f, 0x1376861f, 0xec3b95fa, 0x4c57dc01, 0x4dcdf54e, 0xedce7845, - 0x4a2064ab, 0xeb4dac1a, 0xfbef112d, 0x7d4177eb, 0x7e9f63a2, 0x36f3ce2c, - 0xc2bab6c6, 0xfaa981eb, 0x6f5a1fd1, 0xa02d3e04, 0xd6e11072, 0xfbf5e469, - 0xcf8a3316, 0x8cfbe834, 0xf7f41df8, 0xa3cfa22c, 0x2fc414ba, 0x6ed09bee, - 0x737bd3ae, 0x67d7dc14, 0x07a8dc98, 0xf4421f60, 0x54c2c87e, 0x26fff40b, - 0x574e513c, 0x8fd8efe9, 0x502aaaf0, 0xae242ddc, 0x60dc85da, 0xcd37dc41, - 0x7a25629e, 0x39dd5f64, 0xbff51ab4, 0xfa09e395, 0xcc7e8b31, 0xff30a2e6, - 0x2aef3afd, 0xfd48ffda, 0xa8514876, 0x8dd7439f, 0xb112ddde, 0x50fec22f, - 0xaa521ffe, 0xfa40ee73, 0xb23afb17, 0x7ac2d30f, 0x2295ed17, 0xfdde245b, - 0x3ca17e62, 0x7b48a3a4, 0x7ed3ed14, 0xb1dfd67b, 0xd9c83a65, 0x823a33f1, - 0xd152073a, 0x01ff33f3, 0xf60551d6, 0x70e005ac, 0x33972a5b, 0xfafdf287, - 0x30df9c44, 0x3abc3f58, 0xd31be09c, 0x938f0b64, 0xe90ffc2e, 0x482fee46, - 0xbfcfe04f, 0xe73b72a7, 0x1e5c6927, 0x978d21fe, 0xfb6313d3, 0xf510be2b, - 0x1f971354, 0xfcb9cb5b, 0x41b7ae8f, 0xedadfbf4, 0x668a31de, 0xef760f7f, - 0xf76e5486, 0x885fb91a, 0x0a9613c7, 0x873b06fa, 0xabb614f0, 0xda503c78, - 0xccf45fa1, 0xf372f2a3, 0xbfe8d97b, 0xe69fedbf, 0xb6f487dd, 0xf27a37f2, - 0xf1149c57, 0xbec99582, 0xbfdc64f4, 0xabf6c427, 0x75d6273c, 0x1f9199ba, - 0x1b8c53f8, 0x893dec82, 0xaf284371, 0x34e0f9da, 0x2cd5bfe4, 0xe5e0fe40, - 0x5c51373b, 0x61407970, 0x69f7052e, 0x1627ee5e, 0x47bd58f8, 0xdf4bf1af, - 0x931936ae, 0x77e984c7, 0x6e369b45, 0x58abb358, 0xf6f6fe53, 0x440b2569, - 0xfcb0a1c8, 0xa3ef4699, 0x1ef495fb, 0xd47ea76d, 0xc3f8d2ec, 0x461cee97, - 0x97f597eb, 0x77ad3731, 0x66816b59, 0xf395acde, 0x49f9bc49, 0xd4bb45ba, - 0x469e731f, 0x008ffbcd, 0xff08fefe, 0x4353d2ff, 0xa92d1e69, 0xba40ffbe, - 0xcac3cf09, 0xdabf1afc, 0xb027c724, 0x7ee16656, 0xff23a049, 0x5081ece5, - 0x6fffa72a, 0x71d1f70f, 0xfee305f6, 0xca0beebf, 0xcc397126, 0x0c3614da, - 0x6aa7e31e, 0xa0bfb4ed, 0xa7c52bbe, 0x616beb95, 0xa45f2d47, 0xd45177ad, - 0x5dea28bb, 0x6912bfc9, 0x2805299f, 0x0d7f78d7, 0xcff38f82, 0xa0ba351c, - 0x6e34f8de, 0x3d3916c7, 0x6cef5097, 0x438e24b3, 0x4b36ca7f, 0x52f5005e, - 0x38bafaff, 0x48336d1d, 0x033b8a3f, 0x5ffed6e1, 0x88a8b677, 0x0fb07dc7, - 0xfe587900, 0x8a1641e8, 0xae375390, 0x01cb3c53, 0xef2176de, 0x7d7cdcea, - 0x71a0ee75, 0x5d93f428, 0xd395e7c7, 0x23515fb1, 0x08d4e5da, 0x419a5f7f, - 0xc1cccfb3, 0x8d254e32, 0x9a9ce3cb, 0xea1432a0, 0xa3daef65, 0x875fd8a8, - 0xbb337a42, 0x41130009, 0xdc25d957, 0xa4b1b9be, 0x2636595d, 0x5d56870c, - 0xe00718f5, 0xeadd35a7, 0x8f737d46, 0x0d2437d3, 0x182279e7, 0xf8fcedc4, - 0xda2a3d13, 0x7a753fef, 0x619cd20a, 0x8ef4b838, 0xd6a7d46c, 0x6d9e7c13, - 0xae63fbfd, 0x4da22867, 0xdcddabfe, 0x23b3d19e, 0xa487db8c, 0x8c37d2af, - 0xe727bd24, 0xf4229e97, 0x3df33a45, 0xadfaa367, 0x68c9f08c, 0x861be93d, - 0x2cf6e6ef, 0x815577c7, 0xafbe0f77, 0xa8aab8ca, 0x6c17de05, 0xa14baa0b, - 0x62bbcbdd, 0x85cb83fb, 0x4c75813e, 0x75c9f5c2, 0xc82e495c, 0x7e38867a, - 0xd60fc90a, 0x1ff7b119, 0x2f7d2230, 0x216d347f, 0xa36eb7ce, 0x30949991, - 0xf4ea7ffc, 0x64f9c6ce, 0x082bb477, 0x93dfe91b, 0x1dff4ae3, 0xfcfe477e, - 0x96f928c8, 0xfe5c5fd3, 0x2cf7a75f, 0x1b67948f, 0x6927848d, 0xc7e7873f, - 0x69d5fded, 0xeabecf5c, 0xf9c12ef4, 0x276d7434, 0x3daacf7f, 0xf9631a1f, - 0xe2f9a3ab, 0x6a54704a, 0x6ea0bef8, 0xeb8039be, 0x25547f2f, 0x68dda83a, - 0xdd5938a4, 0x9fb8fb33, 0x46e61ee7, 0xb1d75139, 0xe30e594f, 0x4fb33ed6, - 0xd7011159, 0x05017541, 0x2ec233e7, 0xafcb90f9, 0x3f47ba68, 0x872dda32, - 0x9c4e5c2d, 0x15f9b72d, 0x8359eb80, 0x9deb0eaf, 0xfdbab2cd, 0xbc3c61f9, - 0x11fa6fb9, 0x3fb037cc, 0xb3e20a67, 0xd33bb755, 0x475af50c, 0x5f48dd19, - 0x36fa753f, 0x54525c23, 0x4fb6276f, 0xd7bbb34e, 0x89975b43, 0xfbbca115, - 0x1f1870ba, 0xefe32745, 0x85d3fce1, 0x91db8872, 0x813fc845, 0xa7b4bb34, - 0x361dae48, 0xc73c75f0, 0x9eff7cf8, 0xe89079ea, 0x8d0a48f8, 0x54175d9b, - 0x7f9d9fd0, 0x6b9239e6, 0x9d30ffb2, 0xe4891e79, 0xb3cf2bdf, 0x56f488c3, - 0xf950e42b, 0x8f947ba3, 0x4bfde623, 0x6e91f430, 0xba019fb2, 0xfdf7d1b4, - 0x3ea8d333, 0xbdf0b933, 0xe16aed42, 0x79088afb, 0x4311d723, 0xf5c3ecee, - 0x1cf44ed8, 0xc82772e4, 0xbe628dfd, 0x157cf8d1, 0x9a7c1fe5, 0xde99ea06, - 0x3123fd1b, 0x48787a2e, 0xe527f502, 0xbedf3440, 0xe51ce82a, 0xfe46cea5, - 0xe52bb25a, 0x22bd64fc, 0x34fec567, 0xc10f4382, 0x4a977ea1, 0x7a32a9eb, - 0xc111de87, 0xfd16bf0f, 0x03f9b81d, 0x07fdca23, 0xa25dfdfe, 0x8536fac7, - 0xedacf1e2, 0xd43ce35d, 0xf4a7fe47, 0xe2ce6768, 0xf1db0126, 0xa784bbc2, - 0x2e5c9d59, 0x53ee77d7, 0x74c2d997, 0xc0e67f9a, 0xf56748ad, 0xfb86261d, - 0xdfbfa022, 0xe9a27c20, 0xca47c254, 0xb4f878dd, 0x9472e0ce, 0x47e48df9, - 0x3e54fd85, 0xdca429fa, 0x4eaa7bfe, 0xfbf809f8, 0x1cbc690b, 0xa7df1fa6, - 0xdcb08f08, 0xe45f10b5, 0x603a299f, 0x5bb87dc6, 0x5a7f3f21, 0xe4678725, - 0xc6c7aabc, 0x54ce9b97, 0x50d437a1, 0x587b1cde, 0x7fcbf7be, 0x810bfed1, - 0xe41f786f, 0xd410d9ef, 0xd1fe72f3, 0x7277cbf8, 0xce831b7d, 0x11d71bfe, - 0x3da4dfad, 0xc9e6e920, 0x8f46aa5d, 0xea469dd8, 0x731b0ecf, 0x728ec79c, - 0x61d8cf1e, 0xc76cfae0, 0xe500737a, 0x780b9bc9, 0xa17d995e, 0x43cf8831, - 0xf875a5ba, 0x1f3650fd, 0x5ba755bf, 0x0dd6e583, 0x7842d636, 0x4b3a24f5, - 0x19127e91, 0x1e5c8f97, 0x973cf03e, 0x5b7e7567, 0xeb3fc180, 0x5397737c, - 0xe2cd39dc, 0xf333b8c6, 0xb3ce341d, 0xd72ba40f, 0x2e8dfb73, 0x83ab3f78, - 0x03c49ff3, 0x2fa253c8, 0xae120fc9, 0xb8727861, 0xf8927e4b, 0x67f4bbf8, - 0xa77cbd03, 0xda3daabc, 0x46dbdc78, 0xbe4ed5df, 0x706c3acf, 0xc7869fa1, - 0x6fd1e217, 0xb3b7baed, 0xb51d824f, 0x7a2df33a, 0xfd85be4a, 0x27bf86ac, - 0x3817bc09, 0x74afbeb9, 0x2da9ba72, 0xacbe20e9, 0xfc44d93d, 0xe5c19b6c, - 0x5684ed9a, 0xcff6331e, 0xa8dbbd62, 0x63b5955d, 0x5477e61a, 0x7038ae3d, - 0x6e4f1fbf, 0xfcf0aede, 0xbd774fb8, 0x72f98891, 0xf2b02bec, 0xe1629e31, - 0xe4eb9deb, 0x5eece272, 0x7bd13800, 0xf672f193, 0x63fa95fb, 0xc20a63c1, - 0xfac056b3, 0x139533ec, 0xec7e84ff, 0x61ee49bd, 0x9ecfe4b0, 0x3feee9b9, - 0xeecfbcc1, 0xf746e299, 0x978b5a65, 0x69cfa7e8, 0x037ee371, 0xf40cf7c4, - 0x78efae17, 0x685af123, 0xabe9fa77, 0xd76e508b, 0x799e798a, 0xe10ebf5e, - 0x7fc9e1b2, 0x6bdf8c9b, 0x09aa4a03, 0xf8fbd9c7, 0xbe63677f, 0xf2469eea, - 0xfd3cb517, 0x17f311ba, 0xfe768174, 0x03926f7e, 0xf9fe9deb, 0xef08c9f6, - 0xfa168e96, 0xede7e67e, 0xe4f03e54, 0x77f6bdbf, 0x1378e3f4, 0xccef58dd, - 0x2f09fbf3, 0xf2953e75, 0xf5d1e2db, 0xb9fb7d8e, 0x8f3d44bc, 0xcb9f307c, - 0x92d74931, 0x793f4f7e, 0xbd48c4db, 0x0ab7df21, 0x026b4e7f, 0x099f23d7, - 0xe0adadfe, 0x9ecfcef1, 0xfda7ccb5, 0x1c343181, 0x6375c5f7, 0x2ddc5d38, - 0x71d751e0, 0x46c1a187, 0xdf9fa9ed, 0x73e3df02, 0x27e7d02c, 0x64852923, - 0xd7ca25cf, 0x0faa57f9, 0xbfa026f5, 0x1f45e6e7, 0xeb1f382a, 0x2d432698, - 0xfe69f3cd, 0xf91d561d, 0x6c6d6cbd, 0x38bffb3f, 0xe02ec26d, 0x59dd907c, - 0x3922e39d, 0x8b0f7260, 0x6bb387b0, 0x27182d7c, 0xcfad7ebe, 0xbe3c07ad, - 0xb4e8ea7c, 0x727e5041, 0xf84c52a4, 0xcf5c2bd7, 0x4e346df9, 0x81c1fa3d, - 0x3e0b768f, 0xf5307749, 0xdc03921a, 0x32a5501f, 0xaa7e46d5, 0xf513923e, - 0xee0f42ad, 0x736e7e11, 0x764dde5f, 0x26bb676a, 0xed061f62, 0xf72a366c, - 0xf310fde5, 0xe7f8674a, 0x1971de93, 0xa467be69, 0xf27e603c, 0x8b7e4a7b, - 0xbca11bf6, 0x57d1fcc1, 0x285de59d, 0x3d33e51f, 0xefe4bf8e, 0x74b8fbe2, - 0x15ca174f, 0xa35537b6, 0x95c9e20f, 0xe79f3703, 0x0f95fb7a, 0x901b0e89, - 0xdf7c710e, 0x5ede8d49, 0xe815c24e, 0x890fa5f0, 0x7177970e, 0x55d0daf9, - 0xd4fdc46e, 0x69d7e10e, 0x7484f410, 0xbfe8fb84, 0x9c69933a, 0xe1a1c986, - 0x0bcea728, 0x12ff3bba, 0x3a43b7a7, 0x0e01f91d, 0xdedd1eed, 0x8fd40ca2, - 0xf0978d4a, 0xe6f800dd, 0xa3daf376, 0xd7d56768, 0x6bf23730, 0x07e0a743, - 0xbe117bb0, 0xcbd55d0d, 0x6941bfb1, 0x0ddfc933, 0x41b4c976, 0x63a86e50, - 0xd96fc8a5, 0x425e2abb, 0x7c5d60ba, 0x035d9e3f, 0x4dd22cf6, 0x9f5bbd5a, - 0xdb8f7a8f, 0x2c8fd7bd, 0x723bf6a3, 0xf2e7145d, 0xf38a3157, 0x19fb40ef, - 0x68d65df5, 0x36fb3f6e, 0x5cc5dd92, 0x6537e409, 0xd60d753e, 0x622ff06f, - 0xcd11d794, 0xb4292fc7, 0x5808680f, 0x56681f29, 0x1a7fb717, 0x9f1f38ba, - 0x4f91f093, 0xe4adcf43, 0xc4c17f8f, 0xd0fe11fc, 0xce9a5f37, 0x268becf5, - 0x359fb3d2, 0xb0c7d87b, 0xbc85b7a0, 0x6dac7097, 0xdd21d7cb, 0x09937632, - 0xcc4cb1e7, 0xf5c0cda3, 0x03d0b246, 0x3cf8db05, 0x77e174d4, 0xa789d74c, - 0xe2e79b51, 0xe17f93f0, 0xc88f189c, 0x39e85d22, 0x797eba18, 0xeea4f890, - 0x9a5fde19, 0x677853c9, 0xfb4abd04, 0x0b1e9a28, 0xbbd9b8c4, 0x4c282a0e, - 0xd1cd77b2, 0x35f5f9f0, 0xeb08d82c, 0x2e977ebc, 0xd91c6538, 0x9e490b4d, - 0x58b237af, 0xd2232af9, 0x9556fdb9, 0xbf442dea, 0x36cdd576, 0xb93fa477, - 0xb3a3c12a, 0x24571da0, 0x12ded8fd, 0x4a9d1b8c, 0x6f11bbb7, 0xd25dd2e3, - 0x5bd8d30e, 0xdcdff703, 0xcda1bc0e, 0x1ff70e3f, 0xf309f581, 0xda09ae29, - 0x0edcfc8d, 0xf7fb8f68, 0x9cfed7dd, 0xb85bdfef, 0x070402ff, 0x6f5499c9, - 0x9d8ffa09, 0x5cb5de05, 0xb1ddd93f, 0x93aaf3d6, 0xcdc0e7af, 0x3ee216b7, - 0x8dae61b1, 0x5781e1f8, 0xde9ca594, 0xbee21140, 0x83f9c7da, 0xe13c7f01, - 0x3b247a22, 0x1bc9a1aa, 0x9c8f4d88, 0xaec01a5f, 0xe81b3b42, 0x93b70d71, - 0x13f38c6d, 0xbfb94ba7, 0x6915b947, 0x8d3e4acf, 0xbf497be6, 0x35ff7cfd, - 0x81bcfdf9, 0x8079e3f3, 0x3f7bd203, 0xe9ccbf9d, 0xe07aeb7c, 0x15bef847, - 0x4225b1f8, 0x7fef47fe, 0x1fb89e70, 0x1ef6f290, 0x3a5177a7, 0x6fdda1ca, - 0xab50c66d, 0x2f0d8f94, 0x397e196f, 0x958ccbbb, 0xf0335fa1, 0x60fd246b, - 0x445ed68c, 0x09ea3f4f, 0xfed8baeb, 0x6dd2bb8f, 0x3f3fcddf, 0xaee52f30, - 0x7981d2f4, 0x73a8e929, 0xadbb6f10, 0xa58fb401, 0x3e7a291f, 0x499f044b, - 0x03fdca7c, 0xfeb021c6, 0x37ef82fd, 0x888f7a89, 0x84bec467, 0xf3a5c1f8, - 0xf679487d, 0x6c91f471, 0xb5f97df7, 0x2f5238e4, 0x8c8dd346, 0xaa7ae0a3, - 0xd7afc4c7, 0xcfec5fb6, 0x29f8e8a2, 0x800b5fc1, 0x6dde7037, 0xc417e086, - 0x19d8778f, 0x99f813e5, 0x71e31527, 0x7ce08daf, 0x386fb234, 0xfa66b7b6, - 0x92ba44be, 0x8f7c5d7e, 0x115aaa71, 0x6bddacbf, 0x7f9e4408, 0xd18337b9, - 0xb376bd38, 0x91fc0f5f, 0x87dbe99b, 0xcc15fded, 0xf33d441d, 0x2b8a168f, - 0x8a5b8181, 0x8591a6f2, 0xefce1112, 0x205efb25, 0x0cf7d5fa, 0x39e3bf47, - 0xdf0e3425, 0xdafe109f, 0xfb5fc213, 0xcf7bd77e, 0x17ad02be, 0xf16e72bf, - 0x5ece918f, 0x7d21e4b4, 0xe7f4b09c, 0xdda125bf, 0x92b9817d, 0x690e772e, - 0x55ef5991, 0x2767fc23, 0x7ffdb1ec, 0x373c0b6f, 0x532b788a, 0xb7c3ed19, - 0x19f97067, 0xe3c4bf3e, 0xb4ebefad, 0x1cf937fe, 0xdfe1c193, 0x501ce719, - 0xd7df0661, 0xfce10e74, 0x50aed7d8, 0xdd66afbc, 0x41eb3ffa, 0xb5acd42e, - 0x9f09e907, 0x71ab8ed1, 0x283a83f8, 0xb970309f, 0xcd737f04, 0x07fd6165, - 0xc849d4f5, 0xc5077e33, 0xfd0a96bf, 0xcde9acb5, 0xa15fa1bf, 0x49e66546, - 0xf2c71845, 0x9f041e1e, 0x4f2db53e, 0xf2bff144, 0xa3a67747, 0xd458ca7e, - 0xa6c1f226, 0x55fed03a, 0x2fe8373c, 0x6f672f59, 0x132764a9, 0x1ede001d, - 0x22f6f0cc, 0xe24a2f1f, 0x7745c17e, 0x08fe035a, 0xf057b879, 0x7cfd3461, - 0xcdbce710, 0x01151997, 0xaa616fec, 0xefd46ff7, 0x7234e79d, 0xfa12bced, - 0x5f4823c5, 0x4fddd877, 0x22f2eef0, 0x05d263f3, 0x0e316bfc, 0xb7b1a204, - 0xbaf867b0, 0xbee3a47c, 0x5fa1dfbc, 0xf0e4dbab, 0x91bbf0bb, 0xf176cbbe, - 0xe3f141e2, 0xd2232e40, 0x8545c347, 0xf76961e8, 0xae51c79b, 0xa221a837, - 0x1b66a593, 0xa2e1b1e1, 0xd5a9e9ca, 0xdb243670, 0xa4d7ee03, 0x6032d27a, - 0x277bfe9e, 0x093c5325, 0x17c389f8, 0xe39c452a, 0x37c332f8, 0xf7e00328, - 0x36f13590, 0x305d7fdc, 0x8f3092bb, 0xf408d1ad, 0xe7753570, 0x43d84735, - 0xa5aec72c, 0xfeb7ee83, 0x6e5af386, 0xaf5119f6, 0xd134f0af, 0x4945b179, - 0x98c752c1, 0xd24fbc48, 0xf5fd1a5f, 0xc8497ef1, 0x3c8df797, 0x9d20646f, - 0xcf6c3c73, 0x39b2f510, 0xc79fbcbf, 0xe7c39e6a, 0xbb427828, 0x728887f7, - 0x170f2891, 0x7979d2f5, 0xf797e09a, 0xd17af1c7, 0xe3152ce3, 0x99e1997c, - 0x7682708c, 0xc7d22341, 0x673a166b, 0xfe404ac4, 0x935bbca1, 0xc82c764b, - 0x770869b9, 0x4c982718, 0x67a44cf5, 0x41c81358, 0xa96f67c0, 0xb5b3e08b, - 0xe305e81c, 0x289aaf41, 0x2bf1241e, 0xcf8d1af1, 0x77ca1985, 0x181f4fcb, - 0x51985ebf, 0xcd7e303a, 0x17c250d8, 0xf38c4bd1, 0xf5f0f11f, 0x03c73b6b, - 0x0cf2ebf0, 0xb1c183d2, 0x49b37c91, 0xb5ca51c0, 0x78b413f7, 0xe39d3cfd, - 0xbbd45ea1, 0xda1f7684, 0xe23eeed1, 0x7853f7bf, 0xae02b4fd, 0xfe5da497, - 0x5f2e024f, 0x529f6ba6, 0xd1fb44cf, 0xe2f214bf, 0x47ee74cb, 0x8ddebc07, - 0x09fa95f3, 0x19304ce4, 0xebd178f8, 0x6c339226, 0xd5e51f63, 0x83ffbd40, - 0xea645af0, 0xf41535bb, 0xdec10fca, 0xbb511631, 0x0647284b, 0x48c7efec, - 0xd433b0ba, 0x0e19addb, 0xf4941f6e, 0x48d7b8f1, 0x0ca5aebe, 0x657287e4, - 0x210c63fc, 0x6bf0e40b, 0xc142bf22, 0x6214aebc, 0x07f61767, 0x8c97ff70, - 0xa3dc30d2, 0xe8213bc7, 0x450cd1e0, 0xb215bc25, 0xaddbc442, 0x5f6e7eef, - 0x139e5d0c, 0x4d9365e7, 0xe7ec76be, 0x916fddec, 0x18c27e9d, 0x8b66de1c, - 0x7c18ddf1, 0xfc2521ec, 0xf4a7b6fd, 0x98d5e37e, 0xc1f67e7f, 0x4bdd619b, - 0x1c6ef47b, 0x5f3de972, 0xed1e33bc, 0xc5031eec, 0x6fdf406b, 0x4dde7153, - 0xa13caedc, 0x67c1d2d3, 0x3df76977, 0x907a0baf, 0xdca572e7, 0x157cfa91, - 0x93797373, 0xcb1bb890, 0x3b71dd1f, 0xce5dcb9d, 0x003d87bc, 0x666bd3f7, - 0x3b7c5d92, 0xcf5e51f3, 0x39ed56b2, 0xda6d15db, 0x073bedf2, 0x3925c39c, - 0xfd102abc, 0x2ba5f85e, 0xf3fbeb63, 0x333f2e82, 0x7afdf88a, 0xfdf8cc53, - 0x09fc85ef, 0xb4fbd9c7, 0x2f57fbf1, 0x8c6fbf1f, 0xed87df8a, 0x3df8e888, - 0x6113f7ef, 0x91bf606f, 0x2acffc71, 0xa3e3af62, 0x58b7690c, 0x9f19f935, - 0x125bb00c, 0x45e37be9, 0xd8f99c4b, 0x2b67fde8, 0xd7d38f63, 0x5f368e3f, - 0xe79edc20, 0xb5fdc809, 0x8bc693a4, 0x6567a459, 0xe1c7da59, 0x3df43976, - 0xf4babcfa, 0xf8be4b6f, 0x2ce66158, 0x176d47f2, 0xf29bbc76, 0xbb463f33, - 0xba72f908, 0x4c10b5eb, 0x278fd971, 0x8487570e, 0x1d7a26f9, 0x42675f40, - 0x98d8f211, 0xfd234f69, 0x3a6e66eb, 0xfee82797, 0xe8abbbd6, 0xbdffcf7c, - 0x322332a7, 0x53f72a6e, 0x8f69460d, 0x96fa34d9, 0x65e3e945, 0x1d916f5d, - 0x70d7f606, 0x7a7f3e14, 0xc3d26ef5, 0x1d37992b, 0xd5f7bde9, 0xe56e7411, - 0x3961eadb, 0x4bfc9b9f, 0x35bf3c0c, 0x3987ec8d, 0x75373e62, 0x67503b73, - 0x1c6818f6, 0xd239730f, 0xe7cd8b69, 0x8554420b, 0xf3fd75f2, 0x631de747, - 0x15fcc493, 0xbdf00f6c, 0x52d93c4e, 0xdbce265f, 0x31eae384, 0x8990260d, - 0x6e8996cf, 0x28a73e17, 0x83cf955e, 0x6b1a79e3, 0x3afac1ca, 0xd7cf4873, - 0xc7483309, 0xa2f0fdf6, 0x37945db2, 0xeb70bdce, 0xb36f7c0a, 0x8a313c93, - 0x04cf4c79, 0x6dfc88b9, 0xb75c6666, 0x4d3c16c9, 0xf4f133f1, 0x8f88b857, - 0xf91843fd, 0x07581241, 0xd9b53f9d, 0xb171f9ce, 0xb050e60e, 0x085c716c, - 0x9ce27ee2, 0xf3c7e6c3, 0x672f20c4, 0x5f3fa265, 0xc44ad5f9, 0xee67c80b, - 0x5df78a17, 0x11f3f20d, 0x88a5de42, 0x7908b5f9, 0x8adcc597, 0xe480c7b8, - 0x95f6fddd, 0x267ee037, 0xa3f7798d, 0x71387bbc, 0x32fdc506, 0x93e68f98, - 0xc8d5433a, 0x5b57a72d, 0x46af98ce, 0xe7053bcb, 0xbed3e597, 0x9413b337, - 0xbd04a497, 0x69529799, 0xfd12361f, 0x37210631, 0x3e78598e, 0xcf3166c2, - 0x8853333b, 0x78598e6e, 0xb6b7c25e, 0x7ddadc5b, 0x3f0a437d, 0xdd3e7fbf, - 0xc0f1c66c, 0xe113b98e, 0x07cc7607, 0xdfce167e, 0x41d29c2c, 0x6f9b0279, - 0xe01bdc54, 0x6bbb66fd, 0xeba40abd, 0x7f70a99f, 0xc728ea8f, 0x3cf69c7c, - 0x44f31b87, 0xf7be451b, 0xf6a38b66, 0x9a63f219, 0xb7d63d78, 0xed96e319, - 0xac0e1d5b, 0x37d95697, 0xaafb88cd, 0x9bb1cc15, 0xaff7a0c5, 0xbe608f80, - 0xe032c73f, 0x63f41149, 0x85bae23d, 0xefbe20d6, 0xf0177fc1, 0xdc3294f2, - 0x82bff2bf, 0x773a42ee, 0xd27a3cc9, 0x85dd8d97, 0xbc60d86f, 0xe485b982, - 0xf256f7af, 0x72132fb8, 0x571cbc60, 0x61b5d9f0, 0x85efa7ba, 0x5bb43ca2, - 0x4cd37ff8, 0x80ebae3c, 0x91c4ca21, 0xc69fac43, 0xe4cdc1f9, 0x6bd3e71f, - 0xfb0ff858, 0x4ff70cab, 0xf86a6972, 0x60ef9873, 0xbbb322a8, 0x8dea0ea5, - 0x91fb8357, 0xcf15afaf, 0x543cf142, 0xe5e9237e, 0x65cd9d1e, 0x373e71d4, - 0xc3aba017, 0x94b847ab, 0x60b4b639, 0x4129d73f, 0xd8cde67a, 0x9fd382de, - 0xc94cfc23, 0x9e00c699, 0x00996b37, 0xc8bf2678, 0xffa30f9f, 0xac2fff5a, - 0xcc74f118, 0x279ef520, 0xb9ffe789, 0x0ed53d68, 0xce97593e, 0xc22e7b33, - 0xcf3f28f9, 0x8b74d0c6, 0xa997fef8, 0xd7974955, 0x300f3cbb, 0xe5cf4b25, - 0x871e0ce3, 0xa66f9c6d, 0x7146e5bc, 0x7d53030f, 0xf08c3ff9, 0xc5b8c8af, - 0x7f3606bb, 0x46fd8c5f, 0x07b7164a, 0xfdc0dce6, 0x1f228dc2, 0xcc4f7e47, - 0xbfb27ee2, 0x377b4e64, 0x1e3dec93, 0x949dfd6f, 0x48d9235f, 0xf2115f94, - 0x5f248fe5, 0x278edfca, 0x85dfb47f, 0x29e799fc, 0x40bed036, 0xef2921c8, - 0x68ef22bd, 0x1018f301, 0x1ee23d4f, 0xabe5a395, 0xccdd0e48, 0xf7fef47c, - 0x00ff3c15, 0xfd80d308, 0x6b4334dd, 0x6af3cd3f, 0x8fcf37cb, 0x3e38afb6, - 0x7c0bb8e4, 0xa473efda, 0x6b433c9d, 0x87fa2f27, 0xcf4992af, 0xfea2fc67, - 0x3e70e0d2, 0x3e546351, 0x27c88351, 0x3c2aec6a, 0x4f911694, 0xf3cdd8d4, - 0xaeba1a89, 0xedc44f94, 0xb029af29, 0xde24e31f, 0xec94d25a, 0x727f910d, - 0x8a4ff310, 0xaf6e74c2, 0x0c3cf3b0, 0xa2bca1e6, 0xce95871c, 0x8aeab45d, - 0x9adb8fc8, 0xddf8d768, 0x5577aeb7, 0xbfe93d61, 0x4843f995, 0xc3f6b137, - 0x5f7c59d9, 0x7ee143b3, 0x3302ff74, 0x059d3bed, 0xc15c4d5e, 0xd1c767a9, - 0xa66ef8af, 0x3f27d64b, 0x2f830ec9, 0x019e18ab, 0x8979d185, 0xb67af6fe, - 0x5190fc91, 0xea99ca72, 0x338038a6, 0xf5f92c69, 0x921775e7, 0x2cd9923f, - 0xb84a61ee, 0xdb7379ff, 0x69ebcc55, 0x97576eec, 0x3774c2db, 0x43ec4b36, - 0xf48accac, 0x7bd7efda, 0xbd7e44ce, 0x30b79364, 0x19d7da0b, 0x8bbfe483, - 0x1f7a57a0, 0x2ede5f4f, 0xe150c5e8, 0xe602b05d, 0xd18efbd7, 0x0a6bfb8d, - 0xcfff41cc, 0x7e4c94bf, 0x230e7549, 0x9cb1b53d, 0xf45e93cb, 0x3e3ac193, - 0xfaf7e64d, 0xa466ac6c, 0x4ca7cf5f, 0xc55e3a23, 0xe83d8702, 0x7405db47, - 0xd2cf7918, 0x8eb96d1e, 0xa9fe9075, 0x3d00667b, 0xf2947c93, 0xf4b99eb8, - 0x741b8c06, 0xa1b3db6a, 0x285c395a, 0xbcf147f4, 0xff982da9, 0xf2e3ac50, - 0x0f772d91, 0xf5fb439a, 0x2c4f8e45, 0xa17f7228, 0xebaece5c, 0x73d29fb5, - 0xa17ae7fe, 0xad1ff454, 0x3d854abf, 0x17e41937, 0x7da56fee, 0x7ca9f506, - 0xcfadd750, 0x59e785d4, 0xbb49da22, 0x890bea50, 0x8c09f2af, 0xbbb579e1, - 0x1a7c84b2, 0xbe2086c2, 0x13e27fa1, 0x29583705, 0xf71fbfd4, 0xf18ad785, - 0xa8fc1e80, 0x733afdbf, 0xb36be900, 0xd2fa44d2, 0x3c3ff68c, 0xd23e2ab7, - 0xe35eff0b, 0x4c7d23d7, 0xdd374d64, 0x9926f500, 0xb728ac7b, 0x31fe4e80, - 0x585a7e92, 0xa29f6f30, 0x7efa23a1, 0x98edf936, 0x5af52474, 0x9edcf7f0, - 0x74bcc599, 0x0fe793cf, 0xa83aeedc, 0xd8267df0, 0xeed1079f, 0x93375b7a, - 0x2c2664e8, 0x3955eb03, 0x9e9ff8b4, 0xdf472da9, 0x5ad0c50f, 0x48744328, - 0x9c540678, 0x51bdf44f, 0x98f7291e, 0xb3e5ee56, 0xf8de78af, 0x423fc396, - 0x1d7583ff, 0x0ef6891b, 0x8fc4aa58, 0x27b0f4d1, 0xb78f7beb, 0x118ac9ec, - 0x7e15e96f, 0x68586be5, 0x40ca33e5, 0x687f3b7a, 0x82333e9d, 0xbc7f252e, - 0x1379e06c, 0xae3cebca, 0xc6ccc135, 0x252e1104, 0xf928ffdc, 0xd3a41ae3, - 0x95fd3094, 0xa487f789, 0x06cc197c, 0xd75dbd23, 0x01ea0965, 0xbfa2853f, - 0x8afe906b, 0xdc89f6c2, 0x184cb477, 0x98f96740, 0x4cf60e17, 0xb495d201, - 0x8e958a4f, 0xfde73c16, 0xb6f74bfc, 0xe8237ce0, 0xc3842dea, 0x8ae80559, - 0xf4036afc, 0x147bf6ad, 0x4bfc49dd, 0x359cba7b, 0x6e677ed1, 0xc1b3d702, - 0xcf49dbea, 0xba24b882, 0xa70e737b, 0x21e62abb, 0x5a672bba, 0x6b34a97a, - 0x0974d1cb, 0x74b4ea23, 0x8bba23e7, 0x7478d7a6, 0x4ee91837, 0x2bd4dbea, - 0x48e7ddd3, 0x8fc5df77, 0x3eee9039, 0xa7c672cf, 0x937a68bb, 0xc59f6cf2, - 0x75768951, 0xfa428d63, 0xa19df8a1, 0x511e582d, 0xf6764f9f, 0xd93764be, - 0xfc4d8ddd, 0x478f497b, 0x0533798f, 0x7cf7c56b, 0x1b96256f, 0xe877c1d7, - 0xcf18f4ba, 0x0f7a19ab, 0xa1b85eff, 0xbfbc0de9, 0xdbcfd1a0, 0x337a7cbf, - 0x6c0a879d, 0xdbcbed16, 0xd8dcb12a, 0x8a7fdbca, 0x31abae71, 0x82d02dbf, - 0x96daafef, 0x6fdbe6ef, 0x114fd76e, 0x3ca7ddeb, 0x6bb506f7, 0x3f6eede3, - 0xe4604e6c, 0xfaf6e027, 0x29ceb164, 0xd33af8bb, 0x867ebe3e, 0x4563e80b, - 0xb9ec9f9f, 0x6575744f, 0xece2ef24, 0xb695cbb3, 0x474e7c1c, 0xbc47a639, - 0x43f55bbb, 0x37741c78, 0x3675710c, 0xf8c8d3f7, 0x5429e621, 0x5717d847, - 0x443b7367, 0x614f4bd6, 0xfd8d7e74, 0x72fe4ecc, 0x3e0cdf19, 0x07d414c4, - 0x976146b8, 0x4e778cc4, 0xbb22682f, 0x1960fa62, 0x4ba90ce7, 0x4bc2dc61, - 0xe58b4f9f, 0xe6cb2a47, 0x9129f3f6, 0xd7df2177, 0x4875f204, 0x4890fb17, - 0x90f0fce8, 0xdb9ed077, 0xe734cc97, 0xf3e5f6dc, 0xbcecd4f2, 0x01cd6e7f, - 0x549aeaf8, 0xe58bf7bc, 0xf2b79429, 0x4c161e83, 0xff381c4a, 0x1a0b2ae9, - 0xcf8a0f29, 0x518b657f, 0xe5c257dc, 0x3f813cda, 0xd1186936, 0xa7815cef, - 0x17a16cea, 0xca31598b, 0x6f0279a9, 0x1937343f, 0x336ebeb8, 0x798fc944, - 0x1e3f28d9, 0x6bcf6b8e, 0x97c947bf, 0x4aee311a, 0x62afc761, 0xfd3fe47d, - 0xa7f1d844, 0xfc76e61e, 0xfe41d66a, 0x719fded3, 0x961ebe3b, 0xed12f487, - 0xabddad07, 0x6877d72d, 0xdea00dcb, 0xaec6ffb1, 0x8633b928, 0x1f7ba5fb, - 0x3f432fae, 0x77cecd64, 0x235dffc8, 0x2b404ce5, 0xe740c067, 0x51a1e672, - 0xd6fabfe4, 0xd819e3f2, 0xf26995d5, 0x76c9ef4b, 0x5e77f846, 0x0d2e79e4, - 0x7a11fb8c, 0xc16f23ed, 0xd28b2c7d, 0xa572d14f, 0xe915c850, 0x5bf290ff, - 0xc6429bca, 0x77ec14f5, 0x9b60f1df, 0xe1ef3b28, 0xc4afa16c, 0x4dfa4dfe, - 0x88547da4, 0xd7d211f6, 0xba2226a8, 0xbf727eb0, 0xe847d26d, 0x662505a5, - 0x19917bc4, 0xa6e11bf8, 0xd9f58db7, 0x68f1f434, 0x83f7e5f6, 0xf451efda, - 0x0b63f723, 0x84dcfd05, 0xff181891, 0xb81f720f, 0x5ccfd38a, 0xf4843de6, - 0x9cd5fbf3, 0xf0bee47e, 0x3d03ef9b, 0xa07dc8fa, 0xdd7e4fdc, 0xdd3f60fd, - 0x863ec058, 0xe95cb1e7, 0xfdf1e017, 0x45d38546, 0x3ddf9cfd, 0xf2c2c556, - 0x733368e2, 0xb97086ab, 0x8cc9a665, 0x0316977e, 0x99cd2fdf, 0xd2d97ef5, - 0xb413f908, 0xb8401f97, 0xf9276eb1, 0xdaadeb77, 0x3d2b3671, 0xf711fd77, - 0xc95a8f55, 0x08e174af, 0xc2e59323, 0x0f9411ae, 0xc78199fe, 0x6e7ce55b, - 0xb5f7bc3f, 0xb95bd410, 0xcc6296ee, 0x0255a82f, 0xb7c1d62f, 0x77beac0f, - 0x756bbf91, 0x672f7141, 0xe427c50f, 0xbafdf1b8, 0xc6c7927e, 0xf73f5c03, - 0xdf940929, 0x4787ef0b, 0x38fee9c6, 0xdcefcb88, 0xb807df4c, 0x5b47a91e, - 0xf827f3fa, 0x1b30b413, 0xa7ce1294, 0x704de708, 0x985fcb7f, 0x13798ae7, - 0x04e2231b, 0xbe663ed0, 0xcf2179db, 0x01726147, 0xba6567cc, 0x7fd717a7, - 0x4f85c44a, 0xa9e23889, 0xfc571e44, 0xfe7d7f7b, 0x7ae20db4, 0x3b8894e8, - 0xc6d14a9e, 0x44bd649b, 0x6cd93cf1, 0x60346ef6, 0x37799ebc, 0x3d70fe82, - 0x7ca26a64, 0x5f1c4595, 0x6b252fbd, 0x1ac811ee, 0x106a3e54, 0xd399fbb4, - 0xe3041fab, 0x9ed36f2c, 0xf715ea83, 0xba0af6db, 0xa7f0b5e9, 0x506b371c, - 0xd76c28f5, 0xb3df80bb, 0x289e5fda, 0xbfea5ecb, 0xc910baf7, 0x8ff2fea3, - 0x3a9ce242, 0xf8c893f7, 0x61f8bc40, 0xfa30bc74, 0xbc74699c, 0x37e4b17f, - 0x245fef11, 0x6ee2d4e4, 0xd5b86f1e, 0x820f36cc, 0x6775b7ef, 0x26b8fc50, - 0x135c3fd1, 0xbf5bf7ef, 0xa4879e51, 0x9edcdecf, 0xcff8f8fe, 0xf5e3e222, - 0x2f5a3e22, 0x5da9d7d7, 0xcf0164df, 0x3e3e31ef, 0x60739079, 0x9f3a3c7c, - 0x33b445e2, 0xac3c610c, 0x55b87071, 0xd12aebe9, 0x39617c4f, 0x35f73ca3, - 0x416b2d6f, 0x2d9af23f, 0x615596e2, 0x380bd777, 0xd3975bc7, 0x8d2e63ab, - 0xb9813ebf, 0xe593d622, 0xc994d14b, 0x33c88f92, 0xad93541d, 0x34db9f69, - 0xf07f5344, 0xef9a51ba, 0x4d22fef9, 0x1af5a0b9, 0x6d61fd4d, 0x88f29a15, - 0xea6bd79d, 0x4921b217, 0xa23b6fe4, 0xbb125f47, 0xf347302a, 0x85def47d, - 0xb29ff69a, 0xa0931da6, 0x7b45a75e, 0x7bf3332f, 0x8594c67a, 0x76c7a9f3, - 0xc3f4d52c, 0x29504a82, 0xf633df0b, 0x79a7b899, 0x878f0f79, 0x5ab5dd5c, - 0xbead4e33, 0x1d18f08e, 0x7d622def, 0x086e37e4, 0x1b20ee28, 0xd55dff18, - 0xaeed4ed5, 0x78c8f764, 0x2241c6c8, 0xb2cd97de, 0xd3475d39, 0xc3ec8d85, - 0xe4f4bb0b, 0xc3642c7f, 0xf0449a1f, 0x6b80b032, 0x302efe20, 0xf0bb17ee, - 0x798ddd8c, 0xb5bfb745, 0xca63e68c, 0xde05d2d4, 0x5eb9181f, 0x5d2d48eb, - 0x3a5addd8, 0xa5a09a48, 0x27786883, 0xc174b47b, 0xcbbff042, 0x86753bc0, - 0xb7fe6e96, 0xf081dce0, 0x5be186b5, 0x62d3d07c, 0xbcf1b823, 0x999f6935, - 0x1d143d84, 0x4e7690d7, 0xbbb09070, 0x2e323f45, 0x93f159b1, 0x771fd55d, - 0x0bcc109c, 0xd53da3e6, 0xc95fb8c4, 0x6fe5107b, 0xbd24bf0c, 0x9497e78f, - 0xc09b9d70, 0xf32d67f5, 0x663efc92, 0x93a4fee1, 0x9fc8abd5, 0x913592b4, - 0x9cd9fddd, 0xe8efc2e9, 0xca577aa7, 0x9f901853, 0x8b29f600, 0x06aed7f0, - 0x1fef1a8b, 0xd2a7868a, 0x78ed04ad, 0x4b75986e, 0xfca3e07d, 0xedde0f15, - 0x68ff89a9, 0x51e65fed, 0xb497e522, 0x1278e587, 0xc9ae529e, 0x49ac4c71, - 0x117c899f, 0xc8d8e725, 0xd693f8e8, 0x41fd239f, 0xe3238e32, 0x9bfed14c, - 0x55b8bb08, 0xc1d2718f, 0xce782df9, 0x21e1d8b7, 0xeb29613f, 0x4fdf05b9, - 0xa8b47730, 0xb8bfe12e, 0x2ffbf58a, 0x2babeae2, 0xf26fb5c4, 0xf247a12b, - 0x65b3c607, 0xff961c7c, 0xf1a11ff1, 0x8b95c524, 0xf2f398f3, 0xd3d22708, - 0xfba6bf40, 0x8fd02bf8, 0x8a97d75e, 0x3130aaf5, 0xfdde223d, 0xf5a212a6, - 0x367990fc, 0x6fdb9e45, 0x6ed31d60, 0xe8327f21, 0xa727bc49, 0x58bbfb93, - 0xac3db457, 0x0759bf92, 0xafba412b, 0xde711165, 0x2a77f0fc, 0x659607eb, - 0xec95d21e, 0x82f1a789, 0xe0a3ca72, 0xc84c53f9, 0x8cffb941, 0xf993cfb7, - 0x4f7ef218, 0x94547799, 0x1c75f823, 0x03fd871b, 0x94e595bf, 0xf8017fa2, - 0xc7e48953, 0xfa253cfe, 0xa31f803e, 0x31f32fd6, 0xf212f6f4, 0x5c8b2d1b, - 0x8780d7ef, 0x9c7e5bb4, 0xc8e9e8c3, 0x3eb3d171, 0x3d6fc4e1, 0x47a4b9f8, - 0x68da3f93, 0xfa0d0d84, 0x79145e13, 0xbb5a1d81, 0x9d1c96fd, 0xf7df1b80, - 0xf15e095c, 0xf8f221f1, 0xaebe3e04, 0xf8f3261d, 0x0c971c24, 0x0d0afb84, - 0x8ff7fb5c, 0x115f70fd, 0x2e12ee0b, 0x7e7b4ae7, 0xdbd2f881, 0xbc23a58f, - 0x577aa617, 0xe3dcfd63, 0x5d144fa1, 0xfa555e78, 0x7b8794b3, 0xe74f4ba1, - 0xe3ae1aff, 0x25e1b072, 0xf386893d, 0xb38a26dd, 0x41bd74d6, 0x66d9e176, - 0xfc06b410, 0x72180cbd, 0x08fc65d8, 0xb78ef051, 0xd9eb924f, 0xe5f62390, - 0xef32fd62, 0x39b9d607, 0x475e6627, 0xdfb41c3f, 0xf4aa1c05, 0x1cf09263, - 0x92be7f59, 0x791797da, 0x3af45f5f, 0xfe78722a, 0xf7b329db, 0xc3efec3e, - 0xd81d9c9e, 0xfbbe955f, 0x67c23670, 0xbbe742ad, 0x79f898a6, 0x5e712cdc, - 0xc9a8426f, 0x3399e78d, 0x667df873, 0xf7a47e23, 0xfdf91c62, 0xe0a677b5, - 0xffd93439, 0xe7474508, 0xee7b1947, 0xc12c7f83, 0x3722e6f8, 0xd8bf6fde, - 0xba2fee24, 0x002c1acb, 0x91baf239, 0x186547df, 0x66e744d2, 0xe4f592fa, - 0xb3d34cd7, 0x727748a9, 0xadbcf2de, 0x01f78f7c, 0x7cb15e60, 0xafa5a53f, - 0x7bfa0d78, 0x75c83d04, 0x2beca94f, 0xe185b26e, 0xa33cf32f, 0xf82553e1, - 0x1b43ee43, 0xd05b5ef0, 0xbccde7bf, 0x6daf7d1c, 0x5874feff, 0xf6363dff, - 0x837eb8c8, 0x1e3493c5, 0x6bdc51f9, 0x278717fb, 0xa477df89, 0xbcf6a7bd, - 0xbf97b7c8, 0xdeef1253, 0x51ccff9b, 0x827b97be, 0xcb85e5e2, 0x7078ffbc, - 0x99564869, 0x739d357a, 0xdeae5ef7, 0x8fadff2b, 0x28bedfb9, 0xd3dff7be, - 0xbcec6af9, 0xceb15ec5, 0x88617e70, 0xe7f729ce, 0x7e54be2d, 0x1a477bd9, - 0x08d23ef0, 0xf6bcc838, 0xb48fbc06, 0xd0bf4638, 0xe576cb9f, 0xc4aa877b, - 0x8f301abc, 0x3df23530, 0x38f0b7a7, 0x302f2269, 0xfb7c8894, 0x9d3d2ecb, - 0x11e5ffe3, 0x31dd8cdd, 0xcb9b9de6, 0xa9ca32e1, 0x0e8d1f12, 0xe3b5fbf2, - 0x79e793d5, 0xe8d8b9e4, 0x845675f9, 0x63f9c56e, 0xf1ac729e, 0x3f7cb91c, - 0x99dde72b, 0xf0d1f1c2, 0x9bdf899a, 0xf27cf2aa, 0x4ad094ce, 0x168713e2, - 0x1e04c3cf, 0xe50faf3b, 0x99b2b9d1, 0x8f10efdc, 0xfaa7261e, 0xc8be51ca, - 0xd4caee7b, 0xc111c526, 0x87a2578f, 0x1af5dc30, 0xbb840ebc, 0x7ecbbe91, - 0x7c151f4f, 0xdc363ccb, 0xfa112dcf, 0x5a9ec96e, 0x7ee587b2, 0x3d4ef4e9, - 0x669c6fe5, 0xba72ae3c, 0xd0fda14d, 0xeb631f52, 0x7cad2e40, 0xaa3378a2, - 0xb09925ae, 0x1efe1496, 0xe9661f7f, 0xbaf8a8c6, 0xbd495fd8, 0xbe5fc72a, - 0xd7176b4d, 0x467f6db0, 0x51f4e9fb, 0xb0563f2e, 0x2b3fd226, 0x57f6d01f, - 0xa7d667b3, 0xbce8cf38, 0x8fc21180, 0xec572d37, 0x1958ca57, 0x4f358fea, - 0x9fc46e7c, 0x17c78960, 0x434ffbf8, 0x7ddff187, 0x8efe27c2, 0xc96f3e08, - 0x1720fcf5, 0xf2ef3efd, 0xf5ceaef9, 0x7f45c9cd, 0x7e7cbbc9, 0x702eea17, - 0x8d2bb33d, 0xfd8b5bf4, 0xfaff922e, 0xdffe5cc1, 0x0035f78b, 0x71264c9c, - 0x49aeba6f, 0x4df6489f, 0x43ece880, 0x7e731de7, 0x26776540, 0xd3da43f2, - 0xbf6067d3, 0x1eada7ce, 0x72d6df5c, 0x2ffa214f, 0xf3f356b6, 0x8f1366a1, - 0x397e07df, 0x538600f1, 0xaf6c7686, 0xa39d1740, 0xfd107f7b, 0x3fbaad42, - 0x98bcc61f, 0x5f3cc9d6, 0xda175d32, 0x3c62283f, 0x899035a7, 0x68e77df1, - 0x9a4e6f7e, 0xcb90bcbe, 0x36276e7f, 0xe85c5c08, 0x627f202a, 0x17fa41af, - 0x2e742c3b, 0x2eff8eab, 0xf1c628c6, 0x70eaf32f, 0xf176910e, 0xf9a666d9, - 0x1d51869d, 0x4890d04a, 0x3c50a8f7, 0x30436ea8, 0x67d416fd, 0x4f14a94f, - 0x7b4bf393, 0xe302ab3d, 0xdd8f5266, 0xbfb838a2, 0x0bfdd84d, 0x71e3fc98, - 0x9e82f9b7, 0xff7b0816, 0xf7872b16, 0xc3cee652, 0x2ccd0b76, 0x76ac0751, - 0x2947654b, 0x90d6b3ad, 0x8c85768c, 0x47b7c51f, 0x1ac9fb62, 0xe7e7617e, - 0xe1be959e, 0xf419c9d8, 0x3f865d41, 0x693c85db, 0xffcfce18, 0x83cca1b1, - 0xd786caf1, 0x30efd046, 0x3c781299, 0x1996e41c, 0x843a11ef, 0xbdd61efa, - 0xc88b15ea, 0x73880a5b, 0xd8defccd, 0x453939c6, 0x78f11e74, 0x71ffdd1f, - 0x23ca10de, 0x847906fe, 0x92bea637, 0xe01fbbfb, 0xd90debbd, 0xf941d760, - 0x789fee74, 0x25684879, 0x92991bde, 0x47978977, 0x72c13e85, 0x6cc25e4e, - 0x5685172a, 0x3e3ca1ea, 0x7197932f, 0x36040a03, 0x6cf06f35, 0xc92dda3f, - 0x87702ec2, 0xc377bce8, 0x917423cb, 0x1e7758fe, 0x84676797, 0x3e4cf93f, - 0xc20e6dbb, 0xfaec647b, 0xded27969, 0xc9f5a36e, 0x2cf6caf5, 0xffbb7633, - 0x957e7210, 0xc53da738, 0x3c2d5aca, 0x044fe7fe, 0x1eec1c3c, 0x7fcbf141, - 0xfde14dcd, 0x4f74423b, 0xfa27ec8f, 0xb8e41c77, 0x7bfe15ab, 0xf2a3e759, - 0xcb977ebc, 0xb38c2be5, 0xea19c691, 0xe79be7e1, 0xfe2214e4, 0xc0aa6f00, - 0xc9f7ca9b, 0xd07e7ced, 0x13fefe2f, 0xf46287e8, 0x0afc1ffb, 0xe787e7ea, - 0x27274d1d, 0x5aab38c5, 0x2fb6dc78, 0x69e880b9, 0xf7dc558a, 0xc75da252, - 0x9f6e3cf8, 0xc592f3ba, 0xaf091d79, 0x69c6850c, 0x09cc7011, 0xf6339f0d, - 0xaffbaf9b, 0x8eeb4bff, 0xef0797c0, 0xc5d8396d, 0x9f1e37ef, 0xf485f1c7, - 0xe076429c, 0x677f4d76, 0x9fb547d6, 0xae5f28c0, 0xda80a521, 0x6fee2bdf, - 0x61d9f795, 0xdc71fcbb, 0x57bb45be, 0xfcc1a7de, 0x1c645993, 0x8cdeffb2, - 0x70bf710e, 0x286f3aff, 0x8874eb11, 0xef223a75, 0xcfe7ec33, 0x73797d63, - 0xb8e903ed, 0xfdfdfe1f, 0xfd12298d, 0x563cf869, 0xf1d7c87f, 0x1e5572f0, - 0x1bdf2797, 0xa33ce45e, 0xe70fd9e0, 0x7849f9a8, 0xbb537f22, 0x94ba5a31, - 0xf411ccf3, 0xf3bf8039, 0xe278e5bf, 0xbbfad97e, 0x7338be79, 0xbebae969, - 0xf9875f33, 0x07ddb209, 0x34a0c078, 0x21bc27ec, 0x7327ec4f, 0xbc9c4e58, - 0x339e6f47, 0xde917fa6, 0x7b27ef47, 0xd9efe593, 0xbd1afd69, 0x397bfe4e, - 0x7efc73fe, 0xfca36b83, 0x7a8f183c, 0x176e16ce, 0xf2da2fd6, 0x037e0263, - 0x797d54fd, 0x5312bf38, 0x3bf8f3c5, 0x4af3ab5b, 0x7760ab67, 0xdc552494, - 0xa6e50f99, 0xfc93c6c7, 0xf154192e, 0xf3c83e79, 0xe04d8f35, 0x7c5747df, - 0x79cb043e, 0x8a797913, 0xf79479e7, 0x9eccb460, 0x2bb6159a, 0xd173ccee, - 0x1d4afab8, 0x42676bdd, 0x63d60623, 0xf944dd7a, 0xf1ae1280, 0x5d26259e, - 0xbff3ac53, 0x03d3f4f7, 0xc04cbf8f, 0x1fd0ba7f, 0x2105fc28, 0xe82fe355, - 0xcfe7e44d, 0x92fd5f7b, 0x9bdcd7ce, 0x079f5be7, 0x67ad1bed, 0xf287cd6f, - 0x1407eb06, 0x603c53ef, 0xc61fa087, 0x608b60e5, 0xadd9cabe, 0xd89fb45e, - 0x2559b76a, 0x18ff0ab8, 0xf007a9de, 0xa7b5e57b, 0x0f883c7e, 0x4c79c5e3, - 0xf1a07214, 0x15fdbfb5, 0x678dc4e3, 0x1b346e6c, 0x7c3f7627, 0x135fda27, - 0x1bfedfbb, 0x3cfcc3d7, 0x44f79c90, 0xfbc27ff4, 0x9a265d09, 0xabeec4ff, - 0x6bfd6056, 0x402eebdf, 0x44eeb93a, 0x42c505b0, 0x3effabef, 0x880e7348, - 0x7cd97a7d, 0x39f1b8d1, 0x013f8f09, 0x1e0893a0, 0xf8f0e73f, 0xced9f28a, - 0x0e6e8f3b, 0x7b549391, 0x78ec0ade, 0x605f3b8a, 0x7b8c6e09, 0xd1fd73c8, - 0xd5e3d57e, 0x7f783eb0, 0x20cc1f5d, 0x729e9ec2, 0x24820cd1, 0xc9672e5c, - 0x39a5729a, 0xcabf534b, 0x3ef9af91, 0xcd2af33d, 0x42ae99f7, 0xc8d6794d, - 0x37fa9a89, 0xe535cbba, 0x6a6613d9, 0xaa7b57ea, 0x60c2e535, 0xf17ea687, - 0xf7ed2e91, 0x788f4c63, 0x7eee3a28, 0x27a59f03, 0x2d9ee43d, 0x06f4d53b, - 0x85fe273e, 0xafda2383, 0x8ec5cd7c, 0xf4bdf037, 0x9f9f472b, 0x9be67e92, - 0x3180b6f5, 0x53393fb6, 0x83df082d, 0xf3f1d7a0, 0xfb25ef53, 0x937880fe, - 0xa0a6a7e7, 0x5090195f, 0x9fb9db75, 0x5c32efe2, 0x6efdc458, 0x943111c7, - 0x7f276e4f, 0xd34371e5, 0x79e47fb3, 0xf728b903, 0xaf9bebae, 0x8b94f759, - 0xcbbacd3e, 0x3c28aad9, 0x5729a1dd, 0xd4d6ee39, 0x5eb99e9f, 0x6ba67df3, - 0xb69e144b, 0xba37ca6b, 0x53c28e1f, 0x9e9e147b, 0xf4977cd2, 0x5ffc2ddd, - 0x0adfa1af, 0x3d42939e, 0xc9878895, 0x1f08faa7, 0x2ada7a13, 0x1cd74f11, - 0x957c20ef, 0x2895bd04, 0x348ecb2e, 0x20cf81bd, 0xddb0cbec, 0x7a4ce681, - 0x91766c1e, 0xf370ebff, 0x691e7a48, 0xfffbd376, 0xcf409e68, 0xe87b355f, - 0x33cd9ff9, 0xecd3d9e8, 0x734767a5, 0xae7fd507, 0xcffb8bb9, 0xddeffb52, - 0xc1bf45c8, 0x01a85d79, 0xc18ec623, 0x9e9e495b, 0xc79d084f, 0xeb7f06f2, - 0x3420a9ec, 0x901d67f0, 0x9e207f2f, 0xfb4f2e45, 0x1e0e7860, 0x19fdf8cc, - 0x43a37f22, 0x3b4429e7, 0x0fe3f47c, 0x32e6a7de, 0x37bd69b6, 0x183a7f13, - 0x132866cb, 0x90f7e9b2, 0x93cfbc1e, 0xa8b3d8c3, 0xf7bee84a, 0xb9636707, - 0xe79efc57, 0x241fc7e0, 0xc75bfc3b, 0xe2033dd9, 0xc707a3ec, 0x7b3fb388, - 0x7f4765ca, 0x46afd1cf, 0x471e11d8, 0xc3cbdf85, 0x3bf80d0a, 0xa16ae51c, - 0xf1ecf501, 0x5421e738, 0xe0c97953, 0x7bb75c52, 0x5f91e51e, 0xe1dfa06f, - 0xfdf0a39b, 0xec97acaf, 0xf7a0fae2, 0xa7ed1346, 0x2b3ce98e, 0x957a3f90, - 0xce10c7be, 0x14fe3d37, 0x7b5ea9e9, 0xafc21e5f, 0xbcbdf1fa, 0x4c7becec, - 0x0d944771, 0x8f953e1c, 0x6fdb393f, 0x33e15efb, 0x0d11d71b, 0x1d83b99f, - 0xf4115f7c, 0x201da2e4, 0x3daac7cb, 0x2c5714f5, 0x75c30cf7, 0x389af51c, - 0x81ed7aff, 0xf237e461, 0xf08bce94, 0x360cf4ff, 0xa2e7fad0, 0xe83f44de, - 0xd6207d42, 0x1f9e15ef, 0xa23dedcc, 0x2e67dc13, 0xe0bed2b0, 0xa3df8e98, - 0xeedf5d10, 0xcfa3fbe2, 0x9c87dce2, 0xdc57be28, 0x0becff54, 0x5aef5fd0, - 0xebdd750b, 0x58f6411d, 0x1740136f, 0x54f7ba68, 0xddfe39d3, 0xa12016e4, - 0xf82def38, 0x6cfef82f, 0xfc5f9df7, 0xb07fea06, 0x1d26ead6, 0xf04518e2, - 0x2f2a285b, 0xfd93354e, 0x6e4e78b4, 0x5bc5ea05, 0x56f0bc44, 0x614e9abb, - 0xe8d93543, 0xdb967e80, 0x0403370a, 0x6ab4cad9, 0x5364fe23, 0x9b1dce4d, - 0xe87ab9f1, 0x58f22376, 0x9b7d98dd, 0x07ad8cd1, 0xf9252e16, 0x19a77a17, - 0x3adb75e6, 0xe7ef8bbd, 0xdadaf9e4, 0x22f7946f, 0xc898f7e9, 0xd020024f, - 0xa5c9357e, 0x4949f668, 0x181f4e82, 0x6331e22c, 0xda4bd8d9, 0xe44ed778, - 0xdf8bb3a3, 0x1e271e19, 0xec2efda1, 0x7b8adfc7, 0x4fefa39e, 0x5c3ae391, - 0xcc75ff7c, 0xf6899408, 0x07ae42e4, 0x7cffcdc6, 0x7fac2943, 0x4743b75c, - 0xd5b70d79, 0xb87880bf, 0x68f025d0, 0x4fc85d60, 0x7c97f937, 0x4c421bf0, - 0xf0dce69a, 0xbba5f495, 0xa91951c7, 0xde424b2f, 0x397d48ca, 0x12adafa1, - 0x8fd4a2f5, 0x211ae6c1, 0x8e489b8f, 0x475e6c1e, 0x7ecdc3e5, 0x6e691e7a, - 0x8db8f215, 0x79aaffbe, 0x01c790a7, 0xd2f78f21, 0xf9e6eefb, 0xd9ad7cf4, - 0xa985cf47, 0x6e11d7be, 0xd73b8e32, 0xdcbca3ec, 0x189b0f43, 0x742ef1c6, - 0x038f289b, 0x47b1e238, 0xc94f30d2, 0xa344e744, 0xe5a295f3, 0x743d3f7c, - 0xe5b7b80e, 0xfef7e46d, 0x17b4233c, 0xa7a7c707, 0x4765cca3, 0xe0f1f4b9, - 0x8e8724f3, 0xb4765cba, 0x2e3e4fa7, 0xdd971eca, 0x0d3fe500, 0x71fd25ee, - 0x9bb2e7d4, 0xe3c9fca0, 0xdfbbfcbd, 0xf940b765, 0xfc7dc1d3, 0xd051807b, - 0x2fe0ecff, 0x33958e48, 0x47f220e5, 0x2a7f39a5, 0xd7d00ba8, 0x2f9107e5, - 0x992e67a6, 0x60b17c8a, 0x72e88bb0, 0x41fd6ba6, 0xd91acf2c, 0x1515e2ae, - 0x46e15b1e, 0x5691576c, 0xa9bb62ad, 0xc46c7739, 0x6e86d376, 0xcddb2357, - 0x236fb318, 0xb7706f96, 0x2e9f68ab, 0x1a563940, 0xe59647ee, 0x65a72977, - 0xddd5dd3e, 0xe307d25e, 0x0fa4bcba, 0xe62a5c24, 0xff426f56, 0xe2976367, - 0xa9a5dfc0, 0x27f4ab98, 0x62ee6033, 0x0a93de03, 0x3dfffaf2, 0x87ac77ae, - 0xf9623675, 0xadb72a1a, 0xedfa06ff, 0xe2f6007f, 0x8000e831, 0x00008000, - 0x00088b1f, 0x00000000, 0x3cd5ff00, 0xe5547809, 0x9dcee7b5, 0x4c92642d, - 0xe2420836, 0x96249964, 0x26b6432c, 0x0c486410, 0xf90130ee, 0x10196544, - 0x044816c2, 0x7eab17eb, 0xe0171a19, 0xd16b8d69, 0xb5c46faa, 0x61e4b6af, - 0x1d0958d4, 0x87d252aa, 0xb410553a, 0x88a47479, 0x119099f0, 0xc7d278dc, - 0xf7fce73b, 0x24cee666, 0xbefd1480, 0xff938607, 0xcfd9fbfe, 0x005ffff9, - 0xb3f85380, 0x34607f02, 0x3d2538fe, 0x0468048c, 0xd1bf67f1, 0x0395b26d, - 0x8c0734ac, 0x412fa3a0, 0x6010aba3, 0x76960eaf, 0x24a40014, 0x0b7afcc3, - 0x74b08d96, 0x5de7960b, 0x05480368, 0x20bada68, 0xda85816e, 0x6066e3bb, - 0xe21745fb, 0x52ce38af, 0xe0546e05, 0x9bd40a93, 0x4f34899c, 0x1fd24d9a, - 0x856fc7ca, 0x064a7850, 0x3d9ab7e8, 0x448004ba, 0x0dac7b93, 0xfb9bedc7, - 0x8758834e, 0x31d688af, 0xeb1ebd6c, 0x6c3200e3, 0xca1f1e56, 0x5e541982, - 0xc846ed09, 0xcff5b846, 0xda22a4fb, 0x2327c597, 0x5f434e84, 0xf9ec5f20, - 0x63fe1654, 0xe0543d06, 0x6e03e97a, 0x70d79969, 0xea566020, 0x743967f1, - 0x226670ec, 0x7ed45ede, 0x18bf046f, 0x7dfb43bf, 0xbe8de215, 0xbf697537, - 0x0f5b5403, 0x0230438d, 0xd9dfb8cb, 0x855efe12, 0x878f0dff, 0xc3c06749, - 0x10f0a1a4, 0x1af01fb5, 0xd7de8e41, 0xa66ecb0a, 0xc0bee473, 0xd1fcca9d, - 0xf7218108, 0xf445f2a7, 0xfe05dafe, 0x25ff02f5, 0x5a74e736, 0x38fcdd5f, - 0x8e005390, 0x4d79356d, 0xa9ffdc99, 0x1744293d, 0x2d837593, 0x5b5b3e9a, - 0x00de8367, 0xcdd5adb0, 0x14bad7d0, 0x3f8076f4, 0xf97336b5, 0x2e16d6ad, - 0x30f568ef, 0x8ebad9dc, 0xdb5a5fe1, 0xeb577eb9, 0xdbbf2e46, 0x6fe865ea, - 0x5fbf917d, 0x86657f3b, 0xff4d12db, 0x45cec9d5, 0x7b9e8fc4, 0x3e9913aa, - 0xc853f7b8, 0xc81a9eab, 0xc344b66f, 0x9d658301, 0x8f65c094, 0xd9e1f711, - 0xc36de316, 0x8c73fd7d, 0x19c689bb, 0xad7e09a8, 0x4a437c43, 0x30d0f180, - 0xbe9abdd2, 0x3a1c464b, 0xe4f56689, 0xeb0efe12, 0x6407bf3c, 0xd39b56d9, - 0x383e47a5, 0x17558f1a, 0x6582dc00, 0x78f3ce0f, 0xfa85abaa, 0x48c07e41, - 0x3fa29ce3, 0x097c7193, 0x3af07766, 0x0e1ca210, 0xb1e808c4, 0xd18f2c49, - 0x40ddc850, 0x60f99fba, 0x1913e9e0, 0xcb3382b6, 0xa8f870c5, 0x9e03ab93, - 0x6567a432, 0xd584c3ac, 0xa4f8127d, 0x46538412, 0xd38e00d6, 0x13d46e97, - 0x5644149c, 0x9fc3c750, 0x6322dfc9, 0x14cbf186, 0x6b94d448, 0xed35a3cd, - 0x9a99aceb, 0x5cf4befa, 0xb4d2ff1e, 0xfaed348b, 0xc59a5746, 0x232f53bc, - 0x6f7465d8, 0x0974805c, 0x9b1c9956, 0x98bdfeb0, 0x062822f8, 0xbf1b1698, - 0x317be089, 0x376a5e19, 0x14c9c0ed, 0x934e7dc0, 0x108b237d, 0xc6db9755, - 0x99edc76b, 0x76c36353, 0x6957e657, 0x25c121d7, 0x1dabdfb4, 0xa7df3453, - 0xe9ae5e57, 0x93fb32ef, 0xcef5ad08, 0xc6f7cd7a, 0x9f41af96, 0xe5b1300c, - 0x014be824, 0x343afbc6, 0xecee94e3, 0xbf1fb4d2, 0xeb12641b, 0x378e7d92, - 0x741f9609, 0x152ac4ca, 0x24df9b87, 0x3fa5f558, 0x4e01f683, 0x9f5159b0, - 0x83dc8a4b, 0x963d0247, 0xcae52927, 0x812db7a0, 0xf21270e8, 0x89bf48f5, - 0x6321c230, 0xbff2a963, 0x4c1f104e, 0x32002052, 0x16abf607, 0x3a79804b, - 0x4598d78b, 0x1be5056a, 0xc906c1f5, 0x3847a691, 0x50540e47, 0x8a0428f9, - 0x973aca08, 0x2a6bf89e, 0xb2a58f34, 0x0469dc09, 0xbf74483f, 0x2fdc7c4f, - 0xe2c4da05, 0xcfc4c982, 0x68ff3f75, 0x17ac6dde, 0x5c261c62, 0xfebaefdf, - 0xfd6b4a91, 0x91f53fbb, 0x7e216c37, 0xcd7eb26f, 0x8dcb5278, 0x7f19c72d, - 0x2d6fb96a, 0x92e177cc, 0x9f680ddb, 0xaffe3610, 0xed0a76cc, 0x53a23ada, - 0xb8c9fc23, 0x1ed420ba, 0xc418be3a, 0xbfea3177, 0x04d35a7a, 0x5ddfd7c2, - 0x6f576c4e, 0x9e087210, 0x1c4ef545, 0x29463ea7, 0xa7d44f83, 0xb2a1ed2a, - 0x6ae9cb9e, 0x6f68957d, 0x587bc757, 0x96ad1fb4, 0x522ef195, 0x9ca2cdcb, - 0xa0f7cea9, 0xe5aa1728, 0x397170ff, 0x613fb44e, 0x29ef559b, 0x53ffe908, - 0x0f18ddaa, 0xa06ec9e3, 0xc933903d, 0x1abb481e, 0xeda21f98, 0xb15eb685, - 0x237ff317, 0x44c58c7b, 0xdf63cb8f, 0x90eeb921, 0xf1bae480, 0x8bd38376, - 0xd49e7ff3, 0x12c6b451, 0xb7e7dfc2, 0x6abb7c08, 0xb6329ce3, 0xde6af95f, - 0x3923e226, 0x85c8f76e, 0x563addf8, 0x4ea77ac7, 0xe88138b6, 0xfbd0af7b, - 0xd848ff6a, 0x8686f2d0, 0xb2f5519e, 0x6cc1f3c4, 0xfaf9c1fc, 0xf4f51bef, - 0x8e59c206, 0x9370973f, 0xdcf42999, 0x95add448, 0xea36f3f8, 0x3dd23359, - 0x3a9c1b25, 0x1af29f6c, 0xf1a267ea, 0xc7d0bf41, 0x24f8c5af, 0x8f959c14, - 0x6ff6c9bd, 0x8e528ca1, 0xcf2d7bf8, 0x7c89979d, 0x9fce347a, 0xd0db7c4b, - 0x75d78db2, 0xe3cadd8d, 0x10583583, 0xcce2cf8e, 0x9e97fc28, 0x3fa5ff01, - 0x8271fe26, 0x75cfa403, 0xbeb47428, 0x78b796e5, 0xef95cbbf, 0x43325fac, - 0x472cb8ed, 0x39c68f97, 0x0e1f0832, 0x74074e85, 0x5f050ab6, 0xfabe1357, - 0x1373fb17, 0xf9f0ecb1, 0x3ed9ba47, 0x88972aec, 0x4071cdee, 0xf92a3f74, - 0x410ef68b, 0x0ed68eff, 0x5a5bcbb6, 0x84be18bb, 0x55bad073, 0x8d10dd7c, - 0xc067f9df, 0x131ffcef, 0x01f4a3bf, 0xadfb03a3, 0x4e3c07da, 0x1180ff85, - 0x2b4cf4c2, 0x27e225f1, 0xfae24ba1, 0x2120b93a, 0x138fa9a0, 0x738e52fe, - 0xcae9f13c, 0x37aabb19, 0x98792148, 0x311d0b1c, 0x0ed7cc49, 0xc41daf85, - 0x22ff2ad7, 0x11ea963f, 0xc49d6fcf, 0x37e0437e, 0xf3c0bfc4, 0x3bba78a8, - 0x881baf1a, 0xabc1a78e, 0xc607feb6, 0xc7fa276b, 0xaf8237a4, 0x653778c4, - 0x77f9e346, 0x7c555e0a, 0x7fe4536f, 0x236f3c38, 0x7f9ea73c, 0xb4cb6f3c, - 0xf891b8f1, 0x453ece1e, 0xf75d47d2, 0x7e5a7210, 0x2d3a722e, 0xdff8aadb, - 0x461677e8, 0xa26dfdd3, 0xf74359bb, 0x53c8339e, 0x4f298fcf, 0x848b7891, - 0x3ab8128d, 0x3fdfd12c, 0xdf561ccb, 0x4e3c179d, 0xf8d6ce0a, 0x75bf9367, - 0x29b3fc6b, 0xfd696118, 0xe5349bd8, 0x9aadeb3a, 0xada697f6, 0x6e5fd4d5, - 0xbfa9af5b, 0x4d01ff32, 0x63c76af9, 0xd3e67e11, 0xe77afa9a, 0x73f5346f, - 0xea6bb79b, 0x68f4b7e7, 0xfe7817ea, 0x78ab29aa, 0x1c0adadc, 0x356b6d2f, - 0x65d3f12b, 0xfe03ab0c, 0x8b83125a, 0xdfd9070f, 0xd7b7f4ac, 0xafb24bb2, - 0x32d1fd83, 0xc296ab9f, 0xcd9d8aaa, 0xb5f4126f, 0x2d78955a, 0xad5be18d, - 0x3befd636, 0xee19f35a, 0xf128756c, 0x5dc3255a, 0x4e254ead, 0xb48c3173, - 0xbb66af0b, 0x3d2164a7, 0x44bcbda6, 0xe980b807, 0xc167f87f, 0x77bc5a5e, - 0xdce28ebc, 0x8e5eca35, 0xffb37f57, 0xe3afe436, 0x950726cd, 0x311fb77b, - 0xf9a30ad8, 0x32b7ee65, 0x6cf8c338, 0x0d5fcb6e, 0x45cd67e4, 0x0863ba0f, - 0xa59a9d39, 0xf7207e63, 0xcc2f5003, 0x05218336, 0xd9ecc1f5, 0xf80da392, - 0x189207bb, 0x3f58dcfa, 0x133e0f4d, 0x7a2deb96, 0x979e299f, 0x3fa332e6, - 0x132c4b3d, 0x50f07a4c, 0x7324a43d, 0x7d0d7e9c, 0x383ca1b4, 0xbf18b865, - 0x1c3f22cf, 0xe96f5dfb, 0xbddd9030, 0xfa2fe76e, 0xb87ac36f, 0xf1ce53d3, - 0x25625c3d, 0x3e792dfd, 0x371a9dd6, 0x3520bcbc, 0x5f1850e1, 0x4e19254f, - 0xe1d1f8a5, 0x7adc5277, 0x9cf1c193, 0x05dfba2d, 0xc9a77eca, 0xc16ffb12, - 0x4dde4dd7, 0x713e4852, 0xb84d3b7f, 0x01e226cf, 0xc1b367da, 0x7e445797, - 0xb3f676f6, 0x16d72a9b, 0x2e9a9d11, 0x15313e91, 0xa69de285, 0x8fd92f96, - 0x91cfd48f, 0x90f14cf0, 0xfe656fc3, 0x93badfdb, 0x8b8d45f9, 0x5c7d5b7a, - 0x6ab80b2e, 0x39a3e3c3, 0xa64dff93, 0x4beaa7b8, 0x3c4cff11, 0x53fbdce9, - 0xd5a077dc, 0x17e52fff, 0x9a82bcd4, 0x5bcc8867, 0xde647aa8, 0x6e0975ad, - 0x2c9aefdc, 0x94f30651, 0x5ea3a674, 0xdedf5540, 0x9765159a, 0xbd3ac8ef, - 0xffd6d67e, 0x6cf9fac0, 0x4d31bff9, 0xbe48d5d8, 0x05e337df, 0xe553ad03, - 0x9ffe48ef, 0xfe707d43, 0xd7924d39, 0xf67a7a83, 0x44c37692, 0x7df9dce9, - 0x88a0e5b9, 0xc2ed238b, 0x3607b6f7, 0x2b5c9ba6, 0x92617c73, 0x1e50726f, - 0x4743a544, 0xcf3add34, 0x1fceb740, 0x76d16e93, 0x73bce0f1, 0xf1a08bb3, - 0x8acbdfcf, 0xc83e27f2, 0xa91fbd3a, 0xf781ffad, 0x636b1d6d, 0xef4472b8, - 0xea27593c, 0x01627c45, 0x80eff21d, 0x74b8e657, 0x3c7b6669, 0x195033c5, - 0xb77d278c, 0xf2065bac, 0xd4ef410f, 0x5cfe468f, 0x1f67f0a2, 0x7e243ef8, - 0x7ef7055c, 0x25980941, 0x22ae4bd5, 0x09f4b73d, 0xfc4f0843, 0x27f393af, - 0xcb7e94ab, 0xda469d2d, 0xb567f2ef, 0x1a71d4ed, 0x1fc88a5f, 0x19fa5f57, - 0x73f0ddb0, 0xa7556fde, 0x5977dfb6, 0x62872971, 0x084b1659, 0xa7d267ef, - 0x1baec947, 0x5b27cac2, 0x3f20bf39, 0x9e03e0f3, 0xc4fa21b1, 0x71f14764, - 0xf9e9f65c, 0x23ff5b58, 0xf71cb1f3, 0xf9e891ac, 0xbf78f97d, 0xeb4599dd, - 0xa0f3f556, 0xc4c379de, 0xdca0677a, 0x37a4f226, 0x9e2daefd, 0x3804e4f8, - 0x2a161d88, 0x6a85d2f9, 0x369d74be, 0xcfb93a5f, 0x49b979c7, 0x716dbd07, - 0xbd89f748, 0x55dbce1e, 0x59b776ed, 0x5dd3fcb0, 0xa3fc994e, 0x64b96ff1, - 0xdfeab75a, 0x484efea8, 0xbeb0e58f, 0xf66bbce3, 0xd53bebd9, 0x30f6aa2e, - 0x06560ed2, 0xfec96bdb, 0xe3b6f84d, 0x2be7824d, 0xf7691eaf, 0x7a138bde, - 0x57c1a8e2, 0x8cfc97be, 0xcf1c63d7, 0xaffaf441, 0xc67e16cb, 0x0302cf4c, - 0x1f091fcb, 0x450cdbca, 0x764fae6e, 0xf54d975f, 0x99d0bd8a, 0xa3b2069d, - 0x23df7275, 0xf95f12d7, 0xde1bce65, 0xbf07c77c, 0xccedb5ff, 0xeb2685f9, - 0x863ff671, 0x749a338b, 0xa2f8a6e0, 0x4a56d6a4, 0x6dc50c7e, 0xf3544794, - 0x9fed918a, 0xc8acd7b0, 0xb5573ce6, 0xd9eb49df, 0x1c33d628, 0xbe5a9abd, - 0x8731e4d0, 0xbba9bf9b, 0x4c30badc, 0x16ca5e3e, 0xdbd22ef1, 0xa21cc87a, - 0xc5f2d9f7, 0x65f8b7ff, 0x091e0c9a, 0xe4a16ced, 0x082ffe15, 0xf80e783f, - 0x2083ce19, 0xf9583743, 0x38216a7c, 0x17022e18, 0xdbbb7cc3, 0x60337c4b, - 0xbe248e08, 0xbbf57fea, 0xfe9be202, 0x57b6278b, 0x5f3bf9c1, 0x06fff48a, - 0xfe78dbc6, 0xdbbe5781, 0x7039fc43, 0xf4ace187, 0x6764eac6, 0xe451f127, - 0x53bbcb79, 0x01d73e64, 0x8b967afd, 0x03e8ab7a, 0x1b72a497, 0xe64cd8eb, - 0x1cde908b, 0x37aab4f5, 0xc2bf6017, 0xd7ac744f, 0xb5e49960, 0x80aed363, - 0x70ac458e, 0xa657a671, 0x2fa8a772, 0x95e8995c, 0x15585cb0, 0x4a6fea23, - 0xc52642f4, 0xcb960143, 0x0fac00f9, 0x8bd08017, 0xf7938237, 0x96419189, - 0x6f17fd84, 0x3e709735, 0xa4390216, 0x8e288bff, 0xb74e221a, 0x2f7908e6, - 0xbefa12ce, 0x179b46b8, 0xc95b30f9, 0x4a6bdb1b, 0xe7561072, 0x1d12f738, - 0x1bfc938b, 0x7ca32a1e, 0xa1360e90, 0x75567d7c, 0xaa779f2b, 0x35ed1afd, - 0xcdbf84bd, 0xe2bc7012, 0x9f7936e9, 0x238ce713, 0xf2cdcfc3, 0xa807b5ed, - 0x7b5a11dd, 0xc578f0f9, 0x47f71c7e, 0xd78795cb, 0x1bb14c57, 0x43f1fbe7, - 0xe5cbcf25, 0xebe679ff, 0xf80b3bfa, 0x7e43c14c, 0x7ddda372, 0x046fd79c, - 0x9ffad0b0, 0x40147114, 0x47e50673, 0xd2653c97, 0x11f19f91, 0x03c8639a, - 0xddc61bf8, 0xe31bff04, 0xc77f8267, 0x27e099f8, 0xfc133f18, 0x04cfc607, - 0x1e3b7f17, 0x8d802283, 0x4e4b4e39, 0x301ce879, 0x1c86bd72, 0xf9c1cf81, - 0x7f3c8dbb, 0xf8cddd9d, 0xebf7a41d, 0x9973a5e0, 0x0bc189cd, 0x6fc34e92, - 0xf0dfdd03, 0x7870e9f9, 0x2325cf51, 0xe853bfeb, 0x67a9d45a, 0x15d45ffb, - 0x6b086f88, 0x918e4177, 0x395f0beb, 0x1fe34f18, 0xd7e20eb5, 0xa796e129, - 0x82f944e9, 0x08332d67, 0x677675bf, 0xe51bed09, 0x51f6833c, 0x83c1f5d4, - 0x7c78cb13, 0x75a364ab, 0xb8e51f04, 0x911f6221, 0xb5f75078, 0x81bfd139, - 0x257e6ffa, 0x7a82768b, 0x10dc8407, 0xed43491f, 0xcff32d77, 0xccb05374, - 0x7e9deb8a, 0x0a1e6e4a, 0x29f675ff, 0x5477e78c, 0xc7cf537e, 0xe952fe15, - 0x1df2ae76, 0x6b901e39, 0x6ae77e84, 0xb236a5d2, 0xc9e3274b, 0xee57ac2f, - 0xe6757419, 0xf4fb47bc, 0x6ec194ec, 0xc8d63e63, 0x5f8562df, 0x6dd85854, - 0x36bd1174, 0x59ca1f77, 0xe4fa6164, 0xb3f6c62c, 0xbc9aec72, 0x89d56167, - 0xe14a1fc7, 0xea9a56f6, 0xceba783a, 0x60dfe38a, 0x6d36fede, 0x93f5ae69, - 0xcf2c44ba, 0x1076934f, 0x9ccb605c, 0xe5a3649a, 0x37fd797a, 0x41d94fe6, - 0xa3957522, 0x29b9fd9e, 0xecc264a4, 0x9639ad43, 0xcb071f0e, 0x4d64d675, - 0x31b4d2f9, 0xdb97f69a, 0x57f535b2, 0xd4d38fe6, 0xe55ef3ab, 0x2bb4d528, - 0x51660a4e, 0x60fb875c, 0x64e780b9, 0x7da25daf, 0x1c62beef, 0x3f3da796, - 0xca6e41cb, 0xda7ea566, 0xd12f5a96, 0x69f10063, 0x70ea8744, 0x1f47fae5, - 0xe222c1a2, 0x67eec686, 0xe76d3876, 0x130c3710, 0x7100ac2f, 0xdc5c3f8e, - 0xa02f1910, 0xf4907cfe, 0xd7abf167, 0xdc70db58, 0x2e2755cd, 0xef3ee1b0, - 0x8238c1cc, 0x47128dec, 0x833fc70c, 0x04d92272, 0xf0c8f4ff, 0x03fc10dc, - 0x1f850bf0, 0x3ef69c05, 0xdf0533fa, 0x4a7dbf5f, 0x07f38dfa, 0x57efc51e, - 0xafbe4460, 0x6f78e8d8, 0xdea7e50d, 0xf9ce8191, 0x03ae24e1, 0x77e81beb, - 0xb0f7c439, 0x46bbe9e8, 0x0f77f0a7, 0x94aba6b9, 0x731fdffc, 0x71aabf14, - 0xcba35dfb, 0xf370f542, 0x70f69a27, 0xa6b774bb, 0xb6a6677c, 0xbb94ef7c, - 0xe70ffbc3, 0x5c6c3597, 0x9ca37460, 0x392c3c36, 0x8be843bd, 0x28a4f5c1, - 0x097ba1fa, 0xdb43dbeb, 0x716d1997, 0xe157edd1, 0x6cb79478, 0xaadec618, - 0x193aea7a, 0x7faa879a, 0x71cf9d47, 0x08fbe77e, 0xcdf64f71, 0xc3b09af3, - 0x8db8251f, 0x2fb27ce1, 0xf47b9c47, 0x1dc0f63f, 0xee79d35f, 0xeabe22eb, - 0xa3f6144f, 0x9d33f3a8, 0x08f1610e, 0xd6455fc1, 0xd2ec8e80, 0x0f58d2c0, - 0x2d359ca0, 0x8ae8f38b, 0x7e088fc9, 0x5e4f1e68, 0x9a0f2dc7, 0xeb1fce91, - 0x3cbb1a74, 0x9616c140, 0xd9fd9efb, 0xf7e93b8c, 0xe92f7102, 0x2fb3ed7c, - 0xad7d8407, 0x1e637a11, 0xb7629ff1, 0xd3565500, 0xc768305d, 0x5e10cf48, - 0xbf6b9ca8, 0xc987fdf5, 0x7a11efcf, 0x370af283, 0xb4e05fb0, 0x1d0df368, - 0xbbf8e72c, 0xd73efc2d, 0xb78feb59, 0xf3968dda, 0xd84647a8, 0x218779b5, - 0x57fbc5f4, 0x5e9b3d22, 0xd05ef997, 0x04f6adb1, 0x911fd308, 0x28da6c78, - 0xe5ab9cb3, 0xcbe55ba3, 0x830f6cbc, 0xd185f519, 0x83a706f8, 0x55b57fe5, - 0xd27ab7cc, 0x4ec83337, 0x8bd6eeaf, 0xcdc32f4b, 0x5b064eb3, 0xb79b3cd8, - 0x5d929699, 0x603fd753, 0xf749f455, 0x0a534957, 0x843b5c04, 0xc0bf457d, - 0x417e4290, 0xecf1c4bd, 0x3551ee9e, 0x123da784, 0x3c256cf8, 0x5c6635c4, - 0x1c314cdf, 0x5e50b77d, 0xf9f2d214, 0xd71aa59e, 0xacecf1aa, 0xf27659ee, - 0x5cec3f63, 0x072907b8, 0xccd9ec93, 0x8782d74f, 0x893deefd, 0x93ca74ae, - 0x3fee534c, 0xf60c49ec, 0x67bdbf91, 0xf744ac52, 0x3bfc7019, 0x5f757c69, - 0xf4ae0c7b, 0x9297de66, 0x44fe752f, 0xf67b153e, 0x67aaa271, 0xa7dbe4eb, - 0xf7e7495c, 0xf14ac073, 0xf85974ec, 0x2147f0d5, 0x6d5eaacf, 0x6c49fc92, - 0xa633edaa, 0xa34f11db, 0xe4a97e5a, 0xf735db7d, 0xafd6cf00, 0x5fa38c1e, - 0x567f9894, 0xb1bc4439, 0x47f3faaa, 0x57f9c5ae, 0xfe4fbc61, 0xedaec2dd, - 0x917f08fb, 0x7c60fdf1, 0x7be62ff5, 0xd733e3a3, 0xcddfda32, 0x73df1c77, - 0x69c7442d, 0xea817183, 0xcb173e5f, 0x58a8d6e7, 0xfc287c85, 0xee5b647a, - 0x7f5835de, 0x66062fe4, 0xfd2737d7, 0x58ade8ea, 0x58b9f9be, 0x2491f3c6, - 0x391d90f0, 0xebcf29b2, 0x744b06c1, 0x6fb25ec1, 0xcf8e25b0, 0x327b3e69, - 0x512fb7ef, 0x76b7f27e, 0x7e4843f6, 0x7cc2e86c, 0xe88ff746, 0xb9a3cbfb, - 0xbcc5b81f, 0xca5c8a0d, 0x5fde142f, 0x242ff54d, 0xa5427e73, 0x6327e1df, - 0x7dac149c, 0x2b22be05, 0x92e7deb2, 0x5bdd10e7, 0x697ba15c, 0xf97c84bf, - 0x06f708d5, 0xc7f2f7da, 0x89c3f3ff, 0x17da9fb8, 0x1555feae, 0x07d96fae, - 0x84e340a9, 0xdfb43ae8, 0xb66b6c70, 0x3f057f90, 0xf18c5e2b, 0x27d30c1e, - 0x35123b2b, 0xd1aea6e5, 0x7a6183de, 0x729ef068, 0x04e7c4a3, 0xed5c8a8d, - 0xeddbba37, 0xfba5d794, 0x713f4ca9, 0xce84b51f, 0xf7ff08ab, 0x91ff1899, - 0x5da2f67c, 0xf3566739, 0x4e60c93c, 0x0b75b923, 0x97dc0dfc, 0x31e289b7, - 0xf1493d9f, 0x33b9823b, 0xb3f9c30a, 0x9c1bd577, 0x7b8931e7, 0x9f43318f, - 0x13da77eb, 0xf9837db9, 0x699e4d4b, 0x4d09cb55, 0x015567fe, 0xd2501fb0, - 0x89bd2b66, 0xba1487ce, 0x7aee9fdc, 0xf1def18d, 0x18bbabc0, 0xf2dc4f9f, - 0xd3bbcd31, 0x5d83f4c2, 0x11163c4a, 0xbf98356f, 0x69efe450, 0xe87e7f8d, - 0x9445bdb1, 0xcaf438ff, 0xd3ca22b8, 0x87fd942e, 0xf7c99d7e, 0x86dff69c, - 0xf7cecb70, 0xb91e2f39, 0x0c7ba8de, 0x8d43d092, 0xba648fb4, 0xc77ae3ff, - 0xf42e72ce, 0x850d81c3, 0x1f353f8c, 0xe864703d, 0xa75d5078, 0x3ebabe3a, - 0xddb57c75, 0x5f22ecdf, 0x17f46fd0, 0x415ffd91, 0xfb6130e7, 0x17f78fea, - 0xbbe85a25, 0x4913f855, 0xb7e30e58, 0x2abcf57f, 0xf06a7cf2, 0x47c9565c, - 0xfdadd3ed, 0xaff91199, 0x8321e3af, 0x7eef5c3b, 0x752a73cf, 0xdafdeabd, - 0xfd85ab7e, 0x2576939b, 0xe90e9f1f, 0x1deb0ed4, 0xb7bff23e, 0xc7e41c98, - 0x905c9a27, 0x3469f88b, 0x9afef8fa, 0xe4d12fda, 0x7991efe6, 0x234481f9, - 0x81e5bdd0, 0xf7fce554, 0x42bd602b, 0x9c16e871, 0xd756acb7, 0xd212c5bc, - 0x2cfeaa87, 0x0bdf871b, 0x3ea91ee8, 0xdf2027e4, 0xdb6b1594, 0x2da3f687, - 0xa0ae7bff, 0x6eb25963, 0x24b938c8, 0x1b65c857, 0x9e42c874, 0xa89d1d85, - 0xbf0d1de0, 0xacd7ee1c, 0x40fcf452, 0x0743d9bc, 0x8ab713bb, 0xf513ab7b, - 0x5104edbe, 0x124b400b, 0x89f4995d, 0xfab4baf1, 0x1cc86c9c, 0xd8e3cbb6, - 0xc8504f2e, 0xccd4b77d, 0xf7435bf7, 0xc132fd5c, 0xd0c8218b, 0x413d5609, - 0x4bc30324, 0x2a70c5c0, 0x0cbc3334, 0x015e19da, 0x02af0c1d, 0x89f8433f, - 0x1ed80daf, 0xff656edc, 0x3a25f2e9, 0xd765cbb2, 0xcf97ed0e, 0x3c35f052, - 0x57cb503e, 0xa63e3b9c, 0x8772f72a, 0x7cd8cbc5, 0x2f157be6, 0xec4fe226, - 0x34de0317, 0xc0209382, 0x46264ce3, 0xdd78a6ce, 0x6b7ef7c6, 0xbae5c9c1, - 0x6547c4b3, 0x1777adc0, 0xda97810c, 0x9e64f9a1, 0xb90327c2, 0xe951f8c0, - 0x8dae48f5, 0x30dd2acb, 0x7b234c50, 0xc84f4d10, 0xc59675a0, 0xa7a71cd6, - 0x5f3fb722, 0x7a8f5336, 0x66b4acb4, 0x5f90a90d, 0xe5154ee6, 0xd32f3589, - 0xf3fb7d51, 0x71728a97, 0x81c1a94d, 0xcbdae85e, 0xfa825e66, 0x27dcadd9, - 0xa011a337, 0xb672637b, 0x2b761738, 0x724dcaf7, 0x2fba5ae6, 0x580dba66, - 0x0063b8df, 0x22d7ecfc, 0xb8bc91b7, 0xb37b1c45, 0x3aafd055, 0x2e4b7dd6, - 0x2fb333d9, 0xb87486de, 0x28dd6d79, 0x18f79bb2, 0xa49ff8c5, 0x81bdc6da, - 0xc49932f8, 0xbf7556bd, 0xc189ef58, 0xadb24072, 0xad0cc969, 0x59c75d4b, - 0xe9d77bcc, 0x774fcde6, 0x023d206f, 0x15c70736, 0xbefb1463, 0x34c4cb65, - 0x1d7030f4, 0x20475e56, 0x0b4d772e, 0xee91dd56, 0x1bc6847a, 0xf87c1388, - 0x7529d108, 0x75cbe878, 0xc43b943e, 0xdfb581f7, 0xbd23eabc, 0x042e29f4, - 0xae4df9c7, 0x475a71fb, 0x51902e93, 0x45fbf48a, 0x05007a2c, 0x9096be21, - 0x0f107398, 0x1af04e6d, 0x77945e59, 0x99f9ca36, 0x8b03172a, 0x4fc43c71, - 0x8b55cb99, 0xcc5422ee, 0x60937e6e, 0x16bdbba5, 0x179e686b, 0x724d3d68, - 0xe4f881b0, 0xc607e268, 0xc76e594f, 0xf454fe0a, 0x9eb6f759, 0xa288c6db, - 0xb2e4c20b, 0xaf89db69, 0x6f7486ff, 0x5071663a, 0x3e3c90f3, 0xe79c46b6, - 0x46fa345a, 0x5d09d395, 0x9c383e26, 0xc5a2f5b8, 0x07d26ed4, 0xb7a4d9bd, - 0xda06f727, 0xe81e7dc8, 0xc8463bde, 0x7fd7ea89, 0x7d8b9d23, 0xfc8cccf9, - 0xf9104091, 0x839c5e23, 0x8af4fc73, 0xad5f0738, 0xeca93de4, 0x788b7de1, - 0x573b8d54, 0xde2dbcf6, 0x6ff07985, 0x122bbd05, 0x713e967f, 0x6fc455e3, - 0xd48bef91, 0x6949b478, 0x7bd7a2b7, 0xf227ed37, 0xc51351bd, 0xbfc345a3, - 0xa27a6a37, 0xc8d1e396, 0xb9bd46f7, 0xb14afe4a, 0xa1f8a08f, 0xb436944b, - 0x87c70b3f, 0xf709af46, 0x35c9fab6, 0xd3952b0e, 0xc7d60e2d, 0xe10e3d57, - 0x6489e1ed, 0x9e5519e6, 0xd893ad97, 0x5af156bf, 0x49c9bcfc, 0x7e7e28eb, - 0xe8cdfb14, 0xe97b8bef, 0xde913e4a, 0x837bd012, 0x2cc189cd, 0xb9ba67ba, - 0xfe41df3b, 0x9d5a1ff8, 0x68430ff0, 0x503c6a7d, 0x4b54bf27, 0x2d8e87ef, - 0x3f0b38c2, 0xa679eead, 0xd5e58ccd, 0x1055e9eb, 0x13f384a5, 0xdf2aafc8, - 0xc6978329, 0xd543ef01, 0x39153b08, 0xc0e9a537, 0x188f8616, 0x0db008db, - 0x29300f91, 0x4fcd8bf4, 0x39c7d4d2, 0x4ff4d02e, 0xd4d2cca8, 0xf788c5b7, - 0xfa71e032, 0xef422a0b, 0x3f9d1248, 0x0083f4d1, 0xbd08adfe, 0x7e27b917, - 0x4f7e4eea, 0x3ce06fe2, 0x2565f245, 0x7926f69a, 0x5dfc4cab, 0x435ea5fd, - 0xa6529fcf, 0xb956f11b, 0x9c1cfd1b, 0xb69f4267, 0x01e0263e, 0x5bb317ea, - 0x984bc9af, 0x85f2da6c, 0x629e4a79, 0xe4d58c2c, 0x2ef10629, 0x61d8fef8, - 0x0545f31d, 0xbaaafce4, 0x006cf08c, 0x6f1a2daf, 0x5df840c7, 0x1c5ac6c7, - 0x426a96f4, 0xc932cbcf, 0x8b4baa41, 0xb5b351ff, 0xd6ed1ff8, 0x52cc7be2, - 0x9bd3be2d, 0xb0bef8b5, 0x4cd78b45, 0xd96f168f, 0xda6826eb, 0x346bdbdb, - 0x578dbce5, 0xe45fda68, 0x8f29a19d, 0x4d7af17b, 0x858ec2fb, 0xaee2fa9a, - 0x957a9ae5, 0x83e386cf, 0x11d5bef1, 0xdd03a6fc, 0x74a0f869, 0xf335cfe7, - 0x9ff450fd, 0x05e8a79f, 0x2bd7fe85, 0xf8dde576, 0xb892f7c3, 0x7a158b4e, - 0x50df3070, 0xee78e06d, 0x6d725b3d, 0xc505e91c, 0x7b14b9de, 0x894f3907, - 0x1d9455b2, 0xa2bf717e, 0x36ab9f64, 0x2cf746de, 0x8a8afdc4, 0x09b5edc3, - 0x1de23ed4, 0x494af4d6, 0xf91dde73, 0x67a66b2e, 0xd1209cad, 0x3f7144bd, - 0x841ef231, 0xdeab3efa, 0x2739a319, 0x96bdee1f, 0x78c25f9a, 0x2f148c01, - 0x3efccce8, 0x721fda31, 0x5fd9946c, 0xf6ffb373, 0x79cdc967, 0xfecc6ba7, - 0xecefe20c, 0x79f5eeb1, 0x3aa3b788, 0x3dfd8d87, 0x00d6fde5, 0x2fdf8c6d, - 0x3ca4ccf5, 0xbb8600e9, 0xdfd4d794, 0xbd2663b3, 0x5be5c45b, 0xac221503, - 0xe68f3fa6, 0x71a41fb9, 0xbbd6480e, 0xbbefb14b, 0x20cf3e13, 0x73a2667b, - 0xff3e12fe, 0xfc2f387e, 0xee147bfc, 0x406df50f, 0x79f0f367, 0x8e25cfee, - 0xc1a73e53, 0x77e4c2aa, 0x4f79419d, 0xb9b6e22a, 0xb8d4be0a, 0xff328e6d, - 0x29621c01, 0x5db9f3ea, 0xacbc667f, 0xe253eb48, 0x158766bd, 0xac71bfc7, - 0x7bef84a5, 0x221d4b39, 0xb8e357de, 0xb1f7f231, 0x87ba67b3, 0x88ed22b5, - 0x97869e26, 0x57cc8792, 0x42c5e646, 0x1fe316fb, 0x76cb1f58, 0x74fac0e8, - 0xc6863fce, 0x85f9ca3f, 0xfbdacdb9, 0x3e5bf3dd, 0x02dff0d2, 0xfa9a27cf, - 0x30d04a40, 0x781ff706, 0x1bd4f475, 0xaffd7f10, 0x9e282a98, 0xe4f5ba45, - 0x0fc68795, 0x897797dc, 0xb4ce1bf0, 0x1d79cfcf, 0x5afdcabd, 0x5bfb9f75, - 0xd03971f7, 0xefb8881a, 0xbfc4d1e4, 0x09fe342a, 0x0e8fc9f2, 0x431c234a, - 0xe76673e5, 0x57a9388b, 0xabda7779, 0x55ed3bbc, 0x2af689de, 0x957b42ef, - 0xbbeaa177, 0x9c095edd, 0x8e64bf74, 0x816a7ae4, 0x0f76efc4, 0x969b3ed1, - 0x5de88b07, 0x60715363, 0xbbf3249e, 0x7df423dd, 0x45bb7788, 0x69f49592, - 0x6ef435ea, 0xcf08f0f7, 0xd9d8b251, 0x50d789f9, 0x28d870bc, 0xc5f4a3e4, - 0x7bd2666f, 0xdd53c7bd, 0x3fbf89c7, 0xf31f6495, 0x9f12ebf3, 0x6033832b, - 0xef16719c, 0x13cbbf7a, 0xf32734e7, 0x0a89b9c4, 0xbd0be647, 0x9cb04a56, - 0x2e6f72e8, 0x68dabbbf, 0x385777e2, 0x7617539f, 0x7df2221f, 0x4d1fc95c, - 0x6a1fd23e, 0x5f2127de, 0xbbd3379c, 0xca675a39, 0x6ef126fd, 0xa0cfe02e, - 0x0f747677, 0xbdf245ca, 0x1de29c1b, 0xf0a6de5e, 0xf90930f7, 0x45bd3dca, - 0xb7a779a0, 0x7ec0e7b2, 0xe5af27d2, 0x53f393b9, 0x56c7ef43, 0x7f676fc6, - 0xc6df20af, 0x797ae2f3, 0xee17a8ff, 0xc79cfa24, 0x7e56617c, 0xd7fff479, - 0xf5bc3860, 0x5a3ff62f, 0xf77a1990, 0xaddef616, 0xaf2c3f20, 0x343faea7, - 0x42e5e9ce, 0xe5a97bcd, 0x93dd8f43, 0x7486724b, 0x5948f911, 0x88633f9a, - 0x05f3d3fe, 0x774feffd, 0x97f9a04d, 0x60bc8b37, 0x6fda6f88, 0xdce898f9, - 0x3ef21963, 0x723fdabf, 0xf5b72b9f, 0x9f703e30, 0x617f68f3, 0xf08cbcfb, - 0xbfb3eea5, 0x05a3ef7b, 0xdfdf73b6, 0x6e777df7, 0x6d71811a, 0x767950d2, - 0x7e613eb4, 0x3fed4999, 0x8fedaf56, 0xb1e5390e, 0xd1de48bb, 0xe254e96f, - 0xc4cbb21e, 0xee5daa17, 0x2920e254, 0x02ed83b0, 0x71724bcd, 0xfb61e4b7, - 0xda3be6a8, 0x947fb424, 0x61af7057, 0x685f217b, 0x775f1071, 0x49f9ef22, - 0x58cef41e, 0xc44773ce, 0x758b3fd7, 0xbc7844df, 0xa335aff9, 0xf2defe28, - 0x38942b97, 0x72abd84e, 0x69cb3f85, 0x4147da7e, 0x996df302, 0x730abeb2, - 0x55c9fb33, 0x5e4591e0, 0xac93c943, 0xdff1c1df, 0x141a01ff, 0x43d0aaaf, - 0x000043d0 -}; - -static const u32 usem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x1894738a, 0x18357a18, - 0x326b3618, 0x31686830, 0x20318830, 0xaf8568e4, 0x9fa65371, 0x8181959b, - 0x81f98817, 0xd7881058, 0x6c303133, 0xff5e2260, 0xfb045111, 0xc303209e, - 0x197f2051, 0x6614ee90, 0x64055860, 0x2fe2031f, 0x1080be40, 0x100c8303, - 0x606115ff, 0xc1d20530, 0xc4036c40, 0x9bf145c7, 0x7c80827f, 0xbf2a08bc, - 0x279f8d1b, 0x25ff5f8c, 0x0ff2fc11, 0xc363c808, 0xc7e41632, 0x7a052247, - 0x29370207, 0xca8ff2a2, 0x543c3033, 0x51d06060, 0x919bf082, 0x6280ede4, - 0xec21e4c7, 0xb8c09229, 0x28b5ca07, 0x2a773762, 0x5004fe50, 0x34894bce, - 0x41d3dcf7, 0x8434afe5, 0x3ebc00d0, 0x03a8e414, 0x000003a8 -}; - -static const u32 usem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xc5547c0b, 0x3d9cf8b9, 0x926eece7, - 0x2126cddd, 0x26c2bc21, 0xb80d4401, 0x41a00c40, 0x94520f37, 0xa2a1e1a8, - 0x24786c22, 0xf622ef21, 0xddbf1f62, 0x52c488f0, 0xd4c51f1b, 0xb051768b, - 0x40368bd1, 0x5c1758d0, 0x6d8b459e, 0xd5a045e8, 0x5e40137a, 0xa540b206, - 0xcffd45b6, 0xdd9ccdf7, 0x26364e73, 0xf6ffef6a, 0x9fdbfffe, 0xcccce61d, - 0x7cdf3337, 0x9be6bdf3, 0x91be6489, 0xf21387d8, 0x256efc25, 0x108951e4, - 0x9b4e1892, 0x9fc6933c, 0xedb10994, 0x3bea247e, 0x9e0c8499, 0xd146706b, - 0x64085fa2, 0x21064b4e, 0x758d65c9, 0x793dfa46, 0xe8bc7d91, 0x9819c308, - 0xbdbae47c, 0x720c8409, 0x8266f6d3, 0x7fe92fbf, 0xc637b73f, 0x79c87491, - 0xe131a285, 0xbc9a4afa, 0x877bfa48, 0x149bbeaa, 0x48dda675, 0xfd51fbfb, - 0x9085b720, 0x4678c31f, 0x40cba942, 0x78b8e8b2, 0xfd2e6f5d, 0xaf0e3a3f, - 0x295be8cd, 0x1c1a2210, 0x242444b1, 0xa0482326, 0x679fbe9d, 0x49d7ed3c, - 0xaa36a708, 0x49e74ac8, 0x0896b4c8, 0x808972f5, 0x76cd8878, 0x78e97b25, - 0xe22e7d57, 0x220d57bc, 0x27d69da4, 0x684ed392, 0x61c4953a, 0x232dc7bd, - 0xd57e4206, 0x07123fae, 0x199b1b85, 0xdc155e24, 0x0e210f06, 0xc7afc513, - 0x8f2ae98c, 0xc4c9a79d, 0xab210d71, 0x574c0e3d, 0xfa634679, 0xdb27d0d8, - 0xf9d00673, 0xe9d8320c, 0x63834848, 0x1191dda6, 0x2dc72786, 0x0938e730, - 0xae2926c9, 0x2f5a54c4, 0x4dc840d1, 0xf342dc84, 0x19082375, 0x5084ec49, - 0xbc933dfc, 0x019dca2c, 0x45e60779, 0x7cc37103, 0x2e033263, 0xc62de291, - 0x1c95cf69, 0x1bf8efe1, 0x785fdf80, 0xc1d6152c, 0xefcc1b7d, 0xf0ece219, - 0x46dd9e02, 0x7f5a26e7, 0x5e4ceca5, 0x468ae14a, 0xad832eda, 0x1e1094bb, - 0x1fc04cdf, 0xc9cc8fed, 0x30d7acd5, 0xb4224718, 0xeb05dc73, 0x75b27164, - 0x1574095a, 0xf2e61d61, 0x77655875, 0x38fd19d9, 0x11fa2449, 0xb1fa5aed, - 0x8fe96864, 0xba9fb17e, 0xbf69e79e, 0x3bed424d, 0xbd3ce953, 0x4dce0c4b, - 0xa160dbf4, 0x0af80051, 0x80c425bc, 0x41f92afd, 0x63a05265, 0x179e1ab4, - 0xf6f7e9cb, 0xefcf730e, 0x52e2062d, 0x2a5372e8, 0xcec4777c, 0x6626e3a0, - 0x6b4cec47, 0xe987f1cf, 0xc925d924, 0x4c0eef40, 0xac47041b, 0x477ce300, - 0x9c049b24, 0xf6a4727f, 0x08edd3ff, 0x377ae1f1, 0xda5475f0, 0x3d203c51, - 0x468b1f79, 0x3450883c, 0x17e70c39, 0xad17cf1c, 0x4a434f45, 0x5868e348, - 0x875f9a5f, 0x79a663f4, 0xb09be62b, 0x3fca1edc, 0xacc9e58b, 0xba5e5d3e, - 0x55e3bd18, 0x6eda1759, 0x4291c203, 0x38445e70, 0x9bbf5096, 0x94203f30, - 0x1fd625ff, 0xb7f7eaca, 0xceed251f, 0xf9c29e0d, 0x003b2ebf, 0xd6dbc29f, - 0x2e94adc0, 0x7c106e0e, 0xec0f9a26, 0x75fe418c, 0x9f0cfd7e, 0xd767e289, - 0xea0b9338, 0x8398df9f, 0xefedbcf9, 0x5e5a24db, 0x20945db5, 0xd679d86f, - 0x5bf141d6, 0xfc7f6a63, 0xb83dfa66, 0x602f245d, 0x9f71d377, 0x48b4e29d, - 0x92f9633e, 0xdaad9628, 0xc01e6bb0, 0x91336b2d, 0xeaa70a28, 0x6f3bd2cd, - 0x03d2f9a6, 0x552a8132, 0x838cea9b, 0x4f897e69, 0x8afc8168, 0x3f601f9d, - 0x0ca4b9dd, 0xe039f7f6, 0x752f945b, 0xee93dadb, 0x7dcbdfa6, 0x7ea00a5b, - 0x09c166f9, 0x7ebe5c4b, 0xbf0087d7, 0x211e55bc, 0xcd15f852, 0xdaa1c431, - 0x17db792f, 0xade309df, 0x9426477a, 0xabb291ed, 0x1891190f, 0xe02346a4, - 0x13d36ab5, 0xe79be046, 0x1fb0073c, 0x2f559f05, 0xbb687ed3, 0x2704d7ea, - 0xc0daad4c, 0x3785cdf8, 0x68bce6a3, 0x19d57981, 0x37fb4147, 0xbd42351f, - 0xebf15f52, 0xdf180e51, 0x8c016306, 0x6306fd73, 0x566f8a89, 0x3356ff34, - 0xe94d53ae, 0xbd19dd03, 0xce39e7af, 0x397c95b7, 0xdf484015, 0x4338cf92, - 0x339e87c5, 0x57fd21c4, 0x11c48b34, 0xdf781f81, 0x8760fbe7, 0xbe03f195, - 0xc0ed4b5e, 0x75ebc21a, 0x4fd7cec9, 0x88cd660a, 0xe71ee7c0, 0xcb91a3f2, - 0x7e41278f, 0x2e69f4d0, 0xf971d63f, 0xe271e4d1, 0x933d67f7, 0x71ef5d30, - 0x67bcfa61, 0x4f3ea61a, 0xc17bd611, 0x8dd30733, 0x7f7e371e, 0x698653c9, - 0xbf16a7b3, 0x8e59e2bf, 0x178f66e9, 0x59e6bfbf, 0xa78b6983, 0x9eadd311, - 0x3d5b4c26, 0xbaf7ac3e, 0x36d319a7, 0xff7e0b4f, 0x530da7b5, 0xe98027bf, - 0x9a5f584e, 0x98ed3c06, 0xc31cf6ee, 0x03a7af74, 0x9cf7eddb, 0xc72d74c1, - 0xe49b2dbb, 0x366f1448, 0x18394117, 0x91cae85f, 0x88be3e69, 0x7ae693e5, - 0x9f348c73, 0x8a79a6e4, 0x8195c1c7, 0x0fcd131c, 0x29e565ae, 0x66b9243f, - 0xb2f14f9a, 0xaeb5b4f2, 0x4f9a28dc, 0xa3e5646b, 0xa3737bd6, 0x8f947e69, - 0x39b75f95, 0xf3431b90, 0xf2b0b5d7, 0x67927eb1, 0x01b1f9a1, 0xd07f1f96, - 0xf9a56795, 0x9f2cedf1, 0xcf37a1f5, 0x1d59f346, 0x5d4dfdac, 0x9a58bc81, - 0xcac829bf, 0xf24ab96f, 0x2e4003ed, 0xb5cf980b, 0xd1c7e4e4, 0xe59dae7c, - 0x4b16860b, 0xb7f4088e, 0x0858ee53, 0xb0867c22, 0x7e5125d1, 0xf1d8d3b3, - 0x647d1510, 0x4baaf0a1, 0x2033fca2, 0xfe504593, 0x963af0b0, 0x19648c07, - 0xbc2a3f94, 0x65bbe58d, 0x5cff9607, 0x46f2c038, 0x87ff9607, 0x7bf30870, - 0xef961765, 0xf2c4fe10, 0xff961746, 0xf981385e, 0xcb1bb2fd, 0x962e853b, - 0xfcb1ba37, 0x5753e949, 0xdf2fed3e, 0xdc2e9ee0, 0x5ddb7208, 0x6a597286, - 0x597e0649, 0x04fff9cf, 0xaf2d0640, 0x3944641f, 0xacf3f3b8, 0xd3814517, - 0x97c800f6, 0x05fa04bc, 0x485b3385, 0xc2827d04, 0x7386fb11, 0x349317cb, - 0xa2f96e70, 0x20f3814c, 0x1fea89c2, 0xdc5f9d9c, 0x17cf1da4, 0x129c0ae5, - 0x7fb5979c, 0xcbe5baf3, 0xbe78ed6c, 0xd4e054ac, 0xfeb89c20, 0x4f20278d, - 0xc809c0d4, 0xe59c0aa5, 0x7fb12708, 0x271971e3, 0x8cb8e06b, 0x7538144b, - 0xff506708, 0x378c04e0, 0xac63c76b, 0x863ce050, 0xbfd61e78, 0x534cb979, - 0x5531e3b4, 0xc29e7029, 0x0ff6a4f1, 0x16ab6ece, 0x21adbb3f, 0x3847acfc, - 0xaf37fb23, 0x3f169b5c, 0x7e10b6b9, 0x6b9c2136, 0xb76707fb, 0xdd9f8b4d, - 0x5e7e10b6, 0xe98cfc43, 0x6372bcdf, 0x8dc9f8b5, 0x0de7e10d, 0xfeb8cf1c, - 0xa26f678d, 0x137b3f16, 0x2009f843, 0x37fb1b9c, 0x2d24fc9e, 0x4293f27e, - 0xe10779f8, 0x9c1fee4c, 0xfc5a49bd, 0xe10a4dec, 0x67080fe7, 0x95e6ff4a, - 0x9f8b503f, 0xfc2181fc, 0x7270807c, 0xa94ccddc, 0xbdac70a4, 0x4c3fd9c3, - 0xc3fd9f8b, 0x8939f842, 0x3852a670, 0x29c37de9, 0xa7e2d148, 0x9f842520, - 0xb6e708f3, 0x9fd9c1fe, 0xfecfc5a2, 0xae7e1094, 0xfa3b9c20, 0xe182af37, - 0x0c14fc5a, 0x55b9f867, 0x8672871a, 0xd8274eca, 0x9a19dfe7, 0xc13212e3, - 0xd179624e, 0xf7a024ee, 0x433e8a88, 0xad225dda, 0x371cd96f, 0xd6a231fe, - 0x068d726b, 0xaa56cf4a, 0x9af5a9e5, 0x1ad149d8, 0x15ce2a3d, 0x4c27c9af, - 0x9fa9ac1b, 0x29a69458, 0x3ae7381f, 0xf720f94d, 0x487e4d78, 0xfa9a4dd9, - 0x35736ac3, 0x6fcbe1f9, 0xf54fd4d7, 0xd3e4d4ce, 0xa9afdcd7, 0x8171b23f, - 0xa69afca6, 0xb5f94d72, 0xfc9aa5be, 0xd7dfcdf5, 0xb2d31fd4, 0x437e5342, - 0xf29a63db, 0x35278171, 0x9e0709f9, 0xb1bfd4d5, 0xf94d05fd, 0x68af63c4, - 0x6c7727ca, 0x3e6fe4d5, 0xfd4d6bf3, 0x9addc129, 0xbd9fadfc, 0x439fa9ab, - 0x6fab53fe, 0xd4d03f9b, 0xa13f6a9f, 0xf24eff29, 0x553d3a27, 0xccaf1f6b, - 0x32afcc21, 0x01afd988, 0xc6f311ab, 0xa76616c1, 0x271c4b58, 0x7718fd29, - 0xa00c742f, 0x033403f4, 0xe0ce5176, 0xe83a6bb2, 0xe4ddeff7, 0xbf4ec6be, - 0xbee8cf7f, 0xbf411ec1, 0x9026f4a1, 0x061d4864, 0x8fe5f548, 0x73de8cca, - 0xd51d5c87, 0x18d7db49, 0x68e2a382, 0xe73123fe, 0xf9c7a03e, 0x83ee0306, - 0x42d49168, 0x411368bd, 0xd4d1e9bb, 0xaabd17ac, 0x1866b0fd, 0x308433d5, - 0x3bb235dc, 0xc328f519, 0x9bd03af8, 0x79d187ea, 0xd164260d, 0xbcbb718a, - 0x61fb6823, 0x8fe0c925, 0x3f991930, 0x91bfd424, 0xfd819ff6, 0x6bfe812f, - 0x94dfe97a, 0xbfd34936, 0xd34ca539, 0xfb48d9bf, 0x90f213b7, 0xbfde26e1, - 0xcb36fd19, 0xfec64c56, 0xd865294d, 0x6a46a3ff, 0x8ffba977, 0x88fff50e, - 0x31ebf681, 0xc7b9bb30, 0xd26ed3fc, 0x5ca53fce, 0x9b237f3b, 0x2e434aff, - 0xe71a3fef, 0x0e456abf, 0x394a7f9b, 0xc189bf9b, 0x0b6ff50d, 0xfa01bfe1, - 0xfd2f69ff, 0xb5b3d29b, 0xa95e1ff3, 0xf589bf9d, 0x76e194ff, 0xfb05bfde, - 0x6dc57a7f, 0x2bc3fe6c, 0xc9a37fb1, 0x31fa04ed, 0xf5ae890e, 0x50c9fed1, - 0x040d256a, 0x40fda172, 0xfd1e3a3a, 0xd21a7708, 0x8bdf1c70, 0x2576f466, - 0xf21bd29a, 0xc3b32f33, 0x5273947d, 0xd39aaabb, 0x1ce6c57a, 0x2c3df023, - 0x3164224f, 0x36a2ea1f, 0x3c9be911, 0xa48df26d, 0x26d0bde3, 0xe8bf217a, - 0xe03e29e9, 0x322635af, 0x49da08bf, 0x3fdf0024, 0x1798d9fe, 0xa7d2f3d4, - 0x53e51b8b, 0xde45fc91, 0x96ba325c, 0x1002ef8e, 0x9c7f2a81, 0x186071da, - 0x1eed487f, 0x139fed42, 0x23efeb32, 0xbe41ef6a, 0x687bda83, 0xe63a9338, - 0xdebaf357, 0x5fc7411f, 0x0b9f9444, 0x6e2f79e7, 0x624f0a29, 0x5af8f7fb, - 0x31eb07c1, 0x450c797f, 0xc53c787e, 0xbe4d04de, 0x07eac4c6, 0x2f7c136f, - 0x0dc30808, 0xe1c199f8, 0xcd2f1811, 0x36b3b1cf, 0xb1de7747, 0x7dd1b05f, - 0x5d0866b4, 0x599c308b, 0xa40f25c4, 0x565eefed, 0xa76b832c, 0x8186105d, - 0xa166b09f, 0x3768024c, 0x0649137b, 0xde3a0e27, 0xfe0cedfb, 0x527c970c, - 0x239b47ed, 0x74455d9b, 0x458a733c, 0x69acff1c, 0xed3ff2da, 0xc619718c, - 0x53cd74d2, 0x45ddcfd8, 0xe77bf2da, 0xb9f7f368, 0x572a79b5, 0x0fab9065, - 0x53bfe994, 0xdf8124b4, 0x001bf431, 0xe3907ce3, 0xd95ac1e1, 0x6a5759ab, - 0x72951b76, 0x09b88470, 0x8bdb0bce, 0x5fcfeb3d, 0x7b17cdae, 0x6b85f9b5, - 0xdd39f074, 0x7febe29c, 0xa683e81c, 0x283e81a7, 0xfa724f3e, 0x2d55f308, - 0x9a13dc7d, 0x650fa306, 0xb624a71e, 0x33d6a704, 0x18dc58fa, 0x8a1e9913, - 0x52e0f443, 0x0f4297d3, 0xfc3d38f3, 0x6943d399, 0xeeae9693, 0xc9d5be23, - 0x6b03fdb4, 0x1d3ae177, 0x3d198a11, 0x87a140fc, 0xb83d0d0e, 0xd7e83d39, - 0x87a71e6f, 0x7a308f79, 0x0767afd0, 0xa68e87a7, 0xeb4932cb, 0x1d74aeb9, - 0x0eba7934, 0xa3b775ba, 0x47ae8a1f, 0x10587a44, 0x389d379a, 0x65e42fcd, - 0xd38bd63d, 0x01a79603, 0x09e209da, 0xacf7a7db, 0x2684f94f, 0x7914da5f, - 0x36da6bfd, 0xfaa93dac, 0xf2f2d55e, 0xbb7fb55a, 0x268b79a2, 0xa6f7c4bf, - 0xd3697ea6, 0x717e4d2e, 0xfa9a3be3, 0xd21cd70b, 0x7fbd8be4, 0xbf9fd4d4, - 0xfe5353bc, 0x4d59ed60, 0x176503f9, 0xdcfbf935, 0xbfd4d37f, 0x13f08e77, - 0xa2eefe75, 0xeba89fa8, 0xa7169acf, 0x0d70cfc9, 0xec37d4d2, 0xa02ef6bc, - 0x8bef83c7, 0x4f8ff404, 0xffd1a79d, 0x7653a9f9, 0x1e939d42, 0x5383ee07, - 0x9e98d19e, 0x9f7138f1, 0xc24cf39c, 0x1edb42f4, 0x2a15c80b, 0xc8e04b47, - 0x96e574a6, 0x20d935ba, 0xdfca09d7, 0xd46f958a, 0xb2128779, 0x8a639414, - 0x2326c2ef, 0x44204c09, 0xc7c4e100, 0xe5551415, 0x37947d1d, 0xd0914151, - 0x23b0bcb3, 0x279af7f2, 0x23db878b, 0xf7847f9c, 0x7a021935, 0xe72f7752, - 0x29029524, 0x64277f52, 0xad81f205, 0x34a94f5c, 0xb9517e32, 0xb12e5075, - 0xaa303e41, 0x6bfaabf6, 0x206c9ba1, 0x66ba49d0, 0x5d36973f, 0x04f7e1af, - 0x4089cfbc, 0xdf34136f, 0xd66f9a2b, 0x25daebb4, 0x81abb8e2, 0xfdb95097, - 0x527a292a, 0xd8153e04, 0x0c6b3293, 0x14f5d38c, 0x5112dbe6, 0x34f2ec8f, - 0xc7f385af, 0x4c169e73, 0x30da78cf, 0xac09e53d, 0x93c07385, 0x1e98039e, - 0xda63b4f7, 0xe98639e1, 0x4c0e9e47, 0xc19cf43f, 0x209e4ff4, 0x9f3cc7a6, - 0x43c47a61, 0x0e70027e, 0xfe98cc7b, 0xb4c763c1, 0xe98c93dd, 0xfb0f8f05, - 0x5f5df651, 0xcb867774, 0x7f4073ed, 0xbb6ce811, 0xcd6eac78, 0xbd9d30d0, - 0xa423f2b9, 0x85cf0533, 0x0f4e264d, 0x087a1a49, 0x2377ed80, 0xe51f4bd0, - 0xc3a7324d, 0x2e47dade, 0xbfe179af, 0x7caede87, 0xd30b7a4b, 0x3d1d10d3, - 0x4f45f7a5, 0xe9e9aa1f, 0xe4cec18a, 0x1fa7a720, 0x7d6b73f3, 0x3b1251bf, - 0x77e90ca7, 0x800cdbae, 0xdcfca5aa, 0x98699084, 0x5efbc4bf, 0xa3b5c149, - 0x0d1be81e, 0xe8d2eb72, 0x73828fbf, 0xe8c74b87, 0x3ef6a7e2, 0xf49d3d3f, - 0xda17778e, 0xba3e2543, 0xc61109e8, 0x1af0cd1b, 0xc8d32065, 0x461a4278, - 0x905ce4be, 0xc4897981, 0x739f7b43, 0x3af38446, 0xc06b7542, 0x5d785f6f, - 0x1632bd69, 0xf67a9de0, 0x5e90591f, 0xf475fae1, 0x7cf5111e, 0x09d17812, - 0x25c90df8, 0xfc193393, 0x4691c1f3, 0x6409ea3b, 0xde7f16ba, 0x6bf835db, - 0xcfce5548, 0x7f11931b, 0x1a8cae23, 0xf5fc0fd4, 0xc2fbdfc5, 0xf79802e7, - 0xfb3e037f, 0xf17d8fe2, 0xbc72e245, 0xdfe746d6, 0xf8cc73bd, 0x07c01cc7, - 0xcadf1abf, 0x3c7e9c79, 0xb5f492f9, 0x493bb8e8, 0x14f6e3a1, 0x24d85b88, - 0xa5fe11da, 0x61626bd6, 0xfa70425d, 0xede14f58, 0xbd80a73f, 0x0b553e7f, - 0xef074b2f, 0x6d1781d2, 0x4d2d7760, 0x3270d85e, 0x69283ac2, 0x835d4b55, - 0xb687ad45, 0x1a97f369, 0x382d6985, 0xecec472e, 0x6a272031, 0x5edf181b, - 0x6702a98e, 0xf6097269, 0x3d39ae73, 0x3e7bd996, 0xc7360fc6, 0xe738bf21, - 0xfffac329, 0x06f4f1ec, 0x210f1947, 0x1984e4ad, 0x4b2d31f8, 0xaf7ebdef, - 0xc5fd2cf4, 0x7edde788, 0x89e80af9, 0x97dffa66, 0x09107760, 0x9adc0af3, - 0xba6bd116, 0xd66fbe01, 0x39db47f4, 0x2fe23394, 0xdf6abed3, 0x4294e448, - 0xd45e54b7, 0xe780bd83, 0xd41a4b9b, 0xcb55597a, 0x9af93577, 0xd41a47b6, - 0xfc055c7a, 0x525ff283, 0x3740482b, 0xba8c9c95, 0x811acb25, 0x8218af8e, - 0x088f804f, 0xb9955eac, 0x9fa6e8c3, 0x75b2b7ce, 0xe77c6deb, 0x8854e63c, - 0x3733283b, 0x597239e2, 0x20f9b5cb, 0xaeb7ce67, 0x5bf9024c, 0x5efa5e21, - 0xbff68451, 0x5f2e0494, 0xcf56a0e4, 0x2841f4e7, 0xe9bcd55c, 0x17c212cf, - 0x981977cd, 0xb70f465f, 0xbe91cb8d, 0xf9bd53f0, 0x8ecdc150, 0x6eaa789e, - 0x237468bb, 0xcbffa45f, 0xc149e30a, 0xd454b15f, 0x9771d126, 0xffa27737, - 0x1dec8ce2, 0xe0af83f5, 0x67e73d97, 0xa3153e49, 0xb497979a, 0x260b3f43, - 0xe3888ef1, 0x1f280fde, 0x995bfb3f, 0x57221f00, 0x742cad69, 0xc7bb70cd, - 0x61590c40, 0x6b4167bb, 0xfbe02145, 0xd1d3ebec, 0x8a445bee, 0xa40eb86c, - 0x9cec0b31, 0x7180c4f3, 0x1fc9e755, 0xeb54136c, 0xe464b1f0, 0x305ca678, - 0x1034bb89, 0xd8107bbe, 0xf539a65f, 0xf858e2ed, 0x9076292e, 0x15ca25f0, - 0x17f180b7, 0x2f77d873, 0xfd01d731, 0x634a7b52, 0x4a7b51af, 0x94f6a793, - 0x66425f26, 0x453c4126, 0xf132d3c9, 0x4d278809, 0x8ec941f9, 0xb5252be3, - 0xfd1fa0f5, 0x16e1fb9c, 0x843489d8, 0x37aa87ca, 0xa62acb9e, 0x9892e9f3, - 0x0f894bff, 0xc5654258, 0x5e5e5a20, 0x2cba33e6, 0xa277e73d, 0x943dc275, - 0x163c03f3, 0xd1bf7007, 0x886be2c7, 0xaae2ca43, 0xf3ef5a4f, 0xba2ad81f, - 0x8f506ca2, 0x9bc6577e, 0xafe7f5fa, 0x4f212f9f, 0x9bca3ce2, 0x561c6067, - 0x3e07788f, 0x7059b91f, 0x27ec22f9, 0xf1341651, 0xc332092e, 0x1ad7e29f, - 0x0f5fcbae, 0x6bdf9579, 0x1bfcaea2, 0x440197f3, 0x258a5fc3, 0x913970f7, - 0xbfc013f1, 0x7f710520, 0xc9f8637d, 0x2f5fe03d, 0x844ff8df, 0xefbb543f, - 0xff89fc29, 0xe88ff1d4, 0x48bcfe31, 0x78deabf0, 0x778875f5, 0xcfd5ff2c, - 0xb7ee846c, 0x926352b3, 0xe57bae93, 0x1736d5a6, 0x6bc91df0, 0xd6717d83, - 0x448b4e27, 0x7997df0f, 0x59711fdc, 0xc2bbf004, 0x73fc293f, 0x4ef8fcaf, - 0x6caea3b0, 0x4fe8ed92, 0x4c05366d, 0x5bab9e94, 0xb1921497, 0xf964ef98, - 0xfd022f47, 0xc7c9b4d7, 0xfe5a74d5, 0x41259fcb, 0x94a5107c, 0x48648621, - 0x549f6803, 0x00b8fc6f, 0x121a8df4, 0x6faafdc4, 0x167ffd07, 0xd8b0f28f, - 0x1cb3db18, 0xd049341d, 0x5a6afd9e, 0xb4517c7f, 0x69db7a41, 0xb2d46fe0, - 0xbe90bf44, 0x3bb7195d, 0x00eb642a, 0xc913abe4, 0x0aabe044, 0xd98f885e, - 0x7e5f2b1d, 0x1d276c66, 0xdfc6d757, 0xbe1504da, 0x52e97b14, 0xfc5fc2cb, - 0x1f3bd1da, 0xa3f740bf, 0xe455bf5a, 0xdb8da394, 0x56967e4b, 0xc41b01ca, - 0x906e5573, 0xb9fa5e9d, 0x5f17d5f2, 0xd9fc167a, 0x4739347f, 0xaf15f852, - 0x13723bee, 0x916c57cd, 0x69b21407, 0xf0a48458, 0xffd0d4fa, 0xaf0f8f96, - 0x7db6f947, 0xf618c746, 0xe1f187fd, 0xb2d8a975, 0xf4c648cb, 0xcb5e47c4, - 0x2587632e, 0x74b4fac2, 0xb7fe8016, 0x1abfe5f2, 0xdd9def81, 0xa9819029, - 0x61b9f011, 0x8087ea1f, 0xbe4f5c27, 0xd3f5a15e, 0xeba1afd5, 0xbf467202, - 0x857afa5e, 0x5c00bf9c, 0xf4a1b388, 0x21afdafd, 0x264fee0e, 0xeca1e027, - 0x306c87b5, 0x2d52d39f, 0x56e7f3a3, 0x2bbf0127, 0x7649bd93, 0xb2f7d94c, - 0xfa461fe7, 0x70f43d2b, 0xba57f312, 0x76501906, 0x3cc1077a, 0x1bbfaf17, - 0xdc4259e7, 0xcf658748, 0x9a3e4589, 0x69912a7e, 0x93ec225b, 0x9c9f7c4b, - 0x2e2e817e, 0x4569e79d, 0xe441fc2e, 0xe8bbe172, 0xcf987d0f, 0x98906a85, - 0xd6ccd4ff, 0xd06c80eb, 0xfd10d1c8, 0xe5147c6e, 0xae61b9c7, 0x56ee7081, - 0x28179613, 0x5343c447, 0x6275b207, 0x51db0772, 0xdf0793b9, 0xecbb7ea1, - 0x69ab1a8a, 0xe9467287, 0x9fef197f, 0xf41a3b8e, 0x9149d3b7, 0x46e191ed, - 0x3d500f85, 0xaa674543, 0xfff6cefd, 0xdfb606c6, 0x9beffd95, 0xffca0d31, - 0x23ed9872, 0x97720768, 0x10302b8e, 0x16cd77cb, 0x48983f90, 0xdf3ed220, - 0xae7df328, 0x0bd3d72d, 0xc424bf1d, 0xfa06e8aa, 0x4075c789, 0x34f25f79, - 0xa3e2af6d, 0xadafd035, 0x1f655c27, 0x707e7297, 0xf5c1f81e, 0xd6407e61, - 0x5e2bf627, 0xbdf652b4, 0x5fec2cf4, 0x0ebd5fba, 0x1172bfd8, 0xcd93ffcc, - 0x4fdc8e7b, 0x2d27edf7, 0xf2d5beca, 0x2dbefd55, 0xc630fadb, 0xedf7eb9f, - 0x496b4327, 0xbf4b7dc4, 0x43b7dc47, 0xf847fe3b, 0x24c782aa, 0x2aaf96a3, - 0x7c37b27c, 0x16e4f9ea, 0xd57881d9, 0x3bfa49f3, 0xd27ab24c, 0x0a8742a3, - 0x47ff95fd, 0x47e070d5, 0xe8553a21, 0x0aa74430, 0xade7ea1d, 0xfcbea3c5, - 0x522df023, 0x537a297a, 0x4a95f3c6, 0xa6038b3f, 0xc90ff6ed, 0x50b97c44, - 0xfdc691cc, 0xf3a80643, 0x45be5d3e, 0xcba5df57, 0xbbeae917, 0x4d5af975, - 0x3db6cafd, 0x10748246, 0x9713d4d0, 0x31393bff, 0xfadd1221, 0xf5a1bf98, - 0x39ee11a2, 0xd88258d4, 0xbc415e5e, 0xdc191f10, 0x51b9e221, 0x3d71c537, - 0xa73637f8, 0x8f94bcfa, 0x7e628eac, 0xd07b6e85, 0xd5d34f16, 0x4c1f2c71, - 0x1f03d634, 0xa307be54, 0xbbb1df98, 0x538b6828, 0x7e9d5bd9, 0x8778f911, - 0x0dbdf22f, 0xdd70692a, 0xd7b97a3b, 0x758f9ca1, 0x62c6db47, 0x3e29d17f, - 0xa2a9c7a0, 0xf8396525, 0x27451aa1, 0xea8bece8, 0x79c1b5ee, 0xfd3fb755, - 0xfbf439ae, 0x164477e2, 0x4975e38e, 0xd0765483, 0x975de219, 0xf05c402d, - 0x859fa45a, 0x2d17667e, 0x3f791b5a, 0x2576f394, 0xe0466596, 0x390ed4bb, - 0x51ef3eae, 0xd7ad94e0, 0xe74ff77d, 0xed11a6fb, 0xda8df2ff, 0x9fb73772, - 0xfce4647f, 0xc7191c67, 0xbfe657ed, 0xaa7b7ce1, 0x1cd77198, 0x07dd3eba, - 0xf9a26244, 0xd7117e4b, 0xc166d2e7, 0xe237fe07, 0x57fdc44d, 0xf546824d, - 0xd82e887d, 0xcef4d75f, 0xffb6bac7, 0x4007eb39, 0x307faf47, 0xda69dff6, - 0x471ffaf5, 0x37f905bd, 0x407ca68e, 0xdbcfd67a, 0x02f18519, 0x48ad3bdd, - 0xde3bddff, 0xe401f94b, 0x613934df, 0xff3bdd9c, 0xa9e8163a, 0x0ca9857b, - 0x30f760f8, 0xb95dbfe6, 0x3b63afe3, 0xc2aefe50, 0x1a366c75, 0xffc99f99, - 0xdee08f8f, 0x9d3f25c2, 0x3c17e815, 0xd7e6beae, 0xf0823e51, 0xbea59aff, - 0xe76df40f, 0x43e3cd53, 0xce64adba, 0x1c5f1856, 0x79a87f8b, 0x758bf26b, - 0xd6aaffb4, 0xb485c65d, 0xcfedef3c, 0xfd1c62c7, 0x5d37a656, 0x879e3b90, - 0xc66d87f8, 0x2994acef, 0x26c02f9e, 0x5df646a3, 0xb07935a6, 0xe5e27a8f, - 0xf5a7f473, 0x1aef1f17, 0xaffd7d99, 0xc5c10f8f, 0x67d59ff8, 0x7fde6016, - 0xf403e8fb, 0x2e909a83, 0xd27ef995, 0x4cfa8752, 0xfb3ef35f, 0xfa0e86bf, - 0xd0216f3b, 0x4d9b799f, 0xfdebdaff, 0xeb81d1b8, 0x3d07dfa2, 0xf7c77ce9, - 0xd5aaff30, 0x27ede389, 0xfd368fbd, 0x5beeb63f, 0xfadbbae9, 0xfe77f79e, - 0xfbdde7c5, 0x8f33bfba, 0xce1dbbaf, 0xfede6b53, 0x75f7c71c, 0xffe95cf9, - 0xf457ba52, 0xad4376fd, 0x6f8e933d, 0x82b4690e, 0xe25f7162, 0x03a64b25, - 0x0f2f70a2, 0x383bf8c0, 0x57608d5f, 0xbf989935, 0x581824cd, 0x82dddabc, - 0x3b4447e2, 0x5fae4eeb, 0x0cb439dc, 0x5d3b90f5, 0x827d413f, 0x39edb548, - 0xee7b7eb4, 0x6ac62742, 0xdcc7f192, 0x853d9f90, 0xe6f6b5e7, 0x12e204ef, - 0x677f7ea8, 0xa003f4ee, 0x12e5dee7, 0x29a60f51, 0xa7efbfea, 0x93efb014, - 0x7dd0f6b4, 0xdefe6d6e, 0xddfcda39, 0x843dde1c, 0x229eff8d, 0x587e07c1, - 0x8953ce53, 0x2d3597e0, 0x0a908996, 0xabb54671, 0xbbb8eec1, 0x197edb48, - 0x7f2a6728, 0xe3c537e3, 0x5c78436f, 0x3921788a, 0xed03de22, 0xdc7c8f13, - 0xf9c7b3ed, 0x489ace20, 0x7bc7864e, 0x37e89caa, 0xccb8f6e7, 0x3596cbdb, - 0x659fb0ed, 0xd8ae1d9d, 0x9be1bdd3, 0xe11cfb70, 0x2ff185a4, 0xcfb444bb, - 0xae7d9d65, 0x5dd7cbac, 0xbf1d650f, 0x073cbaed, 0x786372eb, 0x5c5a865d, - 0xccabf604, 0x8b7c87ed, 0x1687e593, 0xe8ae7611, 0x00d2fac3, 0x8466f117, - 0x9897d1e3, 0x9ce02b8b, 0x405a3ccc, 0x6b5dc87f, 0xe60f9445, 0x55c7010c, - 0xf8c64934, 0x450d8fe3, 0x85deb059, 0x7f562613, 0x09c30d9f, 0xf1c25cf8, - 0x516a425e, 0xbf57257f, 0x0b3b32fc, 0xea0825ce, 0x845c4bbf, 0xb8ed41dc, - 0x10216c92, 0x126af10d, 0x078ec6f1, 0x8e40b93f, 0xdae4fc6b, 0x496efc3c, - 0xabe9c30a, 0xe5fc6f7e, 0x17fe9d9f, 0x29c767e5, 0x3a427491, 0xd497bb12, - 0x3f7cf776, 0xa54d63c3, 0xba434be0, 0xfbeac80b, 0xb66605d3, 0x87ebfe0f, - 0xe64f9013, 0x2c4c74fc, 0xe26407f3, 0x6e1ac47d, 0x3af25c37, 0x760fc162, - 0xcfce9fc9, 0x6a6cf373, 0x87a4aabe, 0x9ffe1db8, 0xd3489710, 0x51a17cee, - 0x048b3b04, 0xcdebffd1, 0xc57bc28f, 0xcca376fa, 0x6bafbe06, 0x3f002fd1, - 0xf2afee11, 0xa6d29479, 0x75aaf1b1, 0x59c77b5b, 0x75cf6c69, 0xd571df80, - 0xc5b7ddf9, 0x80fdd82f, 0x1d5143d7, 0xe6114505, 0xafe3893b, 0xf0dff770, - 0x7f4ceafe, 0x99780caa, 0xce6a2f99, 0xee669df9, 0x264098cf, 0x770ab8c0, - 0x0c9b66df, 0x744072eb, 0x1ad57dc2, 0x3ba345ff, 0x1eb1f9c2, 0xfc1f009f, - 0x676427f0, 0xc4f3e009, 0xd808a24f, 0x73f1efd5, 0xcfb80cc9, 0x1eae8191, - 0x731df817, 0xb84fcccc, 0x74c76cce, 0x9c8e6156, 0x68cdfb48, 0x50838fb5, - 0xfebcc1b5, 0xcb03b33a, 0x4a76f087, 0xac95c1bd, 0x5ed1a75e, 0xbffe691d, - 0x79f8128b, 0x937bf399, 0x75bd7f84, 0x35a9f9cb, 0x41fa0b90, 0xd167e2be, - 0xfdc135d3, 0xe09a6971, 0xf60df903, 0x050be630, 0x53de1fd4, 0x64cfafee, - 0x7ba15672, 0xcdab9e3d, 0x1e02f7da, 0x887f78e7, 0x678287d3, 0xf1fabf05, - 0xbf29f52a, 0x9fed55ba, 0xdc6dabba, 0x54dfa06b, 0x81bb05fb, 0x3a96aa82, - 0x6b0fb08c, 0xe1909eda, 0x073ee67c, 0xa2a44b83, 0x83f8eab1, 0x0f166675, - 0xcdfc67b2, 0x2e4e80f3, 0x2c8135af, 0x1745ae24, 0xdf87c06d, 0x0f7f3833, - 0xdfde6c71, 0x57d36489, 0x3c0fabf0, 0x597cf2f6, 0xe715370d, 0x4732ab33, - 0x03da7706, 0x81e4bb95, 0x675a7a2a, 0xe572c78e, 0x074ae0fb, 0xfb420fbe, - 0x1f7871c3, 0x4fb81137, 0x8ed2d192, 0xa81f6cf7, 0x5874638d, 0x88cbb2d6, - 0x7bcd54f9, 0xfa3f4a22, 0x50bb34fd, 0x30bcaf1b, 0xe02863af, 0x5814d0a5, - 0xa7408ce6, 0x7394a393, 0x2729afca, 0xc76e945c, 0x27247ffe, 0xa2722996, - 0x95e3e303, 0xe7df02f6, 0x3031392a, 0x5a589c92, 0xeb0818e7, 0xfa4774b0, - 0x4b24d840, 0x149a99df, 0xefbc4e49, 0x47cce761, 0xeef67df9, 0xdc4e54d9, - 0xb31392a0, 0xf44e90a3, 0xf6513eed, 0x42725f49, 0xcbffb759, 0x907de6fc, - 0xf7f61113, 0x71393a17, 0xe518bf8f, 0x45b33dc4, 0x4facbdcd, 0x391394fb, - 0x5e61f749, 0xa044c676, 0x7db9f79f, 0x0bdf9473, 0x5e407e80, 0x11d94664, - 0xd1b97a6f, 0x53ff5f1b, 0xfffaf97f, 0xbe159e10, 0x3fda94be, 0x7448d4a6, - 0x979e9048, 0xbaf947de, 0xf8c8f400, 0xb907d2fa, 0x67c7539f, 0x66cf808b, - 0x6b2cf9aa, 0x7266ed5f, 0xf52da6a1, 0xfcb4b999, 0x09d946fe, 0x30fef2a2, - 0xf352cddf, 0x5ea8ccdd, 0xe3196ef8, 0x13fd97bb, 0x6dea7f50, 0xfce67f7e, - 0x11b3f296, 0x31f408ce, 0xe68c6e67, 0x7189dede, 0x06d8c9bf, 0x113de5fb, - 0xe63f79cf, 0x71c1c07a, 0x7d04c9bf, 0x9e3e49fa, 0x2f3d7c79, 0x3e794878, - 0x22de5fc5, 0x6d574fa6, 0xd57f1116, 0x57ff6cad, 0x073e0b37, 0xff8c17cd, - 0x56d79e1b, 0xb5e760ec, 0x39850674, 0x78aff5aa, 0xce1ea3af, 0x08362a09, - 0xf70cde78, 0xa59f001e, 0xce259f1c, 0x29573c0a, 0xc1fad26d, 0x2f6da21b, - 0x1e101b90, 0x78abc3fa, 0x105342fd, 0x7f0a1dcf, 0x20373829, 0xabb6d49f, - 0x59fb711a, 0x9a2a4fb0, 0x0d9ddf75, 0x3704ae78, 0xadaf41d4, 0x7b96d16a, - 0x8b17bcf8, 0x146d8c81, 0xb33df93e, 0xf778f4f3, 0xf653f1e8, 0x8873f12d, - 0x9ff327e2, 0xfe259f87, 0xf05e785d, 0xc7a2f175, 0x3f145d47, 0x324f181f, - 0x6c7e3f61, 0xf17f2170, 0xbbe22bbe, 0x189e8b4e, 0xe50f79a9, 0xef2f1ca7, - 0x83f5dc19, 0x80b55ea0, 0x6fd74af5, 0xf34497d9, 0x38c85b73, 0x6d286638, - 0x90e3cad2, 0xa0756ffc, 0xbb5b9f7c, 0xdab88045, 0x60befcc5, 0x7c09ef99, - 0xe5c1e63f, 0xfad3de54, 0xdc9bc70b, 0x287e5e70, 0x53fc882a, 0x409ddfa1, - 0xfa6f94bf, 0x0c4e38f9, 0x9ca3e60e, 0xb8ec136a, 0x4c51032f, 0x8275d16e, - 0x4cf66d77, 0x5f016bfe, 0x6a5fe617, 0x4358eb63, 0x75f60dd7, 0x5be79f81, - 0x80f83e98, 0xe73b22ff, 0xd992eff4, 0x490238fb, 0x44e77e40, 0x8f915cfb, - 0x939aee70, 0x1ddf5aa4, 0x37fe8c9d, 0xe0fc4e09, 0x36fbffa3, 0xbacbdbeb, - 0x7f4cfa2a, 0xd3c157d7, 0x1f3add4e, 0x9c2f6a8a, 0x8272e780, 0xf20bdf13, - 0xd179e1c7, 0xfef646c9, 0x1fae41cd, 0xd805f7e9, 0x78f7ea1f, 0x21c0c066, - 0x145a7a2e, 0xbf6295c6, 0x533f4c69, 0x3bfd29f3, 0x6e375f48, 0xa3b486a9, - 0x7f8e165e, 0x066edf74, 0xd04d3fb9, 0x19d149c4, 0x27ffbee1, 0xbea397c0, - 0x36493e02, 0xc8797ca3, 0x19eebece, 0x1ef02466, 0x3235e5da, 0x06bdd1d2, - 0xe06c91c7, 0x04c98f2f, 0x83e5c7f6, 0x3b9d1e37, 0xa445ca00, 0x26f7e28f, - 0xa56b8354, 0x91aac598, 0x5c9847e2, 0xfffbc13a, 0xaed79513, 0xa097786b, - 0x7ce27b07, 0xb674bf70, 0x0754d773, 0x0f325bf8, 0xcf7386ad, 0x23f67959, - 0x1b1d6047, 0xc74fbbd8, 0x9da1e4d7, 0x0577d0f6, 0xe8c767dc, 0xbb9c017a, - 0x391ea767, 0xe0f7c742, 0xb73c449a, 0xbc4aeb9c, 0xe731ce07, 0x0e9d141e, - 0x5de16f5a, 0x7f9c0b56, 0x122d1f4e, 0x0f2f0ab7, 0xeff47692, 0xeefdadcc, - 0xca4fb0dd, 0xf7843ca8, 0x87fcca9c, 0xfc840ea6, 0xd7db017a, 0xb846dd78, - 0x74ded9e7, 0xfb4998d1, 0x00f5a12f, 0x59eb35dd, 0x028d9abd, 0xe25817be, - 0x64f9027f, 0x1f0146c9, 0xfaa769c4, 0xf5c199af, 0xbed12981, 0xf9a7b69e, - 0x700f6852, 0x03ddc637, 0x743593e7, 0x527ed89c, 0x97539e1d, 0x98b476d0, - 0x2efc6fb4, 0x5eb25bc2, 0xb0af7020, 0xe3ea526c, 0x41de0093, 0x47e509d9, - 0x08dcfd77, 0xfb479ee3, 0x2fe1441b, 0x42a63b14, 0xc103f27d, 0x152eef8e, - 0xbafb8b5e, 0x623bef9b, 0x14e2cd1f, 0xefdca204, 0x2af1d493, 0xb869d125, - 0xd7964a9f, 0x3abcc3d5, 0x06a989bc, 0x468ba7a4, 0x2927e390, 0x7f54ddbe, - 0x7164613d, 0x27bc7b30, 0xfe2a1d8c, 0x1d3a32b9, 0xcb6a2fdb, 0x98b33e41, - 0x853c6114, 0x23e98ebb, 0x7ca3ab9d, 0x94eb57e0, 0x7df029ed, 0x7e136acf, - 0x932af0bf, 0x7586173b, 0xf4fb7fa0, 0xbdc0997a, 0xd3eb95c7, 0x9e3ac1d7, - 0xe13b2cde, 0x8e7c40dc, 0xbe9411c5, 0x7b64fcca, 0xa7b833d6, 0xcb7f199b, - 0x02eeee7b, 0x94a5dbe0, 0x7e70994f, 0xe2563e5a, 0xf53e4728, 0x4be3145c, - 0xe7a57e7a, 0x1b8d6553, 0x65a1cb22, 0xd0e59105, 0x37ee7ad0, 0x6b9f2c8d, - 0xbbe98588, 0xf078c9e3, 0x0d571663, 0xf404d79b, 0x70bb20fc, 0xf3781ed0, - 0xdc819fd3, 0x3be2b4ad, 0x7d92d565, 0x83e8c09d, 0xeb9fff00, 0xec29f2df, - 0x51b9b287, 0x29d90ef8, 0x47d80f58, 0x1cf0136b, 0x8c57c4bb, 0x79e25778, - 0xf4b49b4b, 0xef21f8ae, 0xa5c48b73, 0x31655f96, 0x77aaa5c4, 0x6e9447f4, - 0xdbf33f69, 0xcab01f04, 0xdcea3fa3, 0xe62670ff, 0xe5ae38ed, 0x6b583f5c, - 0xfa3eba45, 0x40d5c5c8, 0x287ef3b7, 0x89dbd010, 0xf20f5dd7, 0x7049bab0, - 0xf4b89f80, 0x297dac87, 0x3ee30f6d, 0x5f4673fa, 0xb01dce94, 0x3fd7aa0f, - 0x6feb1fb1, 0xff001c14, 0xd46286e8, 0x22bcca27, 0x9d8df2c1, 0x79504768, - 0x7b68f185, 0xec1262bc, 0x2655ea83, 0x1562b83b, 0xb3e8527a, 0x40a7bf93, - 0xb3b1cecc, 0xb4673b68, 0x9eb2f903, 0x4239c52e, 0xfd029e48, 0xbd1978d4, - 0x3b2abe75, 0x4df48b61, 0xbd1eec9f, 0xd0227f42, 0xfe98665f, 0x33cfacf6, - 0xf69e3d02, 0x91671809, 0xf40bf407, 0x9fe2b2f9, 0x1eb51621, 0xea7d17d5, - 0xfd07b0e9, 0xe958cbc1, 0xe854fa61, 0xc7874f51, 0x8c0f7225, 0x51d5a1fb, - 0xfabc8f38, 0xce59ef37, 0xcf9e19f6, 0x923fd5e5, 0x44bafb04, 0x0a407162, - 0x1624ab5e, 0x5c63d637, 0x0719d74f, 0xba7c67f5, 0x0e8acc71, 0x20f1edc9, - 0x4a3ea9b7, 0xdf9fb402, 0xe3117e6c, 0xd2bfcf2b, 0x37ea2779, 0x003a516f, - 0x92b66ffc, 0x3e21da00, 0xade547e4, 0x1369c622, 0x4b359029, 0x712bbf65, - 0xb2bf1531, 0xb7cbbe22, 0xb4857c9a, 0x27ebf97d, 0xc25c62c6, 0x7b7fa60a, - 0x39d8115f, 0x2c63b788, 0x972a3bdc, 0x5e8e7c58, 0x345df82f, 0xdebbc3b3, - 0x7a03998c, 0xdeccd09b, 0xb96f2c17, 0xfca93657, 0x65a2fbbb, 0x939e1ea5, - 0xc33ae979, 0x3e300afb, 0x4a76fbf5, 0xcbd74e5c, 0xdbcafe8c, 0xcae7d464, - 0x805cb79b, 0x63f2cd78, 0x6b77b426, 0xc11a2f9a, 0xd5fbcd9e, 0xc41decab, - 0xa7135136, 0xae3e23d7, 0x20980c59, 0x0ab5abae, 0xbe6871cf, 0x3c2df313, - 0xc66bed1e, 0x6afc556f, 0x8a5eebc7, 0xbf6d8ac2, 0x857be1b4, 0x786c9bed, - 0xabf9aa5f, 0xc47b55e3, 0xf034b5c3, 0x4e3bb878, 0x918fe413, 0xc1cee1e3, - 0x7d21283f, 0x878dad16, 0xbf8ccd23, 0x456671d1, 0xa4350f7a, 0xe9fabd77, - 0xddcf10f3, 0xe793f5b5, 0x5f95dc61, 0xe21e7e5c, 0x6882a86c, 0xe6a53d07, - 0xfe31f795, 0x1f176955, 0x97a0edc3, 0xc3f1897f, 0x7268fe17, 0x3b0bb402, - 0xfe80a74e, 0xdfcb6171, 0x782e2092, 0xe8a98ed9, 0x3db659df, 0xedbddf0f, - 0xfa059ecd, 0x7e23f5f5, 0x7b6ebf59, 0x3c60f75a, 0xeeba79d0, 0x714227c0, - 0x2c552d8e, 0xe3c1d47e, 0x8e47371b, 0xcf11ef17, 0xaeeb3ad8, 0x5b1fc029, - 0x67d09e99, 0xba61e35c, 0x63f4379e, 0xf8f3371d, 0xbe3b96d5, 0x3cf1ae32, - 0xd7ae83fc, 0x7c6d18b8, 0x8bada7e8, 0x942cf17f, 0x1af426b5, 0x07e818d7, - 0xf47894fe, 0xd95da3cf, 0xdeb08931, 0xa4f181ff, 0x0e857eb0, 0xa69fd7e0, - 0x8cf8bf80, 0x44bf441c, 0xef098770, 0x38ef966b, 0xc2e9fb8a, 0xef1843f6, - 0xf85c784d, 0xb1fa1205, 0x03ee5df8, 0x6568d9aa, 0x1d7c90f1, 0x61d25e20, - 0x2e3cefc3, 0x12b5d192, 0x9c5bd92f, 0x3498b2e4, 0x8b0b3efe, 0xf8daace7, - 0x0c3f8f01, 0x09309baf, 0x2bf3abd6, 0x3c1550e3, 0x130f01d8, 0x91c071d5, - 0x714352e3, 0x8375bac0, 0x1e3e04f5, 0xf9a5f38a, 0xe9ef10a1, 0x8a468e13, - 0x81b0bf2b, 0x905f0fc5, 0x568fdf23, 0x626b82e2, 0xd7d6fb74, 0xbee078bf, - 0xf175f1e6, 0xa1c63f34, 0x5f051ba1, 0xf323575d, 0x846327f7, 0x85b7646f, - 0x0a549bee, 0x4f2cfbfa, 0x997dc0c4, 0xbe234ed6, 0x55d8a293, 0xdc5dbe7c, - 0x8af5d6df, 0xf5a27188, 0xbf907b2d, 0x3547f9eb, 0x8fd1473f, 0x6f1f2377, - 0x1f931b75, 0x3ead5b5d, 0xb5d3850b, 0xeba44dfb, 0x189dcdea, 0x79bfbaa7, - 0x7543b19b, 0xc3f20cfe, 0xd77f1aa7, 0x22c6bb6b, 0xa2efe73f, 0xcad9fbe9, - 0x3f8d63f9, 0x9b353f72, 0xa9fa6a2f, 0xed18b6f0, 0x3bfbbe96, 0x05eeb927, - 0x99dae778, 0x45ae751e, 0xd08be69c, 0x6462cfff, 0x3237576e, 0xa395383f, - 0x959c3ef8, 0xda2707bd, 0x5b2f51a2, 0x0c749d66, 0x665d21de, 0xcc5c6235, - 0x471e3aca, 0x326723f3, 0xeb4af7ac, 0xbbc604ed, 0xb2abf01a, 0x9bbb65ef, - 0x27273e80, 0xcfaa6517, 0x1bf19461, 0x4f881807, 0xd3ad8fbd, 0x4a7d8206, - 0x1850ef24, 0x7f699dc7, 0xb62e4095, 0x9f7f987b, 0x02313d5c, 0xf64bb7be, - 0x6e14097d, 0x04e0be7b, 0xba4f6cd7, 0x7e43f067, 0x1df69706, 0x4753bc5d, - 0x69c977e7, 0x6ad13d40, 0x1569d808, 0x4f6a8d62, 0x41d70346, 0x5e12521c, - 0x8978c0a5, 0x11e63cc7, 0x46d43f70, 0xf50adaa8, 0x5de6929c, 0x9249d895, - 0x72159dee, 0x57a50478, 0xc557a70b, 0xff65675f, 0xf03b70a6, 0x0cb896fd, - 0xbbe40752, 0x7d46ead6, 0x0b9b29e2, 0xdfd23fef, 0x88938868, 0xf54ed127, - 0x5fb450bb, 0xda3b7dcd, 0xe71f26af, 0xa613e6d2, 0xc9232749, 0x8e3e049b, - 0x7882d102, 0xe06a9b88, 0x70abb2fa, 0xdc785264, 0x19c48971, 0x2c3bf280, - 0x6e808f78, 0x1e7aaf2f, 0xdc768b16, 0x3e1a7c74, 0xe1d19b11, 0x6a71b035, - 0x0389dbbe, 0xe3a747df, 0xaf1bae3d, 0x70b56f26, 0x0911277e, 0xdcc59df8, - 0x2ffe384e, 0x4abdf069, 0x224f8a2a, 0x38c2644c, 0xde2130e9, 0x83cf9625, - 0x6fa9aff6, 0xeb01ef07, 0x0c870b5f, 0xb5efabb5, 0xe0e5c0de, 0x8a514b11, - 0xac93ee85, 0xb818b5e1, 0xb82c9d9d, 0x65a04e4e, 0x9fc801fe, 0x61e796d2, - 0xc8d08a5c, 0x5ac46ae8, 0x4466fb82, 0xad55c790, 0xd53d468a, 0xa8de2664, - 0x8e3f70f1, 0xd0f1e578, 0x3f9f8f8b, 0x28185639, 0xa50d6928, 0x1fceda35, - 0xa62c35cc, 0x4502d08b, 0x8b10fe14, 0x5ff40c6b, 0x6c9dc33f, 0x1bd30718, - 0x2877bf56, 0xc16bdaee, 0x1ba86863, 0x14c0ffba, 0x2ef82164, 0xdd0ef108, - 0x51b8720f, 0x0ec653c9, 0x463406ef, 0x332ef287, 0x698df7e5, 0xdaf37f2c, - 0x7ef0f5a1, 0xe8bda74d, 0xc78c0b66, 0xcf0ebf6c, 0x9af102c3, 0x937bd5f7, - 0x4738ca2f, 0xc1e40c6f, 0x07b7c7fb, 0x23c5fbd9, 0xfc7ba1ad, 0x59378f28, - 0xed007c94, 0x43d6a28b, 0x5aaad7c8, 0x01b9610e, 0x9e1d34f2, 0x421bc810, - 0x65bf79e7, 0xb5f2414c, 0x716b5e14, 0xb1c13c32, 0xbf6632d0, 0xb8c3c1a4, - 0x61d9bdfa, 0x6e2b483c, 0x86e1e1d0, 0x858785af, 0x87a86f6b, 0x3bfa55f7, - 0x0b174a6f, 0x73d35f00, 0xdb8ef80c, 0xf41663c4, 0x145fd0bf, 0x670e23ca, - 0xbcf72f43, 0xc2853b15, 0x97d35729, 0xaba14ed2, 0x9d26e8de, 0xef63afd8, - 0xe7e96a83, 0x87ae2ddf, 0x8b32de00, 0x8896dd2b, 0x0577c7f3, 0x8b8bbba6, - 0x74c213f2, 0x09ee2c4d, 0x11feaef0, 0x5a1f82cb, 0xe9dafe54, 0x34c54b39, - 0x011fde3a, 0x3c31b823, 0xdee5c49f, 0x9e7451a8, 0xc6032e89, 0xb8b11fd5, - 0xdb3b4057, 0x6200609c, 0xf71226cb, 0xf70c4104, 0xfa8feca3, 0xaf8ecc1d, - 0x56f8362f, 0xfc60f3b0, 0xfa611dbb, 0x47d1d0e8, 0x5b47d190, 0xb547d227, - 0x47d193bf, 0x346e5d5b, 0x3b03573f, 0xc70491ba, 0x5937bac1, 0x61a40b0a, - 0x82626e94, 0xb23740f5, 0xc282b6f7, 0x3aebc428, 0xf58f5f18, 0xe652e3e1, - 0x36fadbd5, 0x71fb481e, 0x0799d806, 0xa61e780d, 0xb7a94de0, 0x46e2c2c3, - 0x7ee6cdff, 0x99a9fa11, 0x961fb1d4, 0x3f81eb6f, 0xed875c60, 0xd05dcce0, - 0xae9b36de, 0x6fdc2390, 0xf815c1e3, 0x7f23784e, 0x04963bd7, 0x7bd720bd, - 0x3fdb07c7, 0xde807c21, 0xe8f80193, 0x0af2fdc4, 0xdd9667bf, 0xce40b826, - 0xef618f0f, 0x616ebc90, 0x16bbf576, 0xaf4ca791, 0x5bb83c49, 0x7b2bfb04, - 0x27eb0195, 0x9ea19a42, 0x5f5e2aff, 0x95ddf8d2, 0x89e85575, 0x7818d272, - 0x78f9e4cf, 0xfd2d1ef7, 0xa9a4c7c4, 0x1eed29e0, 0x45a290f7, 0xee265094, - 0xc810f05d, 0x3e3f4a55, 0x7231bb4d, 0x442de014, 0x233e943f, 0x776d0fad, - 0x7c6bad88, 0x5b0be80c, 0xf1152ef6, 0xae7e8e5d, 0x47bc166b, 0xc567eb49, - 0xb4adda90, 0x4d2c567d, 0xf3c09f21, 0x087e7903, 0x743fd34b, 0x7dfa041a, - 0x9ecbf703, 0x922578e5, 0x6399bafd, 0xb8f4cf20, 0x9418e4ec, 0x85beca0b, - 0x5ce05467, 0xdbe7e25b, 0x0334c169, 0x8fb29bac, 0x6021a0a5, 0x4d2b42a5, - 0xce201872, 0xbb8f5de1, 0x7b0bce08, 0x5fb73be3, 0xea81eecb, 0xc7ce7fbf, - 0xebf58df3, 0x2fb8f4bf, 0xb7e039fe, 0xf8f1dcca, 0xbeaf9a4c, 0x69fa32f6, - 0xdf54c457, 0x68ef55fc, 0xeeffc7e8, 0x00c4dfd5, 0x333ffa1d, 0x353fbc45, - 0xf1e8cace, 0xb60e6780, 0x04efe2cb, 0x1c4a8192, 0x15ce2ab2, 0x865eb8ca, - 0xdf86994b, 0x05bacf51, 0xa7ac2059, 0xf6878a57, 0xae78a931, 0xae2eab78, - 0xbb2f3955, 0x80fcc025, 0x42beb159, 0x74faefec, 0x3e49f7f6, 0x9992fa63, - 0xa1ce0ffe, 0x3373f2a6, 0x5efb31d7, 0x09598710, 0x3f08f98d, 0x5afd1536, - 0xfefb4439, 0xaf40d641, 0xf4f28064, 0x67978454, 0x13a795d6, 0x6b915bf4, - 0x4df9c3ae, 0x0cfd2a25, 0x13a346e5, 0xd1f4f1f8, 0xf7f9fe94, 0xe1bff4cb, - 0x867f3226, 0xcdb8ceca, 0xbe515f71, 0xc4696f46, 0xfb7e8577, 0x523f38b9, - 0x2163c5fc, 0x4115173c, 0x8f1e803c, 0x95610eb9, 0xdf13d1d5, 0xf1e9fc7a, - 0x8f51e0ad, 0x9d0f9cb7, 0x9e8ef1f9, 0x23e3d1f8, 0x5be97e7c, 0x7530eb0b, - 0x4bf288b4, 0xfc4f7bc1, 0xedfaf5b0, 0x009eb4b5, 0x0df142f4, 0x30174cf8, - 0x862b27be, 0x3a6c4fd3, 0x140b37e2, 0x0f4801c0, 0x55e3d798, 0x04acc78f, - 0xd5813ede, 0x1af80fdf, 0xed00fc89, 0xb2dd6521, 0xc6f76bd2, 0xe8c4de41, - 0xa7abd14c, 0xbd50bc72, 0xbce6f51a, 0x9bfa2b44, 0x9a9eaf40, 0x5e5bc614, - 0xde571b15, 0x600bcb48, 0xfc0afe9f, 0x0608b1d1, 0x95bcc5df, 0x56e05ff0, - 0xe2ca5f3c, 0xb7df0559, 0x93d5a67e, 0xce0bfaa7, 0xdc3dfe82, 0x05655ee4, - 0x87108c7f, 0xff1479e7, 0xd7f875c7, 0xf36bb3b6, 0x0afc7c7a, 0x27b931fe, - 0xab7a14de, 0x7cfd72b3, 0xfa0a1930, 0x3337d8f2, 0x137f8163, 0xbf447c7f, - 0x4563c4c4, 0x6e9c3821, 0xe2059e91, 0xa7b77d0e, 0x763e0b7f, 0x15494a90, - 0x7253bb1f, 0xd8deb3af, 0xeb298f93, 0xc7af8535, 0x05dde214, 0x4429a67e, - 0x1ec84bfa, 0xffcf0d48, 0xb3f72b79, 0x6043210d, 0x1c585f9e, 0x79f3ff8c, - 0xd54de686, 0x9b3fe84b, 0xb66d9ff7, 0x121bfde0, 0x7842ba94, 0x93f7c34e, - 0xf0f8c6bc, 0xbd656438, 0xd3096a53, 0xfbe2e6e7, 0xe42f14d9, 0x38f098cb, - 0x090559b6, 0xe3e20fdf, 0xf66cdf38, 0xd3db9c42, 0x2b0dfb92, 0x83843df8, - 0x527e7163, 0x3fc81460, 0xb6e5f97d, 0x4e50d5bd, 0x3d6095eb, 0x910afe3e, - 0x3b821ff9, 0x5217be4c, 0xe953d77b, 0xa13946f6, 0xdc3671d0, 0xe801bd7b, - 0xb8c2283e, 0x655cfcfd, 0xcf7645e7, 0xabec45c1, 0xf6f0a7ae, 0x02f7625d, - 0x81db28f2, 0xedfa7a7a, 0x49f34e8b, 0xd3b41e70, 0xcf22abd3, 0x5bfdf81b, - 0x68bb3f45, 0xeb0fbf75, 0xe3efc0de, 0xba8e2ffa, 0x1be7d60e, 0x2d61d5d3, - 0x44f4295d, 0xf438ebe9, 0xf1f99dd3, 0xdfcb503a, 0x049cbccb, 0xe3d151f2, - 0xeb8afac3, 0x9bd7a863, 0xe6dc3f3e, 0x857eb2ee, 0x35e8af3e, 0x6423d97d, - 0xd34644af, 0xebe3ce71, 0x2edcd733, 0x41c68bb3, 0x886fd38c, 0x73cbde56, - 0x393e8344, 0x95ed21af, 0xac573866, 0x07f97e63, 0x3d8d656b, 0xbedb86ec, - 0x67bd9ed8, 0xb6b97f3b, 0xef8a23fc, 0xcef8f141, 0x868ed6ad, 0x7e1491fd, - 0xbf67b7cf, 0xc9c82f06, 0x31a32379, 0xafdf4e7e, 0x7efa7e7e, 0x7035fdf5, - 0xd8c1aafb, 0xd2a9da38, 0x1636ec4f, 0xcd697d47, 0x14f0cd93, 0x73f86f5e, - 0xd4b8879b, 0xa3ae6f7f, 0xa44e7a21, 0x781468f7, 0xc2e7be0a, 0x0fe098cb, - 0x1eff95a8, 0x6cdd9de9, 0xf413f337, 0x6088efd6, 0x8683ea3e, 0xe82203a7, - 0x048223f5, 0xa0ecf0f5, 0x6350b0cb, 0xb97b300f, 0xef003d87, 0x657cd0a4, - 0x0f662eeb, 0x5da1d4b4, 0x0aed4951, 0xe01b3b90, 0x7cc1901d, 0x27681940, - 0x885eec84, 0x7786caaf, 0x0c5db932, 0x37a5a74f, 0x1f33fab2, 0x8c35374f, - 0x9dd5bb00, 0xce932f0c, 0xa8fb5db4, 0xf557da99, 0x508a24a9, 0x76c8aafb, - 0x4ed677ed, 0xde3bdca2, 0xa4bbc025, 0x65a8ff34, 0xecedff72, 0x8fd1b699, - 0xda81bf82, 0x54d9b767, 0xfb6f6f76, 0x039b66e3, 0xfedbd9f1, 0xcd17b4e8, - 0xdf8a3804, 0xe421f282, 0xbe28fe07, 0xf442a3ff, 0x53780b17, 0xe5f6e5e8, - 0x88ced10b, 0x0a6ae6ba, 0x736593c4, 0xb8db703a, 0xc186365f, 0x706189a9, - 0x376e4a26, 0xfbbdd3f4, 0x3bf028ea, 0x04fa3bbf, 0x2b7e79da, 0xf41fdbf3, - 0xe3a91594, 0x026d6bdb, 0x10c097a7, 0xdc777fd8, 0xec0127b8, 0xc0596c95, - 0xb2fd4ef7, 0x99f1e9ef, 0xdb669fc0, 0x6629d257, 0xfde2364f, 0x60547f32, - 0x3d2ac3c8, 0x4ddfcfce, 0x3fdc5ff5, 0xdcff1d44, 0xb5abcd6e, 0xc022f831, - 0x7bdccecf, 0xde80f40c, 0xae584ee4, 0x2b9004b8, 0x24a1eae4, 0xdd6a5f3c, - 0x689f0367, 0xe0e77f17, 0xa49eeb7c, 0xdaad3405, 0xb0369ff2, 0x3e38eae3, - 0xf8ed4bce, 0x76e5535e, 0xa113df11, 0x003d26fd, 0x85d6eb7e, 0x1fdeec59, - 0xc8a6afbb, 0xef9ff1d5, 0x9cc45219, 0x4cff7889, 0x98a737d1, 0x9f183ebd, - 0x1dfd8ebf, 0xf7ba29cc, 0xefe56ec9, 0xcff5e993, 0xe2b26c67, 0xa9f8c32f, - 0x4fd67665, 0xfb2bfb6f, 0x53e204b3, 0x296cbfed, 0xb3f8c220, 0xefc24b3f, - 0x3da40fe7, 0x3df60855, 0x01239d91, 0xa2f644ac, 0xa7cfcb7e, 0xbc2f6fe8, - 0x6793be7b, 0x3cbd6ede, 0x6e2466eb, 0xd004d72a, 0x9803dcc7, 0x07c991d3, - 0xf5bbff45, 0x55dfad33, 0x722b07af, 0x6e3fd732, 0x780210d5, 0xfbc2cc77, - 0x8c240713, 0xc9ebd2f7, 0xbd058353, 0x204fc3e8, 0x4d6d6d7d, 0xfe7b018f, - 0x009f60df, 0xc65eb6dd, 0x49aa83f7, 0xc7781ee0, 0xb455baa9, 0x24fc6007, - 0x67d87af3, 0xe0a13e8a, 0x1eeaeda5, 0x7fda58f3, 0x7d8345f6, 0x76f10505, - 0x57682ff0, 0xc1fdf84f, 0xfe679004, 0x07e784a0, 0xc6f717d9, 0x45f1542c, - 0x7e0355ff, 0x6eeafb7f, 0xfc60f7ed, 0x8b6ed0f5, 0x7bcbd981, 0x063dfff7, - 0x57dbd4f8, 0x90bc212f, 0x6f53d13e, 0xcf3bfd46, 0xd1fc862a, 0x8899bd6a, - 0xde2187d9, 0x152c6a6b, 0xfaef426b, 0x6487ce70, 0xd4f49595, 0x2778422b, - 0xd0f0092e, 0xf0561f43, 0x3e33d3ac, 0x773d71b2, 0xef0f1918, 0x4d5db65e, - 0xc77bc0a8, 0x0afb18fe, 0x8f4ccf94, 0xee7bdeea, 0xfdf0e9c9, 0x9ddec8a0, - 0x7ee22ab8, 0x62b3bdda, 0xdf6a8778, 0xeb8a4e52, 0xc5d06576, 0xfad16f0b, - 0x3345f657, 0xbce4baff, 0x224f7d5e, 0xf1c7df5c, 0xcecc1815, 0xe183bce9, - 0xac6fa8bd, 0xb0f574cf, 0x4361fff7, 0x0058393d, 0xfad462e2, 0xffac234e, - 0x3e8ad9bf, 0x25a5fc67, 0x978bf806, 0xb4210ee4, 0x9268b2df, 0xac15740b, - 0x33b07623, 0x18301fb6, 0x37325d60, 0xcf5c62a5, 0x731cfc2b, 0x31a34b49, - 0x4b174555, 0x19d839f8, 0xaf129bd9, 0x9632befa, 0xfb3397f1, 0x71817fca, - 0x91347f1d, 0xd0f41191, 0xfe4cb185, 0xa77a336e, 0xc77a866f, 0x68df780d, - 0xef5ffeef, 0x97937787, 0x038c731c, 0x5894e0bf, 0x0eda0fb6, 0x710f52be, - 0x821f6dc1, 0x6672a2d4, 0xa068b163, 0x1c45befd, 0x9877afcc, 0x90d6bdfd, - 0x12b8943f, 0xc5379e60, 0xd6fdbe32, 0xdce68301, 0xbefe2dec, 0x8cb1f5ef, - 0x32c6a50f, 0x03d6dabf, 0x700b09b9, 0xc447b9ff, 0x64f01f82, 0x456c3d47, - 0xe8a80fc5, 0x6f0f936f, 0xfe863e9d, 0xc1977273, 0x38edcb0e, 0xf30882fc, - 0x24219c75, 0xf43d204e, 0xac6f0a39, 0x5d5bde1a, 0xc71d1e0c, 0x0aafd86e, - 0xfe04a9fe, 0xbfcd0671, 0x43c52ed5, 0x7f82983c, 0xff4a1e65, 0xdae2168e, - 0xe4adc160, 0xfe15fada, 0x31efe568, 0xe513b04c, 0x5d2033ef, 0x6eb9b76e, - 0x6f72c589, 0xeccfe40a, 0x36d27a63, 0x72494f2e, 0x9fc070f1, 0x79f34eb2, - 0xb7a78caa, 0xe3e7effe, 0x4bafd254, 0x0ec8afd7, 0x76cdd22f, 0xf0ee4f16, - 0x10e9cc06, 0x8e96d677, 0x154a9f7f, 0x8e3f7b97, 0xfdf68cff, 0x830eb6c2, - 0x558fee01, 0x50e210ef, 0xbea7eddd, 0xa933a21d, 0xedafe905, 0x5c7dc118, - 0xe65dfcde, 0x9f72a48f, 0xe786ebbf, 0xf87fb0eb, 0x8120fb39, 0x1bfd93a6, - 0xfc410e56, 0xafb06c06, 0xfba278c2, 0x46dad206, 0x92ebd023, 0xe52d2c65, - 0x9a4bd5e7, 0x4b3fb8dc, 0xc478b3d6, 0x4ca9b165, 0x257a733e, 0xf8c1e886, - 0x7b4dbade, 0x5c1ff08f, 0x7d6d9e7e, 0x4bf40f6a, 0x80fbebe9, 0x9eda9b8f, - 0x55c30758, 0x46ecf5e8, 0x4594e119, 0x3df3cf6b, 0xb8cfccb1, 0xf7a330fd, - 0x5ce51bc9, 0xb26c4f78, 0xbfc1d897, 0x4dc6d6fd, 0xb7eff022, 0xd9539e80, - 0x7b79073e, 0x3163df66, 0xd6f907df, 0x47e02069, 0x652466df, 0x62fb545b, - 0x343786ef, 0xb9bcb7fb, 0xebfa3a6e, 0xe005e23b, 0x55becaf3, 0xe8cdbef0, - 0xfff70dbc, 0x9ffdba9d, 0xc2b7dacf, 0x4f7ad0ba, 0xd4fffdf1, 0xe9ffba34, - 0x718db8a7, 0x66d9c002, 0xdccefc8c, 0xfe90df4b, 0xa3b57c42, 0x297d5f07, - 0x6c1ff996, 0xeaffb4e9, 0xffa12e3b, 0x4e3e3421, 0x2be54f37, 0x002a9374, - 0x0ae91bfe, 0x517c008e, 0x533d02bc, 0xccfe7a3d, 0x0795dc0c, 0xe1ff3c24, - 0x2e3c4be7, 0x6a947704, 0x99f986bf, 0x6fdd6fb2, 0xf2b238c0, 0x9e82576b, - 0x45e8509f, 0xb82b3cfa, 0x7953c787, 0x71f61676, 0x8eb07e04, 0xec8ae3e3, - 0xff7debee, 0x65cf40c1, 0xf98462d4, 0x1d82f590, 0x772945d6, 0xbdef67ac, - 0x94f0e61e, 0x2dbf87ef, 0xde3d83be, 0xf0cc3d21, 0x5c42341d, 0x931f28eb, - 0xc5c84463, 0xb70c40fd, 0xb67d860f, 0xfbafca84, 0xacebf255, 0xaa7488dc, - 0xce23e1e0, 0xb1c4aeb7, 0xc7ce3f79, 0x5d1f07e9, 0x82ff0aa2, 0x3f6c0924, - 0xe7db028b, 0xbb3fc022, 0x90dba6ef, 0x4c88efde, 0xb7b076ef, 0x47efe1e2, - 0x8cfa406d, 0x7bc7669b, 0xce494f2f, 0x7e8d38a8, 0xef74c3e4, 0xced067a6, - 0xfd85fa03, 0x97fd1bde, 0x0893fd01, 0x74a3ef74, 0x853f5aaf, 0xfc5d280e, - 0x7ca5f01d, 0x7285d3d7, 0x65e0a90e, 0x731cee9b, 0xe9e19daa, 0x8d5200ff, - 0x8000b56e, 0x00008000, 0x00088b1f, 0x00000000, 0x7dbdff00, 0xd5547c09, - 0xf37df8d5, 0x3332c966, 0xb2764c99, 0xa00c4930, 0x80490e2c, 0x084ed8b0, - 0xc3884a20, 0x93a0d752, 0x364b0900, 0x94569510, 0x8b062081, 0xb62d1518, - 0xef858320, 0x106d1b43, 0x268358a8, 0x622d1110, 0xa57fb1dc, 0x41459041, - 0xed1fa822, 0xe73bf587, 0x33337bdc, 0x6a02266f, 0xefc7e1ff, 0xdf77dee6, - 0xcf7ece5d, 0x6ec5f739, 0x843631d3, 0xae630731, 0x7d8c01e6, 0xf4bf3f8f, - 0xa12d8c97, 0xcf3773e7, 0x8224715e, 0xf0f7cfd1, 0x5e79babf, 0xc776bd50, - 0xe91c57af, 0xc5cfafe7, 0xffe0525f, 0x8967a671, 0x47f1558c, 0x89ef4cac, - 0xfbc025b5, 0x6cd69d11, 0xe266b498, 0x03846319, 0x8319789f, 0x1c636ff6, - 0x6faa3e54, 0x1f2bd3de, 0xe9cc31ca, 0x9b39a685, 0x998f1533, 0x1b3605b1, - 0x27f967ad, 0xb0dd93d3, 0xc6c646de, 0xc59bbae3, 0xd9dd727c, 0x99c68536, - 0x8f7329e0, 0x66678389, 0xa07b9e4f, 0x6607f9ff, 0x886d964f, 0x70a13ebf, - 0x4018eabe, 0x7ec48c4b, 0x0c985563, 0xc9bf9fe6, 0x326533e4, 0xc49f05b6, - 0xa3db2ac3, 0xfd329b7c, 0xccf4d9ef, 0x9633b7a5, 0x75a4cb6b, 0xb15aeac1, - 0x646858ee, 0xdfbcc197, 0x9bb59666, 0x1dd5d1e1, 0xb081e2de, 0xef462d8f, - 0x389989d4, 0x1c1af398, 0x9d629aff, 0x6a5801ed, 0x38a6cbac, 0x6992d007, - 0xcf8fb65e, 0xeced9793, 0xeea1b2cf, 0x2db9e670, 0xf8128d8c, 0xc930ad62, - 0x421c3f70, 0xd9e1c6f1, 0x20175e13, 0x1750867c, 0xd5e27e7a, 0x667d1ba8, - 0x0144f3ff, 0x78632fbf, 0xd3c1adf9, 0x1d0e66db, 0x553e6027, 0xcacc6649, - 0x5c554b3c, 0xdb6628ff, 0x773ff0e4, 0x1c2e628c, 0x57189a7f, 0x8ffacbb6, - 0x10aeafa6, 0x78869afa, 0x22e88ead, 0xd053eaba, 0xbcc07469, 0x8bdd194c, - 0xee98fac1, 0x80ac5eda, 0xbd71eaba, 0x29554800, 0xf6c7ebe0, 0xd7338d84, - 0x01d99e23, 0x0cc9cb13, 0xcdb567dd, 0xd1b6e1c0, 0xe866fa30, 0xb865e097, - 0x838bc003, 0xde3585e3, 0xdc6bf88a, 0xd7886268, 0xdc39636f, 0x68d953ac, - 0x42b7f403, 0xc6f7247f, 0x57039ea9, 0xd931bd41, 0x9e6050e8, 0xc22e8613, - 0xa0ab89fb, 0xadc3e88d, 0xbc4fbe20, 0xdf9ae23a, 0xa277bb40, 0x8bc0e58e, - 0x05b08d5b, 0xa7bfc3a4, 0x482936f9, 0x27c42da7, 0xc1b2c7f3, 0xbede7826, - 0xd5d11869, 0x052ce2ac, 0xe6ce76e9, 0xdb9f0558, 0x2a74d8c7, 0xd863eff3, - 0x13e89542, 0x16dea0f8, 0xde618f80, 0xd5e1153a, 0x6c93ce3b, 0x11ec6588, - 0x23e335db, 0x32ce81d2, 0xcc1b2459, 0x5f5043d8, 0xb46b7009, 0x4b1614bb, - 0x0a7306f5, 0x236321f1, 0x0cadae08, 0xd518d4f0, 0x6045775d, 0x7f5e2cff, - 0x86eaf1a4, 0x9ec63486, 0x22357189, 0xbb303e9e, 0x87f9c11f, 0x44a9d526, - 0x7fae82e7, 0x127ece80, 0x2c2ed4bd, 0xe0f38762, 0x0e660ef7, 0x47901ba4, - 0xf8066eb7, 0x9b3de895, 0xbd355d70, 0xc38e3e8e, 0x657cb6d5, 0x7ba184f4, - 0x21788eb9, 0x8cc7d817, 0xaeef11f0, 0x7ecdcb53, 0x66c5b3b9, 0x52ed4c17, - 0xfcfc5b26, 0x79eb7286, 0x593b9733, 0x98229a50, 0x7ec762d7, 0xac23a23e, - 0xe5fae4c7, 0xdd62cad1, 0x3e185f78, 0xeb890d7e, 0xaccf9467, 0xf2ff7fe5, - 0x1fd0a19b, 0x9f89577f, 0xc4fce35e, 0xc5a3f5e5, 0x3c22269f, 0xbdf09390, - 0xeb1cc5db, 0xeadf3a97, 0x5fb9748b, 0x3ea09b65, 0x2af464d8, 0xe66db831, - 0xf18a25b0, 0x945b0d90, 0xa820cb56, 0x2e614bff, 0x7fe9c3c0, 0xbfae54a9, - 0x133e3dd7, 0xa1d9afde, 0x7e852e73, 0xf10a2d35, 0xf337b383, 0x371d0045, - 0x31075947, 0xb770af18, 0xf68065d9, 0xc9044ad3, 0xd7009c65, 0x2feb9061, - 0x8268cae8, 0xc02df5e7, 0x5d3d507f, 0xf5c6a808, 0x6c319dea, 0x83be1f80, - 0x1fb47cde, 0x1bda00ec, 0x4f67c89d, 0x9ff1f245, 0x81f0cc8a, 0xbe528310, - 0x4a0188e7, 0x6e825961, 0x62c67af4, 0x78504f00, 0x30b51cb1, 0x3c07a5db, - 0x35e67a2b, 0x7546be00, 0x9f08aab5, 0x8e872eac, 0xe9f3fd99, 0x3bed18bb, - 0x39d0ef4b, 0xd6d5f403, 0x7aabcfbd, 0x31d0eb80, 0x942af58d, 0x6f9e3189, - 0x4623de10, 0x7b63d5d5, 0xf557b15c, 0xa57cff40, 0xe905b76e, 0x44e61aec, - 0x24f92ab9, 0xc1b593ae, 0x81ec5972, 0xda15974e, 0xb5771c47, 0xc7fd800d, - 0xe38299b8, 0x7c0dfd49, 0x0e9162c6, 0x44ca5de3, 0x3fe86718, 0x8e47c118, - 0x68ef75b3, 0xbe3ef905, 0x18e28c63, 0x6be74a10, 0x38b7e398, 0xce9f77ae, - 0x3475f889, 0x9406d733, 0x62ba7f13, 0xf64bc20c, 0xf5cb1def, 0xa78f48ca, - 0xee154408, 0x1de70627, 0xb76fa37e, 0x6c33d601, 0xd1b77796, 0xd99fb011, - 0xed4bc68c, 0x523ed2f4, 0xb10a780e, 0xd2c6b6cc, 0xb78e2338, 0x7e800db6, - 0x1fb07549, 0x78ef4f68, 0xa6b8414f, 0x882875d7, 0x777badcf, 0x3ad37ad1, - 0xf82979da, 0x176179eb, 0x5603db74, 0xdb23ed1d, 0xf2cdf5ca, 0x666f5c53, - 0xadb27ac7, 0x2c7dfe09, 0xd724f42f, 0xf66bf8c1, 0x17ef7566, 0x2895eee5, - 0x52e403e4, 0xc691ac6e, 0xe9eacbb9, 0xbdabfb8f, 0xd20f73b1, 0xdf7bf3e0, - 0xb47f12b1, 0x137e13c4, 0xf84a7df7, 0xba485c48, 0x37d9ad98, 0xb179415f, - 0xa67014a6, 0xca59c284, 0x7eb8358d, 0xf45b1fa2, 0x27cfa024, 0xd8829eed, - 0xcca57b40, 0x20159d1e, 0x8f7be497, 0x19ee662f, 0xed6190b0, 0x16595be5, - 0xb17ef7c9, 0xc27df201, 0x9122fbc0, 0x2e2c9a9e, 0x569fb617, 0xcf388dd8, - 0xfb425833, 0x975e0633, 0xe0407af0, 0x52763b33, 0x870875b6, 0xf8e80d93, - 0x4fde4899, 0x8dee8f2b, 0x83bb09d5, 0xe0eb0bd3, 0x08fb82f4, 0xc666bfb4, - 0x748c3c72, 0x9cf48a79, 0xfee2a64e, 0x76f81786, 0x1b0edd23, 0xf48dddef, - 0x9d04ce9f, 0xa274e78c, 0x63dbf7a5, 0x711d7cb9, 0xdc218bbc, 0x0ee615f3, - 0xc654ef67, 0xbe29bb72, 0x0fd13463, 0xce1943f0, 0x4eb53437, 0x66dca035, - 0x7fa809b6, 0xa0eb137e, 0xae05797e, 0x366f48dd, 0x79f89b97, 0xe9c6d9be, - 0x07d39326, 0x1c273fbc, 0x3e436d3f, 0xa3e7e01a, 0x7347a478, 0x26de3d28, - 0x011bf4e0, 0x3df1d0df, 0xf1f8e177, 0x02973a1d, 0x603b0c83, 0x3ae831f6, - 0x49e8016c, 0xf40653e4, 0xcfb40b0f, 0x9f2215b2, 0x153956a5, 0xb302ebc4, - 0xd7dc1efb, 0xf98d9472, 0x5f3acf48, 0x6c97bc3d, 0x7efe1173, 0x67689eb4, - 0x90686c11, 0x2c40f59d, 0x9557e3b7, 0xfa7ebca1, 0x53ca235b, 0xbdbfe487, - 0x01e5d1b9, 0x50c7f1f4, 0x0e123f7c, 0xa7395adf, 0x2e5fb7c5, 0x8039cb04, - 0x0f8e5ad7, 0x77c7e76e, 0x7cb9502c, 0x3d6b9608, 0x3e4423e1, 0xc1fc3c08, - 0xeb84daec, 0x4045c6cc, 0xfacd1de9, 0xfa4f7b61, 0xf358c5f8, 0x2f67b34f, - 0x8c5f8fac, 0xc7d5084d, 0xd7ae88ba, 0x75478015, 0x6150ea8b, 0xec8bf50b, - 0xfaffc42e, 0x7689c566, 0x9516eee1, 0xf2fd61e8, 0x729bd228, 0x8f6e5fbd, - 0x84aec419, 0x6b3ff052, 0x5a7d258f, 0x5fe62b1b, 0xfcc0bf06, 0xbabc6da7, - 0x3d79e6dd, 0x6fad0e50, 0xe11226f9, 0x71593fdc, 0x4abb411d, 0x85818fab, - 0x84df7814, 0xd70829bf, 0x322a0dc1, 0xad9ef5d6, 0xf6f09526, 0x8c378e2e, - 0x0a33be75, 0xa6a7f5d6, 0x7b40bad1, 0xaf8eeceb, 0xeb05dd6f, 0xfae68daf, - 0xeb9a36b9, 0xcebbd3e7, 0xbb7a41f7, 0x9274e176, 0x9ef4c37b, 0xdce5038f, - 0x730efd1b, 0x6d4acc39, 0xd4e3fb47, 0x68fbe52e, 0xa235a100, 0x0aed1e9f, - 0x06a9ca35, 0x1c4415db, 0x1f0039f5, 0x145b5f84, 0x073eafc1, 0xd6932ef8, - 0xd9d70279, 0x14b2316e, 0xfc0b3f68, 0xbae4fd88, 0xcf7ac47f, 0x9a6f5f84, - 0xa0b468ed, 0xbebfd50b, 0x1e20bc6e, 0xa2d57c60, 0x669c7da7, 0x67c44e51, - 0x10c5d1b3, 0xc283deff, 0xab78103e, 0xba773411, 0x0f01c865, 0x81fd6fec, - 0x7fbe2734, 0x48d9c77a, 0x47ed199d, 0x7d876a8f, 0x565de9a9, 0x5bbb87d4, - 0x39de5ece, 0xc19be480, 0xbb3beb0e, 0x33ddb0ef, 0xcfed47e0, 0xfd88bf6a, - 0x0dcdead5, 0xaa227681, 0x1a945259, 0xda5a523a, 0x220ca9fe, 0x0f2863fe, - 0x57cc19bd, 0x3e5efb0f, 0x54d3d050, 0xd7be40e6, 0xcdbb7be2, 0xe00f619d, - 0xb736cddb, 0xf385d703, 0x3ed2e6a4, 0xe83eb0b3, 0x0679e9cd, 0x0c6fee1d, - 0xed29bd43, 0xb44fb93d, 0xfd7323c7, 0x5ef693fb, 0xce73fef7, 0x68c7da0f, - 0x74ec83df, 0xc52c740e, 0x282d5a73, 0x03320785, 0x784adff7, 0xacfb16a9, - 0xaab7308e, 0xcdb62fb0, 0xca53b270, 0x7dd0ac83, 0xf3869e00, 0x780f387d, - 0x377fcf10, 0x4e11eb3b, 0xda1b0efa, 0x91afb0af, 0x50560fb8, 0xf8708c96, - 0x8c9aecc0, 0x2599fef2, 0xf4fae88c, 0x14f7ccb3, 0xbb4b7a6c, 0x0366e88e, - 0xffe882bb, 0x5b99dd0a, 0xebe266dd, 0x7e7ef8b1, 0xe50ea347, 0xa1cf8e6f, - 0x797ab943, 0x474eb347, 0x2f19e0f4, 0x0f5674e0, 0x54dfebeb, 0xba48fea7, - 0x2e9e1498, 0xabf6f042, 0xb849bc40, 0x30f4128d, 0x3286e10a, 0xb27f4bb9, - 0x370fc233, 0xb54b0bc0, 0x58c78e87, 0xa9c20667, 0x7d63c5ed, 0x9abc613a, - 0x8add8f97, 0xabf9a970, 0xcc618889, 0x418f2f5f, 0x30b2ffba, 0x72735dbc, - 0x0f5b9d71, 0x3dab78c4, 0x157be48b, 0xbda230eb, 0xaddd7200, 0xd2eb900f, - 0xe867db8e, 0xf7f1c628, 0x12d9510d, 0xe759f380, 0x461624b0, 0x3f72c85f, - 0x00396dda, 0xe155f47f, 0xfcc5e4f9, 0xda476e18, 0xb25afc83, 0x9678b7dc, - 0xe7a18c7b, 0x8e0df6f1, 0xb14e7f24, 0xc87a1ec6, 0xa78dedce, 0x81cf5ced, - 0x3ae17660, 0xe2c5fd4f, 0xa9d342f3, 0x0cadf7dc, 0xdb6a74e0, 0xa05e79bb, - 0xe3ac53a3, 0xdf9097f6, 0xb9d336be, 0xfbf078ae, 0x7e2c4b79, 0xfb8abcfe, - 0x2f55d852, 0x407569bc, 0xbb2de2ff, 0xf001bde3, 0xbfe98abb, 0x4ceba6ee, - 0x8fef979c, 0x20fb3be9, 0x274bd83e, 0x16501d12, 0x3c6af8bf, 0x373803a7, - 0x14ff450d, 0x633f8fe7, 0x5ddd8053, 0x3dc6b0bc, 0x1fc02f26, 0xf9922e73, - 0x0efaeb02, 0xab891e23, 0xfda999cf, 0x9e25bb76, 0xd62f4de4, 0x8f4de50b, - 0x7848baf0, 0x3c25db6a, 0x913e0df7, 0x97c5f681, 0x07c5d83d, 0xaf7ec1ec, - 0xdc7b1637, 0xf5fc7263, 0xdea77dbf, 0x5ef30ee6, 0xacff188b, 0xda127873, - 0xd6c6c57d, 0xe1f9c2cb, 0x0b5339e4, 0x57ce37a7, 0x7fb8e346, 0x1f1a6739, - 0xeddb5d6e, 0x3fe69fba, 0x0aab07d8, 0xf44b0bb0, 0xdced379e, 0x326ab05f, - 0x3f2e6bd4, 0xd9ce8e3b, 0xdc845e92, 0xdb798abb, 0xf4b57f90, 0xbefdf121, - 0x4b2a5bc4, 0x693dbc45, 0x11ba7077, 0x43f920fc, 0x396d470b, 0xe13cc8c1, - 0x75cf03ce, 0x799235c3, 0xbede1e41, 0xfe7a40c1, 0x4e1ff3cd, 0x3f7a03cd, - 0x5b60d6b6, 0x5ace530a, 0x51ed3bb7, 0x360da7f4, 0x1fa814d9, 0x865eb473, - 0x4eb95f7c, 0x1c3d2375, 0xe27b7b5b, 0x00bf2874, 0x7582adfe, 0x50306e54, - 0x770dacfb, 0xc109fb50, 0x12eb95d7, 0x7cbca3fa, 0x4481fdb3, 0xeface3c4, - 0xf11ebfee, 0xeb68c5b2, 0xaaca183f, 0x263dc526, 0x3673de00, 0xb7d50646, - 0xdc2cd8e8, 0x532bc487, 0x1dcfdd3c, 0xdc631eb0, 0x6b63c44f, 0x18d51f88, - 0x92ccedc7, 0x9aefb029, 0xbec96721, 0x8a27bddf, 0x662bc9f4, 0xd6c8ec95, - 0xb7f3ffc1, 0xf45ea12b, 0x3649de9d, 0x58f3c09e, 0xce866781, 0x8a8fa040, - 0x7a2f5e08, 0x68764f51, 0x78254591, 0x1d5c82b7, 0x65de4a43, 0x7efd0b1e, - 0x4753df21, 0xfd0e1ead, 0x1818c6c6, 0xb45fa1ea, 0xa06629ce, 0x4e797f27, - 0xc06769ff, 0x9733467e, 0x42e2ed1e, 0x5f6a0866, 0x0a7d6511, 0x4c185aed, - 0x28b0fa8f, 0xd8f9f822, 0x813daecb, 0x5b58c4f6, 0xbfa4bb70, 0xbfa0389c, - 0xb1b97efe, 0x8fe7cf7b, 0x567d804c, 0x9ec953ec, 0xde5c90be, 0x41cafb8f, - 0xda51bf7c, 0x29bdef04, 0xf9e6f3a0, 0x9052cb63, 0x86140abe, 0xe763ae7e, - 0x5ce5f3c3, 0x018c9f41, 0xf1f9fb9e, 0xbb39d13c, 0x7f6c8ebb, 0xeebcc15d, - 0xe2ffae3a, 0xcb0fd9e5, 0xf73b4eab, 0x87f5686f, 0x53fe7f96, 0xf078a3fa, - 0x0b5e19ab, 0xe585ff95, 0xfe5c2dc9, 0x5685e56a, 0x6975c85f, 0x4e7d5bd7, - 0xcf13d20d, 0xd7e27909, 0xfe7a4617, 0x6b8f9e33, 0x9e8486e2, 0x219ec18f, - 0xea877978, 0x760e5ce9, 0x6fd8edd7, 0x5711d980, 0x665a4b08, 0xb9468acb, - 0xdcf164d6, 0x97e01719, 0xa8d4dfea, 0xedd1f943, 0xfb0431af, 0xf5f9e46d, - 0xffbe389e, 0x875e38f2, 0xfb9d2bf3, 0x92794437, 0x2f6f38f5, 0x7e3033a3, - 0x85fbcb25, 0xaf7690fc, 0x9da577b4, 0x7d59ed2b, 0xb367b703, 0x7e41dd63, - 0x5fafd633, 0xed183f90, 0xef73e474, 0xe7da28ae, 0x107b8a67, 0x731569f2, - 0xa017143d, 0x7c0deb07, 0xbcf5dafd, 0x13ec2716, 0x413b26e6, 0x1d1ccfb6, - 0x8d6f9e5e, 0xc2ff53d3, 0x40ca6fc7, 0xb6b3ee3b, 0xce50339b, 0xfff1a67e, - 0x0f0fc4f6, 0x507d7e0b, 0xe15893e8, 0xf9087827, 0xedc0ea08, 0xfef02dae, - 0xe26ec58a, 0xbe2edfab, 0x1747ca91, 0x8fe7a42f, 0xfcd265c5, 0xdc77c2b6, - 0x23a700d9, 0x17d2552b, 0x3eee8d33, 0x91def0b1, 0x1bf91d08, 0xc799d70e, - 0x3b63336f, 0xcce5f3a3, 0xf26c27c7, 0x1f01f806, 0xe90c7dc3, 0x09af9f79, - 0x9d2a5ebc, 0x2b4eb356, 0x7a6eadea, 0xb7a2103d, 0xa72f11db, 0xf6226759, - 0xfa3a55ab, 0xf3a12934, 0xaf5cc83f, 0x2366bf61, 0xd37c8feb, 0x92f5c51c, - 0x029bdfb6, 0x9ed0ab7f, 0xd433f285, 0xcce4615f, 0x7b5e823b, 0xc4ef5d5b, - 0x9333bc91, 0x56eb4edd, 0x3ef44e29, 0xb4e707ce, 0xc639f10f, 0x975fd089, - 0xc775b56d, 0xc779f855, 0x185c71fd, 0xfe4f5c7f, 0xee3aed1f, 0xd570e789, - 0x296485fa, 0xc4c742fd, 0xd9c5167e, 0xe844fc82, 0x0fe70f0f, 0x48de3aba, - 0xd510dbfb, 0xa8b8c5e9, 0x3e7e66f7, 0x55e51a4f, 0x5a95dfd0, 0xfe8858dc, - 0x71c67fb0, 0xbc7da63f, 0xf1cf1927, 0x4e8d92bd, 0x2c5ce3f4, 0x76680e3f, - 0x478138f1, 0xd358eb47, 0x03ec8de1, 0xf0ec4aeb, 0x34a11a14, 0xf8d226c4, - 0x096eac49, 0x11fa0de2, 0xa3dbf230, 0x743c8a7c, 0x213c9743, 0x91a56147, - 0xaddb77c8, 0xbc3c531e, 0x5d467437, 0x53edfa3d, 0xe23c78ab, 0x6de9e284, - 0x1b8d0ecf, 0x5e3932cb, 0xbb88aff0, 0xd0346fe6, 0x3e37f2ba, 0xfcd1f146, - 0x95eb578d, 0x1f943900, 0x27fea06f, 0x9bd39d5e, 0x851f18fc, 0x880ebf8f, - 0x4662f4e7, 0x8a10e11f, 0xbfa58687, 0x313ff17e, 0xf609dcae, 0xef3cb050, - 0x20243f17, 0x0cfaa16f, 0x3c7d73c9, 0xc07f23d7, 0xd358057c, 0x7cc8661f, - 0x8fe40d85, 0xbe6c6add, 0xde51e306, 0xbc431d1a, 0x2bf9efb7, 0xcd676bc5, - 0xb6bc5070, 0xcf7dfdfb, 0x3ff6c72c, 0x118362cc, 0x87be29fe, 0x7ccff415, - 0xc9e3c91b, 0xb1326edf, 0xd9a5b025, 0x3c53376f, 0x8e954d78, 0xeed17ca1, - 0xe832661b, 0xa0db5c78, 0x47f8e02b, 0x0ef12839, 0x7c446404, 0xfc21bc48, - 0x6e3198b6, 0x5fad02fc, 0x7e80cbae, 0xc7dc04f0, 0x4e906b96, 0x15d9557a, - 0x75c817f4, 0x4c9f485d, 0xfa69ff8a, 0xc3d467e4, 0x9c5fc5b7, 0x74819e1e, - 0x5ac3d5ae, 0x7164dbfd, 0x0bbf6255, 0x4213e1e9, 0xd7894dfe, 0x7e3043c4, - 0xc76f0616, 0xf00c1c84, 0xff19df8f, 0x1fe3fc23, 0xe3091ca1, 0xc8c67f1f, - 0x9da36fe5, 0x0c2936dd, 0xe627bcbf, 0x32eeadd7, 0x6f8cfea2, 0xb3cac251, - 0xc651ab6c, 0xfae05713, 0x2b44fc64, 0xb7c0c38f, 0xde5ffb11, 0x7b0bbad4, - 0x165ec6e5, 0x15dbe68d, 0x37b9c3df, 0x046b3ccc, 0x30163b9f, 0xea3aa38a, - 0xa82bc918, 0xb093b8fb, 0x0023f295, 0xb8e04f1f, 0x9d638a17, 0x1d9215b6, - 0x8656e324, 0xf8f3e0d8, 0xcfd9789e, 0x6fc447f5, 0xe27a0f7a, 0xb05d624f, - 0x5fb067ff, 0x141602fc, 0x9971919f, 0x62af3af8, 0xc47547cc, 0x3bdadfc8, - 0xf304b3ce, 0x3386ba3f, 0x8f5053e7, 0xa215b529, 0x72cfb53c, 0x66fc61b6, - 0x9fee29f9, 0xf98f3e5f, 0x79012a96, 0xca2c9e05, 0x05bc4203, 0x0a7607fa, - 0xac53b6f9, 0x5fe4f41b, 0x5abaf9e3, 0xa4f403e2, 0x756e87c4, 0xed784aab, - 0x02a7af0a, 0x43fedaf0, 0xf919fd78, 0xe48b9df2, 0x852f0fcb, 0x9171fe6e, - 0x8c4bf374, 0x3b090c6f, 0x578867df, 0x67407ced, 0xbef88347, 0x78db3a07, - 0xf9d2f189, 0xa7a89fe6, 0x5dfae142, 0x5c28427c, 0xfaeb1657, 0x5166bc91, - 0xd57a70ce, 0x4ffe6096, 0x12d891e7, 0x1e7a5c86, 0x3b7bfac9, 0x1967888d, - 0xd5eb9107, 0xf6c88fe6, 0x0f25169a, 0xbb859fcf, 0xe039d3cf, 0xe8bfdb74, - 0x079a101c, 0x0f9de7c2, 0x39fc8de4, 0xdcd01d56, 0xa677fc0a, 0x752748c9, - 0x377e3995, 0x7bf7fd0a, 0xa0e7cc0d, 0xffd811fe, 0x5ffbc60a, 0x03bcb4d1, - 0x305757fd, 0x479c57bd, 0x1db9ef95, 0x7c7c8315, 0xf2955ec5, 0xfe66d8bf, - 0x2c458ebc, 0x4c74ff41, 0x02398e81, 0x8aeb19e0, 0x78008e62, 0x07b78dc6, - 0x7939e5d5, 0xc13798ae, 0xfde82bdd, 0x82b31ba4, 0xae78a7fa, 0x3a9e7a08, - 0x9ea8372b, 0xa822375e, 0xa385ef7f, 0xde99ea83, 0x67fa836b, 0xaa0e4c37, - 0x1cde34e7, 0xab18ffd4, 0xec147c7b, 0x5bfa3fb3, 0xebcc3f00, 0xd60cb8ea, - 0xb7ac433b, 0xa0f29aef, 0x5afd81f7, 0x53381e31, 0xcf17c990, 0x00abdf8d, - 0xff08671c, 0x39bee5ce, 0x55cfe341, 0x677e88ab, 0x048e1a36, 0xacf469fa, - 0xc02a4f6b, 0x38a7c6b9, 0xb95ea15b, 0xecf9f826, 0xbde81b1d, 0xf6e0bed9, - 0xeb839bb9, 0xd29cde83, 0xb901e79f, 0x4672bf29, 0x87dfb042, 0x9989d085, - 0xb599f4e4, 0x7aa5ffdc, 0x24e86afb, 0x27ec5f18, 0xd0438dd2, 0x9839298d, - 0xc11d226e, 0xfaf95374, 0x0708a1d6, 0xfba3fc2d, 0x0bc9e869, 0xfe007eff, - 0x7d306716, 0xfb4ee169, 0xec567583, 0x95efd850, 0x6acfb850, 0x2a797879, - 0x633b850b, 0x1fd7233e, 0x688fedc1, 0xd981fde0, 0x89ca18f3, 0xa8163bb3, - 0xe3638718, 0xecff3c79, 0xed07af8e, 0x2f898473, 0x97c484e5, 0xf80425d6, - 0xe97c647f, 0xaf19c634, 0x67111764, 0x844ffddc, 0x8f00c807, 0x0b11f301, - 0x71dd119c, 0x3c7f48c5, 0x653f2b49, 0xb9e3fa09, 0xfe2bd204, 0xbc3d6c78, - 0x03e6343d, 0xc653ae37, 0x8ebe64e5, 0x930a2bcc, 0x8497fc9f, 0xb40fcc04, - 0x75f9e347, 0x3a7cfb4b, 0x22bcc977, 0xc302f226, 0x4fa4ffd8, 0x14d7f19a, - 0x26760bb2, 0x0afebd70, 0x176dd78e, 0xa92fbc88, 0x471a7bd7, 0x2a7adfc6, - 0xc52a5d95, 0x2894bb13, 0xf46153e7, 0x3f0947ca, 0xe685bf51, 0xa8147f8f, - 0x38ee6a47, 0x0bf507bb, 0x6c63fdc0, 0x6f4058b7, 0xfdbd7e2b, 0xd12b68bb, - 0xaaebd76b, 0x9c342faf, 0xd8c47089, 0x222d8e01, 0xe445afdf, 0xd6f5c9fb, - 0xf4baa445, 0x9c1ed879, 0x8ae327ff, 0xc28dfdda, 0x3afe71fe, 0x976417bc, - 0x76e5cf2c, 0x870169db, 0x276e160d, 0x9db91318, 0x1f39ab50, 0xfb7036d5, - 0xacd7a40c, 0x8c718096, 0xdfea1689, 0x4c685cdf, 0xdf8471c4, 0x42a67965, - 0x4572c576, 0x77e47b21, 0xfcf4d1b6, 0x868509cf, 0x6fffe844, 0x6011af31, - 0x16636588, 0x93438f5f, 0xe892fe17, 0x68c252ff, 0x36898d2a, 0x5db67fe1, - 0x6a91f481, 0x5da91976, 0x8aa71f0d, 0x1afbe44e, 0xb464f229, 0x42718071, - 0xdfdfa26e, 0xe2d2edc4, 0xfe4189b1, 0xf18cf7fe, 0xd0afdfc2, 0x53942eeb, - 0xef7814bf, 0xeaefffc9, 0xf1476b67, 0xaffff5ad, 0x7ffee48c, 0xf1081f19, - 0x85c73bff, 0x1e23fff5, 0xfe7eeda2, 0x2dd893e9, 0x3e50d29f, 0xea7a30ed, - 0xb5d5fcf1, 0x6878ec1d, 0xa4ebe7ee, 0x7dc0c0b8, 0x673c4ed9, 0xbb64cf2d, - 0x4b6f482c, 0x7f3b4318, 0x696ea747, 0xe95f3c24, 0x3e7c3665, 0xbf3f2d7c, - 0x3871ae55, 0x0e529b71, 0xfdc89d5c, 0x1f380687, 0xbdf1725b, 0x27186dc9, - 0xd9953958, 0xb2350d51, 0xda2b22c6, 0xd8596b45, 0x4168e3f3, 0x770a134f, - 0x4276fe51, 0x0fb7cf17, 0x7693a7ed, 0x73e2217e, 0x2ce79758, 0x7971cf8f, - 0xcf112242, 0x5f3aeda9, 0xb27d73b8, 0xa46ae8ad, 0xf0be81af, 0xc29188e7, - 0xbb32e64f, 0x03f8e227, 0xd87cf1b7, 0x677f294a, 0xf01e98e8, 0x75e0453e, - 0xd79e5aca, 0xff7fcec1, 0x45ed2abd, 0x9433e346, 0x2d53952b, 0x5513f43e, - 0x697a64b6, 0x99c56e5d, 0xe5a2f283, 0x2bd6376d, 0xe86df3f3, 0x9dfd7097, - 0x91fb4729, 0xfcb8c9a9, 0x52a3b3d2, 0x8f1e909e, 0x64d438a7, 0xf1236f41, - 0x72409cb0, 0xc034657e, 0x92ed72bb, 0xf3d7985d, 0xc5191ffe, 0x5da80e9b, - 0x5fb07143, 0xe6167001, 0xa567a962, 0xa648b7e4, 0x718aa671, 0x7982ffbc, - 0xfef3fc23, 0xda75e5aa, 0xf30301cf, 0x9d1d0046, 0x038379de, 0x09e5eeed, - 0x93cfe411, 0xaa83da71, 0x42523ee7, 0x5c1aaefa, 0xd12d4dda, 0x9c83f436, - 0x3a61f9de, 0xb93e4dc6, 0xed05ace7, 0xbbe87fd8, 0x7c2f982c, 0x16bbd17c, - 0x93f1c017, 0x9de52a45, 0x86f42add, 0x897dfb84, 0x271fee1c, 0xdc2117ba, - 0xddfc5b6f, 0x2a3cc0d0, 0xe88130b6, 0xa54fb679, 0x9cb75c90, 0x168d1cdd, - 0xbabd774a, 0x2ea82e39, 0x89b540f5, 0xbf3b85d5, 0x69e824bc, 0x6306d376, - 0xf7e703aa, 0x38fa42ac, 0x7474e7ae, 0xe7c59b7c, 0xa7aff4cd, 0x11b069bc, - 0xb47f83ed, 0xea2b5898, 0x81877d33, 0x8abb49e7, 0x8f0ba015, 0x9d76bfc0, - 0xa68e5e7b, 0xc63e66f1, 0xcc1947e5, 0xebe010b5, 0x724d9969, 0x998fbb41, - 0x25c6389f, 0xae675c01, 0xe3fa1850, 0xc022ffb0, 0xfde1679f, 0xa5fda15f, - 0x379967dd, 0xf9480e58, 0x3cf02955, 0x79f821bd, 0x696fcb65, 0x43cc199c, - 0x27602079, 0x735f9e69, 0xd80af50c, 0x67ed4147, 0x519b66f6, 0x14496f8f, - 0x6ca1edf1, 0xfef0f7d8, 0x18ec88ae, 0x927e184f, 0x36c5c9e5, 0x17cfd622, - 0x7c795047, 0x5172a331, 0xaae3a722, 0x44efb796, 0xc766a97b, 0x738e2316, - 0x9681f1c9, 0x999bd613, 0xe896ef5f, 0x1e21af3d, 0x28252cd9, 0xe1b3504e, - 0x32ec91ac, 0xd1529f01, 0x00f08a5e, 0x1cc2dc3c, 0x503cf1ab, 0xc7f0655a, - 0x5bffe0e9, 0x60c3bf72, 0xd1da80bf, 0xb5173991, 0xb94fb95f, 0x5abcf96f, - 0xf30c7a05, 0x4583e4be, 0xd8cd1f42, 0x2f796938, 0xcefd5100, 0xfc9d1963, - 0x78f649bc, 0x516bc091, 0x8f64fdc4, 0xe3d88517, 0xb7dc3dec, 0xe64ac7a4, - 0xa5a23d24, 0xcc07493b, 0x23f7a06c, 0x4ddebd84, 0x120f2d6f, 0xcc3d245c, - 0xe4685d5c, 0xc8c79be6, 0xb26f4aed, 0xa326d7f0, 0x30e816bf, 0xba063ec8, - 0xed6baa0b, 0x9d0d2ff1, 0xb41f2819, 0xe7ccb876, 0x60e7c2d4, 0x9a5fcf22, - 0xb38d70e1, 0x8073c00d, 0x85f9397b, 0x10ca46f1, 0x3dc6dbe4, 0x6edf2377, - 0x0ff37ce4, 0x92b30f41, 0xf049113c, 0x9af4b3dc, 0xe77fc41a, 0xf2065312, - 0x8a6967b3, 0x3dfd0f1a, 0xc39214ab, 0x18a697a3, 0x97d3ce11, 0x7c871e0d, - 0x345ccb9d, 0x1638b4fe, 0x9c186ed6, 0x7947e5c4, 0x6319819d, 0xf4462908, - 0x506a9f0b, 0x9a8c2fc8, 0x6be02264, 0xf557c096, 0xa4adb78a, 0x6ff01caf, - 0xe01f5e28, 0x2aeab33f, 0xee701f09, 0x52c7cb08, 0x66b154af, 0x3b8c0a63, - 0xd11b6567, 0x82479c31, 0x95b2d7fa, 0x66eaaf84, 0xd5dd7b4d, 0xb9d83f84, - 0xb589cf11, 0xf79f823b, 0x8276124f, 0xbe913993, 0x225a773d, 0xb471af30, - 0x4ad94f80, 0x6b7286c5, 0x84b6b2fa, 0x7d3ea01b, 0xed84eaaf, 0x8587c374, - 0x1f2823fa, 0x1cdecced, 0x719c57f2, 0x9fb09238, 0x52edcac7, 0x8619ef45, - 0x3ce2d3ed, 0xd8cfd0c3, 0x618591f5, 0x73a1df7e, 0x11e4732a, 0xfca20f95, - 0x341b1b2a, 0x2fbec029, 0x3112d833, 0xf365e91e, 0xb83dc593, 0xd4f84088, - 0x7e24ac46, 0x887e45a8, 0x34c3f3f0, 0xdda17b8c, 0x7942a2f3, 0x30476c84, - 0x34709fbd, 0x9091c226, 0x9033efb9, 0x8a6f2e9c, 0xf971f3a5, 0xea2322b2, - 0xb16df2d5, 0xf9c11f64, 0x86cbbdf4, 0x6879f1fa, 0x649ede59, 0x39bcb718, - 0xe306a9d3, 0x19dcf431, 0x0d39ceb0, 0x8efe2487, 0x23bf80f4, 0x7807f0e1, - 0x4f2f6a0b, 0xe0497212, 0x238a2d8d, 0xef3a5abd, 0x58089cd5, 0x48ba99d7, - 0xe9ec93ca, 0x8c66c47c, 0xe903fca0, 0xabdf1abf, 0x7944cfdb, 0x0e57673e, - 0xf169fc21, 0xd3dffe36, 0xcbbda187, 0x68616efe, 0x66cb4d67, 0xf6864db7, - 0x6fce14db, 0x19afead3, 0xddc4768f, 0xbd9e5c49, 0xd5d07205, 0x41b7b197, - 0x0e40ba0e, 0x11f20bbe, 0x4e2fefeb, 0x8b87faa6, 0xb47e541d, 0x47951fb8, - 0xf25fbf84, 0xd102101d, 0x2e2492ed, 0xc9249717, 0x6482faf8, 0xffc66934, - 0x3a21ddfb, 0x6c67de1b, 0x9d36309b, 0xc15cebb1, 0xa9c6f7fa, 0xd3b5fac1, - 0x8c971b60, 0x0a15dbe7, 0xeee5a3d9, 0xe1fd4191, 0x7bc464dc, 0x9e5fac2b, - 0x86f49dbf, 0xe81938c3, 0xb8e2a6f1, 0x37d7fea0, 0x9fd506a4, 0xfad07248, - 0x0ecf8d26, 0xb4b9bf6a, 0xecbd507f, 0xa431919c, 0xf1014777, 0x679102cf, - 0x8e770704, 0xfbef1b17, 0xa4b0dd75, 0x5fbd60bb, 0x73d033ef, 0x5e243e2d, - 0x9951ac67, 0xbe9bc607, 0x2c1fe406, 0x74e348f1, 0x0e2fafe2, 0xb25ce858, - 0x7f6f29bc, 0x350fd401, 0xe80f2819, 0x55b8b2d0, 0x6a1daf68, 0x2832b04a, - 0x6155cb3d, 0x2c8cd8d7, 0x2d15de40, 0xa6f9425b, 0x93933e65, 0xef7697ec, - 0xc0eeb293, 0x122e2af3, 0xd53de4f9, 0xfe10aad7, 0x67df045c, 0xe15ee922, - 0xf127b071, 0x4ef4e12a, 0x0ae3aebe, 0x13f5865b, 0xb9f71f91, 0x6a71d60b, - 0x0e856362, 0xbeea15fd, 0xcf9f9204, 0xb6e90cab, 0xf2819e74, 0xafbf660c, - 0x533ac06e, 0xbe395372, 0x66a3ca55, 0x7c6898cf, 0x021405d6, 0x6d3c16fd, - 0xae01ea7a, 0xfb7d78ff, 0x8203df40, 0x8e8e913e, 0x2c5732c7, 0xf5a1562d, - 0xc276fe7e, 0x87ee7c06, 0xee106fa7, 0xfdc1bd7b, 0xefe01266, 0x20df0af3, - 0x128b6f92, 0x70b4af88, 0xf2e4623f, 0xa07c8bcb, 0x9fa6e5f8, 0x7e9296cf, - 0x26706e98, 0xe56e493a, 0x3adca0a7, 0x7640d2b2, 0xacbbd330, 0x3e8f4893, - 0xe72c744f, 0x8c77a239, 0x691df5c3, 0x5f9864c8, 0xa552be51, 0x1fd20af3, - 0xe7e3efef, 0x0f5587d4, 0xdbcc24d8, 0x525878a0, 0x3edcdd28, 0x5de5186f, - 0x596ded6a, 0xeabc097e, 0xe64bb009, 0x8179e4ec, 0x3f53bf2c, 0x3ee06075, - 0x3cf9f196, 0x4af94105, 0x1daf5955, 0x2ec8eb34, 0xc273c18c, 0xa254f789, - 0x8d5913b3, 0x9f019343, 0x86bb7527, 0x2ff505de, 0xea8f7a26, 0xda223ea1, - 0xeb842ff3, 0x0ccadd5c, 0xfaf30b25, 0x091aaf0f, 0xacfe7def, 0x2e6c49c1, - 0xcf39fcec, 0x43fdeecc, 0x1bd815f6, 0xe1ddb8bd, 0xcffbc14a, 0x1acd1d73, - 0xc7c3807b, 0x00204981, 0x056adb17, 0x7876376d, 0x3c01e588, 0x31d74f57, - 0xe079e04f, 0xb1e3c8b0, 0xa873f324, 0x24a61bb4, 0x5d333973, 0xbd9be9c7, - 0x037a70ac, 0x0f502afb, 0x173db948, 0xbf55aaf3, 0xbb72901e, 0xfe52358a, - 0xdb99238a, 0x1f15b32f, 0x9835ddd9, 0x2bfd0289, 0x56683c6c, 0xf3e4d9b5, - 0xb698d265, 0x7a60fb40, 0x73279732, 0x8e3ecf8c, 0x3ac95be4, 0xfd353ef8, - 0x2af8373e, 0xf543323a, 0xc36d854f, 0x6f8d3b32, 0xb79fa270, 0x756bf052, - 0x256be2a3, 0x51eb853b, 0x299d57e9, 0x3f56a8f4, 0x8d25e885, 0xd1a99a3e, - 0x5831acbb, 0xe97ac2cf, 0xaf5cb2de, 0x68ee9d76, 0x0e61c10b, 0x6ff50bac, - 0xa7b7c785, 0x38add684, 0xeb21a301, 0x31ee64a9, 0x780fb8b1, 0x5d08eade, - 0x215f769f, 0xd4fb15eb, 0xf9c2bbae, 0xbbe62b55, 0x04293554, 0x243eed2f, - 0x9c76b43e, 0x97854bc4, 0x45a2b7c3, 0xd67e7c21, 0xf2321f6d, 0x61ba4b6f, - 0xe02ff0cd, 0xb047497d, 0x6f9412af, 0x1e41ab95, 0xd3d28667, 0x456cd61c, - 0xad61a9ba, 0xdf9053cb, 0x1faf9b5a, 0xb5867e8e, 0xa9f9d36f, 0xa39aded4, - 0x7a50058b, 0xbf8e5773, 0x17e74fca, 0x5cfc278a, 0xe9ddc3f0, 0xe01e9fa5, - 0xeaa37335, 0xd4141c8a, 0x7a3fe44f, 0xbcb38e09, 0x63fa235e, 0xe53f0967, - 0xab59d685, 0x2e5ff7e7, 0xcf015eb8, 0x0fdd7b9f, 0x7764f727, 0x76173f85, - 0x3d1a5bdb, 0xfb81b1ff, 0xfe7ca55b, 0xff22ef5a, 0x3b0bb42e, 0xe3c6ceac, - 0x9eb91a7d, 0xbd724f9e, 0x3979e842, 0x5b35d1cf, 0x13305e29, 0xf68080ed, - 0xa56f56cf, 0xd9f1a578, 0xcbb45699, 0xbe99ae8f, 0x8f52f30a, 0xbd274d36, - 0xa97bf95f, 0x40c63df7, 0x4d68a27b, 0x907bfad9, 0x5247378e, 0xdda2b15c, - 0x2045ce23, 0x639fa167, 0x6cab970d, 0x95b39735, 0x90071fa8, 0xfd8bec7e, - 0xf4f0acee, 0x68087e45, 0xe779bd27, 0x779fcf74, 0xfe77b8c2, 0x25e9da29, - 0x755ad850, 0x5adbcf64, 0xcf563f51, 0xde20f0ff, 0xe07b01d3, 0x7b4b5ffd, - 0x0645aa00, 0xea325b4f, 0x54076121, 0x6c321bab, 0xbd083768, 0x7f801ff1, - 0xe7f87844, 0x11cbfc12, 0xdbf101fe, 0x9c381b4f, 0x7fe06ba7, 0xcbc72578, - 0x2b6ca6f2, 0x6d3f2f9e, 0xebbb26c8, 0x821ca6d3, 0x00078cff, 0x1f5fdcfe, - 0x0035776c, 0x817cf1fc, 0x96f587f0, 0xfc043bb7, 0x0dfe1c9d, 0x256cee1c, - 0xc084672f, 0x57f94bd9, 0xe4d1fe77, 0x78e23b44, 0x57d92b64, 0xaca8b7c7, - 0x932ec03e, 0xac37d176, 0xdfb449f1, 0xf767fc24, 0xf28418e9, 0xd7e1f4a7, - 0xd98788ac, 0x3150785b, 0x95ccfe04, 0xeec7f144, 0xa8edbbf9, 0xdd5f116f, - 0xe245d476, 0x19b986a9, 0xd796c7e9, 0x4239e00e, 0x45bf7171, 0xb66fbc8d, - 0x19bef823, 0xda9592e6, 0x8ce2c5d1, 0xa4f5c088, 0x79d3ef69, 0xbebdc618, - 0xd6eaf9cd, 0x5de7c4f9, 0x25b97941, 0xfe80d5ac, 0xd0acd636, 0x05eaed3d, - 0x8642d685, 0x5a3ab571, 0x09453387, 0x56aecbca, 0x564f6475, 0x447c4519, - 0x892455e4, 0xdc29497e, 0x629c902f, 0x2474f2a3, 0xda707d23, 0x7de1f462, - 0x255f382a, 0x9ddefce3, 0x41dbc226, 0x5fc0135c, 0x333f0a35, 0xb7a442a8, - 0xd3a7185b, 0x297bcc5b, 0x972707ae, 0xa71fa875, 0xc939342d, 0xa18f8dce, - 0x42cdd2f8, 0x5e62ddde, 0x313d46ee, 0x61746ccd, 0x317ae309, 0x1a30d7f9, - 0x0df987a6, 0xef748cbd, 0xf3a234b0, 0xdf123c59, 0x8ef87c96, 0x95ea5808, - 0x1fa38e60, 0xf6dd7e18, 0x5e285c7d, 0xf609f8fc, 0x8546d74b, 0x170c8bf7, - 0x2e5c5070, 0x609b3ff2, 0xc75828ec, 0x6f0714a8, 0x3fb8d877, 0xc9e02d7a, - 0xb6afc7e2, 0xfc79799d, 0xb1f30ab2, 0xbc58f7f9, 0x5d541f24, 0xc8cabd50, - 0x62794f9f, 0x34eaf143, 0x8e61dec6, 0x2ab78881, 0xee782194, 0x61f18b2f, - 0xf43aef7c, 0xd4b1db87, 0xd64cbd13, 0x978eaf33, 0x0e3b660d, 0x25e3fdc7, - 0x2abf9e02, 0x0031ad60, 0x83d7d6f7, 0xb437f3fd, 0x02fb5aea, 0xb7d3af7c, - 0xea7d21b6, 0x1b061c22, 0xaf1ee3cc, 0xa539e2e4, 0xadc5e96a, 0xa689e2b7, - 0xa0a3d5e2, 0xacf9e3ae, 0xfee6bf5d, 0x59805b89, 0xeab76e11, 0xcb9abb59, - 0x52e100e9, 0xa978776b, 0xe2853cdf, 0x202e3237, 0x86183ff1, 0x2de3c40f, - 0x4e307d62, 0x37df1583, 0x7cd7c786, 0x8ccc2f81, 0x15cfb846, 0xf257377c, - 0xbf30535b, 0x0478823d, 0x2ed0553e, 0x22ddb806, 0xe2f89eca, 0x476e14a1, - 0xcfc2943f, 0xe25cf7ef, 0x95dccc7c, 0x82797941, 0x7c4daa5f, 0x75ff397c, - 0xc5307ca2, 0xf5cbe34e, 0x8a7ebd00, 0x0240e8e3, 0x691ebd20, 0x68fb27ac, - 0xc3880b16, 0x49fbfa65, 0x77ad0eba, 0xf7dd11cb, 0x66bb1a58, 0x5f95e820, - 0x8e513a44, 0xce6c62de, 0xf68733a9, 0x52e67193, 0xefa061d6, 0x993f4903, - 0x55633fd0, 0x9535e533, 0xf41efc2a, 0x578b42e9, 0xc7e27607, 0x067bbe22, - 0xa79c46ec, 0xfca15634, 0x773169af, 0x975f2096, 0x2c7a8d5a, 0xdff1163f, - 0x8d17595b, 0x2b2d89ff, 0xdf8606e6, 0xe631504d, 0xa4f80b07, 0xadfb05d8, - 0xebc3f947, 0xe4695d2b, 0x4ff5128d, 0x665c61f7, 0x03a079ea, 0x762e1faa, - 0x5fa7bcc1, 0x91d9cf15, 0xfa7e7c62, 0xdecf413e, 0xe9de34e3, 0x53f3e4c7, - 0xf90af9fc, 0x7f5e2bfc, 0xea2f8e50, 0x2f9e6b0f, 0x827f3cd1, 0xf89f5bd7, - 0xf68bd8aa, 0xda4e68eb, 0x921423a5, 0x37214657, 0x12b6974a, 0xbb754b9c, - 0xb59a3978, 0xdc2ff2ea, 0xdb8a64ef, 0xf7809298, 0x50588fce, 0xd533ff0f, - 0x7e814c65, 0xfe79269f, 0x499ce586, 0x7288d78a, 0xe91f3df7, 0xf21e9285, - 0xae428d27, 0xa6e5ea9f, 0x831ea5f7, 0xf1c3de71, 0xbb9c752f, 0xe4f9c743, - 0x4d738cc7, 0x4738c86a, 0xfebecc7f, 0x24e1ca9c, 0x517691c7, 0xe94bba71, - 0x663afc85, 0x70bf9064, 0x18cebdee, 0xcc314bf4, 0xcfd00377, 0x919cda5d, - 0x7dcfe307, 0x0a8cc5ee, 0xbe849bb4, 0x32a739af, 0xdaa3c817, 0x5f950a73, - 0xc4647db4, 0xdb35b37b, 0xa0e38cda, 0x45942d5f, 0x12aaeb01, 0xa77d04eb, - 0xa7a01c9f, 0x4274bd8d, 0xf3cc3c6e, 0xa13b9e32, 0xd5ce7c47, 0x3dfd1f35, - 0x4a11efea, 0x97f2f8d8, 0x7b077f62, 0xee611fb8, 0x6151e5c5, 0xee34576f, - 0x390614f3, 0xfaa2fc60, 0xbf02f9f0, 0x1528eb12, 0x50fa6ffa, 0xe003844b, - 0x1e3de43c, 0x9b58af5f, 0x62fe8b99, 0x04e8f263, 0x7e8f5b82, 0x67ee2ed6, - 0xd67ee16d, 0x02c77b52, 0xbb994efc, 0xf883ec57, 0xbf09b2dd, 0x2c067c93, - 0x378eef0b, 0x89bf7ac9, 0x3f714663, 0x7ef3d618, 0xf220f99f, 0x6e28decd, - 0x361b4ecf, 0x43e50a30, 0xceb46667, 0x4facfc06, 0x4af7732a, 0xc6abf6c0, - 0xc9a17b61, 0xe08ca7d2, 0xf42e88cb, 0xb8feee49, 0xfe8fec4e, 0x35b18f11, - 0x87d806e1, 0xee950de7, 0x45067803, 0xcbc5c27b, 0xe5c5ef2f, 0x8d97bbb9, - 0x0757b1e0, 0xaff5cceb, 0x760fce43, 0x180e82fd, 0x94d2c8ef, 0x30380fc1, - 0x5d78531e, 0xfcff04af, 0xa33c92b3, 0xa23fe702, 0x68f07d63, 0x18ebb171, - 0x1d71f02e, 0xf74a06c2, 0x80b7a028, 0x31e4def3, 0xa9f541d1, 0x15cc71c5, - 0x9a9dbfe8, 0xb1bf541a, 0xffa83b34, 0x07fa33cd, 0xea689f3d, 0xb00bafc8, - 0x97b67b67, 0x5a9f04bc, 0xed0a258b, 0xbe5a4fba, 0xb416e0f9, 0x4eaa3703, - 0xef6759b4, 0x48c1f4dc, 0xf00675e8, 0x497e471b, 0x3ed1f907, 0x7a747997, - 0x7e303e97, 0x50758a74, 0xd73ca2be, 0x68dc6c5e, 0xf29dadae, 0x78ae7f09, - 0xe25ebcd1, 0x72cb9bfc, 0xa99e3f51, 0x79fc9f7b, 0xcfbe6635, 0xe21e2f53, - 0xbd442ddf, 0x357f7402, 0xe2f688be, 0xc0fc1039, 0x0e3b45ff, 0x86cd9c51, - 0xf7b44dc1, 0xf1e9e6d3, 0x942d64fe, 0x81c65fa8, 0xba018adc, 0x036368e9, - 0x48de61b7, 0xe5db85a6, 0xbf90a6e7, 0xf7146f7c, 0x8c4decfb, 0xcc48efa5, - 0xda86b86d, 0xd345ce6b, 0x1da96ff8, 0xfa2f28e3, 0x13e28505, 0x2da75313, - 0x8decfdc5, 0x1db80ef2, 0xe7f89de6, 0xdc23c7ab, 0x7bf1b66a, 0x77d51302, - 0x5941e7f2, 0xbd0d78d5, 0x7b65513f, 0x621fb015, 0xe342ddce, 0x001b444e, - 0xcb50eaea, 0x5597a803, 0x3f9f6b63, 0x5a31bca0, 0x9ed4de48, 0x26f7a48b, - 0xfdfd7114, 0x0c4f217b, 0x635d7c9d, 0xe7a24dcf, 0xbd7c2e92, 0xf7f282b2, - 0xf51b090d, 0x4321bdf8, 0xaffd42a7, 0x4a9fd73d, 0xfa37dfb9, 0x2fbe91fd, - 0x7af84860, 0xbe8de61c, 0xc8d8af11, 0xe3c8d12c, 0x62c375b3, 0xd5791858, - 0x9e39cf3d, 0xc73a6c6f, 0x3bff8ff3, 0xe417f5cd, 0x9d4592c3, 0x31178c7a, - 0xe10d8473, 0xd8305255, 0x67c01151, 0x8c9baeea, 0xeac31f88, 0xafa88db7, - 0x0516504d, 0xf916af3c, 0xdd795a58, 0xfc83e422, 0x3fd49b8e, 0xd106792c, - 0x4136ade7, 0x9e8f82a0, 0xdf2c7c16, 0x0e33a0ef, 0xf73b71e0, 0x79a6b7f3, - 0xd13942de, 0x7c6ec851, 0x4767e49e, 0x7e69c606, 0x9e03f5ae, 0x1bb21423, - 0xbeaf293b, 0xc3a1c0a4, 0xdd7bc0f8, 0xf3f3877a, 0x26d1f685, 0xca96fdf6, - 0x6fb8e216, 0x1d97f2fd, 0xedaf182e, 0xd43cbcee, 0xcfde720b, 0x0b7bf17a, - 0x1e75d6cc, 0x2fb587cf, 0xef903b47, 0x0ce1e227, 0x4d3ba2e3, 0x76816e74, - 0xbed4778a, 0xef0a7a6c, 0xe15ad5bb, 0x17f30afc, 0x8ad912bd, 0x4af6dc74, - 0xc7f51ea4, 0x9f3dbd1d, 0x5e8a7c21, 0xcf063be9, 0x9316ae8b, 0xe3fd919e, - 0xb6f24a3a, 0x485ef587, 0x4ce9697e, 0x81a7a7f2, 0xa0994bf3, 0x7fc172d3, - 0x6747c11e, 0x0f8892eb, 0x45822ecf, 0x91753c63, 0xda1b7032, 0x7d0b0e0b, - 0xe5f24e97, 0x411f3c44, 0xb1fec4fb, 0xeaa18f74, 0x1f106c5c, 0x14cb9f56, - 0xed471dfc, 0x05cadf92, 0x7d84989f, 0xb5d04331, 0x3f245bb4, 0x624f74b2, - 0x6263ec2a, 0x95bdf03d, 0xc8f9fee2, 0x31ba7e4f, 0x80be90da, 0x022b926e, - 0xedbea7f8, 0x8a768626, 0x744dde29, 0x40ca0333, 0xb766653b, 0x971b629d, - 0x592feb08, 0x7bc3a996, 0x6a79f29b, 0x7fd1a5ea, 0x27c8aa44, 0xa0e6b730, - 0x8ba86b5d, 0x9a7de274, 0x1e3cf133, 0x87057f34, 0xbb837ce3, 0xf98ced08, - 0x3fe4284f, 0xe503fb43, 0x7503d0d2, 0xcabf40c6, 0x5106e74d, 0xb9ca7d3c, - 0x2634a8cb, 0x38472e7b, 0x5ebb9d94, 0x8fd06be0, 0x710e3f8a, 0xc192bf71, - 0xc86e7267, 0x4792bf44, 0x4f1f3c45, 0x0347b667, 0x546b7de3, 0xb8c98ff2, - 0x9933f4a4, 0x804fdef0, 0xdf46fd3e, 0xa3df4198, 0x0a9dfad1, 0xb93ffeb9, - 0xbffa40d1, 0xa19dedaa, 0x79fe783a, 0xf5092ba6, 0xa7837ac9, 0x6733f708, - 0x0339efb2, 0xb83ee7d4, 0xe1dc3ad5, 0xbeb36787, 0x69f50735, 0xfd11c033, - 0xd52bcd5f, 0xf76e3ef1, 0x1a38f344, 0xcf496fa7, 0x739f3a5a, 0x73e09b2e, - 0x7a44ceb6, 0x2dd02ce8, 0x5243d00b, 0x2f3948ef, 0xeba48ff5, 0x5f973d6a, - 0xca18e6d5, 0x9debf323, 0xa442ee49, 0x1f3c7ebb, 0x9e77afd0, 0xf902355a, - 0xe53c74e0, 0x21bd4b5d, 0xc585e0f9, 0x244794c9, 0x03e492f5, 0x7ca5cf29, - 0xf52f7497, 0xfd3fe8d6, 0xc3bfd6ef, 0x3cd293af, 0x7d02a577, 0xfae7ab5d, - 0x85bd5aeb, 0xfc6c67e8, 0xcdd23d24, 0x43d1cbc5, 0x0a1e8e42, 0x3d35a392, - 0xa94581e8, 0x1c5e7e52, 0x7c11cc1f, 0xedc4de33, 0x81f39448, 0x8da6b5e3, - 0xb1f7087e, 0xd9eb953a, 0x3ddd6b9f, 0xa9d5ffc9, 0x97ff2697, 0xfc9c5ea4, - 0xfe54efff, 0xbcad0a9d, 0xa3710fc7, 0xf3bd3fbc, 0x83ea1f72, 0x03f40c83, - 0x6896c1ea, 0x0fa126c7, 0xc5445f48, 0x1f487ef8, 0xfe9ef614, 0xf5e1a9df, - 0xff6c66c1, 0xd240fab1, 0xc91be497, 0xb42f9227, 0x62f9247c, 0xbce16fc2, - 0x8b7a7888, 0xd6aa8fdf, 0x0e289b7b, 0x8c1e88e9, 0xc76dd9fc, 0xdf88536d, - 0xe084f442, 0x04bf3f1f, 0x1fc90deb, 0xff245f92, 0x98fe0b54, 0xf243f829, - 0xf9b56ec5, 0x0a9811d1, 0x08f9e690, 0x93e488e5, 0xfab5e7aa, 0x42ba47a1, - 0x199b234f, 0xae90c75f, 0xa40ca1aa, 0xfc0f532b, 0xf512f070, 0xa48bbec2, - 0xf3feafa7, 0x0f55f4f4, 0xa7e674f4, 0x1da853d0, 0x03be61fb, 0x1f3673d6, - 0x9fa66de4, 0x8dfc26de, 0x9b21fb71, 0x46f6079f, 0x35ee7df1, 0x67ff93a6, - 0xcf3cf7c2, 0x3303da57, 0xd241bf85, 0x01d81e69, 0xf8fc4369, 0xbcc0f3c7, - 0x847b938b, 0x877c5367, 0x3327cf11, 0x03b40ca1, 0x537fb27a, 0xee4d2ed3, - 0x17fe8a45, 0xb480f3c2, 0x1c6edd9f, 0xaf1e1690, 0x027ed303, 0xa262275e, - 0xb22bf92a, 0x00a35c4b, 0xba890f3f, 0xc2094fb7, 0xf902faf1, 0x2e55b2fc, - 0xd607ca3d, 0xf475ddfd, 0xcaa5bc77, 0x31fece7a, 0x8f099eb0, 0x1d1fbf32, - 0x151d8f9e, 0x511fedd3, 0x717fbf98, 0x95fed65a, 0x451be7a4, 0x9ea74ade, - 0x3d4483c7, 0x8096ea1f, 0xbea6817a, 0xeab7f796, 0x3e60593b, 0x928dd209, - 0x0eecf1cb, 0xfa601fb0, 0x2fa8b3f6, 0xff430a6c, 0x86fc6d46, 0x5ca2cf57, - 0x6c50a1db, 0xde0e1baa, 0xfa070481, 0x07d5383e, 0xc65d77ef, 0x78dbcdd8, - 0x43b5f6fd, 0x132f7956, 0x1bdc06e3, 0x2e2b3432, 0x502847ca, 0xa199597c, - 0x4d3dbef0, 0x1eb913ca, 0x0214f746, 0xaf9867de, 0x77ef2977, 0xd1674de7, - 0x4ba6adfb, 0x5186ff98, 0xac6fefe1, 0xe4c6fd10, 0xfe7d84c7, 0xe1ca9a70, - 0x3406fc2f, 0x694d343f, 0xff9f7f0e, 0x1d2fc109, 0x78213f18, 0xfe855a4e, - 0x84a30eed, 0xc2157bb7, 0x41632c7b, 0x9f98347e, 0xbad71bea, 0x7cf41a4b, - 0xbc0d2ebb, 0x77bf687e, 0x03db05a5, 0x5f069bf4, 0xf7801fa6, 0x77de61dd, - 0xfadfbf04, 0x125af843, 0xdba0bef2, 0x5d8e9259, 0xa31ef441, 0xc67d1377, - 0xb4362bc4, 0x91dc6ba3, 0xe0bcf12b, 0x12d2cfe7, 0x138c9b82, 0xb4dff084, - 0xc8033192, 0x6fcf124e, 0xebfc855b, 0xe7f775d6, 0x1ae928fc, 0x5c0136af, - 0xef07f5c9, 0xeb769cbf, 0x024ff42a, 0xaa73d05d, 0xadd603eb, 0x4d66c7e5, - 0x7f86947d, 0xfc91ff05, 0x70007d40, 0x16f941ca, 0x08e8c87f, 0x044f93a0, - 0x7c894e9c, 0xdcd18ef2, 0xe2c8ec9e, 0x3c6977e5, 0xa099f52e, 0x9e9253cb, - 0x90e002a2, 0xf43f4416, 0xf60221f7, 0x29ba704d, 0xbdf3f25e, 0xbfc0c525, - 0xfcfe761d, 0x66fed67f, 0x5fcd3795, 0xcff78ed7, 0x2096f7b5, 0xf7c7ba5c, - 0x768fda2e, 0x6e024dc4, 0x67bdaddf, 0xc08077bf, 0xbbffa273, 0xf41f40ab, - 0xa46a9e3d, 0x3e94250f, 0x2fa50d5e, 0xfa7de6af, 0xbd3d043b, 0x7950b7ff, - 0xcfbcd2e0, 0x17107bf0, 0x5bc0beff, 0xe3af06b1, 0xa31d7835, 0xbaca97a9, - 0x4afe482f, 0xe3be5cb9, 0xe312fbe1, 0xd0a9afd1, 0x3d3f2475, 0x3cf4483f, - 0x77e926d7, 0x4fd5c115, 0x47ed0fcf, 0x2cdc9dfa, 0xf491b5e9, 0xc39424cf, - 0x29f5fc23, 0xfea88728, 0xc5c60970, 0x91eafafc, 0x6fb72855, 0x1ffd9068, - 0x2f37fea5, 0xa6ade393, 0x8c8f12e7, 0xeefa463d, 0xafa97ca6, 0x3fb9271e, - 0xefbf85a7, 0xfeddff4c, 0x4687e41f, 0x6ad65c0d, 0xff4d5eea, 0x6fd017d5, - 0x2fef34cb, 0xa95f3cd2, 0xd4d1afa9, 0x2fdf821b, 0x1f10a19b, 0x38f01596, - 0xb52f96a5, 0xef4ae1f4, 0xf5ba73b6, 0xfb2662b9, 0x26af882e, 0xb5faf3d4, - 0x1a4b1be9, 0x75f501cc, 0x5f384a9b, 0xf7016cc0, 0x7ae6419f, 0x4307a055, - 0x20b3720f, 0xd9b907bd, 0xf9efab4f, 0xafe07ff3, 0x0a371429, 0xab764bb2, - 0x5536f5c1, 0x75bbdbac, 0x810182ff, 0x4be7d5f1, 0x63dd5cf0, 0x5cdbc71c, - 0x2ed02632, 0xae25cd62, 0xfeca7d80, 0x5efbbee3, 0xeb3cf9c5, 0xd1b25cfe, - 0x114f718c, 0x12f3b4df, 0xfa8aa5f4, 0x6ff856ba, 0x2f1e61c6, 0x5aa293c6, - 0x080fe673, 0xee6b27d8, 0xbb6cfb83, 0xb7dfe55b, 0x00fc07ab, 0x8398ca9c, - 0x33a750f2, 0xb6a5e517, 0xfc2cc4c5, 0xf76f782f, 0xd442eadd, 0xc61707d3, - 0x2bd35e51, 0xb17cfce9, 0xe277a63b, 0x45b7a84c, 0xb6f246df, 0x54b1feed, - 0xcb5d52ee, 0x2d8c6cbb, 0x894af75e, 0x1e7c72f9, 0x3bba7043, 0x2592a5fd, - 0xa6f7ef40, 0x8f7de83b, 0x03b896dd, 0x0c07eded, 0x0e043714, 0xe7e89278, - 0x3c60d341, 0xe92d976f, 0xf2b1714f, 0xc38d26c7, 0xf7e5a47b, 0xd25e2819, - 0x9f91b3a9, 0x58c0f3c8, 0xb19a93ca, 0xabde944c, 0xdfe57ca9, 0x7bc7ac7f, - 0x14eb5da6, 0x55cd4efa, 0x6dff375f, 0x1b2bd410, 0xc67ee9b2, 0x9474e7cb, - 0x9ae9fe17, 0x53cc3ebe, 0x47591c3e, 0x9fd0a5f9, 0x9e56bbee, 0xc92fec77, - 0x0daafec7, 0x428e3853, 0x47cfda3b, 0xe14fa857, 0xab32ce3d, 0xbbf30a25, - 0xc8c77e8f, 0x3ef473af, 0xe6ef7d13, 0xd6e7b353, 0x8f74f135, 0x767d2d09, - 0x15587154, 0xf4dac380, 0x29c925fd, 0xf8126ed8, 0x032d6fdc, 0x75d32f3e, - 0x93e90fd3, 0x5f5e588a, 0x92cdeebb, 0xa38fb04d, 0x7ca5f44f, 0xd70c84b1, - 0xd78074ba, 0x93d70ce1, 0xd9fb8a54, 0xc79bfcaf, 0x593a5f25, 0xb5f4889e, - 0xcbf5d059, 0x0313cae7, 0xc5416eff, 0xc1d13d29, 0x02c7462b, 0x5469eefa, - 0x6ce782ba, 0xf43883a0, 0xe710cf9b, 0x85e7a016, 0x57d8c35b, 0x3db9d34b, - 0x84dbf6d6, 0xba208e51, 0x29e498fe, 0xfea0379d, 0xa447fa62, 0x16988ee7, - 0x77752e62, 0x1ddb243e, 0x34327049, 0x3322fa45, 0x1aea7fd1, 0x4ff3a2e7, - 0x96c99f73, 0xfd143e00, 0xfcf2f13f, 0x3fa04fdf, 0xf13efb9e, 0x604b3ffe, - 0xaff6433c, 0x68bc5ab4, 0x58b31c5c, 0x838f88f4, 0x3147c5fa, 0x9d62ad3f, - 0xc540f481, 0x5d4584ba, 0x6e807f28, 0xdda6bfd0, 0xc0c32997, 0xc63d18fd, - 0x192f3f57, 0x5e781693, 0xbbf24139, 0x377cbe27, 0xc6c944fd, 0x65f33d01, - 0xa7cb8da5, 0xf7f8eb71, 0x58872b75, 0x7bbf74f4, 0xe89babdd, 0xc8bcf01e, - 0x5157bc5c, 0xf844ceb9, 0xbc58b4ea, 0xbef12bb6, 0x0b1f4581, 0xae74a1e5, - 0x0e19f54f, 0xca9147c2, 0x54b911f4, 0x190a3dd2, 0xf0b13c3f, 0x1d31c7d1, - 0xbbe673f3, 0xefc0187e, 0xe9d38b8c, 0xf92a6d99, 0xc4f1b51f, 0x1ab7d7ea, - 0x888fd90b, 0x4710f627, 0xe29d62ac, 0xe3e1e2bb, 0xe238da89, 0xbdc5d2bf, - 0xa238eeb3, 0x5187be81, 0x4588e229, 0x7f5a156b, 0xbdfe42e5, 0xee38a292, - 0x18b23e3f, 0xed2fa0e8, 0xc5cb6bdf, 0x7fae693c, 0x8be2992a, 0x5eaf5f80, - 0x99fc8f3b, 0x5e1ce975, 0xb03be265, 0x199d2387, 0x58afde78, 0xae704917, - 0x07f6727c, 0x7de3e44f, 0x81f189c0, 0xa09b6be7, 0xe19f180f, 0xce39683d, - 0xd0f725b1, 0xd68b6777, 0xf31939c3, 0x73d963b4, 0xde226537, 0xde303252, - 0x2e55fb29, 0xef0fbbbd, 0xd86ce707, 0x950ad977, 0xbb6b0f7f, 0xf021f489, - 0xb80b327c, 0xd9633e2f, 0xd72346eb, 0xa8792c67, 0xfe1db3b0, 0xc29f6cfb, - 0x4104fc73, 0x26b7b8ad, 0x5bef27e1, 0xf7f8e995, 0x0a754b36, 0x8902c3dd, - 0x7e97f746, 0xa3fdc191, 0xcedc1979, 0xd270cb2d, 0x55ea9e3d, 0x4cd2e726, - 0xbdf74e3e, 0x55e73875, 0x282a3aeb, 0x1317f9ae, 0x976a57f9, 0xad22ba45, - 0xf9e31f3c, 0xad779401, 0xaa3c0237, 0xfc6e5c1c, 0xad63d042, 0x94d5d263, - 0x0767ae9f, 0x5607eff0, 0xac9cb85b, 0x9bb8058e, 0x86e90139, 0x1939f7e2, - 0xb8e253e5, 0xe6028329, 0x8c3b4457, 0xc7fab0e3, 0x0d63abdd, 0xfec1a7e8, - 0x38420f97, 0x237f5dc6, 0x9559efae, 0xb4801af8, 0xbfed00aa, 0x3c3cd567, - 0xd8ad9777, 0xf0e50e3d, 0xf1832ddc, 0x7b2b0546, 0x23d25dee, 0x3bfe0573, - 0x395a3e45, 0x81bbf1d4, 0xb9706437, 0xdfb951e9, 0x2f0106e8, 0x79f20749, - 0xf7030af5, 0x47bc83e3, 0xe4bd5301, 0xdab71a43, 0x728891d2, 0x81bb7ab8, - 0x8cdf87ee, 0x973806eb, 0x751f492f, 0xdcaae800, 0x51df4310, 0x344ef2ad, - 0x51aabd62, 0xbdffbaa1, 0xd3a40c84, 0x60bd962f, 0x1c39fa45, 0xfa839ad9, - 0xa45e6ba9, 0xda29ee93, 0x8beedfb8, 0xaf743965, 0xc3ad8669, 0x9965df82, - 0x8edb20b1, 0xada0fc72, 0x0fcf88d5, 0xb0ea6736, 0x46d9b2ee, 0xbfa5dd61, - 0x885fea92, 0x41fa177c, 0x9e3852ba, 0x1b769aab, 0xdd2feff1, 0xd4e2e82b, - 0x41f6efb3, 0x4675503f, 0x2fd41f47, 0x527d0740, 0x28cfce11, 0x9a6b9fa4, - 0xa4bc1e78, 0x03a41a83, 0x8239bbe0, 0xbdb66a0e, 0x43f21770, 0x373fe20d, - 0x9e808e94, 0xf9fda9db, 0x7f18e30d, 0x44e91dbf, 0x2fa833ea, 0xce3fa033, - 0x058bebc8, 0x0c7da1fe, 0xe00ef76f, 0xf9dd75f9, 0xd07c4108, 0x66d77e13, - 0x4c3e04e8, 0x8ad77724, 0xd8ae76fd, 0x9dfc456e, 0x1ef7767a, 0x3f54b78c, - 0x11dada0f, 0x3c041f86, 0x56ff716a, 0x19d93f5a, 0xab5fb8b5, 0x74ddff7f, - 0x96b0f82f, 0xfdc9fdf1, 0xfec5ead6, 0xfef173e5, 0x2acfb13a, 0xadb5e026, - 0xc13be72f, 0xf4c7c867, 0x3fb121dd, 0xbbf83d8f, 0xfec5bbba, 0x6cc9449a, - 0x0f8456cd, 0x0fe517e2, 0x28cb8fd0, 0x397409e5, 0xe50365b5, 0xc97c4bf7, - 0xd7efbff5, 0x93fc2e2b, 0x9d8f1254, 0xb6f77c3d, 0xa1c9f045, 0x763292fb, - 0xd8befc00, 0x240d9f4c, 0xcc07d57a, 0xce46e927, 0x49a7f457, 0x61bee2d7, - 0x5f1c56fc, 0x1bd07bce, 0x0e71c7ad, 0x721fce32, 0x8b2f92fd, 0x3b5da7ea, - 0x4efd8ad8, 0x5ed1b259, 0x3f7c7811, 0xbbef46c3, 0xf7806ed0, 0xf2143b5d, - 0xe7121f5f, 0xbdf743fd, 0xe01f2d60, 0xc577f7a7, 0xe19d25ba, 0xe4c9fa0f, - 0xb9daf77a, 0x6ebb583f, 0xbae48729, 0xe1bfee8b, 0xeb976c5a, 0x2051f8c7, - 0x4a384a9d, 0xfaf7957a, 0x344b74b4, 0xdaaaf527, 0xa6d77d33, 0x9dfca21d, - 0x78ed7690, 0x2c3a3ec2, 0x9ebbcdf2, 0xe77df956, 0x41edc965, 0x33188ef7, - 0x259fea07, 0x15b6aef3, 0x49b73c62, 0x521e7ba1, 0x4acfc0af, 0x923e807d, - 0xdef0c1f6, 0x36a57f3c, 0xf10275de, 0x63bc7559, 0x44927e1c, 0x7d57a5da, - 0xa0c6aadd, 0xcf1b6aff, 0x53749383, 0xf89db275, 0x93dc5aa1, 0xeef15b2a, - 0xf74861c4, 0xce281b4f, 0x58df7653, 0xb3fbda23, 0x8a1f4d37, 0x127bc0e0, - 0x6c4fdf28, 0xe047921c, 0xebc4b661, 0xc6c4bef1, 0xbfc7af47, 0x87633a5f, - 0xc1a1df4a, 0xcb8f9071, 0x7f23c8ee, 0xcec8e1eb, 0xaed02389, 0x436ab5ff, - 0xa6e47ebb, 0xffb08b21, 0x58ef4b48, 0xc6d078fa, 0xf4bbaa38, 0xa427a431, - 0x03f32c1d, 0x90bdc5eb, 0xaf9cdeec, 0x8a97757a, 0xefac0bc8, 0xaef9f183, - 0xddf4910d, 0xa3a352a8, 0xdbe715b9, 0x8ee74499, 0x2526385a, 0x2b9ee9db, - 0x8cb369d9, 0x9725222c, 0x453023da, 0xc74375f9, 0x5e4fa81d, 0x1832c3bf, - 0xd4cb8bbf, 0xb9cb43f3, 0x90e3cd7d, 0x61dfc171, 0xeac8eb92, 0x3b57e9cd, - 0x2f7f7c9e, 0x74ec2b9e, 0x3fde919f, 0xebe9ecb1, 0xd89e1f51, 0x7dc7639c, - 0x4919db1f, 0x198e0bf7, 0x78e7bf82, 0xb4c2f7a9, 0x3de4a9f7, 0xc1defcd7, - 0xfba49cf6, 0xb9cbde0b, 0x98f2d2ec, 0x74662e4e, 0x065cfc4f, 0xe8e4fee3, - 0x7e62b6ef, 0xc9a34561, 0x8e64f786, 0x7c63fd20, 0xdf4abb6b, 0xdfbba201, - 0xdb23af80, 0x703ee8f3, 0x5ebcc7c5, 0xf0f8acd1, 0xc3fb72fe, 0xc2fe53f7, - 0xf137b04c, 0x3db7796a, 0xebe1fabd, 0x38ce0d91, 0x3bf1cb3d, 0xf3366700, - 0xef908b7c, 0x75bebc3a, 0xffe38a4f, 0xfd2cfdbf, 0x077bd313, 0xf09347df, - 0x57aae796, 0x720a2e80, 0x72fbf0fd, 0x9fb22cf1, 0x50f62e4f, 0xb4395a79, - 0xb3d2246a, 0x15ee8625, 0x51e3b4bc, 0x5373bf15, 0x79f06dbd, 0x308f1f3c, - 0x9ff7d0c7, 0x90bc5cbe, 0x17279a82, 0x8a3f89d7, 0x15f854b6, 0xb55e547c, - 0xfbde8dad, 0x0b5e4772, 0xd97debde, 0x9ac5c31c, 0x3be820ab, 0x3dbf1299, - 0xfb9657dd, 0x1cd7fcfa, 0x9fdd72cf, 0xc56e9e6f, 0x21fdb57d, 0xe23865ae, - 0x86c63a37, 0xc8a56076, 0x86ba392f, 0x23c7d9db, 0x18abfe62, 0xed7c7cf0, - 0x0efc4494, 0xa9b6ccd1, 0xc57b63d7, 0xe786c54e, 0x49cee703, 0x7dcf3c56, - 0xe2b4efa6, 0xd6cfaa3d, 0x3e57fbc8, 0x237bbbfa, 0xd829b3c6, 0x9eab447f, - 0x84293239, 0xfc32f44c, 0xcbee9ea4, 0xe4ed017e, 0x451f393f, 0x89f813fe, - 0x99927cc3, 0x4bbf722f, 0x9c57f9f7, 0x7d8a46ff, 0xcbb6f7b7, 0x17b506f8, - 0x63f6f015, 0xd096b76b, 0x68de4fdf, 0xbfbae1b0, 0xf1a068dc, 0x4db9c0e7, - 0xbe3deb07, 0xb0839f99, 0x13e8e78e, 0x6779f99b, 0xef3f334e, 0xb833cf54, - 0x60d2fdf8, 0xe80a2cba, 0xeb2ddf47, 0x7323bbe1, 0x737f7c5c, 0x7ee27f40, - 0xb1bf442f, 0x9fee99ac, 0xa93e6a5d, 0xaaff7e96, 0x74dd1791, 0x08bd13db, - 0x23ff22b8, 0x98ba4add, 0xf5c786b3, 0x0b83cded, 0x9d24fe91, 0x5803bf68, - 0x3bfc646f, 0xfa28bab2, 0xb324f7ee, 0x62fa80c3, 0x18e77c4a, 0x075f4f04, - 0x916aaf97, 0xe4f785ce, 0xec29bd58, 0x15dec477, 0xbc1a78f2, 0x7abbf74b, - 0xcff7f8db, 0x59317dc4, 0x474abe82, 0xda293e7d, 0xba038dfe, 0xf2ffae74, - 0xf5d03d3a, 0x3bf691a4, 0xd7809db2, 0x7af35ff5, 0x167b7d9e, 0x7def3fd4, - 0xec3d3af6, 0xf695d26f, 0x2fa80621, 0x75cdf259, 0xc9b9e063, 0x3bd83ae1, - 0x9b139e60, 0x7f71d292, 0xdb087ed0, 0x8e7a27a7, 0xee2b5960, 0xba569d8f, - 0xf4cc2d06, 0xa77b7ff7, 0x0e4be0e5, 0xc0d3bd7f, 0xa73bbbe8, 0x87f5cb7b, - 0xd70e9d2f, 0xa109dea9, 0xdd8ce5ed, 0x5e7cf947, 0x7e076f7e, 0x788911dc, - 0x5dd38aaf, 0xd3c7bcb9, 0xe3c7b9a0, 0xe4d5f7e4, 0x7f792afd, 0xfdff72ea, - 0x7297b5b3, 0x00ffecff, 0x4fb2f369, 0x00008000, 0x00088b1f, 0x00000000, - 0x7de5ff00, 0x5554740b, 0x55b9e896, 0x2a493eb7, 0x54842549, 0xaa84a925, - 0xc0902b7c, 0x310c7c25, 0x0403e548, 0x6a285888, 0xa205a0d4, 0x01148280, - 0x55f4741d, 0x9a7c3061, 0x179f8ee9, 0x102d4622, 0xdd787195, 0x866db1d1, - 0x3220538f, 0xb40e9afc, 0xd38ceb63, 0x68d1d01d, 0x38311b63, 0x6f360cf4, - 0x4dce7def, 0x802a56ea, 0x6f7be7be, 0xf65e97ad, 0xee739f61, 0xffb3ecf9, - 0x5f5bdf67, 0xa5eb2c19, 0x0f24c664, 0xa153ab63, 0x63595a74, 0xff7b9419, - 0x68d2cfe9, 0xac839ac6, 0xc18f2e3b, 0xd3f5a35f, 0x7ccf5051, 0x2e504bba, - 0xcd1a484b, 0x139960c6, 0x996fd062, 0x12aeb189, 0x6d3b26e8, 0x12d8c2cc, - 0x019dfe09, 0x19caf9ff, 0x956c674b, 0x44edfe15, 0xf08742b8, 0x7f466683, - 0x3f98059f, 0x1fd8c0df, 0x3925744f, 0x9d9d8cf5, 0xbb0c2e1d, 0xbc65fb18, - 0x009ce6cf, 0x8ecd1ded, 0xbec634a6, 0xd4a4c37c, 0xd09eff43, 0x60f927df, - 0xe67aa5fc, 0x6d9284ef, 0x24d8ce1f, 0xc3ea2f28, 0x61dfa053, 0x8db6f157, - 0xa9cbbcf0, 0x3f9e0c63, 0xfce70aeb, 0x82c678f5, 0x32f2932e, 0x32777ea3, - 0x9f1eeb80, 0x9dfb1c3e, 0xfe5d7d7d, 0x936eb03d, 0xec1258cc, 0x598c067b, - 0x0030780e, 0x07c32fac, 0xb40e3442, 0xbea09307, 0x0e74f5c5, 0x2f307c23, - 0x0dd8c89b, 0x06ebef8c, 0xf11fbc39, 0x196494c5, 0x6f9b37f7, 0x3283db0f, - 0x3333a38c, 0x98bbae03, 0x4d3f5875, 0x8eb19800, 0x7f60c34b, 0x3263c066, - 0x24c78096, 0xa1eaa6c6, 0xe9afac13, 0x0990fa97, 0x7884d7d6, 0x85d07014, - 0xd72c7a23, 0xc58bf8c3, 0xbc8ecbbc, 0x58c1c46b, 0xeb07fe10, 0x5de62259, - 0x3d7771dc, 0x9092cb9e, 0xc0b74ce1, 0x7ffa25f5, 0x72c79d0f, 0xf2feefd1, - 0xe29c46ad, 0x7eda1dfe, 0xafa6d9cb, 0x52fcf0f5, 0xfdc46dd6, 0x6a8ceb2e, - 0x0cf9a8ef, 0x977cbbd7, 0x99debeb6, 0xc2748698, 0x97b1b2c6, 0xe74d54f4, - 0x99f448bd, 0xca746faa, 0x66e19fb8, 0x371304c5, 0xf4479f3d, 0xb00cdec2, - 0x63ac7ec8, 0x8b4fd118, 0xb1e74f4b, 0x9cc49764, 0x7ebb18e3, 0x42731657, - 0x61aefd53, 0xc85d2654, 0x5fcffaa0, 0x57de3639, 0xd75e7032, 0xc6ab6abf, - 0x6aff5df5, 0x3aea9511, 0x4e1d049a, 0x867497d5, 0x2ce71d61, 0x9b800eb0, - 0x8162c08e, 0xd66e9a7e, 0x99e11887, 0x57bfb199, 0x596bc72c, 0x424fa5df, - 0xfd8a0e58, 0x3a24974a, 0x1f3c6484, 0x433d61ef, 0x031e627a, 0x79993bb5, - 0xa05ca5cd, 0x398ebb1b, 0x24dfe063, 0x19ce2fce, 0x81ee9ccf, 0xfc583976, - 0x87584ab3, 0x0941ae61, 0x5c737b41, 0x33e436d2, 0xe574f416, 0xe20d73c3, - 0x4e38aeb9, 0x54ee0937, 0x1d2af3cd, 0xadfa2adc, 0x18769a4b, 0xb3c1b2e9, - 0x5121e888, 0xc7acd4c9, 0x406a5fa4, 0x67d5b9fa, 0x623ba4f8, 0x585fa21c, - 0x295e0dc7, 0x7378fc84, 0x50ddb683, 0x44ad75f9, 0x8e47d425, 0xfbf6d5e7, - 0xd003d229, 0x717e103b, 0x9c0c3d24, 0xc3a3c583, 0x1224f073, 0xb9cccbbd, - 0x5be012b9, 0xee181b0e, 0xf7cf14df, 0x97310e79, 0x0f80fd86, 0x8875e260, - 0x2e4fa817, 0xc537e2d7, 0xb0e7c5a3, 0x867e2d3a, 0xb7fbb57b, 0xda6ae435, - 0x35237c33, 0xcb8b59ed, 0xbfb67034, 0xc47fd342, 0xec0d6aea, 0xf4d4ce0a, - 0xa37f5bcf, 0xbd682e06, 0xa8bfd35d, 0xbda6817d, 0xa69f7438, 0x268ed47d, - 0xf9da5c0d, 0x98ffa688, 0xda6b8f5d, 0x6a3786c7, 0x7e1dc7da, 0xe84f034a, - 0x7fe9a2da, 0x34db07cd, 0x5fba93ed, 0xdb5fb4d3, 0x9e0686f3, 0xd35bbbdc, - 0x0385ca7f, 0x1d8ab81a, 0x31aff4d3, 0x4f0356ff, 0xa6abfeb5, 0xc7fb74ff, - 0xce19f69a, 0x67da6a3f, 0xd2d1bfb9, 0x93973c6b, 0xa5ff2bd7, 0x9359ee79, - 0x5f50dfef, 0xdd954b34, 0xebf48641, 0x35ba3e24, 0x0184a74d, 0x972a83fe, - 0x1c9e1d04, 0xc1392561, 0xb78e59f2, 0x32b0e914, 0x6e7c7c8c, 0xe0f24497, - 0x28bd28ab, 0x91ebd1ff, 0x4afd9da0, 0x22765e52, 0xc45d41dd, 0x331e29fc, - 0x39d62393, 0x81aaceac, 0x9aed7b87, 0xa706b6fe, 0xe7c33da6, 0x2d67b4d6, - 0xb6703456, 0x7fd35cbf, 0x068f6ac4, 0x34eb0576, 0x7bd6f3fd, 0x6b417035, - 0x517fa683, 0x5ed34fbb, 0x69ac5a1c, 0xafc3b51f, 0x573b4b81, 0xd98ffa6b, - 0x8fb4d415, 0xb4d7af0d, 0xaadc3b8f, 0xb5742781, 0xf35ffa6b, 0x3ed34841, - 0xa6877ba9, 0x4e9edafd, 0x77b93c0d, 0x94ffa697, 0x5c0d610b, 0xfa688ec5, - 0x6a4f98d7, 0x0fd6a9e0, 0xdba7fd35, 0x67da6b4f, 0xb4d73f38, 0x2cd076ab, - 0x7adad7f7, 0xaf5d1761, 0x7cf359fc, 0x90c3dab0, 0x486f823e, 0xd613b34a, - 0x3fe102eb, 0x777ce49c, 0x28ed1e9c, 0x8c14182f, 0x41ad2901, 0x420c92fd, - 0x480ae90c, 0xe2a6358c, 0x20ac4028, 0xc15549b7, 0x4f68c9f3, 0x73aa9000, - 0x1fa0fcb9, 0xeb5ad813, 0x1bb266a7, 0xdf40971c, 0x29bfc25d, 0xa0944b83, - 0x85ebaa9f, 0x4ea166f9, 0x726f3a02, 0x582e3cf9, 0xaf9d7dcf, 0x6862cb4f, - 0x705b0427, 0x9307a01d, 0x9e6f41bb, 0x79776388, 0x378f064b, 0x89780cc3, - 0x5c48ef98, 0x32cca3ab, 0xcc33fcf4, 0xff7fa967, 0xae3e06b8, 0x8a6bfb04, - 0xa0a7ff18, 0xfbb065ee, 0x37c0035a, 0x153d8c05, 0x4cfc12b0, 0x5b704ec0, - 0x7b6549c0, 0x96e54dc0, 0x1ded4280, 0x5f827281, 0x0e087808, 0xdca8ea05, - 0xfd52f016, 0xc10340f6, 0x547c04af, 0xa62c08ee, 0x9f80b5f2, 0x560677da, - 0x40f3fc13, 0xc0ceca90, 0x237faa7a, 0x9bf04ad0, 0xdf827681, 0xdca8840a, - 0xe541d815, 0xb52740ee, 0x22ec0def, 0x9840edf8, 0x30e070e0, 0x5d0207c1, - 0x7c0c1f04, 0x40a1f040, 0x03879537, 0x0d1e543d, 0xf1fb52f4, 0x078205c0, - 0x576b4bce, 0x2e576133, 0xd2c07412, 0x2f793db8, 0x85f6523f, 0xbb462d8e, - 0x43a09177, 0x87983543, 0xcc867740, 0x2ecd6dc2, 0x13a06a3c, 0x71c9d137, - 0x96af2fb4, 0x4070d04e, 0x33560d7a, 0x5a9bd237, 0xc9e954b6, 0x90ae0cfe, - 0xbb732f42, 0x336feb88, 0xb537f553, 0x85283e37, 0x079b9ed0, 0xf811b276, - 0x9f6123e6, 0xe5c7147c, 0xc1bf39f5, 0xa35f768d, 0x66c0af14, 0xb277fe01, - 0x8c2fe03b, 0x5ed77fa4, 0x9fb456d3, 0xc235f5d4, 0xe7183a38, 0x5a2eecbf, - 0x6c3b2357, 0xbd40f5c0, 0x72fc0f47, 0xe2dbe6c6, 0x2fbeba02, 0x2234175b, - 0x85425913, 0x8cc644de, 0x48f3df76, 0xf7fce7e7, 0x17c1c21c, 0x9c429559, - 0x78537ae7, 0x7f30adf8, 0xb2bd11ef, 0x5e3439cd, 0x00ceb796, 0xf6997de1, - 0xa0773fb7, 0x17f75f1d, 0xe1cf0fbd, 0x21b12184, 0xe9dd7404, 0x3acf8892, - 0xd94d3a5d, 0x02fdf766, 0xa26df9d7, 0xa01d4eff, 0x56ebdbf2, 0xb612b2bc, - 0x20a2b8d4, 0xf055ed19, 0x5f680c0f, 0x034e61cf, 0x989b87ca, 0xea1c5de7, - 0xf823e666, 0x52a41656, 0xe176f9b6, 0x21636ebe, 0xa6157d82, 0x8afb589c, - 0x383bd75e, 0x752c70d8, 0xdd90f29a, 0xfbc70077, 0xeb43d136, 0x7a69313a, - 0x5d4bee21, 0x49c33997, 0xdeb366fd, 0xdf7d7017, 0x53fafbee, 0x9d306f29, - 0x61f488fc, 0x3fb06981, 0x3779c233, 0x38e0ef03, 0x214b0fcd, 0x3e9573a4, - 0xa74cc11a, 0x7a851ff1, 0x805e9229, 0x4b7fd04e, 0x9399cdeb, 0x4dd2f448, - 0x3e926ff2, 0xfa7b0468, 0x28542e84, 0x8c4e89e9, 0x5173ac12, 0xee49d01a, - 0xc0f0f4d0, 0xe423287a, 0x17d9d020, 0xfe9fde38, 0xe2371ae1, 0x93dbf96d, - 0x66b7889c, 0xd0079c1d, 0x9ea8f073, 0x442604ec, 0xd2dafebb, 0xb207f910, - 0xc529cca2, 0x7172e373, 0x7ead9ebf, 0x4ddc863d, 0x74f4e5c8, 0x0ba86ec2, - 0xef9cb8d1, 0x2e7d76d5, 0x2e7d473f, 0x15a6df3f, 0xc3d52d9f, 0xf81c4ffa, - 0x8d2ce8dc, 0x3fd58fb1, 0x823f2879, 0x3aef97ae, 0x7e83cd3d, 0xb92eeb17, - 0xbea07131, 0xd2abcc50, 0xe898de91, 0x5c896adb, 0xc75d3f57, 0xa75d22e7, - 0x11e75d00, 0x768a7f5d, 0x33936cf9, 0xbb2856f9, 0x28613501, 0xc95a2f7d, - 0x14c05c7f, 0x2f32172a, 0x0c808b95, 0xc1bd8e90, 0xf7888d27, 0xd52758fb, - 0x777e503f, 0xbdf5d23a, 0xd9f91f3a, 0xd517594b, 0xb5bd672f, 0xaf37b478, - 0x1daef35f, 0xeb537d56, 0x44915393, 0x7fcd0c6f, 0xdb39cb17, 0x4e834fa5, - 0x5cec93e2, 0xe4b747c0, 0xe613227f, 0xd5677dbf, 0x3f505913, 0x85cfcf5b, - 0xa2e7e31d, 0x7de891ca, 0xe0145f03, 0x78a6dff3, 0xa4fa5f68, 0x345f0d3a, - 0x123cce3e, 0xcfbbd38c, 0x8ae6da14, 0xfbf293e0, 0xf28590ff, 0x13bdee4c, - 0xdbf97bcf, 0xef3c54a6, 0xfbd718fb, 0xaf8d4792, 0x119efaa8, 0xe2cfdfbd, - 0x85f7ec15, 0xb22fefa0, 0x17f7d119, 0x658a3812, 0xcb287603, 0xf2cbd9f1, - 0x72f6f406, 0x88d1cedd, 0x95ebd027, 0x7df70e78, 0xd632d9dc, 0x9420fa85, - 0xe1887683, 0xecd29335, 0x7617e8d2, 0x8d850129, 0x7f3e219f, 0x198ee38a, - 0xfca92ebc, 0xeed19fd0, 0xd0591930, 0xce7c465c, 0x677f2226, 0x9abf891a, - 0x3879b511, 0xb7e9d78f, 0x84ff1e0c, 0xefe1ef58, 0x841d3fb8, 0xc52cbcfd, - 0x2feb879a, 0x3cc0fc53, 0x19d24724, 0x2e4773cd, 0x3e7563e7, 0xa076e966, - 0xc1347e9d, 0x8f9e3b77, 0xfd52471a, 0xcfaec3c8, 0x667cf1f2, 0xe5506c57, - 0xaec78d33, 0x84e972e3, 0xf84419c1, 0x014b9544, 0x6f2fd609, 0xa7ff286f, - 0x371d700f, 0x8c612d98, 0xc34ab077, 0x35ff7ed9, 0xdf1f4077, 0xcae3eaa0, - 0x1a8ef8a8, 0x018a61f7, 0x3ecc57d7, 0xf141f152, 0x0e4e551d, 0xb1b0bfd2, - 0x889fc42e, 0x79c7f597, 0xce3fb9fe, 0x8d79c3a3, 0xe6328e42, 0xf8237b77, - 0xae00d6d4, 0x307fc68b, 0xff8d7cb3, 0xd9c0d560, 0xffa6bb7e, 0x4d4ed588, - 0xd6e82bbb, 0x57ade7b4, 0x6b417034, 0x517fa6b9, 0x170347bb, 0xfd34ea87, - 0x6af0ed47, 0x06ced2e0, 0xbb31ff4d, 0xb1f69a7c, 0xf69ac5e1, 0x1afd8771, - 0x6ad74278, 0x3e6bff4d, 0x27da6a08, 0xb4d7af75, 0xaad3db5f, 0xb6f72781, - 0xb94ffa6b, 0x57b4d210, 0xb4d5bfb1, 0xd75f98d7, 0xf1c62fc0, 0xeb54e778, - 0x9b9e683f, 0x81afdf6e, 0xf1e7885f, 0x23ce199a, 0xf9c5e7da, 0x278b6f06, - 0x3ee5987e, 0xffdf69a9, 0x8dcdc8c8, 0x47a12fc0, 0xb67fe474, 0xc53d71d5, - 0x1d39aa1a, 0xd7bef1c4, 0xe66a1f2b, 0xbaf7d1cb, 0x7a9d8e90, 0x75f2266b, - 0x039cf97e, 0xd0ac7640, 0xc51aa2b3, 0xc9eebb9d, 0xf48e5803, 0x6c8d5ebe, - 0xf270d253, 0x7da39600, 0x1903575f, 0xca716533, 0xf996583b, 0x70d8d6c7, - 0xbce7ab89, 0xe0c4e583, 0xb3941a8a, 0xb17e2660, 0x3e7dd608, 0x846d9238, - 0xaa652575, 0xd10f5e71, 0x1d0caaed, 0xdbaaf9f1, 0x4b37142c, 0xa322d6bf, - 0xe81cdf3e, 0xec10791a, 0xd3a7f4dc, 0x69dc62d7, 0xa1f9d83d, 0xc017b022, - 0x59f2c7ee, 0xe043ebb0, 0xbb046d1c, 0x604dcb1f, 0x73fd63f7, 0x9c23f760, - 0x7ad974fe, 0xc9d56e7c, 0x6172ea7b, 0xca0f11fc, 0xd7533456, 0x0e2b7539, - 0x0fec7ac0, 0x4b28ad1a, 0xe267ae8c, 0xec8eb09c, 0x0a8eb065, 0x51078b42, - 0x3052ecfd, 0x1c39321c, 0x2becfd07, 0x1db81a74, 0x2eb045ff, 0x97cf8b58, - 0xaedee93e, 0xb6f9f630, 0x8a1937b3, 0x5d799f61, 0x014d6db7, 0xe6799738, - 0xf1d3be02, 0x93fc602c, 0x09cd8f79, 0x97860c96, 0x48ff7a14, 0x2cee4972, - 0x16b53e46, 0xeb81947d, 0x85fd50da, 0x3ce2b3a2, 0x0839cc8f, 0x787e7eeb, - 0x23e758bc, 0xaff2aa73, 0x79cf5c66, 0xef50ef94, 0x47218cef, 0xffe853fe, - 0x2f5c7993, 0xe5159fc3, 0x08938d93, 0x949d81b3, 0xf376f20c, 0xd1a7d5a4, - 0x41ad90a7, 0xbb23e509, 0x144fcf08, 0x7823c828, 0x1e44fc4a, 0x537947b2, - 0xe733e454, 0x1f3678c1, 0xf1914ed8, 0x785ac5b1, 0x19e79c33, 0x0c7ac0c3, - 0x3282e977, 0x92f0c1ec, 0x9e605157, 0x5fb0798e, 0xb51b3780, 0x8e9165fe, - 0x9f717d91, 0x378beeba, 0xdda76829, 0xf0f5c797, 0xecbb8096, 0x7ffa0313, - 0x4027d94a, 0xfd8b9947, 0xabe40f92, 0x04abd1ad, 0xd2e19fa1, 0x2237efdf, - 0x3ac5df61, 0xfd639f51, 0x27bb089a, 0xb86b8c47, 0x19bc27a4, 0x6a4abd9a, - 0xbd06fcc4, 0x618cefe4, 0xc9e69577, 0x4666b9fc, 0x1e7786ed, 0x5f309c96, - 0xba486366, 0x4bf1c687, 0xc2dbd40a, 0xb1ab3ebc, 0xf0085a53, 0x3a4e791d, - 0xac9c7507, 0x08feb0c5, 0xa0e5d93c, 0xede78564, 0xc425068f, 0x55eadd83, - 0xdae22258, 0x52bdfc4b, 0xf57db4f0, 0x864fb2c4, 0x8abdbae1, 0xa59be717, - 0xcadf9bf2, 0x2b1f3d70, 0xbd42a9bf, 0xc33d1bf6, 0x9c6f8cfb, 0x8c5a724a, - 0xa9a5a87d, 0x973ccf5b, 0x729267f1, 0x9e93f11e, 0x2ce2ddbc, 0xf17dfe00, - 0xd6c34b36, 0x47767418, 0x75b3a71e, 0xe2deaa99, 0x73d749eb, 0xeafaa93c, - 0x1fa72b1b, 0x4cad6e55, 0xce3ab0e1, 0x24f1ecca, 0x8f5a8637, 0xf98e3dad, - 0x19bbd622, 0xfde2b1e6, 0xac2b77cc, 0x21f03788, 0xcc9f34bc, 0xe7d6e9e5, - 0x4637e4dd, 0x3e20cfd3, 0x5c9bd100, 0x1dd97486, 0x31ba066a, 0x682a33cd, - 0x5bfeda2f, 0x2472848b, 0x284ab593, 0xb5d96d47, 0xe7d46587, 0x1bd8afb2, - 0x12be8ec3, 0xa9e7a83f, 0xcf8325da, 0x2abbf9cf, 0x0c0d43b2, 0xe5c9b6e9, - 0xa9f9e1b4, 0x6474da74, 0xe22faa78, 0x3a0bd73c, 0x7aad672e, 0xd60ad3e4, - 0xeb256549, 0xd63af2a2, 0x5987a54b, 0x99ab2c65, 0xf32d6542, 0xf98d3952, - 0xad63aca9, 0x9d64ce54, 0x2eb3d654, 0xa3bfc12a, 0xe4accbd2, 0x7608de87, - 0x9973960c, 0x985bca97, 0x482dca9f, 0xfef013df, 0xdbe095a1, 0xbb952759, - 0x459dff80, 0x53311f18, 0x39e417b9, 0x3c836f96, 0xf20c32c7, 0xf8c269dc, - 0x83ca9b88, 0x43ca8501, 0x0f2a7281, 0xefd43c07, 0xca8ea068, 0x952f01e3, - 0x540d0227, 0xd47c0576, 0x316054ef, 0xfc05ef95, 0x581fbe54, 0x8107e54d, - 0x12ff9520, 0x91654f58, 0xe20ae411, 0x163ddddb, 0x8f9c9afd, 0xe8271e8d, - 0x84f34fa3, 0xfdd1ebff, 0x78f1e2f7, 0x83ba3a8e, 0x94aed5b1, 0x6e6d1e90, - 0xe504279d, 0x74937746, 0x4eeb9437, 0x64d63b70, 0xd93b244b, 0x724abed6, - 0xa4bbb8c2, 0x9c027d6e, 0x0fbcdeed, 0x4f4198e7, 0x6b65ed54, 0x7f841413, - 0xe819a4ff, 0xdfc1ab70, 0x7fda15bb, 0xcebfd2f5, 0xaece8331, 0xc7f53c48, - 0xed4c38d7, 0x66b20e93, 0xf207c02b, 0x26993f4e, 0x10a075f1, 0xc7d2fe3e, - 0xe3e4d673, 0x791cb93a, 0x368e05d5, 0x5b0f19fa, 0xdb18cfc8, 0x0eac667e, - 0x2dab49e0, 0x471fe865, 0xf5b8a3f4, 0xdba2fd50, 0x563ae7d5, 0x1e2337a4, - 0xee0a7dd6, 0x65e51389, 0xcf8c58f7, 0xbbab8e45, 0xfe99f9ba, 0xf647f332, - 0x5e332e93, 0x54e79151, 0x7403ffde, 0x86df4d1e, 0xaebf1f4b, 0x3598f8a3, - 0xf6faf515, 0x7a772e14, 0xdb43e3b3, 0x53dbdd60, 0x9f21bc05, 0x610eb5f6, - 0x8dbad7d8, 0x6fc764b9, 0x1d36f38f, 0xd1bff6c1, 0x69a0db29, 0x636fbc7b, - 0x14f9c131, 0xea9759af, 0xca5ea377, 0xb1fae049, 0x9c48f1cd, 0xffff8233, - 0xe6eee422, 0xadaebeca, 0xd7ad4fe8, 0x6e7802b1, 0x1b05fadb, 0x4bce30dc, - 0x022ec09b, 0xc2f27938, 0x9ed0050d, 0x513741bb, 0xae1e642f, 0x0b4da5e3, - 0xe128d95f, 0x0b5323b8, 0x213cdc61, 0x7586733f, 0x74095d8f, 0xc6d466de, - 0x63f5fa15, 0x8597e73e, 0xd019cc30, 0x5e2239bf, 0x1ac0d5b1, 0x4166f522, - 0x35b7973e, 0x4c34bc45, 0xd33cf1e1, 0xe3d0f888, 0x11aaffb0, 0xbe93fe3c, - 0x9ff14cd6, 0x9e7fc774, 0xe9ed0e9c, 0x4d053a1d, 0x74b6d95a, 0x9efd018d, - 0xf22758db, 0x3f8956e3, 0x76e6cc1f, 0xb92c1832, 0x1efc2273, 0xf2ca37b0, - 0xf6a7e223, 0x7184a086, 0x4b11aa8c, 0xa7378c25, 0x3093ee3b, 0xe0de91fe, - 0xe8897c93, 0xfda9f927, 0x2b9f22ae, 0x6f67d61f, 0xf735e784, 0x3c0cbeb1, - 0x81b79857, 0x566409f2, 0xecdf3916, 0x27878e22, 0xb43d2064, 0x691ad7df, - 0x9af8d15d, 0x991eaee5, 0x1ce07c3f, 0xccbfdba3, 0xfdb8e7e7, 0xf9029871, - 0x1f8f1260, 0x9339789c, 0x6dd9e5ec, 0x23f41ef1, 0xb2393c4f, 0x2aa7e096, - 0x9eff683c, 0x1a62b978, 0x9a9fb396, 0x484efd49, 0x05c630ec, 0xbb753f66, - 0x7939f58c, 0xef1c2eb0, 0x71e891b4, 0x89f753f6, 0xc5a91fe7, 0xf05d72f6, - 0x2e9fd0ef, 0x012d7e6f, 0x891505e3, 0x7961646f, 0x6abdd742, 0x837fcc3f, - 0xd51afd95, 0xda4377b5, 0x3fc1d4df, 0x6b993ce6, 0x378c78c0, 0xf3ce973f, - 0xf031e626, 0xf92f077c, 0xba3b95b7, 0x8e8b01de, 0x5bd9d75d, 0x9ebad783, - 0x5883d65d, 0x34158756, 0x61ed59a3, 0xa72c41ef, 0xd16bf975, 0xa0fba9bc, - 0xdd9620f5, 0xc45e7d23, 0xedffabff, 0x055e3796, 0xab63c478, 0xe68768ac, - 0x633dde3f, 0x0d2fc51b, 0x60a1f90c, 0x8f55bf92, 0xa6f66c04, 0xf6787ca2, - 0xfa875919, 0x8d6ae4dd, 0x4f74d843, 0x4ce30eae, 0x175a53db, 0xe20bbed3, - 0x28f1e219, 0x8ba421e8, 0x2a6f1482, 0x25f013f2, 0x829dc39d, 0x7e294d3e, - 0x8bd60a6b, 0x7efe8e7b, 0xd85e1cf1, 0x4e35afdf, 0xa55279a2, 0x08cdc4a0, - 0x42ec23b4, 0x7f33b79f, 0x96c3e206, 0xf18adfe8, 0xce2a82ad, 0xd3912cff, - 0x996f7605, 0x10508f48, 0x3fd5bd3e, 0xe6c1cf0b, 0xe01bcfeb, 0xb06a0774, - 0x25c93edf, 0x367fee98, 0x39061c4b, 0x3fc2eb43, 0x5ba4e78c, 0x51cec9d2, - 0x806b6fd7, 0x0eec22f1, 0x968dc7dc, 0xba54e781, 0xf5f620db, 0xe60b2884, - 0xf5d4f1f3, 0x7ae7cc6e, 0xd4edd61d, 0x62f47ae1, 0x5d0fb03d, 0xfa227ac4, - 0xd7fafed1, 0xd23b14cd, 0x897e6305, 0x4729cc97, 0xcea17fee, 0xd71a3713, - 0x615fd6ff, 0xe509295c, 0x67f3ac08, 0x919927fb, 0xf1f7a34f, 0xfb88be42, - 0xfe8cbd80, 0xe71f4cc3, 0xbf46e6df, 0x0d94fe84, 0x43bfdc61, 0xd45c60f6, - 0x0c926966, 0x39b5fb11, 0xd99e9eb8, 0x728fdfe8, 0x82796665, 0x8b3df482, - 0x72b5ae75, 0x0f983efe, 0xfd622beb, 0x7136167f, 0xfe7c4ec0, 0xe24ef799, - 0x67583a91, 0xcfea3155, 0xbca5eec7, 0xcc8fcd89, 0xcfeb8c3c, 0x3fb93f74, - 0x7ef40615, 0x3e7dce2d, 0x77656f8f, 0x87bc9ac8, 0xc9acbf2c, 0xac58c88b, - 0xd07a076d, 0xd95d2ac0, 0xa829d5a5, 0x2509746f, 0x9da06733, 0xf923a492, - 0x9a4a720e, 0x8d1ed31b, 0x7f812ba2, 0xcdde7cf5, 0xb373a7cf, 0xb039f859, - 0x737cc55e, 0x7aacd8a2, 0x336f304e, 0xd03279b0, 0x3ead737d, 0x8f1fa124, - 0xb232f1fd, 0x26f70d97, 0xada73e0e, 0x19cce706, 0xd41fa728, 0x2aaf2959, - 0x67a0af0a, 0x94fc99fe, 0x1da8d307, 0xc53365ea, 0xabd6233d, 0xcf6b058f, - 0x3bfd4ae3, 0x0cce7858, 0x4cfae0d7, 0xa899dcc7, 0x32973367, 0xf6e8ff3a, - 0xe7b547a2, 0x78ef7e4a, 0x50b1a38c, 0xe79c07f8, 0x5af6c74c, 0xcfa3efb4, - 0x9cbba555, 0xc2f5b161, 0x2f5c0523, 0xa72824e4, 0x90aec8ea, 0x66f04ec9, - 0xfd23c3cb, 0xb9f2efa4, 0x57e5301f, 0xec43d216, 0x1f087363, 0x3f5dc255, - 0xa8738629, 0xfba1d3ee, 0x7e3ddec2, 0x5099e9e0, 0x7bf5fd4e, 0xdfa0c74d, - 0xe32cefd4, 0xeb377eb0, 0xa081819e, 0xf90361e0, 0x7cbe6b8d, 0x440315a5, - 0x414c8dcd, 0xe3ceabbd, 0x6efae028, 0x25e4218f, 0xb32c5af9, 0xd907246d, - 0xf4114bc5, 0xe89e9002, 0x6f31b787, 0x91f92b63, 0x8612fcb6, 0xaccd3c79, - 0x97d20ef3, 0xe30c8d67, 0x383637af, 0xffb0550d, 0x869d1b1b, 0x219f78f9, - 0x23b43ab3, 0xa8506a6e, 0x8546a6fe, 0xfd799bd7, 0xd50f06dc, 0xf0f46dcf, - 0x5bd40b7a, 0xd4290f30, 0x6f718015, 0x753aa4b6, 0xe8d01f78, 0x4c17ede5, - 0xfc1c7ed4, 0x8c27cc01, 0xbc910b8f, 0xf1d1ed6f, 0x7c7f237b, 0x9ab58248, - 0x3b0ecb12, 0xe8f77f11, 0xcc175014, 0x2b332d94, 0x7836cfc0, 0x7f687a43, - 0x1032858e, 0x3617bb91, 0x7ea10b79, 0xe2b643b7, 0x7b8376fe, 0xc147f98b, - 0x9de132a5, 0xbdde00fe, 0x3af741d8, 0x3efc455b, 0xf14cc4b8, 0x2875b066, - 0x6496ccde, 0xb7863b0a, 0x86b02c77, 0x39031ed0, 0x7bd8e748, 0x00764c8f, - 0x6ea3c3c8, 0xe6768bb4, 0xca9f182b, 0xb7e5aa5c, 0xaa0b85f4, 0x6646bc68, - 0xbebd3f45, 0xbcd78f91, 0xa1d21753, 0x71b9655d, 0xf341d226, 0x3fa0a60e, - 0x53c2ecfb, 0xee10c3b5, 0x3f2e1450, 0x79a172b4, 0x9c4753e1, 0xcebf1fb8, - 0x79fd405a, 0x5fd9af1c, 0x0d2f5dbd, 0xb79d33f0, 0x0c7e4073, 0x61ca3796, - 0x5e63271c, 0xc1f182b5, 0xc627d874, 0xbc8c3bf3, 0x4ca7783e, 0x0be92df7, - 0xf475b0e5, 0x0b677f00, 0x1f23a614, 0xd17c9126, 0x9dc8d7f0, 0xc179f85a, - 0x32efc0a7, 0x9db82bee, 0xd1673e51, 0x903f6d76, 0x57943a93, 0xfadaedd9, - 0xe3fa8b5b, 0x443c1a02, 0xe7e6d9e3, 0x9f7a2f72, 0xc70afb03, 0x74bed115, - 0xd7285f7c, 0x72d8bea0, 0x1b8bea80, 0x44e9c565, 0x0a79d779, 0x53b45ff7, - 0xeb806166, 0x44cd9617, 0xa4dfaa7a, 0xf5c8f0a3, 0xc2e48bac, 0xc6adf695, - 0x19f7a23b, 0xf2efbfbd, 0xa88e5cf5, 0x6613e0f6, 0x1edb07b2, 0x9ef0e8b6, - 0x78adec15, 0x55dc2b8c, 0x402c1d54, 0x1dc8407b, 0x973d25c3, 0xa216cd27, - 0x51ed8353, 0xa1fc6477, 0x13f55465, 0xd86fd405, 0x6e3c758d, 0x968efb41, - 0xe3173f63, 0xe6d6ea4d, 0x13db5de3, 0xa63f951f, 0x729bc7cd, 0x7f2a3321, - 0x7f2a2f2c, 0x7da6946c, 0x545c75aa, 0x51b5d8fe, 0x1a3563f9, 0x967b9678, - 0xcaf5ffa6, 0x86f81a4d, 0xfd343bf2, 0xd6ee78e7, 0x7754dfb4, 0x66fda6bf, - 0x7c0d4aef, 0x6b5fc36b, 0x6be6dffa, 0xb1dfb4d6, 0xf69a27f8, 0x2d49ff68, - 0xf9701577, 0x3feed9be, 0xd06c0149, 0x3df791f7, 0x28de996a, 0x7b9e46f7, - 0xa7b70252, 0xb9fdfba2, 0x8bfbd380, 0x058f9f12, 0x1c789aed, 0xf135d8f3, - 0x854570ba, 0x71c61bb9, 0x21df951a, 0x0ee262dd, 0x6bb6bfbf, 0x3ff6d9ee, - 0xbc60fd0e, 0x1b5cc4a6, 0xff8c3bea, 0x37b940fa, 0x5f747487, 0x4abf5b61, - 0x69b83d22, 0x5cab8f15, 0xaf3c5230, 0x8eac1d7f, 0xdc46fbc6, 0xeceba96b, - 0x2da47110, 0x85424718, 0xfd4199e4, 0x7ef1c656, 0xe3574d3f, 0x371a3e8e, - 0xa418dca3, 0x7e85bcfc, 0xcdc0e309, 0x7bc5663e, 0x02cb7493, 0x069bff9a, - 0x265d9925, 0xb016da2e, 0x67cc0f33, 0x635c155f, 0x527dbd84, 0xb3d4f7d0, - 0xcfddbcf0, 0x5bd31e28, 0x1853edf0, 0xe143e98f, 0x219d7408, 0xf73f3c73, - 0x5fcfeec0, 0xe6daf981, 0x5ca197a5, 0x5acf6e8d, 0x43ebf7be, 0x6e7f6997, - 0xde1f5bd9, 0x1fe7b97b, 0x25ba75d8, 0x38c87da2, 0xf3264369, 0xe001d044, - 0x80fde62c, 0xf9f5c85c, 0xc5230af2, 0xfc01aeb1, 0xbfbe0215, 0x89cff8aa, - 0x3fb9e03b, 0x44eefb39, 0x65ea1d3b, 0x847e87ac, 0x9fe53fd7, 0x9c92fca3, - 0xa3df6051, 0x9b171dfd, 0x7215c76e, 0x8d6d95ba, 0x6a0718bd, 0xd13a344a, - 0xbb32cfcf, 0x07193eca, 0x7ee06d74, 0xfeffb475, 0xddbfbf5c, 0x9177fe49, - 0x944b2718, 0x9e7f2b7a, 0x4e4c8399, 0x3114f717, 0x6a4fa1f0, 0x655e5097, - 0x8d3f942e, 0x89fd8be4, 0xa4238a46, 0xc1dc445b, 0x171358b2, 0xfb06e350, - 0x9095ef13, 0x4bc3d3ee, 0xf18f9e28, 0x5c6f1c02, 0x11d693a1, 0x32c82f1d, - 0x86bad3e7, 0xd7f59f1e, 0xe6314827, 0x1a875a89, 0x279e889f, 0xea04f684, - 0x64f16599, 0x7bef444f, 0x79556149, 0xd7e470e1, 0x51d393de, 0x90329f7e, - 0x5e8a1c3e, 0x143ccf30, 0x42b4fe31, 0xfe63dfee, 0xe63d6478, 0xe3228787, - 0xef41ccd9, 0x2a0c102b, 0x7bb18466, 0x77ce1143, 0xc277cf94, 0x1ec9d8a0, - 0xfe87b504, 0xd7217d5f, 0x9730d303, 0x19f2386d, 0x81dbcbf7, 0x12dcb1af, - 0xd67d92b0, 0xf087fc01, 0x9527010b, 0xca9b80a1, 0xda85016d, 0x09ca07b7, - 0x21e0257e, 0x8ea04778, 0x5e02d7ca, 0x6819dfaa, 0x01e7f820, 0x819d951f, - 0x46ff54c5, 0x9bf04fc0, 0xbf04d581, 0x0160f685, 0x53d7a9c6, 0x4ad03bb9, - 0xed037bed, 0x081dbf04, 0xec0e1951, 0x8103faa0, 0x060f824e, 0x287c1176, - 0x70f82610, 0x479530e0, 0x7f545d03, 0xc101f03c, 0xc93ee337, 0x15df58ae, - 0x4f8578c0, 0xf77da276, 0x15a16fac, 0x7cfb6bed, 0x79c5159d, 0x04b74fbb, - 0x8d1d1ce3, 0xef131efc, 0x040e3123, 0xed086876, 0x67fcfb39, 0xf6a54c8e, - 0x19bed4b9, 0xc4a70487, 0xafdb82b6, 0xfa91996c, 0x0a2130d9, 0xda58eb9e, - 0xdc03d218, 0xed4f185a, 0xf93215b6, 0xfce9cf6d, 0xeedc8529, 0x336df922, - 0xa541fb70, 0x5c853583, 0xe429aede, 0x161f5cf7, 0xca4a73f1, 0x9e47ad8b, - 0xa6ed542d, 0x7f7187f5, 0x3fb079f6, 0x55bcef5c, 0xb597bc66, 0x72b3a3dd, - 0xcbdf937b, 0xb8bf603a, 0xc50f587e, 0x6e7cd985, 0xade6db2f, 0xe63975a5, - 0xd6ed48df, 0xd05347a2, 0xaff76f4f, 0x6deb439a, 0xd9ae2994, 0x82903bee, - 0x89cf6cf7, 0xf0db277c, 0x64a86f78, 0x8d9e7af0, 0xe3077f5a, 0xec03837e, - 0xec63d7a5, 0x496ed303, 0xc71130cf, 0x331cd47b, 0xe829d78e, 0xfe7121d7, - 0xc4ca0f63, 0xb0302f7f, 0x2db9e0fb, 0x5105df60, 0xb6bf540e, 0xbd55e302, - 0x289dbe85, 0x8e779f37, 0x9c03203f, 0xcfc7c75a, 0x82bf255d, 0xf79c3476, - 0xbf502de7, 0x5e4dbee1, 0x4db0ea5c, 0x6ec835ce, 0xcadff3ed, 0x4397f8c0, - 0x5a8f9ed2, 0xf9f62dbe, 0xb78f8782, 0xf14c9565, 0x378adb64, 0xbcf9075d, - 0x33ff91bb, 0xc38a3e8b, 0x5cde4c30, 0x86450ea7, 0x35fc9e63, 0xff7717ce, - 0xcd423aa6, 0xdf3a8f26, 0x6aef9c58, 0xb1e234f1, 0xc62f9b5a, 0x279286ba, - 0xbf239257, 0x81ef1429, 0x942cb164, 0xb819cf23, 0xe49e0adc, 0x052524f6, - 0x8f3c1a4d, 0xe6a02f9a, 0x0be7440f, 0x29e05efc, 0xde62c4cb, 0x4fd67ee7, - 0xd73a41bf, 0xbd1b3c17, 0x92e36794, 0x35874931, 0x7a12d819, 0xde2aa7ef, - 0x3d0626ba, 0x2853e5a8, 0x1fc100c7, 0x2e713216, 0x38f8ea9b, 0x64ce3e3a, - 0x2ae082b6, 0x4318358b, 0x33e5ab5e, 0x2b7f9c62, 0x759b74e4, 0x870dcedf, - 0x1a8f7cf0, 0x8b6a3728, 0xfd01b42e, 0x3d09e084, 0x7d4cd7c9, 0x2257d6e7, - 0x4117f5d6, 0xa18c5b9f, 0x6e87bc62, 0x504af187, 0x94bf22ae, 0xd582fc50, - 0x7d5de047, 0x1d843fee, 0x75c5fcf0, 0x3cff7429, 0xda1c6d6f, 0x4ccced47, - 0xf83360f4, 0xd046c653, 0x32e90d83, 0x8b387d06, 0xfc0e348c, 0xe226aa59, - 0xcbd70cbd, 0x60972835, 0x2616fbdd, 0x99ac3e91, 0x31acdeff, 0xc9f65700, - 0x65b2cf94, 0x9cd3cf29, 0xca3aeff4, 0x31fb7913, 0xf75df7ee, 0x9fbd2d50, - 0x67ca2194, 0xb283cfd1, 0xc2533d72, 0x0b952e70, 0x99bf142d, 0x133e417c, - 0x4851a7e9, 0x17fa3c7a, 0x6d735e3c, 0x0f79acaf, 0xb68f526d, 0x8f54603f, - 0xb7464676, 0xef3edeb6, 0x6153d3cd, 0xfca5f69e, 0xbf8bf6e1, 0x7070823b, - 0x24e28e95, 0x5064fbea, 0x4df14193, 0xf9819839, 0x8ccc1b9b, 0xbe6db9e4, - 0x60f28ad9, 0xc93c7a7f, 0x2cdbf6bf, 0xcbae8764, 0x3b438a6f, 0x556f34d9, - 0x8c23960a, 0x3b18adc1, 0x2dd5e6bd, 0x9127d937, 0x55f355bc, 0xec1cac82, - 0xdc8dbb81, 0xf73e09c8, 0xe51954f4, 0x9967cf25, 0xa796eaf4, 0xadd8f983, - 0xd4e1d695, 0xf9be4cb1, 0xba76f87e, 0xbeb896b7, 0x1da11a70, 0x7ca379e0, - 0x7b4115d7, 0x3f705a46, 0x9cb66d36, 0x6b7ca469, 0xf982324c, 0xccfd0b0d, - 0x658df588, 0x573e48e6, 0xf2fbe4f9, 0x87c63c7f, 0x0e595f87, 0x2bdc695c, - 0x3e417bf1, 0xfca19be7, 0xf210d369, 0x1f8ff554, 0x8bfce029, 0xf57a4b6c, - 0x7da6318c, 0xce22abf5, 0x9e46e567, 0x61bb32a7, 0xc3dd1d5a, 0xcc65bb04, - 0xdc517be7, 0x27a7b50b, 0x7b713dd2, 0xbde30b2e, 0x8e817041, 0xf8d27bc7, - 0xb98ded7f, 0x936a1f14, 0x3cc129fc, 0xb9f097cc, 0x01dafcf0, 0x7f308947, - 0xeb970e5b, 0xe2b7e42c, 0xb38c357d, 0xe0fd7238, 0x74b505ef, 0xa61ec8cc, - 0x789e85f8, 0x888c69cf, 0x1c5c63b7, 0xcfd117e3, 0xc2d5ee4d, 0xe1682e53, - 0xc0d0662a, 0x3c2d6635, 0x3785aad5, 0x7d3b7115, 0x3f5b5dba, 0x1d85a9c3, - 0x74e307d9, 0xc2dfcf3c, 0xf049e222, 0x447e5ef7, 0x68dd681c, 0x765f3efe, - 0xcb8a52f7, 0x78f0e5b6, 0x3695638f, 0x42c591ce, 0x732fe212, 0xd63c5469, - 0x863f66bd, 0xa30bed97, 0x5efc41e3, 0xa9a1f002, 0x7c8a3147, 0x9e68eaf0, - 0xd23dde87, 0xce08bdb7, 0x5f0c60b3, 0x4d1dabc7, 0xdac53f74, 0x5caf88d3, - 0xb0695f22, 0xe88a7cbe, 0xf90f1d40, 0x7fb11822, 0xf84887e4, 0x37be51a1, - 0x8be41e70, 0x2cfea460, 0xfbd036e9, 0xa1be62ab, 0xcfe543f8, 0xa28f7172, - 0x89f4dde6, 0x9bbcd4b1, 0x705f2255, 0x4ebe5457, 0x1936a39f, 0xaebee7fd, - 0xf8b1f195, 0x682ef910, 0xe5887ce2, 0x837f9106, 0xe22c187c, 0xa6f5887c, - 0x637856ef, 0x050b8bd9, 0x63bfdc5d, 0x224f86c9, 0x73acb7f6, 0xbe5e0685, - 0x910de1eb, 0xe3f751f9, 0xbf08303f, 0xed7e519e, 0x2f9db152, 0x2bcbff4f, - 0x48cd0ccd, 0xcf2807df, 0x319c1596, 0x5ea77bf2, 0x42eb9e23, 0xcc99ff61, - 0x2fd1f2b3, 0xf2e211db, 0x37889d6c, 0x33155b34, 0x3b9981c6, 0x50c71355, - 0x4b4d11e3, 0xd854b65c, 0x7c7f7247, 0x7ca56bc1, 0x14f9e1dc, 0xf1aa48df, - 0x32c6cedc, 0x9c6453d6, 0xdd62066b, 0xc056c18e, 0xd957f9e9, 0xc0c74133, - 0xf8174dbe, 0xb0fdc97b, 0x8f2467ec, 0xea68e42e, 0xa39c44db, 0x0b2dbf9f, - 0x8b3e70aa, 0xb0fb49db, 0x1e1aff31, 0xd1c6d417, 0xe73de24c, 0x343be3c1, - 0x7e226df5, 0xb5f1e572, 0x85d33971, 0x2fc621bc, 0x1adf1a8c, 0x7181fc73, - 0xabbdf1b5, 0x714f37b8, 0x2e3a184f, 0xe9cdd236, 0xdfdd9d69, 0x83317185, - 0x06667fe0, 0xf288993a, 0xe3e9ff80, 0xc1ae7e79, 0x198f8da1, 0xfa0baf30, - 0x98b8973f, 0x3efa8ae4, 0x0599fdb5, 0x27cbca12, 0xa4e8fdf0, 0x5a24f2c1, - 0xde44d88e, 0x811cb47c, 0xd37034f9, 0x36cf5cc3, 0xe50f8a4b, 0xfe7ef473, - 0x7587f17f, 0xc8bbe389, 0x778eceae, 0x0f632e9a, 0x638205b7, 0xf175b9f1, - 0x0778c5fe, 0x918ef77e, 0xe3944f69, 0xf88ceb7b, 0x298ec56c, 0xb60f3173, - 0x13ebf04d, 0xa7a23a69, 0xb7d3dbf4, 0x29e823ea, 0xa173e8dd, 0x13ae9c3d, - 0x87f85ff9, 0xd227b471, 0x318c6db7, 0xa9d76abf, 0xd601adb0, 0x6d8e7111, - 0x9fee9ec2, 0xadcc8eef, 0xd27188fa, 0x34b1be4d, 0xa3fe7f5f, 0x87e5af98, - 0xc459b7cd, 0x6cf9d4c3, 0x67f76a77, 0x7f69fa33, 0xd487a136, 0xfee336f9, - 0x15d5f062, 0x75fe13e7, 0x69777cff, 0xf93367f7, 0xf5367f69, 0x7cea1b3b, - 0x3e6c3f2d, 0x76cfe0bb, 0x3d97def1, 0x64377f9e, 0x9a23f7a8, 0xbdccf3fb, - 0xed2f9466, 0xe850bc6a, 0xfa5173bb, 0x3be849ae, 0x6973f9f5, 0x3dff14b9, - 0x7326f877, 0xfa873d2c, 0x933b098d, 0x09933b09, 0xd9e1133b, 0x0d57a735, - 0xbbfc7a07, 0x95cf371d, 0xbecfaf41, 0x1cf8f4ff, 0xf1d9df80, 0xe832b98b, - 0x9eafd9a9, 0x1e0b337e, 0xfbdbfe29, 0xe9f4fc38, 0x5bb4073e, 0xadcccf82, - 0x18693805, 0xbaeacfd7, 0xb97779d5, 0x7cb95db9, 0x6f8f1e75, 0x3d459c82, - 0x67e39cd6, 0xcafc7f18, 0x1f349bd1, 0xeecf2ffa, 0x03105f4d, 0x7cb96a2f, - 0x1e7f2175, 0x9889c0ad, 0xaf48c6cf, 0xc7bea8dd, 0x8f7da752, 0x23692925, - 0x2c7187d9, 0x96394564, 0xfbd0f660, 0x7316d797, 0x533370bd, 0xe15fb81a, - 0x1c79102c, 0x4dcbdef4, 0x6b5c62e5, 0xfdb12fe5, 0x09e79d66, 0x79ff77f4, - 0x68e1bcd2, 0x7379ab3e, 0x3bde06a3, 0xde7dfedd, 0xb1fd9e4f, 0x64e56dc4, - 0x36998f1e, 0x7bdfc9ca, 0xa22b888b, 0x3e143c5d, 0xff73753f, 0x1e9f007e, - 0x0f54cf8e, 0x37b5a7c7, 0xff9c0d69, 0xf4de94f2, 0xc34f89c7, 0x0835f131, - 0xfbf851af, 0x7ea99b93, 0x88ed1ea0, 0xc55be12b, 0xd85f9aab, 0xc80b392c, - 0x9a19675e, 0x14c660fc, 0x1e7bac67, 0x3d48cfa4, 0x197bb46b, 0x3486a3da, - 0xeff98dc5, 0xc7d17fcd, 0x1573dbcc, 0x525ef88b, 0x367de53c, 0x1fc91927, - 0x93349fdf, 0xb659fc61, 0xd4bc234c, 0x3e51d526, 0xeb187ea6, 0x3a357f44, - 0x7c9f5d0f, 0xe909e53b, 0x4061e86d, 0xecc79fd9, 0xe95f2331, 0x5d92563f, - 0x99570048, 0x295f2e87, 0x26753d0f, 0x324f43cf, 0xd85e313a, 0x998c689e, - 0x9badfe87, 0x71fb5dfb, 0x1fb8697f, 0x886eff23, 0xe56c97d8, 0x9f58eef7, - 0xab46f500, 0x5dfc518f, 0x615bffec, 0x4dfda907, 0xf9433f56, 0x4e2a37a0, - 0xa9f45fb4, 0x77e07f5c, 0xe231dc5b, 0x0dbb5f28, 0xa3fdfcf4, 0x99cf5cac, - 0xfb3eddb9, 0x27dfb137, 0x44962b28, 0xdd3624bc, 0x3737450d, 0x9dde78ea, - 0x2d7397ca, 0x9c07ca46, 0xf7d3b16b, 0x2102e66c, 0xf446a4f6, 0xfe56eebf, - 0xd8acb53e, 0x7b7e9e91, 0xfe5f94ed, 0x00b5e196, 0x66a7db97, 0xc2bde818, - 0x28f31253, 0x5df383a9, 0xa994debd, 0xea1bccb8, 0x7645af4f, 0xc8c3182c, - 0xc1757a4e, 0x4e95ad43, 0x8aea8ff2, 0x737d9e91, 0x770fa2a6, 0x77d8c363, - 0x04f2ffb1, 0xfbd5cf2e, 0xfc09e5a5, 0x646bde7d, 0xffec6cdf, 0x4917c555, - 0x725f48d5, 0x2bae0e6f, 0x33dd3fa2, 0x5b9ff445, 0xcffa813c, 0xf5ddafe6, - 0xce3977d2, 0xc8f99da5, 0xec7ce8c7, 0xf429ecb1, 0xbde458b7, 0xe81f9086, - 0xa3d64577, 0xce22c5bf, 0x6e505a53, 0x4f218eeb, 0x3ec332d4, 0xa042e46e, - 0xb18c8cd7, 0xcff5aa54, 0xa175f47a, 0x90fce718, 0xec1fe738, 0x6ac3b4f7, - 0x3df80e27, 0x843cefe0, 0xe172f8f8, 0xb0f1f4a9, 0xbf6a07a5, 0x6ec7bf26, - 0x16ceffec, 0xb00371f9, 0x2db3bef6, 0xdf8c5bd0, 0x87886019, 0x8bf91189, - 0x25f6bf62, 0xefd0526b, 0x20f4b381, 0xbc0476dd, 0x030d6b23, 0xe42cbfcf, - 0xd2160b08, 0x2eb106f3, 0x0ceb5a47, 0x2c38bb8c, 0x6073ca3a, 0x6791aacc, - 0xa6536a73, 0xbb0ba1a6, 0x2716299c, 0xe45df7fa, 0xfbe06417, 0x7c9f180d, - 0xf78636e7, 0x9d69595f, 0xfd75da12, 0xc6f788f3, 0xe17b8957, 0xed2d5f3e, - 0xefd6c327, 0x5ff23197, 0x507382d3, 0xc33df56e, 0x92f19457, 0xc691ddb6, - 0x5dee1ff3, 0x02721f18, 0xed2d67bd, 0xb04f4fc2, 0x30f8700c, 0xa9719fa6, - 0x7282d5d9, 0x140957e6, 0xe7b7d677, 0xfbc820b3, 0x1bfbecb0, 0xf9c877c2, - 0x6c4f2e90, 0xb65b9e16, 0xb9ec9e28, 0x0675a976, 0xe8f731f9, 0xd178ac58, - 0xa7ee62ce, 0x2b628ffc, 0x4fb5cfbf, 0x1f63f4e4, 0xb8e1723f, 0x77ffe7ab, - 0x49f99e84, 0x7fde93b2, 0x4da3ed52, 0x8e47f843, 0x5f213a91, 0xf8115e84, - 0x199f3333, 0x792f45f9, 0xc774b079, 0x96bdaf6b, 0x5b53e8ce, 0x841b4748, - 0x138ea3fd, 0xc6a21f9f, 0xf243c578, 0xb87ab252, 0xedfab0be, 0x75af3841, - 0xce63e9df, 0xfba085ff, 0xd90fd935, 0xd3ad7fb1, 0xfa32c6e7, 0x9c96983d, - 0x3e78dd7b, 0xe9fb332d, 0x96baec95, 0x61dfce33, 0x28f0563e, 0x9fd837cf, - 0xefc3685d, 0x1b0e5941, 0xe265d364, 0x27d046f1, 0x19d8cbce, 0xdeaf9146, - 0x99e78072, 0xbaca58b6, 0xc5a1af30, 0x6a465692, 0x56f3c2d8, 0xcb16fed5, - 0x1607d221, 0x5adfdf85, 0xb8487f50, 0x0947c04c, 0xe110ebae, 0x5077ed43, - 0x128b5dc8, 0x5a5ef866, 0xfd4ad29c, 0x83d7b2cc, 0x34e6ca79, 0x6644f746, - 0xe217f02b, 0xccc75f35, 0xbec9f431, 0x5a4fae62, 0xaabaca4a, 0x7e327d69, - 0xd8b58eb9, 0xe7a4eccb, 0x7cf0ef11, 0xcf968673, 0x577813bf, 0xf91669c7, - 0x4eae77b4, 0xc38ed609, 0x1bf79338, 0xcb16e7a4, 0xf5107302, 0xcbf8e25a, - 0x391a678e, 0xd7fb78d4, 0x43bef18a, 0x2c4fae79, 0x0678e2b3, 0x8d15f7c6, - 0x9c62e1f7, 0x7bfbd5ff, 0x47bd2cc0, 0x581d304d, 0x7deb1ed8, 0x13f3feac, - 0xcfd1f2f7, 0xbc7960fd, 0x02871b56, 0x091eec79, 0x72565afb, 0xd53550e6, - 0x0bd3f8f0, 0xfd519fc2, 0xf6317492, 0xbf7f120b, 0x2bc5283f, 0xe10c5df4, - 0x69c7a4a7, 0x3ef030f1, 0x6f873f2d, 0xde1e781a, 0x7c4c6937, 0xd7cb4e87, - 0x38ff1cdf, 0x059f9345, 0x7131ec7c, 0xde23c63f, 0x3888f5a7, 0x6f18c21d, - 0x049d17a0, 0x89c7f7ff, 0xc33f9c1b, 0x4099acef, 0x5c60eb8e, 0xfa27e1c9, - 0x5dba3936, 0xe239efc8, 0x78d10ffb, 0x2e48c9fe, 0x7a47a5af, 0x51af785c, - 0x119bd69b, 0x7c5fdf8b, 0xee0642f8, 0xfd19c5e7, 0xdf743b79, 0xe769e2f4, - 0xcbc402e6, 0x6ffbed11, 0x474df8ea, 0x22f8a7ce, 0xe5c0a5fd, 0x3a4b2fdf, - 0xd92571b3, 0xddb80b8d, 0x7dfa7ff8, 0x73e617b3, 0xa497753b, 0x084fcf95, - 0xfc141cb9, 0xd320bb60, 0x2aee43f7, 0x3a40adf2, 0x0bac936a, 0x3ce72e50, - 0x9af2f3cc, 0xb3d55b1e, 0xb47f0628, 0xd5fdf28c, 0xbabf08c8, 0xe491bd7c, - 0x3725b35e, 0x28f772f9, 0x9fbb9f43, 0xde7a94e4, 0x79988f55, 0xdb8f8abe, - 0x7bbee9d1, 0x3a260f29, 0x7ea8653f, 0x449d23d5, 0x137f6a0f, 0xc5f28f8e, - 0x15c52372, 0x818fa1ce, 0xb72b3b71, 0x59d7a233, 0xc098c889, 0x7d0663f1, - 0x49607499, 0x106b8e1c, 0x6a0bdcfe, 0xcca1a45c, 0xde7889ec, 0xb9995b70, - 0x9a4e823a, 0x8e0fcf19, 0x2337ff1e, 0xac22fb55, 0xa80c63b1, 0x94c6317f, - 0x97ed9f26, 0xf278643b, 0x0395b4fc, 0x0ee3cc7c, 0xc5a3e743, 0x232dbe71, - 0xf30dac7b, 0x5e0ec0d2, 0x0460b0d3, 0xf64db7e2, 0x3c0368bd, 0xa2687ef4, - 0x0bdfea3c, 0x7c16ed3e, 0x05f9d43a, 0xd23001d9, 0x1d9c7b18, 0x80e297c4, - 0x2327c64e, 0xebe7345f, 0xf63142ea, 0xf3ec5c79, 0x7878f632, 0xc7b3f7e4, - 0x1afe890f, 0x6ded1c7b, 0x46fdd44f, 0xb6768c24, 0x7e3d8627, 0x05f11242, - 0xc2742791, 0x0dd5dce0, 0x39313978, 0x5697be99, 0x5defc090, 0x527fa04e, - 0xabc87e06, 0x7ed1f3a7, 0x7ff52d99, 0x43f84917, 0x47f0608c, 0x62f905fe, - 0xb6bff30e, 0xe23e2248, 0x1b7835f7, 0x73e57e9f, 0xd19236de, 0xf9c036ba, - 0xdb46fde1, 0x6233f9c5, 0x8ea467dd, 0x5037fd52, 0x13ef1165, 0x889d3c33, - 0xf741acfb, 0x72f75174, 0x9fd36d78, 0xdc1fac77, 0xed7286ff, 0x8b86d9bd, - 0x5a622e3c, 0x4b8f42c2, 0x6daa9798, 0x10cea9bf, 0xb9a82f7d, 0x6bd9bb4f, - 0x7d0f5e88, 0xd621d417, 0x1f71dd9b, 0xcd4fbfdd, 0xa644f9e6, 0x04e28c65, - 0xa66df7d1, 0x3d1e5db1, 0x8c0dcfda, 0x38e8fdec, 0x52a9e639, 0xb181b0fc, - 0x79e5122d, 0x7973df6b, 0xfe73fea6, 0x3ad6947d, 0x760ec79c, 0xd1d3da10, - 0xf7a849ef, 0x51f7ea5a, 0xdfab3c55, 0x4dbf4a8f, 0xc163eb47, 0xc6aed429, - 0xb87bf1fd, 0xf911e955, 0x7f582be4, 0x2b7f7a7f, 0x9bdf7b18, 0xcf29eadb, - 0x7fbc7320, 0xb29a186c, 0xc8784614, 0x6fc8c85a, 0xf2683c00, 0xdbd94c09, - 0x16e79f69, 0x224c3633, 0x33da683c, 0xfdd3d340, 0x7e6d42c0, 0x0353ec01, - 0x57abfb47, 0xd94d53f2, 0xf39597f9, 0x9a638a57, 0x94e4bdc4, 0x97fbe251, - 0xed14aca5, 0x9edbf4a2, 0x0738f3a1, 0x5f7181e7, 0xdd629c74, 0xf1826e3b, - 0x77fc8fd1, 0xe2cd2fc1, 0xaefd5b6e, 0xf4c8f30f, 0xce549b1e, 0xf30d2cd7, - 0x12e97bf2, 0x8a6e7c46, 0x8fcc6667, 0x1e4c2a97, 0x04c9bbc4, 0x32596c30, - 0xd4067332, 0x7b3c45eb, 0x8464c48d, 0xf3315599, 0x5dfaa3f8, 0x577d10a1, - 0xd479a868, 0x20b22bef, 0x679d4e7f, 0x2ef577d0, 0x7bf93cf3, 0x6be7e8d6, - 0xcea99e29, 0x87fe143f, 0xbfde8efa, 0x8137bcd5, 0x441d53c7, 0xf4038daf, - 0x417cf04a, 0xca3cf88f, 0x66d5bb85, 0xfa29577b, 0x4c1e670f, 0x114a3650, - 0xd2ce08fb, 0x7e03eff3, 0xd7faf1bf, 0xbc927761, 0x1897dfef, 0x8beefbef, - 0xdae422fe, 0x09597c3a, 0x191a5ef3, 0xfba431e5, 0x29973faa, 0xa0f600ff, - 0xdf111391, 0xd6f18049, 0x1fefce3d, 0x3e77e336, 0xc0e7fef0, 0x13edfe40, - 0xd1f76c16, 0xbcd43677, 0x5da3cc5c, 0x3ef0325b, 0x837df472, 0x89c611bd, - 0x99b26f98, 0x9f401305, 0x0531f4a4, 0xb9ecf3bf, 0x03a65468, 0xa07d6c7e, - 0x93bf0150, 0xa5ee8999, 0x337ead2a, 0x0ae10eff, 0xef676916, 0xefa56e97, - 0x64bf86bd, 0x3e14bf94, 0xc3ee88cf, 0x70c4c39f, 0xddf8ff2e, 0xcbe47afb, - 0x7a5d7da9, 0xfb93f3d4, 0xf67fa4fc, 0xed3d4fd9, 0x9962e7e2, 0x751f9111, - 0xcf545b1d, 0x979f8ae9, 0x5f27ea2c, 0xfdf86a30, 0x46a35eda, 0x5b17c81e, - 0x65fd46be, 0x67aa89ea, 0xe3e33fd3, 0x2dde28f9, 0x53edb5db, 0xdbd03e44, - 0xc35fdf2a, 0xbc73a1ae, 0xcf331698, 0xd5dce06e, 0x71e26e73, 0x79c7c674, - 0x9ff7946e, 0xff404d46, 0xe87147c0, 0xd82fc464, 0xdd952917, 0x58798ecc, - 0x8e994ce5, 0xf3b2bd72, 0xe487a41d, 0x3c0f3cb3, 0x5ffdfc7a, 0x7e8595be, - 0x9dc99ec3, 0xed2f6859, 0x3d15f2f9, 0xd3d5578e, 0x193eb0cb, 0x58a41e4a, - 0x10aa784c, 0xcf5033b4, 0xf59144e3, 0xe74a9eb4, 0xcfe4e565, 0x871a4e50, - 0xd933df6e, 0x87e4c2c2, 0x3da02675, 0xfe7c7cc7, 0x57cab364, 0x70972fec, - 0x9f81845e, 0x52ea54f6, 0x7b9f616a, 0x6c15919e, 0x46f3d3dc, 0xe7bfce02, - 0x7acd39ec, 0xf322fe98, 0x5afbac45, 0x2b53ee71, 0x7efec97b, 0xf92bac4a, - 0xa1c52f6c, 0x30de9553, 0xc3d4dbea, 0x37fefa7a, 0xc8bcf0b3, 0x38a14c61, - 0xfc5eba9a, 0xd73e2a6e, 0x88de7282, 0x5632b3fb, 0x287eec28, 0x55832a33, - 0xcc9a8f98, 0x6b484a76, 0x417d2b53, 0xa5e4e7a4, 0xad939e9c, 0xbf18c3fe, - 0xa3af5e4f, 0x59f24538, 0xcbf406df, 0x0565cb92, 0xf84ae4c9, 0xb7f310ec, - 0xf9d4f98a, 0xa88cf5d5, 0x7ee84bf4, 0x62e3b324, 0x132aaefe, 0xcc5abf8e, - 0x59eb14ef, 0x2c3be8c5, 0x55ad67c9, 0x83272fe8, 0x33df419d, 0x9a79e2b8, - 0xb745f335, 0x99d94f27, 0xb1e0e745, 0xe30ad91e, 0x365b64a5, 0xceb94154, - 0x32ff23a1, 0x3c5187a9, 0x9d27a93d, 0x4f527de4, 0x8a2728a1, 0x0f4269fa, - 0xd4933970, 0xaf2d50f3, 0xa4d2a16f, 0x3f8717ca, 0xda98fb8c, 0x717cb8cb, - 0x98be4978, 0x517cb8d2, 0x9556b8e9, 0x325acc2b, 0x0ff7ea1f, 0x06b5acff, - 0x73f77b9e, 0xbbe5fefe, 0xbcbe5cd9, 0xfbf725fb, 0xd3bf694d, 0x42aa5ca3, - 0x4dfa05c3, 0x33edc0bb, 0xbaab1f95, 0x48113625, 0xe7839a63, 0xc8ba1f87, - 0xd9843b9f, 0x63af00d5, 0x9529c912, 0xdd056b6e, 0x83eab3ae, 0x81fed849, - 0x3477de89, 0x98e5ce39, 0x83fe1ec1, 0x7c41f7ae, 0x33f7f8ef, 0x415def7a, - 0x437e82f5, 0x9a2e494b, 0xe4396c84, 0x3e416058, 0xae487984, 0xe918721e, - 0x3a080ebc, 0xe9af673e, 0x5b3fc308, 0x69fcdfcc, 0xc1ffd43e, 0x9340eb9e, - 0x1e973d4c, 0x885f2f41, 0xe82b3bf3, 0x7bdd29a6, 0xfc04c953, 0xcd1e62fe, - 0x0dfece7b, 0xdcb27fbd, 0xc69f1ff6, 0x3aa72efa, 0x4f7cfa8e, 0xcf19a568, - 0x1f9bd0f5, 0xabb4409f, 0x7b235fe3, 0x7ee3e4ef, 0xd0f89a33, 0x78cf3b12, - 0xadf3fc90, 0x8b7f9688, 0xc80f864a, 0x91667abf, 0xe7121e79, 0x1e4259eb, - 0xddb8554d, 0xe7e56f5e, 0x5fb25f55, 0x8b8afea6, 0xd2af55f6, 0x5ae4f28d, - 0xf29b7fe4, 0x7d4bd124, 0xbd97a73e, 0x0a0f9e82, 0x63ecce7c, 0xed97e89d, - 0x196e982f, 0xe23ef80b, 0x1cff13d2, 0x52c6bb19, 0x291dcf06, 0x024bf095, - 0xd6c97a6c, 0xcf00a9b5, 0xa7a22452, 0x1dad92fa, 0x967fd04d, 0x03a94135, - 0xb3f9e8f8, 0x0eaf3416, 0x9784bc05, 0xe3f872e9, 0x1b9e1754, 0xcaccd3c7, - 0x4ffe8cb0, 0x8cbf63bd, 0xc46df6fa, 0x2ee311ab, 0x7567c11e, 0x6a571f04, - 0x238fb82c, 0x2f2126a5, 0x5e51e33d, 0xd537cace, 0x7c75a18f, 0x1a4c6c7d, - 0x506f77be, 0xa73c95f8, 0x7e82c9ff, 0x6b27ccea, 0xccdfa053, 0xd7196692, - 0x912cd47b, 0xd7da3cfc, 0xc793f944, 0xd2ac393b, 0x74073d2d, 0x5b6fbc79, - 0x6fb61273, 0xd53e4897, 0xe21d2f2b, 0xa7d38fea, 0x0b0f7e3a, 0x3077e1b6, - 0xb7af29cf, 0xb1f53e60, 0xcccf05be, 0x7f1c3c01, 0xb8c43f53, 0xc0ad1f4d, - 0x244cdf71, 0x356d9e3a, 0x8cb1f469, 0x5e84694e, 0xd36f1ead, 0x0d4af5c0, - 0x29cfd3c5, 0x7806e592, 0xad5df3de, 0xd191397b, 0xbd77da52, 0xe14c7be8, - 0xa1cc797c, 0xd63cbe23, 0x8a9cb8f7, 0xfb4659f0, 0xde769991, 0xb21a92fa, - 0x5b29ceaf, 0x826744f5, 0x54f1d50f, 0x4f8a3e3a, 0x9ced1e23, 0x6df68fff, - 0x1dbd20b3, 0xe323bf75, 0x89675d39, 0xa1d0571a, 0x5df0dfaa, 0xda9fa471, - 0x7ef3fb51, 0x3851eb86, 0xd7946bfe, 0xd57d238f, 0xa7a2643b, 0x9afecaa3, - 0x27bf8614, 0xffecd262, 0x9ac91dfe, 0xda7597f1, 0x5db47034, 0xdbfdcfb5, - 0x0ec4cba7, 0xd847a466, 0x3ec2f947, 0xe0771fd2, 0x1768aefa, 0xf7e8eb29, - 0x45d90649, 0x8a2edcf9, 0xbe5487b6, 0xb889d66e, 0x65c78eac, 0x58dff9a3, - 0xf1eec3fa, 0x8e492ad8, 0xc65bbfbc, 0xbe9073ba, 0x8612a3e6, 0x75d01ef1, - 0x15fc23a7, 0x078b6deb, 0xccad7c39, 0xbfbf6976, 0x3f37bfca, 0x1e77d4be, - 0x367495e5, 0x6561df4c, 0x07e518ab, 0x9e786be8, 0xad665e11, 0x258bd488, - 0x8d2df1fd, 0xd84ba45d, 0xac78859b, 0xf1e46b38, 0x38e89e8f, 0x851fea97, - 0xae2bf225, 0x93ea2e52, 0xe67bb8f9, 0x7f6778f0, 0x938f3379, 0xe5fc0915, - 0x5d691a94, 0xdcf7808a, 0xb59efb16, 0x41fa54a4, 0x07dfa2f9, 0xef8029df, - 0x61e690af, 0xb1553d9e, 0xca5291d7, 0x9777b5e3, 0xa14af278, 0x15f12a2c, - 0x3d5e2296, 0x77d35f60, 0x9f643dc5, 0x33bce3a9, 0xfd16e3ca, 0xbcc96146, - 0xee8f0edc, 0x6863ed07, 0xe3d8869c, 0x7a38fb40, 0xf6ec6e7e, 0xfc39b843, - 0x30fb237d, 0x0c0643d2, 0x52f2a664, 0x16e5e32a, 0x8846aefa, 0x1e0de7fb, - 0x9146f3d2, 0x103788af, 0xf4c7fc91, 0x1cbe34f5, 0x58f7419e, 0x8325d82d, - 0x7691f9fb, 0x6a84ac94, 0x6aade322, 0xdf94a8b9, 0x1528ce73, 0x604cf3ef, - 0xa8afc813, 0xea3cfcbc, 0xc3cd43f3, 0xc85765ec, 0x63f35e7b, 0xc3fa49d3, - 0xa55f27e4, 0x4a0e607d, 0x1f39df91, 0x4a89bf6a, 0xc28a1c94, 0x5cf350d3, - 0x22dc79ed, 0xd76af6e8, 0xcc7a655d, 0x2ed1f94e, 0x056b07ce, 0xd5dbf57d, - 0xbe3f1e3f, 0xfe861f3f, 0xfefbd9ca, 0x4a7ef893, 0x37a56842, 0x145e7ec6, - 0xe531f9fb, 0xce70d3c1, 0xfba18c1b, 0x0799ded1, 0xd20263a7, 0xf1f2c77b, - 0x9eb005f0, 0x2dfcc537, 0x6feb9596, 0x1c5b4785, 0x1ef998ba, 0x7a78fe6f, - 0xd93f0da2, 0xdce395ff, 0xa7206dfb, 0xd07d1e5b, 0x7581b0ac, 0x15d96b30, - 0xe347f9ce, 0x6d5d7513, 0x625e305b, 0xf7aabd4d, 0xaf5c5a14, 0x697de024, - 0x764de7ed, 0xb4460efc, 0x43c6a03d, 0xc6a5bd54, 0xa4bb544d, 0x1fe3c1c2, - 0x7bfced33, 0x69f6153d, 0xb20fdfa4, 0xaff21aae, 0x226d3b30, 0x19fd0ab1, - 0xe4fb5add, 0x4657bf3a, 0x9eda2a3b, 0x45334da8, 0x7abd07d9, 0x1715df94, - 0xfe54fdb5, 0xc454acf8, 0x17795451, 0xcf9a4765, 0xbb40499f, 0x670bedeb, - 0x8d142e28, 0x5c2eeb9f, 0xaebd9fde, 0x83f74f5d, 0xb7ad71d1, 0xfdd2e42f, - 0x1baf11a0, 0xcccad4c1, 0x808cc43f, 0x6b7b4c97, 0x18ec1195, 0xf82983a3, - 0x58fc36dd, 0x8d0dc633, 0x7c9c7817, 0xd7fb9d84, 0x2fc18b89, 0x95335185, - 0x78c17da0, 0xef48ce7c, 0xef5d99d3, 0x09bdbd91, 0x9e2186ea, 0xa6199ec7, - 0x5307118b, 0xc08a63cf, 0xb7e66eef, 0x4d81efe3, 0xf7f78bb1, 0x59db462e, - 0xa22d3cfc, 0x2d62e27f, 0x3ce22d3e, 0x435b8327, 0xd3ec79df, 0xe7116f3e, - 0xfb1a596b, 0x63a3ec1c, 0x7aa2439f, 0xc5b6130e, 0x596c39e1, 0x758a4dbc, - 0x2f8b990e, 0x845b0e7f, 0xefd2a95f, 0xb204acb4, 0xe8a6f7af, 0x7b41fbe8, - 0xcb59c313, 0xb2fdfe31, 0xaccfde99, 0xb4367110, 0x6b9f10a4, 0x84bf97b7, - 0xa371db71, 0x7b8e74f5, 0xbcffd125, 0x60feff8e, 0x1fea78cf, 0xf883b327, - 0xfb0780bb, 0x1bbbe9aa, 0xd3bbfcd1, 0x33dd007a, 0x3db9ceb6, 0x839c016b, - 0x9980fb25, 0xcf839bfb, 0x4a3fef07, 0x7b4bbe05, 0xa654b9f8, 0xbda3d49d, - 0xec66f25e, 0x8fe351f3, 0x3a9da47b, 0xaa362b20, 0x98fc8baf, 0xeca33b91, - 0x642db3e9, 0x47c65b67, 0x39c0f7d5, 0x9f8ebdd1, 0xa1d916ec, 0x87ebaf3d, - 0x114aa738, 0x7d7f3087, 0xfb65e28a, 0x7e714efa, 0x25c6d1e9, 0xfe5df727, - 0xe7135e9c, 0xa1c453b4, 0x00e22e7e, 0x7e7fc29d, 0xf2a4e023, 0xea9b80cd, - 0x04280adf, 0x0b940aef, 0x77cfc161, 0x47cb3e56, 0x84aaaf17, 0xcf47edfb, - 0x7f7dbf73, 0xbe83a862, 0x42de74ef, 0xbda417df, 0xdbbf144d, 0x2c727c07, - 0x1fbf49ce, 0x4cdb3478, 0xa5a3b3f1, 0x8a7bfbbf, 0xd16b7cbb, 0xc70bb8f1, - 0xeb4e7ab3, 0x6f184e70, 0xee8b855d, 0x47e036a5, 0xeeffa114, 0xffbe8932, - 0x040e1b34, 0x3a5445ef, 0xf169f537, 0x65ff0f59, 0x1ddff195, 0x617f42c8, - 0xa4e88b8c, 0x2273ef42, 0x4fba373e, 0x571e5f91, 0x871beed8, 0x7af18071, - 0x14fbbe26, 0x3bac4534, 0xe0426f0e, 0x44895379, 0x0a1a73df, 0x86e5d1bf, - 0xa32fae54, 0x3475ffeb, 0xdd1b83d7, 0x773ce8db, 0x50b2ba3b, 0xf913efaf, - 0x2964b310, 0x285fbf48, 0x1cb1dd77, 0x65915bf6, 0xc011bb1f, 0x6853a32d, - 0x4f4afbfd, 0xd8f81c53, 0x21c65785, 0x76b31dfd, 0x79ce305a, 0x53dfc9cc, - 0xf9951387, 0xf29db77b, 0xa4f2312d, 0xe958f2d5, 0x95fdfa22, 0xef7cfc7f, - 0xdf7cd1da, 0x0af5524c, 0xfb815b8c, 0xdef9424d, 0xc3f902b2, 0xfc83b998, - 0xaa73e8cc, 0x88b35f70, 0xfc64f3de, 0xb6bf4f7b, 0x3f782c86, 0x0267ed1c, - 0xff426c7d, 0x3d04f778, 0x5eadaf7d, 0xe782e7e6, 0x1fa4e788, 0x997e13a3, - 0x65667c76, 0xc0fa633e, 0xde1d6079, 0xf13ad0d7, 0xadefaa3e, 0xf86292bf, - 0xc9d683b5, 0xf9589efc, 0xcdcfd1b0, 0x9a20b276, 0x1615b386, 0x709fa176, - 0x99c69f30, 0xcce3e56d, 0x9b7c7112, 0x1759ffa0, 0x81df9475, 0xcf80d6f4, - 0x7927cc95, 0x50f5cc72, 0xb7ac1d57, 0x41c6ce1e, 0x569346fe, 0x5b39090e, - 0xf745525f, 0x07dcc7bd, 0xbfbea3c6, 0xe1e574be, 0x9fc22732, 0xb74154d4, - 0xd52fa529, 0x945a5d20, 0x4c2f8a2e, 0x5d74cb76, 0x36b97d78, 0x17afd14e, - 0xb44bf4a3, 0x928fa8be, 0x54f7113b, 0xf9c4434e, 0x4b9f72cf, 0xab83a488, - 0x2f1ccbc7, 0xd67baf7e, 0x1da71e05, 0xe9f7978c, 0x7803a573, 0xd8ef3e89, - 0xa73e8978, 0xeaad3c01, 0x8c1dcbaa, 0xbf6f155f, 0x1ac9792e, 0x8d1be799, - 0xaf8a1fb7, 0x4156d1e6, 0x579e5caf, 0x3b7dbe08, 0xb771443b, 0xeff94bb7, - 0xff731d4b, 0xb3bfe296, 0x0d63a858, 0xcbe045ca, 0xe8f94239, 0x344ce423, - 0xf4f8061e, 0xbf2e283f, 0x28b7f3fb, 0x21caaa2e, 0xea25f213, 0xea1fc113, - 0x1f9099b9, 0xf02f6f91, 0x2d5e87ef, 0x457ca87f, 0x383f21eb, 0x1fcc8fa4, - 0x5fc5dffc, 0x18cd717b, 0x52167617, 0xd1cab83c, 0xac7bc7a5, 0x3dd250c9, - 0xd27f8892, 0xf5919c3a, 0x591c6e3c, 0xa12f714f, 0xa6b8d4f7, 0xbb3ebeda, - 0x5518412b, 0xc24d47a4, 0xc4fd51de, 0x64538e7d, 0x54faaa7f, 0x57fef716, - 0x08f74fab, 0xfb543a7d, 0x79bb73de, 0x43cbe7dc, 0x1c800f3d, 0xa46f9c9f, - 0x0e4cb8ef, 0xa3dfcc3f, 0xfe498470, 0x9137746f, 0x69fb0c1f, 0xe604a346, - 0xf3e64475, 0xf3bee5a9, 0xefd60a6d, 0x0af4bb95, 0x16ff07f5, 0x568603e0, - 0x0d869dfa, 0x137d738f, 0xd651f457, 0xba83dee5, 0xe6994fb3, 0x61efc24a, - 0xdf835f6f, 0x8c2a0b01, 0xb598ebbe, 0xee458bb4, 0xdc31a5f7, 0xff9c9daf, - 0x68071dd6, 0x69ea1fdd, 0x035768dd, 0x9d964f9d, 0xcfe7050e, 0xfd23dbf6, - 0xf7d97dec, 0xb7009dda, 0x086c697c, 0xa3c37ad1, 0xecf3017e, 0x078d5733, - 0x73ed8d4b, 0x0bf5181f, 0x7346c7c0, 0xa3cc04d5, 0xdbdfb6ac, 0xdae51f3e, - 0x60265bd9, 0xbcec1bfc, 0x83b7d456, 0xcdb7dff6, 0x5d3bbf8c, 0xd69f78ed, - 0xabafa231, 0x5abfbf06, 0x48f7e0ed, 0x87bed1be, 0x7b404cc6, 0x73c1ec39, - 0x0c9f344f, 0x164cdd22, 0x2f1765eb, 0xbd41fc51, 0x9e73d997, 0xf8ff47d3, - 0x8fb80f40, 0x455cbf6b, 0x7db922f7, 0xa026f9ba, 0x3c7d75d5, 0xf1db0c7f, - 0xbf58e07b, 0x001d8628, 0x4be75cf3, 0xcaebf3c6, 0xde8637ba, 0x36fbedcd, - 0xf6e783e0, 0x44bc7064, 0xc31e6fb7, 0xafb882ed, 0x9272cfde, 0x7ff5c03d, - 0xf312c0b0, 0xa9b7553b, 0x3b1ad2fa, 0x552d450f, 0x23daa579, 0x21b35f80, - 0xc69bbf02, 0x7cfdff70, 0xf103a7a9, 0x7fe77df7, 0xe50b710a, 0xf6cf52f1, - 0xae91c331, 0x97ad5f04, 0xee01c663, 0xc5a3f31c, 0x13416e2b, 0x73beabef, - 0x86e96fe9, 0x7441dba6, 0xf8e95065, 0xffe3a221, 0xe27bf48b, 0x20efd0fb, - 0x14fe7479, 0xd347c3dd, 0x03bf4ab1, 0x9be6c874, 0x79e80692, 0x7ec1ba28, - 0xe806928b, 0xfb7ea87a, 0x931fbfce, 0xe9c607de, 0xabdd2cbd, 0xd059b7f4, - 0x540f7a91, 0xfd79ce29, 0xfeec8cd7, 0xf5463da3, 0x7e35c677, 0xca3fe811, - 0x72b0aea3, 0x37b47fb9, 0x3d19fb97, 0x9a9fba66, 0xbe295ee9, 0x235d0dbb, - 0xf211adc6, 0x75dba67e, 0xeaaf3959, 0xfddf550b, 0x43777c4f, 0x00800098, - 0x00000000, 0x00088b1f, 0x00000000, 0x7dedff00, 0xc754740b, 0xeebd6095, - 0x91a93fd7, 0x16883e9e, 0xc085a092, 0xeb404616, 0x7d3d05ff, 0xa71f3210, - 0x900b18c1, 0x04e08b4c, 0x60dd491b, 0x9e3d90e2, 0x123231a1, 0x1f62cd9f, - 0xbd6678cc, 0x8c030d39, 0xc077b19d, 0x0b611c56, 0x3837e2dc, 0x71c6ec4b, - 0x3c4c9c18, 0x6c0843c2, 0xc718d36c, 0xbc4ab243, 0x0f7adef7, 0x0b756bf5, - 0xcceb43db, 0x40e75764, 0xaabd5ea9, 0xfeeb75ba, 0x7ad3d56f, 0xcecc6333, - 0x53f817d8, 0x08acbc3d, 0x65cb191a, 0xfc05f3f4, 0xebf2e2db, 0xdf632b25, - 0xb4cbeeb9, 0x2c93f943, 0x1e670adf, 0x355faf63, 0xb188acca, 0xf6e3a9ae, - 0xfa87b3ea, 0x8c08758f, 0x127b4315, 0xef768674, 0x0077c154, 0x27d1311e, - 0x7d1e9d2e, 0xfd4c9fde, 0x8795cdae, 0x9d32fab3, 0xaf7a6863, 0x59b18d3e, - 0xca0e9bf8, 0x332d9320, 0x5aedcca0, 0xcca012c7, 0x9636f92c, 0xb12e624c, - 0xf2933184, 0x6bcae99e, 0x39f015df, 0xfe831993, 0x56f595eb, 0x0d5d7f30, - 0xcccf31c0, 0x3889f1bc, 0xc9c9d37a, 0x97cd5ed0, 0xd769e30a, 0xfe9fde1d, - 0xe4f329a5, 0x572e3630, 0xfbcdf5a0, 0xf04cf98c, 0xeb6e756b, 0xe7033602, - 0xd1cc7187, 0x1e60a9c7, 0x1d01e999, 0x2adb5ee5, 0xaa6b3fe8, 0xafe5e1c9, - 0x6cdef84b, 0x3e1bdfc6, 0x4ac67ace, 0xe2d9c686, 0x54fac809, 0x4c498ec6, - 0x6f5b2fe9, 0xf8e767c1, 0xb2857ac3, 0xcd6e533e, 0xebcbc455, 0x07e1c792, - 0x860f6778, 0xcb1d6f8d, 0x55633a58, 0x8b9f699f, 0x387d6d0e, 0x58fb305c, - 0x5f4fe5fa, 0x33467cc0, 0x5d398fc7, 0x5d79f847, 0x3e90fa32, 0xeed4ae2a, - 0x4b189362, 0xfc87ec96, 0x992adcf0, 0x36053e1d, 0x7e53f633, 0x0402b8af, - 0xc29fed04, 0x738014bf, 0x5aef6e9b, 0x16ddd027, 0xa21f4c6c, 0x4c0b2597, - 0x2e96381a, 0x9bd4d449, 0xea69c79a, 0xd44f57cb, 0xdb736fec, 0x43fa9add, - 0xea6a661b, 0x354a27ae, 0xd59d55f5, 0xef56f19a, 0xff69ab9c, 0x686feed6, - 0x7f9e6bea, 0x747f5350, 0xe911caff, 0x885f1a22, 0x89e991b6, 0xd23b0579, - 0x3a4d88bf, 0x9cc5cffc, 0xf7f7a3d3, 0x7ec27f21, 0xb7af6ebd, 0xd5fe82ad, - 0xe78d3f57, 0xc5f4b4fd, 0xf90072bc, 0x17d956a3, 0x402bc798, 0xad528d7b, - 0xf445be95, 0x4536635e, 0xee951be4, 0x11560ab6, 0xda66afc7, 0x6db0aafd, - 0x7e47aebd, 0xebd01a2e, 0x3759be61, 0x2157fcb5, 0xc706fc35, 0xc7afcc67, - 0xa5cb84f5, 0x9318eeff, 0x609e397a, 0xfc017fb5, 0x8cc9acc4, 0xa3c74795, - 0x5db7a74a, 0x6f5f6337, 0xeafccadd, 0xa0582b7a, 0xda3ee90e, 0xfc3b67ba, - 0x516b927a, 0x5ebe1dd6, 0x6feffe15, 0xef815f86, 0xf323ff5f, 0xdb1013ed, - 0xe6fc88b2, 0xcfeb5ddf, 0x02402bb5, 0x7a1527bc, 0x278291a8, 0x0e908b12, - 0x83650398, 0x51f99071, 0xc133d40e, 0x9652846f, 0x38af041c, 0x3034ef68, - 0x7e71eb2a, 0xa6861071, 0x35eb45d2, 0x288dca0e, 0xa92c456f, 0xebc79cee, - 0x875e068e, 0xd52ea8f7, 0x3ee7baf2, 0xea92875e, 0x43af275e, 0x5aefaa3f, - 0xb8cef58c, 0x014489c0, 0x5825beeb, 0x5a1e0e37, 0x05ff4bca, 0xe4994a81, - 0x5de83896, 0xec7ea7a7, 0x3707af22, 0xf2d0fa71, 0xf65e3183, 0x5f19b3f9, - 0x813f3c3d, 0xfdc24dbf, 0x006fd75c, 0x828ad43c, 0xd5ef0ec3, 0x3f87320c, - 0xe4d5f715, 0xe097d990, 0x3133a033, 0x8ccf886d, 0x4ab1982c, 0x0f793e20, - 0xedcaadf1, 0xe968e3e1, 0x5af51eab, 0xfc3bec01, 0xe51931be, 0xfaa7a730, - 0x2c12e0b2, 0xd013f9f1, 0xfc327b3e, 0x1f4e1e4b, 0x32a25c2a, 0x5fb5a55f, - 0x32b6aa8f, 0x59b72618, 0x8559d117, 0xd92c9d79, 0x716dcb87, 0x2e2fe550, - 0x56e1c22f, 0x1f39ade5, 0xfb1a6cf8, 0xb9967c3a, 0xaeb36a0a, 0xd9f0abbe, - 0x933e30ba, 0x8496f7ad, 0x321019f0, 0xb7d9f0d3, 0x276e9e89, 0x83094e5f, - 0x4f182675, 0x23e80cf6, 0xc05499ca, 0x3e244243, 0xb21bfb9b, 0x97c8a21f, - 0x5817f037, 0x987e6e67, 0x5cf4519c, 0xfee7aab5, 0xdda2b3a8, 0x117a67e2, - 0xc87c70cb, 0xd2313b2c, 0xbe3cb573, 0x6bba0609, 0x90f80ea8, 0x63be810f, - 0x06dc151f, 0xcec99bcf, 0x805ab862, 0x31e2aac7, 0x71ad6e8c, 0xec909d2f, - 0xecf505bc, 0x4e6e8518, 0xdf11a766, 0xc7bd76c3, 0xb59de442, 0x01f1cbe8, - 0xc70937cd, 0xbf226673, 0xc6db40d5, 0x33fde182, 0x99f00fb1, 0x3e7cc835, - 0x08eacf78, 0x46af5808, 0xf48d9efd, 0xfe51eacf, 0xe8095f57, 0xe5a5ea25, - 0x00745b97, 0xa4013fbf, 0x517c8b57, 0x642e9c30, 0x7ee3d3e6, 0xaffdd57c, - 0x90341fb6, 0xffdb0ebc, 0xcfb0419a, 0xd5394e00, 0x1afa20e4, 0xc8cf6464, - 0x48c7c14e, 0xbc21acbe, 0xade3f6a8, 0x176826f6, 0x622e91e8, 0xf640b37b, - 0xb36ca7d0, 0xf305f381, 0x867a55fa, 0x30afcbe7, 0x34ed1139, 0x7ed4f3cb, - 0xfa23136c, 0x3c97b6a8, 0xb8476755, 0x44cc7606, 0x0abd24b8, 0xc7153f97, - 0x70e260bd, 0x7f08daf9, 0xe4fe0ad5, 0x43331d41, 0x694fbfbb, 0xff5fa30f, - 0xfcd3b720, 0x702bc44f, 0x43f0c8dd, 0x4ed007bf, 0xe5689306, 0x43ff03dd, - 0x69dcf784, 0x01df3f77, 0xf028ae5d, 0x6e856ffc, 0x5124da3f, 0xf5cd3eb9, - 0xc7a07cfd, 0x7c6e917f, 0x0fc866e2, 0xd5f74439, 0x9027cff6, 0xd9f1521e, - 0x10f48637, 0xe8f84dc2, 0xdb8344b3, 0x387510aa, 0xe5bf0abc, 0x2a57c88c, - 0x577c2a9c, 0x0bab7a7c, 0xe7b37bc6, 0xf61c135f, 0x454bf821, 0xfb847ee7, - 0x674fc1cd, 0x92ef88b8, 0x34667635, 0xfc5266f9, 0x964ca488, 0x3ea2a62b, - 0x85cc7388, 0x74cb8c75, 0x364cbad1, 0x02fd1da3, 0xf393274b, 0x82734860, - 0xf7f08ccf, 0xd2ec37a7, 0xa9d6fb43, 0xfbc13322, 0x36bcb35b, 0x09fea75a, - 0x9399eb86, 0xd60361e9, 0x6577f3e8, 0x9c11293e, 0xbf475083, 0xa2f1c6c7, - 0xf8f4689f, 0xc75fb9e0, 0xc10a1cd6, 0xee02c1cb, 0xe7cd9d8f, 0x1e17dae5, - 0x842976d9, 0xad0fda3f, 0xbdddd4d3, 0x2976dbdf, 0x106ede54, 0x3697dc44, - 0xd9db8e85, 0x5ff404c0, 0xe13b455a, 0x903743a1, 0x2c6bf586, 0xae0a7e78, - 0x008fe70f, 0x5be73fff, 0xd2ff3d62, 0x8ff650a9, 0xff69fee1, 0x0df91f24, - 0x2b1ffcea, 0x5f38ffeb, 0xa6387317, 0xb3ba1e01, 0x9f70c5bf, 0x3f7c6c6a, - 0x7a72504d, 0xf54372e6, 0x739e8677, 0x3ea55179, 0x73de3a0f, 0x1ce91d12, - 0x994c76a8, 0x7de911f6, 0x71bbd227, 0x48b5bea8, 0xf08be8d7, 0x220573fe, - 0x16c07bc1, 0xa15b3db9, 0x5c139d97, 0xdfe8d9dd, 0x6c73ab3f, 0xcbce2586, - 0xe51e3adc, 0x7adb56fd, 0xe2e653a2, 0x38c058eb, 0xf4cbcebf, 0xd1e81978, - 0x82b7fe79, 0x8dd62a42, 0xf886c2cc, 0xe70bf557, 0x01d13e89, 0xd7f2bbfd, - 0x5ddd7199, 0x1c66f5b6, 0x82d684cf, 0xea3c386e, 0xe6ec0fba, 0xf4cbcef3, - 0xb2e9e089, 0xc57bb9b9, 0xa33fa801, 0xee5e7bac, 0x6aaf6a3a, 0x09149ff4, - 0x4367e07f, 0xf568e8dd, 0x87263ce2, 0x3ac246bd, 0xb2c66c73, 0xec89784f, - 0x0dbf5513, 0x9dad4fe9, 0x91bafa72, 0x15d763e4, 0xf244cf9d, 0x07305e53, - 0xbcaf9fde, 0x7b720d6d, 0xa3bf6bbe, 0x1cf7c45f, 0xf3e3f902, 0x764dbf73, - 0x2e77359d, 0x56b3e7b7, 0x98549179, 0x3fa1f04f, 0x5bc54f31, 0x195f569e, - 0xa0b7171d, 0xd4de30fa, 0x2c59d1ea, 0x2abe90c0, 0x70f3fcc2, 0x40bb3b7d, - 0x5972d7b1, 0x2d2bda31, 0xc863df26, 0x420d960f, 0xe2a1c23a, 0x8e814575, - 0x7c8620e8, 0x942667b0, 0xb465d95d, 0xd3ccfaaf, 0x5f980417, 0x4366df17, - 0x8cdbd0be, 0xb31bc47e, 0xa80d1f8a, 0xffc24df3, 0xb7b22533, 0x2f848eb0, - 0xfc79397d, 0x86c7966e, 0xb032eceb, 0xa7f248a6, 0xfdf380b6, 0x927e5907, - 0x8ddad10f, 0x7bd2041b, 0x66377caa, 0xc237d932, 0x5c8cdb78, 0xd25f80ce, - 0x3ebf402b, 0xffa017a4, 0xf7b35a17, 0x7ba205e9, 0xadf1e519, 0x12efb152, - 0xfe1fb90b, 0xca898166, 0x547eca93, 0xc336717f, 0xaffc8235, 0x8430f2aa, - 0xc7ca94df, 0xf1f26533, 0x732f224c, 0x2e3f7195, 0x5cdc7ce2, 0x5fb97b14, - 0xfb7a339a, 0x8d7a4b1c, 0x90285287, 0x98dd79e8, 0xc52e4987, 0xa3396f12, - 0x5da33788, 0xa7073fa1, 0x73fdb513, 0xaaffde45, 0xb274e620, 0xe51472b4, - 0xa4e92c41, 0xde83cfe2, 0x79ff97cf, 0x68da47ec, 0x99a3e3ae, 0xe042d4f2, - 0x2e9cbf93, 0x96e583df, 0xbbdb23d7, 0x772f63f3, 0x72801ed3, 0x37df04f1, - 0x79b3e923, 0xfb97b185, 0x48bed14b, 0xf845f6e1, 0x3d15cbfc, 0xd2794b14, - 0x11b36504, 0xff011fd6, 0xfcc28e8f, 0xef5073cb, 0xe5817b72, 0x0fa4b99e, - 0x67e1dfb1, 0x3ec42eb2, 0x1c147b06, 0x0543b441, 0xeddd9239, 0x2d7efd8d, - 0x643f487d, 0x5c61ccaf, 0x2ff3a81f, 0x7af8e12c, 0xb0e0147a, 0x25eade00, - 0xc29baf6e, 0xbfcb50e0, 0x7dbd8c2d, 0xe043e92a, 0x1fbb0548, 0x444205cb, - 0xd0a7af7b, 0x1a7e7318, 0xe2d9780b, 0xe4918d60, 0xefd8c9c9, 0xca0d9a4b, - 0xd3cee9aa, 0x4b96d728, 0x5c60e787, 0x1ff8fbf9, 0x79d21be6, 0xc1a561be, - 0xaeff45e5, 0xbc3bb24b, 0xac478c76, 0x7ccafaa2, 0x52af43bb, 0x94dfb63e, - 0x6c05db7c, 0xe57d51d7, 0xda1f24ef, 0xd617dfc3, 0xf1c6c99d, 0xfb1deb36, - 0x959dc618, 0xe78d837c, 0x9e36ac1b, 0x3c6d109f, 0x29b560ef, 0xcf1b0779, - 0x4a6d583b, 0xf3c6c1de, 0x929b560e, 0xbcf1b077, 0xe4a6d583, 0xef3c6c1d, - 0x7929b560, 0x3bcf1b07, 0xde6a6d58, 0x1538d3c1, 0x9e3691e3, 0x78dab077, - 0xe36ac1de, 0x97980779, 0x3c6c1de7, 0xf17000ef, 0x722d83bc, 0x943ac1de, - 0xf1ff2077, 0x67a49618, 0x547f5fb8, 0x7b06cfa9, 0x786334dd, 0xe76ab55e, - 0x17182dfe, 0xfc7209ab, 0x5e783955, 0x77b414d9, 0x457e300a, 0x04dfb066, - 0x114565fe, 0xb0d5f0c3, 0x13f3c3f9, 0xbde7d9dd, 0xb0a3fa02, 0x03bc2997, - 0x18ea29e5, 0xfe7c3f7f, 0x3b577161, 0x65d6e78f, 0x3bf08b7e, 0x78482cbb, - 0x8718e7c3, 0x13f253ad, 0xffad56b5, 0xb2e67f2a, 0x995f71f9, 0xf80899d4, - 0xbb6d4590, 0x8c2ff988, 0xd7f15ebb, 0x6ab7dc61, 0x15771b50, 0xb8d41b33, - 0x844bcf3c, 0xe1df39c1, 0x6b045f1c, 0x2a7f016a, 0xc1cfe601, 0x53ae15a4, - 0xa45e7c12, 0x881bddb7, 0x453bbcbe, 0xaa6814c7, 0x9e606404, 0x6a2012a5, - 0xc654d286, 0xf24cd2ac, 0xfe9d389b, 0xf1bdd4d7, 0x030f28d9, 0x6c04467a, - 0xf9a83c23, 0xbf580485, 0x2bfc8334, 0x332aeff2, 0x3a47bffd, 0xcc82eb50, - 0x5d8238f3, 0x2f80cd62, 0x5c266ef9, 0xceab9336, 0x45eb6f90, 0x73c335e6, - 0x9b37e941, 0x2d4e2905, 0x76f28933, 0x6541ccb5, 0x695774d1, 0xcea3f011, - 0x7ae175ec, 0x0966ecaa, 0xee3d85f9, 0xf148db3c, 0x32e97ae4, 0xf60049e0, - 0x48da62f8, 0x2ec88a76, 0x451cf8ab, 0x2f1f48bb, 0xadc92278, 0x61ebd88a, - 0x0a2a83b2, 0x2dc7c919, 0x7cfcb22c, 0xcfcb84ac, 0xdf5d4b37, 0xfbd73c44, - 0x878fd516, 0xd0be8f2e, 0x6d9b794a, 0x5bc2f161, 0x6f628afd, 0x90e72447, - 0xe901b93d, 0x8f04f17a, 0x1688e10d, 0xf62a78c7, 0x1b49ecf0, 0x767baec1, - 0xd45aec14, 0x2aecb743, 0xfa9399fb, 0xb1ca3b50, 0xd0ba4f0e, 0x9092baef, - 0xc3ddaa38, 0x8d67143c, 0x6979af1c, 0x9920e214, 0xfe13bfa8, 0xea639d0b, - 0x87fb023a, 0x54bcfbe5, 0x428ef8e1, 0x634be387, 0xa0d317cf, 0x613e27d4, - 0x771b8d0b, 0x970e0459, 0xf5c0d041, 0xfdff62b9, 0x78f624a0, 0x7d72812a, - 0xf22efca9, 0xf974d561, 0x7caa5867, 0xbae1df3b, 0x2d29fc40, 0xf9024faa, - 0x767f66bc, 0x0689ea01, 0x2ae35edb, 0x52d5f780, 0x3a22fdf9, 0x5b1ff46f, - 0x1eb16e1e, 0xf7bc478f, 0xa3cb22b9, 0xc50911bb, 0x28de4fe4, 0x67e4fee2, - 0xfe288784, 0x638bafe4, 0xea7b2fbe, 0xc9fc8673, 0x5b1ffe70, 0x639de3cc, - 0x068e0147, 0xf1465728, 0xc28ca6eb, 0xbf5a8dfc, 0x443ebf6e, 0x854110ce, - 0xdc6c69e6, 0xfc1163af, 0xba35973d, 0x147b37bf, 0xf310b1d6, 0xf591b571, - 0x31c57dda, 0x7e96aff7, 0x3307ca03, 0xd0a9fd5b, 0x6f30bcc4, 0xb2be50da, - 0x0fafd5c9, 0x383f738d, 0xe537e0e1, 0xb37e7008, 0xf272e638, 0xf91e9c7c, - 0xe119bd75, 0x7e066ae9, 0x255fb08d, 0x9bffdc25, 0x9611e13b, 0x3a637688, - 0xe411f743, 0x3637cf09, 0x83637e29, 0x2a767fa2, 0x2c53d472, 0xe52ce952, - 0xe851b9f5, 0xfbcad7fa, 0xb69c4a8d, 0x2bf26251, 0xec7ff491, 0x38fce6e9, - 0x71c6e728, 0xf30def38, 0xf453dfcf, 0xd3d89ec4, 0xa00c9ecf, 0x91b5b993, - 0xf63075f1, 0x0274b174, 0xf6d4bfcc, 0xf8901cf4, 0x0d9b2fb0, 0x2e9c5f94, - 0xef0c58bf, 0x57c28b6d, 0x69782b9f, 0xb03a3e86, 0x34a05bfb, 0x9010f942, - 0xfa405481, 0x6fec55ed, 0x14308e01, 0xf1de0420, 0x3af4e7e8, 0xce7c1ee4, - 0x7fe46d5c, 0xca1bc884, 0x3999569f, 0x83a774df, 0x0efe88ff, 0x9339d333, - 0x9fcf20ae, 0xfcf26576, 0x6a3c3868, 0x456ff4fe, 0x71cf198f, 0xc4166577, - 0xebddf285, 0x6f26989b, 0xe78575dc, 0x8a4fc185, 0xc949fad3, 0x8f8527e4, - 0x74b9909f, 0x247fa85e, 0x021fdcc8, 0x5c50267f, 0xa917e43c, 0x7c98cffe, - 0x7ff15cf9, 0xcd1dfd02, 0x4947119f, 0x07308b0f, 0x74ddff3e, 0x8f10dff9, - 0x1fd3d023, 0x9fd3d0a3, 0x347fdfb0, 0x11cc627a, 0xf0cc68b7, 0x1eb2bb71, - 0x708eb5b7, 0xd321203f, 0x54ce9119, 0x9b7a02fa, 0xe8763250, 0xb4f3217d, - 0x4b136f4a, 0xbd3ebf8a, 0xf0bec05d, 0xafe1acef, 0xd149d6ec, 0x7ab59dfb, - 0xfa0f28cc, 0xf19bd732, 0x99d4c49e, 0x6bce072e, 0x006c9911, 0x3e5cbb38, - 0x007b9e33, 0x64bf2f3b, 0xcdc1bc84, 0x7e3f2e22, 0xdcffecad, 0x2aff9c09, - 0x7dbe0b96, 0x6c4d7fc0, 0x4df70197, 0x4958ff7d, 0x7b88fdec, 0x35ee4872, - 0xf7208c96, 0xe2f8565e, 0x2b5f0573, 0xe729d6da, 0xfb445899, 0xfdec5567, - 0x942b348c, 0x45d75273, 0x745be3a4, 0x2285e787, 0xe21467ac, 0xe4c7e7e0, - 0xcd4c3ce0, 0xfc406d2b, 0xf1c4563e, 0x7dfecd17, 0xb3fc146a, 0x4ad70089, - 0xfd0199f6, 0xc7ff5969, 0x11e748ac, 0x39d9158e, 0x0390069c, 0x5995df80, - 0xfc31b7ba, 0xb5a495d9, 0x67f7d487, 0x67aefe2b, 0x5267e414, 0xf1c3ce0e, - 0x4c0e7e1a, 0x3ec5cf2d, 0x88b4b01e, 0x80ffb9fb, 0x73fc0efc, 0xe358a4a8, - 0x64a8fee7, 0xb5f73f64, 0x1adc8f7f, 0xcba8e850, 0x7d9ed911, 0x40fbf621, - 0xdd60e0e7, 0xb9157cef, 0xaa6f6e11, 0xdbd89ee5, 0x7a59697b, 0xd1c3879c, - 0x24e7b4c8, 0x28dff16e, 0x8f5d2de0, 0x77e968f3, 0x5ffae325, 0x1a58c385, - 0xe78c73f3, 0xff31e867, 0x7d79f9c3, 0x94be2ba9, 0x198f36ec, 0x07d837f5, - 0xb95f6714, 0xcd1f2539, 0x6b67d82a, 0x93be96a9, 0xefa6474a, 0x403bd2e4, - 0xfc9caadf, 0x534c6117, 0xa899bca8, 0xa5699bc8, 0x29afdfb1, 0x8e48af18, - 0x632baf2c, 0x73dbe71f, 0x79744e77, 0xfb379eac, 0x4f1b4147, 0x8f25bd6e, - 0x69474e63, 0x7921faa9, 0x7087eaac, 0x5e868d3c, 0x0bd10c48, 0xcce4510d, - 0x3631c068, 0x9db51f04, 0x98afe502, 0xc0a6f98d, 0x39d89daf, 0x96c7dee4, - 0x4f138851, 0xc87f8d0f, 0xa047af60, 0xb1a5dde3, 0xbca37fcf, 0xdb7c37e9, - 0x47f9d236, 0x28c5d5a3, 0x3173623f, 0xb19fec3b, 0xf6f295b3, 0x94ad05c6, - 0x029d6687, 0xf498fde5, 0xab79f92e, 0x30a7de6c, 0x9e5c367d, 0x5e398d6c, - 0x97d8728b, 0x28c537f6, 0xf8ebcd7e, 0x37f93a4a, 0x153ca3af, 0xb347ee24, - 0xf74ecc0d, 0xb97cafa4, 0x202f58fb, 0x9a2f3012, 0x763ee8c4, 0x7ac7e1a7, - 0x051b47cc, 0xe65cfe3e, 0x974ff9e7, 0xf0a3fc77, 0x31a0e59e, 0x7f543b7f, - 0xfb4d9a51, 0xcfe569de, 0xf39bf6bb, 0x9ea5849f, 0xc19e15b6, 0xa753e1f3, - 0xec1c5327, 0x6b8f03c5, 0xbc5aecec, 0xdf7e80c7, 0x7e861e0b, 0x35d329a2, - 0x9c3b2471, 0xae927f31, 0xa89a508c, 0xfa5e7a94, 0xf86d9d05, 0xf7f73bfb, - 0xbd67e848, 0x724cc078, 0x9e81ea7f, 0xe32155f8, 0x3e719627, 0xfe3d06b6, - 0x35af0019, 0x093273d3, 0xf92b1def, 0xce799173, 0x632bc2d4, 0x0f9d00a4, - 0x6b5791df, 0x2ebba50e, 0x794cd6a9, 0x639d5ce4, 0xfceb1d8a, 0xf4fc431c, - 0x4082fdda, 0x112edd7e, 0xe19aef50, 0xec7a86ba, 0xc3eb890d, 0x496b53a9, - 0xe72a75ab, 0x2de4761e, 0xc7ef8039, 0xf1a7af4f, 0x7b64593b, 0xe5c658cc, - 0x99068bf0, 0x80f17de6, 0x55c8e748, 0x7c69debc, 0x0f30cbd6, 0xa6dea3e0, - 0xa7d87ba7, 0xe5114e8d, 0x8134e9d0, 0xdf2d82ed, 0xee8578e9, 0x0288ec99, - 0xb94a2fef, 0xa96cca9f, 0xf7a77f44, 0x748f2e77, 0xbfa55f7e, 0xa96433c9, - 0x49c0ed0c, 0xff94269e, 0x36e4b6cc, 0xdf24f17c, 0xe68743bf, 0xcffc03cf, - 0x227fc17d, 0x6b21f70e, 0xf75c78cf, 0x6a76a507, 0x1f0f45bf, 0xb0f442bd, - 0xe3efc8c5, 0x8e717578, 0x858eb003, 0xcf1101d6, 0x8352184f, 0x2a6de794, - 0x8b74f2e3, 0x81630fca, 0x7d3de01f, 0xc507bf06, 0xcea9da26, 0x84270726, - 0x559ea3de, 0x0597aca6, 0xc2f9f132, 0xd83777f8, 0xf6158c1d, 0xb08b37a6, - 0xef8985fe, 0x7a86c86e, 0x5e78ef49, 0xb3f778cf, 0xb2b1896c, 0x9f5e0cde, - 0x9367eef6, 0x9bd15ea0, 0x3095ebc9, 0x9bb078d4, 0xbd9ab37a, 0xa4be3879, - 0x0f15bf19, 0xfd7f1472, 0x45d26f52, 0x28355f8c, 0x031f87eb, 0xfbece3ce, - 0xe2ef3a47, 0x78fd5b34, 0x86c9832e, 0x3419f8b0, 0x6077dc85, 0xff2409a9, - 0xf30bfbd4, 0xf63f7f45, 0x84fd99d7, 0x2759bbdf, 0xad8073d9, 0x7e145fdd, - 0x5c2e7b79, 0xc8d96dee, 0x8c4e785c, 0xef0966b1, 0xd64c0833, 0x78e3c17d, - 0x855f9c4e, 0x187f9d47, 0xc8b5b05c, 0x3d70439f, 0x70a8e34f, 0x7937cb5d, - 0x6b7ade51, 0x0427ae59, 0xe084d74f, 0x456c180f, 0x0f1dacda, 0x1b5d3ee1, - 0x40209c13, 0x1b7cb93d, 0xb1b5dbed, 0x8e081fc1, 0xef81ba90, 0x096f5b63, - 0x289763ed, 0x9b9d21b7, 0x216ed68c, 0xb8eeb191, 0xe60c1984, 0xe5d631d9, - 0x406e7bc5, 0xd8ef7477, 0x1c74659b, 0x8beb3800, 0xc7a1f9b4, 0x83fb3a15, - 0x98e60f22, 0x01ce7976, 0x047bba5d, 0xdc70f786, 0xa88c3783, 0x5df616ff, - 0xa4be6234, 0x11a2e7a3, 0xeb03bee9, 0xf3c74e30, 0x6ff988c6, 0xbd5eb963, - 0x91e74a2f, 0x4f1c4bd6, 0x7aeeb2a7, 0xe9e0152a, 0xbdd02d58, 0x9247f5bc, - 0x7d7d60e6, 0xb192ae2b, 0xe78755e5, 0x38b4b920, 0x72c29ffb, 0x95381b25, - 0xccb4240a, 0x10f667a5, 0x4d62b93d, 0xe887b33c, 0x8a4f16c9, 0x1772bea6, - 0x280cceec, 0xfa686637, 0xeafee531, 0x83f43632, 0x949a98e7, 0xdb665c7d, - 0xeeb8c019, 0x3bc19732, 0xc2de3210, 0x3262cdbe, 0x1c11edc2, 0xcbd28d74, - 0xe0ad3fcf, 0x1c52842b, 0xf7cf1f7a, 0xefc40af4, 0xba7a6d1d, 0xcbdcd3c7, - 0x35e6aeed, 0x202ecf82, 0x0dbdf81e, 0xed40af77, 0xeba7deee, 0x1bef1193, - 0x47000f00, 0x7d84f8da, 0x9347112c, 0x4ad5dce9, 0xdf775605, 0xb38e0339, - 0xdd023be2, 0x9bbf5567, 0xb2bfc2a0, 0x91ce91a9, 0xa45e7c01, 0x4d9d754f, - 0x5ce947f6, 0x9789cad5, 0x6187a80d, 0x3406977d, 0x5bd6d4f8, 0xcafada3c, - 0xd1fada8d, 0xf29ee532, 0xf90d3634, 0x209978e9, 0xb52439e2, 0xf9d651fe, - 0xe75ef1b7, 0x0a79d16e, 0xe8cdb3e9, 0x7efa819f, 0xbaa2e8b7, 0x3bcf0eda, - 0xf89df118, 0xb1f100e1, 0xc5b9fc40, 0xf8354b20, 0x8176973d, 0xb60576e8, - 0x0f67f3ab, 0xfd754fbd, 0x554dfaf0, 0x1b9c5aee, 0x4730bbe8, 0x90ed0905, - 0x9316517a, 0x222f88f3, 0xbdf9779e, 0xa36f07c2, 0xeeb803f6, 0x7d852242, - 0x44feebba, 0xbde6179f, 0x3a56cdeb, 0x215776e7, 0xf91d81d0, 0xd6e7475e, - 0x2f79e3e6, 0x7903ef28, 0x2ef28168, 0x9226a1fd, 0x128d33ef, 0x9ce577c9, - 0xe42f2a97, 0xb6e7b517, 0x219e67e6, 0xe7beeb3b, 0xb579d276, 0xc17239c9, - 0x2d0fa8d3, 0x471dfe7c, 0x1866df04, 0x34ef23a7, 0x3271cfc9, 0x61d72f3f, - 0x2f68e453, 0xfd7551c8, 0x50e3bfb0, 0x692261ae, 0x9bcd1e41, 0x5da9566e, - 0xf8283926, 0xffe8756b, 0xdde6538e, 0x75a76d5f, 0x487a3da7, 0x316775c0, - 0xe60166ef, 0x7c3a82bb, 0x55f950ec, 0xf8b5d7ed, 0x565de80b, 0x5b63b5af, - 0x65e3d745, 0x6dbb5f30, 0x2dcfc8c0, 0x1fa88d06, 0xdef8e0ee, 0xf2c3e348, - 0x50ee7475, 0x4730fbe2, 0x7680983f, 0x39a3face, 0xf608d8e3, 0xd3acde8d, - 0x148311c8, 0xf33791a7, 0x67f2b573, 0x772b43a1, 0xa39651be, 0x4f245f69, - 0xdfdfb4d3, 0x3fa9a858, 0xbcd4ace0, 0x9d5360ff, 0xcdb26ea6, 0xb16fbcd3, - 0xe3d4d62f, 0xde6b9773, 0xa558e31f, 0xf5bd3769, 0xed0126a3, 0xc077b371, - 0x06e87805, 0x1e4b28de, 0x12d323d2, 0xe32865e0, 0x2c562d0a, 0x744df3bb, - 0x3c7bb64e, 0xec4497e8, 0x773a1dff, 0xc97c4e69, 0xdfe5035c, 0xfc5abe0b, - 0xc9a00e7e, 0x3ddbf685, 0xf0e3684f, 0x5f38abc7, 0xb94365a9, 0x280ac1eb, - 0x67b05ef3, 0x81e97bf0, 0xcc7f707b, 0x45db8c71, 0x2ec999af, 0x5376899a, - 0xb071bf88, 0x397e66ba, 0xbe427bf6, 0xf582f917, 0xbc0a6932, 0x3b08cfb7, - 0x35ee7a8b, 0xebcbf523, 0xe685d01d, 0xce597ff7, 0xceb3c1e5, 0xfc717bda, - 0xb2d03e8e, 0x7dcf4fc8, 0xaebf4468, 0x013fafa3, 0xe70cd9f5, 0xcfb44687, - 0x7a2b9e87, 0x61c60c4e, 0x0e1fe39c, 0x63de23e9, 0xa46e5edd, 0x722b4ff1, - 0x7a3be5bd, 0xf78b4f3a, 0x864a6b37, 0xe1cb73e4, 0x63ef1fa0, 0x7bf3b4b7, - 0x368e789b, 0xf9069c92, 0xbca861fc, 0xf41d367d, 0x4f1a4cc1, 0x97960fa3, - 0x3edee9f9, 0xfbcd6fc8, 0x5c34972b, 0xc8257cc5, 0x4cf3ed71, 0xb1961e7e, - 0x73fa0301, 0xed35d720, 0xfb95cb1b, 0xde58d39c, 0x2e072017, 0xdbdf2338, - 0x9f8abb7d, 0xaae0b833, 0x16787da3, 0x47e789f0, 0x3f861d9f, 0xe1dbd78e, - 0x81a465ed, 0x661bfd90, 0xff7157ff, 0x7228e5ea, 0xbfb2a2fb, 0x014084fb, - 0x33b7550a, 0x8577e88e, 0xa5ed75b9, 0xcf97dc42, 0xdebfa2b7, 0xee8123f2, - 0xffb2ffc1, 0xac3b34ad, 0x54f878df, 0x7697de1a, 0x86953a1f, 0x0cdb89f7, - 0xcf68cdf6, 0x3dd07d03, 0x3f5e8ee4, 0xa87edfc1, 0xb79f1fb0, 0x140e0af7, - 0xeb9eeec9, 0x364eb40d, 0xa3fd15b0, 0x3ae0517d, 0xabedce58, 0x2a76e5c3, - 0x13982edd, 0xc98f7ef5, 0x1e9013e7, 0x5c213e40, 0x820fc047, 0xe66dbefa, - 0xd4f648a6, 0x27df0565, 0xde1919b7, 0xfe836dfb, 0x59d38eb8, 0xbdf88da7, - 0xb0c39685, 0x71d7012e, 0x1c7881ee, 0xa181837f, 0xf7c2a19d, 0x03e05671, - 0xabfbff5c, 0x2dcf0c0d, 0x27ad596f, 0x81bfbf7c, 0x87fa27db, 0x0335bd7f, - 0x2e80cbea, 0x270f3bf1, 0x9d38df56, 0xbfbee301, 0x7569db86, 0x2f881b0f, - 0x6e13ad97, 0xa50e4bdd, 0xff6e956b, 0x70d3a146, 0xdba70dfa, 0xe6baf461, - 0xdbebd1eb, 0x90ecb7e5, 0x61f7a819, 0x438ce7ff, 0x731efa3a, 0x1a7e401c, - 0x0718613c, 0x2ada4f70, 0x63c3c039, 0xa7bef5d3, 0x9c6e50d2, 0x6df9ede0, - 0x7f2e057b, 0x7d71cbec, 0x8646dd19, 0x2a2e08f7, 0xd95176fb, 0x0a0b3b37, - 0x62cfc8f1, 0xa9ca1260, 0xf9ce256c, 0x1d35818a, 0xe452ff46, 0x8ffa67f2, - 0x87b77b6d, 0x2b7fefd0, 0xcaab74e7, 0xe64669c5, 0xf7c56c3a, 0x045f8d0f, - 0xe06cbce3, 0x282735e7, 0x09c94de3, 0x52822c36, 0xe4e5c157, 0xd438156f, - 0x3e149ffa, 0x437f2760, 0xe6685cf8, 0xd1b79ff8, 0xf8eb8cdf, 0xbd75c999, - 0x305fde1c, 0xea1b7ce1, 0x3f49eebd, 0xb9dfe3c9, 0xee1d9073, 0xa27ff056, - 0x63cf37fc, 0x3532cfee, 0x72d7f68e, 0xe90969f4, 0x68a532d9, 0x30f148dc, - 0xe66ccdf7, 0xbaba014a, 0x5aa54399, 0xaafc745f, 0x82fc8071, 0x2fc40deb, - 0xb9e9d337, 0x0553efda, 0x8e46e9ee, 0x4a97d607, 0xb6e41b7a, 0x67921658, - 0xfaa0f150, 0xfb2996e3, 0x5b1ebf69, 0xcfee28c7, 0x8f84d3d8, 0x84e76d15, - 0x41e71856, 0x02b06c83, 0x3627cfbe, 0x8534bdad, 0x626c9fb1, 0x3a0b05cc, - 0x5cccc9bb, 0x6c7d0377, 0xd81ea892, 0xbbfaa364, 0x5e54ec9b, 0xa2c738b6, - 0xa4e079fe, 0xede20a67, 0x671ed644, 0xed73cc2d, 0x41f081ac, 0xfdf4063b, - 0x376b4298, 0x0cccf4fa, 0x947a37ed, 0xf028adef, 0x8333743f, 0xfcbe40b9, - 0x8e83e702, 0x467f1bed, 0xe6b1cf72, 0x49fa037a, 0xb7176df9, 0xf1bddd62, - 0x5f680d77, 0x04fa007c, 0x7eec0ce9, 0x9e501366, 0x81da339c, 0xa66f9a0e, - 0xeb2f38d0, 0x77c80d82, 0x430263de, 0xf7a0fcfa, 0xd71c71ba, 0xe12d7457, - 0xe6744df9, 0x48ad2d9f, 0xfbb8fc22, 0x7f7c75f2, 0xf7a1748b, 0xf9effa29, - 0x87ee0243, 0x9dfda379, 0x467fec4a, 0xb7af90cf, 0xa41306d7, 0x02f87208, - 0xa3978b8c, 0x86581d70, 0xbd1937b7, 0x413cf053, 0xe1c74293, 0xfa158bed, - 0x941b4c04, 0x213229ef, 0xc1239f8d, 0x5258169f, 0x41f93262, 0xe7e038fe, - 0xabbabe96, 0x811e9622, 0xcff5a87d, 0x762187d8, 0xfc3a347c, 0x437e25b2, - 0x4329c3e6, 0x4323f475, 0x1fa07fef, 0x82fbe919, 0xe3c9aca6, 0xb9778a46, - 0x83bec007, 0xc300eafd, 0xf4829ec9, 0x4fca8d3e, 0x91d9748e, 0xc171cc7f, - 0xd82fa83d, 0x3bf23a5d, 0x7b5abdda, 0x87e141a8, 0x7a1ec506, 0x3feb42b4, - 0x5ed49f81, 0x84a4fdc1, 0x3fe34ce3, 0xff273f85, 0x057c8cc9, 0xfd834ef3, - 0xfed22579, 0xc7aed554, 0x2ed8137e, 0x740673a2, 0xbe15f48e, 0xe0a8bfce, - 0xebe5547a, 0x48d7c865, 0xaf9cbdbf, 0xa96dc7c3, 0x1c0bf9aa, 0x7b945b77, - 0xf157f710, 0x139fdaf1, 0xe7ee5f08, 0x1f4f0852, 0xb59ce7b3, 0x031f9740, - 0x2e80fb1c, 0xf19d39af, 0x9affd049, 0x6c9f19cb, 0x1d03921d, 0xbf53c5cf, - 0xa717936d, 0x19fd42b4, 0xef187ba4, 0x8a3ade93, 0x1cf43e6f, 0xbe753fe7, - 0x52cbfc0f, 0x0d8a9f90, 0xda03a341, 0x262efb33, 0x7c581da0, 0xe414fee4, - 0x6e7068c3, 0xdce054ad, 0x4bdad8f8, 0xf01e9c29, 0x455aee1c, 0xf49fb9bf, - 0x6bff111b, 0xdfa23237, 0xd97ed7fe, 0x49fc7c81, 0xfa84bc5f, 0xf1a3e3f0, - 0xd7ff945e, 0x3a7c998e, 0x6f10fc81, 0x8fb5c822, 0x91f7030d, 0x2f4479bd, - 0x3ee8ffa1, 0xc83ddbf6, 0x4cd7ee8f, 0xb5b1f968, 0x51d75d7d, 0xddf5b5ef, - 0xf2c4557b, 0x87e5d1a5, 0xd38f8df6, 0x6ffad57a, 0x28ed9937, 0xb9113f47, - 0xfbdb589c, 0x6bbfd92a, 0xc0cc6f07, 0x47c7ea38, 0xca094fff, 0x379bf735, - 0xb99e504a, 0x8251b8df, 0xc71feeed, 0x2dd9227b, 0x84f4b371, 0x665f5557, - 0xe26a27bf, 0xfa141b45, 0xd5dceec8, 0x57f00938, 0x03896e7c, 0x7b6ab6f3, - 0x139d14f1, 0x79fe2fdf, 0x21c3ca7d, 0x22033afd, 0xce8a8de5, 0x0eafc7d5, - 0xaa47cba1, 0x94ef9a0c, 0x0f38d57d, 0x2df7e2b6, 0x0275c56f, 0xec0efa3a, - 0xbfc880b6, 0xf046bb2f, 0xf601bfa1, 0xb23f784b, 0x923daea7, 0x9910f742, - 0xbd3f9ce8, 0x1c53eb08, 0x5628eddb, 0x8726a7cc, 0x02cb4bd8, 0xe809bf3a, - 0xe4cfa9a8, 0x203f7b27, 0x62baa45e, 0xfd743d47, 0x85b26337, 0xdc9a7108, - 0x1ca0e777, 0xc0d78f0f, 0x5b8418cf, 0xa7ceafb5, 0xa651f8f3, 0x042dd247, - 0x993b9ab8, 0x161d7884, 0x4b9a69d7, 0xf8f0a2f1, 0xdbb03d8e, 0x93ecfd8c, - 0xabc21275, 0x8fb8a5da, 0xc0e4113d, 0x7972565f, 0x6757f2a6, 0x3af5e780, - 0xc9e6b503, 0x69577e50, 0xcc7491ef, 0xece9780b, 0xc600ffbb, 0x1f073a17, - 0xf30e9f8c, 0x98b7be74, 0x9ae79e61, 0x829e6b54, 0x9ae706fd, 0xa21bc81f, - 0x1af9f09b, 0x345db92a, 0xd6442f64, 0x5f0aa57f, 0x2c1e968f, 0xd0f3fcac, - 0x579fe083, 0x7cff7254, 0x709f8f05, 0x7f5c3cff, 0x1d5972a8, 0xef82ad77, - 0x2af972e1, 0x47e039d9, 0x5b5e5c93, 0x32f7a769, 0x90a516fb, 0x92defd7f, - 0xf875bb14, 0x43a239f8, 0x7c379c97, 0x739ed57c, 0x6653e57b, 0x3d647bf4, - 0x897ba7f1, 0x97fcc3e0, 0x9db9ff6a, 0xeee5d902, 0xdf0f8366, 0x2c0ae153, - 0x07d8f1e1, 0x22cf8364, 0xaa89d90c, 0xddab791d, 0x6abb5021, 0x63f6aa57, - 0xbbe3c9c0, 0xfb788a4b, 0x556b8b65, 0xa75c58e5, 0x97179e85, 0x398ce7f3, - 0xf55fa14f, 0x918152e0, 0x4aec501c, 0xedc34e95, 0x72fb4fce, 0x438a4712, - 0xa7d0af3d, 0xc21367ca, 0x63d543f8, 0x7e7054cf, 0x5e3d40eb, 0xf7fc7a88, - 0x7c3cfb1a, 0x8fe3d05c, 0x463f5257, 0x2e7e8bfd, 0xebf9233a, 0xadfc6566, - 0x4e05feea, 0x59bc20d6, 0xfd19b02c, 0xf5fa68cc, 0x139d8a7b, 0xc519fdad, - 0x3f1dbc7e, 0xc8e4561f, 0xcbf3f168, 0x70f2b795, 0xf9f9a9ff, 0x8c687d96, - 0xd557bf62, 0x1ffb86bc, 0x6a04f7a7, 0x97feff90, 0xe1eee281, 0xfaa53def, - 0xecd3229f, 0xa32ca9cf, 0xf723fd0e, 0xe83f1e1a, 0x43bfb24e, 0x7a5bcc7e, - 0x05ace386, 0xb8ed107f, 0x51266f47, 0x32f686d9, 0x385e2b94, 0x1588f947, - 0x77f0b46b, 0xfb174c63, 0xf3a6cbaf, 0x9eac2d03, 0x7d2d4ce2, 0x5016d249, - 0x0f63dd0a, 0xf2be469d, 0x0fdbd01e, 0x88ffbe84, 0xc799befa, 0xfba636e1, - 0x661af728, 0xc278b40f, 0x7dad7eed, 0x8dc4a950, 0x6f09d9a2, 0x5cb85bf4, - 0x3e27a339, 0xd378c0ef, 0x7d8cc64c, 0x37b82e5c, 0x474938f2, 0xfc04e6df, - 0xd2bb6a08, 0x500c457e, 0x6bf28a1c, 0xbed5eaf0, 0x3ee8d3a7, 0x27cdac97, - 0x39ffefb5, 0xbcf0cbc9, 0x970f7252, 0xbd36ee4b, 0xa12a4792, 0x83b797ef, - 0xed0e393f, 0x1bfdbb4b, 0x8b807788, 0xc8de48f9, 0x3ecbb89a, 0xe9f4af25, - 0x3f257f99, 0x2891c574, 0x79eea479, 0x7ca48f3c, 0x1e787727, 0x0ca9f4e9, - 0x48f3edfb, 0xe8e7bd1d, 0xf2edcb1e, 0x5baaa649, 0x3b8a1c71, 0x7c79144e, - 0x209f6277, 0x626abc61, 0xe9775f1f, 0xafb238b6, 0x3ab57e1b, 0xba81e505, - 0xe22c9f4f, 0xfde4fdf8, 0x5fb06acf, 0xc944afc9, 0xe37aeb02, 0xcb3f0dfd, - 0xd9bb75e0, 0xc436fd8e, 0xc9f33fa3, 0x23c7d6af, 0x1280df7e, 0x17c7e7f7, - 0xc9f1c8c4, 0x667578a1, 0x959dc515, 0xfa08b578, 0x5c50cc70, 0x8bdfbc27, - 0x746e5c55, 0x7142bb83, 0xef3c23cd, 0x9aee9ddf, 0x9ebff547, 0x29dff8c4, - 0xfd1e2990, 0xc635d02a, 0x62c1a68d, 0x3ffd2f31, 0xe62758e3, 0xbac7ba91, - 0xf47c427e, 0xf23b3ad7, 0xfca7f411, 0x9db0f793, 0x6a8623f4, 0x0333cf31, - 0xf7405b3f, 0xdf295231, 0x8fb28f73, 0xa2cfe0e9, 0x2cd0095f, 0x34f43cc1, - 0x2333df25, 0xfe38898e, 0xfb6b830e, 0xf52fcc54, 0xc4cd8e8b, 0x3c148e04, - 0x779e196f, 0x2f9e6412, 0x6a4ff357, 0xfe5a3cde, 0x9479c049, 0xf3f056ef, - 0xf980b296, 0xc4cf3574, 0xf9293a96, 0x43cca5b5, 0x807c42f7, 0xde73afb3, - 0xcffc846b, 0xf21115c3, 0x982beb3f, 0xf3699f62, 0x5f73db8d, 0xaafd3a21, - 0x78c3c679, 0xe68ee2ae, 0x0fdcecc5, 0x28bb830d, 0xf234d3e9, 0x6ff8febb, - 0xfb67a409, 0xbc3e906e, 0x00b13416, 0x78071fc5, 0x40cfbddc, 0xe06b8671, - 0xd10d8dbf, 0xf054efb3, 0xd5f78f71, 0x04f7fd11, 0xfdf1e3ea, 0xb7cf2bdf, - 0x7ee4b7bd, 0x01bdf7b4, 0xc60b1dfe, 0x13d63fb8, 0x6ed18b10, 0xf2fb83b9, - 0xf5846564, 0x7eb8e399, 0x52a3e70a, 0xab4aff85, 0xdeeb9e38, 0x7b987ee7, - 0x48afcf03, 0x7b705c8a, 0x74fd5e78, 0xc6a09a56, 0xca45c7d3, 0x92091cbf, - 0x447968de, 0x7cc9efa0, 0x33cbfcd9, 0xf1f391e9, 0x462f7a2b, 0x3634bfce, - 0x168cfc90, 0x638f0ecf, 0xff2a9dff, 0x7638f3a6, 0xeb44957a, 0xd7e4f64e, - 0xeb43638c, 0xb0fb83bf, 0x7d845674, 0x6fe383b8, 0xf1db1d9c, 0x3b63caeb, - 0x1e3113fe, 0xc78c7b7f, 0x6c7961ff, 0x8abaebf3, 0xdbffc2d8, 0x1fdfc318, - 0x57fffe09, 0xe78407cf, 0x0bcfc3ff, 0x30039f84, 0x17b0f5bd, 0x9d84badb, - 0xefc33f41, 0x24d6bf8d, 0x93141c80, 0xce7dd3f6, 0x1f3ce505, 0xecdeadb6, - 0x9d0c2bdb, 0xf5f1501b, 0x23f73568, 0x5eebbca5, 0x04d45efc, 0x829f5039, - 0xfe72b2f1, 0x59ae4377, 0x898c5e78, 0xc9e63a52, 0xc5f4cde0, 0x5b749760, - 0x5359e722, 0xe9a2f195, 0x35d58391, 0xe315678b, 0x7c8a3d1f, 0x4a87ff0e, - 0xe5ea521c, 0x6899e9f7, 0xf34c5f4f, 0x1ed1d3da, 0x9fc93c4a, 0xbc99f827, - 0x67b2e097, 0xdc7fe62f, 0x7be11b20, 0x26ffc946, 0x1b2bbbcf, 0x60c9d2e3, - 0xf05e6217, 0x920fcc69, 0x7bd12b3f, 0x66977cea, 0x19ea3f71, 0x9f301303, - 0xcfca9deb, 0xdf9eb139, 0xe6a6fd91, 0xfc1acef5, 0xca055a97, 0xfc23b5eb, - 0xf3f9d53f, 0x442b65f6, 0xebcdf80c, 0xf8df2891, 0xe5dff976, 0x9e1e68ba, - 0xe24c7be7, 0xbf409caf, 0xec78e019, 0xefd12168, 0xffe5e38a, 0xc7fe8cd4, - 0x3cf09164, 0xe254afcc, 0x78941705, 0x502f1a87, 0xacff5bf3, 0xc03e49c4, - 0x03940bf8, 0x72810f18, 0x9ddd2cfb, 0x67db4fd6, 0x67ffe045, 0xf21f1e04, - 0x87c794fe, 0x9c8e8d0a, 0x7f94f3d0, 0x63ef8b35, 0x2fe79fab, 0x0fcf78d4, - 0x7e14f595, 0xefc7ef4f, 0x9d6e15a1, 0x5f3d446e, 0x0e2b35b8, 0x4fb219cb, - 0x5ef80697, 0x4eb0fab6, 0x7448bfdd, 0xe75957b4, 0xca4133b6, 0x961abdef, - 0x8b34bff7, 0xa968679f, 0x097bfbe6, 0xd418a0ff, 0x6e229b1f, 0xb131f341, - 0xca47d24a, 0x5f80b52b, 0x76b6708c, 0x7c55b873, 0x75edf8b7, 0x53c5cf38, - 0x1658adc1, 0xa3aec9ac, 0xf5db7bb8, 0xb9bf68ad, 0xae9c6f07, 0xd19978a6, - 0x43c4fe8e, 0xdbb8da03, 0xfe3cd513, 0xe01a2afe, 0x457bb788, 0xef0b8ff2, - 0x927e8915, 0xbfe42c5b, 0xde981b26, 0xdc45f58a, 0x4c682a2e, 0x5b3ac3ad, - 0x60f64492, 0xd27b19c1, 0x714379c3, 0x377be4b0, 0xdd3c458c, 0xc6aacf2e, - 0xe45b2ed3, 0x5f9fb8e3, 0x7edacf35, 0x6f3a3df6, 0xc54baeaa, 0x8d2f9a8b, - 0xcf556796, 0x3f1bb83d, 0x70d39cd3, 0x8c06c18b, 0xbd1e163f, 0x5fce5468, - 0xa1ecb64a, 0x91e16c3c, 0x557f94eb, 0xcf6eadf3, 0xa1abb275, 0xf7fb119f, - 0xd7f9e26c, 0x2c0e00d7, 0xb2dd617b, 0xdba1ef09, 0x7583eca8, 0x9b63f3e3, - 0x6ff4a972, 0x7c795072, 0xf8951953, 0x64f4c999, 0xa75edbcc, 0x59d5edbc, - 0x524dcec3, 0xe8b76f5e, 0x15f108fc, 0x7aa3f792, 0x1f4fde78, 0xee35e3c7, - 0xbefa0633, 0x99acfba1, 0x5f4d77e4, 0x0ff444eb, 0x9ae73f3e, 0x60777088, - 0x2e842dde, 0x961d913e, 0x9d83f424, 0xdbe60b0e, 0x1aaffb0a, 0x874c3cf1, - 0x3c623018, 0xc0cf200c, 0x9eee8b23, 0x6fdcfceb, 0xf1058d5f, 0x58fcdb7b, - 0x8fcfffef, 0x58fc957d, 0x273f3577, 0x0291caad, 0x8bde4ea7, 0xf2d919e5, - 0xd89c8870, 0x94f9e4e6, 0x1127936d, 0x4e76ee1f, 0x321d5a4a, 0x8f23675e, - 0x3bdf245f, 0xfcfa12d9, 0x1f3cd597, 0x67302c96, 0x33567924, 0xc7ddebfb, - 0xd76e411b, 0x3ffbb244, 0xe5d029f9, 0x238ba04c, 0x90389edf, 0x343f19c7, - 0x71adb71e, 0x2831c4f5, 0xd8982e9f, 0xd3af1e14, 0x5858e3c4, 0x5c5a2e5e, - 0x4ea3456e, 0xa179d0b6, 0xdbd404e0, 0x2633f1e1, 0xbd702706, 0xbde0672e, - 0x83319814, 0xf961b195, 0xdf305fb9, 0xfbc327cf, 0xa4751acb, 0x5d3cd42f, - 0x36c8a341, 0x6c167d01, 0x3f28f834, 0xa45e28d7, 0xec6fc576, 0x90320a94, - 0x6b383fce, 0x16ae3094, 0x34731f1e, 0x049eefee, 0x026d1dfd, 0x5dba0bdd, - 0x073d4f1e, 0x3fdbd2de, 0xf96de307, 0x3d77576c, 0xac9fcff4, 0xf4fcf093, - 0x3f1e7cf0, 0xd8a05dff, 0x3671e139, 0x4bb433a4, 0x1bf0e3c2, 0x38d83a15, - 0xd7adeb9b, 0x1d537f14, 0x4e17ed47, 0xcd9d3f3f, 0xb8b46df5, 0xbc6551fe, - 0x6d82c6ce, 0x177f7193, 0x93ea18e8, 0xf35ac6ce, 0x76f190e4, 0xdbe7e6cc, - 0x60fcc19e, 0x907e686a, 0xf3c301e7, 0x2b9caa82, 0x037dffec, 0xc8377be2, - 0x6e63d46b, 0x141fcf1b, 0x8339ab1e, 0x4e086372, 0xc377b7ae, 0xbec8079e, - 0xbe312473, 0x457bfa2e, 0xc502a3de, 0x7c160ae7, 0xea1e3c76, 0xf74499cc, - 0x2767dcb0, 0x3ca2b16f, 0xe316205a, 0x53b71ebd, 0xc26795b8, 0xeffdd27c, - 0xbcefa1ac, 0x7f903e16, 0x81e5f70e, 0x0f9d0366, 0xfddef554, 0xf03534ef, - 0xc64fbdf6, 0xe0ae7b61, 0x79f1d8b0, 0x763f7d23, 0xfa7e4bfe, 0x110b58bb, - 0x81e7903a, 0xe44497b3, 0xd716cb9b, 0x151f23df, 0x4cf2522e, 0x3f4f5ccd, - 0xc0c8b7d0, 0xead3cec8, 0x9f5913cd, 0x46e83c53, 0x8fe5215f, 0x43fcf052, - 0x29be90de, 0x6c7a0a3c, 0x63d39dcc, 0x112d9d3f, 0x1e82673e, 0x17927843, - 0xf87d3cf1, 0xf650effe, 0x8a5e9a3f, 0xff518726, 0xde63fbf0, 0x5c36c10c, - 0xee31db8f, 0x3af68a53, 0xd3a2e394, 0x71661fdf, 0x628a4eba, 0xa149fdcf, - 0xa7e7a8df, 0xcf27477a, 0x7fd987f4, 0xd563791e, 0x4df352ff, 0xa0f6bfaa, - 0x65ab0f62, 0xbbfe5293, 0x72a037ef, 0x21bf788d, 0x86fdf239, 0x68090e87, - 0x1bf7a8a7, 0xcd59194e, 0x4f3c54e1, 0xf277dcab, 0xe93b222d, 0x62fcdfd4, - 0x78a98beb, 0x509049df, 0x3a1fb51d, 0x1dbe7a47, 0xa7b223ec, 0xe3cb7efa, - 0xf9f887ad, 0xc8def6f0, 0xaddbdddf, 0x32f5dfd8, 0xaed1b923, 0xe86db79c, - 0xb744f251, 0x8b8f96e2, 0xb74b71a1, 0x3d56303d, 0x7f23ebc7, 0x8cc71b4f, - 0x60ecb716, 0xdbb73a41, 0xa07046b1, 0x39ddb87e, 0x79ca5ddc, 0x4c71a8dd, - 0xb973e479, 0xb94c71e1, 0xb9c79b5a, 0xf7c4966f, 0x680825db, 0xce759aef, - 0x7fb73a36, 0x9d22904c, 0xcd5a5ef3, 0x257cf4e5, 0xc8d0720f, 0x8560e3e9, - 0xf06ff740, 0xfbee1e1e, 0x1efc63c1, 0x7e02c1ce, 0x7bcd470f, 0xa66bf7a8, - 0xe83de50e, 0x2f7a9dfe, 0xc367bd47, 0x5ae08f98, 0x7d1c5cf4, 0xe1876bc7, - 0xbddb8d90, 0x1a3f7e5e, 0x43e61065, 0x8913cc4d, 0x6bab6b5f, 0xef7a6ac4, - 0x8f4fdb8e, 0x7bf04754, 0xe91f8a7d, 0x2fea8eae, 0xfad6afac, 0xf70f540b, - 0xde54ee17, 0xecd98be3, 0x87fbfb4e, 0x9e8f1c63, 0xf1b63b32, 0xfb48ecc4, - 0xfda2c5b6, 0x5e5aaf1e, 0xb0dfe456, 0xbb0dc5ef, 0x7af5c92f, 0xa7ff60b7, - 0x1ba7ca4a, 0xcaae9f28, 0x7c31eed5, 0xe3291ffc, 0x294065a9, 0xd77ca3bb, - 0xbc4a97f9, 0x7b944bac, 0x2f69ee10, 0xd397e368, 0x97e3690f, 0x35937b33, - 0x78ff7cf5, 0x6785fbcd, 0x8bda6926, 0xda68f703, 0x68142f4b, 0x1503e5ea, - 0xaf2bf79a, 0xb3ea6ad4, 0x65f8da82, 0x61c5cdf5, 0xb47d38f7, 0xdca01abe, - 0xe6757ed0, 0xcbde6a6f, 0x575da358, 0xaebb4796, 0xebb51b89, 0xf6cdc752, - 0xd397d76a, 0x325f5dad, 0xbef2e3e6, 0x7f2e3e7e, 0xc7c95db6, 0xdfb058e5, - 0x2d938d33, 0xf7a9b768, 0xfef7d5a9, 0x5866372f, 0x007f40df, 0x00000000 -}; - -static const u32 csem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0xe4b3ff00, 0x51f86066, 0xb97bc10f, 0x726e1818, - 0x0143f821, 0xd08667cf, 0x0c0c2c6a, 0xc6cc401a, 0xcec0c0c4, 0x717ebc44, - 0x1d7b044e, 0x4cc30307, 0x31c8de20, 0x481afef0, 0x7e879d7c, 0x42f3a976, - 0x81c15968, 0x570837f7, 0xb430310a, 0xc430330a, 0x0cf84088, 0x55f2a8a2, - 0xa9b60842, 0x39766524, 0x0003f502, 0x3471cc24, 0x00000380 -}; - -static const u32 csem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd554780b, 0x733ef0b5, 0x7993331e, - 0x0f20f264, 0x0084f102, 0x021842a2, 0x27088784, 0x01a8c421, 0x54bc8083, - 0x48433c26, 0xbfa81132, 0x2677bd6d, 0xb5ad1104, 0xbc1b6951, 0x14101de8, - 0xd1a07515, 0x40e81c06, 0xdbdab114, 0xd5a8f8a8, 0x40445076, 0x8bcbc248, - 0xaf7fd52d, 0xe649cfb5, 0xd4484c9c, 0xffffbff6, 0xdbf3f1fd, 0xd9cfb3ec, - 0xdaf5ed7b, 0xf6bdad6b, 0x9a32c11e, 0xe4224e24, 0x65a3f85b, 0xf4842784, - 0x0adb2ce9, 0x64918fda, 0x8b2ffc42, 0x108e36f2, 0xf08e77ee, 0xbc8451a4, - 0x980b99b5, 0xcfbc3d69, 0x9fad0846, 0x603d34de, 0xff6422ce, 0xef02b308, - 0x8f9ade9f, 0xbd2fc9f5, 0x7b6814e7, 0x00bc4bd5, 0x13bed375, 0x109d88ce, - 0xa1e5b9af, 0xf6f3e96b, 0x85b27897, 0x93fc450e, 0x9085244d, 0xfec21663, - 0x52fab22e, 0x6d56ab2b, 0xf4077fde, 0x2664de5b, 0xd54fda56, 0xaed365ee, - 0x8765f5a5, 0x54af0244, 0xfa95ab6d, 0x00f2fad2, 0x9afa8417, 0x71c67f7d, - 0x79480ada, 0x27212870, 0x5f22167d, 0x96ceeb49, 0x79f45994, 0x11676045, - 0x83b15fbc, 0xfbe89b73, 0x7ff69b15, 0x3457fd0c, 0xda79038a, 0x36ed8aff, - 0x63610f22, 0x1e604b7f, 0xbc01a64b, 0xc4886f55, 0x97e5eb4c, 0x70044956, - 0xa54bd424, 0x61ff180e, 0x38c07649, 0x0d1c7087, 0xd0cf559f, 0xd577e871, - 0x986e702f, 0x7889b55a, 0xddd69e00, 0xda4f39d6, 0xd2b55e61, 0xf77ef860, - 0xb7bc127d, 0xb2f6502c, 0x36f80655, 0xe700454b, 0xd2d2cda6, 0xadfd9da1, - 0x0ea6fed8, 0xd90d63ae, 0x76a89ea9, 0x47d27963, 0xacee6c88, 0x04a21057, - 0x407700ed, 0xf3ac3e9a, 0x812e79f9, 0x3fd0d190, 0x674b644f, 0xc83094ff, - 0xe8f7fe07, 0xf60f813f, 0xb2db023a, 0xd2b5e93a, 0x772dff45, 0x4bacebd2, - 0x9ed09fa5, 0x56bfdd17, 0xa074043e, 0x5cfbd4f0, 0x4be23e58, 0x4f8372c3, - 0xcafdbc46, 0x06cb0437, 0x3f9f1b9f, 0xe58b1be6, 0xe5829f26, 0x2c62be13, - 0x7c52be03, 0x0e6f8b6f, 0x1e7d5b96, 0xaf94fe7c, 0xbeedcb1c, 0xacfe7c1a, - 0x772c6eef, 0xfcf8fcf8, 0x2c7adf05, 0x2c7abe83, 0xb01af977, 0xf005f46c, - 0xdb7d97bd, 0x05f26cb1, 0x5f1ef9f1, 0x5f219613, 0x407dcb18, 0x7d865a5f, - 0xf01e582d, 0xabe5887d, 0x777e08be, 0xcb1c77d0, 0x3bbc5507, 0x817c9027, - 0x10a9cde2, 0x92171517, 0x8be4a258, 0xca589eb4, 0xf9b729ea, 0x4f5a25f3, - 0xc53ad0f1, 0x70cadf63, 0xfbd699be, 0xccf6b0d6, 0x8581487b, 0xacfd33d6, - 0x4a83c07d, 0x07d69581, 0xc1f6b3d4, 0x7105fc9b, 0xc0383eb4, 0x11deafda, - 0xfad1b02e, 0x9ed641d5, 0xed932213, 0x66139eb4, 0x94b7dcf5, 0xcf5a0ec9, - 0xbcf5616d, 0x9d93fd8f, 0x61179eb4, 0x153f8fdf, 0xeb4f1c9e, 0xfb59dbe3, - 0xd0a44bc4, 0x0913eb45, 0x7b02f587, 0xad02617e, 0xbd58b817, 0x20995fa8, - 0x7dbfe0c7, 0xa1116462, 0x7fddb0bc, 0xd3a422b3, 0x455914ba, 0xfe9f14dc, - 0x8b0f5839, 0xbfb43164, 0x84532fe5, 0x912eb471, 0x17fed0d5, 0x1fb6057f, - 0x6f6c6510, 0xf6c2aff7, 0xed8c9203, 0xb07bdaa6, 0x60a8aafe, 0xbded727b, - 0x92abfef8, 0x6b83ed82, 0x41fac21f, 0x63ed83d1, 0xef8d7f6b, 0xd83c941f, - 0x80dac8fe, 0xffeb4852, 0x00b679c1, 0x9e71d75f, 0xfc0d9272, 0xa52b4c1a, - 0x238ebafc, 0x1e3e4073, 0xf2a6a600, 0x525d2eb0, 0xfbedbf40, 0x3c93de47, - 0x3276f2a7, 0xf53e97d4, 0xf3f61640, 0xd223f61c, 0xfb9ef87e, 0x58cdf899, - 0xbf133f5d, 0x69fad729, 0xaceaf784, 0xdf67ebbd, 0xf0f5e337, 0xf5a1537c, - 0x71fb17b3, 0x135e6ef4, 0x87a09dbf, 0xad4adbe7, 0x4fd8839f, 0x09e0ef42, - 0xfd74638b, 0x5a65c584, 0x7ec47f3f, 0x1e0ef4fa, 0xeba71a45, 0x6b969147, - 0xfd887cfd, 0x9faef7a4, 0x1ead74b0, 0xd685691e, 0xa7ec11cf, 0xa5e6ef7f, - 0xc3d3af98, 0xfad2ae63, 0xcf748939, 0x073f5dea, 0x1cfc7a1c, 0xe7e07470, - 0xa833c21c, 0x702af377, 0xe053f1ea, 0x25cfc0ec, 0xdeaae7ec, 0xa9c073f5, - 0x6701cfc7, 0x0e447e07, 0x77ac35e6, 0xd7882af3, 0xbe20a7e3, 0x0e4e3f03, - 0x3bd119e0, 0xa3ed5e78, 0x7dabcfc7, 0x8a93f03a, 0x1dee8cf0, 0x7a29853c, - 0x74a614fc, 0x784647e0, 0x9faef5c6, 0xf8f45357, 0x03a53579, 0x3f61573f, - 0x5e6ef5d7, 0xfc7aa985, 0xe076a614, 0xc9fb1727, 0x78476cf7, 0xd1c7ed08, - 0xfb073f7d, 0xb073f1eb, 0xae7e077f, 0xd0a67ec5, 0xee7bb27e, 0x8f5328a7, - 0x0ecca29f, 0x9e2214fc, 0x3f5de86f, 0xf8f53307, 0x81d99839, 0xcfd8a99f, - 0xabcdded4, 0x7e3d0ae8, 0xf860ae8a, 0xc08c2499, 0x9dae8675, 0x727e9e6e, - 0x857cbf7d, 0x2ef3efa3, 0x6e5de756, 0xaf0f7602, 0x45a433d9, 0xf6fbe9e1, - 0x0fb9091d, 0xa6bb6890, 0x8fc076e0, 0xd1795a83, 0xd8fc4d76, 0x951d9d38, - 0xeaea24a0, 0x757dc549, 0x1d29f7ef, 0x9d4f6ba0, 0x3daeb573, 0xabab93dd, - 0xd78f9467, 0xa6bfdfbd, 0xe2bf5740, 0xef751bee, 0xd16ff967, 0xcfd7b3d5, - 0xa83fbdd3, 0xfdaea17e, 0x5d0a86ca, 0x958155fb, 0xdb35faba, 0x7f7ba27f, - 0xae8d7058, 0x03d3787d, 0xe111f6ba, 0x91f57447, 0xbdd31e87, 0x8b65ba3f, - 0x87cc7dae, 0xc7daeacf, 0xeae97645, 0xa3df1ed7, 0xf6baff7b, 0xa4faba03, - 0xbdd7bf8b, 0xd5de4f9f, 0x3f96dbdb, 0xe29fdeeb, 0x7ed74cfa, 0x0697da7d, - 0x3aeed53b, 0xe75a8d76, 0xfa08ae41, 0x0974fe25, 0x43b0d5ed, 0xd7d4bac2, - 0xc714fcce, 0xe528f952, 0x22c0e91f, 0x92f91939, 0x21bb51fe, 0x95f96fbf, - 0xaefcfa11, 0x5d2b9ef1, 0x925df9f4, 0x862bb867, 0x8df9437d, 0xca506923, - 0xed8d2826, 0xdf8c89f7, 0x0d2e320b, 0xf7bf423e, 0x2707da9a, 0x3e70fad0, - 0xf1f2083f, 0xbb426732, 0x35278e3a, 0x999c5ef0, 0x5f74dfa0, 0xfe93de56, - 0xdf587928, 0x5c19da9f, 0x45ebbf67, 0x51da1a4f, 0xc1f89fb5, 0x9fd759ce, - 0x212fabce, 0x849f70af, 0xf7e903fd, 0x79a697fd, 0x89667f68, 0xe3d119fa, - 0xa1fc744b, 0xe4187e38, 0x3f8c20e1, 0xe6f8ebba, 0xe3756301, 0x75cb325b, - 0x3a245be3, 0xdf908bbe, 0x8eae7ed7, 0x9e30894f, 0xcfb93790, 0x66737c71, - 0x9f7f8e39, 0xe8aefd44, 0xc63ae3f1, 0xbff9816f, 0x07fcdddf, 0x3fcfd78c, - 0x7f3f42b3, 0xa3ffcd89, 0xf8ead3da, 0x3fff3871, 0xfcd9a773, 0xfcd82b33, - 0x8edfaccd, 0xf81d9df1, 0xc7f8c08f, 0x9cdf19ba, 0xff3f413d, 0xf3f52a2b, - 0x4ff1b337, 0xc7505ed6, 0x5ff8e3b7, 0xfcd81772, 0xf1c4a8af, 0x0dc7b325, - 0xc46523fc, 0xf8e804d5, 0x7c551fa4, 0x742ec0a9, 0x2487281c, 0x6421a152, - 0xe100371b, 0xf18e2bb8, 0x947157db, 0xf99f50df, 0x500939f1, 0xfd4799cd, - 0x57d79546, 0x4097c8ec, 0xf53b61ef, 0xa0a896b7, 0x91e26e2e, 0x7306c9bf, - 0xb7851060, 0x43f789b5, 0xeb86f17d, 0xbd5fa002, 0x14a0b266, 0x184813be, - 0xcbfe7f9e, 0xe7a25b61, 0xd4972c65, 0x5122c78b, 0x07e1d6f2, 0x35219016, - 0xc029be14, 0xeb3ba304, 0x0e3f529f, 0xa98fe31c, 0xffa843df, 0xc6c899f3, - 0xf7f50bfb, 0xfea11ea0, 0xa4ce3a1e, 0xdda3bf16, 0xf0a34e1d, 0x7ff0aa97, - 0xfd79302a, 0xe02e36f4, 0xd5f9f2a7, 0x7fa0478f, 0x1b6ee0bd, 0x1c277a45, - 0x5d24fe65, 0x0fcbce9d, 0x6ddf6a74, 0x10e16c0e, 0x6be032bf, 0x21268a3a, - 0x5067d68b, 0xffbe775c, 0x07a9bec1, 0xb7212739, 0xa54c4512, 0x9abedfef, - 0xe3a2efeb, 0xb9cc52ce, 0x32521d6c, 0x24d7284c, 0x909634c3, 0x88471a5b, - 0x5d3207b4, 0x448d3f11, 0x58a33b8d, 0xaa559f5f, 0x8a8ab7af, 0xb570a268, - 0x66c8e74e, 0x39ecefda, 0x9c6d76fa, 0x4644a681, 0x52bc7567, 0xfa74938a, - 0xb9943668, 0x7485d8f0, 0xdf62e39e, 0x1778f06a, 0x7e8c2489, 0x010fbfbc, - 0xf193faba, 0x362e79bd, 0x73bc236f, 0x4a528b44, 0x8ca739e7, 0x1b7f000f, - 0x9f68ffe1, 0xd0e5314d, 0x22a3fd72, 0x8f9d7531, 0x1eb9fe11, 0x22827ce3, - 0xcbf3f3ac, 0xdf19cf8d, 0xffe9531c, 0x2d07f029, 0xa0fe00bf, 0xf9551ff0, - 0x32af53a3, 0x3d9af0fe, 0xda1f80d3, 0xe904f237, 0xadcbf2aa, 0xa92cbf2a, - 0x2105f3d7, 0xb8e8111e, 0xfb970e6c, 0xcc1f1440, 0x5960f956, 0x6e6f9e83, - 0x3d317e27, 0x6ee65d06, 0x9a6f7cd8, 0x9f7e75dc, 0xff337ca8, 0x9f88fdc1, - 0x7464f3ae, 0xd3a543ba, 0xf6fa35ed, 0xdeba555b, 0x4e75d2ae, 0x51afc3c3, - 0xc9e641f5, 0xdde41101, 0x9e8d53fb, 0x3d3d1d11, 0x708d3d2a, 0xf3d2a1de, - 0x7a331f8e, 0xa88de11a, 0x9c348cf4, 0xae80c913, 0x5be11af0, 0xf9977770, - 0xccab5c60, 0xde9e9b1f, 0x4755fca6, 0x05579ea3, 0x3475586f, 0x6c56ce4a, - 0x2fabae9f, 0xbdd5cc0f, 0x4ca1acbf, 0x7ea4bed7, 0xd17daeb9, 0xf5753bfa, - 0x758fff32, 0xbbb82fef, 0x7b7ed756, 0xf6bafdcd, 0xeb0fe5f9, 0x1b3d73ea, - 0x9ecfef75, 0x3ed759b3, 0x5d19f4ab, 0x9de28cfb, 0x6574faba, 0xd37deeb7, - 0x066eabbe, 0x3deb7cfe, 0x713d809e, 0xc605fdc1, 0x45b82f33, 0xd473bc37, - 0x1f5f2327, 0xf2c10df3, 0x7c8dcfb8, 0x1637d27f, 0x66a6d6cb, 0x7413ac3b, - 0x124a5c5d, 0xcd326908, 0x0fdf5dab, 0xeb8269d6, 0xa9e4c869, 0xb37ad3f5, - 0x28794649, 0x78489069, 0x2c1c2124, 0xed1c2a36, 0xa47b547c, 0xaa06f687, - 0xb6ba93f8, 0x3f624497, 0x76523ef7, 0x7765f005, 0xcbfd03eb, 0x4da7bb00, - 0xed8debb5, 0x8d291c95, 0x1ac84e7e, 0x626ac384, 0xc4a54776, 0x5772bfe4, - 0x4271017a, 0xe6b83c3d, 0x2905e372, 0x9f02a793, 0x78e4eb64, 0x3a35c359, - 0x9a204efd, 0x6df807dc, 0x8af9eea4, 0xbeead7ed, 0x479fb53b, 0x5741abb8, - 0xb165838c, 0xe81333f4, 0xe67370e1, 0xa700618c, 0x4deb1472, 0x3c2ed07d, - 0x755e2be5, 0xafd01074, 0xbee3cb14, 0xf31e5839, 0xea3cb079, 0x53f2c72b, - 0x11960d5f, 0xfe58dddf, 0xf2c7e7c5, 0x2c7adf63, 0x63d5f23f, 0x01afa1f9, - 0x017df7cb, 0xb6fb0f2c, 0x2f8ef963, 0xaf8b6588, 0x9f56cb09, 0x7726a582, - 0x71ddf13d, 0x093e1d75, 0xcf8317fc, 0xed7f3aa4, 0x7c9d09fa, 0x87dfc716, - 0xb9e1a67c, 0xf2acc1a4, 0x1f8e8a43, 0x4397c012, 0xbda1eb3e, 0xb0f95441, - 0xb763efbb, 0x6bfcb77b, 0x0fea6df8, 0x7e4eb7e4, 0x53f030ca, 0x34fc4f76, - 0xa7e28f8c, 0xb31726a9, 0xfa7e547b, 0x8623cc19, 0x8c0f315f, 0xf6513e90, - 0x826f929a, 0xbaa56c75, 0x601f420f, 0x763aacfd, 0x05b77d1d, 0x10c0baed, - 0x0ece3758, 0xd860dbf9, 0x21fb3847, 0xf7567e25, 0x49f233f3, 0xd05778f7, - 0xa01a59bf, 0xdaea4f44, 0x78638d6e, 0x31489ab5, 0xfddaeba1, 0x2f729e83, - 0x81758a1c, 0x01f7c224, 0x8c4774f7, 0x0cada97e, 0xaf09edf8, 0x72af8e75, - 0x8f63bfa0, 0xca0f3dfd, 0x2f6626a9, 0x68f335c7, 0x93f093b7, 0xc76fc06e, - 0xa77664ba, 0x7dbdbc41, 0xbb42e490, 0xe3d64c81, 0xc3a05fcf, 0x4714fddf, - 0xd6eeb82d, 0x06fe21a7, 0xbd38357e, 0x49ebf817, 0xcf84f7bf, 0x7fef3085, - 0xd27b3e01, 0x45e93d8f, 0x342fc8a2, 0xedb7f9d1, 0x80fb961b, 0x1e5ee30c, - 0x9afedadf, 0x7e5f9e11, 0x4b6e3e47, 0x25b8f8d1, 0xa41f8093, 0xc6d9cbca, - 0x2e81e32b, 0x40f4fd1d, 0x9f77ee4f, 0x7eff8264, 0xdfdf4b3a, 0xe2fec67d, - 0xa70dc225, 0x89243ae3, 0x92bf53c4, 0xd1e36cf7, 0xfc47719f, 0x67d83710, - 0xe0c9d773, 0xaffc9e37, 0xeb3d0cb0, 0x0f670be3, 0x3f04e93d, 0x5f1a656c, - 0x1d063473, 0x982ab2b5, 0xf68f6355, 0xf5f49a57, 0x715cf5b3, 0xc725e710, - 0xeb061ccf, 0xa8e6ab8c, 0x0d3f7a08, 0x959fad4b, 0x738e1269, 0x3c767b72, - 0x4c02fff3, 0x4048ec9f, 0x67d2737d, 0xd9fff7c1, 0x8fd774f0, 0x8d210f06, - 0xe80b33e4, 0xdd96da73, 0xcaddfbfd, 0x825e7083, 0x890929f8, 0x69bf815f, - 0x3b7fffa5, 0xb015fa00, 0x0debf5ae, 0x70f37ef2, 0x3743be78, 0xd64efd1e, - 0xbbe18cf6, 0x204ee5ee, 0xa7be34c7, 0xbaabfbf4, 0xbb62bdbf, 0xc76f46b5, - 0xdeeae826, 0x9d1af4a6, 0x00ff0b5d, 0x1386bdc3, 0x54ab0960, 0xb04db0d9, - 0xda7e07af, 0xf049c103, 0x5ef6385f, 0x79222595, 0x16971464, 0x6385d3e0, - 0x6797fe35, 0xa9ea99ff, 0x048a6f13, 0xa25c8ce4, 0xaea9e550, 0x899bf220, - 0x917d6898, 0xc6c2f6fa, 0x6eb02515, 0x26f9789d, 0x931643f4, 0xc7f82752, - 0x0f3ea4e5, 0x89a7b5e2, 0xf3e418a9, 0x39c77934, 0xad1e4a32, 0x2e9d8482, - 0xe3b7af5a, 0xabaf7fa9, 0xd7d06b2f, 0x525b9297, 0xe97edf60, 0x38049106, - 0xf6fa1bd0, 0xf61779af, 0xacd48cbb, 0x57fb7583, 0xa16bbc6a, 0x5419088b, - 0xf6fd556f, 0x0a32bcf1, 0x71604b87, 0x7a1f6d16, 0x7ff32279, 0x2406662a, - 0x59ffbe85, 0xa95bc8e3, 0x07dfa206, 0xbc7ec1d6, 0x6f713a7f, 0xf7e95d23, - 0xc237e15d, 0x5d03d9ab, 0x3855c3f6, 0x4a73b792, 0xcb1e8620, 0x67263814, - 0x102bbeaa, 0xc7b8ba5c, 0x7bfd4334, 0xd13253f3, 0xde1ed3f1, 0x668c2793, - 0xc0fc03fc, 0xe792ed09, 0xd69ff487, 0x7f82ffa5, 0x68fdff6a, 0xfeba79ff, - 0xfb53fda7, 0xfe05d81f, 0xaffab179, 0x2ff3edfa, 0xa93ea9fb, 0x4e97f178, - 0x13c9d742, 0x9b8a7d42, 0xdb72b5d2, 0x96854ebd, 0x13bf05c7, 0x8044f5f8, - 0xef458e2f, 0x154e0587, 0x41cec542, 0x49fe0ddc, 0xecf93ffb, 0xf11e30cf, - 0x85d136d5, 0xe6edb4f1, 0x61ca99b0, 0x12f2e375, 0x23f58392, 0x19df7eac, - 0x7a4dea1e, 0xfa78abfe, 0x1f902997, 0x8d453942, 0x9ed1852f, 0x79fadead, - 0x5e4fac11, 0x64728ed2, 0xbfc60efc, 0xaffa8898, 0xdaef8a4c, 0x38c4e14e, - 0x8bc55781, 0x6767f1b7, 0x37942778, 0x82fa017c, 0xc7e8227a, 0x572bbf1b, - 0x8235d4ed, 0x8d98f923, 0x190c7bfe, 0xc3517a03, 0x3b30090b, 0x5f99eeb5, - 0x70a11ce7, 0xa6fada9d, 0x97c28b93, 0x83674f26, 0x8f73fe8b, 0x6ddebddc, - 0x6d16f2a5, 0x96eb690f, 0xd7daa4dc, 0x8a565621, 0xf3e42761, 0xdd166e54, - 0xf2b8fa7e, 0x7a9f27f9, 0x7f99e20c, 0xd107bb32, 0xff3c57fe, 0x69e3fbda, - 0x314ec57d, 0xc34d84b9, 0xd274a5ce, 0xbfff4bc7, 0x1e93b73b, 0x4d79bf15, - 0xe7b18792, 0xd27624f7, 0xfdcec565, 0x15d61912, 0xfb83931f, 0x063d88a5, - 0x8a47827d, 0x7ba85ec0, 0x8825bfe6, 0xc7d89e33, 0x18acd491, 0x1afcdcf8, - 0x278003da, 0xaf4aa7a4, 0xde19fa0e, 0x80ba52f7, 0xcbd236de, 0x5522def8, - 0x90bf40bf, 0xfbf94167, 0x07903d85, 0x0dd991f5, 0x617f2878, 0xf3e61395, - 0xf8c35085, 0x537bf1fc, 0x8b959f40, 0x961714fe, 0x13f979ec, 0x5bfe423f, - 0x528ff6f6, 0x9444be30, 0x45ae1374, 0xe79874fe, 0x70b34d92, 0x07894b9e, - 0x71fcb0f9, 0xcb4034be, 0xde29020b, 0xac4e4319, 0x2f939322, 0xd2e250b6, - 0xfe017e79, 0x77efe824, 0xb436c0f8, 0xa024efbb, 0xcea47e0f, 0x580c5a85, - 0xf46160bf, 0x2ebaabfa, 0xa33eb010, 0x7deb77f9, 0x93a7402d, 0xd85495fd, - 0xc112f177, 0xfb83e2af, 0xbfcbf696, 0xd195253d, 0x9e42c889, 0xf75d1dfa, - 0x7873c327, 0xac5445bf, 0xc8efba39, 0xe39d59b7, 0xa7c756af, 0x7ac1c770, - 0x6c4a45fd, 0xd44f35fb, 0xb75d00f4, 0x4a2cf8a3, 0x6ffc99de, 0xbbc99fbd, - 0xe981ff26, 0xfe7ed0c5, 0xf8239330, 0x0a43d60e, 0xdb153857, 0x50e4cff7, - 0x3a3f503f, 0x156f9c96, 0xb7d73955, 0xc285f91b, 0x51f1702f, 0x24e3037c, - 0xdf701d22, 0xfa06e965, 0xf51e947d, 0xaeceb8c2, 0xbc726afd, 0x455bf34c, - 0x9b203ebd, 0xdee81e98, 0x9e23f2ae, 0x53c0c52a, 0x52fc818f, 0x20cbf579, - 0xcc2962bf, 0xcd1dcbff, 0x72a3cfef, 0x935065fb, 0x355ebd5b, 0xaef96dca, - 0xdc9624d1, 0x9377697e, 0x9f4b7298, 0x7b5b94c7, 0xfff9f904, 0xf0d55eb4, - 0x78f00c38, 0x351e274d, 0x3e1dd93d, 0x90f27a8d, 0x8d5e2320, 0x1dfe927a, - 0xf95d7926, 0x8d43e351, 0xab9e2aff, 0x51f402ba, 0x7c6a9f07, 0x1aa7c1d8, - 0xef89761f, 0x6c68f0ea, 0x34fb00bf, 0x96f9ae14, 0x528ed38d, 0x4ed2d257, - 0x7f26df70, 0xaafb8f26, 0xe584f396, 0xf3111081, 0xd5303f43, 0x753b068c, - 0x3d6fdfe2, 0x7785177d, 0x2c8bf13e, 0x445ea02f, 0xb7d2ffbb, 0xf3a04edf, - 0x79e2a799, 0x54fb453e, 0x0239974a, 0x70a38e17, 0x3f8815ce, 0xb7e2113e, - 0x0a34f91c, 0xfae5f98e, 0x4c4dfc3a, 0xa7a7ece9, 0x9fabbff7, 0xb7cb7df2, - 0x1d3f5d29, 0x50bbc844, 0x10bc388a, 0x81d357cd, 0xde7f14ae, 0x00605c51, - 0x5088a9ea, 0xbd77e51a, 0xf3fb3220, 0xa319c2ed, 0x9fc9bec1, 0xf19e2c3d, - 0x7bf460fb, 0x3b3eaabd, 0x41e397eb, 0x650d9fcf, 0xf67b7fa3, 0xac4722d0, - 0x9566d0bc, 0xf7535ecf, 0x5cecda5d, 0xbff94f3d, 0x7da3b48d, 0xc95bb7e3, - 0x82fb18b6, 0x5f4d451b, 0x7fa374ab, 0x8e7f1d3c, 0xe97387ca, 0x51b9f1a7, - 0xf5399b74, 0x4aece084, 0x34fbf807, 0xa1fb0fca, 0x06be05f8, 0x235b36fc, - 0xe231a545, 0xf8a9cf79, 0x6be0789b, 0x0c2dcfcc, 0xc7800be5, 0x8baf3b42, - 0xc9a93c83, 0x143250eb, 0x60789ae0, 0x5347cff9, 0xe21ef63e, 0xeb8f90dd, - 0x3c919d0d, 0x2361fc31, 0xb07fa13e, 0x2e888f33, 0x627bd7c4, 0xebc012e9, - 0x04acb37b, 0x95df35f6, 0xe0b155dc, 0xf5b3332c, 0xbd292e66, 0xbffb8a30, - 0xb3f9bf0f, 0x8a02e11d, 0x9676b38f, 0xff95ddf7, 0x759fdc98, 0x0e5a8171, - 0xf56790f8, 0x71002e64, 0xf9e222b4, 0xe50e04f9, 0xfeb4527d, 0xfe9a6fca, - 0x54f5e43c, 0x89973887, 0x110b57b6, 0xdbd8f809, 0xfb0053b4, 0x289926fd, - 0x6a108f18, 0x8a8ccd86, 0x05111d7b, 0xdff357c4, 0xf80edde6, 0x4cd3373d, - 0xe8652e00, 0x01d82719, 0x512342e7, 0xd79bba0e, 0x5a647c1f, 0x10fd08a1, - 0x3f230fe4, 0x74db2514, 0x499359f5, 0xdba5373f, 0x95647344, 0xeafd063b, - 0xbd67c624, 0xff966fd6, 0x04dbf4cf, 0x5f18dfaa, 0xedfad18b, 0x7df18926, - 0x8d4b7e94, 0xd656dfa5, 0x17c0a9ca, 0xa766f72b, 0xbe575d02, 0x2c4fa4b1, - 0x8fbaf6fd, 0xa86ff7f9, 0xfd6de679, 0x1e1b7ea8, 0x51fadfa5, 0xae2316fd, - 0xa5ea5a3b, 0xcffcb37e, 0xa0ebdfc8, 0xb7cc62df, 0xa69fc558, 0xb5438adf, - 0xfb8adfa8, 0xa97cbaf1, 0xfa4f5249, 0xb397ecad, 0x6dba2eb0, 0xf007f831, - 0x0dedfa0a, 0x38c1cf55, 0x5dfee7a0, 0x3d277d72, 0x3d5bd557, 0x67843ff7, - 0xecadcf4d, 0xd33da1cf, 0x9e990f95, 0xf4c5995b, 0x4cbdcadc, 0xc41cadcf, - 0xbf519cf4, 0x6fd17415, 0x21eafbec, 0x23f47bf4, 0x1b7d7eb3, 0x23992f6d, - 0xfdf42dba, 0x9f3b5912, 0x5a3a3351, 0xd4bbfddf, 0x9f73be8d, 0x3d2e73c1, - 0x823fbbe9, 0x7a841bbe, 0x91c8206c, 0x1c6e3f91, 0xd3e5d368, 0xb1f5f7bd, - 0x79045ee7, 0xfe8f03f9, 0xe62607f7, 0xfafbed27, 0xbb9048d8, 0xaa1e00f7, - 0xf9519eef, 0x47e7d5af, 0x28793a7d, 0x7baaf793, 0x1baafe18, 0xd5df3639, - 0x7586407c, 0xd1176fe0, 0x2f7dbe8f, 0x9b67a3f3, 0xc0d8fa5b, 0x225fffcf, - 0x2bfd25ca, 0x87e28b29, 0x302b1739, 0xce2bb9ee, 0xccfc05b9, 0x80b10239, - 0xd0e0bb1d, 0x7ec0278d, 0x3d71705d, 0xe00bbdda, 0xc8e92279, 0xa1db98fb, - 0xebf6f527, 0xaf9da6bc, 0xf9ae9065, 0x8ccd1310, 0x7157132e, 0x5d59cd81, - 0x5da823f3, 0xc62df986, 0xabdf893c, 0x47cd9ff3, 0x8fe45f10, 0xe5f8cc7c, - 0x72788def, 0xad54bc33, 0xaa78f5e6, 0x89e262e1, 0x2ca4ba52, 0xb72f13a5, - 0x975914bf, 0x39cbed01, 0xf38cb7f4, 0x9c66f0d6, 0xcd4786bf, 0xbea059bf, - 0x24743f3f, 0x86889e66, 0x22f92ee7, 0xf80dde1a, 0x33d34b78, 0x206190d7, - 0x3c981f97, 0x7c0d1f3f, 0x178a7bf4, 0x73ade70a, 0x2bcee907, 0x65e2a3bd, - 0x6148e7aa, 0x24780c8a, 0xf367c035, 0x96be77ca, 0xb377e742, 0x210b9592, - 0x937f59f5, 0x688f103c, 0x1ea3b6b6, 0x9470f8d4, 0x5985c999, 0xf5ef2bd5, - 0x7ae21575, 0x50b9c4d3, 0x3d06c2be, 0x7999e6a7, 0xd7f261ef, 0xbaf7fdcc, - 0x6788518c, 0x91482e58, 0x5d015eb6, 0x86a73fe8, 0x40bc5d18, 0x69cffa17, - 0xe020fda4, 0x73993abd, 0xa6fde187, 0x3f02f79d, 0xcfa56ebd, 0x39cbce41, - 0x0e8616f7, 0x65ca7a7b, 0xc58858f9, 0xc8cc18c7, 0x173f5ceb, 0x5d897bc0, - 0xe68993ed, 0x8e00f796, 0x366e5489, 0xfd00c3c3, 0x46fe8a2f, 0x07c8c5fb, - 0x7503e53d, 0x2ab9efc7, 0x3a075f9e, 0xeddf01d8, 0xde43d812, 0xb47f5b30, - 0x1720af76, 0x3a34de22, 0x65f5d134, 0x2983a314, 0xd66f9e06, 0xbd9e2aea, - 0xef844e21, 0x6ffea06f, 0x7ebb0712, 0xf8d41f5f, 0xc5772cdd, 0xd215c413, - 0xe806f4a3, 0xcd7de8b7, 0x11b7a6ea, 0xa6ae375f, 0x15dc99e6, 0x407d1a5f, - 0x6f0e5e0f, 0xd34fcadd, 0x61799891, 0x467e55df, 0xb3f2f599, 0xe6fedacf, - 0xedab8870, 0x90af50e5, 0x7e2e8250, 0xecccd330, 0x07ab6696, 0x0dfdbcf9, - 0xee45bdd1, 0xa8a67faa, 0x257f0174, 0x64e27cfa, 0x4de80898, 0xa67c9597, - 0xe3007bcd, 0xe0f5e8b7, 0xe907ab75, 0x33ff5dd7, 0xedfecccc, 0xead31ece, - 0x9078c3d7, 0xc7eb28d7, 0x5a47ae33, 0x79a7a95c, 0xbf71d479, 0x71b4bcef, - 0x84beebbe, 0x3c60b497, 0xd89fdb4e, 0x89767bc3, 0x73163f60, 0x0a107dba, - 0xfe6fee39, 0x59bffa13, 0xff7ddd1a, 0x530a3f10, 0xe3bebf3c, 0x9f638c49, - 0x34c8f67e, 0xaf159f90, 0xe542c4f0, 0x838775af, 0x889e5984, 0x45427604, - 0x5dfb8f23, 0xcde70844, 0xa833b288, 0xf1f0c327, 0x5ef503a2, 0xa0732ec5, - 0xf15f7e84, 0x103967f2, 0xc35d6b7f, 0x59ff9ff4, 0x91fd1f95, 0xa807c81c, - 0xbcfed810, 0xa88f3e91, 0xb76a79fc, 0x6fe80e6d, 0xc73b3b6e, 0x2d9c115b, - 0x0ce2a39a, 0x16459bf7, 0xc36ddee7, 0x33ff6c3c, 0x0331e61c, 0x48e7d17c, - 0x53d0fcb5, 0x5cbd30cf, 0xe00624d1, 0xf6c5703c, 0x1710ad9d, 0x8cd0f8af, - 0xfb77abf6, 0xd3ec0919, 0xcf3e2fc9, 0xf1371bce, 0x976878ba, 0x3e76e438, - 0x59f8866c, 0x01ea1563, 0xf5823f5a, 0xfbf71aa0, 0x15b2718e, 0xd97dee2f, - 0xe2b8514f, 0xf13b4f37, 0x36cb705c, 0xb723c627, 0xa05f7e5f, 0x7831dc4b, - 0x9c771abf, 0xf5c105fa, 0xf1dc7621, 0x2127caa4, 0x48ee3eb3, 0x3c6127b6, - 0x5799c292, 0xd17e231a, 0x5fcfffc1, 0xcdf60278, 0xf2faed4e, 0xf2bb8009, - 0xfc4f739b, 0x2a93e294, 0xdbac1720, 0xc3df67de, 0xbbed067d, 0xd27d55f7, - 0xb8d3ccfa, 0x27fad34f, 0x6b7a1bb3, 0x2645fbdd, 0xeeb453ec, 0xe2053afc, - 0x4ef7abb8, 0xf56d7f41, 0x4953934b, 0x2b407f0c, 0xbd037f81, 0xd23227d8, - 0x39b1b9ad, 0x4d3ce013, 0x77eb0ee9, 0x58393c47, 0xb2f4e2c5, 0x11de471a, - 0x4bae5f7b, 0xc671b8dc, 0x3ac1d7cd, 0x65ba28de, 0xf1f88bd2, 0xe1cf4a61, - 0x0ee3a0bd, 0x38209f75, 0xe3f1b2f5, 0x4a0ff0d3, 0x7d660baf, 0xe342fe1c, - 0x0c7cff92, 0xba931ada, 0x7b871f8d, 0xdf6d3f81, 0x2159bf6f, 0x5da39016, - 0x1edc61cf, 0x0f7d47e8, 0x85fcfad2, 0x1cbb884c, 0xc0efdb17, 0x66bdebfc, - 0xd8aaa3cc, 0x53ca01fb, 0xe36f4beb, 0xf7511abe, 0xc7495adf, 0x5127db1f, - 0x56ef3a7d, 0xab3b8b07, 0xb4b88074, 0x6ae7c4ec, 0xb5f199fc, 0x2eee9716, - 0x32d63d1e, 0xabbfed80, 0x5b5591fb, 0x43112cff, 0x0b1b9fbc, 0xd9723af4, - 0x0f0d547d, 0x98c3c02e, 0xd896fde8, 0xfd8efff1, 0x80dd0316, 0x758f609e, - 0x7ad0a7ec, 0x07ab883f, 0xed620fb8, 0x666eb5df, 0x62ad34fb, 0x6d45bcec, - 0xc5a465ff, 0xe812efb0, 0x4f4bbedd, 0x78aef8f3, 0xb42706ca, 0x9d7c574f, - 0xbf5b14ba, 0xd4e16adf, 0xe7be037b, 0x67257ebe, 0x05981bcc, 0x78d5597c, - 0x4a7b0244, 0xf9b4df5b, 0xe7fd529e, 0x78f2cf53, 0xb05d644e, 0x51bbf519, - 0x1613547f, 0x5bc23437, 0xab7a616e, 0x1fad89ba, 0x023976a7, 0xa9cfda76, - 0xaf91bb03, 0x911c77ab, 0x83bfb4fc, 0x45237fdb, 0x60acf2a2, 0xc14408fd, - 0xfd85ea7f, 0x897f6c39, 0x71c6ebf9, 0xf1c752ee, 0xe38f6286, 0x374671dd, - 0x507f0ace, 0x2e7ee762, 0x4149de3f, 0x9dfd0d99, 0xe409116c, 0xf20c9ffd, - 0xe31881c5, 0x5a88b5cf, 0x0fc98b3c, 0x1cf1475d, 0xbb9d83a6, 0xb42513e4, - 0xc63b57bb, 0xfde7087e, 0x19243b57, 0xb57517e2, 0xeeb52f2c, 0x4069dcdf, - 0x5b84baef, 0xdeae3f71, 0xb2575f80, 0x1ae21f2b, 0x51d2c2ae, 0xbd46aec0, - 0x7498a093, 0x1476aff0, 0xce14caa7, 0x469daab5, 0x0b9e3704, 0xc5459de5, - 0x65de1f30, 0xec635972, 0x52f6883b, 0x8bc289e2, 0xe39fd2e8, 0xca469724, - 0x7f968fd0, 0x39696953, 0x052e8d88, 0xb1858c53, 0x99fcddec, 0xdb779c2e, - 0x507fd50e, 0x614aec88, 0x8eb06479, 0xcf8aedb4, 0x43f1c321, 0xb47e50a2, - 0x1db9cfa9, 0x5e83f7fb, 0x4a24eb5a, 0x8a339502, 0x86cf9955, 0x2c23acf3, - 0xe9f0365c, 0x857aff99, 0xf10d6bf6, 0xd9b457e8, 0x25527cb5, 0x46cce401, - 0x41bcc41e, 0x936fe560, 0xe634e13a, 0x25781213, 0x298d3eea, 0xa1fd1dbc, - 0x7c589bb3, 0xff572780, 0xcf8b027a, 0xafc00091, 0x542b2fae, 0xe212cf38, - 0x3bfbc30e, 0x580f181c, 0x9422c6f6, 0x3443a01f, 0xf58a92be, 0xac1b5ee7, - 0x67f01cce, 0xbf555a36, 0xc0b4afc6, 0x6ac59b39, 0xf54a7dbf, 0x18a962e7, - 0x975e41fa, 0xe5faf2a8, 0x9843a2d2, 0x8a59e68f, 0x8e753e7a, 0x31acdcfe, - 0xaa204b4f, 0xfe601c9f, 0xadbc9773, 0xb708cda6, 0xc56b7f31, 0xc35d7d76, - 0x37a027e3, 0x127402af, 0x80e2e5fb, 0x3237e23d, 0x4613d7f8, 0x9afc777d, - 0xb5f8f4d3, 0xdafc7aca, 0xa7f11886, 0xadc3afc7, 0x97e697c7, 0xf8df8776, - 0xc873fab1, 0x8afc2aff, 0x548ed556, 0x4aff4af1, 0x654c292d, 0x42e9dc03, - 0x28c2e518, 0x30f61947, 0x9feeff07, 0xafc5a81c, 0xefd40edc, 0xb87cea69, - 0x1b3becc5, 0xf00f11c8, 0xe08e51ba, 0x79e82024, 0x75d8f91b, 0xfac40acc, - 0x4d7b7c8c, 0x355cf4f7, 0x0b23d5fd, 0x809b57e9, 0x3f23877f, 0x89bef3b0, - 0x05975024, 0xc176ea72, 0x59f41dfa, 0xb8458bdc, 0x17b885f7, 0x5efb820f, - 0xa43e585c, 0x0db4abe6, 0x306e7825, 0x029f3e18, 0xdca1e9fa, 0xf7a069f6, - 0x29484bbc, 0xc51fc1e8, 0x0f03f3b1, 0x38bf65a8, 0x85abd549, 0xef824c6f, - 0xe70ca243, 0xdb42dbd5, 0xdea0832c, 0x2a3de3c4, 0xabfa84de, 0x90d6fc60, - 0x6c5ae0c8, 0x38820c09, 0xc7115ec8, 0x013c5d6d, 0xd87665cf, 0x2f96216f, - 0xccfa16d2, 0x9f4a28b9, 0x7a3d36b7, 0x36b9c415, 0xa9e7629a, 0x7e9ab14c, - 0xec1bfad8, 0xc537b792, 0x1eeaf2ca, 0x51e7401a, 0xbaacfd3d, 0xb879330e, - 0xabf3a556, 0xf9c46f4b, 0x64e214bf, 0xf88a4758, 0x461a6edb, 0x3dee39e7, - 0xb0cf8d41, 0xf528e578, 0x2fd03afd, 0xdfeb5fa8, 0xddc3e9e5, 0xe7020547, - 0x2cd546f4, 0x15eb7f45, 0xca73e527, 0x704a7917, 0x616df024, 0xcdef0128, - 0xd04c7ef1, 0x22dd1fae, 0x4f33f8e8, 0x22f3575d, 0x44c05e54, 0x3edf50f9, - 0xec18222e, 0xfc0f00a0, 0xfd71ed75, 0xd55685f3, 0x149272ee, 0x970df3e0, - 0x5ef20e78, 0x7b89dadb, 0x6dbb850d, 0xa3845f71, 0xfa9c3ced, 0xbe25e5a5, - 0xbf7ad638, 0x62f8caca, 0x9d7044a3, 0x8ed4b8d9, 0x4b03c5f1, 0xf580ae2b, - 0x7b1fabfd, 0x8e7588ae, 0xc53f4a3c, 0x252c7cb3, 0xfe058c9e, 0xbc31cb5e, - 0xc697a7d7, 0xf8d7f7c8, 0x8d6fe359, 0xc697d3af, 0x35e56279, 0x7665637e, - 0x21d2c15a, 0xdafe049c, 0xe38f0e3e, 0x5cf1aeb6, 0x9f8ddcf6, 0x7800c9ac, - 0xd0e74dbc, 0x3884b6ee, 0xb1bd9625, 0xfec4eac1, 0x6bf8d75b, 0x2eef8f21, - 0x27a09c2a, 0x0377efbb, 0x813f5bfa, 0x677c2ca0, 0x73c32fa9, 0x642c4bbc, - 0x85bbc40b, 0x1c5bf4fa, 0x6f93ffc0, 0x7de14758, 0xeb84d4ac, 0x8dd146eb, - 0x08abfbf0, 0x1a83f8c1, 0x8d37edcf, 0xcf3e8e6c, 0xff3584fc, 0xc7a52b59, - 0xd21756b3, 0xe6e3c925, 0x3ff77e00, 0xf209dbfe, 0x8cd176dd, 0xfaabec74, - 0xaf77da43, 0x36dd9959, 0x0ad94e33, 0x64f293df, 0xc7b71394, 0x123c5ee9, - 0x78a04dee, 0x4ea3928f, 0xbbf1f9fa, 0x71d50f44, 0xbb449e14, 0x2892f909, - 0xc5d2ec8a, 0x4728fd29, 0x30905c9a, 0x4d8f2047, 0x885cabd3, 0x1ca83b0b, - 0xc3d8b28c, 0x962477e0, 0x105379d3, 0xfac2c4ac, 0x754e116b, 0x3cc6cb9c, - 0x7997ca79, 0x608a3870, 0x71121448, 0xdf4d7fa1, 0x6d7a7a6a, 0x59794102, - 0xa810b0fb, 0x126cfda3, 0xaf885622, 0x01722964, 0x0a251aa4, 0xef179e32, - 0xff304e5f, 0x78fd96d2, 0x42dd8742, 0x37c47e85, 0xfb5882fc, 0x869c7c79, - 0x401fcf2f, 0x6a1ce46f, 0x8de6003f, 0x73c6cadb, 0x3b4166bf, 0xa87f43bd, - 0xba9158f6, 0xdcfb8efe, 0xc209f2c4, 0x3ef44893, 0x687f519b, 0xebb8c9f6, - 0xbf606b22, 0x189fdc68, 0x055bb49c, 0xcead1bbe, 0xa89f43b7, 0x1098e6eb, - 0xfbf427d5, 0x66c8d0dc, 0xf72b07b8, 0x5dc72663, 0x3f21c9f4, 0xbefbf80f, - 0x17c8c47a, 0x2e54c223, 0x32a1f6d5, 0xeae1a7dc, 0x19fb43a8, 0x9e49de83, - 0xed152a3e, 0x8cdf955c, 0xdbe4d678, 0x77b9f728, 0x0ccd9bbb, 0x1a47e62e, - 0x275c21c6, 0xe836721c, 0xb078b7a5, 0x29f2dbf7, 0xbf5c281e, 0xf4a3f902, - 0xb81f384b, 0x21bfe601, 0xe415bd74, 0x27af7be4, 0x5475fa21, 0xbcd3f69e, - 0x0fae3e27, 0xc04e27ae, 0xf3fef543, 0x46127aea, 0x01c8777a, 0x78e89395, - 0x46ffc689, 0xa3e4d77e, 0xc8de2e0e, 0x047673c6, 0x0b9e59d6, 0x663065e2, - 0x7805c9b2, 0x3aedecd5, 0xfe25bed5, 0x56ffb474, 0x1eba88bb, 0x4f800665, - 0x5ecd44ea, 0xe3a25b77, 0x051dab53, 0x4fdb97a9, 0xfea45ef5, 0x1b39d459, - 0xfe8ed0af, 0x84a2f79b, 0xfe37bfcf, 0x7914289a, 0x898dfc3a, 0x7f15dd1b, - 0xb08471f1, 0x9ffec2fb, 0x230cdf9f, 0x7727dc7f, 0xe25aefce, 0xf5422579, - 0xf5aade47, 0x3f193675, 0xd7969c39, 0xfb682f55, 0x01e9dd9f, 0xa98fbca3, - 0x70c66fac, 0xeef20f4b, 0x25f8a9b5, 0xb3e80664, 0xb76a61f1, 0xff957564, - 0xbcfceaf3, 0xb6f78636, 0x8307db5b, 0x3de7ad3c, 0x2f687135, 0xb0264c46, - 0xb413762b, 0x8ffbdc7b, 0x5bde513a, 0x4feb7492, 0x8fc0bb57, 0xa7d9a9f2, - 0x7c6a5d9a, 0x552ec3af, 0x3e2d1bd7, 0x795135ca, 0x193cf0a1, 0x1c03f1e7, - 0xbfe62e75, 0xd05701c2, 0x3d584f63, 0x365fc075, 0xd838973a, 0xce12192f, - 0xb096f162, 0x93bb3e4e, 0xde419b47, 0xb03f1482, 0xfae9f9fe, 0x1eeb8837, - 0x0971b19e, 0x85aa5e0c, 0x97e9bec0, 0xd560d847, 0xfbc7f304, 0x6bfbb0e5, - 0xfbb2e5fa, 0x31c73732, 0xa18b65fb, 0xfa5ac27c, 0x144bcc18, 0xfb9cdf88, - 0x5006e1fd, 0x64f90e21, 0xf800d29c, 0x382b14b0, 0x71170c8f, 0x19de9473, - 0xbc839042, 0x994ac489, 0xd247f163, 0xfb48ffb9, 0xf39128cb, 0x06323f81, - 0x9a373c12, 0x9e7d8a11, 0xf13895e8, 0x8debd987, 0xbcc1ce5d, 0x41cfcaa2, - 0xa937ce89, 0xe9839d84, 0xf050fb88, 0x8eadbf01, 0xadb2715b, 0xab3ed817, - 0xd9e1813f, 0xc101bfe8, 0x5a825e60, 0x822257bf, 0x2bfd1135, 0xdfaff03f, - 0xcaff4164, 0xd041dc46, 0xb1c41fb7, 0xce3aecf8, 0xbfea1ebd, 0x702dda10, - 0x37268fcf, 0x343c3c9a, 0x40b716e1, 0x775e755f, 0x5f7c0736, 0x00ef172a, - 0x9c275b9e, 0x6716bc1d, 0xf8c99ed2, 0xf975e14e, 0x9afd1af6, 0xacfd1d44, - 0xd6895710, 0x08690ef3, 0x5cadedd8, 0xaafc1b9c, 0x831ce5d6, 0xe7a8b397, - 0x3cdd0411, 0x1fcc6cd3, 0xe7f55369, 0x90b2e3df, 0x84f5b51f, 0xc63d6fce, - 0xe8f30d7f, 0x386a8738, 0x973c6a77, 0x11dd969a, 0x7cc74a07, 0xee0952dc, - 0x43672332, 0xbce3b436, 0x124cf6ce, 0x6a64bce3, 0x5cf31ac4, 0xbc5256b0, - 0x4b780d7d, 0x40126b15, 0xcedea71f, 0x1f1188f4, 0xc47f9c6d, 0xfb47d841, - 0x1f331883, 0xd2d32b45, 0x4c584a6e, 0xbf4b4fdf, 0x79ed4b01, 0x19885d83, - 0x71b24c57, 0x64dcec3f, 0xfc18b103, 0xed1b24cd, 0x9de7b4ef, 0xff1415f7, - 0x37bb8c76, 0x37bc31c4, 0x37bc31c4, 0xe53e1a48, 0xcebf9078, 0xf7975bba, - 0x4967c1b4, 0xd10f2010, 0xb9f28e9f, 0xdde8c5c4, 0xf682bef9, 0xdca21f4d, - 0xc4941730, 0x436c9106, 0x21f167be, 0xafc87ced, 0x4024cf7c, 0x96db94be, - 0x16fbfaa5, 0x0604df46, 0x530df9f7, 0xb214dc70, 0xe2983ac6, 0xc9a96979, - 0xd3a3710d, 0xc2723f0b, 0x1985e991, 0x0f20792d, 0x1b8f79a7, 0x984a97e6, - 0x8e6cb85f, 0x2ed30814, 0xc2a81b93, 0x01ba7462, 0x4ccb3bf7, 0xc7aef331, - 0xe9fed8d8, 0x961738d1, 0x90d36969, 0x92f59d4e, 0x8c4bf004, 0x35e54a7c, - 0xcea8f17d, 0x6f94cc73, 0x790c5b14, 0x1349136b, 0x185beb87, 0xb1ac95f1, - 0x35b7aab3, 0x39064979, 0x52ab7d84, 0x3a3547aa, 0x4d5f500f, 0xfe28b8c1, - 0xbfd7a171, 0x79c37f06, 0x45ea015d, 0x10c88e4d, 0xa0ade7a6, 0xa1e2a377, - 0xe83f7b6d, 0x9f8efb0f, 0x0739dbfc, 0x55fd3bec, 0x9e807768, 0xbbcf7e3d, - 0xf4c7380e, 0x2e2c3dc9, 0x4fc18772, 0xfa63645b, 0x74ad8f7f, 0x8177e01e, - 0x9e791fef, 0x77257e28, 0xe593fdb3, 0xde70de01, 0x506f7f5d, 0x70c93055, - 0xf11f908f, 0x1fdea55a, 0x46c7a466, 0x2cb78b1b, 0xca59b1df, 0x4f7c6190, - 0x5c7f8c25, 0x378f43f5, 0xd1dfd03a, 0x63b859e0, 0xd9be0484, 0x7566435f, - 0x6445bdff, 0x025287eb, 0x151e67fb, 0x0f38466f, 0x2f6af7aa, 0x8fcb25f9, - 0xdd63a329, 0x27b0f54d, 0x187bcec4, 0x13e4b1e7, 0x129528b9, 0x1cfdc96f, - 0xfef0ddfa, 0xf33d743d, 0xee1f7ddc, 0xd9e719b3, 0x051f5ef5, 0x2a65b3fd, - 0x6de78dbd, 0x3ed88597, 0x41e262f8, 0xfe72ecf9, 0xc5cec436, 0x678de318, - 0x00db650f, 0xa9b0bf0f, 0x323cc4f1, 0xef6dce06, 0xfe20343a, 0x9f56f772, - 0x828bef52, 0x3ca1bb7b, 0xce5823ee, 0xe2902303, 0xf6f432bf, 0xd55fc05d, - 0x3ef13b4d, 0x8faaefb4, 0x9c2742aa, 0xe9ad4b90, 0x6e876a25, 0x8b20f903, - 0x5a7d9d39, 0xc49cf9bd, 0x9f866afc, 0xb7e7d4db, 0x20723e01, 0xd9fe5bdf, - 0xdbef4a04, 0xd1f3c52a, 0x6f3da5f7, 0xf7c3efd3, 0x3cdabe76, 0xed6b79b5, - 0x9c5e6a55, 0x0e4d3bf1, 0xb97ca9e6, 0x75f4eb78, 0xea8a297d, 0xa9917ef6, - 0xf3c3939e, 0x2d9f1a42, 0xe945a523, 0xa349f831, 0x84df076f, 0xd3f38e7e, - 0xbeb8bae8, 0x3f83c54c, 0x4c4fdd4d, 0x91957883, 0xa73a7a8f, 0x32462add, - 0x7c8dbe41, 0x7dcddad2, 0xb31b2128, 0x4acb162f, 0xa8cfc411, 0x15cebbf9, - 0x171cdf65, 0x14fe0fea, 0xe32b6ee4, 0x083d0efb, 0xf7e8314e, 0xff5c4537, - 0x54e43a57, 0xe90fffb8, 0x13f20e37, 0x4f787ecc, 0x4f98e71b, 0x808a0651, - 0x4f2c62ff, 0x81954afa, 0x97db3a83, 0x04e73c6e, 0x086dbbfb, 0xab51b8c1, - 0x69ef0f43, 0xe37a8f1b, 0x4a8f4ab4, 0x3f9be5a1, 0xdadace83, 0xc7177982, - 0xa771a92e, 0x58e2e64b, 0x39d8b4f3, 0x7778bddd, 0xf9a872a8, 0xfa540b35, - 0xfb6211dd, 0x4d370be9, 0xc9747a47, 0xa1fd54bf, 0xf50e46b2, 0x4b3e918e, - 0x3e63d7dc, 0x3e40a2da, 0x5e85df7e, 0xbba441e4, 0xda776e91, 0x371eec5d, - 0x7b8246a1, 0xe26d8eed, 0x8571ff70, 0x73ff7b10, 0x9df4ddb6, 0x479c63e6, - 0xdb2ff077, 0x2faebb5a, 0x908ff981, 0xf08dcf80, 0x425ff36b, 0xd4a7a614, - 0x2f3776f9, 0xf2c49912, 0x7f75d434, 0x815b9c39, 0x790793fd, 0xc6adcf96, - 0x35f834a1, 0x28f38d78, 0x7cf12be2, 0x8f035b41, 0xf877d979, 0x77067dd9, - 0xfd70e5ac, 0x9a4e8eed, 0x7bf6d15e, 0x30ca9baa, 0xfb43cb6f, 0xedb63b01, - 0x29f6c263, 0xcf7873d6, 0x0cf4b75b, 0xeea57cb1, 0xa30849e8, 0x374a62db, - 0xdebb3ff0, 0x0caf909f, 0x0a27de8c, 0x8c0ca0dc, 0x4122b7de, 0xb15957cc, - 0xf9eeba7d, 0x8e35768d, 0x9ef5eaa5, 0x24d48fe4, 0x696f8cc4, 0x9fc9a6f2, - 0xda778f26, 0x0a6f6665, 0x59198381, 0xd1879f80, 0x7afaa1bf, 0x3df99d9e, - 0xafa5cd0f, 0xa73c6f54, 0x3258a7db, 0x096bd196, 0xbbcf825f, 0x0f14bbd3, - 0xd8bdbd3a, 0xf8c3cfae, 0xe6d1f3a1, 0x3689c9a1, 0x189ca33f, 0x43d237bf, - 0xe919ef8b, 0xc007a462, 0x5bc67e09, 0x35816d7b, 0x38b7ce14, 0xaf7fb706, - 0x4d6ee115, 0xb9c0ac9b, 0xf9f4eacd, 0x3e01fe58, 0xb0fb074c, 0x768eceb4, - 0x8d87eaae, 0x225c5dea, 0x5ecbb557, 0xd9232ab2, 0x24d2a7b9, 0xb58993e0, - 0x17161991, 0x583e8f21, 0xa4f7045c, 0x32387c4e, 0xbff14203, 0x5646f07e, - 0xd77916df, 0xfcfb86e2, 0x690a8a4b, 0x2fd071fd, 0x95fa2fa0, 0x6efbe0db, - 0xf973c4eb, 0x1fdeccba, 0xcf9d2e65, 0xed66b1ee, 0xb33ed495, 0xf2aef5d0, - 0x4157e0f0, 0x4a5b2b7e, 0x542e218a, 0xba781109, 0xce2955de, 0xad872db0, - 0x7be9e3fb, 0x4f3cd91f, 0x76ee21d9, 0x8bae2d71, 0x94058795, 0xc588722f, - 0x573a0567, 0x6d6efd2b, 0x2993b51c, 0x5a26d77e, 0xd317e0dc, 0x97f07ee7, - 0xb22a26d7, 0xa35cf51c, 0x70077c1f, 0x7cb135ac, 0x0c6ffd82, 0xc65c8f8e, - 0x23efd82e, 0x34cfe025, 0x1a582cfb, 0x1725f3db, 0x37c8e79e, 0xb18978b1, - 0x76bb6dfd, 0x00ce49ae, 0x243ea8be, 0x1fc3fca1, 0x84559fd8, 0x613549c9, - 0x0eaad0e7, 0x53773c13, 0xcf08a87d, 0x84b9c0dd, 0xe07a754f, 0xa6ee735f, - 0x9e18af93, 0x44ae040a, 0xd0b71a88, 0xf9d5d56e, 0x9810d354, 0xdce3e10f, - 0xcf846e70, 0xa2ecd530, 0xa0afe7f3, 0xe087c525, 0xff70f372, 0x89e4fd4c, - 0x559fdc3c, 0x2d79aa27, 0xbe3e7626, 0xe557dd63, 0x39fb2b4f, 0xdd028f4a, - 0x25b1ff4f, 0x53f6c6cf, 0xe6d6afd0, 0x8429c75b, 0x35ed7f03, 0x7219e782, - 0xe0334993, 0xb19446cf, 0x47166fc0, 0x6c97caa2, 0x65fe9b3f, 0x9b36e940, - 0x7e53237e, 0x9fc1faff, 0xe3bbff22, 0x68b2ab4d, 0x59f8739d, 0x2e74c33d, - 0xef30b28b, 0x6bf565a8, 0xd006e74c, 0xc358e8ba, 0x4af1b0ea, 0xa3b33e17, - 0x143fc8ae, 0xba3171c6, 0x01ae50ee, 0x2c4c16fe, 0x901c23ae, 0xcb477f70, - 0x794b5957, 0xe2d1f806, 0x5d747a60, 0x3673c16d, 0x28179b88, 0xec4fe432, - 0xfa41ef51, 0x5786a5be, 0x7f4266de, 0x7fc04a09, 0x53e183bc, 0x54690ba3, - 0x5e3c81ae, 0x81ae5412, 0x0e7ebd7d, 0x7e83a24f, 0x96adf23f, 0x1bcfa089, - 0x0f28f9df, 0x82bf73ef, 0x2df233f5, 0xf9d243ea, 0xff6dfe9c, 0xe4fbd1cd, - 0xa9f91cfd, 0x03251df0, 0xec9cafda, 0x3951b722, 0x2c8853ac, 0xad9f8365, - 0x091b2ff7, 0xd91f4fd3, 0xa070af4a, 0x3ae3093e, 0x67bb13f6, 0x7e8dd400, - 0xec496933, 0x949dde55, 0x17ee3773, 0x7d346625, 0x85d610b8, 0x4a7bb1df, - 0xfcc14538, 0xee3b17d3, 0x9718236b, 0x373891b2, 0x9b898dc4, 0xd453f9a4, - 0xf1899af8, 0x945e7255, 0x87ceacff, 0x79085f7e, 0x2c6c63f2, 0x8fce81bf, - 0x823afd07, 0x848e58c8, 0xa0365938, 0x3df583d8, 0x4fe1f824, 0x588fff69, - 0xb2ca7c59, 0x8fe2e89d, 0xb7160e65, 0xe2c9c079, 0xf062718f, 0xe22bb016, - 0xd81710ce, 0x4b8f6d15, 0x0bcfee02, 0xdf709bae, 0xe309a0ee, 0x018b4fdc, - 0xb517ec17, 0x5bc8255f, 0x6d7f6748, 0x7eb5dd2a, 0xabe4911f, 0x0bf7ee20, - 0x9d3fab27, 0xbb8f304f, 0x801484fd, 0x0cc4dcfd, 0x3c744d4b, 0xd9839e69, - 0x1573bfbb, 0x043a04cc, 0x1811c6f7, 0x38becc7f, 0xb9e3d013, 0xe056b91d, - 0x4701178b, 0x66890f14, 0x5fd09dd7, 0x6f0a39e2, 0xf9673e16, 0x223c82fd, - 0xfc77e29e, 0xee19768d, 0x1ada7ad1, 0x56f311bc, 0xbde1379f, 0xee4a2fc1, - 0xf17f50e9, 0x3d02ecac, 0x305674fc, 0xbcf3e70e, 0x62f3e709, 0x2bd5fb5c, - 0x0c0fdc29, 0xc12ef161, 0xcfd00446, 0xbe40a982, 0xae5f3e93, 0xafa6b1f2, - 0xd11c8137, 0xc11c23fa, 0x29820c73, 0xcb48e51f, 0x276b6a27, 0x67d44f98, - 0xfc0f0b66, 0x8b5d371c, 0x8879853b, 0x25284d17, 0xb04dcf68, 0x05ce788b, - 0xbce199f2, 0x0f5544db, 0xb2b8fc4f, 0xbb07e584, 0x9ebdc30f, 0x7ef576cd, - 0x739f7530, 0xd727ca92, 0xa16f0891, 0x245dd7ed, 0x4d27886e, 0x8fdfa8ba, - 0x5f60ca78, 0x57fb514e, 0xf0855dda, 0xede89f38, 0x450d29bf, 0x2c3d6027, - 0xfc008a20, 0x6862d934, 0x09d23b07, 0x9febf0f7, 0xfd50e03f, 0x19924cdc, - 0xeda6c79d, 0x87e14d43, 0xb5fb446e, 0x5e037258, 0x0f95da76, 0xdfc03f20, - 0xc5cb9222, 0xb1f29f25, 0x1721c37c, 0x2cae046d, 0x8769fca4, 0x50dd5cf9, - 0x79d2b7ef, 0xf5903d5f, 0xfa087c0f, 0x93c7cae5, 0x8fdf4093, 0x95a5e957, - 0x7f01df1a, 0x7f19e2b9, 0xca7786b9, 0x2c8ed3e7, 0x37934f7c, 0x67e83be0, - 0x1f98188f, 0xf29bbf6b, 0xafc0d3eb, 0xfd04ed3b, 0x5ba59fb8, 0x699c80e6, - 0x7caab4e3, 0xd5d72c6d, 0xbf0fdcae, 0xc0bfe4fb, 0xbec28dd6, 0x75e8a517, - 0x83024fbf, 0xcfd72bd7, 0x68790698, 0xccf31176, 0x5173d452, 0x1e92fcd1, - 0xdf1a2fc5, 0x9c59dab5, 0xc99fe348, 0xe1e5dfbb, 0x840be4f9, 0x8748b2b8, - 0xcff1a2bf, 0xf7187f44, 0xe6122781, 0x67f9189f, 0x93fc3757, 0x40165e7f, - 0x9fe1756f, 0xba7f8c43, 0x0fda1be3, 0xe4616bde, 0xaa1c779f, 0xff2dddbd, - 0xfcf3c25c, 0xbe4ef7ab, 0x93657eec, 0x6a9f9f4f, 0x62d9c72c, 0x54bb2fe7, - 0xea96efbc, 0xbd01ca6f, 0xcec4d531, 0xe32409ef, 0xeeef0a16, 0xfcdeed38, - 0xefa86c9a, 0xda1e9814, 0x1ea33219, 0x78f769da, 0x669b7e30, 0x0557e761, - 0x23ce044f, 0xe45afbb8, 0xd921dfe8, 0x587660ee, 0xfb8f0c50, 0x37f1ec02, - 0x9d8c1f18, 0x2a43cb9a, 0xa662fa5a, 0x971d4617, 0xcfefc336, 0xbfccea3d, - 0x06967c00, 0x79dfa3b8, 0xcf784a8f, 0x0951f552, 0xf76fe3f5, 0xf1045dbd, - 0x79cf2d51, 0x8bb79ecc, 0xfbc2860a, 0xa1fedf8c, 0x8ead65ea, 0x5f404047, - 0x1fddee1a, 0x4b1e71d7, 0x297e6f7f, 0x674e51f0, 0xf93ef1bb, 0x3fdb1c60, - 0x11644d99, 0xb4719886, 0xdeb85ef4, 0xfcaf78cc, 0xff3b30ec, 0x27b0f336, - 0x2af2bdf6, 0x37ef187f, 0x8a77f6a7, 0xe7efec13, 0x6841f65a, 0xdd6cc884, - 0xd7354a0e, 0x26a33f30, 0x9349f81b, 0xf8a3fc43, 0x44327e0b, 0xb706bbf7, - 0xd07ff3a9, 0xa9fbb02d, 0x4bee1222, 0xefb09cfe, 0x363aea82, 0x40f4c9ca, - 0xe617eaee, 0xcb239c03, 0xcba06695, 0xd7162eb3, 0x5b0905f9, 0x6e6e81b2, - 0x8253f701, 0x0bf93ca2, 0x223df3ae, 0xd3b10e94, 0xe27d3df6, 0x8ff8c246, - 0x9c633d3a, 0xed099f60, 0x31bbe087, 0x824773e3, 0x588fb71e, 0x9aeb049b, - 0xab853706, 0x13bd9b78, 0x81ae0d0e, 0x8f97c64e, 0x00c6cb3a, 0xd03be01e, - 0x8e474d4b, 0x8d7be059, 0xcf7b821f, 0xe2883e30, 0x4e83e00b, 0x4016e0be, - 0xa283c35d, 0xfdb7cfae, 0x8b42f88b, 0x17c8f46b, 0x7e70b710, 0x0b98be2f, - 0x05f23578, 0xce3ce7b5, 0x505cf618, 0xc6937962, 0xe7b13fe7, 0x896efbe3, - 0xd913de60, 0x6bbf6567, 0x7dc049e8, 0xd8b8df90, 0x1c9f6d98, 0x28a6a4cb, - 0x7664e559, 0x2a3bf6bd, 0xda1cc223, 0xa2a8239f, 0xbced0db8, 0xdd27a87e, - 0x31c8fe2a, 0x46fb838e, 0x033e3731, 0x1270d0ec, 0xcc236bd8, 0x87906125, - 0x1989b65d, 0xdae63f60, 0xfcc36426, 0xfab21e5f, 0x5ed2584d, 0x9bfe5bee, - 0x7da772ad, 0x66c3e9a5, 0xfc6d5bb5, 0x4c7f2a35, 0x2779d852, 0x70d1ebd0, - 0x9003eb68, 0xc2e0e009, 0xdadf4db3, 0x22878f50, 0x00936f14, 0xfd878a0e, - 0xfb04691c, 0x24a4df21, 0xb03b064f, 0x3800584f, 0x9d7ef6db, 0x92cef109, - 0x021febd0, 0x3eda25bc, 0x0fbf5bac, 0x35b7b46b, 0x3ff3487b, 0xf3497b34, - 0x82aec17b, 0x1fd532f6, 0xbed99971, 0x05b084d8, 0xe47853ef, 0xa2957cac, - 0xe740b3ca, 0xe3cea251, 0x7082d266, 0x4ca9f769, 0x7251f153, 0x39abfa88, - 0x54c84ed0, 0xeaa9878a, 0xdd532a7d, 0x6e22fbfa, 0x3efb1b1e, 0x9e9fad15, - 0x1bae37de, 0xa3f61ad7, 0xc879687e, 0xf94feec7, 0xc3f98fbd, 0x7ef007e3, - 0xb1dfd601, 0x09feec59, 0x21c3c317, 0x763af629, 0xf1eb9551, 0x9c0e48a6, - 0xe7bfdec7, 0x1e6eb8ef, 0xf7f7f3d8, 0x771c8ec1, 0x97902042, 0xa8c4fe3b, - 0x180fcc78, 0x695f232b, 0x6f3f7afd, 0x9cf611b4, 0xccdeff44, 0x728f0a41, - 0xc167c025, 0x8f5395f2, 0x9dfd0a3c, 0xe8902a3f, 0x92451f73, 0xe5c42067, - 0x1ddfd48b, 0x7b31c83a, 0xa83f6b4a, 0x11c7defe, 0x21216f95, 0xc567bb43, - 0xa9e7451c, 0x1a1ffdea, 0x2f1ea75d, 0x74e4213e, 0xfdfc0fa5, 0x5a10e233, - 0xaa9ce1fc, 0x9ff3490f, 0xf5ce7cf0, 0x600a778d, 0xc69f5fbf, 0xdc6a2513, - 0xe9ea641b, 0x4e21c547, 0x6ff60d3a, 0x4e8f33f3, 0xb7e5bc83, 0xf4814c78, - 0x99be7686, 0x3e16f503, 0x462abde6, 0xba1f5efc, 0x9955ef13, 0xa3e4cf1b, - 0x5fc7f1a7, 0x3864f94d, 0x3b309dd0, 0x4bdd8f30, 0x81efa462, 0x1491ff3d, - 0xbe3dda19, 0x91bfa3bb, 0x2a9caf0e, 0x9eac7dc0, 0xdbe461e8, 0xfe9e747d, - 0x5377e12b, 0xbf8fc42d, 0xfac2ea9b, 0xac34beab, 0xddeafc6b, 0xd81264fb, - 0x4e9f1a79, 0x337c6249, 0x49a3f76e, 0x2f49dec4, 0xc586de23, 0xc97ffe33, - 0xee25d9aa, 0xa3e8d359, 0x843ae977, 0x2d27ea8c, 0xaa563790, 0x70fb3ac2, - 0x4425da11, 0x5c62cf3d, 0xb7f366df, 0xda75014d, 0xccfeefd3, 0xf57acb94, - 0x6fc5397b, 0x0eb00bd5, 0x99ab0916, 0x78ed531e, 0x9d231e0d, 0x08a523df, - 0x19f0777f, 0xe708c0f9, 0xf6f91d4b, 0xda07ae0a, 0x18cce0ef, 0xc6262598, - 0x8f868798, 0xc7ae8499, 0x8f5fbdd9, 0xdbd78c6f, 0x178ee7ef, 0xdad011fe, - 0xe919bc9d, 0xf4d76c66, 0x900c1147, 0xec1fa58b, 0x29f1b993, 0x8ba2df48, - 0x3ae85112, 0xcfe9fa43, 0x2b9293f5, 0xb956df91, 0xf8eeb3d8, 0x4f22faad, - 0xf93b233c, 0xd87a6c4e, 0x5bb77c06, 0x1c41b7a8, 0xf4fb3af5, 0xc2bd103a, - 0xe2660bcf, 0x131115fd, 0x94dad081, 0x886699d0, 0x243f7833, 0x20a1be78, - 0xf0327fb4, 0x0b42abe9, 0xe76d59fa, 0xca387909, 0xd50a6cee, 0x6b2ec0d9, - 0xf3e7664a, 0x5d10260e, 0x78c5f4fe, 0x8e9a6fa6, 0xc4a69d9e, 0x62ee1f68, - 0x28833cfc, 0x9ff439c9, 0x7f29eb45, 0xc7dc1f80, 0x42927181, 0x325afdce, - 0x39732dd8, 0xf6da23f4, 0x992d798e, 0x7b7adbc2, 0x2999ea02, 0xe9ddf74d, - 0xfe0884a2, 0x6f3e2463, 0xfef0e32f, 0x8dd92284, 0x59c5a2f5, 0xf98df7e8, - 0x09466926, 0xa220dfb4, 0xaf8533df, 0x755e2014, 0xabc38d3a, 0x9170f63c, - 0x623df85a, 0x0e3674ff, 0xc093f971, 0x24a77d3f, 0x66fe0469, 0x07d5ac9e, - 0x122eefe1, 0xfab6ff83, 0xcdfb73a5, 0x2cf57db4, 0xa78df30e, 0x3f8832b8, - 0xd68a7f8a, 0x5baf384b, 0xc005a942, 0xf58a33d7, 0xaac31ee7, 0xd4ab393d, - 0xfbd10246, 0xe50b9cf9, 0xfdb5a0fa, 0xf11dfc56, 0xf98122bd, 0xa37e7269, - 0xe7b3efca, 0x9bbee924, 0xa9dd984e, 0xaa4dd5c9, 0xfaa8ddfc, 0x193d73cd, - 0x094bf1ba, 0x40fe87b3, 0x64810bda, 0x7ed8b8f7, 0x96f6b4f4, 0x25e1f3c3, - 0xd068dfbe, 0x310d3787, 0xe57cbdf8, 0x348be45a, 0xc8f78dce, 0x37edf5b8, - 0x8dd7d58f, 0x0fd46bf2, 0x8f8b20b3, 0x3427aaef, 0x2f6b307d, 0x683c422f, - 0x33c53e56, 0xbb7ac5da, 0x317d27bd, 0x7d1bae26, 0x17be4971, 0xfa2e90cc, - 0xefe2e3e2, 0x4b7e2fa5, 0x54b196dd, 0x578edfae, 0xa4fecdd7, 0x298de83f, - 0x81478efc, 0xbae8da8f, 0x47c18e69, 0xc5a3bada, 0x1ca88a01, 0xc5381ea3, - 0x5ca663f6, 0x91fe274c, 0x0e80719d, 0x12ed423d, 0xa97b0c77, 0xe51b3e35, - 0x68ef43ab, 0x2eca257a, 0xb87ef311, 0xda85325d, 0xc02e52a3, 0x2be10fd7, - 0x2925ef52, 0x882b8482, 0xc19da61f, 0xa0579038, 0xcfae2cfe, 0x817f224f, - 0x3b12e3fe, 0xaf68c3e5, 0x0ae87168, 0xe94f6697, 0x1e23a5f9, 0xc3dd9339, - 0x1149f1aa, 0x7fe413e0, 0x04fb8f26, 0x7fd41bff, 0x8000b303, 0x00008000, - 0x00088b1f, 0x00000000, 0x7cc5ff00, 0x55547809, 0xf579f096, 0x55492d5e, - 0x146caa92, 0xb612f08b, 0x84582484, 0x5916ec80, 0xa014a358, 0x8168cb80, - 0x9a126b0b, 0x69ee9c71, 0x0242a6ff, 0x83b74343, 0xe8cedad2, 0x3ad857f4, - 0x08b41a83, 0xd09d0301, 0x584c5015, 0xf82e0834, 0x1a6d1ad9, 0x84490ed1, - 0xbfbb46d6, 0x739cffcf, 0x2aaa4bef, 0xffff4d85, 0xb49fdf3f, 0xdeefb97d, - 0x67b9ef77, 0x979ee73f, 0xb3559bdb, 0xf6e008ad, 0x14078a99, 0x77f1d000, - 0xe042c022, 0xadacc37f, 0xc78ef016, 0x69fcd7be, 0xe7f80d87, 0x9c2ffc3b, - 0xa42cfc90, 0x900bcf50, 0xce54b009, 0x7d57fc5f, 0x3c5e3d33, 0x52fe7a27, - 0x92b9fd98, 0xf81b700c, 0xf71c30cd, 0xff8ec5f3, 0xc7154bec, 0x7e8b2e97, - 0x4a4ce99e, 0xff8790bf, 0xbe230118, 0xd4ca0153, 0x22b79dba, 0x5527ddbc, - 0x334c558f, 0x390ffed1, 0x350ffec5, 0x7c800c97, 0x1674df80, 0x3db1f8a7, - 0x1c2111b6, 0xd1bad00d, 0xec71edc6, 0xefc5f107, 0x3c66e7e8, 0x21fc059f, - 0x52b4b607, 0x4801b721, 0xc4ed1805, 0xff602745, 0x0d3f9e2a, 0xc02486c7, - 0x5c2473ef, 0xe7af00d9, 0xf104e798, 0x5eb8c3bd, 0xe30dd700, 0xf75c01fa, - 0xf72746c8, 0xe6e8db5f, 0x442e0dfe, 0xfac0066a, 0x37af2714, 0x8776f72f, - 0xe35bdf1f, 0x50e7e6cc, 0xf844da3e, 0x7b2fe036, 0x1004086a, 0xac77afdf, - 0x807494d0, 0xb1e2b72a, 0x01d1f566, 0x8e58e34f, 0xbe25cbf3, 0x102ab72b, - 0x1fe5e7c4, 0xc4072bae, 0xee33575f, 0x2aa9f887, 0xfc368355, 0x63d34967, - 0x0cdf453b, 0xdefa08d6, 0x33028e22, 0x86cd16b5, 0x28f02cfb, 0xf1f7151e, - 0x6ff78936, 0x1d412af5, 0x278b79ff, 0x63871e9a, 0xae58bee8, 0x0ffe80b3, - 0x47305bdf, 0x9d718609, 0xdfa29305, 0xd6757c5b, 0xfed8cae7, 0xe898b47c, - 0xbf3fb63e, 0xb7744edc, 0xc1863fe3, 0x95fba230, 0x8d6fa58b, 0xc5ba3e85, - 0x8e74b1b6, 0x9d16bf1d, 0x673a27ef, 0xc6ce9b5c, 0xce8b7ffb, 0x904e110f, - 0x1bf470be, 0x30049e8b, 0x1a07e9bb, 0x55f679d1, 0x32add78d, 0x861433ce, - 0xd4fe79d2, 0xb76ff859, 0xaafcdf42, 0xfe2d2fa6, 0xe79f6b82, 0x22bfed6f, - 0x69fde745, 0xdf7e6f5f, 0x8034f3be, 0xf9ce78c1, 0x8df8d139, 0xbd2c6ba5, - 0x62f7ca16, 0xe635b5e9, 0xa05d061c, 0x60689913, 0x555fbc1c, 0xd16b8e19, - 0x162e97ad, 0x7e4f08ff, 0x5f8071ff, 0xd6fab9f3, 0x76827493, 0xe02057cd, - 0x03c84732, 0x052075f2, 0x0ade5be9, 0xec0444e1, 0x3e738b96, 0x28f5a8d7, - 0x39c469f0, 0x8353e7e8, 0xfadf6ace, 0xb2075765, 0x96fb19fc, 0x14b01069, - 0x972173d2, 0xd255f0b1, 0x7e69233a, 0xcb68f980, 0x10b2d32e, 0x05ba639e, - 0x9b51f5ee, 0x4e03da28, 0x9d1a07a1, 0xfbb75e26, 0x6e099b2b, 0xf0e57804, - 0xf8406280, 0x09e7563c, 0x33218bd2, 0xc945fbf0, 0x9cdfcf3a, 0xdc048104, - 0x9b76b41f, 0x2b44f90f, 0x3941c806, 0x825906d3, 0x9d64b835, 0xdc91f616, - 0xa8347b75, 0xd1bbb946, 0xe048ef78, 0x6c92402e, 0xa99474fe, 0x0fde8b26, - 0x79c54fb7, 0xfa6a1537, 0xb2e29c36, 0xf1a03fea, 0x93ab66ae, 0xf83eebde, - 0x5a662dcf, 0x20f02be7, 0x335af084, 0x4f8e1532, 0xa4839873, 0x93d4ca37, - 0xddfb09aa, 0x8fa4003d, 0x970b2da6, 0x3a6dd200, 0xb138d7b4, 0x8c74429d, - 0xd0bfbf43, 0xde843379, 0x9a74881a, 0x4334e921, 0x6692abea, 0x4946f595, - 0xac841a92, 0xb374fd3e, 0x408cd1a4, 0xee0a497b, 0x3c53433b, 0xf9bfd835, - 0x8fc516aa, 0xba3e932f, 0x951f4fb1, 0x3dbdf5c9, 0x019686ba, 0xff344266, - 0x3d0a3596, 0x798b6254, 0xbe0fed2e, 0xe6557cc9, 0x429f1e8c, 0xfbf913ba, - 0x825e8c62, 0xa653fb18, 0x03b935fe, 0xc58af0f1, 0x8454defb, 0x19b4e7bb, - 0x70e7c59e, 0xfb933b11, 0xc631a7e3, 0x07b6c51e, 0x757a270f, 0xe215eb84, - 0x07f50723, 0xd7b1f579, 0xa3b63f9e, 0xf18e98a7, 0x0d22dd4a, 0xcf2d99b2, - 0xf0fb33ba, 0x92bf0fde, 0xad78b10e, 0xdbde7a97, 0x8e8d7ce8, 0xad8f0fdb, - 0x979ed8b3, 0x48d749fc, 0xf8bdfdf5, 0x95e5e434, 0xe25e890b, 0x0c2e57ff, - 0x4afdb2f2, 0x0c3e59d2, 0xfe783879, 0x51e92272, 0x21aea7c4, 0x6cb8f49f, - 0x9f99679e, 0x06841c85, 0xc36e0a8e, 0xc12485fe, 0xf624aff7, 0xbc23cf1c, - 0x3cf262df, 0xeb68db4b, 0x202a2f87, 0xd175b9fd, 0xe2803379, 0x2887e505, - 0x84ee8a4f, 0xa00db1bb, 0x05ff113c, 0x72482152, 0xd0108662, 0x785e35be, - 0xd319da9a, 0xfbc214f4, 0xddb35c65, 0x29e9eb41, 0xd7f0f7c4, 0x057d132b, - 0xbf5ff1fd, 0xee1a7c11, 0xe6d1b0d3, 0x1c2f50d3, 0x7ee4e8d8, 0xb73746e3, - 0xdcea3687, 0xfc913a6e, 0xaa1ff243, 0x169f16bc, 0xa5e657a1, 0x0330fd0a, - 0x35c10ef5, 0x00609403, 0x23c66f79, 0x7288f2c0, 0x10a4dc10, 0x393cf0bd, - 0xfa44f87d, 0xe888ee5c, 0x3b56ad43, 0x82a59321, 0x67985ee9, 0x09d1f7e2, - 0xd59f3e08, 0x3fd23e7f, 0xfc8cbfaa, 0xefc38416, 0xb0b996f2, 0xb37c390d, - 0x7adf885d, 0x4bd1e965, 0xf4b9fdc0, 0x43b95ebc, 0x8feb84bd, 0x1f84cf0f, - 0x8f18bda2, 0xe2bc2184, 0xff045dcf, 0x100b1684, 0xb2b0d07d, 0xf21a167c, - 0x5ca2b5f9, 0x8448fdc0, 0xef8c1bbe, 0xc4c3cb59, 0x23a0074f, 0x645ef08d, - 0x7e49d9f3, 0x3f04b997, 0xdddb9578, 0x3937ae0a, 0x0951e2c3, 0xf1bee1b4, - 0x2d7f11eb, 0xce21b819, 0x1cc9696f, 0xb713e7a2, 0xc93ef1bd, 0x08e6d7b7, - 0xcc986cab, 0xf6111d9d, 0xe33c007c, 0x74927f24, 0x476877dc, 0x0e4e3f5a, - 0x6abb9eb0, 0x6b5e9209, 0x09ec933d, 0xafd33ee3, 0xacbfd8da, 0x6e5117a7, - 0x8f26270f, 0x42133d65, 0x63f2430d, 0x6d98e713, 0x3c23aff6, 0x7a3e65a0, - 0xedfbdf0a, 0xafd20065, 0x543fdbd3, 0x312d0fc9, 0x40e80ee5, 0xa32a8f38, - 0xf27da853, 0x6e7ce4e3, 0x127724cf, 0xec9b0e7e, 0xcefbed3a, 0x0474bd46, - 0x8da9cbf2, 0xf9023a50, 0x368dade3, 0x746f4f6e, 0xa3667b72, 0x38a3db9b, - 0x3af3fc4e, 0xbd7f138e, 0x6fd4e381, 0x4f6a71c3, 0x7ad43ae0, 0x489872df, - 0xe5bc677e, 0xbc2da8d0, 0xfadb892b, 0x742c933b, 0x50c9c38e, 0xfc4fec67, - 0x370c4e14, 0x2ee50780, 0xdb53fdd5, 0xad3f680d, 0x1c6502fe, 0xf754d4c0, - 0xae3a6d5c, 0x8fe87b3b, 0x19f1c2be, 0x6a7ec3a9, 0x3b6f7843, 0x893868e3, - 0xf5c7d2fd, 0x3f883a9f, 0x92a2244f, 0xb7643c24, 0xc7365179, 0xc418d293, - 0x24c2f768, 0xfd19a7ec, 0xc8a5b9ec, 0x3a4a4b0a, 0xb005c0f2, 0x73e1b1f3, - 0x25df886d, 0x513fff76, 0x9b6812df, 0xfa9d3a53, 0xbc927010, 0xcb20e62b, - 0x7d2510fb, 0xadbfda11, 0xd4c4ff0e, 0xabc07f08, 0xf48d21fc, 0x02af44c3, - 0x77a674ae, 0xf7d2a470, 0xd5b798dc, 0x15313651, 0x2ed7f7f9, 0xc269f995, - 0x741bc534, 0x635f97f4, 0x7af384de, 0xe26fd129, 0xd4b559c5, 0xe2e3982e, - 0x4dd96fbe, 0xa5ff24b5, 0x5fbd6b8e, 0x5c87efc2, 0xc547d666, 0x638bce1a, - 0xe3798d17, 0xffc8c991, 0x0c4b69ee, 0x7d7c4b3e, 0x84935fd6, 0x567732fd, - 0x34752aa1, 0x6bb5df70, 0xbf978d1b, 0xe572c0de, 0x59e8f249, 0xa5ed8ac4, - 0xd33e3869, 0x24c278a1, 0xa93ed32a, 0xa771a34d, 0xcdb421e2, 0x553b8ef4, - 0x5423e344, 0x9fea4ccf, 0xd89d4bd5, 0x4e66d19e, 0x66f384bd, 0x6c78a4e7, - 0xf099def8, 0xff10ae8f, 0xf249ccce, 0x1714e824, 0xa4ae9f04, 0xa9eac7be, - 0x8f1ce9d6, 0x3ad32495, 0x6131e2ba, 0x92d6febf, 0x147045ff, 0x514052fb, - 0x91a5dc68, 0xc7e4fb1f, 0xe275293f, 0x0aa1fabc, 0x099cfc90, 0xe091fee7, - 0xa89ad99f, 0xf5402027, 0xbd296716, 0x9c516f57, 0x2befb89b, 0x5181f9a1, - 0x5c79fd66, 0x769de4f7, 0x6fe507b6, 0x745fb3e5, 0x6cc1cef2, 0x9adfca17, - 0x49ed4c56, 0xcbdbf093, 0xc39f2adf, 0x930826e3, 0xebbf2952, 0x1dbdf81f, - 0x4d293f25, 0x0c4ff5c7, 0x416eb173, 0x116a953a, 0x83e70d7a, 0x55dfef42, - 0x945bf3c1, 0x8f3a3f01, 0xa7e4aff3, 0xff715a14, 0x5109e959, 0x710ce7f3, - 0x8de7f545, 0x45aa5818, 0xfcf2b1d8, 0xadfea8ac, 0x88e94a45, 0x69bef988, - 0x45fd5109, 0x11d2aea5, 0x2b6ff311, 0x5fd5181f, 0x54565b72, 0xb269a67f, - 0xa11b1fd0, 0x7dc854bc, 0x9bfb2979, 0x0a87acd9, 0x1bee629d, 0x8e3f7e38, - 0x7f09b617, 0xfe85d0aa, 0xb4a5d214, 0x80fd88ad, 0xc68f7c36, 0x8f52ec8b, - 0x3ddda005, 0xfc80ec91, 0xf62fe209, 0x6677658b, 0x6305fa3b, 0xb768ae89, - 0x752fe023, 0xfaf1db44, 0xcc27e144, 0x0bad7f01, 0x75a739e9, 0x6557fb1e, - 0x6145d5e9, 0xbf467c20, 0x2a370b1f, 0x13779dd1, 0xac6ab61f, 0x890ce737, - 0xd4adafd9, 0xf48c7ec1, 0xb7c8e6ef, 0xe0217d8c, 0xc6ff276d, 0xffb18738, - 0x4733ceb5, 0xe17ec69d, 0xacd73adf, 0xa9a5859c, 0xcf5fe171, 0x9c2c4cfe, - 0x4f32a979, 0xfb15fe81, 0xeca9ad85, 0x7a4fe22f, 0xf0c13f3c, 0xcf51ca7f, - 0x9cf522b9, 0x585f4943, 0x673d6d70, 0xff2d7bac, 0x78d758cf, 0xde54ea1f, - 0xf7bf78df, 0x7fc4aeb9, 0x27e71bbe, 0xae9e79c5, 0x5cfe7fc4, 0x9a19fcf4, - 0x7940e35e, 0x278a0e3e, 0xa93f7840, 0x959ae46b, 0x52d6f59c, 0x5fa1f65b, - 0xf670b723, 0xb52d40f9, 0x27833b53, 0xb9fe78ad, 0xf94eaa39, 0xea2fc307, - 0x0aa56717, 0x55f8e47f, 0x78e3aedd, 0x53b7407d, 0x88ff51dc, 0xaaf8a76e, - 0x28730bde, 0x370ef48e, 0xc438a7ad, 0xf62d879b, 0xfa154def, 0xdf7c857e, - 0xfea90f68, 0x857f0415, 0xf251e3ad, 0xe9bf2a49, 0x1c5f10b1, 0xbf2f7f27, - 0x5c77bfbf, 0xbf683a0b, 0x1d048fe3, 0x7e7d08be, 0x22defebd, 0xe20ca662, - 0xa917c553, 0x096c4a4f, 0x51fd48be, 0xf54574e6, 0x83ff93c7, 0x0f76cdef, - 0xae6f7a8c, 0x0f35159e, 0xf21cd8fd, 0x902c6a87, 0x353e91a3, 0xcfc87a25, - 0xefe3c58b, 0x0e3df9e5, 0x6051b927, 0x7f55d74e, 0x29e4fb1c, 0x7d8bf811, - 0xc4553dbe, 0x9ec88373, 0x52273ae3, 0x556b6e75, 0xd0e6709f, 0x887e267f, - 0xbaac63ed, 0x95c3d68c, 0x1e77c4dd, 0xba0ae9bb, 0xe3d2f0e0, 0x686ae7f3, - 0x4de33dff, 0xfb1c38ff, 0x215f1ec7, 0xfb4d53fa, 0xfadfb1b2, 0x7fa27df8, - 0xd9bc69a3, 0xb819ec83, 0xf9296e7f, 0x7fbee90b, 0x9b75fa27, 0xd4155b1d, - 0xa8099503, 0x4cd5b0d7, 0xf7a6140a, 0x2ddbc7c5, 0xc0915f68, 0x175e6cc8, - 0x156ec0d2, 0xc26574f1, 0x13d920d0, 0x13abd8ad, 0x0c132ade, 0x9264777a, - 0x09da879d, 0xdd9d7151, 0xfbe1ef82, 0x0bff3665, 0xc9c26f82, 0x87a5ea3a, - 0x200d960e, 0xea9138fe, 0xede43c64, 0x7d26ea9b, 0x21edf085, 0x01fffefb, - 0xf078e6be, 0x3ec59ad5, 0x2579f59d, 0x86f38f64, 0x3e947921, 0x3a6a15fa, - 0x21084f3f, 0xeebfb0ef, 0xb1fe5375, 0x90f165c6, 0xf2427eff, 0x35b6f5ef, - 0xdaa18f32, 0x29a91f05, 0xb17bf5a6, 0xcff25b7d, 0x6a2fb919, 0x910ba1be, - 0x33d9c03f, 0xe8815174, 0x6aa87f13, 0xe1f90f61, 0xe490ff3d, 0x83f9f8a1, - 0x183f8144, 0x8fd1f3d2, 0x777bf9f1, 0xf1b679e7, 0x65a78173, 0x0e9aecc1, - 0x06b38fec, 0xe3fca06f, 0x47ff34a1, 0xad3b8784, 0x87cc91c1, 0xb449f58e, - 0x8e05e28f, 0x0ff88c53, 0x32dd3ce3, 0x705c7fbc, 0x46c1fded, 0x64e96576, - 0x7f637781, 0xe88db1c4, 0xf124def1, 0xe10780dc, 0x303e26e8, 0x0785eae0, - 0x8f393886, 0xd4ff2200, 0x2e8be325, 0xa7ec8f5a, 0xdc7910ea, 0xff38983f, - 0x8ac24552, 0x4de77dfd, 0x791a0f1c, 0xfb1022e0, 0x49b53e4d, 0xf803e065, - 0x96a2513b, 0xcb5c695e, 0x7684fdf1, 0xf6fe262d, 0x2a9d3db2, 0xd5a9bfdf, - 0xf6a0e25f, 0x5379e8fd, 0x093f1c65, 0x59c52a82, 0xc6623b93, 0x467fe71b, - 0x18bd4feb, 0x4d293cfd, 0x3041c3da, 0xb24f3228, 0x974dc641, 0x10a7664f, - 0x2b186b1f, 0x8b0f48a8, 0xd4a4c2ae, 0xb0d33d3e, 0x4959e711, 0x2db8da9f, - 0x8fbceb38, 0x88dc69f6, 0xf49a3f0c, 0x435b9baa, 0xc2ce0aee, 0x623630bd, - 0x0617291f, 0x2fbf2f1e, 0x23ae38f0, 0xb0d397e7, 0x43356e6f, 0xc3c3ef50, - 0x0c2f8914, 0xbbfe38df, 0xf6c1d17c, 0x62db626b, 0xead9e495, 0x711e8136, - 0x113d04be, 0x6c7d08f4, 0xea8d49cf, 0xb59e92ab, 0xca7ed109, 0x924fb978, - 0x7ad45067, 0xd062bf86, 0xacea50f3, 0xc663f256, 0xdfb1563b, 0x3b293292, - 0x93a2fd6a, 0x042ef8d1, 0x63e2979f, 0x71c087cf, 0x5ab3c4c0, 0x29327f94, - 0x63f983bc, 0xcfd187d2, 0xee8f9ca7, 0xfcc9a697, 0xaedd2c56, 0xfb184f85, - 0x7fe969cb, 0xde5d3e3f, 0xcda67c68, 0x8667c689, 0x039f1a2f, 0x6be34596, - 0x1f1a3fa0, 0x898d5783, 0x7d61bf1a, 0xd87f5461, 0xcd44a70f, 0x198342cf, - 0x75be1fd9, 0x91fcd45e, 0xf545163b, 0x67753f47, 0xe0dcfcd4, 0xbcf1a88a, - 0x2efe6bdd, 0x368417fa, 0x3427cd44, 0xfe87be9b, 0x4bfe3637, 0x53ff7ed4, - 0xa18daff4, 0xe7d256ff, 0xa85e8813, 0xecfb0b37, 0xa425b919, 0x6f4d5d3f, - 0x9b79437c, 0xf9ceb140, 0xf03cc0aa, 0x2fd8e0d4, 0x7a429f54, 0xdaa2306e, - 0xd6a37a84, 0x1ec8ab04, 0x71326a3c, 0xf390d31e, 0x3f84d317, 0xc89a62f2, - 0x7b78197b, 0xd922ed1a, 0x43ea5541, 0x248efa73, 0x935453f2, 0xfec9da09, - 0x1fd61e69, 0xbe101ce7, 0x0755f719, 0x4ac5e701, 0x982d2792, 0xbea8fc88, - 0xa9fc72a9, 0x8e83f20e, 0xe4e6a4f6, 0x9f8453ce, 0x4e9b0e2b, 0xfaa6ab7c, - 0xf0df6403, 0xa1e7a19c, 0xdef39fbf, 0xf1495846, 0xe65fd196, 0xe699bf5e, - 0xe67bbb2f, 0x7b7f8a48, 0xacaddf9f, 0x43a08d2c, 0xc51739e4, 0xa40eabf1, - 0xd867fb09, 0xdc7ec313, 0x3a6bd569, 0x538c3ed0, 0xbb407d85, 0xf10d2071, - 0x88f281f1, 0x0169f859, 0xed1f9d33, 0xb827df2a, 0x80df21d0, 0xdd9f4a6d, - 0xe643bfd2, 0xda3b20fa, 0x00937d6f, 0xf74438a3, 0x1de33df0, 0x955dfe86, - 0xecbbf8cb, 0xf97f9e88, 0xaf02e1fe, 0x90f620f7, 0xe22ce70e, 0x17fc063c, - 0x42fe5ea5, 0xd24ee5ea, 0xebf911c7, 0x2676bb55, 0x2e7e7f91, 0xc6e3f847, - 0x3a49dff3, 0xe54d2eff, 0x9dddaff3, 0x047cfeb0, 0xae422ade, 0xe3557ea8, - 0xf991f5c0, 0x39c6b5cd, 0xe7468afc, 0xa8e52758, 0xf923b5a2, 0xfe7f604e, - 0xb75c34c3, 0x7b95d772, 0xa6fbd00e, 0x67614c9e, 0xd2dfbc03, 0x82e380f7, - 0x28817fa5, 0xcd33b6bf, 0xa67570cc, 0x09613889, 0xbbe44e36, 0xb803e825, - 0xda637da8, 0x7c3fe22c, 0xbfb0561e, 0xa4cc15a0, 0xb3fa16bf, 0x33f484cc, - 0x3f6779e0, 0x69cfed1e, 0x1b73ef3a, 0xfb7ef8f8, 0x922a7bdd, 0xd6340fd8, - 0x8141d633, 0x3def3f20, 0x499cc057, 0x0ae99f79, 0x9fb817fb, 0xeefb9e8d, - 0xec99bc1e, 0xbbdfb1b0, 0x0ef4bfe0, 0xf022c5f2, 0xfac6baf0, 0x1134d740, - 0x4b03f97a, 0x44ed1d2f, 0xa66d0dbf, 0x3685e530, 0xbdf2b39c, 0xcf75774a, - 0x9c230fcb, 0x66f9af1f, 0x7f7082bf, 0xbfe7bcb4, 0x3bf3e00e, 0x4741529e, - 0xfdd9f1be, 0xbc447a5a, 0x2bfeee79, 0xafe86f2c, 0x2924ff3c, 0x1eac97a5, - 0xd60f9392, 0x322a34bc, 0x9f4e485e, 0xf74e9099, 0xe2d2933b, 0xc6c46fde, - 0x3f886ba5, 0xf6757e59, 0x5cbe0d4b, 0xc372f92d, 0xf9f9a30b, 0xf3dea486, - 0x2af3fe88, 0x3436c1e7, 0xf1af395b, 0x3587e48e, 0x31337e2f, 0x8f57cf32, - 0xa95ba97c, 0xf74b7275, 0x09fa3aa6, 0x1e5e4efb, 0xeaab71cb, 0x1e73a2cf, - 0x3269fabe, 0xf9bdf7f5, 0x6e079f2d, 0xbbf83ebb, 0x78917911, 0x79ea4aae, - 0xc54af497, 0xf94eab01, 0xb90392ac, 0x7ec2ee27, 0x1fea2b65, 0x5725cf3c, - 0x29a7b1c7, 0x00a83b1e, 0xc32ab7e5, 0x2be4ac09, 0xe520941b, 0xee34d6c3, - 0xfb1832dd, 0x1616ea6b, 0x2556bb11, 0x59567d0b, 0xb13704af, 0xe9873e1f, - 0xa365285c, 0xbfee50e4, 0xd778e3e5, 0x85feb171, 0x3cf6b08d, 0xf55d9dc6, - 0x38205e5f, 0x395a35d6, 0x292176cf, 0xfb8c196c, 0x84abda5e, 0xdc9f7a02, - 0x1c44b976, 0x98f42ab6, 0xf55df685, 0xe411c2dc, 0x381d7636, 0xb93d216d, - 0x59b1e1aa, 0x309179f2, 0x8b9641ff, 0x9595bbb5, 0xd5ac7991, 0xa4420ee8, - 0x02f842fd, 0x40eafb13, 0x2cfa494e, 0x435e1a6b, 0xb6bd42e8, 0xf58569ff, - 0x97e242da, 0xf9ef0e0f, 0xdf686fdd, 0x923dff83, 0x7d745ff1, 0x805f07f8, - 0xb94a8bfd, 0x633c5c0f, 0xb2b2f8a1, 0xde217cc1, 0xba6352fd, 0xcfda1eef, - 0xfd638f88, 0x10162dee, 0x10d93ff7, 0x82ec9e7c, 0x1cb2c7a3, 0x9a57f9e1, - 0xce68f080, 0xec0acb1e, 0xc8ce48db, 0xc11db85e, 0xbef57178, 0x84f18d74, - 0x78fac4b1, 0x3921a0f7, 0x5877a25e, 0xe9579f28, 0x5f10b4ee, 0x173f8657, - 0x9f8dfff7, 0x89c6f2cc, 0x574e5fb7, 0x273f33a4, 0x6437de4a, 0x30b9618c, - 0x90c3daf7, 0x60bee58d, 0xa9d90f45, 0x3b91070d, 0xbfb7a214, 0xec0ee087, - 0x7ce9d04f, 0x9f3e0725, 0xcfb111d8, 0xf47ca51f, 0xf95e59e6, 0xf099ac64, - 0xb193efb9, 0xf3df525a, 0xaac74cae, 0x97997978, 0xdedd85d3, 0x18bbec9c, - 0x9e09072d, 0xd95bee30, 0x147be764, 0x2d2d8394, 0x70729145, 0xc45daac7, - 0x07aa4de7, 0x1b2a0225, 0x79abfa17, 0xc887927e, 0x0cce36a3, 0x4eaa1f10, - 0xfc27f31f, 0x289bf715, 0xff508fef, 0x3ff74dcd, 0x39ac724d, 0x1e646560, - 0xf1d4d2a4, 0xe88516ab, 0xa26bc3ba, 0xf5810afd, 0x75f0ea96, 0x94553c70, - 0x7bdc53a9, 0x202cc274, 0x59bcfd3c, 0x39afbce1, 0x8b35bfd5, 0xe55c7be8, - 0x2fa396f9, 0xbbbee804, 0x11141c6b, 0x7f79c67c, 0x2a0c2e3e, 0x00b9b3ae, - 0xe6edb43c, 0xc4dd4b83, 0x38cf3fbf, 0xdd867ec6, 0x2bd20213, 0x503fe835, - 0x1f9ec7de, 0x093ad30a, 0x1522be39, 0xee9359f7, 0x58b4be64, 0x27ca1efd, - 0x36fb203d, 0xe08ab7cd, 0x8a27a5b3, 0xf5c87bf8, 0x48baf9e5, 0x6f74cdfe, - 0x4b7ce7e9, 0x69f05997, 0x71c00dd7, 0x4cfcd722, 0xe32f21a6, 0xb83b06cd, - 0xd6546aad, 0x44d7da46, 0x79e8dbf0, 0x1ea5c1d7, 0x2d9cdf82, 0x91333df9, - 0xff7622e5, 0xa99f888f, 0x62b4c0ce, 0x99e1166b, 0x9ff7a6f0, 0x7be4a1f7, - 0xf9a01f03, 0x115e4873, 0xfcbc6f54, 0xf8bd3f92, 0x7375d12c, 0x95c72faa, - 0xc2bcd7cf, 0xc6277629, 0xff9c3b95, 0x31b7c901, 0x89f095bf, 0xfcd16fef, - 0x51efc236, 0xc5b35f89, 0xfe593ba7, 0xdfed3a7d, 0xf141be7b, 0x3c8df7cf, - 0xff6c96df, 0xcfef9ef7, 0x54e67cf2, 0x2f5a37e4, 0x399e7819, 0xfe201839, - 0xa2824dab, 0xa8f8f84d, 0xe49b966b, 0x6f91cb6e, 0xd7bc9286, 0x40dc7926, - 0x9be6b179, 0x6fdc9196, 0xf3277419, 0xe42f17ff, 0xfb11aa16, 0x7f17a724, - 0x2f3be745, 0xe2c5b1cf, 0x7c73a1cf, 0x9c69cf2c, 0xefba496b, 0xf911e92f, - 0x7e921826, 0xd7b3fc5d, 0x7194d7b8, 0x61da479e, 0x8f38f38c, 0x5c890dd8, - 0xfa57b67f, 0x98f81ae1, 0xd1e0ec7f, 0xc2f2bfd9, 0xa92baa09, 0x36c13169, - 0xb5253e3a, 0x92fdee22, 0x0c119355, 0xb2186d7a, 0x8d3435d3, 0x39d89f3b, - 0x3ee116af, 0xf8550108, 0x0cf9d169, 0x255e2af0, 0xdaf18f32, 0x63cbeb9a, - 0x21afe33c, 0x63cd8d79, 0x969b0e4c, 0x23ae525b, 0xbcdaf19f, 0xd18cf9b8, - 0x5171d119, 0xc0ce8641, 0x7f047285, 0x4189c286, 0xf1833791, 0x26eabf94, - 0x9fe3855b, 0xde5999e3, 0x9b1cae95, 0x13e0ed0b, 0x3adb6c4f, 0x8470e50d, - 0x6bf503c0, 0xf1f5c988, 0xe6f507ec, 0xc31b5e47, 0x3dea387e, 0x4e02f395, - 0x1d0c4b09, 0x137fd08b, 0x2a27a541, 0xf63e12bf, 0xdbf1326d, 0x2dfd549e, - 0x9b4f4fa2, 0x092875ca, 0x15c5875a, 0x900eee47, 0xe076807f, 0x3e84339f, - 0x7b8a35b7, 0x65ee9b4b, 0x74e0993d, 0xe423538e, 0xd8432f24, 0x1f638aa5, - 0x2ca0b50c, 0x4c9d325d, 0xd7f5c7ce, 0xa64fafed, 0x73dade34, 0xd2a44f6f, - 0xff353b9f, 0xff3c0c82, 0x51aeca17, 0xb75bf236, 0x7e12c706, 0xae6ce142, - 0x20d02ccf, 0x87f615a0, 0x3c29eaa7, 0x9504ba14, 0x5b71a54f, 0x257e34d0, - 0x58555ff1, 0x30f6979c, 0x6dcc8aa3, 0xd5dfb854, 0xeb4a9358, 0x79b6fd55, - 0x97afe910, 0xf39f8432, 0xf13cd5e2, 0xcd1a06be, 0x25c33fbf, 0xa2682a99, - 0x324be37c, 0x5575d94f, 0xfec679e5, 0x55338d05, 0x7e41f227, 0xce11c778, - 0x7559368b, 0x73c26fa2, 0x94d1f020, 0xd5687ec0, 0x7640d9e1, 0x1e05dbaf, - 0x24f7c705, 0xfc447cf6, 0xd56cd3d0, 0xc1373ee9, 0x715203b9, 0x1eb23dfd, - 0xb619172c, 0xdcf7d1de, 0xe9a12fd8, 0x24439497, 0xe57be0be, 0x4c076d04, - 0x3be24477, 0xc959d849, 0xc3127b57, 0xe967ba26, 0x59efdf41, 0x4e0fab86, - 0x380d7de0, 0xec0ed973, 0xf85cf4b1, 0xe5c33a71, 0x05c83e24, 0x8d342701, - 0x26af49d6, 0x8e7cbd38, 0x09eea704, 0xaae1fd28, 0x208e8b1a, 0xa4a3cfca, - 0xc9f4a6cc, 0x5f625577, 0xb0b286df, 0xfca41b27, 0x9d2b6eb7, 0x8547d916, - 0xfdefa933, 0xf8e278ff, 0x9c21dab6, 0x48a80bff, 0x49b63b7f, 0x214e74a9, - 0xde122857, 0x0781428c, 0xdbb40baa, 0x7cef78c4, 0x2a4773e4, 0xe79e7fdb, - 0xf3ed3ab1, 0xf85e58b2, 0x0ff0d17e, 0x17c2521f, 0x76d2466e, 0xc94be63e, - 0x9a7573c7, 0x875c3c8e, 0x3cb8fef3, 0xfd8c2a34, 0x79ffab16, 0x3f57cfe2, - 0x80bdb15c, 0xb31eeff4, 0x4ff49ca7, 0xf671e047, 0xeb345fcb, 0x0ee422db, - 0x7264f486, 0x3ecc61dd, 0x3d36e755, 0xf776fe4e, 0xfba74541, 0xcf736ef4, - 0xb2bb8250, 0xd50b33e9, 0xfc1d5663, 0xb2ebfd84, 0xda5eff4c, 0x3563526f, - 0x864dcfd7, 0x873f5c1d, 0x20eb917a, 0x4fa16e43, 0xf51d9f2e, 0x1d04756c, - 0x06f293de, 0x6461fe3d, 0xbca49abf, 0x1c38a61e, 0x772dfddb, 0xf7f5a70c, - 0xf180fccb, 0x191c355e, 0x04df784c, 0x3c6b71af, 0x5c6a0eef, 0xaef79cbf, - 0xc46f5eed, 0xfe52d3fc, 0x56fdcb4f, 0x20dffa67, 0x7cb6d778, 0xc2d2a16a, - 0xa1a1f3aa, 0x3486f714, 0x4719c53d, 0x6fcaf48f, 0x69553c8c, 0x5f9a163d, - 0xaf581175, 0x536bbd20, 0xbd2f7e90, 0x396638db, 0x348fdf3e, 0x8b3b2149, - 0xe3d92af1, 0x60df66fd, 0xcefd5f9a, 0x8f4963d7, 0xf020241d, 0xaf375f7f, - 0x4378461d, 0x244e2ffe, 0xac0bdb39, 0xcd390cd7, 0xf7c53927, 0x8bff89f3, - 0x7acb9fa8, 0x7da58f79, 0x7ee5cb1e, 0x225c9013, 0x203cb3ff, 0xdfc93bff, - 0x3ca277cb, 0x59a3fbf0, 0x9bb4f7ce, 0xa337ecbc, 0xfdc91f5e, 0xdfd4c5e2, - 0x64ea5ed3, 0x843aa739, 0xf0d79242, 0x04275e11, 0x45f2d740, 0xfd22f80a, - 0x648cbcff, 0xf1242f71, 0xd8433939, 0x9e8e5083, 0xd873c1e2, 0x3e4a3555, - 0xe8a5ec22, 0x9a5a7b4b, 0xbf6d97f9, 0x26524698, 0xda5384ed, 0xd678ff49, - 0x6d28fffb, 0xa7d786d5, 0x73c3a82c, 0xf2a5386e, 0xf71961f8, 0x1c9f2585, - 0xb21af991, 0xa89a7a1b, 0x13e7a61f, 0xe5f54fb0, 0x4bebbd13, 0x9a4d1cc8, - 0xb528e3b3, 0x12a17c53, 0x2da6db72, 0x166a3f6b, 0xfc479e62, 0x6e6470d7, - 0x75e3d51e, 0x0242b39f, 0x6df0d882, 0x222f47cf, 0x8c3e1e1e, 0xa7638ff8, - 0x7fcc38f0, 0x060d7fe8, 0x6ef1ff77, 0x4091ea45, 0xc7e27cd2, 0xafb506ae, - 0x2254808f, 0xfddf5363, 0x007b7da4, 0x677fe76d, 0x2267077a, 0xf00ccf3e, - 0xfa7ddb73, 0xcb124cdb, 0x5c4567fd, 0xe6f160df, 0x6434ff11, 0x871ba863, - 0x2299ad4f, 0x856453ef, 0x379cf7b8, 0x18390a67, 0x0aed8015, 0x33aaebc7, - 0xd4bf7488, 0xe82d7aa0, 0xc0845d2f, 0x6fa4a992, 0x01f75e64, 0xfc5e3f90, - 0x283cfa45, 0xdf900fbb, 0xc1eb7682, 0x11d6c45f, 0x316fd978, 0xeb0058f2, - 0x2b5fc44d, 0x0ff8149b, 0x67aac5c4, 0x93afe7a2, 0x1babf275, 0x8c1b1d77, - 0x5cf35d74, 0x2df938cc, 0xe211ff7c, 0x5d5d7878, 0xcdc33d74, 0x197fd299, - 0x7fc9c30e, 0x3d62be41, 0xd5a0d661, 0x60ac7c8a, 0xf6224314, 0x0be04992, - 0x67cb2bf5, 0x8a6f61be, 0xb9ea5e85, 0x94a75c04, 0x94743bbb, 0xd4a681ea, - 0x8f687965, 0x9f189a29, 0xee2598d2, 0x4aa0b4a7, 0xbc930c75, 0x77ec59fe, - 0xa967bc07, 0xd49564de, 0x5fc4e097, 0xd3c8fbca, 0xddfe92af, 0x9d6c60ea, - 0x9553c0a8, 0x8219379c, 0xcaefb435, 0x69dea2dd, 0xf9e8eeed, 0xeb4f1255, - 0x8c7d3a9e, 0xa11585d2, 0xa7897198, 0x3a98c6aa, 0xdc38b116, 0xadef299f, - 0xf5fb7d64, 0xd1fc5bd6, 0xb78dfc2c, 0xf8c63ae5, 0xef914ce6, 0x1063c4ad, - 0xd505d77d, 0x2ad1f120, 0xfc2c9025, 0xc72c705e, 0xb067ddf3, 0xbdcfac81, - 0x3ee9e25f, 0x7e7c3fc9, 0x19e2bf7c, 0xfdc57df1, 0x7f868b3f, 0x832cf80d, - 0x0d83f9f1, 0xde50b03f, 0x56df9631, 0xffd999d5, 0x13f1235d, 0x7a6b5fcb, - 0x858767f9, 0x7f2c5bec, 0x6b95fa55, 0xf6fc2fc0, 0x0df85bff, 0xcb91af3a, - 0x398735ac, 0x09f6b53f, 0xabf943c5, 0xf7ab9d6b, 0x7f7cf23c, 0x359eb9ef, - 0xc6063de8, 0xa4e7bd30, 0x63bd175d, 0x96bdedfd, 0xe726bcde, 0x66b72f05, - 0xe0dd3e73, 0x6675d8ab, 0xf67dbf49, 0xbd7fc253, 0x276258d4, 0xa4fba3ff, - 0x9ce8a3c9, 0xc02e4caf, 0x566f8ff3, 0xee91fc81, 0x033be1a6, 0xa9e17f08, - 0x5f94c5a2, 0xed0a7f1f, 0xb707dd13, 0x0257fd16, 0xd27b07df, 0xb667ee48, - 0xbdfb488d, 0xfb61d783, 0x70b27dde, 0xe9e93967, 0xb445a593, 0x54e382ae, - 0xed285e9f, 0x42c9f554, 0xbd84477b, 0xc8a64dfa, 0xff716fcf, 0x1b8a51fe, - 0x7b35ef66, 0xdb323f28, 0x8094dfec, 0xa0be15f0, 0xb771aa78, 0x9e47ed63, - 0xbe5175a4, 0xf38acd28, 0x8d08e9fe, 0x1851ed57, 0xb2a6eefe, 0x3f643dbc, - 0xec87aa83, 0x7dd37762, 0x1f920ff9, 0xfe40fcd4, 0x1dfb117d, 0x66fa154b, - 0xb6660df6, 0xec839dd7, 0xbca72ebf, 0xeb1777a8, 0xfb43ce8d, 0xc37dfc2c, - 0x78dc051e, 0xa3ee63ce, 0x3a1e132f, 0x50b69c0f, 0x70d25010, 0x4711d2da, - 0x25ed1b7f, 0x9cc2f30c, 0xe161ddaf, 0x7ffdcdfa, 0x2b79d0b0, 0xf384fb9f, - 0x7e286b6f, 0x19ef3f20, 0x3a77bf95, 0x85aafcda, 0x4eb2b4f8, 0x91590181, - 0x271e66e3, 0xcffd4afd, 0x369e84ea, 0xe4857ff8, 0x0dff8377, 0xf5215879, - 0xe35b7dda, 0xffa1bbf3, 0x96ef041e, 0x03deb841, 0x0eb9cb75, 0xd11d81e9, - 0xfc5257f3, 0x17cd237a, 0xa9f2befc, 0xbdd5f1e8, 0xfd601e7c, 0xbf47ab1f, - 0x2e7ff433, 0x5f9f12e4, 0xa618af0e, 0x7d7d3ca1, 0x8830cd7a, 0x293caf93, - 0x6ec306fd, 0xd89b0e5f, 0xebcec5ee, 0x2162bc6a, 0xfad55b7b, 0x6773f627, - 0xf4c97d35, 0xe16a6f28, 0xc05bd97a, 0x79f08ebf, 0x49dd934b, 0x877976fe, - 0x9af303d0, 0x42a0c1ac, 0xa25aa1e3, 0xf161f773, 0x90e049bd, 0x4816fec2, - 0xe252b8bd, 0xe3c4a575, 0x06e38c4a, 0x8c8c7d53, 0xbc652be3, 0xd7673abe, - 0xa9292a31, 0xdaebe394, 0x1e13268e, 0x5bd081e7, 0x6f4242f3, 0xec31f419, - 0x40beac50, 0xd10f770b, 0x95936d77, 0x4be7d6eb, 0x0ebf35bd, 0x5fd296f5, - 0xb40f747f, 0x7ef1fc8b, 0xddac7701, 0x9e886cad, 0xfc201aef, 0x7fd2cbd8, - 0x4d101c2e, 0xb01ef297, 0x9e7f7e53, 0xfc827aae, 0xfb46bb56, 0x7e458eb7, - 0xf55bf5c3, 0xeaf129e1, 0x4df68cb5, 0xfd181719, 0xc3679405, 0x0ee721f9, - 0xffdc6447, 0x7f84039f, 0x1ab266b3, 0xc446ba20, 0xb30a0b49, 0x7349c6e2, - 0x8637f409, 0x71b3f7dc, 0x77927191, 0xb7e228d7, 0x2cef757f, 0xaaa6baa7, - 0xba2fa13a, 0x29bae126, 0xfb03f7e4, 0xd67555d1, 0x5533c520, 0x7dfc2fc8, - 0xc909f11a, 0x46529363, 0xc671827c, 0x42feb4ed, 0xf3c4eaba, 0xfb446c2f, - 0x2c2fcb8e, 0xabf992fd, 0x3738846d, 0xbc406de2, 0x3788c3b8, 0xbf0aaf2a, - 0xa95e78d6, 0x51dc7075, 0xb5ea24d9, 0x337c8e1b, 0xede10b34, 0xd0f3fe6e, - 0x3e4f54e5, 0x86e7d840, 0x54a7d0e2, 0x1ef5f457, 0xb5ff5c5b, 0xb52bff57, - 0xe6950f2c, 0x6bf64c8e, 0x791fa20e, 0xb7d1ea13, 0xa538e0bf, 0xbdc248e1, - 0x5aebcf94, 0xfce61fe1, 0xc3553a1e, 0x3783f626, 0xe4b72d41, 0x8dfa451f, - 0x4ea29d2b, 0x3f6941e9, 0xf208ffa9, 0x773883f5, 0xf97f6146, 0x8549f437, - 0x10d5ebe4, 0xe95532d8, 0xa42a07af, 0xdfcdacdc, 0xf6ae85b5, 0x0aa7fd63, - 0x31184f29, 0xf58cbdb0, 0x8633fe9f, 0x4edfab5f, 0xbbb8ff64, 0xae52754d, - 0xabfbf119, 0x6227e441, 0x271d905c, 0xe485fb5f, 0x7f794ecf, 0x65493d5c, - 0x8b2699fc, 0x10b7f0d6, 0xdd37cc8f, 0xb2411da7, 0x5f87796f, 0x583e26cd, - 0xdefa3bbb, 0xe7e8e889, 0xc8a0b1ba, 0x7cec8547, 0xbf8c6517, 0x31d5f874, - 0x6fd56fc4, 0xd04a3b7f, 0x96519be7, 0x67c36bf4, 0xe2228ab4, 0xe2229366, - 0x475afde6, 0x556bc532, 0x645f5507, 0xef41bf3d, 0x813ca597, 0xf503f226, - 0xabe67403, 0x1fc126ea, 0xe2d166a6, 0x7e444bfe, 0xf7fbccc8, 0xbe462f1b, - 0x067b1ef9, 0x40f21704, 0xf987b995, 0x89b4eaaf, 0x7d3aa9e1, 0xc4447339, - 0x775a017b, 0xeabfe900, 0xc4fac075, 0xe76fa40e, 0xd891f7d3, 0x027eff9f, - 0xb2c761fb, 0xfb8b97b7, 0x7f48152f, 0x9af6fc3d, 0x60f691d1, 0x2f7100e2, - 0x3707840e, 0x10bf3f79, 0x6c3c4bfb, 0xbf324582, 0xaf79f820, 0x2e309b8c, - 0x9c40737b, 0xfd7aecb8, 0x2b66eae9, 0xeab9fe50, 0x19d72b03, 0x92bcdd7d, - 0xeab87ee3, 0x06fa4d1f, 0xa91bfefc, 0xcaf0f87d, 0xebfcf4d1, 0xe46fabc3, - 0x29b2a97c, 0x2011cf2a, 0x5fe4dcf8, 0x5deef57d, 0x69b67fe4, 0xb6149fec, - 0xee977d9d, 0x9835f769, 0x8ad1dbf9, 0x067613fd, 0x2aafc892, 0x11df4f9c, - 0x98d56bed, 0x32dfd0ff, 0xfb3b2bfc, 0xd88aa757, 0x7c75c2bf, 0x4e8b6e41, - 0xa7bad394, 0x9a688b8a, 0xd7a4e382, 0xe57f93c6, 0x0cb7f3e8, 0xf8933e78, - 0xe0496eec, 0xd9028bbc, 0x4460cf82, 0x1aebdc14, 0x64ff675e, 0xf51aa35d, - 0xdef188fd, 0x7b88065f, 0x3e0cef87, 0xe65e290b, 0x5da2bda3, 0x932fb8d7, - 0x1cd6b1ce, 0xaea93e62, 0x3df18b33, 0x07ba05a2, 0x411fc09a, 0x273f0807, - 0x65d211e8, 0x8438259e, 0xbdbdfafc, 0x2eb28af7, 0xf5ea2824, 0xf3875a6a, - 0x5b974c77, 0xb3c7a5f7, 0x9ee92743, 0xe3be1d07, 0x8a1e2259, 0x5badff1d, - 0x9f8e41e4, 0xf8f1fa13, 0x78e8ff4c, 0xc500327a, 0x48a05f22, 0xef8835fa, - 0x35e763ed, 0xfe787ad3, 0xc70243dd, 0xf73b8f89, 0x63fdf026, 0x75e44ba7, - 0x34dbea4b, 0x6d661efa, 0xec813283, 0xf79cdad2, 0xec197bf8, 0x5c9e9117, - 0xf7c83e1b, 0x7b7515af, 0xc0e37967, 0xec2dddb1, 0x9df93cc3, 0x7cf8ec72, - 0x3c067e39, 0xdb9e3219, 0x673ef74e, 0xf14ecdca, 0xeef89bdd, 0xd7a956f5, - 0x6662df17, 0xe80cea3f, 0x227f7166, 0x481639ee, 0xd4ab7dbd, 0x63dfb1f7, - 0x76fdfa1b, 0x67c2ceb9, 0x73dd3360, 0x7d9f7ec4, 0x170ff4bb, 0xefd79781, - 0xf4bd5df7, 0xfeff6313, 0xea5b8942, 0x8a3051f5, 0xed087af4, 0xe45bd70d, - 0x9eddb026, 0xae32305f, 0xa9df41df, 0x753bf2eb, 0x57fa0d6a, 0xf6c7bee7, - 0xb9cb78f0, 0x86fbf997, 0x1d900973, 0xcfad9ee7, 0xe47a1a1e, 0x79774136, - 0x14e151ef, 0xbff41a30, 0x645a1184, 0xffa0cd7e, 0xff0e9283, 0x394575c7, - 0x63e645a0, 0x07fea90e, 0x475419dd, 0x38fec9dd, 0x21ed809e, 0x3ca86b9e, - 0x846b50d7, 0x7034bb9d, 0xee3e5c79, 0x406a5f3b, 0x6e7493d8, 0xecad725b, - 0x14845637, 0x22b0eefe, 0x9b7fa20c, 0x51caf9c2, 0xbf5c2d0d, 0xf154a4b1, - 0x3c5a8578, 0x7c19f04b, 0xfc26c0b4, 0x7a5f8303, 0x88f925f1, 0xb85fc9c6, - 0xb10bfa55, 0xda1a34fc, 0x4bfad167, 0xea878abd, 0x47c9af36, 0x4ebdc6cb, - 0xf8b5eee1, 0x4cd2f908, 0x9f96317a, 0x1ffb735e, 0xb775fc25, 0x80525e5f, - 0xfdcf1feb, 0x4ff1286c, 0xe8e435e5, 0xddbf4945, 0xae71c08e, 0x7597a963, - 0x8db9f504, 0x5697841d, 0xd3b2bf60, 0x8365bed5, 0x8eb9b7f0, 0xc09c22a0, - 0x4d15a5f5, 0xad6efe76, 0x713aa1a2, 0x26e3e90c, 0x7ec763d5, 0x52e9c379, - 0x179423ca, 0x2a973a89, 0xabbba8bb, 0xbbba8bb2, 0xe7fee9b9, 0xeff813dc, - 0x11d74403, 0xb57e3a58, 0x3ef87be1, 0x9335df56, 0x7fe1370f, 0x4b350f4e, - 0xbb686cfc, 0xc4863992, 0x887fdd34, 0xfd7eeee0, 0x8a7d0b45, 0xd5e63551, - 0xd6825459, 0xde79d6ec, 0xb52d752d, 0xe0365694, 0x429dbbb7, 0x43839aef, - 0xbfcd6fd8, 0xea9b7abe, 0x258c6f83, 0xd2d5d5fb, 0xc112d636, 0x501b9def, - 0x63a1c76f, 0x1ca49835, 0xca2adc6b, 0x0947e922, 0x3e6aaeb9, 0x8bf9499a, - 0x7ce7924e, 0x1e49df6a, 0xdec56d81, 0xc923c933, 0x5a2fd99f, 0x4d4bbd63, - 0xad03cf2a, 0x49edd463, 0x666df091, 0xc4852ef8, 0xa31d003a, 0x8e441716, - 0xd6bffcd7, 0x3e851707, 0x07d288e8, 0x16429e06, 0x0388efe0, 0xa75cad87, - 0xae3ff740, 0x036a3a08, 0xc26efd05, 0x76e48a60, 0x0f7bdd32, 0x834f9727, - 0x41afa9bb, 0xfba54b58, 0xea2ab0e9, 0xbeb086fb, 0xbff7289f, 0x50b70b49, - 0x7964f03d, 0xda053a5f, 0xe80cde79, 0x4e0bd6e1, 0x18ba0efe, 0xb24edc3c, - 0x5a53e785, 0xe2143f2b, 0x99c27bef, 0x4d82eb9a, 0x871d6f7e, 0xd3787dde, - 0x0f8182e0, 0x44d5ee95, 0x79ec533d, 0xfc28186e, 0x42bc9bbc, 0x414b910f, - 0x2093c0f5, 0xd3f9f7c4, 0xebde43a1, 0x54c73fc7, 0x1ee90b8c, 0x31ba3a6f, - 0x208f8c89, 0xe7469fcf, 0xa79de351, 0x19933e63, 0x9f049d4a, 0x7d34ce12, - 0x73febf67, 0x28355374, 0xebefbde5, 0x5171fae9, 0xa7a83ddf, 0xa9f78de9, - 0x7af1597e, 0x43d9beb9, 0xfc538ddf, 0x7b3ad613, 0xc03659f5, 0x722b8198, - 0xfbe84e06, 0xc0fc046e, 0xdfb12475, 0x277c448d, 0xfe231702, 0xe751922e, - 0x48b83bbb, 0x65913aa7, 0x7bfe36e9, 0xa1b6853b, 0x79af29e3, 0x339fcd28, - 0x7dea8330, 0x62f246eb, 0xfb02705a, 0xecbf92b9, 0x78449de0, 0xf7c6bc50, - 0xd37cc02b, 0x320bf7fb, 0xb227bf81, 0x3e77c55b, 0x6d1f91db, 0x3a052ca9, - 0x23c35fd5, 0xd3f93a25, 0x0f365c5b, 0x256c477d, 0x707dedb8, 0x1d44d8d7, - 0xd44d8d48, 0x72f51879, 0xb1ad78b1, 0x8f4e7919, 0x98f1fd8d, 0x627e90ef, - 0x7842dff3, 0x98a9287a, 0xde530eff, 0x5cdcd32b, 0x7fbf250f, 0xf03049aa, - 0xe7e36c50, 0xec94f57d, 0x3d52d667, 0x9359c237, 0x78ff5c01, 0x0a546934, - 0xb4d565d5, 0x9aee7a89, 0x77eb008c, 0x7d615fb3, 0xd25ad35f, 0xb2e2f64a, - 0xdd75c2c3, 0x07512e35, 0xd080c81f, 0x3d347af3, 0xa0f419a6, 0x8f594bfb, - 0x5c65d064, 0x7bd0943a, 0x91dec2e3, 0xdb429384, 0xfdd037cb, 0x7470b8c2, - 0x69d2197d, 0xf7a9d135, 0xc9cd1e3b, 0x7d061ef5, 0xd9987190, 0x06ee929d, - 0xdfc69cbd, 0x516af023, 0xa0c08f7f, 0x4144f6e3, 0xe055332f, 0x7577e70c, - 0x4e96375a, 0x14e11bff, 0x4bb0bac1, 0x00004bb0 -}; - -static const u32 xsem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x93cbff00, 0x51f86065, 0xd2f9c08f, 0xbcde0c0c, - 0xc4b462a8, 0x0c0c5c0c, 0x0e5c4041, 0x7b401ac4, 0xdbe9016f, 0xcdce1c40, - 0xc40110c0, 0x1ff881fb, 0x6207ff10, 0x04d6200d, 0x79405fe2, 0x5b1ba845, - 0xda181898, 0x8803b880, 0x875880bb, 0x97418191, 0x93fb7891, 0xde181984, - 0x7af82389, 0xcd0c0c12, 0xfff3f452, 0x5631c360, 0x29efb5f4, 0x174e3ed0, - 0x19c73f04, 0x505c2498, 0xe0bb70d5, 0x4d078337, 0xcf8d179e, 0x9e7f4787, - 0x5cbf2a21, 0x4d3f950b, 0x23e18187, 0x2d0a9a92, 0xc7416efc, 0x0c0c468a, - 0xabc4464a, 0xca8c60df, 0xd081300f, 0xb1adf900, 0x0003a809, 0x00000000 -}; - -static const u32 xsem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd5547c09, 0xf37df0f5, 0x66499996, - 0x0d909326, 0x8a027108, 0x081380a8, 0xc3b44069, 0x8e22a222, 0x260dc55b, - 0x1037d902, 0xfdaff0fd, 0x2d361032, 0x4682d0d6, 0xa0c0748b, 0x0d0482c1, - 0x00e02418, 0xd52ff82e, 0x5b7bbfd8, 0x16c34a0c, 0x7e1b8092, 0xce7fe5b5, - 0xef25f7b9, 0x6d80264d, 0xfdfb5fbf, 0xe6f169bf, 0x5ddf7bbc, 0x3dcf76ce, - 0x14fbdcf7, 0xf89628db, 0xe0cec663, 0x2cabd20f, 0xdd51b18c, 0xa0db6ce9, - 0x74fa87a1, 0x6559ffe7, 0x4287ead3, 0x6ed0ab1e, 0x9cfdd61e, 0x7e5485b1, - 0x386b8c40, 0xf4d31cbb, 0x8f0e1b10, 0x9616c96d, 0x6e7dd8cc, 0x0901bf46, - 0x912974be, 0x5615ceb1, 0x780cbaf7, 0x085c7aae, 0x20c8f7df, 0xf7c25077, - 0x1652c93c, 0xbaa23fe4, 0xbecc01d7, 0x6cb3233f, 0xe0da66c6, 0xc3fc0f6f, - 0x7cbea07a, 0x63106cac, 0x059969ea, 0x77ea7fa0, 0x3403a512, 0x00efc336, - 0x6c2df978, 0xfeeed0dc, 0xecfd13b9, 0xe8b78073, 0x5b7e89f9, 0x097f90c0, - 0xecffa893, 0x5faa4afb, 0xf2f16f6f, 0x073e6c5b, 0x8d941636, 0x7f963bcf, - 0x8be7c2e9, 0x7aa16e9b, 0xd82c5318, 0xc8b772cf, 0x635cfc4f, 0xbbfaee96, - 0x76a214f1, 0x04d3d874, 0x3188feed, 0xb6bfb5e9, 0xd543c032, 0x0563d556, - 0xaad84cbc, 0x700c7f86, 0x84295ae9, 0x9d9765b0, 0xfb4bc031, 0x9d870e6a, - 0x9fcb0f9a, 0xaa1805a8, 0xff36b728, 0xdbc40afc, 0xa3ad9956, 0xf784fc66, - 0x3bc71b56, 0x9e70e46b, 0x6ba5839d, 0xf7c74f77, 0xccad1a0b, 0x6e95f50e, - 0x057a9fcf, 0x54fbf9c0, 0xd74a4586, 0x01fad02f, 0xea92185c, 0xcf18ee11, - 0x36e0fda8, 0xca1eb439, 0x939ab877, 0x1ff1836f, 0xcf31b4ab, 0x676fd0c5, - 0x80adf273, 0x96d0a287, 0xd15ef849, 0x2c8bc946, 0xfaeb6134, 0x7bc2fb37, - 0xaf241ba5, 0x5c52f015, 0x433ccb17, 0xc0ce1f78, 0x3906d6bf, 0x9fc863fc, - 0x1964e30b, 0x49ead748, 0x57f6c64c, 0x37671e68, 0x0e558e9e, 0x376b1e61, - 0xda01ba5c, 0x5ecaf781, 0xc438bc94, 0x200b0b32, 0xb76fb65f, 0x81d67b4f, - 0x0da05be3, 0x96b8e276, 0x3f2e586a, 0xeecdbb94, 0xd5adfec1, 0xd17e4126, - 0x9e5ab5ea, 0x75c5fe81, 0xcd8f3197, 0x419aafd0, 0x88fe4629, 0x9b018f4c, - 0xc453fb18, 0xf91eaf98, 0x37690944, 0x9fa2e419, 0x2ef44f14, 0xf54d93ae, - 0x4b192603, 0x007eff82, 0x82be027f, 0x57849d3b, 0x05736e9d, 0x3b74e91f, - 0x2987e425, 0xfac6d99d, 0x48e7f4f5, 0x754fe807, 0x5fd29ba5, 0xba52a654, - 0xf443d2b2, 0x07f10279, 0x6fd172e9, 0x4e3658d7, 0x3e5d7681, 0x4b3146e6, - 0xa71be298, 0xe7e09c02, 0x01ddf270, 0xf19673c9, 0x6a13e9eb, 0x72651720, - 0x53e49b15, 0x05ac02fa, 0xb42f30e6, 0x9be8dcaf, 0xd7b19a38, 0x1c71e059, - 0x502922ff, 0xac657480, 0x740fd53e, 0x1e812259, 0xc52d7c01, 0x961e0241, - 0x067e05f4, 0x4f713d3a, 0x24b2b3f6, 0x70889ac6, 0x668f73de, 0x54353d50, - 0x0cf50a8f, 0xc93d773a, 0xf54c73d3, 0xd02f4f24, 0xf54b59eb, 0x9eafcfd8, - 0x318fa627, 0x917a67f7, 0x580bcf5e, 0xfcf3916e, 0x633c95c6, 0x333fb9ac, - 0x949ea84a, 0x002cbdbb, 0x7f9d65e5, 0x864fb358, 0xf8c6c77c, 0x23328f11, - 0x86df8d1f, 0xaa4139f5, 0x97147c8c, 0xa7926313, 0x09825f78, 0x9fb933ee, - 0x7f927ca9, 0x653f29a0, 0x7c11a5da, 0x5eb770e9, 0x54e86026, 0xfea35e38, - 0xd234fd6a, 0xd9fae33b, 0x9fa07e08, 0x03cef483, 0xbb170263, 0x57d8dfa1, - 0x407ff406, 0x8eee5c0b, 0x2e3037c2, 0xea62a589, 0x991a60b1, 0x78e554bf, - 0xfbffdf1b, 0xfde107c1, 0xe0e74b72, 0x4bff8078, 0x8e21f71a, 0x4ca88ffb, - 0x32316e81, 0x3172c0ab, 0x6ffa4656, 0xb3f64669, 0x975e0341, 0x917e000d, - 0xa65debba, 0x1f915206, 0x4115825b, 0x3025cfe4, 0x8c7eb041, 0xe115641d, - 0xfef085e0, 0xc454bc80, 0xfd0355bf, 0x835f6c61, 0xfb5287f6, 0x5b7ed8ad, - 0x075bed2f, 0xb7da98e6, 0xda9817a5, 0x3ed069b7, 0x706747c8, 0xf01f68be, - 0x93b18637, 0x6fb53e6c, 0xf6a02f4d, 0xc0ac6a97, 0x574c7ed4, 0xbb60dffb, - 0x49fb63df, 0x703fc651, 0xe9fc798c, 0x6bf1e645, 0x416cfc7c, 0x431fb450, - 0x20a497e3, 0x117a7f1f, 0xd795bf1f, 0xabbed5db, 0x049aff0b, 0x5ea43aed, - 0xac683fc6, 0x9417fc79, 0xe56fc798, 0x2c17bbed, 0xa83bed13, 0x196978fd, - 0x2505ff1f, 0x0d66bed4, 0xb48f9178, 0x211531fe, 0x40d34f9c, 0x07485280, - 0x921d28fa, 0x93e818c0, 0x8481b2df, 0x38620787, 0x03137ddf, 0xd6e8e6fc, - 0x12042ca7, 0x9970f308, 0x8de2e9e0, 0x3f3e34e3, 0x9f5e6907, 0xab3aba2d, - 0x8cf9a651, 0x2e86b4ad, 0x37b6fe82, 0x678441ca, 0x2432bcad, 0x760a7cd3, - 0xb0a7be02, 0xf3ff3e30, 0x8ceb61aa, 0x674c8ae3, 0x2dadab57, 0xd2eab906, - 0x90d9e3ef, 0x055fe80a, 0x6ea8c132, 0x34f415b8, 0x39fc3d03, 0x0f4c63e8, - 0x392edcab, 0x5d9c7a04, 0x059b946c, 0xb2092edc, 0xff4087f7, 0xdffa227f, - 0xb77c70aa, 0x884293ce, 0xcc566fff, 0xcd9f50d1, 0xa4058eae, 0x5ca3f777, - 0xbb73a9d0, 0x14f64435, 0x9f88074c, 0x191449db, 0x1baed3fb, 0x305c94de, - 0x31f4d63f, 0x0b3777bd, 0xf2854e2d, 0x0ee79733, 0xeff8c370, 0x211d669a, - 0x7cc4fce3, 0xc7242dfd, 0x8725bfac, 0x2b0d69b1, 0xdc00fed4, 0xbcfd4d3e, - 0x1dfef0c5, 0x577c3301, 0x576e1981, 0xed05aa43, 0xad894299, 0xa9ef7a85, - 0xedebe730, 0x3812964c, 0x3f7b455d, 0x85f41c01, 0x3a60f747, 0x89bb1f02, - 0xfcddd3ae, 0xe53fbd5d, 0x4c2ca90f, 0x124b71f3, 0x5127fa23, 0x8f9b80b9, - 0xd3bfb23b, 0x0fcf9b55, 0xa0fe99fd, 0xec8cf84c, 0x58aecb7f, 0xd9ec059f, - 0x552f9a96, 0xf1c8c164, 0xc67ff644, 0xb8f1c8fc, 0x721f9c35, 0x39cf9183, - 0x53f2449f, 0x5fb8e379, 0x53f0321e, 0xbfb5fd69, 0xaf78643c, 0x1326eeb8, - 0xc3ba185c, 0x26bf3e54, 0xbb3f94d7, 0x3f94d0ba, 0x131cd973, 0xd07c1b9c, - 0xfcc67e54, 0x7bfca605, 0xe5311e2a, 0xc2b055df, 0x7811df04, 0xf6fe54ca, - 0xf94d6b69, 0xdc975d96, 0xf5547288, 0xde70cc81, 0xfad1daf8, 0xbf37b473, - 0xa45e2876, 0x57b011c7, 0x818e0e50, 0x7b6982bd, 0xabb248e3, 0x31e60f41, - 0x4b56a130, 0xc6cb83fb, 0xa4665ea2, 0xefd2433f, 0xc634c183, 0x843c979e, - 0x6346b93f, 0x89616061, 0x71f17425, 0x6fc86ca7, 0x0d7e4739, 0x9ec8fa08, - 0xf44b72f9, 0x72ebe5e7, 0xd3bd402f, 0x5f803e9b, 0x3ae79c7f, 0x99103d84, - 0xbf31225f, 0x7ebeb9f1, 0x7ae25cba, 0x53ac44be, 0x3bea5e4a, 0x0e10b99e, - 0x5b38ae0f, 0x5480f57b, 0xfd6893d4, 0x803f2127, 0x51e81814, 0x24c8375c, - 0x65bb6ddf, 0xea1957ea, 0x99abd004, 0x4257bfcc, 0x9bde133d, 0xec30cb7e, - 0xd475ef87, 0x8931acfb, 0xcab6f5e6, 0xa43cbfc9, 0x94fc7d22, 0x469ca91e, - 0x80656b69, 0x059543d2, 0x595e7e94, 0xe54b6941, 0x540f4a7c, 0x63fd2906, - 0x3f4a32e5, 0xf4a6acad, 0x4a1acae3, 0x510cac3f, 0xa3e95eda, 0x2e879754, - 0xf617ebfd, 0xc0b758b0, 0x8b0f6e03, 0xb2822cb1, 0xdee724cd, 0x53f39454, - 0xa3066f8e, 0x63ea7fbd, 0xde8ca260, 0x6fc915f1, 0x47d1d3bd, 0x085e4af6, - 0xcf4fa798, 0xa70c7b7c, 0x26c2dd93, 0x8f47d033, 0xf79cf45c, 0x2b04a1de, - 0xa9c032c8, 0x519c9bde, 0x0fb985ea, 0x3a2e75e9, 0x70e75f31, 0x3eb7675c, - 0xac6c97fd, 0x206972f7, 0xcaf7879f, 0xf0b30f34, 0xd7a45eb3, 0xf49bc50f, - 0x5bd29fda, 0x2e89dca0, 0x33a735fc, 0x6e48e748, 0x8354ffaa, 0xc7882995, - 0x2e10d8a6, 0x7bed4f8d, 0x38f285d6, 0x3eae5537, 0x7c77b234, 0x5467d695, - 0x29e30c3b, 0xa7c3346f, 0xdcc9a5aa, 0xbb89e07f, 0x95f21875, 0x45d0fabb, - 0x4a54ff48, 0xa6e67af5, 0xb1ced46a, 0x7c7141ba, 0x79f10efe, 0xf13c6370, - 0xa93bac2b, 0x3fbb3ffc, 0xf7a3d5bd, 0xf606b187, 0x01f50d85, 0xf73a0de4, - 0xdd07a8fa, 0x3f34af95, 0xfd49abd2, 0x1885ed06, 0x206677f8, 0xac10abd6, - 0x2f5e5bd7, 0xe397ad07, 0xf6a68df3, 0xbe8f3de0, 0x7af7c7a6, 0xb5855be7, - 0x7d04e3ea, 0xe7f0a575, 0xabd9d714, 0xbc4af3cd, 0xec6f2e09, 0x679a6d5b, - 0x7f900ff0, 0xc8292156, 0x9b82253f, 0x32c7143a, 0x6a97fa09, 0xe5bd50f1, - 0x6a572f12, 0x1e02d16b, 0xb466c762, 0xd1cdee33, 0xfb73cff9, 0x1fdf401f, - 0x1ecaadfd, 0xd7e17cc5, 0xb06cf551, 0xe7e82d6f, 0x0dbdd011, 0xef5053c5, - 0x3d76dd1d, 0x98b327d9, 0xa48b85df, 0x8d9d5602, 0x6609ce76, 0x7ffc8c99, - 0x35defd82, 0xc8deb0d2, 0x9fd468b7, 0xf3cccb99, 0x2667d82c, 0x0cc6bf38, - 0x939bb1e7, 0x56f3df91, 0xa0b730aa, 0x6ff39a5c, 0xbe49b8b7, 0x12c559f2, - 0x3f08ef5a, 0xa66ebdd8, 0x2fb907f4, 0xec99e57d, 0x87e8a1dc, 0xf75bfae0, - 0x7026140f, 0x3128a53b, 0xff20f9a4, 0x3f91868b, 0xfbe182b9, 0xa7a825a1, - 0x5de64e82, 0xefd27acf, 0xb23ff687, 0xd27cfabf, 0xfa214fc3, 0xbe49d721, - 0xda759450, 0xd84916c3, 0x974a415b, 0x76eb718b, 0x5c044d6b, 0x47d7011b, - 0xbf377fc0, 0xbf133225, 0x35025aa5, 0x5fce2496, 0x4a482f68, 0x47f816a7, - 0x51ed4fea, 0xb53fed7f, 0x3fa834fe, 0xfd7f54db, 0x0bfeb53f, 0x29bff47b, - 0xafa5fd5a, 0x0416da6c, 0x79b4537d, 0x3cc18b95, 0x4ea95474, 0x4bdd02f6, - 0x21762fd6, 0x82511c1f, 0xa3e7e42e, 0x34727921, 0x22d2f87e, 0xe7cca2fc, - 0x855d7090, 0xc7fd427f, 0x54d9f85e, 0x59bee7b4, 0xbd69baaf, 0x5b0d6754, - 0x1acb4e41, 0xdfa0a70a, 0x1c83e017, 0x46527a5e, 0x9fccd1b8, 0x4aafcf45, - 0x701eff46, 0x844f588a, 0xab2a5ec9, 0x9c24f3fd, 0x2759ca87, 0x7be459c9, - 0x04e9fed8, 0x5ab98fd2, 0xe87ccf5c, 0xe5f9d927, 0x0de52f02, 0xbb293b3f, - 0x30f6bd30, 0x4cb013ea, 0x7c8f0ec8, 0x41d840af, 0xc4ce2c87, 0xb1425856, - 0xa11fb11f, 0xc2f1d4de, 0xaa0edc42, 0xf0e4f0da, 0xb6afd083, 0x24badfda, - 0x7974be03, 0xf33f553b, 0x7a7aafd7, 0x62edcbd7, 0x5efdd7bd, 0x34f3de88, - 0x89adfb0a, 0xd86a25a7, 0xc971f685, 0x841bd55a, 0x9e9b25c7, 0x5c69ee7d, - 0xf5627eaf, 0x17f5045e, 0xc3e37a6f, 0x6f170031, 0xf0a71351, 0xe4a43861, - 0xc394fa6e, 0xba23f9bf, 0xf2f451e9, 0x18679a1b, 0x4270fe7f, 0xb78a5d37, - 0xb0d8d6ec, 0x5098f89e, 0x716b5bbf, 0xfd4fa144, 0x676849c1, 0x56f86d55, - 0xd1e575c3, 0xc94b125d, 0xb5cf8288, 0x80bd906f, 0x0a7a2278, 0x2fd1757a, - 0xd0397ca2, 0x247af505, 0xbdcb22bd, 0x1465fa81, 0x93fd17af, 0xbe2fdfc0, - 0x4fec7e8a, 0x43c45ead, 0xb9f78bc1, 0x95873c70, 0xcfe7ce0a, 0x3f464e2c, - 0x4c1a817d, 0x9fca5376, 0x9fb9ac17, 0xbdff2ff8, 0xfaf993fb, 0x42d7d7d0, - 0x2fb05573, 0xeaf6738e, 0x799c68db, 0x587c402c, 0x0fec8cf0, 0xc2b5fa41, - 0x22896f26, 0x9732c527, 0x80ebc393, 0xc3ce30b8, 0xbf414eb8, 0xd0e5efee, - 0xcc8ff27a, 0xee0fa861, 0x6cf1fdd7, 0x8b5fc12e, 0xb27184fd, 0xdae75f45, - 0xbb5bfc4c, 0x74e919b4, 0x052f806c, 0x4ce56afd, 0x487c0a09, 0xf95ea067, - 0x3853abbd, 0xc947989d, 0x5d81ef16, 0x639f0130, 0x67d566f9, 0x8f7a6e1f, - 0x6ee8c99d, 0x1f689e7f, 0xf3831dfa, 0x5664e1f9, 0x7c651f50, 0x07aeb235, - 0xf0375e60, 0xb9de4199, 0xc23ed7fc, 0xff975de5, 0x31934dd0, 0xb9f7abff, - 0x387be11c, 0xc2bf425f, 0xfbbf9429, 0x83f48956, 0xc9a38595, 0xe42aad79, - 0xc91f9cdc, 0x457fd02f, 0x0df0338a, 0x744093b6, 0xde5abf20, 0xa8df784a, - 0x575db157, 0x39757acf, 0x20fa17ce, 0x707d064f, 0x603eb759, 0xe81eb9ab, - 0xf20aeedd, 0x7a1a9bf5, 0x5f9469ee, 0x07a0d790, 0xe3f557e5, 0xdc6f8ff8, - 0x209de1fb, 0x75ebc7b7, 0xd5eb35b9, 0x782db948, 0x7c84bd69, 0xc7b7291a, - 0x894ac00b, 0x3cf0b726, 0xb416dcaa, 0xaaf44bfc, 0x65c7c78e, 0xf5d55eb3, - 0x8cf86f64, 0xca9793d4, 0x127aa89e, 0xecb3ef7e, 0xf3a8fc9e, 0x457fcea1, - 0x80bd29bf, 0x9f3a09fc, 0xc5d87cea, 0xf61f3aa7, 0xf098cff0, 0x3b7f9918, - 0xc10c04f2, 0x7f255dbf, 0xdf134962, 0xdef7838f, 0xf8459fec, 0xc734d1f2, - 0x9fecdfaa, 0x11438468, 0x79447d70, 0x8fec045f, 0x80881f28, 0x4be54c2b, - 0x8c6af71a, 0x2a6c20f8, 0x2bff9d67, 0x759445f6, 0x950f3eac, 0x82d49c37, - 0x9d691fc8, 0x753fea1a, 0xe8a89821, 0x9329dc3f, 0x7003b0ff, 0xe9da04bc, - 0x0a1198d8, 0x6c591e82, 0x0ecdebe7, 0x012ba777, 0x1cf1c5d2, 0x96d24cee, - 0x9fd41ea0, 0x1fb9da77, 0xe9dfc3a4, 0x31f8378a, 0xa4c9360e, 0x6c425bc7, - 0x093f3472, 0xdf8434cc, 0x3e5bd616, 0xe0768ff7, 0x87b633be, 0xcf40cefb, - 0xfa4765ab, 0x56bf5c7c, 0x23605ecb, 0xedc16b36, 0x77a1742e, 0x71ba0d34, - 0xfd9f3c1a, 0x6db7ccb6, 0xafa53e82, 0x8471dd61, 0x2b189f05, 0x72de7ee1, - 0x4d999fe2, 0x6b321d7c, 0x28797479, 0x39e5ef12, 0x77a869e6, 0xb9f0fd61, - 0xd7ac0fd1, 0xe23ab053, 0x42f5d379, 0x3d69aa6e, 0xce6b5458, 0xd4f5880f, - 0xc9feba37, 0x7fa49964, 0xeb84a170, 0xafb7a17a, 0x38de8796, 0xb1d3e80d, - 0xbfb8664f, 0x2649aa7a, 0xc8da9cfa, 0x305953f7, 0x8cafe489, 0xd4be9275, - 0xf286d6f1, 0x7aef7175, 0x9feb6dac, 0x3e421fb2, 0xe187f6da, 0x6db482bf, - 0x778327db, 0x47cafc20, 0x3d607fe9, 0x65d84fcb, 0xc7733f27, 0x7ff1272e, - 0xa5dfcec7, 0x76f0843f, 0x3af7f92b, 0x1c3b7d76, 0xa163b1f9, 0x60f500b5, - 0x7ebe00c7, 0xedf9daaa, 0x7f9a16f0, 0x331d1117, 0x7de88d14, 0x072fe9aa, - 0x54e02e30, 0xed0a8c13, 0x24b15d8b, 0xdaafe55f, 0xb1d11fc9, 0x80ecdbf3, - 0x9e379fe3, 0xd3ffb132, 0x5ed364e1, 0x73c5fec2, 0x8ef979bf, 0xc02ecfd1, - 0xdd86f1fd, 0x9fc84cda, 0x875fdaf0, 0x78ed7ea3, 0xed4ddb89, 0xdc1acb6a, - 0x48ba18df, 0xbd02a85e, 0xfac851da, 0xd16fb631, 0x4728f1c4, 0x57f2f13d, - 0x2f9cb3f2, 0x7c28263e, 0x8feffb3d, 0xf5c7c90f, 0x9364339f, 0x1ddfdc70, - 0x89ea03f8, 0x4be2565d, 0xebc7bc7d, 0x733d9017, 0xfbdf71ae, 0x52dc6e3f, - 0xbdc67cf8, 0xff9cdfe0, 0xfa878aad, 0x3d072917, 0x03e77cf9, 0x7a726f04, - 0xc9e7bfa9, 0xa7ff6bef, 0xa025fdd1, 0xe3dcebbb, 0x4b3fff0e, 0x0ba7b7f7, - 0x3e31bbba, 0xbfb5fca0, 0xa87eff52, 0x37f96b9e, 0xe36f7ba7, 0xb7fdedd7, - 0x33f79e2c, 0x5664fca1, 0xe2c340ed, 0x6f3dd2da, 0x5bee4267, 0xb1e37b69, - 0xf623e3bf, 0x5e34f47b, 0xf1b6fee5, 0xed03efb8, 0xac4978b2, 0xab3af917, - 0xfa2fb0bf, 0x3b23cbcf, 0x63da7fa4, 0xc5304f64, 0x2bf712b3, 0xe99f4adf, - 0x360bd8a5, 0xc200e3e2, 0x6c052bee, 0x4afe6f5e, 0x4adc3e62, 0xfd7e9fed, - 0xd373b43e, 0x83b264d2, 0xf7fb2521, 0xfe64d775, 0xad3344bc, 0x98f5ae87, - 0x129347d7, 0x89a8ebcd, 0x19abbea2, 0x0ed5ffef, 0x3c021429, 0xcbf01f8c, - 0x8ea7f444, 0x126548bf, 0x605893c0, 0x263bae11, 0x9df5cc3a, 0x836c7dc0, - 0xc5eff1bf, 0x3c2ec4e3, 0x47e95c0e, 0xc9900e3c, 0x3c4e7aaf, 0x6f09bf62, - 0xc78c2199, 0xe3978a61, 0x4bd4a131, 0x1eb16a7e, 0x1da26ec7, 0x349638a3, - 0xb82b3ca3, 0xa078e69e, 0x9ebeb875, 0x4cdf0dee, 0xd115cfac, 0x257f8ea4, - 0xcdd9f64d, 0x5cfad1f5, 0xa50fcba7, 0x7fc74e87, 0xaac92e94, 0x8e692e99, - 0xebca0a39, 0x8c3f5c64, 0x1c99f2c4, 0xb42a0b4e, 0x0fd624df, 0x28e678d7, - 0xa4278041, 0xaf482a65, 0x22f6db7c, 0x79b51f8c, 0xc5c7ea25, 0x1f9a166d, - 0xe112596c, 0x428d487d, 0xf7167bf0, 0xd4f7a428, 0xfe395e2b, 0xbb3f4320, - 0xba06e34f, 0x7c97ef9f, 0xd8cce67f, 0xf0c7f46c, 0xde7fc61f, 0x59b7eb00, - 0x063859ab, 0x615b34f0, 0xf404b8c1, 0x73ec4b93, 0x0cdc9f93, 0xe4aaefe3, - 0x55ce7aee, 0xf2bd37be, 0x015f4ecf, 0x45f9f63d, 0x94c76d8c, 0xc6288a6f, - 0x9a8ff6f5, 0xf7cabe38, 0x1e40d0b3, 0x0dfb2187, 0xab2f8afb, 0xcaf33fdc, - 0x891a5f1f, 0x1d71dceb, 0x7eb8e343, 0xa971e2cd, 0x8a70bd62, 0x0ebce279, - 0xe283afd4, 0x9f74bf68, 0xe7168cec, 0xbfac41b8, 0x28f1837f, 0xb2d47690, - 0x57d7196a, 0xbefc93ac, 0x5b1b5ac1, 0x661e251f, 0x7e116a8d, 0xf8374122, - 0x7fb8d9c9, 0x0d9fdbc3, 0xe919c6af, 0xa8e536d6, 0x1d27bc32, 0x61b9f7f0, - 0xc51feaff, 0x11f7ae2f, 0x2dec1bbf, 0xf451fc93, 0xdfc0bd47, 0x91df3dd4, - 0xa6d2f49f, 0xdfe416b5, 0xa62d6b4b, 0x553ad8fd, 0xb04631f8, 0xa9afd811, - 0x2cceec7b, 0xd93ecba4, 0xe5a5f18b, 0x40b5274d, 0x48c47d94, 0xe8fd627c, - 0xdd556f7f, 0xb50eeed4, 0x75e2267e, 0xc31b09c7, 0xad76f575, 0x3f5a38ba, - 0x7ef2b4ef, 0xf7f566ce, 0xf7f8cf0d, 0x0eb8efc3, 0xae3c7847, 0xf0996b3f, - 0x1ff24483, 0x553e3e23, 0xbf3842c7, 0xf5157ae2, 0x8c8da9c2, 0xc94077e6, - 0x06feb863, 0xd1b1ff79, 0xe37173af, 0x5da0df96, 0xb924d650, 0x4ca24b71, - 0x8fd0d169, 0x2f18de5b, 0xe99c3ce3, 0xdd6fe3d1, 0xc8356ec3, 0x10aaab45, - 0xd98ef6be, 0xfbb61771, 0xd0c69b65, 0xdebdf14e, 0xfc79c2e9, 0x2491a6cb, - 0xeb8dbd07, 0x34564ae5, 0x841ce311, 0x87e48c3e, 0x4c631ba1, 0xa07215f0, - 0x54d7ca1f, 0x6f3ccb6b, 0xd32dfa14, 0x788fb124, 0xf42dfa9e, 0x7b7e99ff, - 0x016fd75f, 0x23906fd9, 0x419bc0bf, 0xd344a5bf, 0x4f25736f, 0xee7de20a, - 0x482941ce, 0xab6fb9d7, 0xdbf4d149, 0x2fbe4aa6, 0x4dc459ba, 0x7e803477, - 0xdfa0dcbb, 0x45bf401a, 0xa3191f89, 0x73fa7ee9, 0xbfd0b7e8, 0xa136fe46, - 0xde328b7e, 0x74fe041b, 0xe9bc36fd, 0xe1b7e920, 0x3c53160d, 0xf84d44f0, - 0x6fd57a9b, 0x68add252, 0xbd53ef1f, 0x67f851b1, 0x37c7b093, 0x6c46388b, - 0x955cf507, 0x5cf4c3f6, 0xb9eaf9de, 0x759e117f, 0x2b77373d, 0x9ee8b8a3, - 0xdcf5c87c, 0xe7a0eddc, 0xae47e424, 0x64eee6e7, 0xa1172fdc, 0xd0f486df, - 0x97ca8c6f, 0xe5fbf985, 0xde4f198d, 0xf08df50d, 0x941b5ea9, 0xefadd11f, - 0x5df51946, 0xbe8bd695, 0xfa7e77db, 0x77d0ab6e, 0xa206c7a0, 0x0fe48d7e, - 0xde39936f, 0xc3e8c77c, 0x79465f1b, 0xfb4c9df9, 0xf859ef92, 0xa33bd1fe, - 0x7f21670f, 0xf3fa2a7d, 0xd9e9c6a2, 0xfaa4195e, 0xc7cebc27, 0xfb91ba57, - 0xb81acbcb, 0x2b56587d, 0xe7f03c87, 0x69df31a4, 0x9dc2ffd8, 0xf8014b12, - 0x13f56b26, 0x9febb40e, 0x1f589957, 0xf034c94d, 0x629cacc3, 0xd957fbf2, - 0xfcf0eb5d, 0xd9852cd1, 0xec5fbfd0, 0xed147498, 0xbe1ce2e0, 0x9e2c501f, - 0xb3b071eb, 0x4464f4bb, 0x9ce3483c, 0x9eb3fb37, 0xad531671, 0x9f53ae9c, - 0xb7184295, 0x22ee33da, 0xb8a17a44, 0x5dfcfcce, 0xc9377f21, 0xf62f842d, - 0xee351cae, 0x85d72f43, 0x4f027da7, 0x9e131780, 0x3c545242, 0x64a7a501, - 0xa5e37726, 0x4b2d77f0, 0xf0a05f70, 0x91f68929, 0xe3adc723, 0x3afc722d, - 0x773f751e, 0xbf2fa8b1, 0x6b9d2d69, 0x8e8bc48a, 0x747c48e7, 0x1f023de1, - 0x7e5d69ef, 0xd71891ed, 0x7a437c04, 0x809ff826, 0x3fc76817, 0xf9d322ee, - 0x5e048f9b, 0x9b8f5646, 0x370fe180, 0xe43a1c61, 0x79ccd5e7, 0x63e02fb3, - 0x119ec7d4, 0x315e9d38, 0x7dc01ac6, 0x4ef60dda, 0x1f3a83d2, 0x3e72b30e, - 0xd95e84d4, 0x3c62afd1, 0x251bf3ad, 0xe521da37, 0xb5e13b61, 0x0ed1f81c, - 0xf53ef645, 0x578124cd, 0x6aaf9d37, 0xd013f314, 0x26eb82c1, 0xf10abe7d, - 0x9b2358f3, 0xebca5d38, 0x58b25d38, 0x94c7ed27, 0x30de48d5, 0x71aca78c, - 0xeba1c50e, 0x0e7e19fa, 0xf0a29d23, 0x7f8d12af, 0xb39b3a19, 0x62cde7bb, - 0xb5aa6e51, 0xe7dc43fa, 0xb1f20a99, 0xfe10d896, 0x3efe1677, 0x2450fc57, - 0x78132ebd, 0x757884db, 0xb93afe20, 0x8efe15fd, 0xf9e969ce, 0x84d04ae5, - 0x9f4f09d7, 0x53b7fce6, 0xac5fa0f2, 0xcfc86f0b, 0xc74a3f90, 0xd233f21b, - 0x465729a1, 0xddf00f38, 0x78e7a327, 0x28d4bf71, 0x0f3b85f7, 0x919ffaf2, - 0xb8ca2cbc, 0xff7f307f, 0x4deebe40, 0xc55987de, 0xf7f0413a, 0xfdcef63b, - 0x77bf9123, 0xd12fdc4a, 0xf7da6f14, 0xd7cac1bc, 0x20ec1b4d, 0xf6dfb807, - 0xe75deab6, 0xae1fa9e9, 0xc03972b2, 0xe0c784f5, 0x0704baf7, 0x75a6f182, - 0xa4178a36, 0xf6e40c7e, 0x6f5f51aa, 0x5ba4b3b2, 0x7faf7ab3, 0x37bfa88a, - 0x8787497b, 0x47a87b61, 0x21bda11b, 0xce45eddd, 0xe0ffba17, 0x43bae35c, - 0x3bdfcff0, 0x1f9dbd2e, 0xce554f1a, 0x4c5f699a, 0xb54aab8f, 0xd1515e04, - 0x992c9bbe, 0xe7a0b7e2, 0x70ffce82, 0xa36ab7fd, 0xa59faf7a, 0xd08ec8da, - 0x2d5ecbcf, 0xf010583b, 0x254fa5f6, 0xe32b0179, 0x7f38b183, 0x1079878c, - 0x8ff72f92, 0xca6ee8fa, 0xed9f6997, 0x29f5dfc6, 0x1bc87dc5, 0xbb1d0c79, - 0xfb225331, 0x6cac3de1, 0x36e1da34, 0x268ab3e6, 0x47e73f21, 0xd73c21f1, - 0x3d5b5992, 0x3d7203c1, 0x85542ea2, 0x674277a9, 0xaf483be2, 0x7a433271, - 0x4cfafb35, 0xbef7f9c0, 0xdc4cb33f, 0x813b078a, 0x8fb119ea, 0x31b96125, - 0xce5a24be, 0xeaf86e8c, 0x7fa05bfd, 0x5ecbf7a3, 0x69bb940f, 0x7281c3af, - 0x85b56436, 0x19780c05, 0xe85542c3, 0xc87d1a77, 0x83ea0b77, 0xf07bb002, - 0xd341497c, 0xc2172ada, 0xbf7a25ab, 0xe498183c, 0xaa6dfe82, 0x32e93939, - 0x0e500bd4, 0xcd5f29ab, 0x4ad795cb, 0xce710c5e, 0xf1415a6b, 0x12b57948, - 0x14dc601d, 0xd78d9892, 0xbd41b21b, 0xfbc3569b, 0xc17f3859, 0xed6f58fb, - 0x416ff7c9, 0xa4fd03bd, 0xfdf237f7, 0xcf783cfa, 0x3b527283, 0x5c2bea87, - 0x073c312d, 0xcf91b053, 0x55fb054f, 0xec37e62f, 0xdde68a7e, 0xdf5ed029, - 0xc28f9c0c, 0xd13ce913, 0xe74dc948, 0x80be1f38, 0x0e0756f4, 0xa5f05f18, - 0x4909f8f3, 0xa3fd62c0, 0x6dfd7fdb, 0x9e535cfc, 0x07d68177, 0x272779ea, - 0xfc42c329, 0xe1f69274, 0x03be010f, 0x79379c56, 0x9cdecb3c, 0xc316b42f, - 0x1b6398fc, 0x6acfef44, 0x1e71471c, 0xe29f99b3, 0xe68ea63c, 0x57bbe776, - 0xefe843da, 0x4ced577b, 0xaf7be7c3, 0xf6f3d2b4, 0xb70f5c4d, 0xbf21680f, - 0x2ad5e1fb, 0x552ff3c3, 0x13d265ab, 0x74aa3787, 0x867e576e, 0x6fe437c7, - 0xdec876e2, 0xc3debcd5, 0x9b7edc75, 0x936dccf0, 0x5fce1e70, 0xeaf9cfcf, - 0x875f5a7a, 0x4d0bb9e6, 0x9ea45bf3, 0xa970f5d5, 0xf54147c0, 0x8f4fda5a, - 0xfaa5bbd4, 0x6fa1187c, 0x9d9f714b, 0x24c3d3f6, 0x91f5a547, 0x6e8e65f1, - 0x43f20dbf, 0xefe23bf8, 0xc32afdb2, 0x45f48d75, 0x678a24db, 0xf21ef9c3, - 0x3e493747, 0xf8287b8c, 0x7b221ad8, 0xe33b943c, 0xf99e703f, 0xc8f0cac4, - 0x03d22b48, 0xb58e54f4, 0x84bf8ff3, 0xb3df47e7, 0xf010e461, 0x5fe12e4f, - 0x5ace138f, 0xb27ee3cf, 0x8c995bde, 0xc4d98de7, 0xf207a43e, 0x3016646b, - 0x92a38de8, 0xf93b96ef, 0xfb46e0fc, 0x966ba747, 0xf3879d56, 0xeb8d916c, - 0x957acf47, 0x0bc78bce, 0x3e0bd618, 0xb70a77b4, 0x0cd648af, 0x73b850fc, - 0x0ea83245, 0xcbc444b6, 0xe6738954, 0xa76f1a85, 0x5ee49770, 0xaf47686b, - 0xdb57af47, 0xb41bdfce, 0xd5bda793, 0xa3fd885f, 0xa1ad7e71, 0xa7ac88de, - 0xd4bdfb47, 0xa75ff393, 0xffb9e257, 0x0a65779c, 0x62f9cf76, 0x3ee320ca, - 0x7eea9e8f, 0x2df7ece6, 0x5fc067cc, 0x98631fce, 0x86ef40cf, 0x40ff2051, - 0xb91a1bbf, 0xea30d73d, 0x459a56a0, 0xbde51bb0, 0xcba3f84c, 0xbbfdf226, - 0x16f7cc86, 0xc94ffca1, 0x581f8892, 0x49f5a030, 0x83cdfb24, 0x59f900fb, - 0x787cfdfc, 0xe1b2e51f, 0xa0a72e29, 0x4fa83c2f, 0x98af56ca, 0x256be544, - 0xb0dfd60f, 0x92ec9736, 0x51991c82, 0xb241ed7e, 0x0f1a0a93, 0x833ca226, - 0x7b44aefc, 0xd5ac6ca0, 0x9758ea8d, 0xdfce5d4b, 0x9961e715, 0xcf0c3dcd, - 0x5876e077, 0xf796f934, 0x72b76133, 0xe1cf2cb9, 0x26eefb72, 0x3e784715, - 0xad724e72, 0x728cb1cb, 0xc72dd59c, 0xd04f577b, 0x870fae50, 0x99a38a24, - 0xe5007a80, 0xe71e837c, 0xf3d8edc4, 0xd973f395, 0xbf20a599, 0x72ea5f38, - 0xa475cbae, 0x2d2b373c, 0xee3f62b7, 0xe34ed2bb, 0xf6d57098, 0xfae3ef0f, - 0x275ff68a, 0x3260f55c, 0x853cc7ea, 0x78e979c7, 0x5c78552d, 0xad7e8f60, - 0x3df5a05c, 0xf445fe9f, 0xd9ab33e3, 0x8b6f125f, 0xb5eff1e7, 0xb9fdf12a, - 0x9c87b3e4, 0x9e7ca79d, 0x4b9d5caf, 0xe5f6f53e, 0xe27ae69d, 0xf5476991, - 0xf01dafac, 0xbe3c0618, 0x8a59f1b5, 0xc2f13e0f, 0x8748a9c1, 0xe7c01de2, - 0x9d1b5fc8, 0x4e7a8c2c, 0x55bcd109, 0x39d320d4, 0xb384a603, 0xe51a716f, - 0x1575c798, 0x3f12766f, 0x0d64bd15, 0x8bf7814d, 0x9c317db6, 0x76166ae2, - 0xf05adc52, 0x072f6105, 0x1ca3865b, 0xbe3c2914, 0xfc2f522c, 0xe7edc6da, - 0xd3b1edb6, 0x1d527c70, 0xa8a2dfbf, 0x6ad576fe, 0xc278a7d8, 0x50bb52a6, - 0x8379f68e, 0xfe78c7c0, 0xbc67fb17, 0x2b8f4157, 0xf5c0db6b, 0x1aa35144, - 0x8a327bc2, 0x63b4b6ea, 0xc7d171bc, 0x957ff256, 0xf3a49dd7, 0x6f361314, - 0x794aff22, 0x8fda6ca3, 0x59df11eb, 0x18ad8727, 0x4a50d897, 0x1f0090fb, - 0xc45eb824, 0xf8c0fe53, 0x3bcde2c3, 0x850105b7, 0xef3f2fc5, 0xac72fd42, - 0xf10bbd79, 0x359ef50e, 0x3c47bade, 0x2223fd67, 0xc386f39e, 0x2f4b6f74, - 0xf0c79cf1, 0xb794100f, 0x4e78e66d, 0xec87d756, 0xb667e84b, 0x47feca3f, - 0xe9be7d97, 0x1e7835eb, 0xe3a5eda1, 0x25dfb06b, 0x0d72fb7f, 0x5db189c6, - 0xcaf79a76, 0xe280f85f, 0xbef7f5b7, 0xc87f09b0, 0xfe29e786, 0xab13fdbd, - 0xdf6b6b17, 0xe31d3879, 0x7cb7db06, 0xccfe8c97, 0x26af3b79, 0xadbcef7f, - 0x94585213, 0x914f4379, 0x11e7437f, 0xb7491f7f, 0x297b0dbd, 0xd004ed9e, - 0x5760f51d, 0x297d6e9c, 0x88f67f8f, 0xd18ddcf8, 0x88f43bcf, 0xe5b86dc7, - 0xff512bc6, 0xf27b7037, 0xefb9719c, 0x3f2f3d03, 0x146e3a0f, 0x37f5d7f1, - 0xf72e359c, 0xf401fe04, 0x74cdd8b2, 0xf661bafc, 0xbcc69faf, 0xc6bd3e86, - 0x03cf86e5, 0x8a79fa7f, 0xa73e6c77, 0xa5e8e51d, 0x343c50df, 0x078a6fd2, - 0xd3afa3e7, 0x11ca3cf1, 0xce3a73b5, 0xad3b9d3f, 0xd14fdf74, 0x9e488fce, - 0x47beb7da, 0xce266a7e, 0xaeb3b435, 0x973f8f1f, 0x9d6b78c4, 0xd0579e3c, - 0x3d7de301, 0xe22e7a2e, 0xeb5f397a, 0xc5bdbef1, 0x1f6d5ef9, 0xe00fee28, - 0xb5a5c8f1, 0xb3f1107f, 0x729374dd, 0xcf075e90, 0xe3ad471a, 0x72f42dc1, - 0xf47b1c77, 0x38aeeab8, 0x21ba08f6, 0xea9e713d, 0x3807538a, 0x49f9046d, - 0x2e768a3e, 0x8f2d7da2, 0xa3576f7f, 0xe3d6379f, 0xf4117dda, 0x9bdbc7d6, - 0x7b72e8bc, 0x50fc71ae, 0x4266d13c, 0xb57c4f52, 0xbf5d1f7d, 0x7f4bb4cf, - 0xebbefad7, 0x148954bc, 0x5eeb1e79, 0x86d2cbe4, 0xeccfe483, 0xf18b7f5a, - 0x7bff09b6, 0xc5320bdb, 0xdfa92f39, 0x523dfa4b, 0xbde1947f, 0x7bfa512d, - 0xe7d85dbf, 0x68fe7c8d, 0x7219c97b, 0x7b6d3d40, 0x975f13b6, 0x71483c6d, - 0xbdd66fd6, 0xe218b5ac, 0x08fe7027, 0xf6d3c619, 0xa4e1eee2, 0x30fdc5cf, - 0x8954ed91, 0xa29bca76, 0xf1be53b7, 0xe29da9a4, 0x76e6bd60, 0x63bdbb9c, - 0xac76ef8a, 0xb73358ef, 0xcbd58f13, 0xf6d14393, 0xd8aaec69, 0x29e6afef, - 0x0f74a3cc, 0x7bdf938e, 0xc862bb23, 0xcce79cee, 0x112e38f9, 0xbae28d53, - 0x388816aa, 0x537a9fb0, 0xce55de91, 0x77f618eb, 0xe0d7e231, 0x01dd51ff, - 0x9aaaf686, 0xbf42cfea, 0xd1dea443, 0x642c2d12, 0xe73cf7a0, 0xed0f14e4, - 0x90d3848b, 0x0f32079e, 0x67ef58ab, 0xcfabfe11, 0x0524b614, 0x5059f7fa, - 0x7a802ef2, 0x0c5ff7d9, 0xd67b3bf0, 0x8781c3af, 0xa9bf9365, 0x0079dacc, - 0x35ec2bd7, 0xc847ed3b, 0x7f74ecbb, 0x3b1af948, 0xd6ef778d, 0xbb239f6f, - 0xc656d7fb, 0x556087f7, 0xb996f783, 0xb7871d79, 0x2fe6bb7e, 0xcbe35768, - 0x1afe7ed0, 0x89eb8f28, 0xfeb4b18d, 0x8e2978e9, 0x7fcb51ee, 0xa8a9a1ed, - 0x3963f2d7, 0x4e6fe63f, 0x7d415509, 0x6e1c49ad, 0xee8034dd, 0xc97e28ab, - 0x7ba5f149, 0x8652beb7, 0xe6fb54f3, 0x60330c58, 0xfb09afed, 0x7ee237ff, - 0x63d51aad, 0x642f338c, 0x2e78c78a, 0x536118a8, 0x3f23135c, 0xfa11c906, - 0xe8e31ab1, 0xc5d8113c, 0xa84e7aa6, 0x89780f9d, 0xf8fd838f, 0x3f70aa39, - 0xe59107d4, 0x76fdfcf4, 0xdcbd8e7e, 0xba39ef0a, 0x9d6b97cb, 0xeeae1c79, - 0x3349f5c7, 0xe744ff95, 0xb3df9173, 0x23fe5e5e, 0x7aaedebd, 0xe265fbf8, - 0xfe489b7e, 0x57a5d43d, 0xb4717afe, 0xf4a25bfb, 0x2fdf9e9f, 0xed05a0b1, - 0xba762d96, 0x67ef0bb7, 0xdb0e73c0, 0x55ffbe34, 0xfdd30ae2, 0x3e843b39, - 0xd309892e, 0x44fd3e7d, 0xc23cb03f, 0x22f2d6cc, 0x15f4bdd2, 0xb3f8c33b, - 0x3e9cd7d2, 0xb6e977a4, 0x957f5b6f, 0xb18bf185, 0x7d2bd7e4, 0x1f117fed, - 0xd3c35a94, 0x2dbcfee9, 0xe7f78656, 0x3b796db5, 0x4db5e51d, 0x9c27a70d, - 0xb4af5f65, 0x57be6ade, 0x58e38c40, 0xbc42e865, 0xaf3f4177, 0x9e8bd45b, - 0xdb8632b9, 0x9f18f6d7, 0xdde48635, 0xb1d44f7c, 0xc641c6ca, 0x9e45fbf3, - 0x7fb17ae8, 0x9d8ffa8c, 0x38f47743, 0x263fdaf7, 0xe699ed09, 0x96407464, - 0xfa8e3d81, 0xe4eea8bc, 0x7c1ff430, 0x6fdfa316, 0xf9c389e0, 0x73ad33e8, - 0xcfbfea18, 0x19873bd2, 0x952399e7, 0x92a28f36, 0x8ed2875f, 0xfaf327b5, - 0xb5378c31, 0xf7a68b4f, 0x12c4c586, 0x8e1e8afe, 0x7a8e7a8d, 0xabe70c4c, - 0x531f6834, 0x43e5176c, 0x2d33f76f, 0x31b87a44, 0x49ebc3c6, 0xbcf8690b, - 0x20fb6eb8, 0x950a1e23, 0x72072a6a, 0x642cf84a, 0x832cb52b, 0x2bdbd6fe, - 0x28f0ef9c, 0xf2813f74, 0x55f8ba7f, 0x3933a6ee, 0x518e3191, 0x5c6614e0, - 0xe7eb33f2, 0x6fd51448, 0xcc69fc43, 0x646456ef, 0xf7926a95, 0xa94f5618, - 0x7e2ecc03, 0x43055a5f, 0xec44793d, 0x0c1fa3ef, 0x3d7c6ed3, 0x383f7a48, - 0x328bb180, 0x4f09bef0, 0xbf80db9c, 0x3eb3706b, 0x2b69e309, 0x5317d718, - 0x488f68dc, 0x033b00c1, 0x595554fc, 0x03df8837, 0x2f187cc2, 0xf42c2649, - 0xf37ee5cf, 0x8083b43b, 0x843df94f, 0x1550b157, 0x86c318a0, 0x9e3aefc9, - 0x96f3fbf1, 0xeb8ccc7d, 0x0741128f, 0x7a4ddc16, 0x7fbac1cc, 0x5aa3009d, - 0x155b7d45, 0xdc1cb7f7, 0x59b8739f, 0x58c3ed18, 0x42c70b07, 0x1caa18ea, - 0x2bbfca33, 0x5f03600b, 0xf39ac7ba, 0xf402e523, 0xf5bb445a, 0xf7a83f84, - 0xbf7a88ab, 0xabf7a88a, 0xe3abd5b3, 0x2836dca9, 0x58a5ef03, 0xf02f595c, - 0x09b3dbc6, 0x867e01bc, 0xcc7f3de0, 0xfb15e312, 0x18d784e6, 0x962b1bd1, - 0x8e6eba07, 0xfa7e20c9, 0x4eaedc59, 0x8966978c, 0xc3d70c35, 0xbefd248b, - 0x1877e64f, 0x1b6e63de, 0xa223e1c9, 0xcf02cd9d, 0x55bf748b, 0xb276f28f, - 0xb7947abf, 0x263e56f7, 0x6f67797a, 0xde8d89fd, 0xea5ef89f, 0x5a8d8eaf, - 0x4bd50fff, 0xf47daf65, 0x76efee0e, 0xa03727e9, 0x6e676cde, 0x1a54fd46, - 0x16b7fadf, 0x4cedc27a, 0xde999a5b, 0xc0dfc831, 0x9a17316f, 0x49f2479f, - 0xf472fe14, 0x29df7185, 0x61f3bbda, 0xe74d5e7e, 0xbe315c83, 0x9f7cb589, - 0xdc79eefc, 0x46cb078f, 0x25dfe61f, 0xe1aeeff2, 0x0fdde3f6, 0x1b0fb4cb, - 0xc1d5bf79, 0xe1efcdff, 0x801f07b8, 0x5f33ddbc, 0xa233850a, 0xdec5dbdd, - 0x677a878f, 0xde44fe88, 0x9e601583, 0x68e4cb49, 0xbe7160f7, 0x45e1cfd4, - 0x8b317fde, 0x66fdc5f9, 0x3159e7e6, 0x22dbe26e, 0x0f55a425, 0x82c79eed, - 0xd1ef802b, 0xc7be04fe, 0x9c592ffd, 0x8d2e66c7, 0x9adfd7c7, 0xa77fd260, - 0x70e27886, 0x8baf66be, 0x7cfe6ee7, 0x149eb5ee, 0xe54579e3, 0x1ee9ac74, - 0x9bd52aa0, 0x3d4dfa8a, 0x80f33d7d, 0x07a76a1c, 0x1f218f31, 0x7e1256ec, - 0x3d24f30c, 0x5084aa95, 0x3f6e2a2f, 0x37bb47cb, 0x5eb3f39e, 0xaebc4b5e, - 0x177ccecb, 0xe6461dfe, 0x5dcfff81, 0xdff3a1e1, 0xa7fc3957, 0x5d95fe71, - 0xa380de39, 0xb7043f27, 0xe15771f2, 0x8e7a33b8, 0x7af34aa7, 0x0ebedec9, - 0xcbf245e6, 0x3fd86d79, 0xc8f9ead9, 0xadfbfd83, 0xd30fd0ca, 0x23de3f13, - 0x153fc821, 0x24714fea, 0xc194dc72, 0xbc72fed8, 0xfff4146f, 0xe8bf7132, - 0x52264aa2, 0x08b7571e, 0x34a51fef, 0x913ea447, 0x8f72a64e, 0x974a7b8a, - 0xd5297a54, 0x56f36bf1, 0xb6983dd3, 0x36fb790b, 0xa25fa0b7, 0x402fe045, - 0xb52d97f6, 0xed1df682, 0xde308aee, 0x60d2c727, 0xb961c1de, 0x9abf09ab, - 0x13bf919b, 0x456c13ca, 0x66b55218, 0x7149d10a, 0xc87cb057, 0x0604754f, - 0xe37da2c7, 0x6987df31, 0xd6711d4d, 0xf8bb31fb, 0xfbc7136d, 0xb7e71263, - 0xa63fbc48, 0x6e307b36, 0xbb6bb1e2, 0xbc22abee, 0xe38872c3, 0x7ef93ffd, - 0x37bc4f6e, 0xc0699b4f, 0x327b33bb, 0x0267fde1, 0x5e054bcf, 0xaa1d04ab, - 0xc4ab3e04, 0xe255afbd, 0x812adcde, 0x3bc42adf, 0x7b888fa4, 0x3d23177b, - 0xef119520, 0xa1d6bfc0, 0x7b432641, 0x520f0f7c, 0xb75be087, 0xb2a4fc85, - 0xbc43efc3, 0xde39135b, 0x03a00e6d, 0xdde035f1, 0xc241f983, 0x78e0eaa7, - 0x0e9cf286, 0xef105602, 0xa739f123, 0xb6fde007, 0x87d424d8, 0xd6784c63, - 0x1f9fc712, 0xf3e29fde, 0xf390a25b, 0x6a25fc48, 0x5d605efc, 0x8fb37bbe, - 0x765c44ab, 0x1197b895, 0xcd7688f1, 0xbb0fc02a, 0x3f93e398, 0x2f60221f, - 0xfd6249a5, 0xc074055f, 0x3d8527fc, 0x74c67884, 0xb75f2c67, 0x762a5a24, - 0x04a788ab, 0x4b0fdf7e, 0x6cb4b20c, 0xf18043c6, 0x1e641a97, 0xe1fdf584, - 0xc8ff335a, 0x7ee2256e, 0xc893cf49, 0x56df2b6f, 0x2f7fb82d, 0x74debfcf, - 0xe69e5bae, 0xfe10f78b, 0x35da1203, 0xb872133f, 0xfa85f902, 0x8bc3d7c7, - 0x152c1f05, 0x223f06f7, 0x2131e7f8, 0x7ceb8fcf, 0x48e7e5e3, 0xf1e64f96, - 0x1699898e, 0x9862bf71, 0xe309e319, 0x834cf5bd, 0xc6dad17e, 0x9fdd2943, - 0x92b63ec9, 0x650ec6dc, 0xf8afe43e, 0xf10c1f8f, 0x7dfd70fb, 0xd78a1ed1, - 0xeb1dbfef, 0x0e83bf89, 0x711587b4, 0xd7cca4cf, 0xef51cd93, 0xeef2ad8d, - 0xa65fa1b1, 0xbeecfeb7, 0x73f11b69, 0x1e44e5de, 0xbfe027d6, 0x8ec03663, - 0xc157581a, 0xc81bd62f, 0xa57a8c5e, 0xebfc49c6, 0x1be7fe80, 0x17b624f8, - 0xc754ceff, 0x5f501bb5, 0x240680bc, 0x6a2fc130, 0xcf11d906, 0xfa0f7380, - 0xfea956b1, 0xac2f38be, 0x8fee8f8a, 0xdf2c65fb, 0x5d657087, 0xac2bf26a, - 0x9ef47d54, 0xef59ac7b, 0x44f314ac, 0x9cb344c2, 0x4fc2f3e8, 0x39577d45, - 0x5fb13b02, 0x9227a7c9, 0x1cde273c, 0x52a89e7d, 0xf7de20b5, 0xcb8c3551, - 0xe3573077, 0xfd0f73f6, 0xe49f68c3, 0x3af06054, 0x7ce983f4, 0x7d7190b6, - 0xaedc6417, 0x04f5c7d4, 0xe715bdf2, 0x3ff13703, 0xcb0807ce, 0xdefc6a17, - 0xe42dbbe3, 0xe4225887, 0x672151ed, 0xfd7c85cb, 0x8acbe51c, 0x297b58f7, - 0xab9085fd, 0x90872895, 0xe0cd8f1e, 0x3fb8bcf6, 0x2ccf5f4c, 0xfba08db4, - 0x161cab22, 0x4f94179a, 0xae0721ac, 0x768f760f, 0x7647ffa3, 0x4e03b966, - 0xfba2cfcc, 0x2cf8a5dc, 0x37cdf237, 0x9c1759ce, 0xc8161e2d, 0x2b16f74f, - 0xea4bf72a, 0x8957c8f7, 0xf75408fb, 0xd5fd0ccd, 0xd856264f, 0x9635de29, - 0xe4d787c7, 0x81de1366, 0x86b19d1e, 0xb4ca5a75, 0xfbeebaeb, 0xec9feac3, - 0xef835ee5, 0x6960de85, 0x41a17641, 0xfb88d44f, 0xc8279924, 0xc5f41886, - 0x31268bc2, 0xd4f5eff4, 0xcde8bd13, 0x2e6f5cf5, 0x4deba292, 0xf5d78edd, - 0xd17ea466, 0x4c17c5d3, 0x54bf9d36, 0x7a465e1d, 0x3f744867, 0xcac3b242, - 0xd7992ff7, 0x33d19b9b, 0xec95f01f, 0xed0be030, 0xf16fdd21, 0x89e328e3, - 0xae4793d4, 0x00d7e7d3, 0x4b343bdd, 0xfa393cf3, 0x79abf3ac, 0xfd3fc85e, - 0x794fcd08, 0x5a5347a7, 0xd92d7350, 0x69770c23, 0x1c2ef70c, 0x0bbf7d5e, - 0x46b87be9, 0x56af9fec, 0x74bf1843, 0x197166b8, 0x0f76d5c1, 0x2fdc66d2, - 0x3de1741e, 0xc8d6b34d, 0x247e9fb4, 0xf14e9826, 0x399fdf9f, 0x63e21b23, - 0x9a5dac16, 0x6b38fc8e, 0x373a52dd, 0x37c1247b, 0x59806fd8, 0x79ec8796, - 0xbcc6fefd, 0xb43ead67, 0xdbe37bc7, 0xfdd1d5bc, 0x27f8553d, 0x779853ae, - 0x7643ae08, 0x8674c6bb, 0xfc8e0f81, 0x82eb4ec2, 0x8ed82d2a, 0x58bad570, - 0x2555837c, 0x280fbf44, 0x0fb571d5, 0xf0ea94e9, 0x73298b5d, 0x4f7ed024, - 0xdbc472ef, 0x3b5f456f, 0x2d3ebbee, 0x3a0245ee, 0xbbf264dd, 0x56d77df2, - 0xb66347e1, 0x4463f25e, 0x7c97a7be, 0x62938f17, 0x7ff9e8ee, 0x6869ffb7, - 0x315df58f, 0xe6b4bf8e, 0xe84f92f8, 0xa11f7989, 0xcf8bc450, 0x5a1b175a, - 0x66ce4518, 0xb3c7f389, 0xce997ec4, 0xebd7858f, 0xe3e739f6, 0x5e973e48, - 0xfaf884b8, 0xcd2a7dcb, 0xafc0656b, 0x17a5efa8, 0x507dd346, 0xe2bb9e0b, - 0xfc0b8c71, 0xf94cbf6a, 0xc4eda725, 0xf53fedc7, 0xce8239d2, 0x9df4a9df, - 0x5df6af88, 0xda01e74d, 0x3ad3fdc5, 0x7c9cd29e, 0xc1c6bc3d, 0xe9de50f5, - 0x743c919f, 0xa66857f1, 0x779e7286, 0x5e5ce7fa, 0x31d9fef0, 0xdeebec38, - 0xe0a1771c, 0x2cd7806b, 0x2169349f, 0xc2df9bd4, 0x0d8d8ae5, 0x7b1f9196, - 0xd1f7ac6d, 0xc6bff228, 0xb5f931e1, 0xf3965bf2, 0x4caec0f7, 0xcc99c434, - 0xc87bdf12, 0x65efcd3f, 0x4b20ee65, 0xfa127945, 0xcc0e5bb0, 0xdbb772f7, - 0xd3d4e3cd, 0x79c6bb17, 0xd6fd6985, 0xe8abce3d, 0x53b09e79, 0x13465bf2, - 0x5f9e3ddc, 0x9e368e8d, 0xa58c71ee, 0xd1f1edf2, 0xb450ffdb, 0xc0595adf, - 0x8b4fa07c, 0x79bffdc4, 0xd434fba1, 0xe3ab791f, 0xb8c32413, 0x4d8a6bf2, - 0x35794ff1, 0x5fdf74b9, 0xed5ceafe, 0x76bc835e, 0x36cd85d1, 0x4743e5d1, - 0xd532e880, 0x40e3dfe1, 0xf0a17cb9, 0x583d4f81, 0x11d3a72f, 0x82bc382d, - 0xae7ddbf4, 0x3ea7e768, 0x8d53a48c, 0x1fac13a0, 0xd2740cb2, 0x7ef913e9, - 0x07d2faeb, 0x8bfdc53e, 0x45edf8a7, 0x08b1ebbd, 0xc74465fa, 0xf383a75f, - 0x0fd82b6b, 0xdfc2f381, 0xbbf8a665, 0xe827f15e, 0x7f47e3ad, 0x51dff60e, - 0x944efb94, 0x1f5851cd, 0xe17387e7, 0xc17dbbad, 0x8fa2e30f, 0xf3a9c527, - 0x04167cc3, 0x71aa3e01, 0xf1f7a3fb, 0xb682c43c, 0x974f18f3, 0xf1362e9c, - 0x01738a43, 0xff415397, 0x211e7ba3, 0xc50d6ebe, 0xbd19ed7a, 0xd9c5278f, - 0x185c1f0b, 0xffb34364, 0x11c1f1ef, 0x29f837cd, 0xde60479c, 0xf0bd79c2, - 0x1b86c7f9, 0x18ea97fb, 0x79c4e697, 0xf6fcfaa9, 0xbde383b7, 0x1e1d70fb, - 0xab7b275c, 0x8e254860, 0xbf7c60c0, 0x37f4f5c8, 0x145bdfe8, 0x68f0c4ff, - 0xcae2f476, 0xdfa0977d, 0x99b2aab5, 0xc5d85552, 0x0ce2ed0c, 0x688f5dfe, - 0x2b5e05f7, 0xcae2ebf4, 0xb5b7ee66, 0x70db9905, 0x323b00cf, 0x8ad8fc92, - 0x69cf6cc3, 0x7e8dc06a, 0x83dc4d73, 0x65812aa0, 0x67e85919, 0x1a0ccc4a, - 0x938d77f0, 0x4f2cd7ef, 0xfdc6e3dd, 0x8fd42b10, 0x9a5b33fe, 0x77e4ca72, - 0xe5995d7b, 0xd7e93a04, 0x7ab0c744, 0x1f91249f, 0x1f8454f2, 0x1fa994f2, - 0x7da6cd89, 0x28bc488a, 0x281dfe36, 0xb3ff0985, 0x9dfe87c0, 0x3e6ea5a4, - 0x8fc295ce, 0xaffa04fd, 0x363b022f, 0xc1f645d6, 0x7c2c0b92, 0xe853687d, - 0x3c6b2bbe, 0xf1c5af2f, 0xff71d871, 0x59f5c643, 0xde276098, 0xd5d32610, - 0xf1c2128b, 0xdc2123cc, 0xe0978587, 0x5c63a37a, 0xfcf803cb, 0xd7207b79, - 0xa6ff7809, 0x0901f36f, 0x81fc33f7, 0x35cf118b, 0x03d33072, 0x772d7fe5, - 0x74b96266, 0x8138fac8, 0x39e017a7, 0x9f618087, 0xdcd7df94, 0xe13dcb0d, - 0x112be60b, 0x5fdf86fb, 0xc7b7cc6c, 0x1fb02af8, 0x4acbdf91, 0xfda242fc, - 0x074cfc41, 0x34fdff9f, 0xf2772f3f, 0x07f10575, 0x6e3ed7f2, 0x3c529d3f, - 0x87efb871, 0xb4dd79d8, 0xbcf363ef, 0x114f686e, 0xe05ad8eb, 0x4fb0c557, - 0xb3e2a177, 0x545d3f20, 0xfd8dcf0d, 0x2727628d, 0xf2dae838, 0xdebd76a8, - 0x83af3c3f, 0x4f4f94f8, 0x92247b22, 0xed74762f, 0x69eff027, 0x9e33a1dd, - 0xf1c388b2, 0xfad1ff4c, 0xfdae93ee, 0x761c45aa, 0x5efca873, 0x69fe3fbe, - 0x99c51c6e, 0xa3b8fdea, 0xda336969, 0xf53477c5, 0xbcf8899d, 0x3fe2e0a3, - 0xed43ba63, 0xfa8b13dc, 0xce897ee2, 0xc1f9dd97, 0xa42c6aeb, 0x475fdf5b, - 0x2f3c1ff7, 0xeb3a71e4, 0x01fe9154, 0x7ef8d6e6, 0x47df8857, 0xae02bcc5, - 0x715fd157, 0xdb743877, 0xf3dd000d, 0x3406e87a, 0xebefa6f7, 0x43d5037c, - 0x893ddea0, 0xf7f494f6, 0x726fbd1a, 0x35d7bf98, 0xe346c57e, 0x8daf1ee9, - 0x0f8fafc6, 0xeff84a7a, 0xf7b88fc2, 0xf8c7c74d, 0x77dc7c99, 0x1d75dec4, - 0xe03acb3b, 0x3fb0db0e, 0xde3e78f3, 0x7cfc489f, 0x1fa05985, 0xf6fa745f, - 0xe33e3f20, 0xbd45edf4, 0x4ceb6257, 0xbc920657, 0xcbcf85bc, 0xc905c0e4, - 0x0313fe30, 0x21271702, 0x9cfb9a1e, 0xc07fbd97, 0x80fbf9ce, 0x81f7f39d, - 0x5baf9d0c, 0xecd7c89c, 0x538d2274, 0x92c77eff, 0xbb1f87ad, 0xc4fbf81d, - 0xbb3efcdb, 0xe373d952, 0x9697e443, 0x3e2e3199, 0xfc203d32, 0x7c5d2d0c, - 0x433bc7c8, 0xa332f2e1, 0xc1ce9621, 0x9b2f98cc, 0x319fdbee, 0x32c3c79f, - 0xadf879a5, 0x22c275a6, 0xb3d2d711, 0x4483f41e, 0xfe7333d6, 0x6517ba04, - 0x471ee69b, 0x9c35917e, 0xf44e66cf, 0x608e78c9, 0xf68932cc, 0xf21f47f1, - 0x3c00b634, 0x45ef1433, 0xe0f99d31, 0xfbc20d7f, 0xb99aca51, 0x9e45347f, - 0x4853f993, 0xf3e1ed57, 0x1073c23d, 0xc79f0e4f, 0x69cfd861, 0xdd322b53, - 0x38f7cfc8, 0x7207a87c, 0x827df56f, 0x22fdd574, 0x0afbbcfa, 0x171801d8, - 0x27b77b9a, 0xb724f907, 0xd4a3eede, 0xd01894c6, 0xb30ab96b, 0x31a29a61, - 0x0c698ec5, 0xbd9a61b3, 0x354fd850, 0xe0fd9137, 0x786bf1ca, 0xd36e79bf, - 0xfbe35ff3, 0xb7784af9, 0xdcabe064, 0xa3bfb7a6, 0x3f3e7673, 0x565efdc5, - 0x9fd699a7, 0xf0cdeac3, 0x38668de5, 0x47866c33, 0x65c333ee, 0x67683638, - 0xe11ef88c, 0x86569d9e, 0xde2b2bdf, 0xf438a56c, 0xa0ae7157, 0xe93b5e78, - 0x4dc509c5, 0x712718d9, 0x05a745fc, 0xfe3b95fd, 0x59c532fa, 0x658a6e74, - 0xfbb86718, 0x831618d3, 0xed9bbc71, 0x18bf30eb, 0xd9fe8768, 0xb5f6cde2, - 0xedb34f18, 0x434f9d52, 0xedb50f14, 0x4bbcfc6f, 0x086b06e7, 0x6f8e2ee3, - 0xe445fe7f, 0xfa1be3cb, 0xaaf61d93, 0x7d60b414, 0xdd3847c1, 0x3ebd08c7, - 0xe2f5e846, 0xfc7af33a, 0xaf6e970a, 0xfce287ba, 0xe3812637, 0x2fb2b5bb, - 0x2577c587, 0x8c6dfb74, 0x40dd67b0, 0x7687cfcf, 0xd08879d3, 0x7ba179cf, - 0x6bd11f35, 0xb3ea0c41, 0x0cdaa38e, 0x5c5d4bf4, 0xcea3c663, 0xcc8497df, - 0x24ba27cf, 0xcf0ce7a1, 0xc55e3033, 0xe71524b3, 0xdfa367ef, 0x8bbd7f53, - 0xbc2f19db, 0x20f2e9a0, 0x992a7b8b, 0xb2ae70c7, 0x79b3ef5b, 0x089e31fd, - 0xfbb035e9, 0xbb447179, 0x2eb1fd7a, 0xda5fcf2e, 0x448279f8, 0x95638781, - 0xe86ec8fb, 0x7d2b23b2, 0x380689be, 0x727766af, 0x776fe12e, 0xf986bdf2, - 0xdec364aa, 0x4e30bbe4, 0x8f414eae, 0xe3b92b36, 0x498f9fb9, 0x3d72e7c4, - 0x11f313f6, 0x6ff56d8f, 0xd81cb0b8, 0x718c23d9, 0x5735f967, 0xe41a26fb, - 0xb9f287fe, 0x3712b74e, 0x392bcbc7, 0x9cf093cd, 0xff0d7148, 0xfd71618e, - 0x80dcb76d, 0xcfcd5ef8, 0xcc2b67d3, 0x963c832f, 0xfaedb96c, 0xfcbcf061, - 0xec5e5199, 0x2b71540f, 0x78de2f3e, 0x3d15ce92, 0x8efee16a, 0x0504fa48, - 0x13fa3d9f, 0x39ea0147, 0xcb75efa8, 0x9f7f7a08, 0x239bec05, 0xdcef83e3, - 0xb38e4505, 0xa06f0ffa, 0x9f3330f8, 0x684bdf02, 0x97ae75bf, 0xe9e8ebbc, - 0xd19becc2, 0xa02df754, 0x8fc87978, 0x0c297eba, 0xa489eb99, 0x6fc16aef, - 0xe4621bf0, 0x7d72c893, 0xdce904a6, 0xd07cc974, 0x43ff0693, 0x8a6aa1c9, - 0x076c8dcf, 0xc1985823, 0xe181da0e, 0x9b972875, 0xfc169c78, 0x88b65b24, - 0x61c41f63, 0xf915c7ba, 0xf8a21811, 0x83d13652, 0x4d99bd78, 0x37d754c6, - 0xc3f5396d, 0x52abfcb1, 0xa2bf73cb, 0xe7249cfa, 0xdd30ee6d, 0x9c4fdb6f, - 0x70f36f47, 0x8feeff58, 0x64d45f9e, 0xe3aeb8a7, 0xbfd23427, 0x149e300b, - 0xb768bfcb, 0x3d68c058, 0x78cfa5be, 0xab6e538c, 0x1fa5f7e7, 0x5e33efab, - 0x1ebccb3b, 0xf9f44fa9, 0x39fe20f6, 0xbe7afd1a, 0x83ce1726, 0x771c788b, - 0xcc8a9f4a, 0xd274288a, 0x2ad44bdf, 0xd3fd7132, 0xbbc38f79, 0xcc14f08e, - 0x9fefc850, 0x5c9a7e4a, 0xe83a9fe1, 0x02edbff6, 0xaca139ba, 0xec25fe0f, - 0xdfa1d793, 0xfbd90bf3, 0xf7507b80, 0xacacfd3e, 0xa3df9d00, 0xfb40f40f, - 0x56161533, 0xe266df80, 0x609c353c, 0xae674f9a, 0x719e2896, 0x78f372d6, - 0xe36ebef0, 0xaac05afc, 0x5622dea9, 0x6ac1694f, 0xce217e73, 0x273c2e47, - 0x8a76e3c7, 0xfaf9cd6a, 0x8d92c0b9, 0xf0d1ac67, 0xc7d335f6, 0xc702fbe7, - 0xa36cdd27, 0x2ab7ddfe, 0x6977ef8e, 0x6df387cc, 0xe9272ae7, 0xa01662ff, - 0xe629dc7e, 0x7307f2fd, 0xed20b37d, 0x37d33f98, 0xcb9e0fab, 0x2d23f3e7, - 0xf99e4919, 0x13c57ebd, 0xbf007859, 0xbce187cf, 0x8524dc5b, 0x036c2187, - 0x9fc11d51, 0x3826bde3, 0x3679e37e, 0x6e38fc7d, 0x3ef673e3, 0x9e116fa7, - 0xb8f9929b, 0x0225f98d, 0xad1b251f, 0x98d17f26, 0x79d0528d, 0x6aaf9e39, - 0x1acaf7a1, 0xf54d58ce, 0xec1d798a, 0xba076601, 0x2b58298d, 0x755660e3, - 0x25d0f1e9, 0x1ccbced1, 0x755c7810, 0x945f5e5b, 0xbed1c7db, 0x9d1027ed, - 0xf84a7a43, 0x06d858a3, 0xec8cc5ed, 0x7b3f2982, 0xe2938721, 0x26a6bd1e, - 0x4a2fbe8d, 0x653361fb, 0x0e789bff, 0xd03e32b3, 0x99da0e37, 0x2ba5f169, - 0xc1bebf24, 0xcf9d6fe4, 0x88e4f0f1, 0xa22a4b8a, 0x3a75b7ac, 0x53d5213f, - 0x3b70409c, 0x599da79f, 0x20c06a9d, 0xb8e32317, 0xd3db8cbe, 0x3a8fe742, - 0xfe744ab7, 0x20e929f9, 0xea7e0f9d, 0xff430f5a, 0x09d02a40, 0x1253eff5, - 0xfcf7845b, 0x34dc3565, 0x73a40de7, 0xe3178c56, 0xc61b4a0f, 0x1a0ea5c9, - 0x62e3b73f, 0xbee2d62b, 0x218cca54, 0x61df9023, 0x866e33dc, 0x3ce3a3e7, - 0x075f5ed4, 0xc2ea7ba7, 0xa1dcc660, 0xce7fbed8, 0xc38f281b, 0x7cbce862, - 0x99cae00a, 0xb432e940, 0xe65952cf, 0x5333b46e, 0xa04678a7, 0x8b957f4f, - 0x916493b7, 0xf684dc67, 0x270e08e3, 0xd6f92c3c, 0xa0ae1311, 0xfcac5276, - 0x1cf87a93, 0xfa1b4ded, 0x7a061c27, 0xc4c8a84f, 0xf10653f6, 0xa70b5134, - 0xbbfb3d61, 0x75a01ee8, 0x23373cc8, 0xbbef3d7d, 0x2eb82971, 0x0b06dfdc, - 0xfb63d075, 0x97fdf4d3, 0xfbec83b0, 0xf2f0870b, 0x97994ec2, 0x24e7cfc9, - 0x15f6eba6, 0xfaa1d72f, 0x5ea246e2, 0xf9db8f7d, 0xe47c395f, 0xeb42bf07, - 0xa0803ce5, 0x58e9f953, 0x0bcc3216, 0x21bed3e5, 0xb4fcb3fb, 0xef1cf4cb, - 0x95c63509, 0xa1ec1497, 0xb2943bef, 0x509f3a66, 0x838e6f5a, 0x7a2622bf, - 0x979f3abb, 0x3059969f, 0xf99abb6a, 0x2c3ee9f9, 0xb95a27d8, 0xd3f3f364, - 0xfc6e1992, 0xe8539456, 0x7169cb39, 0x0a71fae1, 0x67a847ce, 0x7aa09642, - 0xda5d3779, 0x79a62ddd, 0xe1c3dda8, 0xa8bfb10e, 0xb7f5ebe7, 0x39c4d34f, - 0x7bcf7e3d, 0x2028255b, 0x4dd3cfc0, 0x5ddfc927, 0xf09bb4d2, 0x3745f3a3, - 0xd059629e, 0xaae4a780, 0x6405b0e6, 0xfdb8e9fc, 0x025e874b, 0xcba3d924, - 0x7d4b3bf3, 0xbf1f2163, 0xef90616b, 0x792eacd8, 0xcab37527, 0xf0fd0b22, - 0x6389d2ee, 0xdf2f308d, 0x35f37efd, 0xb2b78113, 0x6bf7f286, 0x6b7bdee3, - 0x7506c621, 0x4ce83b9d, 0xb00d3bf7, 0x0076022d, 0xbb00cc3c, 0x2313f223, - 0xe02353f2, 0xcdbe5e34, 0xbd974e19, 0xfb8e6d8c, 0xf4051ae0, 0xf0df5b5c, - 0x6479bc74, 0xd747d579, 0x4b8ef7e0, 0x7bf7f8b3, 0xaf249acb, 0x65a3d064, - 0xe4871e5e, 0x3368b6f0, 0x9a1e2287, 0x507d44df, 0x71b928d2, 0xdfa8e0fd, - 0xdf182612, 0xabde18f3, 0x92d3ebe7, 0x5ef483fa, 0xb10ff5af, 0x3a3f3c90, - 0x772a73e4, 0x362dfdae, 0xaf3dfcc5, 0x52bbf6de, 0x50b7812d, 0xc7f7eadf, - 0xa8f96db7, 0x20aa7bfb, 0x7d7ded7f, 0x469f497b, 0xc72f5b9c, 0xe5ba38fe, - 0xa3e3c745, 0x7dd14e43, 0xd6187fba, 0x079a01f4, 0x2e4ef3b1, 0xff75abc0, - 0x14787a54, 0x27785fda, 0x4f1fce2f, 0x704ba148, 0x059a7a5e, 0xef76c12e, - 0x3768bd29, 0x80ec6a7e, 0x5e0cf2da, 0xdc4df309, 0x01ffc249, 0xfc00cb67, - 0xc7e9dd64, 0xa4e1c2ff, 0xe609ba16, 0xafefeab6, 0x1ecdefc1, 0xc032d018, - 0x8ff7f002, 0xe0993a5f, 0x419e5a8b, 0x04eac2f8, 0x196b0f0e, 0x03fbc320, - 0x23267d83, 0xa3bbd6fd, 0xa109fdcb, 0xc5fef46f, 0x891df60e, 0x84aafb43, - 0x2c783bcf, 0x757a06da, 0x4db1d17a, 0xd31f01eb, 0xf49623ff, 0x5bb6fadd, - 0x1e13f3ae, 0x6f8c7e82, 0xa6f8114c, 0xbbf49179, 0x5f44f642, 0xba130b9c, - 0x6f4ce9e9, 0x71bcd0f6, 0xb416c569, 0x0fa6521f, 0x55e379a5, 0xee27ef97, - 0xe9e9dd51, 0xc4fe9e24, 0x5bfae6ed, 0x46bc50b6, 0xb24e43ca, 0xdf171eab, - 0x23b90067, 0xba0870fe, 0x3c7cdc58, 0x73190dff, 0x80001bd1, 0x00008000, - 0x00088b1f, 0x00000000, 0x7dddff00, 0xc594780d, 0xbbbcf0b5, 0x26effeef, - 0xb24d9bbb, 0xf379f909, 0x71100843, 0xa9189313, 0x18884dd6, 0x220bb531, - 0x49716b62, 0xc93049f8, 0x2d16ad46, 0x544859bd, 0x46d10882, 0xe1b80a04, - 0xfd2b6202, 0x1a8c4582, 0xf68882e8, 0x72dfbd2b, 0xbd3fadeb, 0x8a7e1bd7, - 0xb4564288, 0xeb6dea5c, 0x2666739d, 0x5c9377d9, 0x9f7b7aa8, 0xbe8f8be7, - 0xcef33bce, 0xfe73399c, 0xb3339ce6, 0x9086bb1a, 0x258e4264, 0x4ec730dc, - 0xe631df9f, 0x224c9d15, 0xf433bba4, 0xc84b499c, 0xc421127b, 0x09f04845, - 0x0e7b6853, 0xd1eddf21, 0xb4897504, 0x734de1de, 0x44b2d116, 0xc345bd7c, - 0xd57fbde5, 0xd2b3e5de, 0xd32d3172, 0x9912abe7, 0xbd33f58b, 0xfe5a0e69, - 0xa7aefe02, 0x9f561ee5, 0x58ad25ae, 0x7fbec39f, 0xe5dc84aa, 0x76d4cfa3, - 0x7d296e3a, 0xb5b89dae, 0x916b8e9d, 0x0bca1789, 0x5d6c16e7, 0x736a614e, - 0x897842cc, 0x51269bd7, 0xe6364ef8, 0x76d1566a, 0xc8afa7bf, 0x515c8435, - 0x97b0cde0, 0xff40f9d1, 0x44d21c74, 0x3c369527, 0x37981cfe, 0x7ad7afad, - 0xcf3a64b3, 0x39fe1ddb, 0xe35ebed0, 0xd0b4429d, 0x77c0b789, 0x8823b405, - 0x3b76399f, 0x40f227b6, 0xffffbc19, 0xb8954f08, 0x4f115fee, 0x7534ef77, - 0xf8242c9d, 0xb7fd05f7, 0x2aa1d7b9, 0xbad2fa07, 0xcb871a4e, 0xd0ffc377, - 0x24ad4871, 0x2c3a1493, 0x8d6e22ab, 0xbfe836ff, 0x7a07e979, 0x513781a2, - 0xf02ff43d, 0xeb0a4ebe, 0x82fce952, 0x76cf24fb, 0xb2cfdec2, 0xe8959211, - 0x21e613bf, 0xc3f79ee0, 0xd17f34e6, 0x3f2c7cf0, 0x76e6a978, 0xe4b79c5a, - 0xf4edaecc, 0x590f79fb, 0xdb865108, 0x9d711ed3, 0xb8cf7fdf, 0x9f495c9a, - 0x86b0defa, 0x19fdebe2, 0xb69cb3c4, 0x1a435f7b, 0x73efff00, 0x743f95bc, - 0x853211f7, 0xb5d95f90, 0xd0499df8, 0xbddbe483, 0x53b7e288, 0xd0234122, - 0xd23d4cc3, 0xd28860c3, 0xfeb095c3, 0xfbe87d74, 0x872707ee, 0x067d7482, - 0x619100c9, 0xbec4153e, 0xbfa9895d, 0x29eb00a3, 0xb44d049d, 0x0e68da3e, - 0x5e80956d, 0x50a5a028, 0x5feb093f, 0x07fad895, 0x38e230ef, 0x1d1933dd, - 0x433a3776, 0xb6001cc1, 0xc6de008b, 0x7694a3a2, 0x64487482, 0xb69994ef, - 0xe36c7c61, 0x3a52c172, 0xb4dbe2f0, 0xe4dab23f, 0xb01f4f19, 0xbb943284, - 0x4a3c7152, 0xbe91ab0f, 0xfd470664, 0xab42d38f, 0x394f5c70, 0x36a3cbac, - 0x1f787cef, 0x014591fd, 0xc89937f8, 0x7d09634a, 0xe8c3a44a, 0xe1c0eba4, - 0x134f5d21, 0x60bb83a0, 0x7f878a00, 0x536f386f, 0xd89ffbe8, 0x08038425, - 0x484e58cd, 0x75f5611d, 0xa4c72ccb, 0x86d4f029, 0xddf4090d, 0x03bc1bca, - 0xd972be82, 0xf3fb48d3, 0xeb22ba73, 0x83c036a3, 0x804bbe1f, 0x29b73ffe, - 0xefd32856, 0xd3f2c0a7, 0xbf870bef, 0x7df039ff, 0xe0c7c019, 0x65166d27, - 0x1f8c34bb, 0x80b9fcf1, 0x6f69ebaf, 0x9c6278ec, 0xd98f7ef8, 0xf007ffbd, - 0x4e1ef145, 0xb45e0174, 0xf0f1aeb8, 0xc7d1f4ba, 0x5e7eb44d, 0x82b1d69b, - 0xd4bfd3e2, 0xf015f386, 0xbd1a95de, 0xec8de48e, 0xa5a594ff, 0x2ff9865c, - 0x964f7465, 0x62e22819, 0x2e1fa2f1, 0x485dd253, 0xd23587a2, 0xf0e5ef28, - 0x517f8001, 0xf8f7cc77, 0x621abfdf, 0x21be09db, 0x3f07148a, 0x92452ba7, - 0x12fcdd61, 0x3ebd375b, 0x56e40f3a, 0x9f02dc3c, 0x8de5c6ff, 0x7c788ba0, - 0xbbe01bff, 0x5dbe246c, 0xe84c81fa, 0x80d4bfd7, 0x9fef8a78, 0xf77e1090, - 0x4d0489b4, 0x4bd6ee94, 0xfaebd212, 0x90212d07, 0xe8a6839b, 0x6067c00e, - 0xdeb88dff, 0x0acd1ae7, 0xea364da1, 0xf705bf19, 0x171f18db, 0xdc80140c, - 0xece7473b, 0xee73eba5, 0xa09eda37, 0xa4208024, 0xadda37e5, 0x5ee7ff40, - 0xb3f589be, 0x5a10a2dc, 0xe986000e, 0x7fe081b8, 0x578a11b6, 0xc7119669, - 0x0a57b13f, 0x8fbea019, 0x5e4639e2, 0x36ffa39e, 0x8dcb0c94, 0x3800a841, - 0x07082cfa, 0x8e23699d, 0x59335df7, 0xd16fc745, 0xad0d5e48, 0x2932596f, - 0x31e0ced4, 0x16d5cac6, 0x4a90e90d, 0x45bff986, 0xdee0bc73, 0xa7275622, - 0x60ac7970, 0x851243bb, 0x3ab8c9b3, 0x05fa05a2, 0x4bf5a03e, 0x78673ea0, - 0x7f565a1d, 0x479817f4, 0x7d351ecb, 0x9eaf3d34, 0xba5892c7, 0x17a619ca, - 0x17c3294b, 0xf1a126a9, 0x2f1b5e14, 0x21226a5b, 0xe963e02d, 0x2ae27234, - 0xc0e0f4da, 0x5b23a074, 0xa3a92f69, 0xe269c0cf, 0xa7b8510d, 0x36bcf7f6, - 0xd477b68e, 0xba613244, 0xcdbfa581, 0xf0d5793b, 0xaf380b3a, 0x4b427fe9, - 0x7e1e38ac, 0xeef14147, 0x89bb62b6, 0x7d88aeb3, 0x92efc0ae, 0x0f2f4c35, - 0x1fe02bc0, 0x75cde999, 0xfd526f5c, 0x617af28a, 0xafd404d7, 0xce40ffa0, - 0xf4c0953d, 0x903dc831, 0xaa8e6d33, 0x9e741cab, 0x14d56766, 0xc71b1947, - 0x27e98367, 0xa788fea1, 0x243d78eb, 0xb5e6a5da, 0xc75ab716, 0x0cf9476e, - 0x90dd16f1, 0x2c88e4c8, 0xafd17961, 0x10ab3d75, 0xe6e9193e, 0x2839cdde, - 0x97481b97, 0x89bce81e, 0xc740f484, 0x98248c8b, 0x1162e940, 0x9f48966d, - 0x881bd78b, 0x8d7eb312, 0x89b97521, 0x49bb85cb, 0x7bbfbf04, 0x357d5c67, - 0x7d68db09, 0x2d8491b3, 0xd755ecf0, 0x8e7d50b7, 0x85f7d67c, 0xe93df621, - 0x8bbdf366, 0x3aa3bbaf, 0x79d3f5a4, 0xdd51306f, 0x5d0684ea, 0x97533eb8, - 0x267ae0f5, 0x1e737896, 0x2bf2bd06, 0xa52b679d, 0xf5f03fdb, 0x6639f812, - 0xbc00aaaf, 0x9c1ab59b, 0x0361f47f, 0xd524e7e2, 0x6bfeb0e3, 0x59aee41d, - 0x8dae79f4, 0x8075f378, 0x2cd67b26, 0xaf3c48db, 0x00d4c57a, 0xd0e0d374, - 0xd32ae8a8, 0xf972c3a1, 0xe5ff8e0a, 0x1cd6d096, 0xa014f744, 0xa15cf2a7, - 0x9994c957, 0x474c7cb4, 0x6e5a3bed, 0x43f56399, 0x4f60037f, 0x0efdf2d0, - 0x77eecf26, 0x453d71e8, 0xd057cc59, 0xfb071d0d, 0x9ec55f33, 0x43658e02, - 0x74609fed, 0xbaf0f5c3, 0xea0f7346, 0xd5fa21e1, 0x22dfa410, 0xfaf01e9f, - 0xf32b970a, 0xf8a16ec1, 0x1412857e, 0x2f608fc8, 0x3e295fb3, 0xe5a52de6, - 0x79174e57, 0x67402956, 0xf2bcde4c, 0x4159331d, 0xccf37c87, 0x27fb1f4f, - 0xb4fe7f5a, 0xfad0315e, 0x746b4005, 0x88915efd, 0xbe0bc617, 0xbe810868, - 0x7b33d26c, 0x15ff69b4, 0xfbd19ecc, 0x71842c37, 0xc079d05e, 0x084a69de, - 0xeb03b73d, 0xa2943cd3, 0x863aabc9, 0x16cbe0cf, 0xf439bdf6, 0xa0bb9fb3, - 0xa413d53e, 0xff26a3ed, 0x74d75846, 0x7a889283, 0xc25ad7f9, 0x381709c6, - 0x878f5e28, 0x9c7ddd98, 0x4e304956, 0xa1fb0dbf, 0x90b69a7c, 0x33a273f6, - 0xe543e715, 0x2759da2f, 0x82b618d6, 0x34375dfc, 0x8fed84ae, 0xd3d37ceb, - 0x8bf8f968, 0xb4e59ec5, 0x0fa7d06a, 0x073d29eb, 0xafbb32d6, 0x016ca35e, - 0x16fd90fc, 0x8f58879c, 0xb5c59ac0, 0xb2581f50, 0x8f9016ec, 0xc839f163, - 0x3723127b, 0x166891cf, 0x86c6d3f0, 0xe830dedc, 0x1e89fe95, 0x4dc4af54, - 0x8dd29f17, 0xa93db59d, 0xee8df863, 0x5f3d21d3, 0x1740ff6e, 0x43d33972, - 0xca804e30, 0x0ff82265, 0x594c72e5, 0xad995a3b, 0x5495e063, 0xeba9df6e, - 0x47fc1253, 0x9e5a5d60, 0x97f78ffc, 0x145e302a, 0x4ae922e5, 0xa93cbe46, - 0xba03cef3, 0xf5875475, 0xfd7a3175, 0x99d983a4, 0x076e06f5, 0x963eb092, - 0x797d450f, 0xc5ee9a95, 0x7fa704f3, 0xf7c9845b, 0xce1af591, 0x401ab71f, - 0x20654d8f, 0x23d06c93, 0xc15fe856, 0x0e9ea7fe, 0x3969ebeb, 0xbf58597b, - 0x4f813f88, 0x46c3be28, 0x1b93ef3a, 0x29bf8c6c, 0x459fa01a, 0xe5f50415, - 0x63b52d22, 0xd2bde04b, 0xe5d74037, 0xa40e8bd4, 0x8a67f22f, 0xf9ef8a15, - 0x5033b784, 0xb1ca97bb, 0x30a43a97, 0xafe60bec, 0xe5356c37, 0xb57b5f00, - 0xcdcf5836, 0xf9b1ca12, 0x1b05951d, 0x9ec97968, 0x13fd702b, 0x2e5d182a, - 0x2f503909, 0xb1f2e54e, 0xa3d210de, 0x8933fe1d, 0xf6883ec0, 0x1374f68f, - 0x64ad28fd, 0xae401e24, 0x1421e8ab, 0xd1f6a653, 0x57265ed4, 0x24e79509, - 0xf2126ec6, 0x8938e41e, 0xf4d503b3, 0x88fa1411, 0xa4a23dc9, 0x7213dc82, - 0x97dd98f9, 0x3e3b44e8, 0x97d6153f, 0x9b9327ae, 0x6bc425bb, 0x7d456933, - 0xd0c0f422, 0x9c8f5cb8, 0xbe9906d2, 0xcf813c32, 0xae0e677c, 0x8bd212eb, - 0x95e844fa, 0xdf20e8b1, 0x88fbe1a9, 0xbc60e9d1, 0x9afec153, 0x75f0934e, - 0x65a6bc74, 0x853cdc24, 0x50536d3d, 0x693d323f, 0x9e127a64, 0x97d0cbe6, - 0x5e31faf1, 0xc1ebc61f, 0x77d33d54, 0x3d859d62, 0xd98d3a93, 0x85975301, - 0xfc08a4b4, 0x94eade35, 0x26bb61e4, 0xa8d18ef0, 0x1f65095c, 0x9ef905c9, - 0x2a62f950, 0xc4c80fad, 0xa1657c0b, 0xefa1e978, 0xb7fb7337, 0xd7cd9527, - 0xabf467ad, 0xd8a47d93, 0xc112eb0a, 0x99346f7d, 0x051e81d8, 0xe8db373e, - 0x1df02577, 0xefa1b7e3, 0x1cc3a48d, 0x2bd57df3, 0x173fd426, 0x0c85b65e, - 0xb3f88f68, 0x94bfb41d, 0x4ed01bdf, 0x0d8af73d, 0xae39e9f5, 0xefc25d0f, - 0x7e611e40, 0x41aebe16, 0x008e3552, 0xc6334bed, 0xf6140881, 0xd983b359, - 0x21ed2359, 0x99139f5e, 0x80cae8c3, 0x8e0bcdfb, 0x4ca00781, 0x7fa021e1, - 0x7e32716e, 0x5699ec0f, 0x3efa43fc, 0x187ab3e0, 0x40c5fdf6, 0xf7ed06af, - 0x7d2918e7, 0x8b2ed74d, 0xd1e7483e, 0x83b5699c, 0xfeceab7e, 0x41dddfd7, - 0xd1ee1fcb, 0xf3ac0311, 0x497369f6, 0xb7f2d8ee, 0x3e3ba431, 0x772fc310, - 0x9b9754ef, 0x40e5d57b, 0xbf7cba9f, 0x653ae6d3, 0xf9e1d941, 0xc1b5d282, - 0x87ba7ad0, 0xd5786bc2, 0x8668fa80, 0x1390ffd3, 0x7a26ade4, 0xc86cf018, - 0xf80a78fe, 0x9ffd023b, 0x5034f048, 0x31148a36, 0x5f5f03fc, 0xb6cfcd30, - 0x61b7828f, 0x06a311fc, 0x75ad4cf1, 0x173944f6, 0xd2e27ce0, 0x403c3f7b, - 0x9668bfe7, 0xdf02bed9, 0xcacb6b78, 0x18449ec1, 0x4dfd6049, 0x8bbec21f, - 0xf5846bb6, 0xb693353f, 0xac3570a3, 0x89b0fa67, 0x6f801244, 0x69dda85b, - 0x1bfc4ba4, 0x77776fce, 0xf4c3cb44, 0x359dbb7f, 0xf94e0113, 0xe80fb22f, - 0x37e851e3, 0xeade4ec6, 0x4bfc7264, 0x463299fb, 0x02b699f8, 0x038d9afe, - 0xfe3a4afa, 0x0cf97ff5, 0xa5e2fde5, 0x823ee1af, 0xb33e63ce, 0xc80a4dab, - 0x1e0fc5a7, 0xdf62f7c0, 0x8ad32a76, 0x36d7b6fb, 0xa1d95818, 0xcda9f2c7, - 0xb8b95f6c, 0x3cc10a57, 0x931759a5, 0x6c2f412a, 0x640dd9d6, 0xf1e35e24, - 0xb7a6c1f8, 0xf5efc013, 0xf61d2201, 0xc7b3127b, 0xb809adec, 0x135a507f, - 0xac0cbec0, 0x9043f1bf, 0x6b378b8f, 0x902f603d, 0xcff4367d, 0xc37cde2c, - 0xe85685c4, 0x4aa4d3e7, 0xb96d13f0, 0xd0543c01, 0x7e6217ce, 0xf4f5c89e, - 0x6ae5bcbd, 0xd0f1f805, 0x62ff0666, 0xd0077187, 0xd17ff5d1, 0x1ac97f22, - 0xb93b07e2, 0x089def5b, 0xda6cad7c, 0xe7d61d3e, 0x1ae99983, 0x224bbf6c, - 0x638bc076, 0x5fbc0a69, 0xe03ec92c, 0x8df586e3, 0x4f76b1b5, 0xc7f9939d, - 0xa597b32a, 0xaf91580c, 0x6d3e80e6, 0x08f94cde, 0xdef59fc6, 0x0d70eeef, - 0x6b3495f3, 0xa1532dfd, 0x1e7567ff, 0x7b21bbe0, 0x90b7d366, 0x4c2fe0be, - 0xe398b5f1, 0x99f2abeb, 0xa4f822c1, 0xeae400b5, 0x05ad15e2, 0x8cec51f6, - 0x44d93e21, 0x213272f9, 0xf9129da7, 0x1993fc02, 0x63bed54e, 0xb59a7dac, - 0xc67a8350, 0xedde21e8, 0xb74a99f4, 0xb71fb0c9, 0x6f58c925, 0x7d23d24b, - 0x77ba7fcb, 0xbce86fe7, 0x2ffa749e, 0x26ccbe80, 0x6bd062de, 0x455ed44a, - 0x35405acd, 0x136461da, 0xcc89afb3, 0x92eb85fc, 0x31558ec9, 0x125373fb, - 0x39504fdb, 0x73f405f1, 0x1f3fddee, 0x64b6fc06, 0xec053c7d, 0xcfc5c085, - 0xb35fe0f4, 0xdf284bf6, 0x011f1ead, 0xcff409ba, 0x868a0b24, 0xc3c072e5, - 0xbcfc46f4, 0x98e924e6, 0xb145751c, 0x82974a9f, 0x41076ee5, 0xd4b8da7a, - 0x46fef68c, 0x4004c857, 0x2b7cadff, 0xee46a7ec, 0xfb6e340f, 0x740b5785, - 0xe3ec921e, 0xfe30aca1, 0x17986c18, 0x3e71d2d2, 0xc41796dc, 0x8f4a9ef2, - 0xb759d696, 0x5ccae3fd, 0xce9f53c0, 0x9eaded03, 0xdf980481, 0x244edb87, - 0xb61afcc0, 0x0dde7169, 0x16524fa1, 0x09cb0d16, 0x905fc69d, 0x5d827604, - 0x42f8c2b2, 0xedb87c5e, 0x560594d3, 0x7d403fe6, 0x5e3a3a5a, 0xc9cacecc, - 0xdff5fdf0, 0x6672eb64, 0x72042197, 0xf9898cf0, 0x33bb45f7, 0xaeffa636, - 0xcdfe124b, 0x3fd02cde, 0xa2796543, 0xf7c4e406, 0x2efe6ced, 0xf0166f7d, - 0xba9247e5, 0xb52b259f, 0x52e54424, 0x84894ae3, 0xf33fcca8, 0x20594bdc, - 0xfedc3fff, 0x0c5d5652, 0x89dff17c, 0x6a498de7, 0xaff09a7f, 0x0ce1f4ba, - 0x63ceaf18, 0x31cc7e60, 0x3da2abfc, 0xa4fccf59, 0x816b9483, 0x8377c50e, - 0xd82f660d, 0x18c483bb, 0x5d5b9702, 0x7ad7f73f, 0xd82ef9bd, 0xe3ef88d7, - 0xf40d5ffa, 0xfa92e144, 0x5827f424, 0x9f28a28a, 0x77fcb4bf, 0x918cf5d1, - 0x8d9d74ff, 0xc6cd4eb0, 0x0471e1e8, 0x780f43e9, 0x6558b7d3, 0xed2957d0, - 0xf7a2be8c, 0xe59f706b, 0x814c2732, 0xdd3e80b8, 0x76f9056d, 0x43b9817d, - 0xb3ef0893, 0x333ed042, 0x0bbf10bd, 0x0ffa3156, 0xc3f410a6, 0x095691a5, - 0xe676b4fd, 0x20a8cfe7, 0xf8b455f6, 0xe76624b3, 0xbd6789b8, 0x5fd70f36, - 0xc70738c2, 0x400fd08b, 0xcf2f2047, 0x23a44648, 0x7b425fa9, 0x9de9ab54, - 0x458efd07, 0xbac52b57, 0x2a1aba72, 0xeae89dff, 0x23c74149, 0x20afcae8, - 0xa38db95d, 0x23f715d3, 0x127b765f, 0x36bec1f4, 0x2d6be395, 0xfbd13f97, - 0x2eafc28d, 0x796b7cc1, 0x6b46b57f, 0xc47a0b58, 0xd638fba3, 0xda89bc3f, - 0x4a7fb0c5, 0x3e9ebb03, 0x57cfb5c7, 0x6448dd70, 0x9608fc00, 0x2fa88dab, - 0x7244d31f, 0x9d498ec0, 0xe81bbad4, 0x515e7523, 0x0bee3b49, 0x17a01c33, - 0x7fa2d740, 0x1f34e974, 0x1c5823b3, 0x8f533a28, 0x07969cfb, 0x8ecc7d2b, - 0x097e41a8, 0xa02936ac, 0xe7f5a707, 0x08fa072c, 0x031e232c, 0x86cf71d2, - 0x9dcfe045, 0xac80f56d, 0xb225f113, 0x9d77cd52, 0x05538b12, 0x0f18226f, - 0x0d338e1b, 0xe821f96c, 0xf422c6ff, 0x8ff90c9b, 0x8dea09f3, 0xd6438dcb, - 0xde2136ad, 0xd068fc45, 0x25741146, 0x3fb191fa, 0x7a646892, 0x407ca468, - 0x054a73ff, 0xa1eb7f11, 0x3cca2e9c, 0x5ff823de, 0x456ca3c4, 0xc8b01cbe, - 0xbf399c2b, 0x049c4332, 0xb36c77fc, 0x00fd8416, 0x19598dfa, 0x694fcadd, - 0x50e92028, 0xaaab9ffb, 0xbcca6233, 0xc1f7d0fd, 0x5f573755, 0xa877fa8b, - 0x7aa6c01e, 0x26bd9459, 0xc355e205, 0x83b532f5, 0xff127d8d, 0x1be6e2be, - 0x941eaaa8, 0xee7ff8c4, 0xd11f82f4, 0xc5e35444, 0xf5c727c2, 0x5bfda3af, - 0x383ede15, 0xefe826ee, 0x7e5112a9, 0xe14bd3a0, 0xf753ab5b, 0xdfe52887, - 0xf78c4143, 0xaf0e537f, 0x6c319d5a, 0xe17b501f, 0xc36549cf, 0xefa3c276, - 0x495d76d5, 0x3fd8b2c7, 0x15fe83d5, 0x92e03efa, 0xe7890ed0, 0xf49704d7, - 0x656becd5, 0xe09d7d84, 0x74f5f662, 0x2fba4960, 0x581df941, 0xdf6023e6, - 0xe9c4bb52, 0xe3e4bb42, 0xfd680753, 0x1f9f59b9, 0xbb40a71e, 0xbec1e67b, - 0x4651702a, 0xa9d81bf9, 0x6f94490d, 0xaeccfd8c, 0xe31cfaa6, 0x967e8205, - 0x38fd39d8, 0x97fc0482, 0x32a4fbdd, 0x5a4277a0, 0x6ba36eb3, 0x379703f9, - 0xfbe1c713, 0x9779f8cd, 0x205f98bb, 0xa1b55850, 0x26dffa00, 0x5617b011, - 0x594f1e15, 0x63a9fb80, 0xbe630b29, 0x0a7bec6b, 0x53b8d9f1, 0xcb1e2a37, - 0x7804e1a9, 0x45f9796c, 0x338dc82f, 0x42650921, 0x04ea1c83, 0x41a1b6bb, - 0x29211603, 0x03bfcd0d, 0xf5731fe3, 0x5f9d3c64, 0x8177d706, 0xa706b79d, - 0xbfe9bcc2, 0xd1b57d12, 0xc4e508b7, 0x2b46b9c6, 0xeb0a91c6, 0xd83c41ee, - 0xc3c05ecd, 0x34aac2aa, 0xe665a718, 0x4dc63b74, 0xf5073da8, 0x077e0f2d, - 0xae0245fd, 0x1aba7d55, 0xa9ca77b0, 0x0a0bf75d, 0x4673a677, 0xf5f2878d, - 0xe2eeed38, 0x5710acfb, 0xff8e5d1f, 0x174664bf, 0xf82f921d, 0x8ff452ed, - 0x677f5892, 0x1fb31f76, 0x55e9716f, 0x5c5bf1fe, 0x36bdaecc, 0xe4069918, - 0xb01e5fb2, 0x201d5d80, 0x5f604fde, 0x65567c4d, 0x9313ae3b, 0x0536ae5f, - 0xd74666fd, 0x425763c0, 0xee32b5fd, 0xf03c8867, 0x5cf71863, 0x8ab3cba7, - 0xf2803e70, 0x90214583, 0xfe5cfbc7, 0x96fac2ef, 0xdcf57b73, 0x831637cb, - 0x5fd8517f, 0x5099cf9d, 0x94da766f, 0x4e406b27, 0x796649fe, 0x6468c603, - 0xc967ed1a, 0xb71c4ee7, 0x84ea14d3, 0x68f60ff5, 0xeac9beb1, 0xdbf4045f, - 0x29faeb78, 0x0d608798, 0xd51e8015, 0xd008bab9, 0xa0bedd31, 0xf2e8c51f, - 0x4f238811, 0x2597ce0b, 0x767117d0, 0x63f034cd, 0x85c5bee1, 0xce2adc7e, - 0x1529e31f, 0x2b22329c, 0x34917c74, 0xf9bce76c, 0xbc32d9e7, 0xc68ff614, - 0xd5eefcc8, 0xec04cd73, 0xf448f25c, 0xf8fc06b0, 0x7b0108ae, 0xc257b9b8, - 0x5f0b9a71, 0xe5fec3d0, 0xdfc65eee, 0xa0dfbe01, 0x78c2cbf8, 0xedc2cb94, - 0x67460e81, 0x1c787224, 0xb679f9e0, 0x76d0849e, 0x42577e31, 0xc0793396, - 0xf8f3d3fb, 0x37f73343, 0xf5884d51, 0xcec25cab, 0x5b8ea158, 0x49d771f0, - 0xf016af11, 0xfca92c5a, 0xc3d9e2e4, 0x183c4fbf, 0x1bfc0e9d, 0x7e05f4a5, - 0xccd20da7, 0xf3a75e7b, 0xc93650db, 0x9b98a603, 0x04b69392, 0xa45253de, - 0xfbed2f78, 0x0dd03a64, 0xafc821a9, 0xda957d2d, 0xeb8b2b66, 0xa58c5e60, - 0x53ea07b5, 0xfd442aef, 0x5993710c, 0x1cb3fdf4, 0xe65669af, 0x08af73c7, - 0x341c40e6, 0x9eefa0f1, 0x2bfc61d7, 0x4d87e8cc, 0x73636ba5, 0xf82573e2, - 0xf8a4dcbd, 0x7767e800, 0xf00252ad, 0xc41f7888, 0x0d16670b, 0x3d38e3e7, - 0x7d2b7792, 0x983976ee, 0x6a40cedf, 0x1f785e00, 0x1fc70eb2, 0xe3079fc1, - 0x9e0f7c42, 0x32c2d2e7, 0xc0c9fffa, 0xefb8ed96, 0x483e6037, 0xef1bdf6d, - 0x35adfe80, 0xc78c5e92, 0xd52dd9c6, 0x02beb789, 0xf6783ff4, 0x018796d4, - 0x7af6dbae, 0xce25ef30, 0x9bfeb91e, 0xb33f3ecc, 0x3f00a2dd, 0x9b72e56c, - 0x27c88fda, 0x3f6c5dc1, 0x1e476f19, 0x27f7a975, 0xddafe543, 0x05f0648e, - 0x0b3cb3b7, 0x7c03df21, 0x70d837ff, 0xd7f4013e, 0x13c10dbf, 0x8db20f97, - 0x8ff483e7, 0xe6f20f9e, 0xe8104b0e, 0x09af7ce1, 0x8f3292fd, 0x45b59d7b, - 0x7524001f, 0x01cf0e38, 0x72581b79, 0xca1ae7e6, 0x8b0f727f, 0x8f12c923, - 0x4b4afd33, 0x6bcc5c58, 0x808bff07, 0x774c765b, 0x3e408b7b, 0x713779b2, - 0xb39351bf, 0x2ef16140, 0x94d43796, 0x7b002e10, 0x87ae55ea, 0x5e2ccc9a, - 0x87d0e835, 0x26a35d61, 0x185d1fff, 0x93df62d7, 0xd8941a5f, 0x884f56b8, - 0x0a2775d9, 0x9d3d6135, 0x07d80f67, 0x59ab6eb0, 0x9f286b7c, 0xc7a1bf60, - 0x5890e2c0, 0x41ccec1e, 0xe22f5939, 0x3f99fb56, 0xa7c79eae, 0xf45acc4e, - 0x745ca40c, 0xb035ad48, 0xaab0bb3f, 0x0fe8fd12, 0x9f13393c, 0x7ed52bf5, - 0xa7e045ff, 0x238e1bcf, 0x1d7bff0b, 0xbd99e8f1, 0xd447ec3c, 0x5945fb50, - 0xbe815729, 0x15f621cc, 0x2095ff20, 0xe9abad5d, 0xc13e83b3, 0x12349768, - 0xa77239d8, 0xfbeb0ccb, 0xf5068768, 0xe343b054, 0xcf027685, 0x8fccc939, - 0xf3324d74, 0x0aa5d06b, 0xd9e238c1, 0x0771e3a1, 0xa272dfde, 0x2353c309, - 0x76a3e7b1, 0x7d3466b9, 0xd0ebfa2d, 0x4fc11ab5, 0xa0d4cd17, 0xde82fbdf, - 0xc6fd173b, 0x790202ce, 0xd6b61d54, 0x1eac3595, 0x2982e779, 0xebfac3ea, - 0x12486664, 0x33f209c5, 0xcbe79935, 0x616de1c5, 0x1f1cba97, 0xa90c698f, - 0x3fc4f5cb, 0xc58f2d21, 0xa7df620f, 0x75f93326, 0xc70e5561, 0xe3f307b7, - 0x6797fcc4, 0x3269bc30, 0xb33733d9, 0x41d02e6a, 0x7397c42e, 0xabfcc9e0, - 0x7f082674, 0x092e75ee, 0xde0e23e9, 0x80da300e, 0x3c593abe, 0x3f856ff4, - 0xe4caee1e, 0xbc1fae14, 0xd65f886e, 0x8f18f5db, 0x493f5cbe, 0x0e5ab25d, - 0xfebf950d, 0x27db2cfd, 0x9e796a75, 0x50e51d8d, 0xe5cd9d9d, 0x11d9e484, - 0x6a56f786, 0x3a3cc02f, 0x3f6025b5, 0x8ad5bb4c, 0x6fd968f3, 0xf3703f42, - 0xd02c81b2, 0x03552de3, 0x89b71005, 0x2b402fc7, 0xdb45f90b, 0xfee8b9d5, - 0xd884ec03, 0x4b5f3c76, 0xfef5671d, 0xf60cb920, 0xbf762739, 0xb76afa01, - 0xfd15f509, 0xf00603bf, 0x839cbcb3, 0x3687ccf6, 0x0bb41b7f, 0x9e5bc398, - 0x85bb01cd, 0xfdcd4dd9, 0x0bb01e86, 0xe2623aeb, 0xd59ff07c, 0x591fb8ea, - 0x3bff44e9, 0x6fbf56e9, 0xddf714d8, 0x17603888, 0xbd3af3ae, 0x3bf0227f, - 0x7f983bd5, 0x8351b670, 0x5af50379, 0xb79022cf, 0x7b6a4d67, 0xad8dacfc, - 0x75a196d7, 0xb5bda0f6, 0xf675cc65, 0xd73ac014, 0xb63f886b, 0x6758669f, - 0x7c4dbeba, 0x78becf9d, 0xf3ac0175, 0x2eafbbc7, 0xa75e7580, 0xdf02f2eb, - 0x5bfc39b4, 0x27bf6993, 0x3da1f06f, 0x2f58f225, 0x24f71e97, 0x432bfdab, - 0xff21ffe5, 0x30fa58ca, 0x5a87043c, 0x4af4ba1f, 0x3a83c806, 0xd5bfe1a3, - 0xaa37f08b, 0x4068cf1f, 0x3ffec77f, 0x0766ba7f, 0x2d7e81c8, 0xbfa223da, - 0x0f3fb2fd, 0xeffda1ec, 0x69413db8, 0xb91bfeec, 0x246dd85f, 0x88abf041, - 0x27b0807d, 0x5bf1e5e3, 0x251f3e7c, 0xbb006f7b, 0x8dfacbe6, 0x633bf81b, - 0xe76653e8, 0xcc3c936e, 0x7e8bdc6f, 0xf37d96e4, 0x3e27e0ed, 0xe37e621d, - 0xd18b1796, 0x7a18dc6f, 0x65790c2d, 0xc3b25fa4, 0xdb71a3fe, 0x07c804b1, - 0xba5cfb10, 0x8c933daf, 0xefdea8f4, 0x489d0e9e, 0x0a01fc80, 0x71e82577, - 0x07aa2b8b, 0xfba16fba, 0x6c23c83d, 0xa187a391, 0xc11716df, 0x3ed2973c, - 0xc44ffef5, 0xf4fa3779, 0xf6377728, 0xd790214b, 0x4e7f7a29, 0x9235e806, - 0x2078c761, 0xc98bb3e7, 0xb294d4de, 0xf7baf8d8, 0xe1e4e4f3, 0x0d81b07c, - 0x03bf4889, 0x83b5e23a, 0xe360db3c, 0xf9464cf2, 0x8e4dc7f6, 0x630fcb10, - 0x6218ffed, 0xc8a34276, 0x5849930b, 0x68b5eba6, 0x585df7b6, 0xe1f7906f, - 0x5b1f7938, 0xbbfb7116, 0x52f51849, 0xca181933, 0x176d8b0f, 0x7887d71f, - 0xd21faab8, 0x1f80ac5a, 0x07ab4eec, 0xb8f881e0, 0xf6c83eba, 0x961f94eb, - 0xafd30c96, 0xbf410758, 0x1d0fdc2d, 0x08fe3868, 0x4fa06fd0, 0xd77d83b2, - 0xdbf461e4, 0x905bf744, 0xefcf1b47, 0x379d57a4, 0x97ff163a, 0xd1f5a8a6, - 0xe4eff950, 0x453ebd5f, 0xfe62f7cd, 0x343f6fc2, 0xf1897ecf, 0xe2bcdc65, - 0xfef1a9f7, 0xbccfb176, 0x2738795c, 0x870f2d45, 0x79677fca, 0x2eb43758, - 0x1d50f2f1, 0xe59bf8cf, 0x5c70ffe1, 0x4f7d99e3, 0x03bec027, 0xa7d878ec, - 0x63aedcac, 0xfd1413f9, 0xe9e2f1b1, 0xc597ab5a, 0x5ea2b54f, 0xa657871d, - 0xe33c38f3, 0xd45ed7eb, 0xf335bae2, 0x3ef37138, 0x369a079b, 0x9c631758, - 0xba7e3e36, 0x0e9eec84, 0x471f154b, 0xce7e026d, 0x753c74bb, 0x8f8b0a75, - 0x20725852, 0x6f3e216f, 0xa7eb35eb, 0x7598fe49, 0x1ba22aaf, 0xdbe85182, - 0x33890728, 0x14c6fde6, 0xc6bf5766, 0x7adc8bf3, 0xad608e76, 0xfd85e2cd, - 0xf2c35b8c, 0xf2e07e9f, 0x18bc826d, 0xfaf1c2a3, 0x4344edf2, 0xae8cf2f1, - 0xb04ae517, 0x3901ead9, 0xa237fc28, 0x5e3c8bff, 0x3ffad971, 0xfcf7de8e, - 0x3c7bd30f, 0xf18bf67e, 0xddb8d6fe, 0x151b8a7a, 0xe3a4105f, 0xca5f1023, - 0x63bf4919, 0x1d1633f5, 0x1df14d1f, 0xfe766149, 0xb857cc14, 0x2963394c, - 0x3f009e8d, 0x5063d911, 0x7e09afc0, 0xab8fd412, 0xaa3e78d3, 0xe6267ca7, - 0x2573b369, 0x58ce1ce2, 0x4307e476, 0xc8ecc3eb, 0x9f5cc60f, 0xde47672f, - 0x087df0ee, 0xd2b27674, 0x1e01e78b, 0x61f851b5, 0x619cf87f, 0xe22e73d4, - 0xfca5c63c, 0xd1c45f2d, 0x4bff17d5, 0x3a92d472, 0x75f95d96, 0x13cfd1cb, - 0x763a7fc0, 0xff9e413f, 0x45bc4119, 0x6b6449f7, 0x103b5f8c, 0x197bf961, - 0xfef15e1c, 0xa1bef83f, 0x999bd521, 0xfc7fdf4a, 0x1248d1ae, 0x652e9ea9, - 0x67c5b172, 0x4b42b8c5, 0x697fcb2f, 0x8e504659, 0xb4df80b7, 0x3389fc08, - 0x4f7dd809, 0x2013fd3a, 0xf7d1ee8f, 0x226d41ac, 0x1167dbf8, 0xbdcef3b0, - 0x9c33cacb, 0x6798c9fe, 0xe3006cb7, 0xceb3dd18, 0xf9561e60, 0x523e9f17, - 0xa2f08a53, 0x5065c13f, 0x3db9679f, 0xf133c995, 0x6f843d9c, 0x3ff3fa2f, - 0xdaf9606e, 0x0ed79701, 0x0fe1097e, 0x8c1128b7, 0x61ecb42b, 0x96b95bc6, - 0x30fc87cd, 0x65a9e903, 0xf831654f, 0xa9af494d, 0xf2ddec18, 0xdf715bdf, - 0xe983f1f7, 0xcfb12798, 0x7c02afe5, 0x37434ad8, 0x4d9a7d81, 0xf7bb01c7, - 0x1537dde3, 0xfe42dc03, 0x39bf03ad, 0x4d9d7f1d, 0x462717ed, 0x64bf7796, - 0x33ee2647, 0x5afeac9b, 0x133aff98, 0x9db82383, 0xfee14f9f, 0x17fe78f2, - 0xd5aa9f7c, 0xdfa938e0, 0x5c9c6235, 0x3a7585c8, 0x0de637e2, 0x9e1293cb, - 0xf1701867, 0x99fec73c, 0x97854f2c, 0xbe752ead, 0x37c947e7, 0x253c0094, - 0x8b57f2a9, 0xe4475967, 0xb2a4940b, 0x5cea9678, 0xb322e5a2, 0x7aed73a7, - 0x4adb27a4, 0x9454e2c2, 0xbfaec09e, 0x06991a36, 0xbbf2bce7, 0x9e02d7c3, - 0x20d45ff7, 0x4799e49e, 0x28933e30, 0x56f2f1b1, 0x004e740f, 0xadfd8c7f, - 0x954960eb, 0xa0157b2e, 0xefa749f4, 0xffe45481, 0xaf1842d6, 0x2c745fea, - 0x059f72bf, 0x59dd0cfd, 0x795f984d, 0xea833dee, 0x33fc4e7c, 0x3e605648, - 0x6fdf6e65, 0xdb604e31, 0x279a8d23, 0x15aa44fb, 0x1825a6f9, 0x36398e99, - 0xce50bad7, 0x1f7efbca, 0xee43bb04, 0x91024194, 0x03579d0e, 0xcb82d3e7, - 0xc7f5fa09, 0xb035db77, 0x3f3cd95e, 0x7fff7066, 0xbee3f14e, 0x4205c445, - 0x3749bf2c, 0xc7ec08f0, 0xdf03e5e4, 0xec7ac20c, 0xc05a6871, 0xb68baa7f, - 0x9f65dfa0, 0xd9acfd05, 0xbe2b797d, 0x2bd9cb41, 0x1b0718ed, 0x6ceee57c, - 0xf3a7e7cc, 0x3cca3f1c, 0xf9654a1f, 0x8b3ef248, 0xfc99f406, 0xa8c0f104, - 0x0aa523b2, 0x968a7ee1, 0x07df3f69, 0x8e1e4a7a, 0x0a3f829b, 0xaa4354f4, - 0xcdd0077f, 0xa5a4b9d0, 0x892e7666, 0x2db5a79f, 0x9c176f7d, 0xfdc2d9f7, - 0x4ff707b9, 0xbffe859e, 0x7582594e, 0xf960e0b8, 0xb2a42f95, 0xfc48e278, - 0xd63cc41f, 0x65bf7ddc, 0x02e28d7a, 0x8c7597fa, 0x574ee45e, 0x5f19f80f, - 0xde63f049, 0x611d75ee, 0xeccdc62d, 0xa35c7f27, 0xd677ecc4, 0xb2d33d33, - 0xe3cfed93, 0xd29737f7, 0x921ebf2f, 0x0cbf4c33, 0x764eff95, 0xf4e2efcb, - 0x6fbcdfca, 0x5efdea21, 0xbf12fdbc, 0x8f611bbf, 0x9637f5c7, 0x50f2231d, - 0x61c786aa, 0xd84db4f6, 0x9e554149, 0x9f95954e, 0xfbaa343b, 0x47649f5f, - 0x3b79107a, 0x72caed29, 0xfe8fdbc8, 0x4edfa088, 0x3c8915e4, 0xcb1560a2, - 0x8c6a09f7, 0x4dd12e78, 0x687f30ba, 0x124b091c, 0xf006d7fa, 0xe42a6dfc, - 0x4fefd111, 0xff62e6a4, 0xa567899b, 0x22a6e516, 0xc826fc01, 0xb802493f, - 0xc1161b43, 0x7159b778, 0x9fe4133c, 0x033ee124, 0xc7dd39f9, 0x35a756f2, - 0x3a43b8b0, 0x4e50cfd5, 0x697467cf, 0x3cc7ab9a, 0x22579156, 0x5e044ff2, - 0xd3be38aa, 0x01ca2c27, 0x54f228b9, 0xe53d99d6, 0x39c11760, 0x1cbf3868, - 0xbcf3346c, 0x776fd613, 0x4f9e2e63, 0x2979b2fe, 0xf91678f1, 0x7f44fa29, - 0xe46cbba6, 0x37416739, 0x7089eb31, 0xecc7dc6d, 0x3d06aafc, 0x71b063ce, - 0x072bfa06, 0xec04351b, 0x037eaa81, 0xf1b8c3a3, 0x93d5ce36, 0x872bf430, - 0x054f204c, 0xceca5c3d, 0x085beba5, 0x6d83e0fe, 0x524ef33b, 0xd6d43fde, - 0x9341cf8b, 0x12bdabd4, 0x03cea1cf, 0xb48df5c9, 0x1af95afc, 0x6689b7c8, - 0x6a849449, 0x96faafd3, 0x60c4f54c, 0x287df472, 0x7be1bedf, 0xba3e3cac, - 0x9beda245, 0xed623ed3, 0xa9d33681, 0xefff5ed8, 0x57eb41b5, 0x267f7fd0, - 0x351cf9f1, 0xebf464ee, 0x3f41123c, 0xa57fd712, 0xadba3e4c, 0xdc9fb47a, - 0x54951f3c, 0x8854fcf3, 0x7b72d0f8, 0xefc6315a, 0x13d944ad, 0x030cfa81, - 0xe30827b3, 0xccf1f687, 0xf4e46d6f, 0xbf843240, 0xf208206a, 0x81c73dae, - 0xe7c90fdf, 0xf310863d, 0x8ff1b19b, 0x9e0578be, 0xb679124b, 0x6733d884, - 0x36f9815f, 0x135af2aa, 0xdb29a73f, 0x7bbce133, 0xc1db8ebb, 0xe6c47cbc, - 0x04f3885f, 0xddf6a4be, 0x507e1bd1, 0x7674fc04, 0x41f30fef, 0xa7a8ddce, - 0xe45184fb, 0x933a595a, 0xeb3a836b, 0xb77e894a, 0x016fe6c6, 0x32c77c3a, - 0x311c3a6f, 0xa9549b9a, 0xc1bc0077, 0xd780b4e7, 0x8e274e64, 0x473e0cd9, - 0x3c824fb5, 0x1b1376d4, 0x7b2fd937, 0x7f845cf1, 0x851b74b6, 0xf2625dbb, - 0x88947e9b, 0x92a15576, 0x26c87108, 0xcb55ee7e, 0xcb9688e5, 0x1b6e7f91, - 0xc1a997c8, 0x13ef4d78, 0x7fe7b05a, 0xbfe2e3cb, 0x9f9f51cd, 0xb83371e8, - 0x569673c5, 0xcfe802b9, 0x523aaba5, 0xab40e94b, 0xfd7084f7, 0x37186d32, - 0x772b603e, 0xa5efd00f, 0x42951fec, 0xe67b773e, 0xbe214a8f, 0xdc7a75a7, - 0x8f7298be, 0x357fd19b, 0x59bc03b4, 0xefc14b5a, 0x97f5b5fb, 0xfa2bfb48, - 0xf50dfdf2, 0x35706063, 0x7059a319, 0x9359fe6e, 0xffac3b7f, 0x30c7f985, - 0xfa40fc2e, 0xaf21f7d1, 0xd18ea8e3, 0xe793305d, 0x69ee93e3, 0x0eee9409, - 0x5e7839e7, 0x1ebf8b0a, 0xa8fcc09e, 0xfcb17e54, 0xe61289d1, 0x66ced621, - 0x266f62e7, 0xfa018e91, 0x68593a3d, 0x1c8af4fd, 0x796b7fb4, 0x77f4c89e, - 0x7eb0097c, 0xca8f6fd3, 0xb2c7f720, 0xeb746ee7, 0x3e188194, 0x975149be, - 0x97542e6f, 0x9751e5bf, 0x97f15dbf, 0x9365b109, 0xe8107bd9, 0xdf8955f5, - 0xb10d7147, 0xa4ba7f23, 0x935dd820, 0xe7e74a5f, 0xe53e5989, 0xf17ef94f, - 0xf5820aa5, 0x5b8d3b29, 0xfdcf508d, 0x3f5e5aef, 0xd98c4dd9, 0xea07c44e, - 0xf3c4a8e9, 0x93185d32, 0xb1ef7b22, 0x6d343f33, 0xecfda7ab, 0x1f20af9d, - 0xe43558a7, 0xa5ebc09b, 0x04c3b446, 0x289bb45f, 0x963c537d, 0x819a338f, - 0x9e75dbde, 0xd697d0f5, 0x2f40506c, 0xb1182657, 0xc83fed6f, 0x9b96d7a8, - 0xcb4ec40c, 0x63371f07, 0x3e265cb9, 0x20a123c8, 0x51e786ce, 0x0ad4279d, - 0x60eda5f3, 0x160eedbe, 0xeb96d757, 0x7ed3cf51, 0x3e0f5d71, 0x9c1109a1, - 0xf98ca57f, 0xc1661ca6, 0x7c247477, 0x6be734ff, 0x518486ad, 0x7bb3a58e, - 0xfed10e39, 0xbf83dfa1, 0xdfa0f6d2, 0x13b950ae, 0x271bcfea, 0xc0a8b9e0, - 0x592f79d0, 0xda15c003, 0x67e87cb9, 0x3f04f2e7, 0xa542f90b, 0x852bbe5e, - 0xf8149030, 0x053b050f, 0xfb8204ec, 0xccb71100, 0xd97a8a34, 0x0da6fd0b, - 0xe0e767b5, 0x56997852, 0x60253585, 0x27f1bca7, 0xe4b1c3a0, 0x931a6145, - 0xe429e213, 0xc3c316c5, 0x19af6a47, 0xef0a3d6d, 0x9b0cf2c7, 0x84c7ad9d, - 0xad4be00c, 0xe8064279, 0x478776cd, 0x0b94c5f1, 0xae6a76e9, 0xdb45f013, - 0x35adf2d1, 0x18e5f2c7, 0xc69854fd, 0xe76d00e4, 0x1ef0a24d, 0xc0192934, - 0xdb8ca3bf, 0x7cb5c6cc, 0xe9bae3bd, 0x41ddb4b8, 0xb6971d1b, 0x843266db, - 0x8da30935, 0x78c0a15f, 0xa2971a97, 0x833f911d, 0x93a503af, 0x0ec1f820, - 0xaf4834da, 0xf2be7833, 0x1e3664c1, 0xffe75429, 0xf8e99be4, 0xcea65f98, - 0xda51b9f7, 0xfa7a01d4, 0x56c25369, 0x3837cfa0, 0xfcb61cdd, 0x69d83e43, - 0x382bcc6f, 0x71267284, 0xd1100779, 0xf28bd20c, 0x0bc1c846, 0xa1cac769, - 0x8de1e54c, 0x0fde7469, 0x079d1ee4, 0x3c721f9d, 0xa5f68f9d, 0x56935bd9, - 0x417e1236, 0xa06e029f, 0x218be053, 0x5f838d3a, 0xa5b91bd0, 0x37251317, - 0x9e173b53, 0xa425eec2, 0x2bc5e595, 0xa3f3c399, 0xd8dd3e44, 0x18d1e6ca, - 0x746fb844, 0xe6f318fc, 0xffe718ee, 0xf735c01e, 0xbef04fca, 0x3f9ee222, - 0x1477f601, 0xc96979de, 0xc6f07bff, 0xca97f9db, 0xcf8b1f0f, 0xacd2f8c5, - 0x1e1f989d, 0x7cc56d98, 0x3f3c69f1, 0xc1a0d036, 0x0fdd00b8, 0x85a23ee2, - 0x97204318, 0x5cbb72a7, 0x45785b9c, 0xe0d6fe62, 0x7d45068b, 0xde7c513f, - 0xe97982b8, 0xbf2c65c1, 0x6f7ec87c, 0x1f7ed056, 0x9cfc73d2, 0x93317744, - 0x28f7dded, 0xe689fbea, 0x44fdf513, 0x7121ed0b, 0x32948a6f, 0xdddfbf9c, - 0xbbfe9043, 0x9f58b96d, 0x88fa65ae, 0xa3e9837c, 0xbaa21cee, 0x399d691f, - 0x94f31134, 0x46c15e78, 0x6ff83fc8, 0x9a7e0bf2, 0xc2fca926, 0xc9afe543, - 0xf0e6dc2f, 0x5b3a02ef, 0x92cde458, 0xebd63d28, 0xd2987f99, 0x8108a6eb, - 0x7cd6c574, 0x44dda7d8, 0xe4d2df5a, 0x02febd21, 0xa53275e9, 0xbd153cd7, - 0x15fc61ee, 0xe82d2144, 0x0b4e8875, 0xfd00f3e3, 0x6edc60fb, 0x5befef47, - 0x6fd35f60, 0x683cb0f0, 0x2f19d796, 0x59e0621f, 0x5c783320, 0xf3c22d5a, - 0x0f13f43a, 0x4df0e5cf, 0x12a69d2c, 0xf1631fc6, 0x824caa4f, 0xfe6192b6, - 0x6ffd9931, 0x7c43b8c1, 0xcfdb08f4, 0x6b5b808e, 0x739a7a45, 0x057f8b07, - 0x802ecc2c, 0x1d1a5838, 0x7f1f267f, 0xdaafa74e, 0x4a66ed01, 0xfa610f0c, - 0x167f850f, 0xdfd99faf, 0xb370798c, 0x63c775aa, 0x2f2120ed, 0x2e6ddc45, - 0x7dab7f6f, 0xd2f20ea6, 0xe3aad767, 0x64ef735d, 0xb339b6f1, 0x25ccfdd5, - 0x7cc13fab, 0x03aad24d, 0x53bdcdfc, 0xda49ff5d, 0x026c9c50, 0x710ec9c4, - 0xe520d03f, 0xd7a3e013, 0xba6f1793, 0x84f9d287, 0x8095149f, 0x9486f0df, - 0xd04f6dc6, 0x271bb3f2, 0x94f5f961, 0x28ff7eef, 0xc0296fd4, 0xe25c3572, - 0xe056fb04, 0x8567ca43, 0xc8cc77e5, 0xc27d0049, 0xe087bdfb, 0xdfd9b77b, - 0x73b6933d, 0x3cc5c94f, 0xd7ee6ad6, 0xeac85c18, 0xc6d2be6f, 0x52ef9552, - 0x6d5c5fd0, 0x1d35f766, 0x04bb7e29, 0x73abaaf2, 0xd5e4b979, 0x243e5049, - 0x3af7827d, 0xcab66b9c, 0xe92d0eb0, 0xb93ecfcc, 0xa44f0a50, 0xf276a978, - 0xbcd99bfe, 0x4b9e4b6a, 0xaea93e07, 0xf64cfd62, 0x41e67654, 0x2c79cd3b, - 0x26374b9f, 0xbf05fe00, 0x957df0e5, 0x5c7d2bb0, 0x3de4bc4e, 0xfb4491d6, - 0x0f2519f5, 0x7157d14c, 0x664bdd8c, 0x7d03e765, 0xfc191cde, 0x2cbcd3f4, - 0xb8cab6ef, 0xe1e40d3c, 0x297d7e2d, 0x2c6ecbcc, 0x1179043e, 0x65951589, - 0x246da798, 0xfe94beb8, 0x3f03a7c7, 0x5649fd5e, 0x559d1002, 0xbe82ff4d, - 0xafba0a66, 0xe537d356, 0x65e9c9db, 0x2adf9697, 0xd30d36fa, 0x3ef658f7, - 0xe102ab85, 0xaf5a86fa, 0xc7138d0d, 0x8ee3f19f, 0x2fe03725, 0xc30efe56, - 0x987c8bd7, 0x798dd901, 0x825da7c0, 0x38026f4f, 0x9e089af4, 0x3c96ca8f, - 0x7180f093, 0x7a88c785, 0x055f8e2f, 0x33e0997c, 0x1709192f, 0x6ec2c9fc, - 0xf02e7f65, 0x7af064a3, 0x38979dfa, 0xe3a2e187, 0x7a0e91df, 0xcf0611fc, - 0xc995a966, 0x112fbe19, 0x311697fe, 0x7cf53edf, 0x1eeccdcb, 0xcbf83703, - 0x3c527630, 0xcbee0869, 0x9f310758, 0xb3e7d700, 0x9e9b3e8d, 0x4736edce, - 0xedcfd23d, 0x283aa354, 0xff74c25e, 0xd41e700f, 0x7ec1f704, 0x62f1216f, - 0x47d29cfc, 0x6ec63d20, 0xe3c6f012, 0xb90c65a9, 0x789f3f1a, 0x5baf0cfc, - 0xe29e0d24, 0x7cd0e1fc, 0xf19e732f, 0xaf4b8af6, 0xb93a5bf6, 0xec39d17f, - 0xfa842c4f, 0xa0f6625a, 0xe123d13f, 0xda96af7e, 0x6ba7201f, 0x71fa086b, - 0xfa0d569c, 0x321d8513, 0xff5c9f16, 0x6ab7264d, 0xf73f089b, 0x4f17e6c8, - 0xe064a98f, 0x1ad6787e, 0x800b0d95, 0xaaac1bff, 0x56b50673, 0x4e788f16, - 0x503211c8, 0xa87f7a06, 0x0fef423c, 0x8a1c8194, 0xf6ae7fbf, 0x3b7bf322, - 0xacf84a2f, 0x032b1cf5, 0x19acefbd, 0x56790328, 0x14fef767, 0x13dc55d6, - 0xbdcf8f19, 0x97911ae9, 0x1a745972, 0x0e2247cf, 0x7fe6c47a, 0x3fc63d39, - 0xa08a5675, 0xcbb5759f, 0xcfe7e7ce, 0xd8767a01, 0xefc12a73, 0xaad8db34, - 0xd138bb03, 0xce903fe1, 0x5f17e8e4, 0x9a17e6c0, 0x56de3c52, 0x66587fed, - 0xee1e22c3, 0x81b878e5, 0x9bf3d9eb, 0xa90fb8b4, 0x0d3e16f6, 0x9bc0a0a1, - 0xbe42123a, 0x147ea2f5, 0xa79dc6f7, 0xda185506, 0x7d436f3f, 0xf557f8bb, - 0xb09b2718, 0x1894435e, 0x6431397d, 0x327fdd56, 0x5553a779, 0x5d37a2be, - 0xbecafed5, 0x717d555c, 0xfeaa9278, 0x544b37aa, 0x54c8b2e5, 0xdfabfb55, - 0xaf9552a9, 0x6aa19819, 0x3df403bf, 0x4e37e3c5, 0xffbd52cf, 0x37f4e368, - 0x5d7d3e21, 0xefaa3bf4, 0x043f704f, 0x85237a09, 0x040bfe74, 0x53ac5ebd, - 0x9acd4f7d, 0x7c0e54b0, 0xac16fecf, 0x95f77966, 0xfdb16314, 0xdb52ec2d, - 0x28903713, 0x84b62be6, 0x40984f24, 0xbeba9dde, 0xf107afb1, 0x0f7ba97a, - 0x6be6b826, 0xc69754c0, 0x22633b51, 0x0d5c8220, 0xf1638379, 0xbfd6a5fb, - 0xa97fe480, 0xd5b837f5, 0xd4526feb, 0x54296feb, 0xa3cdbfaf, 0x0ac4ff5e, - 0xbc3bfaf5, 0xaa4ff5ea, 0xb27faf51, 0xa9febd4f, 0x9febd573, 0xffaf57e6, - 0xbaf506b8, 0xd7aab667, 0x7aa97b3b, 0x4b82735d, 0x74f1f554, 0xc849e820, - 0xf795bccf, 0xa453dbaa, 0x42e86268, 0x5f02d9d0, 0x8d63e603, 0x35487aef, - 0x4c7d3c5e, 0xf48f3c20, 0xe547d22b, 0x727f6e38, 0xa97aa0ba, 0xda325c6a, - 0x73c03719, 0xff6e04ee, 0x33b746fb, 0xd58afc84, 0xe6fbb1eb, 0x08dae4b1, - 0xd1f7c57d, 0xd82bea63, 0xf7869b47, 0xefd163d1, 0x59ea84bb, 0xfa357c1c, - 0x33b0eecf, 0x999a0e38, 0x5429ff3d, 0xd1db435d, 0xde141536, 0x743e6177, - 0x93cd77fc, 0x1df20fd1, 0x7183abd2, 0x7c1124ef, 0x7c5123ce, 0x755d89fa, - 0xf10165be, 0x645fb9e9, 0xc9a9e009, 0x7a0e5038, 0xa3fcc2ff, 0xee7c63ef, - 0xdd65d248, 0xe21c7207, 0x3909e33f, 0x49c9e5c5, 0xf2d10388, 0x27f71339, - 0x8ae2897a, 0xee29e7c1, 0x269bacf7, 0x5a259ea1, 0xd5b1e633, 0x9ea12edd, - 0xf60ffbaa, 0xf4c71f6c, 0x52e788da, 0x6e2ed781, 0xa13b301f, 0x62dd0e0f, - 0xadf890fc, 0xec7a8f68, 0x3fb4deb0, 0x47f98716, 0xdbb17f76, 0x25dce0c8, - 0x89c2b911, 0xdd7106c7, 0x7ce1fd61, 0xe0c8db9b, 0x4623a5db, 0xe264efc0, - 0x31f0fb47, 0xd63c8a99, 0xefd624ef, 0x17f05cd1, 0x7e6fcd9a, 0xa9f21aab, - 0xf472e0e5, 0xa88f7fdf, 0xb677f7fd, 0xffbfe84a, 0x3e9b851e, 0x1b8f76dd, - 0xef28b2f4, 0x1e21b802, 0xfbe8ed00, 0x04ab7754, 0xadafb1fe, 0xb10f3dbf, - 0xbfb25f76, 0x83087ea1, 0x3d60fe0b, 0x83367f85, 0xd281b7d2, 0x11efb6cb, - 0xfbc61ff4, 0xa969c76b, 0x31fc8106, 0xc097bb1d, 0xfb67af2d, 0xbb1ec3e2, - 0x7444cfca, 0x7a47380e, 0xf20e7b29, 0x9cc54fbe, 0x3474a0d3, 0x1fbafdea, - 0xa47cb065, 0x44c8b6f6, 0xe39e4b88, 0xdb87d771, 0x56b2c4de, 0x265e60f6, - 0x88e5f7dc, 0xa2ef5ef9, 0x4e7231f5, 0x63efd2b6, 0xeace8de4, 0x1e6bcbc3, - 0xbc608b69, 0x25efc753, 0x5ee3347b, 0xbfc63fbb, 0x6e38cef2, 0xc4831927, - 0x69b8429e, 0x4f4eff4f, 0x5a3f4023, 0x762a7cbb, 0xd3706d1f, 0xeef562fe, - 0x1b1264c5, 0xf6d9587f, 0x88fdc20e, 0x6743f7e4, 0x36127c86, 0x641b7c51, - 0xdf4d0338, 0xe511b86f, 0xaf76deaf, 0x1aa1ee07, 0xb7067f0b, 0x7e56217c, - 0xdf8e387e, 0xe7e5c5cf, 0xc9d16d93, 0xdb7b4e30, 0x5d6f0a80, 0xfdf1176d, - 0xc452369a, 0x7ac43fea, 0xf4828d4d, 0x42d28a73, 0xf27ae204, 0xc1fc0d80, - 0x10263ed4, 0x8db9d67f, 0xb8306f18, 0xa2e4bc18, 0x9e63e90b, 0x3e00c19d, - 0x1f4a4cbf, 0xe1d52fef, 0x4cbefafe, 0xefbfb62b, 0x780fe337, 0x29eadf29, - 0xc37fb41a, 0x61c7867c, 0xf973d3f8, 0x0fbf6449, 0x5d3e80e4, 0xd38538c6, - 0xf1d70b3e, 0xf027f6cb, 0xcc1137ae, 0x5a67d647, 0x5cb85ed1, 0x6a19dd38, - 0x8fe3c7bc, 0xffe509e2, 0xf74f1c7d, 0x93fcc83d, 0xf04fddf7, 0x4a59053c, - 0xe987caff, 0x87971c6a, 0xcf87c4a9, 0x082a36ae, 0x465eb00d, 0xed409fe2, - 0x8d8bd211, 0x82a7e04d, 0x80ecaf7a, 0xaa2788d4, 0xb9e1335d, 0x1764e2a6, - 0x6bdae3b0, 0x13c08b3f, 0x2f801162, 0xc109037b, 0xab98bc55, 0xf877c740, - 0xd7813959, 0xe565cc27, 0xe89f5e44, 0xef4ce563, 0x0035520b, 0xcb471716, - 0xca6f3ab4, 0x80bc7907, 0xfcf173b0, 0x84cd8d7e, 0x73ab0bcb, 0xdfd43566, - 0x8b9cf049, 0xaf09ffa8, 0x5f1eb34f, 0x637a0799, 0x0dfbfab6, 0xd6a90f1c, - 0x30d35de3, 0x17aea6de, 0xeb64acf1, 0xfbf137f9, 0x53fd7522, 0xf59b7bfc, - 0xd41a647c, 0x7fc7abe7, 0xac5bd79c, 0xca8def2c, 0x037f767e, 0xd78c7faf, - 0xc61ea09b, 0x5af5642f, 0x6f09df71, 0x18e1c9d7, 0x431e33e2, 0xbf33260c, - 0x233696f2, 0xbf3c57f2, 0x73f707dd, 0x9bf30d95, 0xf519297d, 0x32fb86de, - 0x5049dc98, 0x51debc06, 0x77a8a2e4, 0x37cc65da, 0x48f5bad0, 0x972b064f, - 0x871f9c27, 0xead489e4, 0xe4c64461, 0x9ae8a5f4, 0x9005f012, 0x0ff4596b, - 0xfbe33ae8, 0x918fe21a, 0x664de973, 0x83e58fe2, 0x39554e05, 0x5574cee5, - 0x5cecd77b, 0x74b5bd55, 0xcc9eaa92, 0xdc9f2276, 0x5ccbe9cb, 0x17aaa254, - 0x6d9065f7, 0xb59d9dbc, 0x554fe5d3, 0xa85f3bb5, 0x9f8d0224, 0xa3dc49ba, - 0x7c8231e6, 0x9b96d7b8, 0xb3f8fc0a, 0x4e440ab6, 0xf627e53b, 0x1ba7f3b4, - 0x54fa598c, 0xcb10b978, 0x7e583bcf, 0x879b7b7f, 0x9e087395, 0xab6f6faf, - 0xca2ef2c1, 0x69fcf09f, 0xdb9f179b, 0xcfa15969, 0x2bfda47f, 0xda1e9fb4, - 0xa19f943f, 0x3373c3fd, 0x3f9e1fed, 0xfd43fda1, 0x942fda06, 0xc170a69f, - 0x0fda29f3, 0xed31ffbc, 0xb44fca1f, 0xb6bcb0f9, 0x1f962e6d, 0xf3e3f36f, - 0x7c06b6b1, 0x8ad6d9df, 0x96db47e5, 0xb6e1f3e2, 0xdbdb3e20, 0x2f7d6256, - 0xf9e793a7, 0x2be7dc79, 0xf103bdd9, 0x219fdfeb, 0x9d2fbb61, 0x154a539f, - 0x3f2ab97a, 0xfc033fa7, 0xfceabd02, 0xc21fc054, 0x8c786261, 0x0668e387, - 0x91270fb3, 0x930b72c8, 0x1f07181f, 0x6159e7df, 0xae35fca1, 0x4e7bad95, - 0xd3eb145f, 0x4778d81a, 0x5c409db9, 0xce519241, 0xbb439b8e, 0xcaa45273, - 0xd007f2c2, 0x14dc430f, 0x5aece53f, 0x21e64672, 0x5725c00d, 0x331e3d50, - 0x397c21af, 0xb7809c18, 0x57fde0d1, 0x696d378e, 0xa75fbb2f, 0x6c0c2ba6, - 0xe2b6f666, 0xb9c63afd, 0x9f4cb0be, 0xef1f9f2e, 0x717498e9, 0x5224dd3a, - 0x9bf176f9, 0x8ccfa144, 0x31fef526, 0x6a89417d, 0xb8bda67f, 0xd1572886, - 0xfbd48b7e, 0xbdfe733c, 0x198cefaa, 0xf5eaa90f, 0xfaaa15ae, 0x1e73bbba, - 0xc73e0371, 0x6199b8b1, 0x210272f5, 0x4fdd85e4, 0x4ce65c20, 0x92738f36, - 0x605f7ec2, 0x133dff37, 0xd6797fbe, 0x5c65f1ce, 0x09f2fb8d, 0x482c560e, - 0x0f406a0c, 0x448bfc7d, 0x9e3b7f94, 0x7e9fa0d1, 0x40690922, 0xe6a64cde, - 0x015fd424, 0xf16b8c37, 0x942d26aa, 0x85a2898b, 0x8a2455f2, 0x7fba3afb, - 0xf5d264d1, 0x9ffad16b, 0xd9f2d131, 0x2cb3ff4c, 0xfa8c30bf, 0x67af80ba, - 0xadc7d881, 0xdcfde397, 0x37f44cc6, 0x7625cfa9, 0x874bfdf0, 0x970df989, - 0xc153ca3b, 0x46373e0e, 0x7dcda83e, 0x14058de2, 0x63b4b6df, 0x1fef14f8, - 0x9ea33457, 0x94cbcfd7, 0xf75e5abe, 0xd44faa7a, 0xf307937c, 0xcffa5b38, - 0x6b76e029, 0xff228fc9, 0x3c84e874, 0x9e411253, 0x893d970d, 0x3b1e6624, - 0x93c9deda, 0x11fa2151, 0x375f326f, 0x4ff95f31, 0x4bc87695, 0xd179e02c, - 0xf2d2db3b, 0x7f0fc7ab, 0x5074e3ef, 0xa0352248, 0x348b0b5f, 0xe074109e, - 0x31fcabb5, 0x2f2efca6, 0x4b930b9c, 0xf2c40788, 0xf785d244, 0xd57fc829, - 0x7c9a3e62, 0x50a21af0, 0x0d6ad8fb, 0x70d16093, 0x75fb84bf, 0xfce5cfbe, - 0x9c6af667, 0xec259c8f, 0x74e80f26, 0x1bd599f2, 0xacfc3a01, 0xf4d8c75b, - 0xd0bebab8, 0x2def504a, 0x1487d42a, 0xebcbee09, 0xe5407bc2, 0xc8c9122d, - 0xb9a63801, 0xdf7e83e7, 0xb63a416b, 0x9fc72fac, 0xe359b830, 0x0efc40af, - 0xc2357b28, 0x9aeda2e8, 0x82b7eb27, 0xf001393d, 0xdcbc0562, 0x430d5f91, - 0x1e2217e7, 0x2f79f217, 0xc8e8f3e4, 0x833fc21c, 0x70bc7887, 0x6ea2ef1f, - 0xcf528fe1, 0xaad2f1f3, 0xa2bdc36f, 0xff2d11ed, 0x3e352299, 0x5322e957, - 0x70c34be6, 0x66173851, 0xb8015c82, 0xd80f82af, 0x919f9afc, 0x941cc6c8, - 0x6f68356b, 0x3f306994, 0x9b2e9e3d, 0x8fdc9932, 0x7dd9d866, 0x4853eee4, - 0x93e5c3cf, 0xc2482c6f, 0x5bb333fd, 0x8fcb326c, 0x58957af4, 0xe12af7bf, - 0x72e7e45f, 0xa1de1ccc, 0xb127057b, 0x892b60bc, 0xb4bc87ac, 0x2bf5f6b1, - 0xdc707332, 0xb53d7de1, 0xa53f205d, 0x5c7988cc, 0xa13e44ab, 0x69995472, - 0x57384f63, 0xfa74e465, 0xf79d4da8, 0x6fcf9db3, 0x418f5f3b, 0xf27bc8a3, - 0x9cc716d6, 0xafeba9f3, 0x88963f47, 0xff720ed3, 0x1d59a0e1, 0xa4e46d57, - 0xaba87830, 0xc1f10cca, 0x6da7162e, 0xdd99bfec, 0xc7efbb6b, 0xed302f78, - 0xa87a0153, 0x57ebede7, 0x0b58fdaa, 0x5f91fa77, 0xf164fde3, 0x398a317e, - 0xe31fec3d, 0x335b62fd, 0x43c27ef9, 0x7b0e218a, 0x61de7562, 0x7277ec33, - 0x1f0f9e08, 0xef017da7, 0x81bba6dd, 0x974fb82e, 0xa3fbb114, 0x54ffd7e2, - 0xb2f11e96, 0x78efac53, 0x3ba5da2b, 0xd81c98cb, 0x2dfce079, 0x2b3f69e3, - 0xf9d52473, 0x3a399580, 0x29b7a75c, 0x97b3c37d, 0xeed19a90, 0xa9943b29, - 0xef726af9, 0xc1eff55a, 0x1c0df734, 0xff2828b6, 0x1fba035e, 0x4279fc3c, - 0x1451f211, 0x08c4bf7f, 0xc19930c2, 0x76b3e70d, 0x17993e6b, 0x676f0f4b, - 0x36ff58ca, 0x0d2f8ba7, 0xae1ab557, 0xa56f45b3, 0xfd7060cc, 0xb9c6e40e, - 0x5894f1f0, 0xb5c0467b, 0x03df8c7b, 0xe2abf0f8, 0x1fad42a9, 0xfa74f062, - 0x6ed3c3bf, 0xfcf0e8fd, 0xb3f3c395, 0x9b5eec43, 0x515ff591, 0xe1ab759f, - 0x647cfb3d, 0x0a49880e, 0x7f115fef, 0x182993ee, 0xebf8e613, 0x59f4e52d, - 0x078fe5ca, 0xc09150cf, 0x1e63577b, 0x924caf66, 0xbe5ca16a, 0x2cf77f00, - 0x02c3ef93, 0xbf9e3f1a, 0x4619ef21, 0x64d77f95, 0x9ddeba31, 0x878a8d2e, - 0xcf362cd2, 0xb2ea4703, 0xd8f1bfc1, 0x7202063b, 0xbfcf3361, 0x6bdecc7e, - 0x05a67b84, 0x425ca11e, 0x747d019f, 0xc7bc2811, 0x2a333f4a, 0xd3c651d6, - 0xc6d6f1b0, 0x4f188df1, 0x1564a73c, 0x3a557b32, 0x387385a4, 0x0b7daf6b, - 0x5b5b7fef, 0xfdeca32a, 0x1d5ff8d2, 0x5bf0ff87, 0x7a30b729, 0xe1459299, - 0x90fe916b, 0x0e5a6df0, 0x2a7fd148, 0xbd157c82, 0xa01fe71f, 0x4691ec78, - 0x8b2d29e2, 0x9f988bd1, 0xdb80bf98, 0x5c02dd76, 0x06bbdb07, 0xbca51a54, - 0x8917d0bd, 0xbcc1ff5c, 0x2b5c5f50, 0x654c73b3, 0xdafbae32, 0xee78a98a, - 0x17cf376c, 0x1fa35e89, 0x164477f5, 0x763dbc70, 0xb811b7f1, 0xafd83947, - 0x883ffbc3, 0x15bee03c, 0x8dff1fee, 0x5389f78c, 0xfb81aa7a, 0x391c0ecc, - 0xebfb009f, 0x843a59f9, 0x87973e7b, 0x35b51783, 0xc8ec1e78, 0x0c6d7667, - 0x6965d7fd, 0x89127db9, 0x35af39c0, 0x8b3cec25, 0xd603db95, 0x001b2723, - 0x43c56b7e, 0xde862906, 0x10196566, 0x68fa35ae, 0x17f6878a, 0x6125a7d8, - 0x7bc1ffe6, 0xb3ce8719, 0x5a1e19da, 0xbda10f4a, 0xf767ed60, 0x2965d635, - 0xb852ce4c, 0xe6f7d2f7, 0xebd99f89, 0x8e94bea1, 0xbdfc3b97, 0xd3d6cecd, - 0x4beec65c, 0x3fed7b5a, 0xc83ee1db, 0x471df844, 0x79f2efd8, 0x7292b80a, - 0x48dfbc35, 0xcbf81724, 0x5abe632e, 0x235ef86f, 0x2f82fbd8, 0x62d5cade, - 0x39f947bb, 0x0a2b4789, 0x4cae7043, 0xdb35b1d0, 0xcc1640ff, 0x0bc5f28f, - 0x7c44ef68, 0xf63f10d3, 0xdf33c862, 0x32e64525, 0x076f443b, 0x68d42c3e, - 0xe116fc54, 0x549e26eb, 0x73dda3fd, 0xa15da73f, 0x46423bf7, 0xfe4de702, - 0x22667178, 0x191da7d8, 0x1af3dec2, 0x259b5f01, 0x8c0e625f, 0xdc5a2ff3, - 0x72381e0f, 0xedc601bc, 0xbe02f3a0, 0xeb75f87d, 0x3a53b06a, 0x53e45eec, - 0xd0ecbe31, 0xfd60f5f0, 0xdf7bd6ec, 0xd4647f04, 0x3acdeec1, 0x11867538, - 0xd3b69fe8, 0xa07f3f40, 0x04f0f7fb, 0xfd1aa7e8, 0xb3ed0b06, 0x8b77c3a6, - 0xb011ff88, 0x6b75176f, 0x3c83f755, 0xc2c5e5cc, 0x8e12168b, 0xac2c2fd9, - 0x6b9e0ef8, 0x0131785c, 0xcfcc3fdf, 0xcfcc3fed, 0xf8e2edbd, 0x5f3f9978, - 0xfb8afacf, 0xde9c4f6f, 0x8eddfe4a, 0xbbf7c63a, 0xa59afd60, 0xfaa83d01, - 0xc73f5335, 0x687f64f3, 0x21b093b3, 0xf311de06, 0x98e1224c, 0x5dda8771, - 0x52709134, 0xfa32faec, 0x15af9e1d, 0xe6d0ffeb, 0xdd8e3c46, 0x1e1538ff, - 0x53cffb87, 0xff6471e1, 0x87ff5805, 0xf44bc2b6, 0xfe8c793f, 0x0ff05473, - 0xef8f9bf7, 0x7bac1dcf, 0xeef942d6, 0xc6c57860, 0xf7e14b57, 0x7bf80cf7, - 0xb7afa41b, 0xeeb9cf0a, 0xfa0e7822, 0x7a7ffd81, 0x1f52f21f, 0xc0f7aad8, - 0xe8ba8318, 0x7a28cf3c, 0x83d89f26, 0x789cef70, 0x87959dbe, 0xdeff1ceb, - 0x90ec8728, 0x942c6a67, 0x8ce7a0ed, 0x015a1224, 0x235297fb, 0xdf1139ca, - 0x34fefd12, 0xb392ab53, 0x46a17ee2, 0x68d87f9e, 0x26aff161, 0xac2cffab, - 0x574d12ff, 0x1f68cfcb, 0xf03b0ba7, 0x0e213b7c, 0xf888d7dc, 0xc5fb0c8e, - 0xf97d703c, 0x9b0b9c08, 0x0cffe397, 0x1509fbbe, 0xd1ef102b, 0x0fcdb15e, - 0xf38f79f9, 0xa6e3e47d, 0x2313db88, 0xf2d9753f, 0xba1bb357, 0xecb7e8e2, - 0x8cc23b77, 0x40d9757e, 0xcfc8dabf, 0x7ce072eb, 0x67bf00e3, 0xb9fb414e, - 0xde30f4ae, 0xfc275947, 0xf3e32b02, 0x601d3256, 0x54788b4f, 0x8217e402, - 0xdd86b0dd, 0x616f5853, 0x275ffae5, 0xba17b9e1, 0x8114b21f, 0x65add99c, - 0x071e22fe, 0x1e61cf3b, 0x02c9ae34, 0x7cf20efc, 0xaffdf397, 0xe7a7bde1, - 0x3a478e57, 0x0fe5ffa8, 0xddc31ef1, 0x0d9f4ce9, 0x3ea1b3ee, 0xca7837ab, - 0xddcd5ee1, 0xed6ecce9, 0x2509c395, 0xa3ec7631, 0xa7285519, 0x5e395e3f, - 0x19271b13, 0xc2e4cd9f, 0x94ffe11a, 0xce70e5a3, 0xf0d2e3ea, 0xdd3ea13f, - 0x1bdfc263, 0x53fdecd3, 0xbabfde39, 0x63bf80c6, 0xe277b551, 0x5fb0b9ba, - 0x1f31904c, 0x84d7b35b, 0xc55d9cf0, 0x6f8383ee, 0xef35ee41, 0xcbbf871d, - 0x62896f56, 0xd9b364de, 0xc1f10053, 0xc0dfbdfa, 0xf1389fdf, 0x902cc4f8, - 0x9593c783, 0xfb6fbc2c, 0x3a748a71, 0x26fbe3ef, 0x579df7b0, 0xdb6ab9e3, - 0x347f8b1a, 0x4bd088ff, 0xedcdf7f1, 0xd73e2f4e, 0x6899f807, 0x5e1c80f4, - 0x675fe438, 0xbfd607f7, 0x24a59d19, 0xf306ffa0, 0xa7edea17, 0xeb1df7f0, - 0x49dd8fbb, 0x42e93e30, 0xbcfb15fa, 0xb9eb71f8, 0x8faddafe, 0xd5df83ce, - 0xf8e76fab, 0x59f7bfe7, 0xdfc629af, 0x5ff8149b, 0xf31f7713, 0xc5de38f7, - 0x1911c4f3, 0x76a4b9ef, 0x8ff81645, 0x2037ec4e, 0x33589dbd, 0x1057ef19, - 0x5853d5e3, 0x8f4f94ed, 0xb029953b, 0x15b20bbe, 0xb676ff36, 0xe9ef157f, - 0xbdf811f8, 0x2d3ee8ce, 0xda0dafe6, 0xc71009a3, 0x7944ed14, 0x5afd3e68, - 0xddb7bdfc, 0xdd7007e9, 0xa0115d29, 0x6d2fcd2b, 0xbf03b7a8, 0xf71bbf64, - 0x82092971, 0x8ef8349f, 0x077bf701, 0x9ed019f7, 0x9d977c1e, 0xef711fcf, - 0x059a359f, 0x7e06dcf7, 0xdae50e39, 0x0b746660, 0x784dbfb3, 0x51e0e4cf, - 0x5e3cd5ff, 0xd1efc69c, 0xefbb034c, 0x18533ec2, 0xc4fa3eec, 0x6c9043b8, - 0xfdfbe373, 0x882fbc16, 0x24f9d93e, 0x7f1b8f69, 0xf1748937, 0xfdf823ef, - 0x09fe5903, 0xc81fa720, 0xe15bfda3, 0xeed893fb, 0x4affae42, 0x9211598c, - 0xc74bc7ce, 0xd9fd337e, 0xccfa5ef8, 0xa80f7ecd, 0xb047d78b, 0x5ff0603e, - 0xbdf8f38d, 0x328cf48d, 0x5f7aafcf, 0x49d97de4, 0x6e028eb8, 0x23b4678a, - 0x93d2f1e3, 0x029ff6cd, 0x3974f11f, 0x80979eb4, 0x7832fc0f, 0xb63ec0bf, - 0xea26ab8e, 0x9ce93c99, 0xde32f68c, 0x27931430, 0x07df7cb8, 0x3a839748, - 0x97a0d3ef, 0x847547a2, 0x2d48c3dd, 0x5457f003, 0x16f576b0, 0x7010f7e6, - 0x07e7e19c, 0x1e593b1a, 0x3ee799e1, 0x856f9ac8, 0xa81ff3f3, 0xff0bcfce, - 0x0124ed21, 0x8f5633fc, 0xc4575092, 0xc22d76ec, 0x6e8f7ec5, 0xdfc14e8d, - 0x3e3e0c0b, 0x2712fd11, 0xbc5ecaf4, 0x15d57607, 0x6d27a01a, 0x4fbf9731, - 0xfb8979b0, 0x6d3dc4dd, 0xc81978f1, 0x99b2fa66, 0x3b82eff8, 0x25138ffe, - 0xf14b0785, 0xff744abe, 0x52cd206b, 0x7e589af6, 0x9185ea3b, 0x2fea42f7, - 0xff827bf1, 0xb053e5bb, 0x9f806556, 0xd5e80260, 0x7fb676d3, 0x40225bc4, - 0x3cd96bbf, 0xb803e03b, 0x4ef882ff, 0x5bc45e83, 0x4e1e2825, 0x9e3eac4b, - 0x1bbc84ce, 0x1ba00f81, 0xa3be17e8, 0x9d9e7f7d, 0x763ff6c3, 0x17943f27, - 0xaa5e43d4, 0x490157d0, 0x0f7dc0d6, 0x024a1d27, 0xcec9e5d0, 0xc872e73c, - 0x292871f7, 0xe076f6b1, 0x0e7bc110, 0x73ff3814, 0x922efc35, 0x05f80a77, - 0xfed53b77, 0x5e787888, 0xfd401ca8, 0xc6985ff3, 0x800053c5, 0x00008000, - 0x00088b1f, 0x00000000, 0x7db5ff00, 0xd554780b, 0x733effb5, 0x79332666, - 0x84841e4e, 0xe4249840, 0x09308401, 0x0741410f, 0x68151048, 0x85280978, - 0x42100793, 0x17b6881e, 0x240cdb5b, 0x41b45a20, 0x768bd151, 0xb4544140, - 0x03414141, 0x58a50077, 0x56d56351, 0x880dcb6d, 0xa8311fbc, 0xadadff97, - 0xfb5bf5ff, 0x90ce649c, 0xf9b7b5a8, 0x67d9d83e, 0x7b5ad7bf, 0x3bdaf5ed, - 0x3f437cdf, 0x756109d7, 0x10f4422b, 0x116dce22, 0xa3109862, 0x42f382dc, - 0x11c885d8, 0xca8df3fc, 0x5c3adb89, 0x8df88588, 0xdaf9aaaa, 0x2bc89eb5, - 0x1f5c2deb, 0x774675e3, 0xb5f1bdf1, 0x28f250ff, 0x084c21b3, 0x5d3dfe87, - 0x1e310f88, 0x90ea7b8d, 0x460ca7dd, 0x09ac2e1a, 0x75ac5442, 0xa51a45fa, - 0xbacc4e6f, 0x4285e653, 0x5c6cc775, 0xe34ad899, 0xca2a6f96, 0x1fb29112, - 0xd0aaf341, 0xea9e55e7, 0x0a8752cd, 0xeaa8f6d1, 0xebf684da, 0x6a8f9e55, - 0xa51eb8f3, 0xdbd627ef, 0x9fa9cb5c, 0x273e7d0a, 0xc5d16b7a, 0x0ab794b9, - 0xf280bdab, 0x45da2d56, 0x54782efd, 0xb177f62d, 0x81f7aa3e, 0xf80ba0b5, - 0x3a894d60, 0x1ea8327c, 0xe39469d6, 0x7268f7bf, 0xc2fcd157, 0x63cc77e9, - 0xd1f7e2a3, 0xd1f44efc, 0xfc7f21e6, 0x82b13093, 0x45daeaf2, 0x2bdceed1, - 0xa1c27de1, 0x01727b45, 0x031eb95f, 0x18e3a19e, 0x7808bcf0, 0xbabd20c6, - 0xabf04bc5, 0xa0f5487d, 0x4be6bece, 0x98df80d1, 0xae47453d, 0x61b5f7c1, - 0xecda8c22, 0xcefe9c3b, 0x8b8f34ad, 0x3d4155ab, 0x193dd28a, 0xdbc68289, - 0x2e7cf96e, 0x4dbf73e0, 0xd2917acc, 0x47a7b7d2, 0x46fd285b, 0x21f51fa7, - 0x6a352709, 0xae7cf47a, 0x98b93edf, 0x9edcc7f2, 0x7aa082c4, 0x2ce9d63f, - 0x6b655f14, 0x718d16ff, 0x78d8d62a, 0x2e5e065d, 0xbf341d62, 0xfe118d8b, - 0x8b9704e5, 0x5fb8dbbd, 0xbf464f03, 0x4183c015, 0xa56f544f, 0xe38fa5db, - 0x114717b3, 0xe1b4d35c, 0x64e82e9e, 0x2e3483c1, 0xe51f5bfa, 0xff7de675, - 0x74780d71, 0x25969be0, 0x8f03fc0c, 0xbc6da44f, 0xde59be97, 0x93d10ab3, - 0x7d78d0e0, 0xcbdf42aa, 0x850984f6, 0xda532bfa, 0x9c09288e, 0xac14fb77, - 0x8c3cf17f, 0x9871f657, 0xf7c7e505, 0xf3c79f5e, 0xc12bc10a, 0x7a2bb529, - 0x96d698bf, 0xdf8209ea, 0x736d3ec5, 0x7d06be79, 0xe79bce74, 0x4c37bb51, - 0x4c5c5f60, 0x76467c23, 0xf801b1c2, 0x5df5c619, 0x6f6fa676, 0xb1d7e01e, - 0x7ac8575e, 0xfdeb215d, 0x0b7d3040, 0x29ebc68f, 0x82cc24ff, 0xdc0fe5ef, - 0x71a6e594, 0x8e3bdf8e, 0xce3c75d7, 0x75fd879b, 0xcffa953c, 0xe59d72bd, - 0x733ad00f, 0x8d9d65bf, 0xb757c64e, 0x7b6b8ceb, 0x3acb7c42, 0x6874ea37, - 0xab33f3ac, 0xfa8ada3b, 0x9cb155bb, 0x14fb6a8a, 0xcc8d7fdf, 0xd0d056bb, - 0x0f4936b5, 0xfc236bb5, 0x6685d7c0, 0x6e7f04db, 0xf1a01f27, 0x583d27be, - 0x8f8e1e98, 0x023c3f75, 0xea9f75f4, 0x9701b9f2, 0x9cfcef21, 0x57efc7f2, - 0xb1f9025d, 0x0fc47e12, 0xc70fe02c, 0x73278b53, 0xb5cdaf7e, 0xb4f9fa82, - 0x047f6ff1, 0x63dc5cfd, 0x5f5e0b73, 0x90b3fdf1, 0xaf82f9a7, 0xc66e5c11, - 0xebce54b8, 0xd619ef57, 0xe8f17288, 0xbba65760, 0x0214be0b, 0xaa358ae7, - 0x01d21f69, 0x3ed5e3c1, 0x3ac6e290, 0x8713380c, 0xa83a9acd, 0x4fc81e13, - 0x9709d41f, 0x9ad0bb5a, 0xfb12fbf8, 0xfc414194, 0x9749f00c, 0x3cff44e7, - 0xa2d2c7c9, 0xc873f683, 0x8ff942fc, 0xff48cf51, 0xcc57c1d2, 0x705178fc, - 0x1950e09e, 0xc21c5f92, 0xca42aa37, 0xb7ca43ab, 0xf99cfaf7, 0x13f8e840, - 0x31bee4d3, 0xc3aa58e0, 0x9145bb71, 0xc53ee47c, 0x2d7e89bf, 0x4bedbab5, - 0x8e2ffe69, 0x4fd0f311, 0xae385599, 0xced97de5, 0x8ab52beb, 0x7c02b086, - 0x633d70f7, 0x435fd4dd, 0xc3e51c58, 0x7aa21f25, 0x7941ec13, 0xf31adf83, - 0xf0934f09, 0x5bc5d230, 0x83c78d9d, 0x14dd59e0, 0xeed7ca6b, 0xee3c6e4a, - 0xc62fcce8, 0x6ff4c92f, 0x387ead22, 0xaa7f22e0, 0x8c1eb577, 0xb249fa20, - 0xd469e168, 0xff83c5ef, 0x66eb9d1b, 0x262f0fbc, 0xe9a816fc, 0xf5a61d2f, - 0x3d56edb6, 0x9befd09b, 0x5f11fcf2, 0x1b787a5f, 0x9bd9af7d, 0x7775ee21, - 0x8e143fae, 0x8a5d7717, 0x17efa74e, 0x05c3d90e, 0xcda501c9, 0xd1ed63f1, - 0x84babfbc, 0xbb875bbb, 0x6b05dfd1, 0xa094f46b, 0x6b44177a, 0x7a20d4f4, - 0xa975dd29, 0xfc31e44e, 0x1f106a7c, 0x8f4f74ff, 0x2f7d2ab1, 0xb1af7dfb, - 0xe9c74a16, 0x736fdefd, 0xe686b93f, 0xe61ddbed, 0xbef34cd9, 0x0b2ce6f0, - 0xb3785fda, 0xea7f4f42, 0x4fb3f4e5, 0xb47e3153, 0x31bbd245, 0x293488de, - 0x8e59954f, 0xfc1a313e, 0x699ed5ff, 0xe59d69f5, 0x2c829665, 0xad9b79e0, - 0x7de62e6d, 0x95ab1141, 0xc67eceb8, 0xfdb9b9a5, 0x9f27dd85, 0xf4f87f00, - 0x60053efe, 0x6776172b, 0x7e5469e7, 0x5921e3e1, 0xc2f7ea2e, 0xf01ec97d, - 0xf7366d85, 0xeede994f, 0xdf60f289, 0x9c61fd1b, 0xf77fe825, 0xa435c355, - 0x52f9cb1f, 0xe3934f3e, 0xce8294fa, 0xee2da37e, 0xbf028f5f, 0xb3cdbdf8, - 0x7fa59299, 0x8b19e8cf, 0x773f61f5, 0xd5b28781, 0xe26dc261, 0xde782b27, - 0x8763c2a5, 0x1172841c, 0xa2e55f44, 0x6fcfbf98, 0x405f7f34, 0x17df027c, - 0xaf7f37ae, 0x5aab8d10, 0xfc8b7d69, 0xf682efe6, 0xfb112f8f, 0xe269f8da, - 0xd6f17ef3, 0xf54cc26f, 0x0fe74f84, 0xa5c7e60e, 0xc7c11fb4, 0xfefc579e, - 0x3defc015, 0x7433af2a, 0xd2d3cb5d, 0x448f1d78, 0x6b6e63fc, 0x598f5e10, - 0xe0893584, 0x1c2ecc7a, 0x47e80549, 0xbeab9c08, 0xcdfe613d, 0xfedee4d4, - 0x3296a55f, 0xe0b24bdf, 0x05c3b83c, 0xedfd47ce, 0x7e8a9939, 0x791756ca, - 0x77e6835b, 0xe47de6d1, 0xdf5790e7, 0xf54d7e23, 0x37f58d8e, 0x1d79a58e, - 0xd4f557bb, 0x33af3177, 0xe3f99f24, 0x28f71e09, 0xf2843fc2, 0x2d4c9ccf, - 0xde9cbc21, 0x34b5327c, 0x3115fe98, 0x8d1e982b, 0xebc26694, 0xf489ac82, - 0xeb05ad18, 0x89d7ad09, 0x0d7cf35f, 0xb1553a78, 0x787a2ba4, 0xe54f7414, - 0x05577f39, 0x3d9acee4, 0x33e83f36, 0x0f17e362, 0x6cfa0adf, 0xda40b9b6, - 0x2f547bb5, 0x5bb174e4, 0x1ce267f5, 0xba34fe6b, 0xeecce712, 0x68352e21, - 0x170e74dd, 0xb0b97ce3, 0x596252eb, 0x1933f72e, 0x9eed44f2, 0xdfa03c87, - 0x5cf1e6ee, 0xf1affa9a, 0xff99af3f, 0x20fdcf9d, 0x81f046f1, 0xc0b2278d, - 0x3e0f89df, 0x99fd8697, 0x791db5f5, 0x83875a21, 0x2c7e68fe, 0x7ff45fbf, - 0xa3a5f2c5, 0xbbfaf559, 0x349ec3c0, 0x07ffc33b, 0xcd026fcf, 0x7e73b12f, - 0xe03d9f34, 0x6b3cc6cb, 0x9c766ddc, 0xd11d17b3, 0xb4a7e079, 0x89f989a0, - 0x06e4f9fa, 0x289b2d7f, 0xee16bf88, 0x09c2bf9e, 0xf151a179, 0x6f280f40, - 0x2adcf956, 0xddfaa0df, 0xecc29784, 0x213bf6bb, 0xe5443e9f, 0x3abc74d4, - 0xa8b38fea, 0x54fbc2fe, 0xf8dbefce, 0x80da3fd3, 0x11360dd7, 0x47863c06, - 0x63c7d26f, 0x3e916879, 0x37cd45bf, 0xb7a0569d, 0x013d51ec, 0xe51cdfb4, - 0xd5b2f7c1, 0xf4c163b6, 0x50bf1f35, 0x2bd7f37f, 0xf81a40fe, 0xc2fcb984, - 0x27ce9f30, 0x5c6fbe42, 0x027f7535, 0x89eb2b52, 0x72e6fc8b, 0xf34ebcfc, - 0xdf7fd5a9, 0x17a6b99a, 0x29c173f0, 0xabf60b44, 0x1df595b5, 0x054d6811, - 0xfeec2f1e, 0xac78152c, 0xb27ff57d, 0xebf81744, 0x51cd4fd8, 0x84222709, - 0xc6e74b38, 0xfdd01637, 0x5dc5c9a5, 0x8fb17fd4, 0x6d5b17dc, 0x63905ebe, - 0x8afc6ff7, 0xddc5c1f9, 0x17575f5a, 0x5fb9dbf4, 0x124b4e7d, 0x205380d2, - 0xbae4da1d, 0xe484fb11, 0x1f417bc1, 0xdd4d569b, 0x6be77944, 0xa2424836, - 0xf7923336, 0xfcc7f60b, 0x7d8d7ea0, 0x017c15b2, 0x1fc930e9, 0xe523ec5e, - 0xbcbad584, 0xfb5f75b0, 0xe62ecce4, 0x26cd3ab3, 0x923edbcf, 0x2b4dcc6f, - 0x9c874f0e, 0x0345f161, 0x75ebc21f, 0x157c1027, 0x97eabe9d, 0x3df0512d, - 0xda723449, 0xfa71345b, 0x245a10b8, 0x0b8f0bea, 0x4fa21670, 0x7bc7e02c, - 0x31abd79e, 0x8e89fcdf, 0xd06af03b, 0xf8562f83, 0xeaefd337, 0x63508746, - 0x46b5ed20, 0xa0d451a3, 0x4beebfa9, 0x540fb6e5, 0x3ed49fd6, 0x2e3d3e06, - 0xc8cbf7e0, 0xf8c131e9, 0x74b877db, 0xdeabfa02, 0xf52e7a49, 0x4d877e77, - 0x5957a004, 0x3d50bf69, 0xec2fe1db, 0xcd4be069, 0x5cbc808a, 0xaf7c794b, - 0xfaf5651d, 0x9792e083, 0x9a91e12e, 0xbb70c59e, 0x9a1ef560, 0x9573fa08, - 0xdbd721da, 0xc04f970e, 0x2a4b6379, 0xfb5e63b5, 0xa4758f0e, 0x56b16f01, - 0x9aab37de, 0x5c5b718d, 0xf62a3fe8, 0x436f9e03, 0x534445ae, 0xc28f86bb, - 0x874c0cfc, 0x3a6143e4, 0x85021b5c, 0xf817770e, 0x14c289f1, 0x77ca8231, - 0xcf3013a8, 0x1752aef3, 0x958b68f0, 0x9b308776, 0x9af40277, 0x78b8d8b0, - 0x7a446fcc, 0xabffcf06, 0xcf3c25d8, 0x80bc48af, 0x7af241be, 0xbd0df231, - 0x7d8655cb, 0x8fbc23e3, 0xfc721d6b, 0x9f2a3da8, 0x43a462a3, 0xbbefdbe7, - 0xc89c68ca, 0xd024dabe, 0xa89f3183, 0xf00baf61, 0x858b1ce7, 0x3786b3e5, - 0x2f80d722, 0xd21be518, 0xf819bd25, 0x75609958, 0xae3c7f81, 0x574ae7d3, - 0x6820a3b1, 0x161eb69d, 0x0ec55e1d, 0xbdbb69c0, 0x97ce10f8, 0x738efa36, - 0x54d27f73, 0xaa14f407, 0x273f4167, 0x64c768ea, 0x0ee9dfa3, 0x424177c0, - 0x5bb478e9, 0xc2ac9628, 0x5eb85b7e, 0x3e208115, 0xe39360db, 0x211cb82e, - 0xc73a4302, 0xe3f8405d, 0xf9a397f6, 0xd653837b, 0xfb92886b, 0x2974cee7, - 0xd3d4ae2f, 0x83fa7ab5, 0xccc7baf9, 0xfec7cfd7, 0xe4a94b71, 0x53a677ef, - 0xeb4ad5bf, 0xab268878, 0x80edda92, 0x973a89ef, 0xcd058408, 0xc6758af7, - 0x38d0408b, 0x3b2ef51d, 0x183e2045, 0x47c66e1f, 0xb9237ae7, 0x125d44fc, - 0xfefbb1c3, 0xec704c53, 0x04c33fec, 0xcffb2bc7, 0x7513f2e2, 0xffd1df39, - 0x4ffa6ec0, 0xb3bfcd33, 0x5dfc7edf, 0x82fad2ec, 0x22eddcbf, 0xd374c07e, - 0xbb2676ca, 0x7606fda2, 0x9871f12f, 0x95f7dc80, 0x0576cb53, 0xe96d87f1, - 0x0b9f5d76, 0xfadf80a4, 0x6b4e3ac4, 0x8f1a5d77, 0x0be26ef6, 0xcbd0e76c, - 0xcf1b456b, 0xfa02fc13, 0xbab648bd, 0x96977cb9, 0x98c8bd0d, 0xf33c8747, - 0x859f48bb, 0x9ed841f6, 0x1f6347bf, 0x4db6b45f, 0xa9aa7d86, 0xde088d59, - 0xfdf407d7, 0x17cfb631, 0xd5d7b079, 0xbdf11da0, 0x9c5dee9f, 0x84d4f80d, - 0xde61e5b5, 0x2dfef7fb, 0x57c8e70f, 0xc5f7167b, 0x9f54adf7, 0x5b7b0fe5, - 0xbfa8278d, 0xb3e5c27e, 0x9b4ce88c, 0xfa1ffdf5, 0xfa9eeb7d, 0x36c7985e, - 0x2e483dd8, 0x56f659ac, 0xb078f1c6, 0xe083ef21, 0x16f8825f, 0xa6bb43eb, - 0xdf2063a9, 0x0f32487d, 0x96ee87e5, 0x3ed0c372, 0x83496fc2, 0x2ce1f7dc, - 0x619a89f0, 0xe1541776, 0x9616fcf0, 0x3987c3b7, 0x9f9f385c, 0xebc193ed, - 0xc84e43b3, 0x78a2fb40, 0xf154e7a6, 0x1b6dc9af, 0xe04ff642, 0x68db350f, - 0x75b56abc, 0xf78538f2, 0xa9f031d1, 0x78bfb79a, 0x135fd747, 0x8c5a9f81, - 0x5f78f04b, 0x432127ef, 0x9a7a893b, 0xabbef5a3, 0x9b8cdea8, 0x1fa15393, - 0x99fae895, 0x19404898, 0x1068fcc9, 0x9e5720ec, 0x7a0f52db, 0xc034d14d, - 0xf0ec97c1, 0x981afce0, 0x71c91c22, 0xf4fed0d8, 0x57ee34a9, 0x2ec316e9, - 0x03de60aa, 0xdf3d35f4, 0x2c6969ab, 0x38fe939f, 0x3b3fd1d0, 0xfbc325ae, - 0xa30bf077, 0xdf3787fe, 0xe2eb483a, 0x79e430dc, 0x36e9bdbb, 0x3aadb3cc, - 0x9847f592, 0xc9eed0f3, 0x2a02c39b, 0xc8b68aec, 0x3fe7d0d5, 0xb07b988a, - 0xfee3c107, 0x83222d28, 0x799acdda, 0x95e42ac3, 0xa5eef1fd, 0xd692e7a0, - 0xd3e7c0e1, 0x83262d4e, 0x6872afc6, 0x8969137d, 0xd968fbe7, 0x8be43831, - 0x449e25e3, 0x2ee2a0f1, 0x53e72fe7, 0x0ff1c8a2, 0xe8496947, 0xf2d2c4a7, - 0x66f855c4, 0x837b616d, 0xfdc1e868, 0x8a8bb79c, 0x037fe4ae, 0x75f4470e, - 0x6b89b3ec, 0xf6fad32f, 0xd4f18dad, 0xefcb7cd3, 0x96b7399e, 0xe296f9d2, - 0x9a6a80c4, 0x55d61677, 0x9be92be5, 0x79f3f24c, 0x65ef3e9b, 0xaeadbcfa, - 0x1cfde0ac, 0x437aef3a, 0xc285f95e, 0x50ff20fa, 0xac5f15fe, 0x87ca5eff, - 0x307d2e59, 0x20d6e70d, 0x3649db0b, 0x22ded384, 0x7d5df23d, 0xbed38f9e, - 0xf7f1c473, 0x149ef8d5, 0x3d27db2e, 0x7ec3f16c, 0x37763c50, 0x9ac9e9e3, - 0x634a8f48, 0x1db70895, 0xf0995072, 0xd9fc5cb2, 0x69edbf98, 0x661575a5, - 0x6e01d768, 0xa92de2f3, 0xb43cf01f, 0x6f205381, 0xf8eb928d, 0xd7937916, - 0x6cb85531, 0x3589942c, 0x531fc816, 0xf329725d, 0xa63fb915, 0xe30daf09, - 0xd71a10cd, 0xbb05c3fb, 0x1fc4fa17, 0xbcd10ba0, 0x7f1f0a67, 0x9cfc2d9f, - 0x5c022ade, 0x95a2c7ff, 0x89bc06f3, 0x4825e63e, 0x53d938fa, 0x8cdff865, - 0x9117bf79, 0xad1967d7, 0xd923ca63, 0xad5fac99, 0xf9f0c1eb, 0xd14f79ae, - 0xeff686e9, 0xfd83f43c, 0x99fa9d3b, 0xfec8637a, 0xe061ec2d, 0xf6dbf333, - 0x877b4b51, 0x4c9914fe, 0x475eb870, 0xc5def5e9, 0xa9153fac, 0xf847c291, - 0xfaa51969, 0xf21c7721, 0xa0484f2e, 0xb9fddc75, 0xb77e83d4, 0x843dbc5c, - 0x46377fca, 0xd2dcf515, 0x64d4f2cb, 0xbdc99fbd, 0x9d869fc7, 0x2408b0f5, - 0x17b9a50c, 0x8f5ed65d, 0x564ef9a1, 0x52c435b7, 0xa4de84f9, 0xbdf104c7, - 0x5bb6121b, 0xd8ddd7a1, 0x627dfccf, 0x99df59ae, 0xc0551a24, 0x7350f279, - 0x0f807dbd, 0x0c8ad7d1, 0x0188b7a9, 0xdfee8062, 0x47fbb963, 0x13ed1f7a, - 0x0be1d92f, 0xbb433579, 0x3a5c7007, 0x18b9b3e9, 0x7ae55857, 0xd951de6a, - 0xe48c779e, 0xdf9d2f2c, 0x84e8ebc7, 0x08f29308, 0x6e48a7f2, 0xcea67a40, - 0x3a39e9cd, 0xa17e51e7, 0x67eb23ce, 0x7d803f14, 0x73faba56, 0xb772f02b, - 0x6ef9c253, 0x761faa67, 0xc6a68ab5, 0xe55e98f1, 0x4883a6ae, 0xe3c503cb, - 0x382ecc71, 0xd220e4b4, 0xb6f43bbb, 0x5fdd0e25, 0x5dbff3c0, 0xa3dbd3a7, - 0x8834dea6, 0xbbedc9f6, 0xf6ebdfa5, 0x4da7533e, 0xc6de404a, 0xa8e8eef9, - 0x3422b2fa, 0xa8cf22da, 0xb758cdde, 0xc1e8f9b7, 0xc9e75a78, 0xff3c11ba, - 0x9e5e75d3, 0x09bad9ff, 0xa33dfe9c, 0x27ae39f8, 0x6c79673e, 0xd6a3b6d2, - 0xe45faa14, 0xb7d8bc55, 0xdf857ad7, 0xdeb1744f, 0xf581cf26, 0x1f600e74, - 0xf534198f, 0xe9303bf1, 0xda276d0c, 0x5171b8cf, 0x3c99c611, 0x7a8ac4a2, - 0x2216bf33, 0x4e93ad3e, 0x8dee8bbf, 0xf8eb57f5, 0x6157bf3b, 0x1bdf9e78, - 0xdf6cf0cb, 0xf9031191, 0x8ccee960, 0x6f89489e, 0x046f7a1a, 0xd97ed7e0, - 0xff6df3c2, 0x8ef59c28, 0x774bf6d0, 0x7a89ec0e, 0x22df0967, 0xfb3cde48, - 0x83b87ffc, 0x71b395cf, 0x027d5f4d, 0xc957f6fe, 0x39b248df, 0x5ff818f1, - 0xd01e5eef, 0xce5d05cb, 0x02233d26, 0x6e8d5fe7, 0x427f0457, 0xb4b86cfe, - 0x217f0ee7, 0x17f62c65, 0x9c1373c6, 0xb9191cc3, 0x7f7087c7, 0xfd467e47, - 0x9258fcbd, 0xb9effa07, 0x63a48fed, 0xf34dadfc, 0xfa8c793f, 0xf8b7ef3f, - 0x9d4e746c, 0x5e174d17, 0x2a7e1f05, 0x777bed92, 0x9c2f342b, 0x717b9bc3, - 0x86b1473e, 0x2c39c32f, 0x73cfbcfc, 0x1975b714, 0x17aaadf1, 0x7a05ed1f, - 0x30608d7c, 0x5b5fca82, 0xed7cc11b, 0xc8e79b35, 0xb8f7f432, 0xfbe9efec, - 0x0bb63cef, 0x05d57de9, 0x65fa5277, 0xa1e31c46, 0x034581fc, 0x79ce9ed0, - 0x3dfd4c91, 0x80128af7, 0xbad06abf, 0x69922b7d, 0x1c37837e, 0x34a2f4b5, - 0x1ea529ff, 0x373ec0e9, 0xf9fd821e, 0x6e6e196f, 0x9a5b643f, 0xd96d829a, - 0x75c9ffcb, 0xe59bfe7c, 0x9f75dc82, 0x3a25ed8f, 0x4a0183e5, 0x348d99d3, - 0x8fd4b0d7, 0x6386340a, 0x6767af23, 0x6ff7b4f3, 0x49075815, 0x8977981e, - 0x91e7c3dd, 0x7811b7df, 0x78e5af3e, 0xf62bbf58, 0x3b7a0a3d, 0x707a25af, - 0xfa4cbd3e, 0x7fa8d5fc, 0x7cebcac4, 0xa2f7a9e5, 0x2189df61, 0xbf09d93d, - 0x78db7e48, 0xe3eeafd4, 0xf587f016, 0x09fae279, 0x8ecd4f80, 0x9fb91b9d, - 0xfa07872a, 0x4bcec56e, 0x2f205307, 0x993c20de, 0x321dc7a0, 0xaf42abff, - 0x56a5a547, 0xe652fc6c, 0x5f398a5b, 0xfc27da4c, 0xca4ca2fe, 0xe7e88f49, - 0x63cd68a0, 0xee24c97e, 0xafd7c4ee, 0xebe518a8, 0xb0c97cd3, 0x27e71b6f, - 0xfda97b9d, 0xb2ec65b0, 0x5bd8cb7d, 0xdf2e1953, 0xebb3dcf3, 0xdfd197e7, - 0x73e17623, 0xdf303f52, 0xc1be9ec0, 0xcdebcf2e, 0x2f4067c4, 0xe34d79c6, - 0xed93f5e6, 0x29afe0bd, 0x076832aa, 0x91e523c1, 0xbe379630, 0x62b3f8ef, - 0x6df9f156, 0xe1b55bc8, 0xd9f22f92, 0x885fed41, 0x37eeaed2, 0x7932760c, - 0x3bab0bde, 0xe3c8f217, 0xfa6bde51, 0x96d5bcb1, 0x39d0358a, 0x53e61d7a, - 0x95fc92a3, 0x457f2411, 0x73af7dc6, 0x2de51034, 0x5beffb42, 0xcd046c7f, - 0xf1290633, 0x86a468ef, 0x485a45de, 0x7d39fc97, 0xf3f8135b, 0x3f926143, - 0xbe610d47, 0x7433ac64, 0x07c4039c, 0x6f3be234, 0x11a339d0, 0x3917183f, - 0x7d78cac6, 0x907552dd, 0x3922e5ce, 0x1ada0802, 0xdef3943b, 0x61638228, - 0x2eb42aa4, 0x252347f4, 0x3ac7cdbc, 0x984427c7, 0xc42515ea, 0xbf8fb1da, - 0x1d55faef, 0x3cb86a4f, 0x8370d4bf, 0x7413babf, 0xfac87dbf, 0x776f7ae5, - 0x3abe630e, 0xeb7ef956, 0xdf15b22e, 0x8b8f3c09, 0x7373e7cc, 0x2394e45c, - 0xd475e09a, 0x7ae87be1, 0x1c25d743, 0xfa8e4fdf, 0x167c2289, 0xedcfc7ec, - 0xb66b776c, 0x5bf73eb5, 0xa2f36b82, 0x47ec0f5c, 0x70bed32f, 0xb54e9f80, - 0x0cdb9cb3, 0x37ea92d9, 0x5c7170f7, 0xdfba6bcb, 0x6f5b37dc, 0xbe7c14ef, - 0xc5eecf34, 0x615ef47e, 0x48ec1034, 0xd26fd2f5, 0x16f25b6c, 0xe5e6ebce, - 0x819a1e29, 0x69efc150, 0x97e47ccb, 0x095ebcfc, 0x817f0adc, 0x40bb73ef, - 0xfeb175fd, 0x5f94e9d5, 0x9e0c8bf7, 0x8fa447cf, 0x8abc62d7, 0xeb5be670, - 0x71c9bd62, 0xff979f04, 0xb279f2a1, 0x91f29f2e, 0x6ed9d7cc, 0x378a6eb3, - 0x04ad7e19, 0x36eb6f1d, 0xb05ef2ca, 0x4d3ca293, 0x26c4ffb6, 0xd7a2dfeb, - 0xfbf1d04b, 0xb4a74eb1, 0x683f99ff, 0xa0ac2393, 0x95fb77ff, 0x46fbc6be, - 0x17e19378, 0x933cac7a, 0x54b7986d, 0xf4c690de, 0x66d3dba4, 0xe8dcfce9, - 0xc31c0d17, 0x9fcb4f21, 0x3b37f3d9, 0x2a33df41, 0x1f21479c, 0x22b1547e, - 0x0cfd7a0a, 0x21840d4d, 0x917a6abe, 0x4bae43b7, 0x395eb8c7, 0x1fa1b96e, - 0xdf00ca06, 0x710e6dbd, 0x81ffcb2f, 0x96fac121, 0xfa45e781, 0x1a6eadbe, - 0x7eb060f3, 0xfe27695d, 0x72e51833, 0x6a45573f, 0xd57d07bf, 0xc1e1baee, - 0x54fbbd60, 0xbc7943f9, 0xcf71f4ef, 0x3c1f79d5, 0x6f39099e, 0xb8c6a702, - 0xf011fa1d, 0xd5f6fd49, 0xefda73cf, 0xdaf00b3e, 0x92fa94e4, 0x85e3edb5, - 0x359faf94, 0x09f7cf80, 0xd85e1d53, 0x8477daf5, 0xadaf61f9, 0xc5ee159f, - 0x44f7eaba, 0x985761f9, 0xd21befa7, 0x6fbbf8bb, 0xade98dbb, 0x667feeca, - 0xdaabb50b, 0x89e99fdb, 0x96ed95e8, 0x642357be, 0x6d37b479, 0xf79450e5, - 0xcd79fa64, 0xf2e18ee6, 0xe5c15537, 0x58ac81e1, 0x539b7782, 0x1375853b, - 0xbcfdb2bd, 0x1fbf2eca, 0xfa12e9d1, 0x96fffb25, 0x42bf7144, 0x8f3f6bcf, - 0x584f7d67, 0x91f3c9bd, 0xaf207dbf, 0x7dcbb347, 0x7ea46a21, 0xe725c478, - 0x9e39a475, 0x8f4185f7, 0xdcb78a47, 0xef809593, 0xfcd2af24, 0x0d4cb2fe, - 0xd06e1fc0, 0xf2f5329f, 0xbb5157db, 0xd9555f4f, 0xd7e7336f, 0xfbe30f8b, - 0x13d5159c, 0x6bbcad39, 0xf5cb9f32, 0xa2eea71f, 0xa7a984f2, 0xe06bbfd8, - 0xd9954e7f, 0xe9989a9f, 0xdf813355, 0x83f6ff5c, 0xd9e1ff54, 0xaf001627, - 0x473533c3, 0xf6dbec26, 0x4cff97d6, 0xfe5d6df3, 0x36a3d627, 0xf8116b44, - 0xd3f7717e, 0xc566bf5c, 0x7e802cff, 0x74956350, 0xb5db9c63, 0x91bf3d3a, - 0xffa2c5a9, 0x63bf15aa, 0xb722223d, 0xbbd7f245, 0x3a3f1fbe, 0x65f9bcd3, - 0x0e2dda85, 0x54e1ae6f, 0xfce1e7f5, 0xa204ab3b, 0x2b860c95, 0x5ce775eb, - 0x47e06881, 0x72b948b3, 0xbf10d6f1, 0xa8925031, 0xdda88bdb, 0x8f5526e2, - 0x41dbf457, 0x17f5a1a7, 0xf7ae77d3, 0x8a57bf3d, 0x763df926, 0x30d7fdd7, - 0xfe0045fe, 0x64cf33ae, 0x9c3d026e, 0x5674f9df, 0x34369fb0, 0x72be72bd, - 0x7df4e7fd, 0xd8be8e73, 0xc2db6f40, 0x0b85f64c, 0xf4eb24cf, 0xc2e9e926, - 0xe7ecd933, 0xd9f7d44e, 0x0967c505, 0x085fbb47, 0x9e10678e, 0x971ce1a6, - 0x0e1a6de3, 0x9d61fbb9, 0x6f8e2e2f, 0x67be0e1a, 0x68e141f0, 0x41bb63ca, - 0xf41e534e, 0x8a7f8364, 0xfe2ca6e2, 0x42ca6fee, 0xd22d97fb, 0xa7cc630e, - 0x8e14b9f2, 0xf0b5a27b, 0x6e7caefe, 0x8de426e0, 0x929dea71, 0x253bd4ef, - 0xb75d097f, 0xe8ed2996, 0x1ee64fa4, 0x3ea4b3a7, 0x5c82f496, 0xde6593e4, - 0x370bf329, 0x6fe1d894, 0xbcc9b7af, 0xfd897d6b, 0x35f7e618, 0x4fc4b569, - 0xc5bf7473, 0xdda97f02, 0xfafefb0b, 0x3f1ce1e5, 0xcf3edb31, 0x7af6694b, - 0x035c69bb, 0xe6fdfd0f, 0xf9f48bef, 0x0b890df4, 0xedb6a5ea, 0xf639c30b, - 0x8e32e8a4, 0xb4a64960, 0x6cfb3ee3, 0xaa917c47, 0x6dc2dbeb, 0xea5ba1d0, - 0x8fd78c1b, 0xef5e06ed, 0x2ff9a148, 0x5ea5e3d6, 0xfab848b6, 0xe37c959e, - 0x052d7ce5, 0xc005d5e7, 0x2c5ce71d, 0xef2173e5, 0x7919bc49, 0xf0a15f03, - 0x82f1f15d, 0x9f95d814, 0xc7f694c8, 0x8f2c7c50, 0xe513de1a, 0xd4cf5c06, - 0xdc00ca1d, 0xa89d758d, 0x68e97af3, 0xafbfb4eb, 0x8c6877cf, 0x30477c8f, - 0x1d6fd77d, 0x20248872, 0xd5ab6e71, 0x5bd42583, 0xbf43f7fd, 0x36aadfa8, - 0x3b9704f9, 0x91739780, 0xbd41dffb, 0x0b621b05, 0xed180fa0, 0xf22fae17, - 0x7bcd0796, 0x5e3356e0, 0xf3993506, 0xf3997783, 0x0d06715b, 0xe5dbe7fb, - 0x21f9cc07, 0x93f9cc87, 0x3371dc1f, 0xea854fb6, 0xbe855fbb, 0x87f1e7f3, - 0x7a9f4e70, 0xe06895f9, 0xcb5ff16b, 0x0b8f420f, 0x3c21678d, 0x7c73d02a, - 0x97a6145b, 0xba5ae22b, 0xdc4643e1, 0x30627606, 0xdf0a54dd, 0x95da6b41, - 0xa68acff5, 0x6744bd9b, 0xcfdecb55, 0xecb37a90, 0x5ad36477, 0xd0cee43b, - 0x3be3bb71, 0xc6ebd222, 0x21192a3e, 0x365eaecb, 0xfe8a7c4e, 0x1e37bcd6, - 0x2bf258f4, 0x929be585, 0x075fb297, 0x3edd1cdd, 0x6f4e46fb, 0x30f0c09e, - 0x9b0b92ec, 0xe5144095, 0x8744235d, 0x8bf11f7f, 0xf1210da5, 0xe2426b9f, - 0xcb99d682, 0xf7daee17, 0x504710ff, 0xe38278e1, 0x678cae2e, 0x5e801ff4, - 0xb04a7959, 0xa9f2aa7d, 0xe5ccc26f, 0xf5f35d72, 0xade71875, 0xf1cb5df0, - 0xaacb577b, 0xa3fe38e2, 0x4ba8e973, 0xcb73853b, 0x5eaf7738, 0xf29551b7, - 0xfd84b7bc, 0x8e7691c8, 0x8876ac8b, 0xebcd0440, 0xebdd9450, 0xd697efa2, - 0xb2bcb147, 0xe85ce480, 0x270a948b, 0x627a4dc7, 0xbbc4eed0, 0xd565cb2a, - 0xd51e12f1, 0xb0fc51bf, 0xa8c3571d, 0x3293fc8b, 0xd80448bf, 0xf23a0bbe, - 0xf803ad06, 0x468bce0b, 0x59565fa9, 0x9f00fb03, 0xab68738e, 0xad155eb9, - 0xc838a3f3, 0x35efe67b, 0xd7eb8da2, 0x2c26faee, 0x3d907bf8, 0x435ef59a, - 0xf97556ff, 0x3865fd4a, 0x20744fcb, 0x6cbe8384, 0xeebedcba, 0x6823921e, - 0x7b0d2b7d, 0xdf295af8, 0x9e51b2dd, 0x679f2463, 0xd6eb4e01, 0xef867c92, - 0xce206fa4, 0xf70a2c44, 0xea5ef94b, 0x6766eb0b, 0xf2f45cb1, 0x400a5e3f, - 0x487b691f, 0xbad2bb61, 0xbaefd97c, 0x3973fafb, 0xe3c2a7f8, 0xb61cb184, - 0xde518a6e, 0x4f91f587, 0xc864c530, 0x1ef7faf9, 0x4bdefe6e, 0x3ec166f5, - 0xb2741e22, 0xfb90c47d, 0x2ebeb90d, 0x1ac9cb56, 0x75feb9d6, 0xf0516db1, - 0xf88a89bb, 0x6cb725ef, 0x36e3cfd6, 0x2afc3f5a, 0x83e295c7, 0xf5198ff0, - 0x73c96646, 0xef58f865, 0xfb1ebd16, 0x532dca5f, 0xe68ebdee, 0xc5b0fe55, - 0x81a17b0d, 0x66f5e107, 0xd7c70e01, 0x77400b3a, 0x7b4ac7c3, 0xc97c91d9, - 0x0a8623e7, 0xab1a378e, 0xcb363bf7, 0xc2934a62, 0x9fa91e89, 0x1ed245e3, - 0x98b4351f, 0x132496ed, 0x6e2aebcc, 0x4fdeb265, 0xf7f8bdb9, 0x4f98bba3, - 0x4a145d07, 0x6df8fbf9, 0x2f3926ca, 0x0e27c72f, 0xf6c9c07f, 0x39fae3ce, - 0xe881e064, 0x0fcb1868, 0x0d8b5f3a, 0xa0b59ba1, 0xa0879c07, 0x6e982507, - 0x8b7174cc, 0xee2be122, 0xbaf7f293, 0xe8379958, 0xf13ff482, 0x229ba0bf, - 0x4eeff0c1, 0xdbd6340f, 0x74481e9d, 0xd07408b0, 0x0e842f51, 0xec3fd584, - 0xa542fcdb, 0x2b876223, 0xab148284, 0x17ce21f0, 0xebc32467, 0xb11fab1e, - 0x12adbd78, 0x92ac7d2f, 0xf1b4e8ee, 0x7d701785, 0x4b7de22f, 0xbc285c1e, - 0x4524bf54, 0x1fad7db0, 0x713155c9, 0x45204edc, 0xbb0a8e58, 0x5f68a513, - 0x2ffb2312, 0xfe3829e9, 0x5af3fa8e, 0x36e674e2, 0xc15efe1c, 0x47da0572, - 0x9f7b7017, 0x5af7b645, 0x219bed29, 0x95b698f5, 0x5cbf1c61, 0x2c9f7772, - 0xb1c4c9d0, 0xa2393a66, 0xde9195d3, 0x8dd6ed94, 0xf0249e75, 0xfe86d283, - 0x3bd4de7c, 0x0277ab8b, 0xb047cf9f, 0xeab259fc, 0x618693c7, 0x7bc42f7e, - 0x9333c280, 0xa83fb3b7, 0x4ff661b4, 0xb4be843e, 0x2bdfc9d5, 0x59f5b5b2, - 0xf715ff90, 0xa1f49ddc, 0x7b01c674, 0x9ad7b512, 0x957f9ca6, 0xedbec9d2, - 0x989e40ef, 0xfae55d3c, 0x3fb48593, 0xce39068b, 0xd6e7df24, 0xd26fea24, - 0x69c38528, 0xa95d3a8e, 0xa40fc1b7, 0x2ca9f7e3, 0xe47f9745, 0x5592813d, - 0x73d2b27d, 0xc9213fe1, 0xfd390bb8, 0x18fea353, 0xa5e40365, 0xfee4e3be, - 0x1fa3ea33, 0x4b3a7bf4, 0xd5bf55ca, 0x09e462e1, 0x7cbf5cae, 0x8cd1d875, - 0x40b6a468, 0xfde9a536, 0x7584bec7, 0xe3174c4e, 0x77ee03d7, 0xcf1362aa, - 0xf984adb7, 0x1b965442, 0x4291abf4, 0xd6e3facd, 0x8f27ccfe, 0x7a3b698e, - 0x6e8fe537, 0x8ced241e, 0xbe617dba, 0x707cb04b, 0x77e48c74, 0x98239b6d, - 0x5ab88ffe, 0x3da4e2a3, 0x650ded8e, 0xb67c493a, 0xf87efeac, 0xed22cbb9, - 0xcc7e7147, 0xc71a687f, 0x53ad9427, 0x07b86103, 0x6f6cc6b0, 0xded48aa8, - 0xb5087ec6, 0x07da841b, 0xa3a03340, 0xd30a35f2, 0x8f7adf61, 0x9cf9993d, - 0xcafac2e2, 0x70fd0323, 0x9c7b940e, 0x857cc71c, 0x826be0fd, 0xb9d870fb, - 0xb5890705, 0x009f6b67, 0x258d254e, 0xe446efac, 0xfabfcc6a, 0xec1704aa, - 0x26fe9d17, 0xbe0b5ec2, 0xc64d6d64, 0x9655fcbe, 0x3130f19b, 0xc91595ce, - 0xfbe4ed74, 0xae6d4711, 0xe8efcc2c, 0xe705a74a, 0x9215c4ed, 0x39df69be, - 0x1ee18f70, 0x3f0708ab, 0xfb259ad8, 0x5adcb39d, 0xbdf291bc, 0x151ac21d, - 0x67cafa07, 0x5fd85efa, 0x75e62dfb, 0x046217ea, 0x35b289e4, 0x74bce56b, - 0x96d610fa, 0xe71a78c2, 0x02b4e6d4, 0xe43a01d8, 0xdb63fedb, 0xba0ec701, - 0x3d30ae98, 0xc10e7ad0, 0xbfde9c8e, 0xe9ca32f4, 0xcbd03efb, 0x7e81b1c4, - 0x522f1b88, 0xb6be38ab, 0xe078493d, 0x6d176c77, 0x93b48f2c, 0x67be023c, - 0x9f8319f0, 0x1d785d10, 0xdef89d89, 0x22534752, 0xceb5be1e, 0x75b3e9c1, - 0x7825612e, 0xe24bab6f, 0x6e750bfc, 0x72ea9b4e, 0x758bfbf8, 0xa8efce1e, - 0x97f9c11b, 0xdf9cbceb, 0xd3813755, 0xf98aeb57, 0x08afc1bb, 0x0c97cc3e, - 0x27f063be, 0x3e0cbe83, 0x73574a15, 0x17b8cc09, 0x1f99ed41, 0xeb107c1a, - 0xf27414b0, 0xe9cf0327, 0x092fb14a, 0xceb450fc, 0x5228ff06, 0x0aff3dcf, - 0x22bdb9c1, 0xed22ed92, 0xf6c1f242, 0x079f0748, 0x0bb176a9, 0xdbfa89f6, - 0x0eef47bc, 0xad6f873a, 0x88358450, 0xc4bc7f8e, 0x7441ac29, 0xac596f3c, - 0xd9673f29, 0xa4f46ffb, 0xd18ddffe, 0x1e69b372, 0xe2797e47, 0xf7d13ff1, - 0x4cf2fcdf, 0xf34ef026, 0xc608fcd8, 0x9f5c2bbd, 0xd79cab47, 0x9796765d, - 0x7d4b86fa, 0xd4b86fab, 0x08e3f0b7, 0xa23dcf8a, 0x2d24a3e3, 0xb1a79df6, - 0x9baeec6f, 0xb44ec047, 0xfa4bde52, 0xf2a3f804, 0x2bf8e8bf, 0x70c6165d, - 0xf7d06d2d, 0x36dc706b, 0xb258f5c1, 0xf14ef960, 0xd7bf010a, 0x03d85fb1, - 0x63882b24, 0x40afc38a, 0x6be52276, 0xab98ec0e, 0xe411f77f, 0x21d96576, - 0x4735b396, 0x087fc724, 0x705ced9f, 0x83b2ca7f, 0xf6b44f5c, 0x466fc536, - 0xc1daf50c, 0xc0e34037, 0x7ece695f, 0x1a2efd81, 0x547fbe15, 0x5f2f7fae, - 0xa2e298ad, 0xf2ab6467, 0x959645de, 0x4259f3d3, 0xf91a473f, 0x96e832bc, - 0x61c708f8, 0xdbe63796, 0xe7f10417, 0x597bfd52, 0xa714c58e, 0x9d967f79, - 0xcd8f39fb, 0x9bdefd49, 0xcf9f6e93, 0xf7cdcffc, 0xa5fa8c05, 0x60ab0539, - 0x835d2e4f, 0xf6cea6a8, 0x7d56d925, 0x7fa92e5e, 0x8b5ce839, 0x2ea2f8e2, - 0x9e4307cf, 0x475f8539, 0xef59fcf2, 0xb9e17caa, 0xac8fe017, 0x9f1873fc, - 0x75839553, 0x7fae4afb, 0x839634f8, 0x70ca91bc, 0xff12e1c8, 0x35fdcf85, - 0xb55d711a, 0x97bda43b, 0x6b48a3d2, 0xfb60aaee, 0xf6878d5e, 0xadf81c49, - 0xfaffefd9, 0xfbe67f0b, 0x14b0849d, 0xe3986e3d, 0x7c766ad4, 0xb06bf1ca, - 0x7286f9c7, 0x1d5f1c7f, 0xf956beda, 0x4257f59a, 0x68a7c32c, 0x3c8997cf, - 0x12979d8f, 0xf76ae7c1, 0x2aec4cac, 0x1fb4288e, 0xb0c1ce23, 0x358ad5ff, - 0x59cfc39f, 0x9384d77b, 0xff65de92, 0xca1eeda1, 0x31384a8e, 0xeec62050, - 0x5893b62a, 0x2c9fc705, 0xed38edd5, 0x63f64cfe, 0xd7772777, 0x2446a7ae, - 0xdd5bb592, 0xbeb38831, 0xae84c428, 0xb649f4f0, 0xd3cf6b94, 0xfb3f823e, - 0xe59536e2, 0xa2db8bca, 0x6cd43f78, 0xe220f07b, 0x529e6b04, 0x2d58edd8, - 0xafce385a, 0x1c2a8766, 0xec1de7c1, 0xcfddf147, 0x5173f173, 0x8b5f404b, - 0x66ef149a, 0xc3bb4f9a, 0x6823d31d, 0xbe80af3e, 0x87173488, 0xff470d35, - 0x079ffcc6, 0x37920b7f, 0xc83f3517, 0xef548df1, 0xbf37cb02, 0x3c38e08d, - 0xc1dec93a, 0x186ecf3c, 0x45f5fec2, 0x586bdb4d, 0xe116d83e, 0x8ce9e982, - 0xe40f7ccd, 0x81de3e80, 0x9c8f296c, 0x67d1edd5, 0x1f59505f, 0x2fb13cc2, - 0xb871e8cf, 0xf537bb46, 0x4b666f76, 0x5b26a7f9, 0xfea34fee, 0xd1a3a6a2, - 0xc9fea8fd, 0xfa73ef5d, 0x166fbebe, 0x3df0b645, 0x223b93cf, 0xc9e09ef8, - 0xfe39ff1d, 0x7cef1a35, 0x250498d3, 0xc89d9f68, 0xba7dc9b6, 0xf32fc641, - 0x13d61725, 0x673d789a, 0xac28a5b7, 0xa4de032f, 0xf1dd9fb7, 0x3643df12, - 0x1c1febe4, 0xb14b382f, 0x18a3dc86, 0x8d72083d, 0xd7bf55a3, 0x63dba6d1, - 0xaffa6ffe, 0x5927bfd1, 0xe471f58a, 0xc4610d3d, 0xbd64b86f, 0x27b73522, - 0xc1dcddf6, 0x97b899ee, 0x7192de2d, 0xfbb7a297, 0x737fe811, 0xbb678ddf, - 0xbb9b52cb, 0x1c5ff227, 0xe0958526, 0xce887733, 0x875a9257, 0x347bbec1, - 0x8615ca4d, 0xb56aad3f, 0xbf04bc22, 0x3e67445e, 0xd0aafde4, 0x49c90760, - 0x563d7c67, 0x71daf161, 0x99d9463e, 0x3bb7ea2e, 0x75bec137, 0xec7c2ec4, - 0x29d17b7f, 0xd2e927fd, 0xf618f20f, 0x7155a517, 0xd878ac81, 0xa9ba74f1, - 0x41e54a9a, 0x29b553f4, 0xea390590, 0x2bda5d9c, 0xa9fd0e51, 0xabd640aa, - 0xfd14e9d7, 0x69a3dfa0, 0xf72c0bae, 0xd0128cee, 0x44af2c3f, 0xd3c8bb49, - 0x41614dce, 0x1cbf76e7, 0xc777118b, 0x66df4afe, 0x0bcc3f39, 0x7b22fcf2, - 0x5de41663, 0xd145dc63, 0x39de3c8d, 0xe145bc7d, 0xa39fd28d, 0x3ea211c7, - 0xec136f8f, 0x267b6a77, 0x33e6e58c, 0x632f2dc9, 0xf4cf33fc, 0xa387b8e7, - 0xbb05fe69, 0xf1c9dcb8, 0x86cf95e7, 0xd3df3005, 0x5db144cf, 0xca4db4eb, - 0x12a3a763, 0x143b1e59, 0xf65cf0f5, 0xa6153d63, 0x5a742ec0, 0x9424f611, - 0xf2c1ee6f, 0x32dd6540, 0x1254d7f6, 0x4b1c817b, 0x7fc804e9, 0x67f737a7, - 0x37e9d17b, 0x415cbe55, 0xbbe357df, 0xfee71a26, 0x0880f58c, 0x799e23b6, - 0x83fd6ff6, 0x5a463bfd, 0x3ed994f9, 0x5183d066, 0xf923945e, 0xd48e5160, - 0x71c86e53, 0xd11d5a71, 0xaf3a70f4, 0xc207f253, 0xb481eb03, 0xef61131f, - 0x3bb4d23f, 0x9c048951, 0x09ff5903, 0xfa956fb8, 0x366d99d6, 0xbe5553f6, - 0x3b65e512, 0xf157ddd4, 0x554ac97d, 0x1695e3ca, 0xf950df79, 0xffb656e5, - 0x2ce33fd4, 0xde083c00, 0x6db6dfac, 0xe471f556, 0xf4b7a7b8, 0x808d7e91, - 0x10797f9e, 0xc62635fb, 0x59537989, 0x0790dace, 0x2a7a5eb8, 0x69fee382, - 0x34e22f1c, 0x73f67f2a, 0x0598cf09, 0xc1d027ac, 0x4ab9fccd, 0x77d5cfe7, - 0xfb83135f, 0x955de210, 0xb25c79ef, 0xff827a7a, 0xd1ebc286, 0xbf3f9d1c, - 0x83f338fc, 0x8837da2a, 0xfbac5b0f, 0xab3f1713, 0x78b95cb0, 0x308f35d5, - 0x26c77ddf, 0x5ce22f70, 0xc1d183d3, 0x91cfa8f8, 0xbdb3b0fc, 0xa62feb87, - 0x5bfdb2fa, 0x2d9f3cd1, 0x13e60f36, 0xddefc78a, 0x07f559fe, 0x226cafb5, - 0xcaef22f9, 0x2d125ff5, 0xf833fd3f, 0xfb2736cb, 0x7cff0951, 0xadacea3f, - 0x7fd60169, 0xf32779f6, 0x72b1b39d, 0xf3a49fdf, 0xf98d97d4, 0xb66bf4dc, - 0x9a61fccb, 0xd0b439c0, 0x98d7ee6f, 0x9b1cead7, 0x4f78b7a4, 0xd544fc0c, - 0x47f40f84, 0xb711f9f8, 0xedc6d77f, 0x40b3d743, 0x4fb1d76f, 0xba608f9f, - 0xe24bdb39, 0xd90bece5, 0x8d1d9e7c, 0xf34ef495, 0x74de854d, 0xb8a65636, - 0xa87a0499, 0x387a4974, 0xed89a63b, 0xed956702, 0xc9b51e9c, 0x74cb9576, - 0x5fd13b7f, 0xb407e812, 0x63aabb09, 0x19e40b4d, 0x05e1f9f0, 0x4f70069c, - 0x0e8ed43b, 0xd7f9c53a, 0xe333efaa, 0xebf6051d, 0x89a79fb0, 0xba6bc7ef, - 0xedb5593c, 0xf0257f4a, 0x614db554, 0x197fda7f, 0x13acd0fd, 0xd1003f0c, - 0xc29f62e5, 0x6e2c22ef, 0xfb116db8, 0xbdac96d3, 0xac6f7415, 0x6f7eb163, - 0xf2a2a8fc, 0x693a8e7c, 0x395ee4ff, 0xdfdf019e, 0xef1d28e7, 0xf38cb875, - 0x3bf0f68b, 0x47496e39, 0xfea46d94, 0x35941aaa, 0xa19a4e3c, 0x19f5cae7, - 0xd8b02270, 0xaa3be761, 0x6eeed3df, 0xbb3cc6fd, 0x9d31cf9b, 0x934d1fcf, - 0xdedb93f7, 0x2fccf796, 0x26243d7d, 0x41e45bee, 0xf46061be, 0xd063b887, - 0x22f3f520, 0x35f61cf8, 0xcf34ebec, 0xff660dac, 0xe653ce4e, 0xe66d80fc, - 0x730eee7c, 0x9cd9af3e, 0xce6ebcf7, 0x0ee309ff, 0xf41384eb, 0x4235c46f, - 0xfd0a46ff, 0xf5261ddb, 0x7fa1e46f, 0x8dfe8523, 0x91bfd0ef, 0x3c8dfe87, - 0xa1e46ff4, 0xfe85237f, 0xfeeeef8d, 0xba554e12, 0xe07814bd, 0x4eddbab8, - 0xf7813e23, 0x89d9c5cb, 0x558547cc, 0x1717a5ea, 0xd8fcb2e5, 0xe29a6f61, - 0x11937b60, 0xad18958f, 0x1c47f785, 0x2ab2d280, 0xb1db8d39, 0x55f6ba1d, - 0x2aae8769, 0xeec24670, 0xe4f2bad1, 0xa73d882a, 0xd418b4a3, 0xdb6b68bf, - 0x2f56f802, 0xff7ec03b, 0x77eee5d6, 0x63f893af, 0x5f118bfb, 0x0f738255, - 0x25f49b7c, 0x71ee7719, 0x4353db04, 0x4d6244fd, 0xd3f21e50, 0xd43e733a, - 0xe6be042f, 0x46abed35, 0x6c6fc7c6, 0xfbe0c96d, 0xe0e33e9f, 0xea9f69fb, - 0xcb313bf6, 0x2198f2c1, 0x1bce23cf, 0x9f7a5970, 0x95e709b2, 0xc31c7fa7, - 0xa650fdb9, 0x68617ee9, 0x0879765a, 0xf91df3cb, 0xe3058a35, 0xbe5f4f94, - 0xcd6af58f, 0xedd2e7cb, 0xd7b2dcfa, 0xeef34c5b, 0xd1370fef, 0x71adc0d1, - 0x5ecc7e21, 0x7783faa6, 0x31f887a5, 0xa7ca9807, 0xbe6219ad, 0x8d7c5f8f, - 0xbdafbca9, 0xa1cf6e23, 0xfce4b9fb, 0xa5ceb25c, 0x6f5e02c8, 0xc554bd68, - 0x6ff827f3, 0x4e52dbc5, 0xc673a72d, 0x2bbfaf1b, 0x9d7f0052, 0x57e03277, - 0x858b64d1, 0x3f4cad9d, 0xf332c487, 0x15615cb9, 0x275c573e, 0x84b855dd, - 0x7fda9637, 0x654c6d69, 0x47e5fa3a, 0x68812aa9, 0x3c9680d1, 0xde8bafe8, - 0xe838727c, 0x98dd5aaa, 0x3bf2a2ea, 0x5c16ff14, 0xb7133f20, 0x9524713d, - 0x495aa927, 0xaa73c27f, 0x1cff702d, 0x19edd1f0, 0x7ca4ef02, 0x68a5e6ba, - 0xe9d41f8e, 0x0ae6d52f, 0x6c6c1d07, 0x814f5954, 0xeb8d4cfd, 0x8d8d93a4, - 0x6bd0e1f1, 0x3e28c62a, 0x5c06c7c8, 0x8508fa0c, 0xefefc907, 0x97bd69ba, - 0x94f7c90e, 0x752e758c, 0x41a2fac9, 0x07de37b6, 0x5c7bd630, 0x372b47d7, - 0x3b7591be, 0x7fd73f7d, 0x7e1b9e5f, 0xbc5dbadc, 0x6d96c5ee, 0x7d29925b, - 0x85dda1c7, 0x7b7d2d75, 0x1a48f45c, 0x326dcbe7, 0x75b3fdae, 0x23e13e4f, - 0xe3777a7e, 0x0fe87693, 0x9dbf5695, 0x6679cddf, 0x0ef11da3, 0xc8dd6fd7, - 0x2d6c17df, 0x71807b61, 0x1194eecf, 0xa3c3ad97, 0xc1b2ac62, 0xde3ceb45, - 0x1585ca5f, 0xa69e32e1, 0x46f51d48, 0x55b5d602, 0xa6bac7c9, 0xe3b76f17, - 0xf58781fd, 0xa6fba17a, 0xa2b4f0fd, 0x357bb01e, 0xd4c71c29, 0x11993edd, - 0x64fbcfe8, 0x4e34e5da, 0xc81e5fa7, 0x8287de7a, 0x239c2fb4, 0xf5fa21b9, - 0xf5da5561, 0x4ef9559a, 0x30903d98, 0x5ec2f20d, 0x35456ef9, 0x0a23439d, - 0x710bb7a0, 0xa3c5a535, 0xd79d1354, 0xf6984616, 0xb4112cc1, 0x9bbfa8af, - 0x7e532f45, 0x530cc4fa, 0x07d399fd, 0x0b9df886, 0x7f99cb3a, 0x8f7a6d5d, - 0x9f2efaa6, 0xc7bb615b, 0x4a77f358, 0xbb3a62ef, 0x5abed4d1, 0x47bd354c, - 0xf7a9e8b3, 0x6544ce18, 0x54e1c476, 0x6658f7e8, 0xeff54769, 0x169dfcad, - 0x7dafda62, 0x927f3c33, 0xfd8da5e7, 0x7d3d8609, 0xe8cf7e16, 0xef0cbcea, - 0xbc451788, 0x9a1dec30, 0x61691e59, 0x3c48553d, 0xa8f6eb54, 0x8f691cea, - 0xd8b5f6aa, 0xf04d8f11, 0x4810a6b7, 0xb6151a6a, 0x477d5237, 0xdfcc9c4a, - 0xcc3bef85, 0xdfd052f7, 0x521f9465, 0x42bfb04b, 0xdd686bcb, 0x606a1738, - 0xd83b6247, 0x076c9384, 0xfbd1c633, 0xf434e837, 0xfed0807d, 0x33700c06, - 0xbadcaeff, 0x822f60fd, 0xd8e2b4cf, 0x549dc47c, 0x95b14d35, 0x6f495ee4, - 0x54bfff06, 0x7ebf6161, 0x4c03e1fb, 0x5615ed6f, 0xff4b8c8f, 0x78d4b876, - 0x9435dda5, 0xbad0170e, 0xb05e7fe0, 0x15f8f143, 0xe9f00f59, 0x810cfa05, - 0x70174a4f, 0x01d5e033, 0x7e7290bf, 0xe2286e3f, 0x0a7be426, 0x1425c057, - 0x0b38fa9e, 0x2772c134, 0xf3cfcbcd, 0x8c57e90a, 0xb78fdd08, 0xb0ffd9db, - 0xe52e1141, 0xf531e1bb, 0xf4e3b4b2, 0x6feb90cd, 0x2078a9db, 0xd97cdfbf, - 0xe83bdfca, 0xd9c658a7, 0xde689f4f, 0x54f41daf, 0x8ccff72c, 0xeedc89cb, - 0xdf5745df, 0xff864f45, 0xdd7e3426, 0x19e647b8, 0x1ab7dfa0, 0xf37d8626, - 0x1be1c44f, 0xe77741f2, 0xe439c74c, 0x9910f1d2, 0xbcf9e5de, 0xe39d2a34, - 0xbedd35cc, 0x4d69f068, 0x5b8c676f, 0x78eee542, 0x7e6f7bd0, 0x43557167, - 0xfbf06a46, 0x1b4ada37, 0x975381db, 0xe25a73c7, 0x7ce22574, 0xdf2e5929, - 0x4f763969, 0x29f844cf, 0x25b4ad8e, 0x8faea44c, 0x553439dd, 0x88be420c, - 0x86d74fd3, 0xcfb60acd, 0x032de91b, 0x9c61f9e4, 0x872de7ef, 0x3f6167a3, - 0x8d19dcae, 0x2bc5a190, 0xa2ee1fdf, 0xa2d9be73, 0xfec01a2d, 0xce7c8de0, - 0x3cc6d70b, 0x390ce7d8, 0x516572a3, 0x5503c84f, 0x04f038ff, 0xb96d01e4, - 0xea72112d, 0x81540fe9, 0xe73a1ad0, 0xe538be58, 0x6a7df494, 0xabdf0473, - 0x2f08a53c, 0xd48b51fc, 0xd32e797d, 0x337cdb79, 0xd2708fc6, 0xae30c3b8, - 0xc6124b7f, 0x30b2f8f5, 0x333cb6ae, 0x8bbb2ba6, 0x97aed691, 0xc316dff2, - 0xa3dbacce, 0x0f23f721, 0x4b645fb9, 0xc8791fb9, 0xf72148fd, 0xfc0d7be3, - 0xd71bf00e, 0x6f43e5b7, 0x39158df5, 0x8e1cf84b, 0x7f5c81cc, 0x01ee12bb, - 0xf15dba3f, 0x8478e4f4, 0xf9e5620f, 0x2357821b, 0xb246dd1d, 0x5edd1059, - 0x8221d977, 0x88c6ebe3, 0x9c7e5358, 0xbf54d923, 0x2a6695c8, 0xbfa93ebf, - 0x7706fca9, 0x537f29be, 0xfd5348ce, 0xa6319e49, 0xdc468ffc, 0xc53faa60, - 0x9f94c53b, 0xa9b66136, 0x12e28cfe, 0x59ccf953, 0xb3e54c8b, 0xf94cdbb5, - 0x34ee2b5b, 0x92f1ffd5, 0xaf72a6e5, 0x0e715970, 0x231f4336, 0x3e85efb8, - 0x6fede946, 0xe3064667, 0x4b38d475, 0x350cef97, 0x56fa900d, 0x39f7ae74, - 0x09ee25d0, 0xe8fb0e81, 0xe2f680f7, 0xbf06199c, 0xfa914065, 0xe8324b70, - 0x685eb426, 0xfd88a8f9, 0x6594f097, 0x9f6ee7ff, 0x313e2561, 0x43fdaaea, - 0xfb7f2832, 0x5619e6c0, 0xaea32fe2, 0x3a52ffd9, 0xdcf17fe5, 0xf07cb237, - 0x57284bfe, 0xfccbf772, 0xc822c134, 0x9bce06af, 0x8c75a3e1, 0x8d7d2eba, - 0xba53da47, 0x5235538c, 0x9d7101c0, 0x00d20380, 0xfdd227d1, 0x5f489f44, - 0xb72cfa27, 0xe8907109, 0xd221e913, 0xf7fdf14b, 0x3d2297a4, 0xd2297a4c, - 0x452f4877, 0x297a42da, 0xcdd43fd2, 0x3a83f4e2, 0xb1fddb8d, 0x8fd382ae, - 0xf7f096ea, 0x7196ea4f, 0x1f3a97fa, 0x8064ff7f, 0xb0087f61, 0x8bf0c69d, - 0x091fc0d5, 0xdb2ede7b, 0xb1bf60b9, 0xabe795e2, 0x5facc7e1, 0xb0235a22, - 0xb1ad5b4f, 0xfe9d1c27, 0xadf9eec9, 0x92089c55, 0xdee19ccb, 0xf8f006cf, - 0xb7cc5dbd, 0xc447eff5, 0x84053eb4, 0xb5d34fa7, 0x3307e0b3, 0xc656ca0a, - 0xeeb8ff10, 0xd03625eb, 0xae9687cb, 0xd5efa3ef, 0x03a7dbf9, 0xf7e86dbd, - 0xa65dfd5a, 0xae321d6b, 0x6b6b5af0, 0xbfdbdb3d, 0x03c46e14, 0xefec33ed, - 0x5ef958f7, 0xe085f2b1, 0xc104e8fc, 0x5b2ffaf9, 0x5af10e38, 0xcf892797, - 0xc46f3d1d, 0xfdf87505, 0xef1413f1, 0x8de1f863, 0x2fc29f78, 0x3e41c75a, - 0x77691d18, 0x0dc48587, 0x2fbedfc0, 0xbcc68fea, 0xc3277df8, 0x97d4ffbf, - 0xf2f78022, 0xb5fe3f0c, 0xd834968e, 0xe1df4615, 0x33c704f0, 0xe57afe19, - 0xe715168b, 0x64af1189, 0x3bcc638c, 0x15fd4aca, 0x5d23c674, 0x47ca6aeb, - 0x757d465c, 0x93d7f724, 0x49dde3be, 0xb955e7aa, 0xec3e535d, 0x22aba3c7, - 0x8ce9423d, 0xafa9e813, 0x3af1ea9b, 0x38d0bf0b, 0x1eb4624e, 0x1c7e8127, - 0x01df9cb2, 0x48109d1c, 0xa39ffbc6, 0xb03dd897, 0xb88e3e83, 0xb8ce82b3, - 0x088fd405, 0x2798c7da, 0x15f7edfa, 0xbcf217cd, 0x9df0cbd7, 0x29f492e6, - 0x3f5e7adc, 0x2c6385af, 0x3d54bbdb, 0xfae61c5f, 0xcfd1046b, 0x90da19ad, - 0x1fdfd481, 0x7ccc8c94, 0x7a3217d6, 0x094fdf60, 0x0bb04779, 0xf03119fa, - 0xbc7e84ff, 0x05bdef12, 0xe942e1db, 0x418fc0c8, 0xbbde064f, 0x0e832ba3, - 0x18d0e282, 0x65711def, 0xf4a17f7a, 0x199d1dd6, 0x43ad75f4, 0x8cf001d2, - 0xae8320f8, 0xf89a2f94, 0x2ae8eb1e, 0x067f9f07, 0xc5d2855d, 0xe9257495, - 0x0e27feb4, 0xba4aefee, 0xc007a4ea, 0x55d387e5, 0xf8f38a8b, 0x79a7a59f, - 0xee3c626d, 0x765c97ff, 0xabda441f, 0x7c17b69f, 0x198c4ca6, 0x2e13120f, - 0x62ec1075, 0xba32f5a1, 0x7f4a17a9, 0xbc6eeda1, 0x6e465da2, 0xfa71bb70, - 0xaeda1959, 0x047aed12, 0x71c21bb7, 0xf7e96f11, 0x1a72de08, 0x999e2d71, - 0xb90e5390, 0x2f2df26d, 0x27cc8de1, 0xf3a719ba, 0x096243f3, 0xee24bf9f, - 0x854f40fa, 0xcb8d693a, 0x42fac85d, 0x71d76461, 0xedea3705, 0xdc5d7fc7, - 0x4f8cf980, 0x37e3cb30, 0xf5fcf2ea, 0x0ffb91a2, 0xc6e1477d, 0xce59ebdc, - 0x61477d0f, 0xfe3d40f3, 0x81a44d20, 0x8f0a17df, 0x0efe9f9c, 0xcfbea146, - 0xc9ba7453, 0x5462ab70, 0x6a9bee1c, 0xaf321c56, 0x3c8c1de3, 0xfce3eb8c, - 0xe9cfc20d, 0xfdc0224d, 0x0903a24c, 0x61091ff9, 0xc85fef93, 0xaa35bafb, - 0x5790dff6, 0x4fba7b8d, 0xb057b53b, 0x4c440fcf, 0x4a77839e, 0xd7190dc6, - 0x17f6ed0f, 0xdbce59ba, 0xb960c8ef, 0x16d2fb13, 0xde27c9d7, 0x5fba73a4, - 0x8a37bca6, 0xfb46f714, 0x3bfa79d1, 0xbf91c73a, 0x40b96731, 0x736ef1bb, - 0xfed193bc, 0x6138d726, 0x9cfeef8d, 0x776f29bc, 0xdecdd86f, 0x042ecd8a, - 0xbd8adf7e, 0x7deb10aa, 0x45a7b62b, 0x4e7661a6, 0xafd2bd07, 0xa0d8b92b, - 0xc6f1cefb, 0xc1dd78f3, 0x286b80d9, 0xff380d3c, 0xeb1eb800, 0x077bae0a, - 0xaa379608, 0xad5f2423, 0xd57c908e, 0x58757380, 0x9ede7dc7, 0x5527f1c1, - 0xf9af090e, 0x5611aecb, 0x2c17f512, 0x93f9c91b, 0xb807c275, 0x6092c69f, - 0xf7b10f10, 0xce58eb09, 0x9ddcef1b, 0xe8bdf87d, 0x2ae79a24, 0x983ff687, - 0x4082b9df, 0xe2844916, 0xbe7a86e4, 0x05fe7f8f, 0xaa7d03d5, 0xf1af754a, - 0x96facec0, 0x7d71ef2a, 0xfe15207d, 0xd754f158, 0x0e55e8f1, 0x9f435f09, - 0x98afd21c, 0x5fb1adf7, 0x80befe85, 0x0ef55f21, 0xc6dcf193, 0xe4eef73d, - 0x92e1e1ad, 0x930ef5af, 0xebc0d8fc, 0xee7ebb06, 0x89c33f53, 0x3afca68f, - 0x98abf59c, 0x2e4c6f58, 0xc28583ec, 0x76189fa4, 0xf904f695, 0x22b5ca7e, - 0x945191eb, 0x13643c2f, 0x076f2a7e, 0x92794043, 0x1fb6b3f4, 0xef82a4ba, - 0xfc294517, 0x6f71863e, 0x22c92c29, 0xc27c41dc, 0xbd370ee9, 0x13911b4b, - 0x7947ca67, 0xc7ea997a, 0x9537488c, 0x98077ac7, 0x1427e3ca, 0x8a3df298, - 0xefd536af, 0x29ac6b39, 0x68ddac9f, 0x31529faa, 0xf83794d5, 0x24fc8a58, - 0xc5b92cfa, 0xb2efbed4, 0x34fd5352, 0x5ca9a55f, 0x319b3bc5, 0x25b7ab40, - 0x81cf1127, 0xd58c9fca, 0xe3de434b, 0xf0cb08b5, 0xfe6b77ce, 0xcbde5a33, - 0x80b91099, 0x6cc9afdf, 0x9e7999fc, 0x2c6b44ea, 0xcdbbd7a5, 0xc928b17c, - 0xb9171f9c, 0x71df814f, 0x9fcccb9c, 0x4d589653, 0xeae51ff9, 0xe44f34fc, - 0xbbe3ddb1, 0x300daff0, 0x4e143fe1, 0x7efc0f44, 0xef9d3b68, 0xcdebcc3e, - 0x070f7e32, 0x75e0937e, 0x0c126fc0, 0x824df807, 0x049bf0f3, 0x24df87d7, - 0x937e1cb8, 0x8721f2e0, 0xd61ff8cc, 0x55ffc662, 0x6ff1991f, 0x787765d0, - 0xa66ad91a, 0x9a29a10f, 0xba782df2, 0x7e9994e6, 0x1d73f142, 0x09b15b89, - 0x09e287c0, 0xbe387fb8, 0x8be08656, 0x37f7c3f0, 0x31477bdb, 0xd7d71e7e, - 0x20606d75, 0x3a2e97df, 0x6fbc0aa4, 0x71f3ac63, 0x6d3fdcfd, 0x89731ad5, - 0x5dcefccf, 0x763e0490, 0xdb7e909d, 0x4f1655f1, 0x207fba80, 0x29d99c64, - 0x3fa843da, 0xaa52fe2b, 0x26d2741d, 0x0e7bcfdf, 0x95d8797c, 0x123eb2f1, - 0xf6bef84f, 0x27be54cf, 0xa8d2c475, 0x8eaf8f80, 0x9f009ed1, 0x84bb9799, - 0x8a249bd7, 0x5c402fb7, 0xa5857fd4, 0xafb73f22, 0x722dc7bc, 0x89fef95b, - 0xa6e727c1, 0x2da9b8c8, 0xdd7fbab9, 0x9ea7e323, 0x777295c9, 0x71c5c794, - 0xf2b925de, 0x8ba90d7e, 0x010773a9, 0xd99d873e, 0x0b3acf80, 0x8ad9ebbf, - 0x9d09e47b, 0x0f21c8f7, 0xa3ecfe43, 0x1ff57fcb, 0x47581c3b, 0x3a617af6, - 0x1dfbfb7f, 0x81e2f8a6, 0xfca65d5b, 0x5324a6a0, 0xdcbbc1fd, 0x40fcf2a6, - 0xc87ca98e, 0x3f298f21, 0xa98465ac, 0x791f55fe, 0xad91f94d, 0xaff54c13, - 0xca6c5539, 0x47b688a7, 0x8abedf01, 0xcd1c53b4, 0xb9fa974d, 0xe4dc705b, - 0xe563bbdc, 0x7edd5f7d, 0x46fbc861, 0xd3a6b9dc, 0xd11ea875, 0xe8e52ed7, - 0xf52164fa, 0x1fae8746, 0xa13eb30a, 0x1de371e9, 0xe67c58f7, 0x5e2371b8, - 0xd0ef43bc, 0x7b8e8af5, 0xe2f19d34, 0xf178e0de, 0xbf5d61b9, 0xc75e7d1f, - 0xfbfce87b, 0xeb7ae5da, 0xbdf3b4ef, 0xa15e631d, 0x96c949f3, 0xd1d9bb74, - 0xbfaabdf5, 0x46fb4ae5, 0x25f1666b, 0x3613fdd0, 0x6dff2b4f, 0xf3c62b84, - 0xb75e22b4, 0xcf7617fe, 0x8f77f70a, 0x5cb07737, 0x658b1ccf, 0x8e5c94de, - 0xddfd338b, 0x92418884, 0x7583adbe, 0x78c84afb, 0xdc646373, 0xbbb1889a, - 0x8fddbf41, 0x6499e127, 0xff7c0d17, 0xf167bf4b, 0xf74d35e3, 0xbd8e68a1, - 0xce3f7f51, 0x4c3d036f, 0x59f24b1c, 0x5b13c93e, 0x49143d7a, 0xcb13ca72, - 0x8a9f6cac, 0x3757fe7b, 0xde75fafb, 0xfa4be99f, 0xb203e810, 0x07a8f40e, - 0xb72954f2, 0x2beb920c, 0xb8eebf52, 0x187ec0e7, 0x43f3f421, 0x174fbc70, - 0x6874c6f4, 0x75dfe3ac, 0xdba0c1ef, 0xfa193850, 0x3be3d0af, 0xd2f319fb, - 0x07ec67e1, 0xfdc67e03, 0xb66df713, 0x7c914de2, 0xe202658f, 0x6dfc0ce5, - 0xc6f693c9, 0x503c3a05, 0xbba8fc0f, 0x6e6a457a, 0xedf7ec0c, 0xeae31dc2, - 0xea3b0e82, 0x62e09bff, 0xfbbbbfc0, 0x87f1dd6d, 0x5df0be50, 0xa3baddf7, - 0xdef67fd3, 0x909f105b, 0x5e3a4bf1, 0x1c2cfdfc, 0x94777017, 0x323f3f79, - 0x9189f248, 0xe4fdf483, 0xccd6fd23, 0x0ffc042f, 0x9d552bf5, 0xbcf3c85f, - 0xdf98ad24, 0x8af9c6af, 0x37f35bfb, 0x8847f94a, 0x87abc4e2, 0xe36f8fc2, - 0x7ad7cbfb, 0x4a6ddb05, 0xde3f151b, 0x75f12af9, 0x9fb30fad, 0x0772cdcf, - 0x26c83bbf, 0x46576a4d, 0x5da5f6ed, 0xc2facef9, 0x60eef948, 0x0beafbe8, - 0x2f19bd75, 0x86df606a, 0x19eebdfa, 0x3cb1fba4, 0x9cf2c3c2, 0xa150d71e, - 0x37a0e9d7, 0x0e6f7cbf, 0x31f6327a, 0x671f1ca5, 0x3f0dcdc0, 0x3cce90d4, - 0x073c37c1, 0xb58379e7, 0x0ec5f8cb, 0xab7e1af8, 0x61ecbf0e, 0x1a1127be, - 0x77ce718f, 0x3f2bba20, 0xeb1fe198, 0xf8741f6e, 0xefc3bec7, 0x89691ed6, - 0x69f1dfc6, 0x67df26df, 0xfd5bf4e9, 0x22cbb865, 0xf03153fd, 0xfdeab53f, - 0x5d798d89, 0x96d50fdd, 0x9438e4ef, 0x73b68b66, 0x2cefad10, 0x7b778ff5, - 0x9fdc89ef, 0x26117788, 0x2ba976ea, 0xcdcbadd7, 0x8fe914a3, 0xef8ca9f6, - 0x5ef209f6, 0x8151f13d, 0x4fc4677d, 0x0481114c, 0x4a1f86a4, 0xe1923d5b, - 0x4aa1f86f, 0x9e792302, 0xda17ea33, 0xeb68e4f0, 0x851577a3, 0x53fd3bbb, - 0x5c647dad, 0xaa7e7754, 0xb9f39769, 0xaf97e9bf, 0x183e7ee1, 0xb6e52694, - 0x036efb86, 0x2ad80d9d, 0xab67586c, 0x4bbfebad, 0xabf3a851, 0x3d9ae812, - 0x96ade282, 0x962fbc2b, 0xbf88c22a, 0xe46f3e62, 0xf9ea352f, 0x7dbf9922, - 0xeab7cca5, 0xd16da7ef, 0x275820ed, 0x7a07ac52, 0x4edd36f9, 0xc5207582, - 0x7c1df03a, 0x35f0790d, 0x90d7c1e4, 0x0a435f07, 0xa5ef86be, 0x761538a2, - 0x0ad3f85b, 0xfc07f683, 0x72418569, 0xc169fc13, 0x82d3f879, 0x169fc3eb, - 0x5a7f0e5c, 0x69fc3970, 0xd3f879c1, 0x9fc3eb82, 0x3f879c16, 0xfc3eb82d, - 0xf879c169, 0xc3eb82d3, 0x0e5c169f, 0x39705a7f, 0x79c169fc, 0xeb82d3f8, - 0x5c169fc3, 0x62996f3e, 0xd3cdb7f2, 0x5b287fdf, 0x51f4cf1f, 0x9b1c5198, - 0xeffdf847, 0xc4fc7f88, 0x373c0e96, 0x2edd022f, 0x48f70ead, 0x904e373c, - 0x8908b778, 0x8cd9b6e7, 0x32ecbbe7, 0xb4e3245f, 0x7e07e943, 0xf49b42ab, - 0xdf85215b, 0x56fc290a, 0x2ab7e148, 0x2b7e94cc, 0xe15bf0a4, 0x4856fc3b, - 0x0a42b7e1, 0xf85215bf, 0x6fc290ad, 0x2b7e1485, 0x0adf83b4, 0xf856fc29, - 0x5215bf0e, 0xfdf0adf8, 0xfe03cd08, 0x905e632b, 0xf499fbf3, 0x9343a252, - 0xe532ea5e, 0xd707e721, 0x5c1f9c87, 0xb83f390e, 0x707e721c, 0x707e721e, - 0xc1f9c87d, 0xdc8349f9, 0xef20bfbc, 0xbc83b707, 0xd41f9c1f, 0xb6037be8, - 0x2e1b49ab, 0x35b48ebc, 0x7142794a, 0x2f353109, 0x8bfc2673, 0x35254ead, - 0x6d8423d6, 0x859980f9, 0x38f4d794, 0x66d13cc7, 0xae39be01, 0x05a6f080, - 0x0f65c704, 0x5cc97ffa, 0xf9b3f86e, 0xbf9ef087, 0x50deb043, 0x35afdfa3, - 0x4b847bda, 0xefd46a45, 0x2f5d77cc, 0x1ea37c74, 0x79a0cbf3, 0x8f996290, - 0xbbfc9378, 0xaf700b22, 0x91458b60, 0x642bb8f1, 0x5d28743c, 0xe793caad, - 0xf6cb16fb, 0x5388e1fd, 0xb83c5129, 0x156591ef, 0x80056c87, 0x7e0292d3, - 0x562f2af7, 0xab92d75f, 0xcc658711, 0x124bb0db, 0x867be09f, 0xbd84daa3, - 0xfd19c69c, 0xefe3b085, 0x4bb44c73, 0xa0ed0279, 0x29f40e6f, 0xf4414dde, - 0x9e4f2cbd, 0xb6ef9a7b, 0xfbe9cbab, 0xae4b6dc0, 0x89c5fdc6, 0xd3ddb2e1, - 0x386689bf, 0xf8506e4e, 0x6da8ce9e, 0xc9fb8bc2, 0x3a7e75cb, 0x5ecb9b70, - 0xf8bae3ce, 0x6fd1a3de, 0xbe5486c9, 0x5a2259a7, 0x450f710b, 0x3df8550c, - 0xb46e037c, 0xbeb1d7be, 0xb02ada2c, 0xfbe0ff2f, 0x7e2e244f, 0xa34ffb9f, - 0x2116c687, 0xcb3450ae, 0x0d2742f7, 0x83d9592d, 0xe5f9a5e6, 0xbfa3a17b, - 0xe706f258, 0x85ef929f, 0xe70cf932, 0x9879f1f9, 0xfdf853ed, 0x8dbec995, - 0xee370496, 0x25b72f65, 0xe136fea2, 0xf5055881, 0x8d8af708, 0x168ae575, - 0xbd01538b, 0x41f10388, 0x639c47f4, 0xdf25e83a, 0x59f7e363, 0x365d58a6, - 0xce431bf0, 0xb1c97129, 0x3151d48b, 0x4432cf7c, 0xd0d4b84e, 0x7e62e383, - 0x3b4e9c78, 0xba5fe7df, 0x8572c9d3, 0xbe615eb6, 0xc65f3e79, 0xf6dd56bb, - 0x7a4b70e1, 0x99ce9c67, 0xbc16ff34, 0x7d267b03, 0x8508f47b, 0x79bd88e5, - 0x0da3d704, 0xcd3df12f, 0xf06f9592, 0x0d4b943d, 0xfbcb450f, 0x52ffd26c, - 0xb0cdc3ae, 0xf1d7cd3b, 0x69c7ae53, 0xef93ab1d, 0xcc39d33a, 0x6a5caeef, - 0x119cb1b0, 0xf21a2f2a, 0x911ef1a7, 0xc23fae10, 0x60d153ce, 0x0bc03be3, - 0x4aac94d7, 0x91ca5712, 0x7339758b, 0xe38d8351, 0xf7f42ab2, 0x6eff42d4, - 0x1e3d62cf, 0xf356f16b, 0x42f24ff7, 0x7de350e4, 0xc94ebd4d, 0xb06607db, - 0xc6c4b43c, 0xcb39cdfe, 0xb6247ca5, 0x93ee3f0b, 0xce3e59cc, 0xe666f782, - 0x947af4ec, 0x5de9e82e, 0xd89a4e5d, 0x4ff864ea, 0xfcc11cb9, 0x14e5ea65, - 0x397cdfce, 0x9799d399, 0xee2adc65, 0x5a6e8122, 0x073be48b, 0xd1f2ebef, - 0xc6b1c40c, 0xc9eb3e43, 0xf44eddf4, 0x74f2218d, 0xabc035be, 0x3878801c, - 0x44ada6d1, 0x8dc4ec9c, 0x4d83ef82, 0xfd451c82, 0x155c82cf, 0x5691fd8f, - 0x2661f7c4, 0x68bf7c28, 0xf4dbd0d2, 0x43fb40fd, 0xf7e13f30, 0x29c2b457, - 0xcd39c47e, 0x805bb6d2, 0x685f637f, 0x5efca3be, 0x629f24ea, 0x9a923bc7, - 0x741b6fae, 0xe63fba1f, 0xb276e846, 0xeb076948, 0xb26193b0, 0xb7c92478, - 0xd3e4266a, 0xf66db0b9, 0x608109d2, 0xcb2b951f, 0xd576fc7b, 0x419206cc, - 0xc9fb55ff, 0xde458b1c, 0x9039233f, 0x96880bef, 0x2f949ea2, 0x4014a359, - 0xf5e6323f, 0x38ec67b9, 0x3a4eb0cf, 0xa7d8ed28, 0xd2e51ef2, 0x7e4d327b, - 0x8cb4d09b, 0x34fd8de0, 0x27f5a637, 0xf468610a, 0x1c2de160, 0x85ebf781, - 0x005428f1, 0xe8b798f1, 0x3bc1eaf9, 0x973ab4ff, 0x91f9c4e1, 0xa6687dbf, - 0xe05ff22f, 0x6b147393, 0x4b1bdff0, 0x0d5768b2, 0x50f7c1ee, 0x11bf03c7, - 0x9efc6db9, 0x4bb64a44, 0x7b10a9f2, 0x8960f54b, 0x4bbb50c7, 0x773cae59, - 0x7a9dd584, 0xdc7bfb2b, 0xd634b76c, 0xbe66cc7d, 0xf3a46be7, 0x5ee7eb07, - 0x9ee7bfdd, 0xf916c3ca, 0x1663c2fe, 0x8857f6ff, 0xd0f72f5e, 0x8fbd6066, - 0xe79ede21, 0x8cfaf1af, 0xf83a4cf7, 0x896efe95, 0x96474f41, 0x2afbe25d, - 0xb77691a5, 0xe54f441a, 0x0fbe15ab, 0xde4cba5a, 0x2b56d6e7, 0x6e845df2, - 0x99bf58ec, 0x9efcbffd, 0x117e6fd5, 0xf8750b2e, 0xbcb7b1ce, 0x84eb48e1, - 0x3d979fef, 0x347c9360, 0x0efb8990, 0xf2712cb7, 0x7b9fd9bb, 0x0f06ab8a, - 0x8c3c9e03, 0xe5d871a7, 0x8c4b7f54, 0x4bdf04b6, 0xd841cb45, 0xfcfee71d, - 0xba8f7e6d, 0xdf8d39b6, 0x95d92cbf, 0xd9ef0abf, 0x7ed1ee7c, 0x4497f582, - 0x4790ecba, 0xf9621a6a, 0x53db9e7c, 0xda2bcfbf, 0xe067cfd8, 0xd2c1bee7, - 0xbe7d778e, 0xaea2e71c, 0x6cc01157, 0xbaf54c53, 0xf61a63b6, 0x4b3b50d1, - 0xdf21bbe8, 0xdd815765, 0x5f641ec4, 0xb632ec35, 0x71b3639c, 0x77b1cfae, - 0xf73ef7fd, 0xf437f3ea, 0x7a1df9da, 0x9ef8ee6d, 0x2ad7ff90, 0xcbd3d82e, - 0x7133dd23, 0x90fca1bf, 0x62b4910d, 0xbe5b9c62, 0x7c8f731f, 0x8ef4a63f, - 0x7367e67c, 0xdc029380, 0xfbc9193b, 0xe94fdcb8, 0xfbf7ee90, 0xf40f6bad, - 0x0a7a0dd9, 0x821df978, 0x1ed79772, 0x951f2417, 0x77a62a35, 0x0bfc8c24, - 0x97c95583, 0xfc00dd48, 0x9a477c7e, 0xcd396f1d, 0xf1093121, 0x27417b99, - 0x51db3ac3, 0x993f8e3d, 0xca0e2e98, 0xfe14bdf7, 0x2f18e4bb, 0x955beff8, - 0xc3df9a36, 0xdf2cfaa0, 0xc51c1aed, 0x68b895fd, 0x5d4869dd, 0x03824f3c, - 0x3eeda9c3, 0xe3cdcfea, 0x02ca3e30, 0x07ec1b7e, 0x42f71073, 0x7e5c5bf9, - 0x6d29c61b, 0x68d4ef90, 0xda38e46b, 0x20fb58ea, 0x975607c8, 0x5cb04fbd, - 0xbddf20d8, 0xddffa39e, 0xcb2f9a11, 0x2704e5cd, 0xee33b3dc, 0xabc286dd, - 0x797f9f44, 0xce59ac63, 0x036b5c6c, 0xf377667e, 0xdd39c65e, 0x30da5d0e, - 0x2837df86, 0xbef97ab7, 0xfbc3a68a, 0xf79cdbb3, 0x7b325fc2, 0x34b623dd, - 0xb065ffca, 0xe9cf6b94, 0x7a6271fb, 0xa9df9320, 0xf1c9cdba, 0x8d5db3e3, - 0x780edebc, 0x81f0443f, 0x662ae2dc, 0xf89d1378, 0xbe596f10, 0xcedf8cce, - 0x77c944f9, 0xf095d7fc, 0xd5605bfe, 0x79e0aeec, 0x8997dfac, 0xb4d9a1f8, - 0x970ef1ef, 0x1f7c6970, 0x3343c4f6, 0x6205eff9, 0xe6cf1c9e, 0xbbc78f71, - 0x4c374453, 0x18fd06d7, 0xf18df3f7, 0xb4ab1eac, 0x6bbe7bc7, 0x420f7a9f, - 0x7c27af4e, 0xddd00fc3, 0x02e3b53e, 0x2f6b8d26, 0x5e07ef97, 0xfdf4efc1, - 0x6a01fffa, 0x00d36c91, 0x0000d36c, 0x00088b1f, 0x00000000, 0x7dedff00, - 0x65555c7b, 0xd6bbf0ba, 0xc0d857da, 0x51b08b66, 0x62020dc0, 0x10106d11, - 0x80a17515, 0x636a735b, 0x8dc42937, 0x910150b7, 0xf39fa8ac, 0xa96f0db1, - 0x962a2695, 0x8da6b675, 0xb2707595, 0xd99b1b46, 0x0f5d9a6a, 0x39d38d3a, - 0x32cdb653, 0x34d209bb, 0x99d37d9f, 0xde79e7be, 0x0daf60b5, 0xf9a675a4, - 0x3efcefce, 0x7df5e3fc, 0xee7d7bd7, 0x765ef3cf, 0xb24c6322, 0x98783631, - 0x8c81b183, 0x45931819, 0x77a13fc8, 0x6302edfb, 0xbeac7195, 0x28d2132d, - 0x0b6bff56, 0xdfe3df63, 0xa2749ef8, 0x8f2c6453, 0x5da0dbb1, 0x10af7c1b, - 0xd6ccabd9, 0x29d33df3, 0x148af7d0, 0xd41dd336, 0x7ec3fb1e, 0x13efd5e3, - 0x338b69fc, 0xe3abea7b, 0xbb78d856, 0x9a7ed0a9, 0xdd8beb05, 0x3ea81bf5, - 0x26e9b3cf, 0x3632c591, 0x87ff04db, 0x7b4894a5, 0x32e6c456, 0x7057b0d6, - 0xe1a8a11a, 0x18b18941, 0xf08b9f48, 0xbec664b1, 0x3bcdf868, 0xcfbd40b7, - 0x64af6f37, 0x35e67b43, 0x398a3fc7, 0xf7363046, 0x0c733652, 0xa5de6c60, - 0x0f569431, 0x073864f3, 0xf8dbd506, 0xc607ba5c, 0xfb2dadbf, 0x5a307fdc, - 0x30e59fb7, 0xbf73fef6, 0xe868e3fd, 0xde9f3197, 0x3acf4d7d, 0xa13ead66, - 0xc304b2af, 0x4d73af8d, 0x83155746, 0x18b6ce79, 0xcd14121c, 0x64c55e5e, - 0x33b32798, 0x13e41a67, 0x422bcc75, 0x16fd6cbf, 0xf3eb04d9, 0xb557fe30, - 0x5da9905c, 0x824fbe63, 0x7a860cf5, 0xdf5e1cc6, 0x58f7f00c, 0x4884670c, - 0x912de8a8, 0xcdbc1903, 0xf83d29f7, 0x21a90c1d, 0x89ef07a7, 0x5ecc1d0a, - 0x7b6d0657, 0x330305f0, 0x65eb0f96, 0xfceaae1c, 0xbff32aa7, 0xfb20bd6d, - 0x4e0ddea0, 0x2757cf07, 0x7ac1e61b, 0x364face7, 0x5cb486cc, 0x473e5ef9, - 0x2f8dde5b, 0xccaf8aab, 0x4f587695, 0x57c71b57, 0xe13d3ad7, 0x2f4f6bab, - 0xa931257c, 0x00771e67, 0x8e00d8be, 0xe382362f, 0x57c0530b, 0xa82f33a5, - 0x7c70bfde, 0xedfe7ecd, 0xd0765e0f, 0xceffa8fa, 0x1dbe8d07, 0xb6acffd0, - 0xf2b784bd, 0xc9f41bd5, 0x99ceaf50, 0xdb51704c, 0xb6cfaecf, 0x6de78032, - 0x1debb7ab, 0xe8eefc16, 0x9521ee93, 0x413f1059, 0x6790099e, 0x3bbc40ba, - 0x397ea7a2, 0x9c617ba4, 0x91cd8b25, 0x719edaec, 0x3cf428b6, 0x86da3ebb, - 0xafaecde3, 0x7165887a, 0xf66777fa, 0x66b3bfe6, 0xa0b317ce, 0xb3cfe43f, - 0xe424ce45, 0xd4510a8b, 0x3e9a9bf0, 0x79837884, 0x35e0063d, 0xdbc3fe23, - 0x0c38469e, 0x6ce6145e, 0xa9a94f86, 0x8b8e1f01, 0x36f38cf4, 0x826bcc88, - 0x8135a97a, 0x548f388b, 0x876c28a0, 0x528d8469, 0x1df90b16, 0x4802ed30, - 0xee9e2453, 0xc3f5f273, 0x677e3f77, 0x5c3c8131, 0xa1cf4abf, 0x3b606af4, - 0xfe00a757, 0xd9cc310d, 0x4fa1e8ec, 0x3e951fb5, 0x6fedfa55, 0x70ae7b7d, - 0x3993677d, 0x3386593c, 0x56e304c9, 0xb9cc3c3e, 0x3afcb846, 0x0f00610d, - 0x817ad05b, 0x7d6c0b58, 0x903537ac, 0x0fcd7657, 0x24a5b7ad, 0x86f58fb6, - 0x93e553ae, 0xc3ce2639, 0x015127c0, 0xfad77798, 0xf10c51a1, 0xca2f302d, - 0xcd8bb39d, 0x5d5bce22, 0x504d53d7, 0xbbb6e619, 0x33e944c9, 0xc368c04d, - 0x764d3e00, 0xe4df3fca, 0x29adb4a0, 0x9ddbca83, 0x633f9a36, 0x80698881, - 0x85308aa7, 0x8f3cfdff, 0xe54165e5, 0xee9c6d53, 0x11035b4e, 0xfd3920b6, - 0x0d79bd71, 0x0efa428b, 0xccfc883c, 0x5db2871a, 0xf5e9d430, 0x4cc42367, - 0x3f3e4fa4, 0x7d12ddb5, 0x163fc927, 0x02ec7061, 0x24b19b96, 0xe02374fb, - 0x38f2ee6b, 0x9b129027, 0xe49438d1, 0xb46f0cc2, 0x7eb00093, 0xcc78430b, - 0xf860e453, 0x2395aa92, 0xb26b7eb1, 0xe6718055, 0x5ae79c5a, 0xced5fda9, - 0x4b7bf1fb, 0x93252199, 0x9026caaa, 0x72287763, 0xdcc0896c, 0xa07787c8, - 0x12fe449c, 0xfea2a50f, 0xf055a3b9, 0x56cf291b, 0x21d7000b, 0x78d2eecd, - 0x055b1394, 0xbb6c0ee7, 0xa9a9e40d, 0x0d769e47, 0x7a817f73, 0xf4077d81, - 0x255ffd07, 0x5d710220, 0xca1c726d, 0x75824df1, 0xb979c317, 0x059f080d, - 0x6e9c9d0a, 0xc8e11339, 0xa3eb81ec, 0x65105ff8, 0x288b23cc, 0x3d141b6f, - 0x79406486, 0x310e4e45, 0xca41f870, 0x3a3f11da, 0xa0e909a7, 0xc51292cb, - 0x886f28fa, 0xf2c38948, 0xc912ad39, 0xaa9e9545, 0x7c2835d5, 0xa3be1733, - 0x2a912bde, 0x56be9162, 0x74a44cb6, 0xcd9286ce, 0x24e3a05e, 0x9a3b1dc1, - 0xb867a3d6, 0x13b5399e, 0x55bc47af, 0x9b4630ef, 0x7a496f00, 0x104e526f, - 0xbed9ce3f, 0xbb41892a, 0xd3cddbf3, 0x5b17fe51, 0xa1a38acb, 0xd16dbcfd, - 0x1e9052d9, 0x7ae6ca49, 0xc4ed4164, 0xacf00638, 0x2791fbf9, 0xe78fa0ac, - 0xe8569f42, 0x70b69bff, 0xd4aa179f, 0x924fed34, 0x31dee780, 0xa1b3e279, - 0xe0f142fe, 0x1f50a32d, 0xe2a7be08, 0xce23bea9, 0x503c87da, 0x0fc073d3, - 0xdaf7a00e, 0xf51ef5ff, 0xd6f895f3, 0xbed0e5f5, 0x4885f6a6, 0xa6e167ec, - 0xa15be43f, 0x49e8a0fc, 0x173ffec3, 0x45653fb6, 0x9edd6c02, 0xee7c7a85, - 0x4f28b4a6, 0xf917f21f, 0xbd51f100, 0xaaf8205f, 0x517c33e5, 0xc7bb8406, - 0x4c560ccf, 0xf480ccad, 0x8d625e7e, 0xf6a80f68, 0x323e5a8c, 0xf3adcb9b, - 0x9093eb51, 0xb53fe64e, 0xccf50925, 0x5f3c1167, 0x6fadd4f1, 0xecf2dca0, - 0xaf101a34, 0x38331d1e, 0x41799f51, 0x551d22bf, 0x93c6ff03, 0x04ae61dd, - 0x0eca2a7a, 0x6fceb827, 0x51fa411d, 0xa77c179d, 0xcc74cff2, 0xd218f385, - 0x748d99dc, 0x7f9d67ff, 0xcff3e22e, 0x17a766f5, 0xf5cd99f1, 0x4bd79fdb, - 0x05ee58a5, 0xe47b4186, 0x885febcf, 0xd8f4b548, 0xfbd2256f, 0xd67684b2, - 0xea36428b, 0x76ccf0ed, 0x1bb22cc3, 0x9d59d118, 0xc359d395, 0xe0e97d01, - 0xa8c7b218, 0x37e746a4, 0x05af85f4, 0x9dd5bd8a, 0x80d7b7df, 0x87b3527c, - 0x6d3511db, 0x508ec867, 0x855a92ed, 0x39ee179f, 0xda857643, 0x871f6eae, - 0x5e3eed4b, 0xc801955e, 0x80e5cd1d, 0x0aba4200, 0xfbf905f1, 0xd3d7f5fe, - 0x7bf26997, 0xb5df7f29, 0x750f2e56, 0xb7a8499d, 0x349c64d6, 0x976bfe20, - 0x5e42fd2b, 0xbcde341f, 0x2f0481ec, 0xc16a1f2c, 0xfd8d0ef6, 0x9a2fbb50, - 0xc36bfbda, 0x97bea356, 0x4c3a2ceb, 0xa42d6b9b, 0x8bd5b7ff, 0x9c5cba19, - 0xed13985c, 0x916183b9, 0x07472859, 0x06653c2e, 0x3b6a0248, 0xbe50888f, - 0x2f73ca3a, 0x031c67d2, 0x6f5090ae, 0x5fb405f8, 0x74f95e3b, 0x6e3ff604, - 0x066be048, 0xbf0bd753, 0xf20c5e9b, 0x2d981964, 0x06671f64, 0x0f1d2046, - 0xf4e5cc3c, 0x1ab67ae3, 0xb9d31bf5, 0xf72834d9, 0x3c42dca3, 0xdbe61b7f, - 0x1dffff05, 0xfec60ff3, 0x143fc999, 0xd0a4bddb, 0x5968dba7, 0xaebcc02d, - 0x8359ea1e, 0xd041be4b, 0x222d935f, 0xac34a40e, 0xdfe7a1d7, 0x82757b55, - 0xc113a722, 0xc8bb408e, 0x416ec830, 0xf3366e3a, 0xccb209f5, 0xf71e611a, - 0x8d9e1e67, 0xa76d7a7a, 0x9d611989, 0xc8c33a13, 0xe41c4d7e, 0x6cd6bd22, - 0x2dbd224e, 0x02ac7438, 0x14ce1fea, 0xcfac3afd, 0xcfac3e4c, 0xae76214c, - 0x9db19668, 0x6fb5f070, 0x960fbe51, 0x82891e2e, 0x47be0df5, 0x9d433670, - 0x8f73aeca, 0x15a41bff, 0xfdec7697, 0x2dff4857, 0xe113b3ca, 0x75cbba7a, - 0x5ba803c6, 0x39336d6b, 0xc160deb9, 0xef7838eb, 0xb13691b7, 0x9d1d7e67, - 0x4dfb9ee7, 0x2726a62e, 0x07099fea, 0xa11fd225, 0xc3b0e9f3, 0x3d5287c4, - 0x2c3b3bb2, 0xb0104fa2, 0x70f791fe, 0x164c137e, 0xbaf684bf, 0xb065ff49, - 0xc48e617e, 0x935773e8, 0x83df614a, 0x938b1091, 0xd1747d47, 0x38eb7642, - 0x3a550f85, 0xdb9b2b7b, 0x72296f8f, 0x73338555, 0xaf582cc8, 0xd66cf0a8, - 0x1022faab, 0xf87b32ce, 0xaf529176, 0x932892eb, 0xf46d5e1d, 0xebb2e831, - 0x33d250e0, 0x3fd9c9fd, 0xf601dda0, 0xf954f2c4, 0x5327845d, 0x0acdeef4, - 0x2dfd54fc, 0xacdffd29, 0x8b66f1c0, 0x5376e1c8, 0x7a14dc08, 0x1e97a50a, - 0xdb41887a, 0xeccf1ba3, 0x51a3f6be, 0x6bdf84c9, 0xfd78e61e, 0xedfaf090, - 0xcd802b5b, 0x4dbfa0d8, 0x0cfefc21, 0xb98bf578, 0xedaf023f, 0x9bf578a1, - 0x375e2187, 0xa0676489, 0xa376881d, 0xb5c0e507, 0x60f6e794, 0x51392306, - 0xd7398529, 0x8077e324, 0x87c91643, 0x541f28a3, 0x15c430b9, 0xe9f506b8, - 0x71e57069, 0x8db1017e, 0x10a4e797, 0xf6b0245d, 0xbc072c78, 0x277da1e7, - 0x7e668699, 0xe5b7720c, 0xdfdedf01, 0x82cd3f40, 0x983ceb6f, 0x8b66f78f, - 0x0eb7ed13, 0xc3d5e89f, 0x59a25a3c, 0xbf187ed6, 0x4e55fe65, 0x4533962f, - 0xf8374c6e, 0xef837ed0, 0xbdf88d49, 0xe97f7f9c, 0x441f67ef, 0x8d33acfb, - 0xb25abad1, 0x67da3a59, 0xf419652d, 0xdcaab7fd, 0xb7823079, 0xddf4e32f, - 0x43e6df32, 0xa3e8f43d, 0x27a8e1be, 0xf1cbb65a, 0x510d4836, 0x981cf89e, - 0xd38920ff, 0x94324b7d, 0x7059ba43, 0x7ec5cf97, 0x0df3e1ae, 0xff3d8794, - 0x4e657414, 0xe506d105, 0x76231ba7, 0xe9555ca0, 0x2e30f074, 0xcf7887df, - 0x7938456c, 0x7a8cb027, 0x8543ffe8, 0x0bf854de, 0x008d36c0, 0x3c1098f7, - 0xa31774a8, 0xca585fc0, 0x413bcfe9, 0xf31d4f59, 0x0091bfa1, 0x38070953, - 0xf0c11a57, 0xd5967483, 0x6ff38d93, 0x91f80c5e, 0x0f1c1d70, 0xdd5645a7, - 0x155f07d6, 0x0df128e6, 0xa6f90218, 0xa9be7192, 0x7a42ba44, 0x0aba046c, - 0x481647a2, 0xae173e88, 0x83ca15d0, 0x1cb8f708, 0xc257e758, 0xf0b1f21f, - 0xa694ffad, 0xa4ce35f7, 0x1e2f2e1c, 0x734a7b33, 0xd04def48, 0x656f9dd8, - 0xfa889a7f, 0xafbdf4e5, 0x149a6025, 0xeb8c9ee5, 0xd7fe5cd8, 0x1fff1452, - 0xb8f407c6, 0xffcb0f8e, 0x2dda224f, 0x235f4b95, 0x79d2bffa, 0x37989996, - 0x5d1ee01c, 0x00fd382c, 0x462d79bf, 0x16f824e7, 0x0c755c57, 0x6ad659e1, - 0x56911874, 0x1c8d62d8, 0x408f2b3b, 0xda1d8a37, 0x39ba246a, 0xf4894bf7, - 0x8b92b9c1, 0x0f800eaf, 0x4e0856e7, 0x32d657ac, 0x3790256c, 0xa816292b, - 0xa057995e, 0x1ca9657a, 0x051a275f, 0xaf4037a2, 0xde283b25, 0x8ef5a731, - 0x13df88a9, 0xa40f5fc5, 0x187ac1f8, 0x2e63e547, 0x959e48de, 0x56abf529, - 0xbb47911b, 0xacb597bf, 0x3ffc88ba, 0xde521bd3, 0xec53e93a, 0x5b51acb7, - 0x8235c6ee, 0x4e57771d, 0x07ca0c44, 0xefce64e6, 0x40f24811, 0x93fa0ff2, - 0x447140bb, 0xc20f30cf, 0x61bc89c3, 0x99eba47a, 0xdba05708, 0xdd7ca5e8, - 0xbe0aa733, 0x99ceb049, 0x1f67ce16, 0xfbbe0996, 0x09ff3e05, 0x5065ef40, - 0x5d740b1e, 0x38e4c316, 0xe626dd48, 0x2e79c70f, 0xca09f61d, 0xd438d3db, - 0x8fefaa28, 0xf75ca1b4, 0xb78911e8, 0xe5a52f32, 0xede947cc, 0x98f34fcc, - 0x74933ac1, 0xfc93af90, 0xf38e312b, 0x0367b32b, 0x8b5fd7d2, 0xe0169c4e, - 0x4239ddfb, 0x439428de, 0xdd68038d, 0x701f5b97, 0x067680a5, 0x5fac41aa, - 0x147ee396, 0x4ccab3fb, 0x74ab718f, 0x995a8e95, 0x17d61537, 0x9be2debb, - 0x6b8beb04, 0xf5c21cf5, 0x38374fa6, 0x1383ef10, 0x74133af8, 0x543f9fdc, - 0x81a3606e, 0x183f360e, 0xdb3a43e6, 0xda2035bc, 0x03e6fea1, 0x97cc0180, - 0xf0bc14af, 0x4e61eadd, 0x7559d38c, 0xfeed111e, 0x188f56a2, 0xe1a7e208, - 0x394441b2, 0x23d3be91, 0x5ab49ea2, 0x353d53d7, 0x4fd4ac5f, 0x59067937, - 0x4e9e4ec9, 0xa15c33f4, 0xd49fb51f, 0x045f8356, 0x4ac917b8, 0x57b7997d, - 0x9e8a61fb, 0x3961db56, 0xab7a67d2, 0x453f4fa3, 0x3f505b4d, 0x08f88f83, - 0x7bd205c6, 0xfd711fca, 0x1bf084da, 0x36abf378, 0x2103374c, 0x9d1c71f8, - 0x79e34cc7, 0x15d33cf8, 0xbfbf87da, 0x63e38f7f, 0xb9bbf01e, 0xe422fef5, - 0x1f00cda3, 0x9de6f3c4, 0xcfd4ccb3, 0x799a59f4, 0xf286a931, 0x4b070825, - 0xa23c75ef, 0xd53d2fcc, 0xbd695a23, 0xe76843ce, 0xe28ccba5, 0x763f6a01, - 0xf405741d, 0x857a776a, 0x90cbcc7a, 0x47b8945a, 0x4eb38e3a, 0x5d31ff40, - 0x6b4957c1, 0xf63361fd, 0x5f1466e3, 0xfe85cf4c, 0x8426fea1, 0xfc37a183, - 0x5e99e742, 0x4273e7cc, 0xf18edfa9, 0xe76c7494, 0x74431158, 0xd5d7e7c5, - 0x1c6214ea, 0xa08fb197, 0x7e90c9fd, 0x0cb8c29e, 0x7e4ecfa4, 0xb42e4a6d, - 0x97d1fe7f, 0x52d0b476, 0x0fb33e0e, 0xf5ab56e5, 0x9c709be6, 0xff9f2283, - 0x5de2724d, 0x206ddf98, 0x53be9a3d, 0x7944db4e, 0xebfd1393, 0x55df56ae, - 0x2cbd422f, 0xeb64c618, 0x0a138f3d, 0x3a15da9c, 0xcb793938, 0x53ef5c20, - 0x582c7745, 0x5f87ed02, 0x3b8d38f7, 0x94fcca7c, 0x9b0fc816, 0x30abcbf8, - 0xc78e5f7f, 0xfee4023c, 0xde5fd2b0, 0x6ae50fb6, 0x821cfce9, 0x4576c597, - 0xda39a9f2, 0xbf02f5e3, 0x52dc4737, 0xd2b8fc8e, 0x24487066, 0xfa19eb77, - 0x7711cd59, 0xe5bfb1db, 0x4c26f9d1, 0x36bfd60d, 0x6e3c9ca1, 0x1e2131c9, - 0x18132d9a, 0x0aaceb96, 0x4f1bbe9e, 0x885240fa, 0x73847772, 0xe5744cba, - 0x0c272864, 0xbcad0609, 0x2f7971d6, 0xb43e1dd9, 0xf5acba9f, 0x60cc8148, - 0x7ca05409, 0x69795493, 0x3c717a71, 0xa3b4e2c9, 0x9142b4bf, 0xaf862c37, - 0xf73960d3, 0x5eaf389f, 0x962e63fd, 0x867f4b50, 0x4128ccb0, 0x9bda3ff9, - 0x573e10c6, 0xbbc58353, 0x6844f518, 0x70205d7f, 0x4fa38e50, 0x7e337647, - 0x5eddee48, 0x7a341bb2, 0x7a5e5ba4, 0xf221f5a2, 0x7a811e52, 0x792058a2, - 0x0ceb61e9, 0x0c12feb8, 0x3c5c00b2, 0x545eb8db, 0xce267bf9, 0x49e5f005, - 0x5e5c9165, 0x2673e4e9, 0xd1efc60e, 0x452a5cae, 0x5e021e22, 0xc3e9e0c9, - 0x9378f79f, 0x9d1e507f, 0xa987fa41, 0x21fe9007, 0x0fe144fd, 0x6f078a8f, - 0x50a3f5d9, 0xd912cb5f, 0x85cb9503, 0xe2cfb436, 0x6947d1bc, 0x2edcc5be, - 0xa6bf9768, 0x892a1cf5, 0x7979444b, 0xc799d962, 0xbebd41ef, 0xfff49c29, - 0x5667a5a4, 0xa66e3c60, 0x211a7057, 0x7d1a59ef, 0x6f987bf7, 0x905d3a34, - 0x81f0ab3f, 0x914597fb, 0xb8084f68, 0x759e8cce, 0x83321656, 0xf139e29b, - 0x3b409633, 0x34e0a34f, 0xa1e07a3b, 0xef527ac7, 0x37bc05f5, 0xfad0fe46, - 0xa8d7bc3f, 0x3e7759c8, 0xc6a2d9ca, 0x700a87e4, 0x7cf5eb5d, 0xd7d18d9e, - 0x3927de53, 0x1cb97639, 0x3fd8a99e, 0x57b3a59e, 0xc0f7c3c6, 0xcef9416a, - 0xc8a956f1, 0x88e340e5, 0x0d3f1863, 0x3e48172c, 0xa252bc79, 0x5ccdda1f, - 0xef784d9e, 0x5d900a28, 0xb43de5d8, 0x722b5a92, 0x3674a3de, 0x94588c17, - 0xe3dfa76f, 0xfe479ffe, 0x9bb62563, 0x83b5a2d3, 0x0cfd0226, 0x67bcb840, - 0xf1e9fd26, 0xefbad196, 0xea6945f0, 0xd38ead55, 0x8bab3de4, 0xe7b0c7ae, - 0x52277bac, 0x3992af3c, 0x2ade9122, 0xc1376e65, 0xe61b259f, 0x4f9d5733, - 0x2ac7b731, 0xa27ec18b, 0xb07b5aef, 0x3389fec7, 0x78a8df20, 0x3a13f154, - 0x19765eef, 0xacd076e3, 0xdd7ada75, 0x16301076, 0xe5caba8a, 0x32bf76da, - 0xb9459fbb, 0xe038dee8, 0xaeabf21b, 0x80821e50, 0x266e7f21, 0xa61f71e3, - 0xced543e8, 0x517a592f, 0x6668728f, 0xc23d45e3, 0x1fd2e673, 0x385fa7e6, - 0xa1bef3b5, 0x3ebb4a20, 0xbf934e39, 0x534435d1, 0x30f766ff, 0xa75bf7cd, - 0x5ef9ab5f, 0xc9a919ee, 0x5e3d5edf, 0xfd467f53, 0x7a1cad24, 0xa3d69a37, - 0x79bfa7e2, 0xa3e8a5bf, 0x12ec4277, 0xe23a9d35, 0xbf91133f, 0xe4672c3f, - 0x33787cbf, 0x1d31f8d3, 0xe7822423, 0xf93d5c80, 0xc8e5f731, 0xbf208fef, - 0xa1f44fc9, 0x7343f3c2, 0xa228c9a1, 0x7ee4627f, 0x725fa879, 0x5e503990, - 0xfdb1d4ce, 0xff8f5442, 0x9cf30e67, 0xe3bafec7, 0xf10f4b0d, 0x1f884378, - 0xff78a573, 0xbfcc0670, 0x4d79790f, 0x16c3f72e, 0xffaf36ee, 0xb58e0838, - 0xfc9ad16d, 0xebf1fda2, 0x3bd60e3f, 0xae1d044b, 0x93e146b3, 0x7da0165a, - 0xa0e8bb52, 0x40c4eafe, 0x583be62c, 0xf4b46c67, 0x0a8b838f, 0x258f800f, - 0xa9de2837, 0x193fc3fa, 0x9e0a453e, 0x1a70b4cb, 0x90e3cb93, 0x29108f5f, - 0xc7239cdd, 0xf103fee7, 0xf49eb41c, 0xdc7fbcdc, 0xc847227a, 0x9f9f0859, - 0xe3dfaf1b, 0x17940f1e, 0x7f0b908e, 0xfe4cb826, 0x47a5c247, 0xd82f47cf, - 0x72a3fa0d, 0xfdfb819d, 0xbf5c33de, 0xfefd7237, 0xf68fb47c, 0x44f39b87, - 0xed070ee7, 0xe93ed297, 0x618d7ba1, 0x59df1819, 0x797d23a1, 0x8190997a, - 0x2126c2fe, 0x0f36fc8c, 0xc81648ab, 0xc878b9be, 0xaa31fd48, 0x3afded07, - 0x0551f390, 0xe4096b3e, 0x71e5ccdf, 0x716e35b1, 0xf5038a4a, 0x1eac1ff6, - 0xe27a8b8a, 0xfd9e1e11, 0x696be130, 0x2bee45df, 0x6bd0127e, 0x8512d1e5, - 0xd5cc5f8f, 0x2e1f3ad1, 0x949db914, 0x1f70ba2a, 0xa9d81563, 0x96065768, - 0x915f28eb, 0x6d59e9c7, 0x9d0a1ff7, 0x14dd94c7, 0xda88f386, 0x7d7dba24, - 0x2e51fb8c, 0x793d0f8f, 0xb3ed1857, 0x68742a01, 0xd6bddbef, 0xaf582e69, - 0x8d96d0bd, 0xdcdadfb6, 0x4d6fea68, 0xcf159746, 0x748cfca1, 0xfe8eca78, - 0x8cfac0a0, 0xe655cd33, 0x580feeab, 0xe936fe94, 0x9da2bf41, 0x1e289822, - 0xf91af161, 0xb16715f9, 0x1ccade26, 0xa76e0b02, 0xf428f3d6, 0x1b42c76a, - 0xeff697e1, 0x5db178d5, 0x1ba417a1, 0xcf4abbc4, 0x8983fda1, 0xe9cc8dec, - 0x15d9f389, 0xe51a8e52, 0x8f748dd9, 0x1f90eafd, 0x07fe5cbc, 0xe3c4be6e, - 0xded7de2c, 0xe18879c3, 0x0c9c525f, 0x5fce4aec, 0xbee2434b, 0x024f913f, - 0x40cf0e66, 0xde1e5684, 0xdac9d0ab, 0x48de827f, 0x3ebc02ba, 0x8fe5cb9c, - 0x36fdc0ab, 0xb2c73bca, 0xfba230d4, 0x96270b1f, 0x51384560, 0x3872ba5e, - 0x1f3df379, 0xcc749e10, 0x7f71b46f, 0x72e1f90b, 0x31c2a47c, 0xbe9e6449, - 0x3c88f2f4, 0xca1bfbe5, 0x6ab7ae7e, 0x61d90fc8, 0x02c57728, 0xcc2cd2c6, - 0xffb6bc61, 0x8f9c0e7a, 0x396ae885, 0x96aee5d2, 0xcfe43094, 0xcabc6564, - 0x0ca7d29b, 0x205fa077, 0x040ed018, 0xe3c0c3bf, 0x574edc3f, 0xb94f7ae5, - 0x72c47ed6, 0x1f8f664f, 0xeaf7daa6, 0x82973c77, 0x59f3aae3, 0xfd61d8a5, - 0x125577cd, 0xdca2724b, 0x808f765a, 0x5ab1dcf0, 0x717df8d4, 0x0325615e, - 0x7fce3e3f, 0x8efd13af, 0xcdafb038, 0xf575cf28, 0x5e083382, 0x0a817b81, - 0xf8871338, 0xe24fe02b, 0x8967bd3a, 0x57c7425e, 0x85abb1d7, 0x5de71b8f, - 0x9f90c82c, 0xa02f5154, 0x9956b7df, 0xa3055c7f, 0x3e9969ef, 0x9e21e301, - 0xe38a5616, 0x03335655, 0x332af5c6, 0xf2865399, 0x7443c6ca, 0x02b9edde, - 0x206f2539, 0x4f3a4fc9, 0xa4f02ae3, 0x4d1d01e7, 0x7643284d, 0x864bb867, - 0x167f89f1, 0x4cb5a71d, 0x59efa2f0, 0x843ce2d4, 0x11d001fe, 0x2d3c7dc5, - 0xe75f1a01, 0x5d7271e5, 0x80e9c18b, 0x658d4875, 0x5521ffb4, 0xd4329c1b, - 0xdf29b63b, 0x2d95f18f, 0x0ddfdc8d, 0xd67493f5, 0xd1c3d7fa, 0x9910ab5f, - 0x790a0144, 0x5659fa2a, 0x30562e85, 0xf7ee3b77, 0x41fe1933, 0xdca548bb, - 0x2a6f3d5a, 0xd0e52266, 0x13dc8378, 0x6b9e409f, 0xd3b240dc, 0x678daa94, - 0xc92b2d48, 0x7d6233af, 0x890faca8, 0xa5d54877, 0xac971714, 0xf35bf2da, - 0x8e086222, 0x9e1e3c59, 0x8d88ef73, 0x727cc2b7, 0x1fe3797f, 0x41873d30, - 0xfe5b8033, 0x4c073bb2, 0xac16ff87, 0xa62378d8, 0xe8cebc4f, 0xe08fc19c, - 0xfa8c6657, 0xe8fafcf1, 0xb2abf295, 0xb9d00f26, 0xd27dafc2, 0x094f1abf, - 0xfe954fe5, 0x4d4ef943, 0x7f865ed7, 0x120526d7, 0xdf4f0f91, 0xdb03323b, - 0x73de3657, 0x5f88c7c8, 0x77d00705, 0x117177a5, 0x5660ba23, 0x5e5bd097, - 0x490b3784, 0x1f37bfec, 0x3b7c863f, 0x13e7effe, 0x95df087f, 0x63ce8c09, - 0xf649fd81, 0xdfaa9a9c, 0x3eb9f223, 0x246790bd, 0xc1464ebc, 0x053bac0a, - 0xc7bee0da, 0x2b4e6078, 0xf02e7fa4, 0x4de38b3c, 0xef9e3c81, 0x6b40fd7b, - 0x4b37ae0c, 0xa78ef5c7, 0x76e68edb, 0xa8ffb748, 0x06590fd8, 0xdced0536, - 0x771126c0, 0xc0e0596e, 0xe2d63be7, 0xc9b96bbe, 0xcaeb0699, 0xf448dfba, - 0xf68a0484, 0xa7689651, 0xb6aee5b8, 0x9f69cb8f, 0xd2c0d1b1, 0x0ee06e28, - 0x006473c3, 0x4caab0cf, 0xacc357b2, 0x857aaf68, 0x1e88aaa4, 0x22f5087b, - 0xef2cb40a, 0x30ac53ad, 0xb042aefe, 0xec7b3347, 0x59fed51c, 0xeb4c9f9c, - 0x6820ed57, 0x8fddb0c7, 0x0b4aa7e5, 0x19bb224b, 0xf7fb83e6, 0x90264cb6, - 0xff5213ed, 0xd92332f4, 0x7baf76af, 0x5bb470ca, 0xa0e6a797, 0x9ae30add, - 0xfd7f6e24, 0xbb67ca3b, 0x285ef94e, 0x49b9e0e6, 0x05801f75, 0x8718d174, - 0xfeaaed53, 0xe763a5e7, 0x9505b954, 0x9f2f9b7f, 0x59ff7ec1, 0x5563dd72, - 0x634d4de8, 0xe9e079f8, 0xcf8dbd0a, 0x9e9a5337, 0x73dbb3ff, 0xfe93aea7, - 0x39feeb79, 0x9ffae1d7, 0xffd88eb1, 0x3cd8f821, 0x3ac67ff9, 0x4ff2996e, - 0x5f37875c, 0x43cfc86e, 0xe746d679, 0x7e2eec88, 0xdee41c2e, 0xcb9cbc3d, - 0x09938b39, 0x74ffc764, 0xfd84d779, 0x1c1f419d, 0x7778a1cf, 0x67183a08, - 0x88a1a588, 0x8ca5cdec, 0x2c8681f6, 0x4340fbe5, 0x224d3a96, 0x6e1603da, - 0xec520e27, 0xb94b41ce, 0x9ca719dd, 0x118b882b, 0x3fd4327d, 0xca5bcbf6, - 0xbee0c6e7, 0xd5ec9190, 0xf5dd36e6, 0x5e53d416, 0x868fce89, 0xd2d289da, - 0x5f9c4a95, 0xf6aa9f6b, 0x79e31a68, 0xb4b3b2fd, 0xa3daa74f, 0xb4f29443, - 0x603f7ca5, 0x1ed68b48, 0xdad6ab8d, 0x1082fa8f, 0xbaa9733b, 0xeb49d07f, - 0xe9d72dd3, 0xa87ffcf1, 0xb07b89dd, 0xab0714a8, 0xfeb4067a, 0xf630d74d, - 0xf9f77e74, 0x1fdc1c8c, 0xd05ab99a, 0xcf5539e8, 0x7e282402, 0x43e3e2a4, - 0x3f8873d4, 0x5fb534f7, 0xaf3e6fd2, 0x2e4c7048, 0x539cd74f, 0x1e7eec62, - 0x3a73712f, 0x11eaf5fa, 0xddaed16b, 0x37c6eeb7, 0xfd697d31, 0x04e5e19d, - 0x6f54f5af, 0xebc6cb7f, 0x7650ff30, 0xe6123dbb, 0x53a8d0f5, 0xefd009ef, - 0x85e33c6a, 0x2978b3eb, 0x9e14b68f, 0x7ab3d08b, 0xa4dbdfda, 0x0d9f4c0f, - 0x45122be5, 0x23be911c, 0x1832981d, 0x59309f9d, 0x35f57e78, 0x30e3ee8c, - 0x1a9f5ce5, 0xd73d0987, 0xc7c3cab7, 0xc4f00559, 0x18963573, 0x39a91f7e, - 0x08e9fee1, 0x818766ef, 0x8b3939e1, 0x624fee72, 0xa82aaed5, 0xbf7edc77, - 0x0bee167d, 0x7e881867, 0x26ce98a4, 0x9ed993c4, 0x71c2af63, 0xcd35e242, - 0x2037e929, 0xfbb5bc59, 0x20679ef0, 0xc9cf7b7d, 0x2a9d312f, 0xf3c3efb5, - 0x88465225, 0xbf6bd29f, 0x9bdc1198, 0x4a5f3387, 0x6e3b9632, 0x754e9110, - 0x869a6feb, 0x50c154fe, 0x4f581ae7, 0x1bf30258, 0xbd611e60, 0x7b7989f6, - 0xce9c20a9, 0xf59648d5, 0xdfd80d15, 0x7fba08a8, 0xae03bec0, 0x4df3a7cb, - 0x80f657f4, 0x0e3a47a8, 0xc38ff653, 0x1fed7b32, 0x30c2fcd3, 0x3b59e14d, - 0x7a15c3e4, 0xca7b635f, 0x6b77fb87, 0x106e5213, 0x69f53d1d, 0xbbd6195f, - 0xab1bbbf2, 0x26fd5f68, 0x9fcf1593, 0xcafb2985, 0xa574e3a1, 0x43675b3a, - 0x6418b46a, 0x55f11673, 0xe0725f0f, 0xe68353d8, 0x9cfaf501, 0x736e3aa7, - 0xda83c71e, 0x64c2d19f, 0xf74323b4, 0x81fb43ad, 0x56be7079, 0x31fda9ea, - 0x01e746d6, 0x518b8874, 0xa7abb57d, 0xe9df0db9, 0xff1fbb24, 0xcc82e382, - 0x35fc431a, 0xcedb55ac, 0x0dcfca9c, 0x2a18f4a8, 0xfdd0a52f, 0x6f7ad4f7, - 0x9f81e138, 0x1fad0827, 0xf6d0d70a, 0x5833b7f0, 0xe160ddde, 0xa95d88fb, - 0xac22b99d, 0x473da57b, 0xbf5a7f33, 0xef7fd3d0, 0xbe6d3cfd, 0xb9f6364c, - 0x7d07943e, 0x4e8277cd, 0x6c596fbb, 0x8d2fb6d1, 0x25777ed1, 0x4592f368, - 0x6d91dfe9, 0x8e1af3a2, 0xf79e137c, 0x18d8f953, 0x8af7efe2, 0x2efa2adf, - 0x1e74c991, 0x79de9375, 0xe3c4e50e, 0x01d24033, 0xf82c3c7d, 0x552e58cc, - 0x0f515bb4, 0x93d3adc6, 0xaefc7a9c, 0xbde0ce5b, 0x6ba016a0, 0xf771e584, - 0xc56e9b47, 0xf148b17c, 0x70fb9b0d, 0xcb51d239, 0x37bf5f77, 0x3a9fcf1b, - 0x5bce740d, 0x75b1b73d, 0x1e2b61ac, 0x94cb8a0b, 0xfdf069cd, 0x84e62aa1, - 0x6323b099, 0xfc712363, 0x15a2d12d, 0xd1f3ddf5, 0x718efff5, 0x8c19e694, - 0xe14219f6, 0x46d23757, 0x756e3672, 0x5bf780b6, 0x5f9b1e1e, 0x06317289, - 0xaf9465fc, 0xc57dca90, 0xf015c717, 0xc5b6c0f8, 0xbe23c52f, 0xdb0f5837, - 0xa2159e69, 0x52d8a713, 0x8b7fe5c1, 0x7b3ed185, 0x3752a8f3, 0x72ec4d1e, - 0x8b3c0ec9, 0x41dee2d8, 0x2d595ef3, 0x9cacd972, 0xc8580197, 0xbe9c3951, - 0xfd4a360c, 0xb3346e98, 0x972839f8, 0x7ce8c292, 0x81f67f50, 0x57cb84b4, - 0xe9cc6f6c, 0x1143debf, 0x5cc8f18d, 0x9fe467cb, 0x6dfd0b9f, 0xf299b19d, - 0x538d3caa, 0xdfbbbbe8, 0x1bba3d10, 0x36724bf0, 0x9e2ce41a, 0x878e63c7, - 0xf575b789, 0x3a20b4c2, 0x7c8055d5, 0x2ee7e2cd, 0xbebb7e30, 0x87e334a8, - 0x9b9d4cfc, 0x5518e5cb, 0x97ebbb1e, 0xda05dc61, 0x635f51fb, 0x0fce783f, - 0xb7d71952, 0x443fa851, 0x830cf37e, 0xe839ef03, 0x430e402a, 0x56825d7b, - 0xc9181c4f, 0xc1fb35f1, 0xa09eccbb, 0x728c4d38, 0xbea3661e, 0xeb069cde, - 0x744338d9, 0x6c78076e, 0xfa1068a9, 0x55c4c78a, 0x0d997e70, 0xde6fd1f5, - 0x1b139152, 0x8c669ebc, 0x36d0c073, 0xdb9f0fd7, 0xbfc885d3, 0xbc79235d, - 0x1cdd67bd, 0x3f4071be, 0x479a87a8, 0x6ae6ae97, 0x557241da, 0x6d6de567, - 0x073a7aae, 0xcfc155d9, 0xf813ad5d, 0xc4a4827e, 0xf28b9bcb, 0x4bf4bf49, - 0x492b152f, 0x57e2849f, 0xe5fd3f9d, 0x9911e907, 0x8719f1f1, 0x4cceb49b, - 0xda07e1fa, 0x4af9743b, 0x1e0bd47d, 0x62ba7f6d, 0xf8e33651, 0xaf105fa8, - 0x7bc5e63a, 0x95fda193, 0x3a16fc2a, 0xe069c91f, 0x8d9db1ed, 0xdbf48bf8, - 0xc8e00169, 0xa1ce82e9, 0x3c38f7b3, 0x7c3a24b7, 0x2e01f86b, 0xae7487d2, - 0x78f7a52b, 0x658e098f, 0x7de8efb8, 0xe7f3a25d, 0xcd4f7aa1, 0xb13070ab, - 0x3e9ce736, 0x0f9c4dec, 0xa76935ea, 0x01fa89d7, 0xed8a97d0, 0x094b2a36, - 0x5cd4b3bb, 0xd7ade8e0, 0xab6d5cba, 0x937282af, 0x03f69983, 0x99534c3c, - 0x79c0307f, 0x1ccf33ed, 0x3df58abf, 0xf803ae0e, 0xe6bce099, 0xe63347f9, - 0xedf37b40, 0xb9b426ad, 0xf5a1cf43, 0x76a4ef6e, 0x4cab4b71, 0x23c519d3, - 0x86b95465, 0xafd90b08, 0xe48674cc, 0xc6c934b3, 0x3d10a7ed, 0x50f80eb9, - 0x644af08f, 0x38d0af04, 0x49f8e871, 0xdefcc905, 0x1a52e2e4, 0xa7454377, - 0x5d90e31e, 0x4ec57aae, 0xefa9f4f2, 0x7bb1fb42, 0xff23a73a, 0xc81a1577, - 0xc1f87e1e, 0xcf119349, 0xc51265de, 0x7bd17ad1, 0x233dbac8, 0x1cae9cf5, - 0x7f28cd8b, 0xdbb9ccb7, 0xfec3e8ec, 0x8b3152d8, 0x965a2fce, 0xa5633b70, - 0x88e481bd, 0xe7b942a5, 0x71cbd8a2, 0xa213bfaa, 0x3754b727, 0x9bdef198, - 0x8590de7a, 0xed97dbd8, 0xbbbd1fbf, 0xf18bf961, 0x2aee4fa8, 0x79c78869, - 0x4ff0896f, 0xd5df1377, 0xf2029f93, 0xf1e51e38, 0x920e91a2, 0x7ff2dd2f, - 0x0e3b39c6, 0x5569181e, 0x43db8af8, 0x417fe25f, 0x928d66bf, 0x1c6014a7, - 0x8e44b52d, 0x74bc6076, 0x00d3bbdf, 0x7abd93ae, 0xfb8d63f2, 0x2fc1f481, - 0x49382632, 0x681e9e5f, 0xac9d22b0, 0x8f46fc6a, 0xe2ce6bf7, 0x7fe855e9, - 0x87b70255, 0x9818c556, 0xa1f342df, 0x2e754f45, 0xf5a7a866, 0x0137dc09, - 0x798fc5bf, 0xfd102316, 0xbaf18e4c, 0x298700ad, 0x30bbbe31, 0xd7ac4aad, - 0x129c60d9, 0xf080b447, 0xc563a29d, 0x9daf1e06, 0x115cf385, 0x59c511f3, - 0xd1c5a727, 0xc5a3547d, 0xc9fbc3ad, 0xf6d5677a, 0x8bce8cb5, 0xb015bc51, - 0x8ce1f74a, 0xb6bdc718, 0xeeab8e27, 0xdcf1a913, 0x04290575, 0xffc1212f, - 0xcb23e22d, 0x1ef1101a, 0x403e987e, 0x46aaf8f6, 0xcd41f913, 0x91da3b09, - 0xf823323d, 0x3e7aa43e, 0xb163e017, 0x0c567c02, 0x95d69bbc, 0x17bb1494, - 0x91faa5e7, 0x50af20f1, 0xcc2565de, 0x4beb8a9b, 0x4aedc37a, 0x0cc67a86, - 0x1660365d, 0xa2b9eae0, 0xc61eac78, 0xd8583c21, 0xabfb4c38, 0x40d122bf, - 0xf2d0d8f1, 0x5c780b27, 0x21050b32, 0x135eebae, 0x755dcfdd, 0xaaf7bee0, - 0x301e7e50, 0x6767c939, 0xffbc1481, 0x66771dde, 0xaeddff7c, 0xdbb5bf9c, - 0xa63f740d, 0xf8ccbe3b, 0xe71abcbe, 0xd9e51a88, 0x31f2788c, 0xc7f421c7, - 0x8f71abfe, 0x4fca461b, 0x6dac7f60, 0x63c515c0, 0x68eac6c2, 0x8529279f, - 0x05f78279, 0x5feb2956, 0x7a870dd5, 0x75f5ea3b, 0xf6079428, 0x378d870f, - 0x2226bbe7, 0x88ec46dd, 0x47dafd47, 0x171343bc, 0x79287bc1, 0xfa6204b1, - 0x9c79aa93, 0x3cea6624, 0x5348778a, 0x0ad93ef9, 0xdcfc6016, 0x7c84c0a0, - 0xfd4beaba, 0xe887700d, 0x927accd7, 0x90ae9193, 0x7f2f48b8, 0x6576e645, - 0xa2dbdc88, 0x02f1f9f0, 0xcf91ee25, 0x93e7bff2, 0x5228bb25, 0x1889f7d9, - 0xe8724295, 0xd90a5711, 0x411cc443, 0x9d9cbef0, 0x87b15073, 0x8f9ca77e, - 0x83e72bf7, 0x83e72b0f, 0x0b77c55f, 0x863f90c0, 0x7a4016ef, 0xe549c9bc, - 0x2815346f, 0x6fe399ca, 0x4892ee45, 0xf9941fb2, 0xadf994e9, 0x25734eb0, - 0x6d567e03, 0x5879d3d3, 0xe984c263, 0xaf32cf68, 0xdb119edc, 0x7587ef73, - 0x9efcbfc2, 0x095da773, 0x3a4f3a1e, 0x3ff7cac7, 0x542d7c55, 0xb612afea, - 0xc75f9019, 0x36e16a76, 0xc6a452fe, 0xda622cae, 0x4d1397f3, 0x4bf53443, - 0x97f3daac, 0x6ad7ec93, 0x68764fbe, 0x975e5fcf, 0x1f643e31, 0x0b574b56, - 0x806e8013, 0x7d33aa4e, 0xd685ff34, 0xcd7b8a52, 0x74c7b90d, 0x3f36ab47, - 0x2fcda7df, 0xabcdaddc, 0x46c3c9e7, 0x9230f429, 0xf131fc8d, 0x0cf7e44e, - 0x0107ef85, 0x3ab36fbf, 0xcfda1199, 0xf8bf7816, 0x1b00c61e, 0x76c94bed, - 0xe3ac238c, 0x5cb09ff7, 0xc3bdcbc7, 0xbe7af695, 0xdb8ec56f, 0x4b1dbee8, - 0x06ede1cc, 0xfc7eeff0, 0x72f1a48e, 0xfe87af0e, 0xa21bd612, 0xe5c353f4, - 0xfe459c93, 0x33ec9b82, 0x62b36b23, 0xc2fe016a, 0xe9399a34, 0xab0c759e, - 0x9075bf27, 0x51327f72, 0x43bca4e8, 0x3e6186b0, 0xf0a67045, 0xe48f85f8, - 0xfe4950c3, 0x89f12a75, 0xf447745b, 0xb90d97e6, 0xaaf007ba, 0x910286f8, - 0x5623e2e4, 0xd8f9ef46, 0xbf13f75c, 0xb016c36e, 0x8f6b336e, 0xf87a1549, - 0x61bcede7, 0x5c135fc4, 0xb52fda0e, 0x780b2415, 0x8588a52e, 0x4536cb9c, - 0xc4a3e869, 0x5f42171a, 0x4be84243, 0x9d7f7f4b, 0x3945d5ec, 0xe842ce90, - 0xe5be2ff0, 0xaf182c51, 0x05fa8f4c, 0x7689d58f, 0xca9e054a, 0x754f9602, - 0xee319b46, 0x73d18b67, 0x3fd8a579, 0xab9f4aa5, 0xb2eb59e4, 0x566bfbe1, - 0xf6e649d1, 0xf13d2dba, 0x96df1825, 0xea35f600, 0x5c919963, 0x1fd3b07d, - 0x7fd43576, 0x65fffc04, 0xeb1bfd0c, 0x65efbc64, 0x5f10e4b5, 0x7949623f, - 0xd05ef300, 0x437f58e8, 0xe5aff731, 0xef826ce8, 0x05bea151, 0xc23da5ef, - 0xc1a94cf2, 0xfebc2df5, 0x5164597a, 0x31189f90, 0x9dbfea82, 0xcef86667, - 0xd9a07781, 0x63ec7187, 0xdd77acf2, 0x7b7feb41, 0xaf07d714, 0xa8f11c19, - 0x7c991e0f, 0xd287a677, 0x685f8d74, 0xbee4104b, 0x8f8517ce, 0x92bd7236, - 0x78c7e25b, 0x34c2747c, 0xfd039957, 0xe90bb71d, 0xf112e742, 0xfd375be8, - 0xa87e2b44, 0x0fc106e4, 0x5d749b4b, 0xe3ff430e, 0x35770b11, 0xd59e291e, - 0x02f98652, 0xd903ee91, 0xd9ebe25c, 0x7e02aeb8, 0xe54af0fe, 0x181ea871, - 0xbfdb9a32, 0x3c448693, 0xdffa1430, 0xb15a2450, 0x2b7a0dff, 0x4ef1e7dd, - 0x1757e466, 0xe097eabb, 0x11096dbc, 0xda6fcf0c, 0xbe781a0a, 0x00ccc0d8, - 0xbd6b934f, 0x4a69f117, 0xf6c08cf5, 0x7a7e0747, 0x5b19ed1c, 0x703a4882, - 0xaef9cba2, 0x2817eb1b, 0x79e29df1, 0x9b3c70eb, 0x599ab445, 0xb9541c0f, - 0xcbc99ebe, 0x0ab2ffc9, 0x0accdef4, 0xce0d436b, 0x708491e7, 0xae6df3b2, - 0x79e20b06, 0xd13d40c3, 0x7f224941, 0xc2556a57, 0xffcc0ab4, 0x7191a062, - 0x1f2ff3be, 0x5381fe8a, 0x5b3575a0, 0xc75e681a, 0xc139892e, 0xa9a896ef, - 0xcf85a1d9, 0xf8f146ef, 0xf1e30990, 0xf5b79f80, 0x8b9a9ccc, 0x78a7a3f4, - 0x6b7c7f53, 0x7ece5d73, 0x2afe61fb, 0x110b0394, 0xc29785be, 0xfa404f98, - 0xfe61293d, 0x5b017f77, 0x60d9d680, 0x6e41fec1, 0xbfa2fabb, 0x7e9cd188, - 0x4b0e0b9b, 0xd7824ef8, 0x341f1021, 0x444e4e5b, 0xb528783e, 0xa1e8e88c, - 0x899a8f82, 0xfcf3862f, 0xeef779db, 0x137a3c41, 0xe77f69c3, 0x315982a1, - 0x60bef4c1, 0x32f44894, 0x4e616fee, 0x9463e23f, 0x91fbf881, 0x8c56c708, - 0xccf3794f, 0x824bbf64, 0x986cd975, 0x2862c4e7, 0x5da2fe87, 0x7ef13e62, - 0x0b8f0575, 0xd57e302b, 0xf8843b65, 0x31664a90, 0x3949ae7e, 0xef9114f7, - 0xb435435c, 0x25956ffa, 0xd8cfde97, 0x4270d092, 0xbb20b6d9, 0x5722906a, - 0x45889406, 0x5906df28, 0xeb655db8, 0xbb940594, 0xaa47fba1, 0xed29d7be, - 0xa65b328c, 0x371b54a3, 0x7d7015d2, 0xe97f6a1b, 0xc35edc2c, 0xae8fbc3f, - 0x893f35cf, 0x317438e7, 0x197f7ada, 0x0a739ca5, 0x3a54afb1, 0x7ae560df, - 0xd1ae4362, 0xa1bd7487, 0x2a59db98, 0x47f2ab1f, 0x872abf85, 0xef7e7bd4, - 0x5195f628, 0x87365e4e, 0xe599eae4, 0xd4076f78, 0xc317739e, 0xfa56897b, - 0x1f72aefe, 0x6f6294f1, 0x5bd8a7bd, 0x5bd8a1ff, 0x05bda3ef, 0x835186f9, - 0x1437bf08, 0x08dd762e, 0x20901af3, 0x3a14df11, 0xedc44c4e, 0x271971af, - 0x61d97d2c, 0x0ea2d111, 0x348f05e3, 0x36497bf2, 0x1598ed97, 0x95cf59f1, - 0x766b2cf9, 0xbcbb3469, 0x7ae3f27c, 0xe43ed1d2, 0xb9557beb, 0x994c794f, - 0xfe6571ff, 0x57f3286f, 0x43498fed, 0xbca132be, 0xefaf10df, 0xfc297e47, - 0xb9d0a729, 0xb57950a8, 0xe908c401, 0xfc9122eb, 0xe778209f, 0x25bde46a, - 0x4ef5f720, 0x1e68c959, 0x7660dbbf, 0x7c462c57, 0xa714664e, 0x27aae89d, - 0xb90365b9, 0xf8b37245, 0xca6ceb5c, 0xe5833847, 0x6381519e, 0x8e5acbb1, - 0x4638be72, 0x24571f4f, 0x5bbdd0a4, 0x1d0efed5, 0x0cf072f7, 0x82a66795, - 0xf3e25ef5, 0x6c7247ff, 0x8ee3e32c, 0xfd3a24bd, 0x4f1cde5c, 0x91237926, - 0x5fed0a7c, 0x636f3795, 0xbe2064cc, 0xfba1644f, 0x610a7700, 0x9de7844e, - 0x3f307c28, 0xff7dd197, 0x673d8ac1, 0x01d1de57, 0xceb8a14e, 0xf5b04ed8, - 0xfc7af883, 0x1bf75325, 0x8f8edc6c, 0x9a27e4d6, 0x4bf535e2, 0xef9ac9ac, - 0x35c3ec93, 0xb23b27df, 0x32ebf935, 0xffea6946, 0xc9a459c2, 0x593050df, - 0x2e4cbf53, 0x6665e4d3, 0x0e4877a5, 0xfa1eed36, 0xa7fd1eb1, 0xa71fa1b6, - 0xa14f86f5, 0x0e0bf0f1, 0xa3b5e160, 0x00e8678b, 0x87518546, 0xfc864cef, - 0x6793d1c6, 0x0aef80e8, 0x3afe1f07, 0xd3685819, 0x7f3c29e8, 0x53afe1f5, - 0xf465bf20, 0x863f3c75, 0x3adcf091, 0x2f0cea7a, 0xea1c59e0, 0xd0347479, - 0xea972df1, 0xf83da28f, 0xe6d365c7, 0x4ef84b26, 0x06625940, 0x8a6ce7cc, - 0x7efc61e7, 0x15acec73, 0xfc761178, 0x8f74f577, 0x79a337ed, 0xfc8b8ebb, - 0x8b8e8d5d, 0xbb0d1dfc, 0x53f6f1c8, 0xcbbef553, 0x7e9a0e04, 0x64115fdf, - 0xfd05af7e, 0xdc6939cd, 0xfd14c4df, 0xdfd14c4d, 0xcdfd14c4, 0x6fee7a39, - 0x26fe8a62, 0x89bfa396, 0x324d5be9, 0xb934efa5, 0x726f6d28, 0xbf7dda53, - 0x6ae729e0, 0xef380a3d, 0x985b8b4f, 0x1117e4c3, 0x4ae7a14e, 0x4f9df43a, - 0x45ca7ed0, 0x12fbc0e6, 0x394e2287, 0x39acbf70, 0x2e7444cf, 0x4c3bb674, - 0x9730bdf0, 0xb62f9be7, 0x617e503b, 0x8e9eed1e, 0x946cb6e8, 0x16b5cdbf, - 0x35bbee27, 0x23c7f45f, 0x1bd6149f, 0x714cdee8, 0xe9c52767, 0xbdfc2d0a, - 0xc7114384, 0x91e3288e, 0x9179da5c, 0x277c45f9, 0xb0eedcc7, 0x3f60e32a, - 0xea326e30, 0x3025c2b7, 0xbf5bf52e, 0xb0a9fa98, 0x842b8f74, 0xe1fa6b8c, - 0x410a2771, 0x3176a6e3, 0xc701177a, 0xf5c66875, 0xfc3f744b, 0x78c25fa2, - 0xd3b44761, 0x354d718e, 0x21df8c5f, 0xdfcf45bf, 0xf8742c5f, 0xb893d425, - 0x5bef89bd, 0x33d881c6, 0x1f0d79d3, 0x47a865c9, 0x5d9db971, 0x9a179d7c, - 0x9f900bfc, 0x6077958a, 0x7ba58cc0, 0x730c4c9b, 0x9128bea2, 0x38363bbe, - 0xe339df17, 0x1b15a0ef, 0x1f90dbdd, 0xde5c74eb, 0xdf3318b0, 0xcfb5d057, - 0x3bd415ff, 0xec983b19, 0x4bfb0495, 0xb404752c, 0x44cae45f, 0x5b24e3bb, - 0x7568724f, 0x8f7fe794, 0x31be7a06, 0xf4505eb3, 0x7763f527, 0xfdc0ef85, - 0x86578e88, 0x4d1f21e5, 0x645e3a33, 0x1f7fbfc0, 0x3cfc44dd, 0x8791ca2d, - 0x7dfdac2f, 0x8f9e0af4, 0x3788bc73, 0x69acad83, 0x8ffc7146, 0xf1452f3f, - 0xa79a740d, 0x7fb43a0a, 0x765373d4, 0x063613d1, 0xfaeb54e0, 0xd7e7c0ca, - 0x7078c069, 0xc10718d4, 0x4661e06f, 0x273a98e7, 0xe076f847, 0xfa80df7e, - 0xb2878c6c, 0xd61e474c, 0xd277d24b, 0xef8ef27d, 0xa827fdf8, 0x50537919, - 0x8389fefc, 0xf8afab92, 0xdc31c9e3, 0x6a945d4e, 0xa8788759, 0x944c9bb3, - 0xe748bc1e, 0x9dce9982, 0xd96bf18a, 0xa97bf7d0, 0xfae18eaf, 0x41a57921, - 0x74410231, 0x30e594c2, 0x0cbde6a6, 0xbbf6d0f4, 0x8bdfbac3, 0x43327003, - 0xdef3c89a, 0xeb178f1d, 0xac65f534, 0xe31dfddf, 0xbda7acf4, 0x8fcddbfc, - 0xc6554f2f, 0xc7997a43, 0xd50c7fc8, 0x6d0b6b3b, 0x843f3bea, 0xcc63c7e7, - 0x523de9db, 0x14877949, 0x4e315aea, 0x3de8ce11, 0x37bfc1ae, 0x9e819afb, - 0x3d399a76, 0xdd3c8aa7, 0xeafaf229, 0xbbeaa53b, 0x7a14cf6b, 0xa3cc2b6e, - 0x8fd4fc7e, 0xdf1b37b4, 0x6d6788cb, 0x6efabe34, 0x012f5a94, 0x2b0920f4, - 0xe23a675d, 0xfb1250ab, 0x63e7e784, 0x1d20e68a, 0xb2f2685c, 0xcdf4824f, - 0xc6c8f085, 0x49d5fc60, 0x3f5af7da, 0xda81331f, 0x1b6beda9, 0x284fb227, - 0x3a27e978, 0x69154daa, 0x624ebd1f, 0x9c3be2af, 0xa80d5920, 0xa776d597, - 0x78e2de40, 0xc5fc82ef, 0xbb903df4, 0x3ed1e89f, 0xfbe94e9d, 0x3f2a1e4d, - 0x694d54dd, 0xca9ea9a0, 0xa46a6a3f, 0x23db96f4, 0x167f9172, 0x3ec65fed, - 0xdaf7a209, 0x1027bd36, 0xd4553f94, 0x51ad1d37, 0x7254e8e8, 0x1c9fdfdf, - 0x53bbedc3, 0x3b3e38e3, 0xf7c0dec0, 0x972e80da, 0xdbfd6d5b, 0xfdca1d1d, - 0xf9e3a3ae, 0x3c4765fe, 0xc31f2fcf, 0x64596efd, 0xe8fed8ad, 0x3fef0378, - 0xefc6ac45, 0x7bf78db2, 0x77a45d2a, 0xb1357ea4, 0x5831fee8, 0x73ca163f, - 0xaea7f27a, 0x41e5dfe2, 0xaf9d5cbc, 0x42b6fdfa, 0x61eefaab, 0x8fcf7f3a, - 0x7a02f7df, 0xfad5fea7, 0x3e702663, 0x4befad0c, 0x43c9e7e5, 0xc2a9f1e1, - 0x6817c4b7, 0x241f2367, 0x9d45f107, 0xa542f883, 0xd6fe9543, 0xa7387216, - 0x0f3a151a, 0x07eee7e7, 0x76842ea3, 0xb4cce383, 0xbbe3208f, 0x9d9eb0cb, - 0xa12fc282, 0x63bca0fc, 0xca83f2ac, 0x0fbd2a07, 0xefe33e06, 0x8c75f334, - 0x5f79fa95, 0x7b475958, 0x845dc46c, 0x2b7a83d7, 0x12b1adea, 0xb0792f7f, - 0xedcef5d8, 0x11b19fc8, 0x96918c0e, 0xf7d4b2ac, 0xfe3ec725, 0x9543c2af, - 0xa3c0fd0b, 0xca0c1c17, 0x123fc3bb, 0x50e7240e, 0xf6fd238e, 0x8c4eb721, - 0x177629b1, 0xc7cfdfa7, 0x1d226fc8, 0x1d660875, 0x30e87bde, 0xf05f7df7, - 0x0ebe78e8, 0x16d68e95, 0xe3074a32, 0x96f6873a, 0xba7aea7b, 0x230779d7, - 0xc61a97f9, 0xacf143cb, 0xfe482bae, 0xa979c19d, 0xec0c64f0, 0xa127e81f, - 0xe8ef42c6, 0xe0e856dd, 0xd3f036fc, 0x67ac0dca, 0x3e8a35fd, 0xf8944c7b, - 0x7e8ac87b, 0xa4172ee9, 0x1a996599, 0xcf4743bd, 0xefe15f3a, 0x5645fb8a, - 0xa372ef8d, 0x171c1d6f, 0xe5c8521f, 0x3cf4d743, 0x2f13f711, 0xf742d5fc, - 0xea0c2f8b, 0xcef68d3c, 0x533d5685, 0x2a9b23de, 0x8b9dde80, 0xf90c133e, - 0xf39ef2a5, 0x0ef7e8e7, 0x176d7a83, 0xb5bda34f, 0x4cc4ab68, 0xeb609e78, - 0x3d20b737, 0x4f457bcd, 0x5b9a99e7, 0x7a471e37, 0xc04fb73c, 0x85d96fe7, - 0x31c5027d, 0x7c225b6b, 0x0a5fa866, 0xc77fac79, 0xe3c7c96e, 0x39c5328b, - 0x3ef1946a, 0xa0a5d731, 0xeb713e5d, 0xfb843a5d, 0x8b02edbc, 0xb48f7e83, - 0xdf0c79de, 0x8db7391d, 0x366b2fdf, 0xf9c0ee47, 0x0ceb4a97, 0xc17ca083, - 0x635e5e76, 0xf70cfd29, 0xcd3c1743, 0x60b3fe28, 0x8ff9046f, 0x1ff45af3, - 0x8eec8205, 0xfcda6dea, 0x4066d67c, 0x53b0583a, 0x07b35e5b, 0x79f241f2, - 0x2f12a150, 0x29b2ce19, 0xe3c2d25e, 0xef7caa07, 0xb97b5f6d, 0xde506d1c, - 0x897f66ff, 0x5f0ff7a5, 0x23e926f9, 0x2997cf0b, 0xff9033f9, 0x178e1bea, - 0xca752e15, 0xb3c55fd8, 0x675836dc, 0x2b662bdd, 0x0775edfa, 0x79e246ce, - 0x016145b0, 0xbd99177a, 0xded1592c, 0xe4bf607b, 0x1ed6f845, 0xfb893f34, - 0x9e2f7598, 0xa13c6030, 0xb262df74, 0xef312657, 0xfd9bf44a, 0x89dac8a2, - 0x7de9da8e, 0xce77265f, 0x1c2e7ec3, 0x0ed15b30, 0x4ff97ba8, 0xfcc76ec7, - 0xa7dd028b, 0x201890bc, 0x55b7993a, 0x0c437ba2, 0x1efcb42d, 0xaf10913a, - 0x28b6e788, 0x0ee58f7a, 0x19e23bc4, 0x4648eef0, 0xd071e13a, 0xf44b4f79, - 0xd9b5b9bd, 0xf9cff580, 0xbc557e38, 0x094b4a97, 0xe71e0bcf, 0x75b89cf8, - 0xa430e6d7, 0x64f5a783, 0x76811f8f, 0x0d3b7883, 0xe15e181d, 0xc5d85ffd, - 0xd37791cf, 0x376301c1, 0x2f3ce01d, 0xa7c00747, 0x472ff7a4, 0x97e89d07, - 0xddffbf92, 0x0ed0c7b9, 0x87e7e08f, 0xd51b77d5, 0x2e071a77, 0xdf14753c, - 0xbfb34ae7, 0xa5777640, 0xc5da8bed, 0x9d09de8c, 0x4be78853, 0x02bdbf26, - 0xca7277d1, 0x2f14d9b3, 0x6d7607d5, 0x744378c1, 0x3ac7c538, 0xe1b6cb92, - 0xb6c598fb, 0xc2f6936f, 0xcefd163a, 0xeb11e748, 0x3fc67e15, 0xbea2073c, - 0xa7780c4b, 0x07b519f3, 0xc65cfc8d, 0xe1fbed3e, 0xce9cf11d, 0x959d0c4b, - 0x804fd18b, 0x411c70fe, 0xc2e9fee6, 0x451dfc83, 0xa85c9fd5, 0x47b8a7be, - 0x60836efb, 0x3dea9b7d, 0x70429850, 0xd6371a18, 0x73797681, 0x0d84f339, - 0xc17d21fd, 0x5c7ca9df, 0xb5fa8bf1, 0x1bd1fb27, 0xbcc91daa, 0x15daf721, - 0x014775b9, 0xbbd1e39f, 0x7be1d0df, 0xf93b1d8c, 0x3fcc3bef, 0x062af208, - 0x1af519f7, 0xd4a753b9, 0x0fe914ff, 0x5bde76e0, 0x052892ff, 0x8bf797cb, - 0xa79a9fb1, 0x48753f79, 0xf5571457, 0xfe830e6f, 0x33d36cbe, 0x4c0597e4, - 0x23fb3791, 0x4bd46e28, 0xbedcecbe, 0x50f7cd12, 0x76085aba, 0x94222e26, - 0x69f6eabe, 0xa85d3deb, 0x670e7bec, 0xfff9e0d7, 0x90e031af, 0xba5f23d7, - 0x8e67e9df, 0x6eefe428, 0xef68287d, 0x056b0fef, 0x77ea0f96, 0x63c4cfb8, - 0xeafe4aa4, 0xfe4d56dd, 0xa6bb369a, 0x1dfbb5fe, 0xfed9ef9a, 0x11f7cd0c, - 0x7c9a9dc7, 0xa6817b5e, 0x64f7c8fe, 0xc0547e4d, 0xe63fa9a5, 0xef935bbc, - 0xf4f584ca, 0xe9a8cf61, 0xa9a0bb24, 0xd661d93f, 0x465d7ff4, 0x65df26b4, - 0xd8a3e051, 0xfbfdaa99, 0xff6e42a7, 0x7c2aa686, 0x8ed4e17f, 0x37edfaa3, - 0x2bc76814, 0x5de3b593, 0x1df05e29, 0xff9e9d41, 0xf8a6027e, 0x34ba09fb, - 0x9809fbfe, 0xc04fdfc7, 0x013f7f14, 0xe4dd7fcb, 0xa6befca4, 0x04bfca02, - 0xf7e6097e, 0xe9829f83, 0x609fe0cb, 0x77e0e5f9, 0xb8f7194c, 0xca1bee32, - 0x4e153fb8, 0xbdfd296f, 0xef87f4a3, 0x3df4ea0d, 0x795d6bdf, 0xe3e025e2, - 0x7467db22, 0x086e595f, 0xa31c6294, 0xe18975f3, 0xf1e667f9, 0x418a6f1d, - 0xa18036fd, 0x9ddcc49d, 0x6e3ee26f, 0xad438bdd, 0x81efae78, 0x07787ffd, - 0x27d85fbf, 0xf0e6bc51, 0xd891b3fe, 0xc29797cf, 0xe90a30e9, 0x7cd7c845, - 0x0d7e502b, 0x6773c77c, 0xca4af793, 0xa46d67bb, 0x554cbeef, 0x2fba3ef3, - 0xd7b3deed, 0xb85a7880, 0x7f7d2f7b, 0xf35af81d, 0xcd76f77d, 0x87d62b77, - 0x47cea174, 0xf7cf8571, 0xa9f9fdab, 0x7f2a4d7e, 0xddf3fe3f, 0x418e5647, - 0x6ab7bc7d, 0x17b5c600, 0x3b1139ee, 0xf1f007fb, 0x66cf4bd5, 0x3da81ea2, - 0xd1e72920, 0x07b57f78, 0xcf9e4af4, 0x6f7526bf, 0x63379e29, 0xb3ba047b, - 0x4f5b25f4, 0xee16c4e7, 0x728355df, 0xedc66176, 0xb57f8a7a, 0x83bc4a49, - 0x6350d3bf, 0x6baedc65, 0xdf123afb, 0xdb7dffa9, 0x1ef1ebd1, 0x23c1c774, - 0xc74c5ef4, 0x4fe3493e, 0xf1cb1d8d, 0xf72c763b, 0x77dcbeff, 0x09cf1224, - 0x8476d03e, 0xa7e75dc3, 0xf2561ff5, 0xbc12901d, 0xfeb44bf7, 0xcd2497f9, - 0xc0b801ef, 0xcdfba171, 0x7022d3fb, 0xf8db275d, 0x7d40d378, 0xd56a7950, - 0x1bff9c1c, 0xe53cf2f6, 0xddfa327d, 0xaeab8ea1, 0x767285db, 0xe7d49b61, - 0xd839f779, 0x98efcc2f, 0xebe9d39e, 0x1b1c2fa9, 0xc37f7004, 0x749b2035, - 0x62af5284, 0xa59bd72c, 0xea2a4f06, 0x47169391, 0xfdf9d204, 0x8811a1ae, - 0x6298c3df, 0xba49ebb9, 0x1f60be07, 0xb5a4ef1f, 0xeee9123d, 0x5211bee4, - 0x2dcbfef0, 0xe9ba7aca, 0x5e6f1bbb, 0x6fb553c2, 0xe9fb05bb, 0x9f2f1fc1, - 0xf54ad636, 0xb89df0df, 0x93aced05, 0xc0ddfc19, 0xfe460663, 0xdc3dc2f5, - 0x70793e4e, 0xfbe0f6f0, 0x7c14d359, 0x7df06474, 0xf5fb0bf5, 0x77dbbd4a, - 0x3d3d4d31, 0xed4ed7c7, 0x33beac7c, 0x5e7da10f, 0x6744b8f3, 0xf5f46a1d, - 0x4ffeb8b1, 0x57e769b7, 0x46b9c0ad, 0x0d8d8fef, 0x039ad7a2, 0x21637cdd, - 0xf2a03f3a, 0xa9f08389, 0x8664f1e2, 0xe765e7c4, 0xecd5f8ef, 0xdd7445dd, - 0xe3c4be3b, 0x31ef83b7, 0x74be2939, 0xb55a7f19, 0x2dfc821b, 0xbd23bdfa, - 0x989e686b, 0x9c1f63d2, 0x1a1f942e, 0x987e879b, 0x93ccfc9b, 0x185bec0c, - 0xebed16b3, 0x891dfa28, 0xd76e38cd, 0xffbd3d3e, 0xb03a6b5f, 0xef23df00, - 0xc0a30272, 0xe9b6bbbc, 0x4667dfbb, 0x629e773b, 0xf0ea7ee7, 0x7fa04be4, - 0xb489976b, 0x923d9abe, 0x5c17cf0f, 0x57dee450, 0x406f937b, 0x2e39ad7a, - 0x9a3fd159, 0x70fc96d8, 0x77e92e61, 0xdaeb57b2, 0xb75c9db8, 0x58bb205b, - 0x156a43b5, 0x629ce43b, 0xd65b9f07, 0x57e3edc9, 0xea11b604, 0x7b030dad, - 0x9b5de604, 0xdaec8539, 0xcadd695a, 0x473c0ec1, 0xe61bb5a5, 0xe7443c1f, - 0xd1cec0ae, 0xaddc2f94, 0x69b6d7cd, 0xf8bfaaf3, 0x3b6ed8d2, 0x37fa3863, - 0x1c615225, 0x0a9bc3f2, 0xe77f555e, 0xf49c6bce, 0xe80f27fb, 0xb8d4531c, - 0xd16bc204, 0xc7cc2f2b, 0xc26afb79, 0x347fe49c, 0xdae096fe, 0xd7ee17f1, - 0x1bdee074, 0xf0e333f2, 0xe9cfd8ed, 0xf05e917c, 0x2cbaefe1, 0xfd815d42, - 0x32df0499, 0xbb7b3b8c, 0x293e4922, 0xca1a08e7, 0x632affb9, 0xb2a6180c, - 0xe7f72c7e, 0x38eaf543, 0x0e8a405d, 0xb1811392, 0xd8af5429, 0xde57cfc0, - 0xfd24e119, 0xedc4c436, 0x6e2621f5, 0x75d10faf, 0x85dfa32e, 0x7df02418, - 0x6997ac8e, 0x9d6d60ff, 0x0417f685, 0xe10e957b, 0x955076b1, 0x887de90e, - 0xfd032db5, 0x8c5f353a, 0xec7b33df, 0x478b5283, 0x8cece387, 0x047d9417, - 0x74cb4fae, 0x90747d56, 0x996c657e, 0x3dea7e66, 0x7e7d9fcc, 0xa59f9856, - 0xef807e67, 0x75ff6c28, 0x86ec93ae, 0xf7f532a4, 0x2e49ea1a, 0x12fcf0a8, - 0x7018bde8, 0x816c7745, 0x1db66a6e, 0x96b2ff22, 0x76c4afb5, 0x1d7c91a5, - 0xbefe06a5, 0x4f186951, 0xfcb8e375, 0xa5d2512a, 0xc3f6b4e3, 0x7eb27191, - 0xc63ba41c, 0xf2e34db9, 0x79953f68, 0x6f0d7d61, 0x43d677f3, 0x13943ee5, - 0x7c0d7d3d, 0x466ff288, 0xd54d60bd, 0xbf9c69d8, 0x6ea2f116, 0xf6f85a3e, - 0xea27c493, 0xc66acc39, 0xa3667bf9, 0xc41a9ad9, 0xdf908b17, 0xc377ded0, - 0x138c7cbf, 0xeb6abff0, 0xe9973a7c, 0xa2b58c69, 0xfa48b75f, 0x7e25f692, - 0xda2ddf2c, 0xcdfbcdaf, 0x11fdfe9c, 0x1949f902, 0x0de3bae3, 0x0a498fc4, - 0x08f76c7f, 0xfb600e74, 0xcf1e3a77, 0x7e2810ab, 0x36143377, 0x624994da, - 0xba22eabd, 0xe333724f, 0x4b596347, 0x3dbbf28c, 0x796fb431, 0x9beeb293, - 0x2843fe75, 0xdbea8e57, 0x749e3192, 0xc4e4d6b4, 0x1b59cbfe, 0xc15a6fbd, - 0x153d29da, 0x9fa2f75e, 0x2226f73a, 0x63c9fddd, 0xf6d678a4, 0x50223be5, - 0xe5b167be, 0x044fdc56, 0xb7c6ec50, 0x73b3fb01, 0xd51df742, 0x2f60c4fb, - 0x027d21c7, 0x1d2127fe, 0xd8dc079c, 0x5fb77a73, 0x2317c7f8, 0x2c5f7f11, - 0x5b96e179, 0x9d5ffa19, 0xa82d47e4, 0x5df7465f, 0x33da9c81, 0xaaf07bf2, - 0x5bc55de2, 0xf01d5e37, 0xb0af182f, 0x938404a6, 0xc91965f4, 0xe8917fa5, - 0xf0e5d69c, 0xbc7dc2aa, 0x0e3b9f82, 0x8a15f970, 0xb70f156f, 0x43f5bbe2, - 0x236eef49, 0xc923313c, 0xb87a50cb, 0x3080be1c, 0xc4d93ce9, 0xa1f92318, - 0x4f2e4583, 0x2813cf07, 0xf33b795e, 0xf48012bc, 0xf5f7f096, 0xc70adefc, - 0xb782855b, 0x2fdf313f, 0x71ff9232, 0xce323b78, 0x606e34dd, 0xe50dbe6f, - 0xb2f8fed3, 0x37fce1c6, 0x18fa5f55, 0x3f0863f2, 0x376bf087, 0x2ff09d1e, - 0xc69e8f08, 0x6ecbe248, 0xae7b4b7c, 0x7fe22f4c, 0x5fb58e30, 0xaf93f9f0, - 0x46055f80, 0xf8f8bfbf, 0x54dead38, 0xa5c2a6f1, 0x07e0b8bf, 0x2ad47fcc, - 0xe70abed0, 0x748dbbe3, 0x57dd43ff, 0x5e4ff751, 0x5cf5c719, 0xd801fa68, - 0xb55fb84b, 0x40e4e326, 0x194f33b4, 0xfef87ed4, 0xdacb07ef, 0xb6f7f113, - 0xe9e2283e, 0xddff0329, 0x872f350f, 0x07e4b8f1, 0xc22f46f1, 0xf86103e9, - 0x1f33d404, 0xcf5cf708, 0x070671f3, 0x26e3cbe6, 0x53903de0, 0x798e357a, - 0xf07f12bf, 0x8f9479f1, 0x027aa62c, 0x074a5dff, 0xf61ddefe, 0x1736082b, - 0xbb83e7cc, 0x9d7de8d2, 0x718d7dee, 0x467f0edc, 0xdc774759, 0xe2815eff, - 0x355133fe, 0x84c4fee1, 0x877c2e2d, 0x437df4f3, 0xb4df69b3, 0xea3e3b41, - 0x978a64fd, 0xfee7e06e, 0xabea752e, 0xb75bf482, 0xc8be2dbe, 0xd1e4e7cb, - 0xbfa88cef, 0x86db2747, 0xc7dcff73, 0xd550df7f, 0x5fc75d67, 0x73c704b0, - 0xdfe2533f, 0x0fe1f9dd, 0xc3eb0526, 0x4dad4f43, 0x0daa7ec7, 0x05a72cde, - 0xb1ee877f, 0xaa5bb424, 0x4e955a9f, 0x0f53f4f6, 0x545fa3a4, 0xba6d63bd, - 0x0f70f94c, 0xbe3a65f9, 0x1b9e2fee, 0xd4f3e745, 0xdccaf6fe, 0x1d30a8af, - 0x3dbd412a, 0x56afeae5, 0xda41fee0, 0xffc5027d, 0x15f6b066, 0x332b67a8, - 0x16b15f38, 0xe87fc913, 0x776bf68f, 0x4ec5ff0d, 0x646f0794, 0x81cfd59c, - 0x203e127a, 0xd5df1035, 0xdfa3adf2, 0x7fcd5c09, 0x7ea7b027, 0x56ffed22, - 0x9de8172d, 0xfcf519ab, 0xf1a4f377, 0x59c704d1, 0xd18fb3ab, 0x794b57fb, - 0x6fa314f9, 0x67ec49df, 0x3fdf818b, 0xe094ee64, 0xb29270fb, 0x9d73385f, - 0xca717bf2, 0x639b6938, 0x53af07b7, 0x591df652, 0xdf2477ea, 0x32f0506e, - 0x5789e975, 0x54efd0ed, 0x1e3cc7bd, 0xe9b3bfbe, 0x619faa5c, 0x3a33f41c, - 0xf066985f, 0xd71f3a3c, 0x7148c3bd, 0xc1acdcd2, 0xcfd41c52, 0x11b45259, - 0xab4b99d3, 0x728f9d1e, 0xcd94d5b8, 0xf9f2358f, 0x114e0835, 0xed91f4e5, - 0xb842ceb7, 0x7fc4df9d, 0xfb61abff, 0xc2ddfa30, 0xafdee4fe, 0xf9eff89a, - 0xa264dd3d, 0x2b26d9f4, 0xcfeba3c3, 0xff29d935, 0x4a0e4daf, 0xcd3cf4d9, - 0xd7f4d8ef, 0xe14b88df, 0xb973bbf4, 0x3bf4cdab, 0x39460d88, 0x2bc03c75, - 0x1ddaaaed, 0xc2eb280f, 0xbdb2b8f7, 0x0e1113c9, 0x3e2c0fb9, 0x75b3a686, - 0x7d97df3c, 0x24eae4f3, 0x2c77d614, 0x7cc4f33d, 0x78fb7ef8, 0x270835f7, - 0x148bb6d3, 0x607238a7, 0xbbc22555, 0xaf91877a, 0xf9f7594f, 0x8f71e94d, - 0x75f97c62, 0x160dc53d, 0xc4f33b6d, 0x877f0c03, 0x9821b177, 0xbd74afde, - 0x7ee78f57, 0xaaf8e5e6, 0x78fc383f, 0x449b5abe, 0xf803b3fc, 0xf3a7f32a, - 0xcba5a2d5, 0xc6cb7e08, 0xb8426fbb, 0x937bd79d, 0x0fce9f90, 0xee744b1f, - 0xf820457d, 0xdbbc72ab, 0xbfe056af, 0x575b6c50, 0xc723dc98, 0x04b961bf, - 0x3e0743df, 0xf9fb474d, 0x3fe5fd9b, 0x6097eeb8, 0x1861fedd, 0x1a5133af, - 0xe0df3dfa, 0xf584ea19, 0x3ef3f7e5, 0x6af1d2e8, 0x539f9ffc, 0x36213fc0, - 0xe6219df8, 0xd4f9828d, 0x61fc141c, 0x26cfa859, 0xbf43a67d, 0x8fcffc11, - 0x198ce734, 0x9f4828fb, 0xcbdf37f7, 0x4fd875a5, 0x1ddc8f5a, 0xfcc89ef9, - 0x547b7a41, 0x83f98c20, 0x73f6edc6, 0xfb40cca0, 0x1724f14e, 0x2e786f10, - 0xe181c2ec, 0x99ff303b, 0xc2f1e381, 0xf14f604b, 0xf2931078, 0xd9f9d67b, - 0x50b22f81, 0xb7ae86ce, 0x882fe5ee, 0xaff66a3e, 0xfad028ba, 0xcba67f27, - 0x0ffafcba, 0x1645f53d, 0x7d33efe2, 0xb6fd1f20, 0x1640860b, 0xb7eea1e2, - 0x58ff9e5c, 0xf3e5a838, 0xf7e81b57, 0x1304eb3a, 0xf48949d1, 0x2e1fc525, - 0x87f1e71c, 0x924f03ba, 0xc83aed3c, 0xc48b40e3, 0x8c38d2f6, 0x399fd49b, - 0xcbacf286, 0xe831fdce, 0x2b71de9f, 0x41e8aa1c, 0xde12675d, 0x4dd83bf7, - 0x3c8fdc0f, 0x0c3bfc8f, 0xf3a369fb, 0x9c2b2cbd, 0x39f15da1, 0x7c30f3f2, - 0x257930bf, 0xdf79f9d2, 0x8f941cc0, 0xadfd666f, 0xbf86e28e, 0xb27ba70f, - 0xe6926db5, 0x3af7799c, 0x703f127c, 0x29fb54c4, 0xe7c1c99c, 0x1b8e0cb9, - 0x837e6ec8, 0xba2e13ef, 0x7b13f38a, 0xed53f399, 0x7b0643f2, 0x15bb7f50, - 0xc8ed527e, 0x1bffbf29, 0x85b3e5f1, 0xd504fd32, 0xffc7a54f, 0x4cf7fe9f, - 0x33412fff, 0x800063ec, 0x00008000, 0x00088b1f, 0x00000000, 0x5aa5ff00, - 0x5554700d, 0xbdef3e96, 0xdd2749fe, 0x12421349, 0x42068408, 0x03621a88, - 0xc4d67281, 0x206efce9, 0x6b01bb33, 0x8d08c42d, 0x749d2422, 0x6aece882, - 0x021a6eb9, 0x367564ac, 0x1d47598c, 0x809f9b47, 0x9476ec28, 0x0da0c040, - 0x6ba2cb0a, 0x3a26aa45, 0xab545b55, 0xa6e00eac, 0xd63b8223, 0x3be7b8e2, - 0x1dddb5ef, 0xa6ed4fe2, 0xee7dba8a, 0x9ee7b9cf, 0xce77ce7b, 0x52b48f3d, - 0x6a22ca22, 0x2a08cdcf, 0x6ea6ff0a, 0x6d4445a2, 0xf67f2429, 0xaf1f4541, - 0x7dbc64d3, 0x58c9a340, 0xce08eb93, 0x4754419e, 0x459a26dd, 0x654284b4, - 0x29bf71a4, 0x795bcbf2, 0x6d0dfebc, 0x61931741, 0xb06aad1b, 0x7aa6d513, - 0x1314360b, 0xaacaab0d, 0x0bcc6286, 0x4b9d2e95, 0x7efe0df4, 0x879b744a, - 0x2a224f99, 0xf60f14d3, 0x169c9d1b, 0x8b5dc9dc, 0x491bfb97, 0xeaa7984d, - 0x534f98f3, 0xa3827c08, 0xd81d4b25, 0x9964b468, 0x8eef3e23, 0x07d6d237, - 0xd2a14e31, 0xf9f6123b, 0x68858f4b, 0xcb17d121, 0x650faa17, 0xdaae79f2, - 0x51337403, 0x29ed768d, 0x70ddf785, 0x05564ccc, 0xafbc67fc, 0x670239f2, - 0xfa65ea34, 0x790a4752, 0x4bceccac, 0x1bcf0f1e, 0xd8293b99, 0x3f6fe7c5, - 0xe78990a0, 0xeeb11db5, 0x6d79e14c, 0x9bb648e6, 0xf036ddf7, 0xdb878b3b, - 0x2cf7fef6, 0xcf58b9ae, 0x9e433647, 0x6dfa1514, 0x174ff277, 0xce607f91, - 0x3f3177fb, 0xf44d69ff, 0x67bd37ed, 0x05d7d621, 0x5afd8f9e, 0x82d5f60e, - 0x56f0a56e, 0x3cfdda27, 0x9bbf48af, 0xe5dff86f, 0xb386575c, 0xf8be7e38, - 0xa7a25d39, 0x69f8bd18, 0xd602f73e, 0x43eb468b, 0x21ee5976, 0x6e717b96, - 0x252e8ece, 0x5fae9d71, 0x4b69768f, 0x9d15cb0e, 0x6615b8a9, 0x6c0d4d15, - 0x851f4276, 0x1797b38a, 0xb97f5f47, 0x9bf42d74, 0x9dbd2c12, 0x90b517cf, - 0xc7e2c7dc, 0x04b49bb6, 0x6a0f1679, 0x3443dc1e, 0xc90e9a95, 0xe2a77bbd, - 0x61bca83e, 0xd61267a9, 0x2b7bbe8d, 0x7955196f, 0x73fafdbd, 0x7975ca04, - 0xc9a9b0ce, 0xd7721b7d, 0x80ede5e7, 0xc400d9fe, 0xfaa94e8e, 0xc7951efe, - 0xbfd7c7e7, 0x46a79c68, 0xf089ce2b, 0x9dc506f8, 0x9f671ce3, 0xf587bb58, - 0xe9ef86be, 0xb46fbe45, 0x6938752f, 0xfda26ccd, 0xff42b91d, 0xda4b8773, - 0xf4914750, 0x16e1d2bf, 0x2dc760fa, 0xf0ea1f42, 0x51d03d08, 0x8ed1ed27, - 0x033fe906, 0x708cff51, 0xe2ec20a0, 0x4a6d7c14, 0x1cce1e9c, 0x9e494f43, - 0x24a99c3f, 0x991453d3, 0x3cb870ff, 0xa5fa6018, 0x939ca732, 0xc0d1ca8d, - 0x4b4e68fa, 0xb40ca12f, 0x674a41f9, 0x037bb1bb, 0x3ffbb61e, 0x43daedd4, - 0x4bcfc533, 0xf33aaf30, 0xdbf846ce, 0x692b2ce5, 0x1ec3cfac, 0xde63dfef, - 0x0555d3e9, 0x683fd1db, 0xfef95b73, 0x94dc5787, 0xff47bd01, 0xb78d234d, - 0xb05a28ae, 0x0ae994b9, 0xcc7622bb, 0xc86e6efc, 0x4fc6bb66, 0xb83553e6, - 0xe3a4d4ba, 0x02b67384, 0xc1aeb7fd, 0xdb261b3e, 0xfc795816, 0x57f7b94a, - 0xf7a627d8, 0x0aeb29da, 0xd98bd0bc, 0xf3cabef5, 0xa66eff02, 0x80f79e5e, - 0xdf649dc3, 0x822bcb47, 0x45c59bb0, 0x07cf36b3, 0xd9ba767f, 0xf5bb3fbc, - 0x51e7c87e, 0xc14e94d3, 0xb8099731, 0xf3fdc410, 0x452e953e, 0x716c30ec, - 0x7f993299, 0x2b22b538, 0x194eebc0, 0xb8da7df7, 0x7dc633ef, 0xd5fdc3bf, - 0xfdcbbedc, 0x1fb88768, 0x9e988aed, 0xd085a34d, 0x0da7f05f, 0xef44792f, - 0xa3a0f9a3, 0x3b0e5a66, 0xd33f025c, 0x81bf27f1, 0x5ca278e5, 0x036ee397, - 0x6b6e867f, 0x85d7d3e8, 0x858b4f84, 0x4bffb0bc, 0x9f609f58, 0xf5f175b1, - 0x9bb2ed24, 0xe7c29029, 0x20b6c3a0, 0x895344f4, 0x0ecb5f80, 0x692e08e7, - 0xcf8ab329, 0x017a644f, 0xabd29e09, 0xae5e7d56, 0x85fc216b, 0x8cfb2475, - 0x9980d504, 0x399fc4ed, 0xf2c99854, 0x167e188e, 0x49fd0fa3, 0xcff6fc13, - 0xd7db9a67, 0xfe7cfd14, 0x13854365, 0xa9b15eb0, 0x4eff33b0, 0xe1acfc7d, - 0x0699fe87, 0x943ce33f, 0x7dc7ca12, 0xce1d8f44, 0x2ee987bf, 0x1ead787b, - 0x8285c207, 0x5c2e14df, 0x42549c06, 0xd44dc8e7, 0xaf7dfc77, 0x47d027e9, - 0xfdd079e8, 0xd3af7fc7, 0x6739df4a, 0x50a4f8e2, 0xfd04e2be, 0x3df74181, - 0x409dc13f, 0x87395f9b, 0xdfa6cb71, 0x3327ab7b, 0xa783586e, 0xff37603b, - 0xed97dba2, 0xd027ff40, 0x2b11cb5b, 0x0f2b2ec1, 0x0af67ff4, 0x3bf4b78f, - 0xa8fb80dc, 0xbbe88667, 0xc7dec8f3, 0x7d236f61, 0xae87f166, 0xfe7bbffd, - 0x25679911, 0x35bd5b98, 0xcfbc4a54, 0xe37fe3d1, 0xb49f6135, 0x6fd015d0, - 0x39179c57, 0xfeea27ea, 0xa9f1543d, 0xf5bd0037, 0xc46bf81f, 0x0a0cfab5, - 0x65e96ec0, 0xe46647be, 0x6a86f57b, 0xc771e12a, 0x6ff04ad0, 0x86eac97b, - 0xcd5efa9d, 0x5f1f84a9, 0xfb14ccf3, 0x3bb1be6b, 0x3d57711f, 0x23cf6fba, - 0x23679859, 0xc99edbc8, 0xf57ac476, 0xdd163b69, 0x6bb7f72f, 0xf7206fcf, - 0x64ed1b3e, 0x03cccd3e, 0x99ef35fb, 0xd1f00c1d, 0xe3fafb5e, 0x1a87b895, - 0xe83db9ed, 0xa6dbb2bf, 0x2d670f42, 0xf8728c9e, 0xbbb359e1, 0xba0ceb17, - 0x2ea27879, 0x56a45a4f, 0x3bab2fee, 0x37d7711f, 0x80bfe1f1, 0xf75af5dc, - 0x3ce2cff3, 0x3884ad7b, 0xeb1f6171, 0xe85dd78d, 0x2dc7cf35, 0x9873ec8f, - 0x94972f60, 0x82cf95ee, 0xef3eaf7f, 0xf45bad92, 0x439de819, 0x11e78fd8, - 0x6525f2e2, 0x85ff527b, 0x5e25bdde, 0x97c5dfd6, 0x09bd8bea, 0x17f31bf6, - 0x526b6edf, 0x6024147c, 0xbf19f25c, 0x3b2019c9, 0x8366dfc7, 0x99e878bc, - 0xbe296791, 0x737ee2fe, 0x6a3ac2d8, 0x94e6d2b6, 0xf83fb8cc, 0x0ebcfef2, - 0x3ba9f3e7, 0x34c7910a, 0x84ac882f, 0x51b05c5f, 0x7bcf2e4a, 0xbe5f88db, - 0x2a971b83, 0x4f2ddf25, 0xc7ee854d, 0x38f57357, 0x16c07576, 0x1ddf280c, - 0x83a3fe8f, 0x8eccef9c, 0x67af77d3, 0x7e71297e, 0xad425b6f, 0x2db7de6e, - 0x738fc753, 0xe33f7f3c, 0xcfb19558, 0xe79287aa, 0x299152df, 0x8966d3f6, - 0xc60e2214, 0x88ac2ff8, 0x10a45ae1, 0x5d763578, 0xe013d23d, 0xe08acbc8, - 0xf2a0ef88, 0xa86e96a1, 0x4fae3b34, 0xa8204a5f, 0x0f7f8c95, 0x7b8c8bb9, - 0x55ef5e60, 0xdbe57ee8, 0x98d8f36f, 0x246a4b4f, 0xab53791d, 0x7c8e9223, - 0x46a8e468, 0xcbeb8d3b, 0x199ff18a, 0x4649afdf, 0xf6643fb8, 0x8fdbc6d8, - 0x6f3c438f, 0x2ab37e1d, 0xfdd0a93e, 0x4d2069a6, 0x646723f6, 0xe9b6ec11, - 0x3875e4b9, 0x1fc133a7, 0x65760647, 0x8fe2137b, 0xaa3b90cf, 0x137e287c, - 0x7ca3fafd, 0xa54f81d8, 0xf6ab0acd, 0x65b1af22, 0x3a294d0a, 0xe5b1b01d, - 0xa7b4befb, 0x5e2e7ec2, 0x1e3f156d, 0x73822251, 0x0aae27b9, 0x23988c3e, - 0xca8e7382, 0x18fc11ff, 0x09591099, 0xb4adcadc, 0xc9f196af, 0x1e2e9591, - 0xa0c2b2ff, 0x03e491a7, 0x57322785, 0xb5ea4f03, 0x3711b7d1, 0x09d99769, - 0x7be9893f, 0xa227a19d, 0x783b86c7, 0xb3410ffc, 0x4e61f10b, 0x0be462a5, - 0xb5f9f896, 0x908d3fb8, 0xf841c0eb, 0xdddd9367, 0xfdc1a32b, 0xbc1f20af, - 0xe5dddb33, 0x326f5eba, 0xcacae587, 0xee2d6afc, 0xfbdd3b29, 0xdfcc158f, - 0x07c91c5f, 0x4bb5b1ce, 0xdd7b6a1c, 0x47fb13ba, 0x807ba3cd, 0xde1c175f, - 0x9f582b27, 0xada196ad, 0x67d22ca5, 0xa429c8e6, 0x6f604bf8, 0xbdba2382, - 0xb2ef148d, 0x561e9f08, 0x9767eb2a, 0x4b940f71, 0xa1f603b4, 0xe6fcf7e8, - 0x00efabc0, 0x6686466f, 0xf58f4e09, 0x4f030ba7, 0x3e3703a6, 0x981ef8e0, - 0x60ffef13, 0xfa0b5ef5, 0xc3b8bf97, 0x9ef6e112, 0xbbe7c9cd, 0x0cf6ed7c, - 0x9e3d0bf8, 0xec7b0fd0, 0xeac7a649, 0x4e197605, 0xe88083f2, 0x29c79cfd, - 0x0e54b7f2, 0xdf0f41b5, 0xd698cbd2, 0x6313e812, 0xa9f331e8, 0xce1fcf41, - 0xb6f84879, 0x430f0b4e, 0xcc07236f, 0xe4ef7c04, 0x7f7426b8, 0x1aef105a, - 0xadc700f5, 0x216e3d2c, 0x0fa4b45e, 0x8cbdc4ad, 0x989d5bf4, 0xa7c8e9bf, - 0xdb3f38f9, 0xdbce3e63, 0x3670e472, 0xf78dcec1, 0x6cc7c704, 0x1ff4b78c, - 0x24bbc6c9, 0x86aadfd6, 0x4717210a, 0x47e012b8, 0x85afdfac, 0x8b7f210b, - 0xf1825432, 0xf996e428, 0x49a06b4c, 0xe8aad1ce, 0x34474f7e, 0xf7b1f9c1, - 0x6e8551f6, 0x250f8caf, 0x1d3707c8, 0xb11254bd, 0xd9a0f1c7, 0xe81395c0, - 0xdffdd62f, 0x09c0c8b9, 0xbf0cda5e, 0xbc27071f, 0xf5a3dc31, 0xae7dc816, - 0xb63b9742, 0x3bcaf85e, 0x6de32023, 0x992a5daf, 0xc6758c59, 0xa3c04a3c, - 0x017c7159, 0x0e0ae40e, 0xf367326c, 0x2bcf7cb9, 0xd25e4eee, 0x96b1b8dc, - 0xd33ad3a7, 0x6bd0b5fd, 0x5de40513, 0xb1ae5637, 0x8570f476, 0x553ebf7e, - 0xf6fb8f7f, 0x964ec128, 0x7d6322eb, 0x9bc17cee, 0x5d67f030, 0xf85ac6f5, - 0x7e597ddf, 0xf9bbe24b, 0xedaff887, 0xadd7a649, 0x339b58df, 0x1efb9f8e, - 0x126a7eda, 0xd9afcf5d, 0xdb36a3bb, 0x4c7f7d75, 0x98b68bee, 0x49e6959c, - 0xbe58fa89, 0xb71276b1, 0xaffe52eb, 0x7dcfd0fa, 0x8c3588f1, 0xb5facbb8, - 0xfdb7fce0, 0x0925bd71, 0x5f807fb7, 0x9d6b0533, 0xfe5bbe33, 0x12ab6db1, - 0x4f80561e, 0xe2bd5fec, 0x0937ec67, 0x18aa6dfb, 0x5a68a753, 0x37791d3d, - 0x4f4f5779, 0x6d8c53ac, 0xa8a72819, 0x49bd88b7, 0xd2b87ecb, 0x623e8e3d, - 0xd4ae6ff3, 0x864d9f64, 0x6fa94f1d, 0x1e15e679, 0x53ccb97f, 0x557ec956, - 0xbf92a9ae, 0xa6a7dd8f, 0x860fcf52, 0x80bf1db2, 0xcd07453d, 0xb949f84e, - 0x4f33eba6, 0xfc2efcbd, 0xe1db2f31, 0x357e64ea, 0xbcfa6955, 0xea273663, - 0x5f63d140, 0xffe07be5, 0xa5cbec5b, 0xd3b262ce, 0x953f1e64, 0x3df0573b, - 0xc6c7cfb6, 0x7aa5693e, 0x645ed3be, 0x533afefe, 0x3adbe3b1, 0xc51be493, - 0x12d9c169, 0xf890bf87, 0xe85c1d16, 0xf7c05cd4, 0xd6fe1da0, 0x677ff5fe, - 0x0c8f0e23, 0x0bba67fe, 0xd3ed75b8, 0xb6cfd874, 0x81d38f81, 0x6606270f, - 0x1d9ed039, 0x1fd03972, 0x16b8fbad, 0x368cbaf3, 0x8b30675e, 0xf636b19c, - 0x13d58e7e, 0xcdd1de12, 0x73af6bd0, 0x614b2fdb, 0x82dda9ef, 0xce8efc63, - 0xd788fc44, 0xe3395c19, 0xeb1265d5, 0xf5b3050c, 0xd45a033a, 0x7acc0a19, - 0xea34019d, 0x6751680c, 0x0cea3f40, 0x006751a0, 0x68033a8d, 0xa2d019d4, - 0x2bfe80ce, 0xbcb16ba8, 0x50de4e51, 0xecd1aadf, 0xf40fff82, 0xf5e4416a, - 0x74d31c0f, 0xc412877a, 0xfbc67f7d, 0xaf460e23, 0x28b075e8, 0xe77953c7, - 0xfbcb341f, 0x5eda1a20, 0xd6f71337, 0x5571b9af, 0xd9371117, 0xa3cddb14, - 0x6a1f5127, 0x1bdc53ef, 0x2e5fe85d, 0x5c1b6c72, 0xfa237ef8, 0xd56ecd7b, - 0x9abafb85, 0x6f97fa8d, 0x58ea57b0, 0x2cc739d5, 0x15fbcf72, 0xeffde1ca, - 0x64efeab0, 0x2cbdc6bf, 0x9545b0f7, 0x1d6fda3c, 0xcb4bf792, 0x4d738a8b, - 0x7eda1e42, 0x1382e7cb, 0x9df4b69d, 0xb21fd790, 0xc524d739, 0x7de48f57, - 0xc174fc7e, 0x45433c8d, 0xa7d5af4c, 0x7b5edf90, 0xf9213801, 0xb47e4248, - 0x33fcd9d6, 0x5da467e4, 0x7efce133, 0x644ee87e, 0x6d3dd6f9, 0xb09228fe, - 0x9930737f, 0x6df60df6, 0x99c823cd, 0x034a8fdc, 0x943fb2e2, 0x74aa1fdc, - 0xc6927d64, 0x3cd1e63f, 0xff755be4, 0x3f40e6b4, 0xdbb977ef, 0x61caf92a, - 0x2570f78f, 0xb349f1fb, 0x272fea47, 0xbde4d98f, 0x9cfb7e75, 0x8d4bfaa4, - 0x1fea5536, 0xc48acc1b, 0xdee52bf1, 0xaacbb063, 0xeea57bba, 0x10eb9552, - 0xe1d98e7f, 0x3786f2d1, 0x5cc377c0, 0x6abfd497, 0xe10bf4ac, 0xf72f7ec7, - 0x7f16683c, 0x8254e9ab, 0xc9abd32a, 0xad7f816d, 0x3d8a7562, 0x298fed99, - 0x78ab0fec, 0xbb04c6af, 0x915db0da, 0x100a42bc, 0x8695e7ac, 0xfe0d573e, - 0xfb0a57eb, 0x3d56bdcb, 0x5553ce0f, 0xc5d79fe1, 0xdfe78b71, 0xfc0b5e47, - 0x55c71d66, 0x5f671cb4, 0x37bf708f, 0x9ebe6a6d, 0xc072bbe7, 0x3319f57f, - 0x726a4f01, 0x95e85e7e, 0xfced5f78, 0x095bef84, 0x737da5df, 0xa8e1f7d3, - 0xc8493e89, 0x759a4f6b, 0xca7d61fc, 0xec14eb7b, 0x5e3eea55, 0x3474cf69, - 0x8ca2bb49, 0x340bffc4, 0xe02f6f3d, 0x4a6672bb, 0xeb0fa2dd, 0x6eedda6b, - 0x0b863fe8, 0xbefc8dbb, 0xe796e540, 0x5bd54eed, 0xdc29d30b, 0xca5b8d3f, - 0xe7617e14, 0x5c71d47c, 0x3d4f3fc2, 0x7d05c0bb, 0x4377697c, 0xc739351f, - 0x31dde1e6, 0x72ffe0cb, 0xdc55c359, 0x029d2797, 0x438f9fd8, 0x5adfacdd, - 0x5d41481c, 0x50d1e43d, 0x38a63f27, 0x1ebfaef1, 0x716fb74f, 0x140acfc2, - 0xb5b7ea27, 0xd935dda9, 0xe676bfcc, 0x9cf0370c, 0x61ea55f1, 0x76eadc23, - 0x53506b70, 0x6ca6b5f4, 0xff0df3d4, 0x54a6f729, 0xd7f78a4d, 0x1d147e1b, - 0xf11d22fc, 0x6dd447f5, 0x807f8377, 0x835eee6c, 0xfea0ec3f, 0xbf5269a6, - 0xe5d1d98d, 0x613b39fd, 0xf4ab5347, 0xef8d8d75, 0x0c4f9199, 0xc1cde6dd, - 0x7cd72bfe, 0xce5b25be, 0x8cbd7e39, 0xb8033771, 0x165eb63b, 0x463df1c3, - 0x6b781dfd, 0x26baea32, 0x326baea3, 0xa326baea, 0xea326bae, 0xaea326ba, - 0xbaea326b, 0x6baea326, 0x26baea32, 0x97ae13a9, 0x878eddf6, 0x08ea1da4, - 0xbc4278c8, 0xc7eab9b8, 0x55175dd5, 0xa577538d, 0xc4865714, 0xbd7bf65d, - 0xcea63dde, 0x26aefeca, 0xe0d57bf8, 0x431e7b84, 0x7163d25e, 0x6b5438b3, - 0x603c16f1, 0x54f07c17, 0x8d6f5b8d, 0xf52ecfe9, 0x9b64cbd9, 0x2ca87b8f, - 0x5152659a, 0x23ee34c7, 0xdf84ef56, 0x1bf09ce0, 0xd31bf0b4, 0xfcdfb8ec, - 0x5daec2d6, 0x0109e7aa, 0x726c13c9, 0x32375bbf, 0x2f7d30ae, 0xe5709339, - 0xc2b831b3, 0x90159a0f, 0x95a0ed63, 0x233f74ba, 0x37254ff8, 0x0e3f9c7f, - 0x9c7484ce, 0xda1a9699, 0xb5a67d87, 0x1791baa5, 0x9d8bbfb3, 0x88a6dc9d, - 0x06a1afbf, 0xbc1c77d9, 0x7c9e4749, 0x73d1c4ef, 0xf7f9e1bf, 0xf25d83fe, - 0xd793ad9d, 0xe0fffa2e, 0xae954d4d, 0x84775f8f, 0x9659e77d, 0x43b654ea, - 0x16d5578e, 0xb8ba922a, 0x50fe2a9a, 0x58ae3da3, 0xd377a380, 0xb577dc3c, - 0xc839e1b5, 0x2efec399, 0xa32cdfef, 0x6a1a6bbe, 0xd9f4cbde, 0xbe373cec, - 0x3dcd4dab, 0x800b0544, 0xb0c57547, 0xadd4b3ab, 0x1963dd60, 0xbf83bfde, - 0xa7cc5edc, 0x96fee356, 0xb3b69753, 0xce63ee4b, 0x32fbdc42, 0xf51fabab, - 0x9e6f2d86, 0xb2c27a90, 0xd442d70c, 0x79bcb61b, 0x5c73a75a, 0xe51b8afd, - 0xabab13b2, 0x66f8827f, 0x109f3eeb, 0x09a1fd67, 0xc0fb7449, 0x09f3eee4, - 0x3f05ae71, 0x3f4e9df8, 0xafb84c53, 0x5c944356, 0xf21dbbd5, 0x4bfeebf9, - 0xa8d3cf7f, 0xaaa7c9c4, 0x749c5c74, 0xe7b0c282, 0xf90ec5d1, 0x713397fe, - 0xdbd43cfd, 0x10b5d8a8, 0xfdaf38f3, 0xe2f8ec35, 0xc1a79ead, 0x7738cf27, - 0x3579f10e, 0x0d90c758, 0xbbe319ed, 0xdbd529e4, 0x3d36b688, 0x357e9260, - 0x6df68a58, 0xfa20f435, 0x81762fd9, 0xf393ed4f, 0x3a622c6e, 0xb79a1acf, - 0xe9788ede, 0x73fe8dd9, 0xec5e9e65, 0xdfeeb637, 0xe58f9c69, 0xc37987d9, - 0xf9e4aa85, 0x6dea37c3, 0x55c22ecc, 0x371d0e3a, 0x93aca8fc, 0x58e7fbe4, - 0xa55e39fb, 0xfdf9781a, 0x47bcb372, 0x7e4c4f20, 0x0a5d5eea, 0xa3de5879, - 0x61afbc86, 0x5299ec9c, 0x7b6ef98f, 0xc77ec80d, 0x7c653b0d, 0xe3af396c, - 0xa685b4a3, 0x0de404e0, 0x4e0d1e53, 0x7653bc80, 0xdc5cda8c, 0xb51810be, - 0xe1787f21, 0xe86d476f, 0x7543c17f, 0x56bfe1e3, 0xc2df09ad, 0x3f5951b2, - 0x921af79d, 0x04e8c277, 0x4d856fe4, 0x6c02596f, 0xe69e73b7, 0xb7f2937d, - 0xd3638922, 0xfe9a5b0d, 0x87b04aa8, 0xe490cfe9, 0x259d54ab, 0xdd14bee3, - 0x3e8f7dff, 0x6e8ec2a8, 0x09dcb208, 0x69e737f6, 0x1248e5d3, 0x6bacb0df, - 0xf3837031, 0x3f71a4b5, 0x3cbe4733, 0xe423c0c5, 0x378c8d8f, 0xbeb7a6fe, - 0x79c8be42, 0x8c7e18dc, 0x261c314d, 0xebef5dc4, 0x20fc1711, 0xbbdade79, - 0xf78ad91e, 0x76e3536d, 0xd78fbc8b, 0xdb456df4, 0x259efada, 0x4cbf2487, - 0x65f9cf9a, 0x9c9d7d12, 0x7b68e463, 0x39adf3f0, 0x76cbece3, 0x0ed12d70, - 0x37439a4e, 0xd27abde0, 0x480eea9f, 0x0fdd091c, 0x6ad9d97c, 0xecae2377, - 0xd8a555fa, 0xa9f5b7d7, 0xfaa98f32, 0xa751d947, 0x52540fcc, 0x87e6fc11, - 0xe1e011da, 0x0c3c24ec, 0x8972dd48, 0xddae7043, 0xadb60778, 0x123e4a71, - 0x5336ebf3, 0x98adc3e8, 0xef90e597, 0x45b70c11, 0x6f7c2ca6, 0x4aeee29a, - 0x2ece2bc8, 0x9d041599, 0x830a19dd, 0x15cfe8ef, 0xd5c8ea37, 0xd6ae3a69, - 0x7bad0da8, 0x352dfc79, 0x5bf1b82c, 0x6ff307e0, 0x7697acb7, 0xb14cd945, - 0x290a5cdb, 0x7067fffa, 0x3d7bc42d, 0x67ad3df6, 0x20efb05b, 0xf04afbde, - 0x8fa8b599, 0xe45d95fe, 0x80d50689, 0x33d3cf99, 0x7bb70481, 0xb8942cee, - 0xc686a513, 0x2cff91fb, 0x6a3a954f, 0x13d704cf, 0xd3da6ef8, 0xf5e4a37c, - 0xc7a4fe87, 0x29a5d1fb, 0x3d71e46e, 0x711b5cf3, 0x5d479eae, 0xa29afe32, - 0xa13c0bf3, 0xa967a7eb, 0xe69ece7e, 0xc59f794c, 0x8767a1ee, 0xbfbe3267, - 0xe5bc3259, 0x1803a8d5, 0x667b1fdf, 0x4fb73f70, 0xde770d29, 0x75733e07, - 0xb9945779, 0xde4edee4, 0x7b13e379, 0xf1867d74, 0x897dac1d, 0xfefde923, - 0xcb80febf, 0x002220b3, 0x00000000 -}; - -#endif /*__BNX2X_INIT_VALUES_H__*/ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ad5ef25add3e..fbf1352e9c1c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -53,12 +53,19 @@ #include "bnx2x.h" #include "bnx2x_init.h" +#include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.48.105" -#define DRV_MODULE_RELDATE "2009/03/02" +#define DRV_MODULE_VERSION "1.48.105-1" +#define DRV_MODULE_RELDATE "2009/04/22" #define BNX2X_BC_VER 0x040200 +#include +#include "bnx2x_fw_file_hdr.h" +/* FW files */ +#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) @@ -1539,7 +1546,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) len, cqe, comp_ring_cons); #ifdef BNX2X_STOP_ON_ERROR if (bp->panic) - return -EINVAL; + return 0; #endif bnx2x_update_sge_prod(fp, @@ -5232,13 +5239,15 @@ static void bnx2x_gunzip_end(struct bnx2x *bp) } } -static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len) +static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len) { int n, rc; /* check gzip header */ - if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) + if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) { + BNX2X_ERR("Bad gzip header\n"); return -EINVAL; + } n = 10; @@ -5247,7 +5256,7 @@ static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len) if (zbuf[3] & FNAME) while ((zbuf[n++] != 0) && (n < len)); - bp->strm->next_in = zbuf + n; + bp->strm->next_in = (typeof(bp->strm->next_in))zbuf + n; bp->strm->avail_in = len - n; bp->strm->next_out = bp->gunzip_buf; bp->strm->avail_out = FW_BUF_SIZE; @@ -5369,8 +5378,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03); msleep(50); - bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); - bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); DP(NETIF_MSG_HW, "part2\n"); @@ -5434,8 +5443,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03); msleep(50); - bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); - bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); #ifndef BCM_ISCSI /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); @@ -5510,7 +5519,7 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); - bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END); + bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE); if (CHIP_IS_E1H(bp)) REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp)); @@ -5518,14 +5527,14 @@ static int bnx2x_init_common(struct bnx2x *bp) msleep(30); REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0); - bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END); + bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE); if (CHIP_IS_E1(bp)) { /* enable HW interrupt from PXP on USDM overflow bit 16 on INT_MASK_0 */ REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0); } - bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END); + bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE); bnx2x_init_pxp(bp); #ifdef __BIG_ENDIAN @@ -5571,60 +5580,60 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0); REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0); - bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END); + bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE); /* clean the DMAE memory */ bp->dmae_ready = 1; bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8); - bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END); - bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END); - bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END); - bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END); + bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE); bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3); - bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END); + bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE); /* soft reset pulse */ REG_WR(bp, QM_REG_SOFT_RESET, 1); REG_WR(bp, QM_REG_SOFT_RESET, 0); #ifdef BCM_ISCSI - bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END); + bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE); #endif - bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END); + bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE); REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT); if (!CHIP_REV_IS_SLOW(bp)) { /* enable hw interrupt from doorbell Q */ REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0); } - bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); - bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); if (CHIP_IS_E1H(bp)) REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp)); - bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END); - bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END); - bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END); - bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END); + bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE); + 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_block(bp, TSEM_COMMON_START, TSEM_COMMON_END); - bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END); - bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END); - bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END); + bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE); /* sync semi rtc */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, @@ -5632,16 +5641,16 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x80000000); - bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END); - bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END); - bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END); + bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE); REG_WR(bp, SRC_REG_SOFT_RST, 1); for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) { REG_WR(bp, i, 0xc0cac01a); /* TODO: replace with something meaningful */ } - bnx2x_init_block(bp, SRCH_COMMON_START, SRCH_COMMON_END); + bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE); REG_WR(bp, SRC_REG_SOFT_RST, 0); if (sizeof(union cdu_context) != 1024) @@ -5649,7 +5658,7 @@ static int bnx2x_init_common(struct bnx2x *bp) printk(KERN_ALERT PFX "please adjust the size of" " cdu_context(%ld)\n", (long)sizeof(union cdu_context)); - bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END); + 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)) { @@ -5658,7 +5667,7 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, CDU_REG_CDU_DEBUG, 0); } - bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END); + bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE); REG_WR(bp, CFC_REG_INIT_REG, 0x7FF); /* enable context validation interrupt from CFC */ REG_WR(bp, CFC_REG_CFC_INT_MASK, 0); @@ -5666,20 +5675,25 @@ static int bnx2x_init_common(struct bnx2x *bp) /* set the thresholds to prevent CFC/CDU race */ REG_WR(bp, CFC_REG_DEBUG0, 0x20020000); - bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END); - bnx2x_init_block(bp, MISC_AEU_COMMON_START, MISC_AEU_COMMON_END); + 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_COMMON_START, NIG_COMMON_END); + bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE); if (CHIP_IS_E1H(bp)) { REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp)); REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp)); @@ -5763,6 +5777,7 @@ static int bnx2x_init_common(struct bnx2x *bp) static int bnx2x_init_port(struct bnx2x *bp) { int port = BP_PORT(bp); + int init_stage = port ? PORT1_STAGE : PORT0_STAGE; u32 low, high; u32 val; @@ -5771,7 +5786,9 @@ 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); #ifdef BCM_ISCSI /* Port0 1 * Port1 385 */ @@ -5798,21 +5815,19 @@ static int bnx2x_init_port(struct bnx2x *bp) REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i)); #endif /* Port CMs come here */ - bnx2x_init_block(bp, (port ? XCM_PORT1_START : XCM_PORT0_START), - (port ? XCM_PORT1_END : XCM_PORT0_END)); + 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, func ? TIMERS_PORT1_START : TIMERS_PORT0_START, - func ? TIMERS_PORT1_END : TIMERS_PORT0_END); + 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, (port ? BRB1_PORT1_START : BRB1_PORT0_START), - (port ? BRB1_PORT1_END : BRB1_PORT0_END)); + bnx2x_init_block(bp, BRB1_BLOCK, init_stage); if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) { /* no pause for emulation and FPGA */ low = 0; @@ -5837,25 +5852,27 @@ static int bnx2x_init_port(struct bnx2x *bp) /* 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, port ? TSEM_PORT1_START : TSEM_PORT0_START, - port ? TSEM_PORT1_END : TSEM_PORT0_END); - bnx2x_init_block(bp, port ? USEM_PORT1_START : USEM_PORT0_START, - port ? USEM_PORT1_END : USEM_PORT0_END); - bnx2x_init_block(bp, port ? CSEM_PORT1_START : CSEM_PORT0_START, - port ? CSEM_PORT1_END : CSEM_PORT0_END); - bnx2x_init_block(bp, port ? XSEM_PORT1_START : XSEM_PORT0_START, - port ? XSEM_PORT1_END : XSEM_PORT0_END); + bnx2x_init_block(bp, TSEM_BLOCK, init_stage); + bnx2x_init_block(bp, USEM_BLOCK, init_stage); + 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, port ? PBF_PORT1_START : PBF_PORT0_START, - port ? PBF_PORT1_END : PBF_PORT0_END); + bnx2x_init_block(bp, PBF_BLOCK, init_stage); /* configure PBF to work without PAUSE mtu 9000 */ REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0); @@ -5885,18 +5902,17 @@ static int bnx2x_init_port(struct bnx2x *bp) /* 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)) { REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); } - bnx2x_init_block(bp, port ? HC_PORT1_START : HC_PORT0_START, - port ? HC_PORT1_END : HC_PORT0_END); + bnx2x_init_block(bp, HC_BLOCK, init_stage); - bnx2x_init_block(bp, port ? MISC_AEU_PORT1_START : - MISC_AEU_PORT0_START, - port ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END); + bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage); /* init aeu_mask_attn_func_0/1: * - SF mode: bits 3-7 are masked. only bits 0-2 are in use * - MF mode: bit 3 is masked. bits 0-2 are in use as in SF @@ -5905,13 +5921,17 @@ static int bnx2x_init_port(struct bnx2x *bp) (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, port ? NIG_PORT1_START : NIG_PORT0_START, - port ? NIG_PORT1_END : NIG_PORT0_END); + bnx2x_init_block(bp, NIG_BLOCK, init_stage); REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1); @@ -5931,7 +5951,9 @@ 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)) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: @@ -6036,7 +6058,7 @@ static int bnx2x_init_func(struct bnx2x *bp) if (CHIP_IS_E1H(bp)) { for (i = 0; i < 9; i++) bnx2x_init_block(bp, - cm_start[func][i], cm_end[func][i]); + cm_blocks[i], 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); @@ -6049,7 +6071,7 @@ static int bnx2x_init_func(struct bnx2x *bp) REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); } - bnx2x_init_block(bp, hc_limits[func][0], hc_limits[func][1]); + bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func); /* Reset PCIE errors for debug */ REG_WR(bp, 0x2114, 0xffffffff); @@ -10595,7 +10617,6 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) mmiowb(); fp->tx_bd_prod += nbd; - dev->trans_start = jiffies; if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { /* We want bnx2x_tx_int to "see" the updated tx_bd_prod @@ -11082,6 +11103,190 @@ static int __devinit bnx2x_get_pcie_speed(struct bnx2x *bp) val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT; return val; } +static int __devinit bnx2x_check_firmware(struct bnx2x *bp) +{ + struct bnx2x_fw_file_hdr *fw_hdr; + struct bnx2x_fw_file_section *sections; + u16 *ops_offsets; + u32 offset, len, num_ops; + int i; + const struct firmware *firmware = bp->firmware; + const u8 * fw_ver; + + if (firmware->size < sizeof(struct bnx2x_fw_file_hdr)) + return -EINVAL; + + fw_hdr = (struct bnx2x_fw_file_hdr *)firmware->data; + sections = (struct bnx2x_fw_file_section *)fw_hdr; + + /* Make sure none of the offsets and sizes make us read beyond + * the end of the firmware data */ + for (i = 0; i < sizeof(*fw_hdr) / sizeof(*sections); i++) { + 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); + return -EINVAL; + } + } + + /* Likewise for the init_ops offsets */ + offset = be32_to_cpu(fw_hdr->init_ops_offsets.offset); + ops_offsets = (u16 *)(firmware->data + offset); + num_ops = be32_to_cpu(fw_hdr->init_ops.len) / sizeof(struct raw_op); + + 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); + return -EINVAL; + } + } + + /* Check FW version */ + offset = be32_to_cpu(fw_hdr->fw_version.offset); + fw_ver = firmware->data + offset; + if ((fw_ver[0] != BCM_5710_FW_MAJOR_VERSION) || + (fw_ver[1] != BCM_5710_FW_MINOR_VERSION) || + (fw_ver[2] != BCM_5710_FW_REVISION_VERSION) || + (fw_ver[3] != BCM_5710_FW_ENGINEERING_VERSION)) { + printk(KERN_ERR PFX "Bad FW version:%d.%d.%d.%d." + " Should be %d.%d.%d.%d\n", + fw_ver[0], fw_ver[1], fw_ver[2], + fw_ver[3], BCM_5710_FW_MAJOR_VERSION, + BCM_5710_FW_MINOR_VERSION, + BCM_5710_FW_REVISION_VERSION, + BCM_5710_FW_ENGINEERING_VERSION); + return -EINVAL; + } + + return 0; +} + +static void inline be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n) +{ + 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]); +} + +/* + 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) +{ + 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) { + 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) +{ + 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); \ + if (!bp->arr) { \ + 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); \ + } 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; + + /* Create a FW file name */ + if (CHIP_IS_E1(bp)) + 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); + + 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); + goto request_firmware_exit; + } + + rc = bnx2x_check_firmware(bp); + if (rc) { + printk(KERN_ERR PFX "Corrupt firmware file %s\n", fw_file_name); + goto request_firmware_exit; + } + + fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data; + + /* Initialize the pointers to the init arrays */ + /* Blob */ + BNX2X_ALLOC_AND_SET(init_data, request_firmware_exit, be32_to_cpu_n); + + /* Opcodes */ + 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); + + /* 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); + + return 0; +init_offsets_alloc_err: + kfree(bp->init_ops); +init_ops_alloc_err: + kfree(bp->init_data); +request_firmware_exit: + release_firmware(bp->firmware); + + return rc; +} + + static int __devinit bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -11116,6 +11321,13 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, if (rc) goto init_one_exit; + /* Set init arrays */ + rc = bnx2x_init_firmware(bp, &pdev->dev); + if (rc) { + printk(KERN_ERR PFX "Error loading firmware\n"); + goto init_one_exit; + } + rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -11163,6 +11375,11 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) unregister_netdev(dev); + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); + kfree(bp->init_data); + release_firmware(bp->firmware); + if (bp->regview) iounmap(bp->regview); @@ -11412,13 +11629,20 @@ static struct pci_driver bnx2x_pci_driver = { static int __init bnx2x_init(void) { + int ret; + bnx2x_wq = create_singlethread_workqueue("bnx2x"); if (bnx2x_wq == NULL) { printk(KERN_ERR PFX "Cannot create workqueue\n"); return -ENOMEM; } - return pci_register_driver(&bnx2x_pci_driver); + ret = pci_register_driver(&bnx2x_pci_driver); + if (ret) { + printk(KERN_ERR PFX "Cannot register driver\n"); + destroy_workqueue(bnx2x_wq); + } + return ret; } static void __exit bnx2x_cleanup(void) @@ -11431,3 +11655,4 @@ static void __exit bnx2x_cleanup(void) module_init(bnx2x_init); module_exit(bnx2x_cleanup); + diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index faf094abef7f..d4b570886c6e 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1850,9 +1850,10 @@ static u16 aggregator_identifier; * Can be called only after the mac address of the bond is set. */ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast) -{ +{ // check that the bond is not initialized yet - if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->dev->dev_addr))) { + if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), + bond->dev->dev_addr)) { aggregator_identifier = 0; diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index a306230381c8..2c46a154f2c6 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -26,10 +26,10 @@ #include #include #include +#include // General definitions -#define BOND_ETH_P_LACPDU 0x8809 -#define PKT_TYPE_LACPDU cpu_to_be16(BOND_ETH_P_LACPDU) +#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW) #define AD_TIMER_INTERVAL 100 /*msec*/ #define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02} diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 74824028f85c..d927f71af8a3 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -51,10 +51,10 @@ #include #include #include +#include #include -#include #include -#include +#include #include #include #include @@ -89,19 +89,19 @@ static int max_bonds = BOND_DEFAULT_MAX_BONDS; static int num_grat_arp = 1; static int num_unsol_na = 1; static int miimon = BOND_LINK_MON_INTERV; -static int updelay = 0; -static int downdelay = 0; +static int updelay; +static int downdelay; static int use_carrier = 1; -static char *mode = NULL; -static char *primary = NULL; -static char *lacp_rate = NULL; -static char *ad_select = NULL; -static char *xmit_hash_policy = NULL; +static char *mode; +static char *primary; +static char *lacp_rate; +static char *ad_select; +static char *xmit_hash_policy; static int arp_interval = BOND_LINK_ARP_INTERV; -static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; -static char *arp_validate = NULL; -static char *fail_over_mac = NULL; -struct bond_params bonding_defaults; +static char *arp_ip_target[BOND_MAX_ARP_TARGETS]; +static char *arp_validate; +static char *fail_over_mac; +static struct bond_params bonding_defaults; module_param(max_bonds, int, 0); MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); @@ -151,14 +151,14 @@ static const char * const version = LIST_HEAD(bond_dev_list); #ifdef CONFIG_PROC_FS -static struct proc_dir_entry *bond_proc_dir = NULL; +static struct proc_dir_entry *bond_proc_dir; #endif -static __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; -static int arp_ip_count = 0; +static __be32 arp_target[BOND_MAX_ARP_TARGETS]; +static int arp_ip_count; static int bond_mode = BOND_MODE_ROUNDROBIN; -static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2; -static int lacp_fast = 0; +static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2; +static int lacp_fast; const struct bond_parm_tbl bond_lacp_tbl[] = { @@ -210,6 +210,7 @@ struct bond_parm_tbl ad_select_tbl[] = { /*-------------------------- Forward declarations ---------------------------*/ static void bond_send_gratuitous_arp(struct bonding *bond); +static int bond_init(struct net_device *bond_dev); static void bond_deinit(struct net_device *bond_dev); /*---------------------------- General routines -----------------------------*/ @@ -221,7 +222,7 @@ static const char *bond_mode_name(int mode) [BOND_MODE_ACTIVEBACKUP] = "fault-tolerance (active-backup)", [BOND_MODE_XOR] = "load balancing (xor)", [BOND_MODE_BROADCAST] = "fault-tolerance (broadcast)", - [BOND_MODE_8023AD]= "IEEE 802.3ad Dynamic link aggregation", + [BOND_MODE_8023AD] = "IEEE 802.3ad Dynamic link aggregation", [BOND_MODE_TLB] = "transmit load balancing", [BOND_MODE_ALB] = "adaptive load balancing", }; @@ -246,12 +247,11 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id) struct vlan_entry *vlan; pr_debug("bond: %s, vlan id %d\n", - (bond ? bond->dev->name: "None"), vlan_id); + (bond ? bond->dev->name : "None"), vlan_id); vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL); - if (!vlan) { + if (!vlan) return -ENOMEM; - } INIT_LIST_HEAD(&vlan->vlan_list); vlan->vlan_id = vlan_id; @@ -351,16 +351,15 @@ static int bond_has_challenged_slaves(struct bonding *bond) * * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL, * or @curr->next otherwise (even if it is @curr itself again). - * + * * Caller must hold bond->lock */ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) { struct vlan_entry *next, *last; - if (list_empty(&bond->vlan_list)) { + if (list_empty(&bond->vlan_list)) return NULL; - } if (!curr) { next = list_entry(bond->vlan_list.next, @@ -382,11 +381,11 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) /** * bond_dev_queue_xmit - Prepare skb for xmit. - * + * * @bond: bond device that got this skb for tx. * @skb: hw accel VLAN tagged skb to transmit * @slave_dev: slave that is supposed to xmit this skbuff - * + * * When the bond gets an skb to transmit that is * already hardware accelerated VLAN tagged, and it * needs to relay this skb to a slave that is not @@ -394,7 +393,8 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) * i.e. strip the hwaccel tag and re-insert it as part * of the payload. */ -int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev) +int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, + struct net_device *slave_dev) { unsigned short uninitialized_var(vlan_id); @@ -428,7 +428,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_de * b. The operation is protected by the RTNL semaphore in the 8021q code, * c. Holding a lock with BH disabled while directly calling a base driver * entry point is generally a BAD idea. - * + * * The design of synchronization/protection for this operation in the 8021q * module is good for one or more VLAN devices over a single physical device * and cannot be extended for a teaming solution like bonding, so there is a @@ -443,7 +443,8 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_de * @bond_dev: bonding net device that got called * @grp: vlan group being registered */ -static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp) +static void bond_vlan_rx_register(struct net_device *bond_dev, + struct vlan_group *grp) { struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; @@ -485,7 +486,7 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) res = bond_add_vlan(bond, vid); if (res) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: Failed to add vlan id %d\n", bond_dev->name, vid); } @@ -520,7 +521,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) res = bond_del_vlan(bond, vid); if (res) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: Failed to remove vlan id %d\n", bond_dev->name, vid); } @@ -551,7 +552,8 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla write_unlock_bh(&bond->lock); } -static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev) +static void bond_del_vlans_from_slave(struct bonding *bond, + struct net_device *slave_dev) { const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct vlan_entry *vlan; @@ -673,7 +675,7 @@ static int bond_update_speed_duplex(struct slave *slave) * if supports MII link status reporting, check its link status. * * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(), - * depening upon the setting of the use_carrier parameter. + * depending upon the setting of the use_carrier parameter. * * Return either BMSR_LSTATUS, meaning that the link is up (or we * can't tell and just pretend it is), or 0, meaning that the link is @@ -685,16 +687,29 @@ static int bond_update_speed_duplex(struct slave *slave) * It'd be nice if there was a good way to tell if a driver supports * netif_carrier, but there really isn't. */ -static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting) +static int bond_check_dev_link(struct bonding *bond, + struct net_device *slave_dev, int reporting) { const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - static int (* ioctl)(struct net_device *, struct ifreq *, int); + static int (*ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; if (bond->params.use_carrier) return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; + /* Try to get link status using Ethtool first. */ + if (slave_dev->ethtool_ops) { + if (slave_dev->ethtool_ops->get_link) { + u32 link; + + link = slave_dev->ethtool_ops->get_link(slave_dev); + + return link ? BMSR_LSTATUS : 0; + } + } + + /* Ethtool can't be used, fallback to MII ioctls. */ ioctl = slave_ops->ndo_do_ioctl; if (ioctl) { /* TODO: set pointer to correct ioctl on a per team member */ @@ -714,23 +729,8 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de mii = if_mii(&ifr); if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) { mii->reg_num = MII_BMSR; - if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0) { - return (mii->val_out & BMSR_LSTATUS); - } - } - } - - /* - * Some drivers cache ETHTOOL_GLINK for a period of time so we only - * attempt to get link status from it if the above MII ioctls fail. - */ - if (slave_dev->ethtool_ops) { - if (slave_dev->ethtool_ops->get_link) { - u32 link; - - link = slave_dev->ethtool_ops->get_link(slave_dev); - - return link ? BMSR_LSTATUS : 0; + if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0) + return mii->val_out & BMSR_LSTATUS; } } @@ -740,7 +740,7 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de * cannot report link status). If not reporting, pretend * we're ok. */ - return (reporting ? -1 : BMSR_LSTATUS); + return reporting ? -1 : BMSR_LSTATUS; } /*----------------------------- Multicast list ------------------------------*/ @@ -748,7 +748,8 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de /* * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise */ -static inline int bond_is_dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2) +static inline int bond_is_dmi_same(const struct dev_mc_list *dmi1, + const struct dev_mc_list *dmi2) { return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 && dmi1->dmi_addrlen == dmi2->dmi_addrlen; @@ -757,14 +758,14 @@ static inline int bond_is_dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list /* * returns dmi entry if found, NULL otherwise */ -static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) +static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, + struct dev_mc_list *mc_list) { struct dev_mc_list *idmi; for (idmi = mc_list; idmi; idmi = idmi->next) { - if (bond_is_dmi_same(dmi, idmi)) { + if (bond_is_dmi_same(dmi, idmi)) return idmi; - } } return NULL; @@ -826,15 +827,14 @@ static void bond_mc_add(struct bonding *bond, void *addr, int alen) { if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ - if (bond->curr_active_slave) { + if (bond->curr_active_slave) dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0); - } } else { struct slave *slave; int i; - bond_for_each_slave(bond, slave, i) { + + bond_for_each_slave(bond, slave, i) dev_mc_add(slave->dev, addr, alen, 0); - } } } @@ -846,9 +846,9 @@ static void bond_mc_delete(struct bonding *bond, void *addr, int alen) { if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ - if (bond->curr_active_slave) { - dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0); - } + if (bond->curr_active_slave) + dev_mc_delete(bond->curr_active_slave->dev, addr, + alen, 0); } else { struct slave *slave; int i; @@ -872,9 +872,8 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) rcu_read_lock(); in_dev = __in_dev_get_rcu(bond->dev); if (in_dev) { - for (im = in_dev->mc_list; im; im = im->next) { + for (im = in_dev->mc_list; im; im = im->next) ip_mc_rejoin_group(im); - } } rcu_read_unlock(); @@ -893,7 +892,8 @@ static void bond_mc_list_destroy(struct bonding *bond) kfree(dmi); dmi = bond->mc_list; } - bond->mc_list = NULL; + + bond->mc_list = NULL; } /* @@ -926,14 +926,14 @@ static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, /* * flush all members of flush->mc_list from device dev->mc_list */ -static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev) +static void bond_mc_list_flush(struct net_device *bond_dev, + struct net_device *slave_dev) { struct bonding *bond = netdev_priv(bond_dev); struct dev_mc_list *dmi; - for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { + for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - } if (bond->params.mode == BOND_MODE_8023AD) { /* del lacpdu mc addr from mc list */ @@ -950,44 +950,40 @@ static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *s * old active slaves (if any) according to the multicast mode, and * promiscuous flags unconditionally. */ -static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active) +static void bond_mc_swap(struct bonding *bond, struct slave *new_active, + struct slave *old_active) { struct dev_mc_list *dmi; - if (!USES_PRIMARY(bond->params.mode)) { + if (!USES_PRIMARY(bond->params.mode)) /* nothing to do - mc list is already up-to-date on * all slaves */ return; - } if (old_active) { - if (bond->dev->flags & IFF_PROMISC) { + if (bond->dev->flags & IFF_PROMISC) dev_set_promiscuity(old_active->dev, -1); - } - if (bond->dev->flags & IFF_ALLMULTI) { + if (bond->dev->flags & IFF_ALLMULTI) dev_set_allmulti(old_active->dev, -1); - } - for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { - dev_mc_delete(old_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - } + for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) + dev_mc_delete(old_active->dev, dmi->dmi_addr, + dmi->dmi_addrlen, 0); } if (new_active) { /* FIXME: Signal errors upstream. */ - if (bond->dev->flags & IFF_PROMISC) { + if (bond->dev->flags & IFF_PROMISC) dev_set_promiscuity(new_active->dev, 1); - } - if (bond->dev->flags & IFF_ALLMULTI) { + if (bond->dev->flags & IFF_ALLMULTI) dev_set_allmulti(new_active->dev, 1); - } - for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { - dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - } + for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) + dev_mc_add(new_active->dev, dmi->dmi_addr, + dmi->dmi_addrlen, 0); bond_resend_igmp_join_requests(bond); } } @@ -1041,7 +1037,7 @@ static void bond_do_fail_over_mac(struct bonding *bond, rv = dev_set_mac_address(new_active->dev, &saddr); if (rv) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error %d setting MAC of slave %s\n", bond->dev->name, -rv, new_active->dev->name); goto out; @@ -1055,7 +1051,7 @@ static void bond_do_fail_over_mac(struct bonding *bond, rv = dev_set_mac_address(old_active->dev, &saddr); if (rv) - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error %d setting MAC of slave %s\n", bond->dev->name, -rv, new_active->dev->name); out: @@ -1063,7 +1059,7 @@ static void bond_do_fail_over_mac(struct bonding *bond, write_lock_bh(&bond->curr_slave_lock); break; default: - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: bond_do_fail_over_mac impossible: bad policy %d\n", bond->dev->name, bond->params.fail_over_mac); break; @@ -1088,17 +1084,17 @@ static struct slave *bond_find_best_slave(struct bonding *bond) new_active = old_active = bond->curr_active_slave; if (!new_active) { /* there were no active slaves left */ - if (bond->slave_cnt > 0) { /* found one slave */ + if (bond->slave_cnt > 0) /* found one slave */ new_active = bond->first_slave; - } else { + else return NULL; /* still no slave, return NULL */ - } } - /* first try the primary link; if arping, a link must tx/rx traffic - * before it can be considered the curr_active_slave - also, we would skip - * slaves between the curr_active_slave and primary_slave that may be up - * and able to arp + /* + * first try the primary link; if arping, a link must tx/rx + * traffic before it can be considered the curr_active_slave. + * also, we would skip slaves between the curr_active_slave + * and primary_slave that may be up and able to arp */ if ((bond->primary_slave) && (!bond->params.arp_interval) && @@ -1146,16 +1142,15 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) { struct slave *old_active = bond->curr_active_slave; - if (old_active == new_active) { + if (old_active == new_active) return; - } if (new_active) { new_active->jiffies = jiffies; if (new_active->link == BOND_LINK_BACK) { if (USES_PRIMARY(bond->params.mode)) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: making interface %s the new " "active one %d ms earlier.\n", bond->dev->name, new_active->dev->name, @@ -1165,15 +1160,14 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) new_active->delay = 0; new_active->link = BOND_LINK_UP; - if (bond->params.mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) bond_3ad_handle_link_change(new_active, BOND_LINK_UP); - } if (bond_is_lb(bond)) bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } else { if (USES_PRIMARY(bond->params.mode)) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: making interface %s the new " "active one.\n", bond->dev->name, new_active->dev->name); @@ -1181,9 +1175,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } } - if (USES_PRIMARY(bond->params.mode)) { + if (USES_PRIMARY(bond->params.mode)) bond_mc_swap(bond, new_active, old_active); - } if (bond_is_lb(bond)) { bond_alb_handle_active_change(bond, new_active); @@ -1196,9 +1189,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { - if (old_active) { + if (old_active) bond_set_slave_inactive_flags(old_active); - } if (new_active) { bond_set_slave_active_flags(new_active); @@ -1228,7 +1220,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) * bond_select_active_slave - select a new active slave, if needed * @bond: our bonding struct * - * This functions shoud be called when one of the following occurs: + * This functions should be called when one of the following occurs: * - The old curr_active_slave has been released or lost its link. * - The primary_slave has got its link back. * - A slave has got its link back and there's no old curr_active_slave. @@ -1248,11 +1240,11 @@ void bond_select_active_slave(struct bonding *bond) return; if (netif_carrier_ok(bond->dev)) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: first active interface up!\n", bond->dev->name); } else { - printk(KERN_INFO DRV_NAME ": %s: " + pr_info(DRV_NAME ": %s: " "now running without any active interface !\n", bond->dev->name); } @@ -1294,13 +1286,11 @@ static void bond_attach_slave(struct bonding *bond, struct slave *new_slave) */ static void bond_detach_slave(struct bonding *bond, struct slave *slave) { - if (slave->next) { + if (slave->next) slave->next->prev = slave->prev; - } - if (slave->prev) { + if (slave->prev) slave->prev->next = slave->next; - } if (bond->first_slave == slave) { /* slave is the first slave */ if (bond->slave_cnt > 1) { /* there are more slave */ @@ -1331,7 +1321,7 @@ static int bond_sethwaddr(struct net_device *bond_dev, (NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | \ NETIF_F_HW_VLAN_FILTER) -/* +/* * Compute the common dev->feature set available to all slaves. Some * feature bits are managed elsewhere, so preserve those feature bits * on the master device. @@ -1399,14 +1389,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL && slave_ops->ndo_do_ioctl == NULL) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: no link monitoring support for %s\n", bond_dev->name, slave_dev->name); } /* bond must be initialized by bond_open() before enslaving */ if (!(bond_dev->flags & IFF_UP)) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME " %s: master_dev is not up in bond_enslave\n", bond_dev->name); } @@ -1422,14 +1412,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); if (!list_empty(&bond->vlan_list)) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: cannot enslave VLAN " "challenged slave %s on VLAN enabled " "bond %s\n", bond_dev->name, slave_dev->name, bond_dev->name); return -EPERM; } else { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: enslaved VLAN challenged " "slave %s. Adding VLANs will be blocked as " "long as %s is part of bond %s\n", @@ -1449,12 +1439,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* * Old ifenslave binaries are no longer supported. These can - * be identified with moderate accurary by the state of the slave: + * be identified with moderate accuracy by the state of the slave: * the current ifenslave will set the interface down prior to * enslaving it; the old ifenslave will not. */ if ((slave_dev->flags & IFF_UP)) { - printk(KERN_ERR DRV_NAME ": %s is up. " + pr_err(DRV_NAME ": %s is up. " "This may be due to an out of date ifenslave.\n", slave_dev->name); res = -EPERM; @@ -1472,7 +1462,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); } else if (bond_dev->type != slave_dev->type) { - printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different " + pr_err(DRV_NAME ": %s ether type (%d) is different " "from other slaves (%d), can not enslave it.\n", slave_dev->name, slave_dev->type, bond_dev->type); @@ -1482,14 +1472,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_ops->ndo_set_mac_address == NULL) { if (bond->slave_cnt == 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: The first slave device " "specified does not support setting the MAC " "address. Setting fail_over_mac to active.", bond_dev->name); bond->params.fail_over_mac = BOND_FOM_ACTIVE; } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: The slave device specified " "does not support setting the MAC address, " "but fail_over_mac is not set to active.\n" @@ -1539,7 +1529,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* open the slave since the application closed it */ res = dev_open(slave_dev); if (res) { - pr_debug("Openning slave %s failed\n", slave_dev->name); + pr_debug("Opening slave %s failed\n", slave_dev->name); goto err_unset_master; } @@ -1551,9 +1541,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * it might fail and we do not want to have to undo everything */ res = bond_alb_init_slave(bond, new_slave); - if (res) { + if (res) goto err_close; - } } /* If the mode USES_PRIMARY, then the new slave gets the @@ -1578,9 +1567,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) netif_addr_lock_bh(bond_dev); /* upload master's mc_list to new slave */ - for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { - dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); - } + for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) + dev_mc_add(slave_dev, dmi->dmi_addr, + dmi->dmi_addrlen, 0); netif_addr_unlock_bh(bond_dev); } @@ -1621,7 +1610,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * supported); thus, we don't need to change * the messages for netif_carrier. */ - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: MII and ETHTOOL support not " "available for interface %s, and " "arp_interval/arp_ip_target module parameters " @@ -1630,7 +1619,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_dev->name, slave_dev->name); } else if (link_reporting == -1) { /* unable get link status using mii/ethtool */ - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: can't get link status from " "interface %s; the network driver associated " "with this interface does not support MII or " @@ -1662,13 +1651,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (bond_update_speed_duplex(new_slave) && (new_slave->link != BOND_LINK_DOWN)) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: failed to get speed and duplex from %s, " "assumed to be 100Mb/sec and Full.\n", bond_dev->name, new_slave->dev->name); if (bond->params.mode == BOND_MODE_8023AD) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL " "support in base driver for proper aggregator " "selection.\n", bond_dev->name); @@ -1677,9 +1666,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ - if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { + if (strcmp(bond->params.primary, new_slave->dev->name) == 0) bond->primary_slave = new_slave; - } } write_lock_bh(&bond->curr_slave_lock); @@ -1726,9 +1714,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * anyway (it holds no special properties of the bond device), * so we can change it without calling change_active_interface() */ - if (!bond->curr_active_slave) { + if (!bond->curr_active_slave) bond->curr_active_slave = new_slave; - } + break; } /* switch(bond_mode) */ @@ -1742,7 +1730,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (res) goto err_close; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: enslaving %s as a%s interface with a%s link.\n", bond_dev->name, slave_dev->name, new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup", @@ -1774,7 +1762,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) err_undo_flags: bond_dev->features = old_features; - + return res; } @@ -1799,7 +1787,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) /* slave is not a slave or master is not master of this slave */ if (!(slave_dev->flags & IFF_SLAVE) || (slave_dev->master != bond_dev)) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: cannot release %s.\n", bond_dev->name, slave_dev->name); return -EINVAL; @@ -1810,7 +1798,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) slave = bond_get_slave_by_dev(bond, slave_dev); if (!slave) { /* not a slave of this bond */ - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: %s not enslaved\n", bond_dev->name, slave_dev->name); write_unlock_bh(&bond->lock); @@ -1821,7 +1809,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) mac_addr_differ = memcmp(bond_dev->dev_addr, slave->perm_hwaddr, ETH_ALEN); if (!mac_addr_differ && (bond->slave_cnt > 1)) - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: the permanent HWaddr of %s - " "%pM - is still in use by %s. " "Set the HWaddr of %s to a different address " @@ -1839,7 +1827,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) bond_3ad_unbind_slave(slave); } - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: releasing %s interface %s\n", bond_dev->name, (slave->state == BOND_STATE_ACTIVE) @@ -1855,13 +1843,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) bond_compute_features(bond); - if (bond->primary_slave == slave) { + if (bond->primary_slave == slave) bond->primary_slave = NULL; - } - if (oldcurrent == slave) { + if (oldcurrent == slave) bond_change_active_slave(bond, NULL); - } if (bond_is_lb(bond)) { /* Must be called only after the slave has been @@ -1903,18 +1889,18 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) if (list_empty(&bond->vlan_list)) { bond_dev->features |= NETIF_F_VLAN_CHALLENGED; } else { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: Warning: clearing HW address of %s while it " "still has VLANs.\n", bond_dev->name, bond_dev->name); - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: When re-adding slaves, make sure the bond's " "HW address matches its VLANs'.\n", bond_dev->name); } } else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) && !bond_has_challenged_slaves(bond)) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: last VLAN challenged slave %s " "left bond %s. VLAN blocking is removed\n", bond_dev->name, slave_dev->name, bond_dev->name); @@ -1934,14 +1920,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) */ if (!USES_PRIMARY(bond->params.mode)) { /* unset promiscuity level from slave */ - if (bond_dev->flags & IFF_PROMISC) { + if (bond_dev->flags & IFF_PROMISC) dev_set_promiscuity(slave_dev, -1); - } /* unset allmulti level from slave */ - if (bond_dev->flags & IFF_ALLMULTI) { + if (bond_dev->flags & IFF_ALLMULTI) dev_set_allmulti(slave_dev, -1); - } /* flush master's mc_list from slave */ netif_addr_lock_bh(bond_dev); @@ -1974,41 +1958,36 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) * Destroy a bonding device. * Must be under rtnl_lock when this function is called. */ -void bond_destroy(struct bonding *bond) -{ - bond_deinit(bond->dev); - bond_destroy_sysfs_entry(bond); - unregister_netdevice(bond->dev); -} - -static void bond_destructor(struct net_device *bond_dev) +static void bond_uninit(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); + bond_deinit(bond_dev); + bond_destroy_sysfs_entry(bond); + if (bond->wq) destroy_workqueue(bond->wq); netif_addr_lock_bh(bond_dev); bond_mc_list_destroy(bond); netif_addr_unlock_bh(bond_dev); - - free_netdev(bond_dev); } /* -* First release a slave and than destroy the bond if no more slaves iare left. +* First release a slave and than destroy the bond if no more slaves are left. * Must be under rtnl_lock when this function is called. */ -int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev) +int bond_release_and_destroy(struct net_device *bond_dev, + struct net_device *slave_dev) { struct bonding *bond = netdev_priv(bond_dev); int ret; ret = bond_release(bond_dev, slave_dev); if ((ret == 0) && (bond->slave_cnt == 0)) { - printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n", + pr_info(DRV_NAME ": %s: destroying bond %s.\n", bond_dev->name, bond_dev->name); - bond_destroy(bond); + unregister_netdevice(bond_dev); } return ret; } @@ -2027,9 +2006,8 @@ static int bond_release_all(struct net_device *bond_dev) netif_carrier_off(bond_dev); - if (bond->slave_cnt == 0) { + if (bond->slave_cnt == 0) goto out; - } bond->current_arp_slave = NULL; bond->primary_slave = NULL; @@ -2039,9 +2017,8 @@ static int bond_release_all(struct net_device *bond_dev) /* Inform AD package of unbinding of slave * before slave is detached from the list. */ - if (bond->params.mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) bond_3ad_unbind_slave(slave); - } slave_dev = slave->dev; bond_detach_slave(bond, slave); @@ -2070,14 +2047,12 @@ static int bond_release_all(struct net_device *bond_dev) */ if (!USES_PRIMARY(bond->params.mode)) { /* unset promiscuity level from slave */ - if (bond_dev->flags & IFF_PROMISC) { + if (bond_dev->flags & IFF_PROMISC) dev_set_promiscuity(slave_dev, -1); - } /* unset allmulti level from slave */ - if (bond_dev->flags & IFF_ALLMULTI) { + if (bond_dev->flags & IFF_ALLMULTI) dev_set_allmulti(slave_dev, -1); - } /* flush master's mc_list from slave */ netif_addr_lock_bh(bond_dev); @@ -2112,20 +2087,20 @@ static int bond_release_all(struct net_device *bond_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (list_empty(&bond->vlan_list)) { + if (list_empty(&bond->vlan_list)) bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - } else { - printk(KERN_WARNING DRV_NAME + else { + pr_warning(DRV_NAME ": %s: Warning: clearing HW address of %s while it " "still has VLANs.\n", bond_dev->name, bond_dev->name); - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: When re-adding slaves, make sure the bond's " "HW address matches its VLANs'.\n", bond_dev->name); } - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: released all slaves\n", bond_dev->name); @@ -2143,8 +2118,8 @@ static int bond_release_all(struct net_device *bond_dev) * - is already active. * - The link state of is not BOND_LINK_UP. * - is not running. - * In these cases, this fuction does nothing. - * In the other cases, currnt_slave pointer is changed and 0 is returned. + * In these cases, this function does nothing. + * In the other cases, current_slave pointer is changed and 0 is returned. */ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_device *slave_dev) { @@ -2153,15 +2128,12 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi struct slave *new_active = NULL; int res = 0; - if (!USES_PRIMARY(bond->params.mode)) { + if (!USES_PRIMARY(bond->params.mode)) return -EINVAL; - } /* Verify that master_dev is indeed the master of slave_dev */ - if (!(slave_dev->flags & IFF_SLAVE) || - (slave_dev->master != bond_dev)) { + if (!(slave_dev->flags & IFF_SLAVE) || (slave_dev->master != bond_dev)) return -EINVAL; - } read_lock(&bond->lock); @@ -2186,9 +2158,8 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, new_active); write_unlock_bh(&bond->curr_slave_lock); - } else { + } else res = -EINVAL; - } read_unlock(&bond->lock); @@ -2240,6 +2211,9 @@ static int bond_miimon_inspect(struct bonding *bond) { struct slave *slave; int i, link_state, commit = 0; + bool ignore_updelay; + + ignore_updelay = !bond->curr_active_slave ? true : false; bond_for_each_slave(bond, slave, i) { slave->new_link = BOND_LINK_NOCHANGE; @@ -2254,7 +2228,7 @@ static int bond_miimon_inspect(struct bonding *bond) slave->link = BOND_LINK_FAIL; slave->delay = bond->params.downdelay; if (slave->delay) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status down for %s" "interface %s, disabling it in %d ms.\n", bond->dev->name, @@ -2273,7 +2247,7 @@ static int bond_miimon_inspect(struct bonding *bond) */ slave->link = BOND_LINK_UP; slave->jiffies = jiffies; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status up again after %d " "ms for interface %s.\n", bond->dev->name, @@ -2300,10 +2274,11 @@ static int bond_miimon_inspect(struct bonding *bond) slave->delay = bond->params.updelay; if (slave->delay) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status up for " "interface %s, enabling it in %d ms.\n", bond->dev->name, slave->dev->name, + ignore_updelay ? 0 : bond->params.updelay * bond->params.miimon); } @@ -2311,7 +2286,7 @@ static int bond_miimon_inspect(struct bonding *bond) case BOND_LINK_BACK: if (!link_state) { slave->link = BOND_LINK_DOWN; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status down again after %d " "ms for interface %s.\n", bond->dev->name, @@ -2322,9 +2297,13 @@ static int bond_miimon_inspect(struct bonding *bond) continue; } + if (ignore_updelay) + slave->delay = 0; + if (slave->delay <= 0) { slave->new_link = BOND_LINK_UP; commit++; + ignore_updelay = false; continue; } @@ -2361,7 +2340,7 @@ static void bond_miimon_commit(struct bonding *bond) slave->state = BOND_STATE_BACKUP; } - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status definitely " "up for interface %s.\n", bond->dev->name, slave->dev->name); @@ -2390,7 +2369,7 @@ static void bond_miimon_commit(struct bonding *bond) bond->params.mode == BOND_MODE_8023AD) bond_set_slave_inactive_flags(slave); - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status definitely down for " "interface %s, disabling it\n", bond->dev->name, slave->dev->name); @@ -2399,8 +2378,7 @@ static void bond_miimon_commit(struct bonding *bond) bond_3ad_handle_link_change(slave, BOND_LINK_DOWN); - if (bond->params.mode == BOND_MODE_TLB || - bond->params.mode == BOND_MODE_ALB) + if (bond_is_lb(bond)) bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN); @@ -2410,7 +2388,7 @@ static void bond_miimon_commit(struct bonding *bond) continue; default: - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: invalid new link %d on slave %s\n", bond->dev->name, slave->new_link, slave->dev->name); @@ -2531,18 +2509,18 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_ pr_debug("arp %d on slave %s: dst %x src %x vid %d\n", arp_op, slave_dev->name, dest_ip, src_ip, vlan_id); - + skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip, NULL, slave_dev->dev_addr, NULL); if (!skb) { - printk(KERN_ERR DRV_NAME ": ARP packet allocation failed\n"); + pr_err(DRV_NAME ": ARP 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; } } @@ -2582,7 +2560,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) rv = ip_route_output_key(&init_net, &rt, &fl); if (rv) { if (net_ratelimit()) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: no route to arp_ip_target %pI4\n", bond->dev->name, &fl.fl4_dst); } @@ -2619,7 +2597,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) } if (net_ratelimit()) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": %s: no path to arp_ip_target %pI4 via rt.dev %s\n", bond->dev->name, &fl.fl4_dst, rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); @@ -2767,13 +2745,11 @@ void bond_loadbalance_arp_mon(struct work_struct *work) delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); - if (bond->kill_timers) { + if (bond->kill_timers) goto out; - } - if (bond->slave_cnt == 0) { + if (bond->slave_cnt == 0) goto re_arm; - } read_lock(&bond->curr_slave_lock); oldcurrent = bond->curr_active_slave; @@ -2789,7 +2765,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work) */ bond_for_each_slave(bond, slave, i) { if (slave->link != BOND_LINK_UP) { - if (time_before_eq(jiffies, slave->dev->trans_start + delta_in_ticks) && + if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) && time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) { slave->link = BOND_LINK_UP; @@ -2801,14 +2777,14 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * is closed. */ if (!oldcurrent) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status definitely " "up for interface %s, ", bond->dev->name, slave->dev->name); do_failover = 1; } else { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: interface %s is now up\n", bond->dev->name, slave->dev->name); @@ -2821,24 +2797,22 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * when the source ip is 0, so don't take the link down * if we don't know our ip yet */ - if (time_after_eq(jiffies, slave->dev->trans_start + 2*delta_in_ticks) || + if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) || (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) { slave->link = BOND_LINK_DOWN; slave->state = BOND_STATE_BACKUP; - if (slave->link_failure_count < UINT_MAX) { + if (slave->link_failure_count < UINT_MAX) slave->link_failure_count++; - } - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: interface %s is now down.\n", bond->dev->name, slave->dev->name); - if (slave == oldcurrent) { + if (slave == oldcurrent) do_failover = 1; - } } } @@ -2849,9 +2823,8 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * do - all replies will be rx'ed on same link causing slaves * to be unstable during low/no traffic periods */ - if (IS_UP(slave->dev)) { + if (IS_UP(slave->dev)) bond_arp_send_all(bond, slave); - } } if (do_failover) { @@ -2932,7 +2905,7 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) * the bond has an IP address) */ if ((slave->state == BOND_STATE_ACTIVE) && - (time_after_eq(jiffies, slave->dev->trans_start + + (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2 * delta_in_ticks) || (time_after_eq(jiffies, slave_last_rx(bond, slave) + 2 * delta_in_ticks)))) { @@ -2976,13 +2949,13 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) write_lock_bh(&bond->curr_slave_lock); if (!bond->curr_active_slave && - time_before_eq(jiffies, slave->dev->trans_start + + time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks)) { slave->link = BOND_LINK_UP; bond_change_active_slave(bond, slave); bond->current_arp_slave = NULL; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: %s is up and now the " "active interface\n", bond->dev->name, slave->dev->name); @@ -2998,7 +2971,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) bond_set_slave_inactive_flags(slave); bond->current_arp_slave = NULL; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: backup interface %s is now up\n", bond->dev->name, slave->dev->name); } @@ -3014,7 +2987,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) slave->link = BOND_LINK_DOWN; if (slave == bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: link status down for active " "interface %s, disabling it\n", bond->dev->name, slave->dev->name); @@ -3033,7 +3006,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) bond->current_arp_slave = NULL; } else if (slave->state == BOND_STATE_BACKUP) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: backup interface %s is now down\n", bond->dev->name, slave->dev->name); @@ -3042,7 +3015,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) break; default: - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: impossible: new_link %d on slave %s\n", bond->dev->name, slave->new_link, slave->dev->name); @@ -3076,7 +3049,7 @@ static void bond_ab_arp_probe(struct bonding *bond) read_lock(&bond->curr_slave_lock); if (bond->current_arp_slave && bond->curr_active_slave) - printk("PROBE: c_arp %s && cas %s BAD\n", + pr_info(DRV_NAME "PROBE: c_arp %s && cas %s BAD\n", bond->current_arp_slave->dev->name, bond->curr_active_slave->dev->name); @@ -3126,7 +3099,7 @@ static void bond_ab_arp_probe(struct bonding *bond) bond_set_slave_inactive_flags(slave); - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: backup interface %s is now down.\n", bond->dev->name, slave->dev->name); } @@ -3176,9 +3149,8 @@ void bond_activebackup_arp_mon(struct work_struct *work) bond_ab_arp_probe(bond); re_arm: - if (bond->params.arp_interval) { + if (bond->params.arp_interval) queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); - } out: read_unlock(&bond->lock); } @@ -3200,14 +3172,12 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) read_lock(&dev_base_lock); read_lock(&bond->lock); - if (*pos == 0) { + if (*pos == 0) return SEQ_START_TOKEN; - } bond_for_each_slave(bond, slave, i) { - if (++off == *pos) { + if (++off == *pos) return slave; - } } return NULL; @@ -3219,9 +3189,8 @@ static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos) struct slave *slave = v; ++*pos; - if (v == SEQ_START_TOKEN) { + if (v == SEQ_START_TOKEN) return bond->first_slave; - } slave = slave->next; @@ -3284,14 +3253,14 @@ static void bond_info_show_master(struct seq_file *seq) /* ARP information */ - if(bond->params.arp_interval > 0) { - int printed=0; + if (bond->params.arp_interval > 0) { + int printed = 0; seq_printf(seq, "ARP Polling Interval (ms): %d\n", bond->params.arp_interval); seq_printf(seq, "ARP IP target/s (n.n.n.n form):"); - for(i = 0; (i < BOND_MAX_ARP_TARGETS) ;i++) { + for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { if (!bond->params.arp_targets[i]) break; if (printed) @@ -3331,7 +3300,8 @@ static void bond_info_show_master(struct seq_file *seq) } } -static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave) +static void bond_info_show_slave(struct seq_file *seq, + const struct slave *slave) { struct bonding *bond = seq->private; @@ -3347,12 +3317,11 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave const struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; - if (agg) { + if (agg) seq_printf(seq, "Aggregator ID: %d\n", agg->aggregator_identifier); - } else { + else seq_puts(seq, "Aggregator ID: N/A\n"); - } } } @@ -3361,9 +3330,8 @@ static int bond_info_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) { seq_printf(seq, "%s\n", version); bond_info_show_master(seq); - } else { + } else bond_info_show_slave(seq, v); - } return 0; } @@ -3408,13 +3376,12 @@ static int bond_create_proc_entry(struct bonding *bond) bond->proc_entry = proc_create_data(bond_dev->name, S_IRUGO, bond_proc_dir, &bond_info_fops, bond); - if (bond->proc_entry == NULL) { - printk(KERN_WARNING DRV_NAME + if (bond->proc_entry == NULL) + pr_warning(DRV_NAME ": Warning: Cannot create /proc/net/%s/%s\n", DRV_NAME, bond_dev->name); - } else { + else memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ); - } } return 0; @@ -3437,7 +3404,7 @@ static void bond_create_proc_dir(void) if (!bond_proc_dir) { bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net); if (!bond_proc_dir) - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: cannot create /proc/net/%s\n", DRV_NAME); } @@ -3453,8 +3420,28 @@ static void bond_destroy_proc_dir(void) bond_proc_dir = NULL; } } + +#else /* !CONFIG_PROC_FS */ + +static int bond_create_proc_entry(struct bonding *bond) +{ +} + +static void bond_remove_proc_entry(struct bonding *bond) +{ +} + +static void bond_create_proc_dir(void) +{ +} + +static void bond_destroy_proc_dir(void) +{ +} + #endif /* CONFIG_PROC_FS */ + /*-------------------------- netdev event handling --------------------------*/ /* @@ -3462,18 +3449,17 @@ static void bond_destroy_proc_dir(void) */ static int bond_event_changename(struct bonding *bond) { -#ifdef CONFIG_PROC_FS bond_remove_proc_entry(bond); bond_create_proc_entry(bond); -#endif - down_write(&(bonding_rwsem)); - bond_destroy_sysfs_entry(bond); - bond_create_sysfs_entry(bond); - up_write(&(bonding_rwsem)); + + bond_destroy_sysfs_entry(bond); + bond_create_sysfs_entry(bond); + return NOTIFY_DONE; } -static int bond_master_netdev_event(unsigned long event, struct net_device *bond_dev) +static int bond_master_netdev_event(unsigned long event, + struct net_device *bond_dev) { struct bonding *event_bond = netdev_priv(bond_dev); @@ -3490,7 +3476,8 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond return NOTIFY_DONE; } -static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev) +static int bond_slave_netdev_event(unsigned long event, + struct net_device *slave_dev) { struct net_device *bond_dev = slave_dev->master; struct bonding *bond = netdev_priv(bond_dev); @@ -3568,7 +3555,8 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave * locks for us to safely manipulate the slave devices (RTNL lock, * dev_probe_lock). */ -static int bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) +static int bond_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) { struct net_device *event_dev = (struct net_device *)ptr; @@ -3923,9 +3911,9 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd switch (cmd) { case SIOCGMIIPHY: mii = if_mii(ifr); - if (!mii) { + if (!mii) return -EINVAL; - } + mii->phy_id = 0; /* Fall Through */ case SIOCGMIIREG: @@ -3934,18 +3922,18 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd * instead of SIOCGMIIPHY. */ mii = if_mii(ifr); - if (!mii) { + if (!mii) return -EINVAL; - } + if (mii->reg_num == 1) { struct bonding *bond = netdev_priv(bond_dev); mii->val_out = 0; read_lock(&bond->lock); read_lock(&bond->curr_slave_lock); - if (netif_carrier_ok(bond->dev)) { + if (netif_carrier_ok(bond->dev)) mii->val_out = BMSR_LSTATUS; - } + read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); } @@ -3955,32 +3943,26 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd case SIOCBONDINFOQUERY: u_binfo = (struct ifbond __user *)ifr->ifr_data; - if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) { + if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) return -EFAULT; - } res = bond_info_query(bond_dev, &k_binfo); - if (res == 0) { - if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) { - return -EFAULT; - } - } + if (res == 0 && + copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) + return -EFAULT; return res; case BOND_SLAVE_INFO_QUERY_OLD: case SIOCBONDSLAVEINFOQUERY: u_sinfo = (struct ifslave __user *)ifr->ifr_data; - if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) { + if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) return -EFAULT; - } res = bond_slave_info_query(bond_dev, &k_sinfo); - if (res == 0) { - if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) { - return -EFAULT; - } - } + if (res == 0 && + copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) + return -EFAULT; return res; default: @@ -3988,18 +3970,16 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd break; } - if (!capable(CAP_NET_ADMIN)) { + if (!capable(CAP_NET_ADMIN)) return -EPERM; - } - down_write(&(bonding_rwsem)); slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave); pr_debug("slave_dev=%p: \n", slave_dev); - if (!slave_dev) { + if (!slave_dev) res = -ENODEV; - } else { + else { pr_debug("slave_dev->name=%s: \n", slave_dev->name); switch (cmd) { case BOND_ENSLAVE_OLD: @@ -4025,7 +4005,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd dev_put(slave_dev); } - up_write(&(bonding_rwsem)); return res; } @@ -4037,30 +4016,30 @@ static void bond_set_multicast_list(struct net_device *bond_dev) /* * Do promisc before checking multicast_mode */ - if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC)) { + if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC)) /* * FIXME: Need to handle the error when one of the multi-slaves * encounters error. */ bond_set_promiscuity(bond, 1); - } - if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC)) { + + if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC)) bond_set_promiscuity(bond, -1); - } + /* set allmulti flag to slaves */ - if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI)) { + if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI)) /* * FIXME: Need to handle the error when one of the multi-slaves * encounters error. */ bond_set_allmulti(bond, 1); - } - if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI)) { + + if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI)) bond_set_allmulti(bond, -1); - } + read_lock(&bond->lock); @@ -4068,16 +4047,14 @@ static void bond_set_multicast_list(struct net_device *bond_dev) /* looking for addresses to add to slaves' mc list */ for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { - if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) { + if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); - } } /* looking for addresses to delete from slaves' list */ for (dmi = bond->mc_list; dmi; dmi = dmi->next) { - if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) { + if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); - } } /* save master's multicast list */ @@ -4197,9 +4174,8 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) if (bond->params.fail_over_mac == BOND_FOM_ACTIVE) return 0; - if (!is_valid_ether_addr(sa->sa_data)) { + if (!is_valid_ether_addr(sa->sa_data)) return -EADDRNOTAVAIL; - } /* Can't hold bond->lock with bh disabled here since * some base drivers panic. On the other hand we can't @@ -4270,9 +4246,8 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev read_lock(&bond->lock); - if (!BOND_IS_OK(bond)) { + if (!BOND_IS_OK(bond)) goto out; - } /* * Concurrent TX may collide on rr_tx_counter; we accept that @@ -4282,9 +4257,8 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev bond_for_each_slave(bond, slave, i) { slave_no--; - if (slave_no < 0) { + if (slave_no < 0) break; - } } start_at = slave; @@ -4319,9 +4293,8 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d read_lock(&bond->lock); read_lock(&bond->curr_slave_lock); - if (!BOND_IS_OK(bond)) { + if (!BOND_IS_OK(bond)) goto out; - } if (!bond->curr_active_slave) goto out; @@ -4329,10 +4302,10 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); out: - if (res) { + if (res) /* no suitable interface, frame not sent */ dev_kfree_skb(skb); - } + read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); return 0; @@ -4353,17 +4326,15 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) read_lock(&bond->lock); - if (!BOND_IS_OK(bond)) { + if (!BOND_IS_OK(bond)) goto out; - } slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt); bond_for_each_slave(bond, slave, i) { slave_no--; - if (slave_no < 0) { + if (slave_no < 0) break; - } } start_at = slave; @@ -4399,17 +4370,15 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) read_lock(&bond->lock); - if (!BOND_IS_OK(bond)) { + if (!BOND_IS_OK(bond)) goto out; - } read_lock(&bond->curr_slave_lock); start_at = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); - if (!start_at) { + if (!start_at) goto out; - } bond_for_each_slave_from(bond, slave, i, start_at) { if (IS_UP(slave->dev) && @@ -4418,7 +4387,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) if (tx_dev) { struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); if (!skb2) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: bond_xmit_broadcast(): " "skb_clone() failed\n", bond_dev->name); @@ -4435,15 +4404,14 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) } } - if (tx_dev) { + if (tx_dev) res = bond_dev_queue_xmit(bond, skb, tx_dev); - } out: - if (res) { + if (res) /* no suitable interface, frame not sent */ dev_kfree_skb(skb); - } + /* frame sent to all suitable interfaces */ read_unlock(&bond->lock); return 0; @@ -4487,7 +4455,7 @@ static int bond_start_xmit(struct sk_buff *skb, struct net_device *dev) return bond_alb_xmit(skb, dev); default: /* Should never happen, mode already checked */ - printk(KERN_ERR DRV_NAME ": %s: Error: Unknown bonding mode %d\n", + pr_err(DRV_NAME ": %s: Error: Unknown bonding mode %d\n", dev->name, bond->params.mode); WARN_ON_ONCE(1); dev_kfree_skb(skb); @@ -4524,7 +4492,7 @@ void bond_set_mode_ops(struct bonding *bond, int mode) break; default: /* Should never happen, mode already checked */ - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: Unknown bonding mode %d\n", bond_dev->name, mode); @@ -4551,6 +4519,8 @@ static const struct ethtool_ops bond_ethtool_ops = { }; static const struct net_device_ops bond_netdev_ops = { + .ndo_init = bond_init, + .ndo_uninit = bond_uninit, .ndo_open = bond_open, .ndo_stop = bond_close, .ndo_start_xmit = bond_start_xmit, @@ -4565,48 +4535,34 @@ static const struct net_device_ops bond_netdev_ops = { .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, }; -/* - * Does not allocate but creates a /proc entry. - * Allowed to fail. - */ -static int bond_init(struct net_device *bond_dev, struct bond_params *params) +static void bond_setup(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - pr_debug("Begin bond_init for %s\n", bond_dev->name); - /* initialize rwlocks */ rwlock_init(&bond->lock); rwlock_init(&bond->curr_slave_lock); - bond->params = *params; /* copy params struct */ - - bond->wq = create_singlethread_workqueue(bond_dev->name); - if (!bond->wq) - return -ENOMEM; + bond->params = bonding_defaults; /* Initialize pointers */ - bond->first_slave = NULL; - bond->curr_active_slave = NULL; - bond->current_arp_slave = NULL; - bond->primary_slave = NULL; bond->dev = bond_dev; - bond->send_grat_arp = 0; - bond->send_unsol_na = 0; - bond->setup_by_slave = 0; INIT_LIST_HEAD(&bond->vlan_list); /* Initialize the device entry points */ + ether_setup(bond_dev); bond_dev->netdev_ops = &bond_netdev_ops; bond_dev->ethtool_ops = &bond_ethtool_ops; bond_set_mode_ops(bond, bond->params.mode); - bond_dev->destructor = bond_destructor; + bond_dev->destructor = free_netdev; /* Initialize the device options */ bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; bond_dev->priv_flags |= IFF_BONDING; + bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; + if (bond->params.arp_interval) bond_dev->priv_flags |= IFF_MASTER_ARPMON; @@ -4631,12 +4587,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); -#ifdef CONFIG_PROC_FS - bond_create_proc_entry(bond); -#endif - list_add_tail(&bond->bond_list, &bond_dev_list); - - return 0; } static void bond_work_cancel_all(struct bonding *bond) @@ -4671,9 +4621,7 @@ static void bond_deinit(struct net_device *bond_dev) bond_work_cancel_all(bond); -#ifdef CONFIG_PROC_FS bond_remove_proc_entry(bond); -#endif } /* Unregister and free all bond devices. @@ -4689,12 +4637,10 @@ static void bond_free_all(void) bond_work_cancel_all(bond); /* Release the bonded slaves */ bond_release_all(bond_dev); - bond_destroy(bond); + unregister_netdevice(bond_dev); } -#ifdef CONFIG_PROC_FS bond_destroy_proc_dir(); -#endif } /*------------------------- Module initialization ---------------------------*/ @@ -4742,7 +4688,7 @@ static int bond_check_params(struct bond_params *params) if (mode) { bond_mode = bond_parse_parm(mode, bond_mode_tbl); if (bond_mode == -1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": Error: Invalid bonding mode \"%s\"\n", mode == NULL ? "NULL" : mode); return -EINVAL; @@ -4752,16 +4698,16 @@ static int bond_check_params(struct bond_params *params) if (xmit_hash_policy) { if ((bond_mode != BOND_MODE_XOR) && (bond_mode != BOND_MODE_8023AD)) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": xor_mode param is irrelevant in mode %s\n", bond_mode_name(bond_mode)); } else { xmit_hashtype = bond_parse_parm(xmit_hash_policy, xmit_hashtype_tbl); if (xmit_hashtype == -1) { - printk(KERN_ERR DRV_NAME - ": Error: Invalid xmit_hash_policy \"%s\"\n", - xmit_hash_policy == NULL ? "NULL" : + pr_err(DRV_NAME + ": Error: Invalid xmit_hash_policy \"%s\"\n", + xmit_hash_policy == NULL ? "NULL" : xmit_hash_policy); return -EINVAL; } @@ -4770,13 +4716,13 @@ static int bond_check_params(struct bond_params *params) if (lacp_rate) { if (bond_mode != BOND_MODE_8023AD) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": lacp_rate param is irrelevant in mode %s\n", bond_mode_name(bond_mode)); } else { lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl); if (lacp_fast == -1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": Error: Invalid lacp rate \"%s\"\n", lacp_rate == NULL ? "NULL" : lacp_rate); return -EINVAL; @@ -4787,14 +4733,14 @@ static int bond_check_params(struct bond_params *params) if (ad_select) { params->ad_select = bond_parse_parm(ad_select, ad_select_tbl); if (params->ad_select == -1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": Error: Invalid ad_select \"%s\"\n", ad_select == NULL ? "NULL" : ad_select); return -EINVAL; } if (bond_mode != BOND_MODE_8023AD) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": ad_select param only affects 802.3ad mode\n"); } } else { @@ -4802,7 +4748,7 @@ static int bond_check_params(struct bond_params *params) } if (max_bonds < 0 || max_bonds > INT_MAX) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: max_bonds (%d) not in range %d-%d, so it " "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n", max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS); @@ -4810,7 +4756,7 @@ static int bond_check_params(struct bond_params *params) } if (miimon < 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: miimon module parameter (%d), " "not in range 0-%d, so it was reset to %d\n", miimon, INT_MAX, BOND_LINK_MON_INTERV); @@ -4818,7 +4764,7 @@ static int bond_check_params(struct bond_params *params) } if (updelay < 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: updelay module parameter (%d), " "not in range 0-%d, so it was reset to 0\n", updelay, INT_MAX); @@ -4826,7 +4772,7 @@ static int bond_check_params(struct bond_params *params) } if (downdelay < 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: downdelay module parameter (%d), " "not in range 0-%d, so it was reset to 0\n", downdelay, INT_MAX); @@ -4834,7 +4780,7 @@ static int bond_check_params(struct bond_params *params) } if ((use_carrier != 0) && (use_carrier != 1)) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: use_carrier module parameter (%d), " "not of valid value (0/1), so it was set to 1\n", use_carrier); @@ -4842,14 +4788,14 @@ static int bond_check_params(struct bond_params *params) } if (num_grat_arp < 0 || num_grat_arp > 255) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: num_grat_arp (%d) not in range 0-255 so it " "was reset to 1 \n", num_grat_arp); num_grat_arp = 1; } if (num_unsol_na < 0 || num_unsol_na > 255) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: num_unsol_na (%d) not in range 0-255 so it " "was reset to 1 \n", num_unsol_na); num_unsol_na = 1; @@ -4858,12 +4804,12 @@ static int bond_check_params(struct bond_params *params) /* reset values for 802.3ad */ if (bond_mode == BOND_MODE_8023AD) { if (!miimon) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: miimon must be specified, " "otherwise bonding will not detect link " "failure, speed and duplex which are " "essential for 802.3ad operation\n"); - printk(KERN_WARNING "Forcing miimon to 100msec\n"); + pr_warning("Forcing miimon to 100msec\n"); miimon = 100; } } @@ -4872,12 +4818,12 @@ static int bond_check_params(struct bond_params *params) if ((bond_mode == BOND_MODE_TLB) || (bond_mode == BOND_MODE_ALB)) { if (!miimon) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: miimon must be specified, " "otherwise bonding will not detect link " "failure and link speed which are essential " "for TLB/ALB load balancing\n"); - printk(KERN_WARNING "Forcing miimon to 100msec\n"); + pr_warning("Forcing miimon to 100msec\n"); miimon = 100; } } @@ -4897,7 +4843,7 @@ static int bond_check_params(struct bond_params *params) /* just warn the user the up/down delay will have * no effect since miimon is zero... */ - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: miimon module parameter not set " "and updelay (%d) or downdelay (%d) module " "parameter is set; updelay and downdelay have " @@ -4907,7 +4853,7 @@ static int bond_check_params(struct bond_params *params) } else { /* don't allow arp monitoring */ if (arp_interval) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: miimon (%d) and arp_interval (%d) " "can't be used simultaneously, disabling ARP " "monitoring\n", @@ -4916,7 +4862,7 @@ static int bond_check_params(struct bond_params *params) } if ((updelay % miimon) != 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: updelay (%d) is not a multiple " "of miimon (%d), updelay rounded to %d ms\n", updelay, miimon, (updelay / miimon) * miimon); @@ -4925,7 +4871,7 @@ static int bond_check_params(struct bond_params *params) updelay /= miimon; if ((downdelay % miimon) != 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: downdelay (%d) is not a multiple " "of miimon (%d), downdelay rounded to %d ms\n", downdelay, miimon, @@ -4936,7 +4882,7 @@ static int bond_check_params(struct bond_params *params) } if (arp_interval < 0) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: arp_interval module parameter (%d) " ", not in range 0-%d, so it was reset to %d\n", arp_interval, INT_MAX, BOND_LINK_ARP_INTERV); @@ -4949,7 +4895,7 @@ static int bond_check_params(struct bond_params *params) /* not complete check, but should be good enough to catch mistakes */ if (!isdigit(arp_ip_target[arp_ip_count][0])) { - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: bad arp_ip_target module parameter " "(%s), ARP monitoring will not be performed\n", arp_ip_target[arp_ip_count]); @@ -4962,7 +4908,7 @@ static int bond_check_params(struct bond_params *params) if (arp_interval && !arp_ip_count) { /* don't allow arping if no arp_ip_target given... */ - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: arp_interval module parameter (%d) " "specified without providing an arp_ip_target " "parameter, arp_interval was reset to 0\n", @@ -4972,12 +4918,12 @@ static int bond_check_params(struct bond_params *params) if (arp_validate) { if (bond_mode != BOND_MODE_ACTIVEBACKUP) { - printk(KERN_ERR DRV_NAME - ": arp_validate only supported in active-backup mode\n"); + pr_err(DRV_NAME + ": arp_validate only supported in active-backup mode\n"); return -EINVAL; } if (!arp_interval) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": arp_validate requires arp_interval\n"); return -EINVAL; } @@ -4985,7 +4931,7 @@ static int bond_check_params(struct bond_params *params) arp_validate_value = bond_parse_parm(arp_validate, arp_validate_tbl); if (arp_validate_value == -1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": Error: invalid arp_validate \"%s\"\n", arp_validate == NULL ? "NULL" : arp_validate); return -EINVAL; @@ -4994,20 +4940,20 @@ static int bond_check_params(struct bond_params *params) arp_validate_value = 0; if (miimon) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": MII link monitoring set to %d ms\n", miimon); } else if (arp_interval) { int i; - printk(KERN_INFO DRV_NAME - ": ARP monitoring set to %d ms, validate %s, with %d target(s):", + pr_info(DRV_NAME ": ARP monitoring set to %d ms," + " validate %s, with %d target(s):", arp_interval, arp_validate_tbl[arp_validate_value].modename, arp_ip_count); for (i = 0; i < arp_ip_count; i++) - printk (" %s", arp_ip_target[i]); + printk(" %s", arp_ip_target[i]); printk("\n"); @@ -5015,7 +4961,7 @@ static int bond_check_params(struct bond_params *params) /* miimon and arp_interval not set, we need one so things * work as expected, see bonding.txt for details */ - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: either miimon or arp_interval and " "arp_ip_target module parameters must be specified, " "otherwise bonding will not detect link failures! see " @@ -5026,7 +4972,7 @@ static int bond_check_params(struct bond_params *params) /* currently, using a primary only makes sense * in active backup, TLB or ALB modes */ - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: %s primary device specified but has no " "effect in %s mode\n", primary, bond_mode_name(bond_mode)); @@ -5037,14 +4983,14 @@ static int bond_check_params(struct bond_params *params) fail_over_mac_value = bond_parse_parm(fail_over_mac, fail_over_mac_tbl); if (fail_over_mac_value == -1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": Error: invalid fail_over_mac \"%s\"\n", arp_validate == NULL ? "NULL" : arp_validate); return -EINVAL; } if (bond_mode != BOND_MODE_ACTIVEBACKUP) - printk(KERN_WARNING DRV_NAME + pr_warning(DRV_NAME ": Warning: fail_over_mac only affects " "active-backup mode.\n"); } else { @@ -5094,37 +5040,53 @@ static void bond_set_lockdep_class(struct net_device *dev) netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL); } +/* + * Called from registration process + */ +static int bond_init(struct net_device *bond_dev) +{ + struct bonding *bond = netdev_priv(bond_dev); + + pr_debug("Begin bond_init for %s\n", bond_dev->name); + + bond->wq = create_singlethread_workqueue(bond_dev->name); + if (!bond->wq) + return -ENOMEM; + + bond_set_lockdep_class(bond_dev); + + netif_carrier_off(bond_dev); + + bond_create_proc_entry(bond); + list_add_tail(&bond->bond_list, &bond_dev_list); + + return 0; +} + /* Create a new bond based on the specified name and bonding parameters. * If name is NULL, obtain a suitable "bond%d" name for us. * Caller must NOT hold rtnl_lock; we need to release it here before we * set up our sysfs entries. */ -int bond_create(char *name, struct bond_params *params) +int bond_create(const char *name) { struct net_device *bond_dev; - struct bonding *bond; int res; rtnl_lock(); - down_write(&bonding_rwsem); - /* Check to see if the bond already exists. */ - if (name) { - list_for_each_entry(bond, &bond_dev_list, bond_list) - if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) { - printk(KERN_ERR DRV_NAME - ": cannot add bond %s; it already exists\n", - name); - res = -EPERM; - goto out_rtnl; - } + /* FIXME: pass netns from caller */ + if (name && __dev_get_by_name(&init_net, name)) { + pr_err(DRV_NAME ": cannot add bond %s; already exists\n", + name); + res = -EEXIST; + goto out_rtnl; } bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", - ether_setup); + bond_setup); if (!bond_dev) { - printk(KERN_ERR DRV_NAME - ": %s: eek! can't alloc netdev!\n", + pr_err(DRV_NAME ": %s: eek! can't alloc netdev!\n", name); res = -ENOMEM; goto out_rtnl; @@ -5136,43 +5098,24 @@ int bond_create(char *name, struct bond_params *params) goto out_netdev; } - /* bond_init() must be called after dev_alloc_name() (for the - * /proc files), but before register_netdevice(), because we - * need to set function pointers. - */ - - res = bond_init(bond_dev, params); - if (res < 0) { - goto out_netdev; - } - res = register_netdevice(bond_dev); - if (res < 0) { + if (res < 0) goto out_bond; - } - bond_set_lockdep_class(bond_dev); - - netif_carrier_off(bond_dev); - - up_write(&bonding_rwsem); - rtnl_unlock(); /* allows sysfs registration of net device */ res = bond_create_sysfs_entry(netdev_priv(bond_dev)); if (res < 0) goto out_unreg; + rtnl_unlock(); return 0; out_unreg: - rtnl_lock(); - down_write(&bonding_rwsem); unregister_netdevice(bond_dev); out_bond: bond_deinit(bond_dev); out_netdev: free_netdev(bond_dev); out_rtnl: - up_write(&bonding_rwsem); rtnl_unlock(); return res; } @@ -5182,21 +5125,16 @@ static int __init bonding_init(void) int i; int res; - printk(KERN_INFO "%s", version); + pr_info("%s", version); res = bond_check_params(&bonding_defaults); - if (res) { + if (res) goto out; - } -#ifdef CONFIG_PROC_FS bond_create_proc_dir(); -#endif - - init_rwsem(&bonding_rwsem); for (i = 0; i < max_bonds; i++) { - res = bond_create(NULL, &bonding_defaults); + res = bond_create(NULL); if (res) goto err; } @@ -5238,13 +5176,3 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION); MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others"); -MODULE_SUPPORTED_DEVICE("most ethernet devices"); - -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ - diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index d28731535226..55bf34f59bbf 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1,4 +1,3 @@ - /* * Copyright(c) 2004-2005 Intel Corporation. All rights reserved. * @@ -34,33 +33,14 @@ #include #include #include +#include #include #include "bonding.h" -#define to_dev(obj) container_of(obj,struct device,kobj) +#define to_dev(obj) container_of(obj, struct device, kobj) #define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd)))) -/*---------------------------- Declarations -------------------------------*/ - -static int expected_refcount = -1; -/*--------------------------- Data Structures -----------------------------*/ - -/* Bonding sysfs lock. Why can't we just use the subsystem lock? - * Because kobject_register tries to acquire the subsystem lock. If - * we already hold the lock (which we would if the user was creating - * a new bond through the sysfs interface), we deadlock. - * This lock is only needed when deleting a bond - we need to make sure - * that we don't collide with an ongoing ioctl. - */ - -struct rw_semaphore bonding_rwsem; - - - - -/*------------------------------ Functions --------------------------------*/ - /* * "show" function for the bond_masters attribute. * The class parameter is ignored. @@ -70,7 +50,7 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf) int res = 0; struct bonding *bond; - down_read(&(bonding_rwsem)); + rtnl_lock(); list_for_each_entry(bond, &bond_dev_list, bond_list) { if (res > (PAGE_SIZE - IFNAMSIZ)) { @@ -84,10 +64,22 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf) } if (res) buf[res-1] = '\n'; /* eat the leftover space */ - up_read(&(bonding_rwsem)); + + rtnl_unlock(); return res; } +static struct net_device *bond_get_by_name(const char *ifname) +{ + struct bonding *bond; + + list_for_each_entry(bond, &bond_dev_list, bond_list) { + if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0) + return bond->dev; + } + return NULL; +} + /* * "store" function for the bond_masters attribute. This is what * creates and deletes entire bonds. @@ -96,12 +88,12 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf) * */ -static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count) +static ssize_t bonding_store_bonds(struct class *cls, + const char *buffer, size_t count) { char command[IFNAMSIZ + 1] = {0, }; char *ifname; int rv, res = count; - struct bonding *bond; sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ ifname = command + 1; @@ -110,67 +102,48 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t goto err_no_cmd; if (command[0] == '+') { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s is being created...\n", ifname); - rv = bond_create(ifname, &bonding_defaults); + rv = bond_create(ifname); if (rv) { - printk(KERN_INFO DRV_NAME ": Bond creation failed.\n"); + pr_info(DRV_NAME ": Bond creation failed.\n"); res = rv; } - goto out; - } + } else if (command[0] == '-') { + struct net_device *bond_dev; - if (command[0] == '-') { rtnl_lock(); - down_write(&bonding_rwsem); - - list_for_each_entry(bond, &bond_dev_list, bond_list) - if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { - /* check the ref count on the bond's kobject. - * If it's > expected, then there's a file open, - * and we have to fail. - */ - if (atomic_read(&bond->dev->dev.kobj.kref.refcount) - > expected_refcount){ - printk(KERN_INFO DRV_NAME - ": Unable remove bond %s due to open references.\n", - ifname); - res = -EPERM; - goto out_unlock; - } - printk(KERN_INFO DRV_NAME - ": %s is being deleted...\n", - bond->dev->name); - bond_destroy(bond); - goto out_unlock; - } - - printk(KERN_ERR DRV_NAME - ": unable to delete non-existent bond %s\n", ifname); - res = -ENODEV; - goto out_unlock; - } - -err_no_cmd: - printk(KERN_ERR DRV_NAME - ": no command found in bonding_masters. Use +ifname or -ifname.\n"); - return -EPERM; - -out_unlock: - up_write(&bonding_rwsem); - rtnl_unlock(); + bond_dev = bond_get_by_name(ifname); + if (bond_dev) { + pr_info(DRV_NAME ": %s is being deleted...\n", + ifname); + unregister_netdevice(bond_dev); + } else { + pr_err(DRV_NAME ": unable to delete non-existent %s\n", + ifname); + res = -ENODEV; + } + rtnl_unlock(); + } else + goto err_no_cmd; /* Always return either count or an error. If you return 0, you'll * get called forever, which is bad. */ -out: return res; + +err_no_cmd: + pr_err(DRV_NAME ": no command found in bonding_masters." + " Use +ifname or -ifname.\n"); + return -EPERM; } + /* class attribute for bond_masters file. This ends up in /sys/class/net */ static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO, bonding_show_bonds, bonding_store_bonds); -int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave) +int bond_create_slave_symlinks(struct net_device *master, + struct net_device *slave) { char linkname[IFNAMSIZ+7]; int ret = 0; @@ -181,19 +154,20 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla if (ret) return ret; /* next, create a link from the master to the slave */ - sprintf(linkname,"slave_%s",slave->name); + sprintf(linkname, "slave_%s", slave->name); ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj), linkname); return ret; } -void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave) +void bond_destroy_slave_symlinks(struct net_device *master, + struct net_device *slave) { char linkname[IFNAMSIZ+7]; sysfs_remove_link(&(slave->dev.kobj), "master"); - sprintf(linkname,"slave_%s",slave->name); + sprintf(linkname, "slave_%s", slave->name); sysfs_remove_link(&(master->dev.kobj), linkname); } @@ -251,8 +225,8 @@ static ssize_t bonding_store_slaves(struct device *d, /* Note: We can't hold bond->lock here, as bond_create grabs it. */ - rtnl_lock(); - down_write(&(bonding_rwsem)); + if (!rtnl_trylock()) + return restart_syscall(); sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ ifname = command + 1; @@ -264,46 +238,47 @@ static ssize_t bonding_store_slaves(struct device *d, /* Got a slave name in ifname. Is it already in the list? */ found = 0; - read_lock(&bond->lock); - bond_for_each_slave(bond, slave, i) - if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { - printk(KERN_ERR DRV_NAME - ": %s: Interface %s is already enslaved!\n", - bond->dev->name, ifname); - ret = -EPERM; - read_unlock(&bond->lock); - goto out; - } - read_unlock(&bond->lock); - printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", - bond->dev->name, ifname); - dev = dev_get_by_name(&init_net, ifname); + /* FIXME: get netns from sysfs object */ + dev = __dev_get_by_name(&init_net, ifname); if (!dev) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Interface %s does not exist!\n", bond->dev->name, ifname); - ret = -EPERM; + ret = -ENODEV; goto out; } - else - dev_put(dev); if (dev->flags & IFF_UP) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Error: Unable to enslave %s " "because it is already up.\n", bond->dev->name, dev->name); ret = -EPERM; goto out; } + + read_lock(&bond->lock); + bond_for_each_slave(bond, slave, i) + if (slave->dev == dev) { + pr_err(DRV_NAME + ": %s: Interface %s is already enslaved!\n", + bond->dev->name, ifname); + ret = -EPERM; + read_unlock(&bond->lock); + goto out; + } + read_unlock(&bond->lock); + + pr_info(DRV_NAME ": %s: Adding slave %s.\n", + bond->dev->name, ifname); + /* If this is the first slave, then we need to set the master's hardware address to be the same as the slave's. */ - if (!(*((u32 *) & (bond->dev->dev_addr[0])))) { + if (is_zero_ether_addr(bond->dev->dev_addr)) memcpy(bond->dev->dev_addr, dev->dev_addr, dev->addr_len); - } /* Set the slave's MTU to match the bond */ original_mtu = dev->mtu; @@ -317,9 +292,9 @@ static ssize_t bonding_store_slaves(struct device *d, bond_for_each_slave(bond, slave, i) if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) slave->original_mtu = original_mtu; - if (res) { + if (res) ret = res; - } + goto out; } @@ -333,7 +308,7 @@ static ssize_t bonding_store_slaves(struct device *d, break; } if (dev) { - printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", + pr_info(DRV_NAME ": %s: Removing slave %s\n", bond->dev->name, dev->name); res = bond_release(bond->dev, dev); if (res) { @@ -342,9 +317,9 @@ static ssize_t bonding_store_slaves(struct device *d, } /* set the slave MTU to the default */ dev_set_mtu(dev, original_mtu); - } - else { - printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n", + } else { + pr_err(DRV_NAME ": unable to remove non-existent" + " slave %s for bond %s.\n", ifname, bond->dev->name); ret = -ENODEV; } @@ -352,16 +327,16 @@ static ssize_t bonding_store_slaves(struct device *d, } err_no_cmd: - printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name); + pr_err(DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name); ret = -EPERM; out: - up_write(&(bonding_rwsem)); rtnl_unlock(); return ret; } -static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves); +static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, + bonding_store_slaves); /* * Show and set the bonding mode. The bond interface must be down to @@ -385,16 +360,15 @@ static ssize_t bonding_store_mode(struct device *d, struct bonding *bond = to_bond(d); if (bond->dev->flags & IFF_UP) { - printk(KERN_ERR DRV_NAME - ": unable to update mode of %s because interface is up.\n", - bond->dev->name); + pr_err(DRV_NAME ": unable to update mode of %s" + " because interface is up.\n", bond->dev->name); ret = -EPERM; goto out; } new_value = bond_parse_parm(buf, bond_mode_tbl); if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Ignoring invalid mode value %.*s.\n", bond->dev->name, (int)strlen(buf) - 1, buf); @@ -409,17 +383,19 @@ static ssize_t bonding_store_mode(struct device *d, bond->params.mode = new_value; bond_set_mode_ops(bond, bond->params.mode); - printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", - bond->dev->name, bond_mode_tbl[new_value].modename, new_value); + pr_info(DRV_NAME ": %s: setting mode to %s (%d).\n", + bond->dev->name, bond_mode_tbl[new_value].modename, + new_value); } out: return ret; } -static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode); +static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + bonding_show_mode, bonding_store_mode); /* - * Show and set the bonding transmit hash method. The bond interface must be down to - * change the xmit hash policy. + * Show and set the bonding transmit hash method. + * The bond interface must be down to change the xmit hash policy. */ static ssize_t bonding_show_xmit_hash(struct device *d, struct device_attribute *attr, @@ -440,7 +416,7 @@ static ssize_t bonding_store_xmit_hash(struct device *d, struct bonding *bond = to_bond(d); if (bond->dev->flags & IFF_UP) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME "%s: Interface is up. Unable to update xmit policy.\n", bond->dev->name); ret = -EPERM; @@ -449,7 +425,7 @@ static ssize_t bonding_store_xmit_hash(struct device *d, new_value = bond_parse_parm(buf, xmit_hashtype_tbl); if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Ignoring invalid xmit hash policy value %.*s.\n", bond->dev->name, (int)strlen(buf) - 1, buf); @@ -458,13 +434,15 @@ static ssize_t bonding_store_xmit_hash(struct device *d, } else { bond->params.xmit_policy = new_value; bond_set_mode_ops(bond, bond->params.mode); - printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n", - bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value); + pr_info(DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n", + bond->dev->name, + xmit_hashtype_tbl[new_value].modename, new_value); } out: return ret; } -static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash); +static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, + bonding_show_xmit_hash, bonding_store_xmit_hash); /* * Show and set arp_validate. @@ -489,39 +467,41 @@ static ssize_t bonding_store_arp_validate(struct device *d, new_value = bond_parse_parm(buf, arp_validate_tbl); if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Ignoring invalid arp_validate value %s\n", bond->dev->name, buf); return -EINVAL; } if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: arp_validate only supported in active-backup mode.\n", bond->dev->name); return -EINVAL; } - printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n", + pr_info(DRV_NAME ": %s: setting arp_validate to %s (%d).\n", bond->dev->name, arp_validate_tbl[new_value].modename, new_value); - if (!bond->params.arp_validate && new_value) { + if (!bond->params.arp_validate && new_value) bond_register_arp(bond); - } else if (bond->params.arp_validate && !new_value) { + else if (bond->params.arp_validate && !new_value) bond_unregister_arp(bond); - } bond->params.arp_validate = new_value; return count; } -static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); +static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, + bonding_store_arp_validate); /* * Show and store fail_over_mac. User only allowed to change the * value when there are no slaves. */ -static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf) +static ssize_t bonding_show_fail_over_mac(struct device *d, + struct device_attribute *attr, + char *buf) { struct bonding *bond = to_bond(d); @@ -530,13 +510,15 @@ static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attrib bond->params.fail_over_mac); } -static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t bonding_store_fail_over_mac(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) { int new_value; struct bonding *bond = to_bond(d); if (bond->slave_cnt != 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Can't alter fail_over_mac with slaves in bond.\n", bond->dev->name); return -EPERM; @@ -544,21 +526,22 @@ static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attri new_value = bond_parse_parm(buf, fail_over_mac_tbl); if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Ignoring invalid fail_over_mac value %s.\n", bond->dev->name, buf); return -EINVAL; } bond->params.fail_over_mac = new_value; - printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n", + pr_info(DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n", bond->dev->name, fail_over_mac_tbl[new_value].modename, new_value); return count; } -static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac); +static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, + bonding_show_fail_over_mac, bonding_store_fail_over_mac); /* * Show and set the arp timer interval. There are two tricky bits @@ -583,28 +566,28 @@ static ssize_t bonding_store_arp_interval(struct device *d, struct bonding *bond = to_bond(d); if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no arp_interval value specified.\n", bond->dev->name); ret = -EINVAL; goto out; } if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n", bond->dev->name, new_value, INT_MAX); ret = -EINVAL; goto out; } - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Setting ARP monitoring interval to %d.\n", bond->dev->name, new_value); bond->params.arp_interval = new_value; if (bond->params.arp_interval) bond->dev->priv_flags |= IFF_MASTER_ARPMON; if (bond->params.miimon) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: ARP monitoring cannot be used with MII monitoring. " "%s Disabling MII monitoring.\n", bond->dev->name, bond->dev->name); @@ -615,7 +598,7 @@ static ssize_t bonding_store_arp_interval(struct device *d, } } if (!bond->params.arp_targets[0]) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: ARP monitoring has been set up, " "but no ARP targets have been specified.\n", bond->dev->name); @@ -641,7 +624,8 @@ static ssize_t bonding_store_arp_interval(struct device *d, out: return ret; } -static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval); +static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR, + bonding_show_arp_interval, bonding_store_arp_interval); /* * Show and set the arp targets. @@ -677,7 +661,7 @@ static ssize_t bonding_store_arp_targets(struct device *d, /* look for adds */ if (buf[0] == '+') { if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: invalid ARP target %pI4 specified for addition\n", bond->dev->name, &newtarget); ret = -EINVAL; @@ -686,14 +670,14 @@ static ssize_t bonding_store_arp_targets(struct device *d, /* look for an empty slot to put the target in, and check for dupes */ for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) { if (targets[i] == newtarget) { /* duplicate */ - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: ARP target %pI4 is already present\n", bond->dev->name, &newtarget); ret = -EINVAL; goto out; } if (targets[i] == 0) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: adding ARP target %pI4.\n", bond->dev->name, &newtarget); done = 1; @@ -701,17 +685,16 @@ static ssize_t bonding_store_arp_targets(struct device *d, } } if (!done) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: ARP target table is full!\n", bond->dev->name); ret = -EINVAL; goto out; } - } - else if (buf[0] == '-') { + } else if (buf[0] == '-') { if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: invalid ARP target %pI4 specified for removal\n", bond->dev->name, &newtarget); ret = -EINVAL; @@ -721,7 +704,7 @@ static ssize_t bonding_store_arp_targets(struct device *d, for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) { if (targets[i] == newtarget) { int j; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: removing ARP target %pI4.\n", bond->dev->name, &newtarget); for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++) @@ -732,15 +715,15 @@ static ssize_t bonding_store_arp_targets(struct device *d, } } if (!done) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: unable to remove nonexistent ARP target %pI4.\n", bond->dev->name, &newtarget); ret = -EINVAL; goto out; } - } - else { - printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use + or -.\n", + } else { + pr_err(DRV_NAME ": no command found in arp_ip_targets file" + " for bond %s. Use + or -.\n", bond->dev->name); ret = -EPERM; goto out; @@ -773,7 +756,7 @@ static ssize_t bonding_store_downdelay(struct device *d, struct bonding *bond = to_bond(d); if (!(bond->params.miimon)) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Unable to set down delay as MII monitoring is disabled\n", bond->dev->name); ret = -EPERM; @@ -781,14 +764,14 @@ static ssize_t bonding_store_downdelay(struct device *d, } if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no down delay value specified.\n", bond->dev->name); ret = -EINVAL; goto out; } if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n", bond->dev->name, new_value, 1, INT_MAX); ret = -EINVAL; @@ -803,15 +786,17 @@ static ssize_t bonding_store_downdelay(struct device *d, bond->params.miimon); } bond->params.downdelay = new_value / bond->params.miimon; - printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n", - bond->dev->name, bond->params.downdelay * bond->params.miimon); + pr_info(DRV_NAME ": %s: Setting down delay to %d.\n", + bond->dev->name, + bond->params.downdelay * bond->params.miimon); } out: return ret; } -static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay); +static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR, + bonding_show_downdelay, bonding_store_downdelay); static ssize_t bonding_show_updelay(struct device *d, struct device_attribute *attr, @@ -831,7 +816,7 @@ static ssize_t bonding_store_updelay(struct device *d, struct bonding *bond = to_bond(d); if (!(bond->params.miimon)) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Unable to set up delay as MII monitoring is disabled\n", bond->dev->name); ret = -EPERM; @@ -839,14 +824,14 @@ static ssize_t bonding_store_updelay(struct device *d, } if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no up delay value specified.\n", bond->dev->name); ret = -EINVAL; goto out; } if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n", bond->dev->name, new_value, 1, INT_MAX); ret = -EINVAL; @@ -861,7 +846,7 @@ static ssize_t bonding_store_updelay(struct device *d, bond->params.miimon); } bond->params.updelay = new_value / bond->params.miimon; - printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n", + pr_info(DRV_NAME ": %s: Setting up delay to %d.\n", bond->dev->name, bond->params.updelay * bond->params.miimon); } @@ -869,7 +854,8 @@ static ssize_t bonding_store_updelay(struct device *d, out: return ret; } -static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay); +static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR, + bonding_show_updelay, bonding_store_updelay); /* * Show and set the LACP interval. Interface must be down, and the mode @@ -894,7 +880,7 @@ static ssize_t bonding_store_lacp(struct device *d, struct bonding *bond = to_bond(d); if (bond->dev->flags & IFF_UP) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Unable to update LACP rate because interface is up.\n", bond->dev->name); ret = -EPERM; @@ -902,7 +888,7 @@ static ssize_t bonding_store_lacp(struct device *d, } if (bond->params.mode != BOND_MODE_8023AD) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n", bond->dev->name); ret = -EPERM; @@ -913,19 +899,20 @@ static ssize_t bonding_store_lacp(struct device *d, if ((new_value == 1) || (new_value == 0)) { bond->params.lacp_fast = new_value; - printk(KERN_INFO DRV_NAME - ": %s: Setting LACP rate to %s (%d).\n", - bond->dev->name, bond_lacp_tbl[new_value].modename, new_value); + pr_info(DRV_NAME ": %s: Setting LACP rate to %s (%d).\n", + bond->dev->name, bond_lacp_tbl[new_value].modename, + new_value); } else { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Ignoring invalid LACP rate value %.*s.\n", - bond->dev->name, (int)strlen(buf) - 1, buf); + bond->dev->name, (int)strlen(buf) - 1, buf); ret = -EINVAL; } out: return ret; } -static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); +static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, + bonding_show_lacp, bonding_store_lacp); static ssize_t bonding_show_ad_select(struct device *d, struct device_attribute *attr, @@ -947,7 +934,7 @@ static ssize_t bonding_store_ad_select(struct device *d, struct bonding *bond = to_bond(d); if (bond->dev->flags & IFF_UP) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Unable to update ad_select because interface " "is up.\n", bond->dev->name); ret = -EPERM; @@ -958,12 +945,12 @@ static ssize_t bonding_store_ad_select(struct device *d, if (new_value != -1) { bond->params.ad_select = new_value; - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Setting ad_select to %s (%d).\n", bond->dev->name, ad_select_tbl[new_value].modename, new_value); } else { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Ignoring invalid ad_select value %.*s.\n", bond->dev->name, (int)strlen(buf) - 1, buf); ret = -EINVAL; @@ -971,8 +958,8 @@ static ssize_t bonding_store_ad_select(struct device *d, out: return ret; } - -static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select); +static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, + bonding_show_ad_select, bonding_store_ad_select); /* * Show and set the number of grat ARP to send after a failover event. @@ -994,14 +981,14 @@ static ssize_t bonding_store_n_grat_arp(struct device *d, struct bonding *bond = to_bond(d); if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no num_grat_arp value specified.\n", bond->dev->name); ret = -EINVAL; goto out; } if (new_value < 0 || new_value > 255) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n", bond->dev->name, new_value); ret = -EINVAL; @@ -1012,10 +999,11 @@ static ssize_t bonding_store_n_grat_arp(struct device *d, out: return ret; } -static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp); +static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, + bonding_show_n_grat_arp, bonding_store_n_grat_arp); /* - * Show and set the number of unsolicted NA's to send after a failover event. + * Show and set the number of unsolicited NA's to send after a failover event. */ static ssize_t bonding_show_n_unsol_na(struct device *d, struct device_attribute *attr, @@ -1034,25 +1022,26 @@ static ssize_t bonding_store_n_unsol_na(struct device *d, struct bonding *bond = to_bond(d); if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no num_unsol_na value specified.\n", bond->dev->name); ret = -EINVAL; goto out; } + if (new_value < 0 || new_value > 255) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n", bond->dev->name, new_value); ret = -EINVAL; goto out; - } else { + } else bond->params.num_unsol_na = new_value; - } out: return ret; } -static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, bonding_show_n_unsol_na, bonding_store_n_unsol_na); +static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, + bonding_show_n_unsol_na, bonding_store_n_unsol_na); /* * Show and set the MII monitor interval. There are two tricky bits @@ -1077,37 +1066,37 @@ static ssize_t bonding_store_miimon(struct device *d, struct bonding *bond = to_bond(d); if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no miimon value specified.\n", bond->dev->name); ret = -EINVAL; goto out; } if (new_value < 0) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n", bond->dev->name, new_value, 1, INT_MAX); ret = -EINVAL; goto out; } else { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Setting MII monitoring interval to %d.\n", bond->dev->name, new_value); bond->params.miimon = new_value; - if(bond->params.updelay) - printk(KERN_INFO DRV_NAME + if (bond->params.updelay) + pr_info(DRV_NAME ": %s: Note: Updating updelay (to %d) " "since it is a multiple of the miimon value.\n", bond->dev->name, bond->params.updelay * bond->params.miimon); - if(bond->params.downdelay) - printk(KERN_INFO DRV_NAME + if (bond->params.downdelay) + pr_info(DRV_NAME ": %s: Note: Updating downdelay (to %d) " "since it is a multiple of the miimon value.\n", bond->dev->name, bond->params.downdelay * bond->params.miimon); if (bond->params.arp_interval) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: MII monitoring cannot be used with " "ARP monitoring. Disabling ARP monitoring...\n", bond->dev->name); @@ -1141,7 +1130,8 @@ static ssize_t bonding_store_miimon(struct device *d, out: return ret; } -static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon); +static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, + bonding_show_miimon, bonding_store_miimon); /* * Show and set the primary slave. The store function is much @@ -1171,12 +1161,13 @@ static ssize_t bonding_store_primary(struct device *d, struct slave *slave; struct bonding *bond = to_bond(d); - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); if (!USES_PRIMARY(bond->params.mode)) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Unable to set primary slave; %s is in mode %d\n", bond->dev->name, bond->dev->name, bond->params.mode); } else { @@ -1184,7 +1175,7 @@ static ssize_t bonding_store_primary(struct device *d, if (strnicmp (slave->dev->name, buf, strlen(slave->dev->name)) == 0) { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Setting %s as primary slave.\n", bond->dev->name, slave->dev->name); bond->primary_slave = slave; @@ -1196,13 +1187,13 @@ static ssize_t bonding_store_primary(struct device *d, /* if we got here, then we didn't match the name of any slave */ if (strlen(buf) == 0 || buf[0] == '\n') { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Setting primary slave to None.\n", bond->dev->name); bond->primary_slave = NULL; bond_select_active_slave(bond); } else { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Unable to set %.*s as primary slave as it is not a slave.\n", bond->dev->name, (int)strlen(buf) - 1, buf); } @@ -1214,7 +1205,8 @@ static ssize_t bonding_store_primary(struct device *d, return count; } -static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); +static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, + bonding_show_primary, bonding_store_primary); /* * Show and set the use_carrier flag. @@ -1237,7 +1229,7 @@ static ssize_t bonding_store_carrier(struct device *d, if (sscanf(buf, "%d", &new_value) != 1) { - printk(KERN_ERR DRV_NAME + pr_err(DRV_NAME ": %s: no use_carrier value specified.\n", bond->dev->name); ret = -EINVAL; @@ -1245,17 +1237,18 @@ static ssize_t bonding_store_carrier(struct device *d, } if ((new_value == 0) || (new_value == 1)) { bond->params.use_carrier = new_value; - printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n", + pr_info(DRV_NAME ": %s: Setting use_carrier to %d.\n", bond->dev->name, new_value); } else { - printk(KERN_INFO DRV_NAME + pr_info(DRV_NAME ": %s: Ignoring invalid use_carrier value %d.\n", bond->dev->name, new_value); } out: return count; } -static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier); +static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, + bonding_show_carrier, bonding_store_carrier); /* @@ -1284,19 +1277,20 @@ static ssize_t bonding_store_active_slave(struct device *d, { int i; struct slave *slave; - struct slave *old_active = NULL; - struct slave *new_active = NULL; + struct slave *old_active = NULL; + struct slave *new_active = NULL; struct bonding *bond = to_bond(d); - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); - if (!USES_PRIMARY(bond->params.mode)) { - printk(KERN_INFO DRV_NAME - ": %s: Unable to change active slave; %s is in mode %d\n", - bond->dev->name, bond->dev->name, bond->params.mode); - } else { + if (!USES_PRIMARY(bond->params.mode)) + pr_info(DRV_NAME ": %s: Unable to change active slave;" + " %s is in mode %d\n", + bond->dev->name, bond->dev->name, bond->params.mode); + else { bond_for_each_slave(bond, slave, i) { if (strnicmp (slave->dev->name, buf, @@ -1335,18 +1329,18 @@ static ssize_t bonding_store_active_slave(struct device *d, /* if we got here, then we didn't match the name of any slave */ if (strlen(buf) == 0 || buf[0] == '\n') { - printk(KERN_INFO DRV_NAME - ": %s: Setting active slave to None.\n", - bond->dev->name); + pr_info(DRV_NAME + ": %s: Setting active slave to None.\n", + bond->dev->name); bond->primary_slave = NULL; - bond_select_active_slave(bond); + bond_select_active_slave(bond); } else { - printk(KERN_INFO DRV_NAME - ": %s: Unable to set %.*s as active slave as it is not a slave.\n", - bond->dev->name, (int)strlen(buf) - 1, buf); + pr_info(DRV_NAME ": %s: Unable to set %.*s" + " as active slave as it is not a slave.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); } } -out: + out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); rtnl_unlock(); @@ -1354,7 +1348,8 @@ static ssize_t bonding_store_active_slave(struct device *d, return count; } -static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave); +static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, + bonding_show_active_slave, bonding_store_active_slave); /* @@ -1371,7 +1366,7 @@ static ssize_t bonding_show_mii_status(struct device *d, curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); - return sprintf(buf, "%s\n", (curr) ? "up" : "down"); + return sprintf(buf, "%s\n", curr ? "up" : "down"); } static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL); @@ -1388,7 +1383,9 @@ static ssize_t bonding_show_ad_aggregator(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id); + count = sprintf(buf, "%d\n", + (bond_3ad_get_active_agg_info(bond, &ad_info)) + ? 0 : ad_info.aggregator_id); } return count; @@ -1408,7 +1405,9 @@ static ssize_t bonding_show_ad_num_ports(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports); + count = sprintf(buf, "%d\n", + (bond_3ad_get_active_agg_info(bond, &ad_info)) + ? 0 : ad_info.ports); } return count; @@ -1428,7 +1427,9 @@ static ssize_t bonding_show_ad_actor_key(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key); + count = sprintf(buf, "%d\n", + (bond_3ad_get_active_agg_info(bond, &ad_info)) + ? 0 : ad_info.actor_key); } return count; @@ -1448,7 +1449,9 @@ static ssize_t bonding_show_ad_partner_key(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key); + count = sprintf(buf, "%d\n", + (bond_3ad_get_active_agg_info(bond, &ad_info)) + ? 0 : ad_info.partner_key); } return count; @@ -1468,9 +1471,8 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d, if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - if (!bond_3ad_get_active_agg_info(bond, &ad_info)) { + if (!bond_3ad_get_active_agg_info(bond, &ad_info)) count = sprintf(buf, "%pM\n", ad_info.partner_system); - } } return count; @@ -1538,6 +1540,7 @@ int bond_create_sysfs(void) printk(KERN_ERR "network device named %s already exists in sysfs", class_attr_bonding_masters.attr.name); + ret = 0; } return ret; @@ -1562,12 +1565,8 @@ int bond_create_sysfs_entry(struct bonding *bond) int err; err = sysfs_create_group(&(dev->dev.kobj), &bonding_group); - if (err) { + if (err) printk(KERN_EMERG "eek! didn't create group!\n"); - } - - if (expected_refcount < 1) - expected_refcount = atomic_read(&bond->dev->dev.kobj.kref.refcount); return err; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index ca849d2adf98..6290a502742e 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -286,8 +286,7 @@ static inline unsigned long slave_last_rx(struct bonding *bond, static inline void bond_set_slave_inactive_flags(struct slave *slave) { struct bonding *bond = netdev_priv(slave->dev->master); - if (bond->params.mode != BOND_MODE_TLB && - bond->params.mode != BOND_MODE_ALB) + if (!bond_is_lb(bond)) slave->state = BOND_STATE_BACKUP; slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; if (slave_do_arp_validate(bond, slave)) @@ -322,8 +321,7 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond) struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); -int bond_create(char *name, struct bond_params *params); -void bond_destroy(struct bonding *bond); +int bond_create(const char *name); int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev); int bond_create_sysfs(void); void bond_destroy_sysfs(void); @@ -350,12 +348,8 @@ extern const struct bond_parm_tbl bond_mode_tbl[]; extern const struct bond_parm_tbl xmit_hashtype_tbl[]; extern const struct bond_parm_tbl arp_validate_tbl[]; extern const struct bond_parm_tbl fail_over_mac_tbl[]; -extern struct bond_params bonding_defaults; extern struct bond_parm_tbl ad_select_tbl[]; -/* exported from bond_sysfs.c */ -extern struct rw_semaphore bonding_rwsem; - #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) void bond_send_unsolicited_na(struct bonding *bond); void bond_register_ipv6_notifier(void); diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 57def0d57371..d5e18812bf49 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -12,6 +12,68 @@ config CAN_VCAN This driver can also be built as a module. If so, the module will be called vcan. +config CAN_DEV + tristate "Platform CAN drivers with Netlink support" + depends on CAN + default Y + ---help--- + Enables the common framework for platform CAN drivers with Netlink + support. This is the standard library for CAN drivers. + If unsure, say Y. + +config CAN_CALC_BITTIMING + bool "CAN bit-timing calculation" + depends on CAN_DEV + default Y + ---help--- + If enabled, CAN bit-timing parameters will be calculated for the + bit-rate specified via Netlink argument "bitrate" when the device + get started. This works fine for the most common CAN controllers + with standard bit-rates but may fail for exotic bit-rates or CAN + source clock frequencies. Disabling saves some space, but then the + bit-timing parameters must be specified directly using the Netlink + arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw". + If unsure, say Y. + +config CAN_SJA1000 + depends on CAN_DEV + tristate "Philips SJA1000" + ---help--- + Driver for the SJA1000 CAN controllers from Philips or NXP + +config CAN_SJA1000_PLATFORM + depends on CAN_SJA1000 + tristate "Generic Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the "platform bus" (Linux abstraction for directly to the + processor attached devices). Which can be found on various + boards from Phytec (http://www.phytec.de) like the PCM027, + PCM038. + +config CAN_SJA1000_OF_PLATFORM + depends on CAN_SJA1000 && PPC_OF + tristate "Generic OF Platform Bus based SJA1000 driver" + ---help--- + This driver adds support for the SJA1000 chips connected to + the OpenFirmware "platform bus" found on embedded systems with + OpenFirmware bindings, e.g. if you have a PowerPC based system + you may want to enable this option. + +config CAN_EMS_PCI + tristate "EMS CPC-PCI and CPC-PCIe 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). + +config CAN_KVASER_PCI + tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" + depends on PCI && CAN_SJA1000 + ---help--- + This driver is for the the PCIcanx and PCIcan cards (1, 2 or + 4 channel) from Kvaser (http://www.kvaser.com). + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index c4bead705cd9..523a941b358b 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -3,3 +3,10 @@ # obj-$(CONFIG_CAN_VCAN) += vcan.o + +obj-$(CONFIG_CAN_DEV) += can-dev.o +can-dev-y := dev.o + +obj-$(CONFIG_CAN_SJA1000) += sja1000/ + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c new file mode 100644 index 000000000000..574daddc21bf --- /dev/null +++ b/drivers/net/can/dev.c @@ -0,0 +1,657 @@ +/* + * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix + * Copyright (C) 2006 Andrey Volkov, Varma Electronics + * Copyright (C) 2008-2009 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MOD_DESC "CAN device driver interface" + +MODULE_DESCRIPTION(MOD_DESC); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Wolfgang Grandegger "); + +#ifdef CONFIG_CAN_CALC_BITTIMING +#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ + +/* + * Bit-timing calculation derived from: + * + * Code based on LinCAN sources and H8S2638 project + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz + * Copyright 2005 Stanislav Marek + * email: pisa@cmp.felk.cvut.cz + * + * Calculates proper bit-timing parameters for a specified bit-rate + * and sample-point, which can then be used to set the bit-timing + * registers of the CAN controller. You can find more information + * in the header file linux/can/netlink.h. + */ +static int can_update_spt(const struct can_bittiming_const *btc, + int sampl_pt, int tseg, int *tseg1, int *tseg2) +{ + *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; + if (*tseg2 < btc->tseg2_min) + *tseg2 = btc->tseg2_min; + if (*tseg2 > btc->tseg2_max) + *tseg2 = btc->tseg2_max; + *tseg1 = tseg - *tseg2; + if (*tseg1 > btc->tseg1_max) { + *tseg1 = btc->tseg1_max; + *tseg2 = tseg - *tseg1; + } + return 1000 * (tseg + 1 - *tseg2) / (tseg + 1); +} + +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt) +{ + struct can_priv *priv = netdev_priv(dev); + const struct can_bittiming_const *btc = priv->bittiming_const; + long rate, best_rate = 0; + long best_error = 1000000000, error = 0; + int best_tseg = 0, best_brp = 0, brp = 0; + int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; + int spt_error = 1000, spt = 0, sampl_pt; + u64 v64; + + if (!priv->bittiming_const) + return -ENOTSUPP; + + /* Use CIA recommended sample points */ + if (bt->sample_point) { + sampl_pt = bt->sample_point; + } else { + if (bt->bitrate > 800000) + sampl_pt = 750; + else if (bt->bitrate > 500000) + sampl_pt = 800; + else + sampl_pt = 875; + } + + /* tseg even = round down, odd = round up */ + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) { + tsegall = 1 + tseg / 2; + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2; + /* chose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + if ((brp < btc->brp_min) || (brp > btc->brp_max)) + continue; + rate = priv->clock.freq / (brp * tsegall); + error = bt->bitrate - rate; + /* tseg brp biterror */ + if (error < 0) + error = -error; + if (error > best_error) + continue; + best_error = error; + if (error == 0) { + spt = can_update_spt(btc, sampl_pt, tseg / 2, + &tseg1, &tseg2); + error = sampl_pt - spt; + if (error < 0) + error = -error; + if (error > spt_error) + continue; + spt_error = error; + } + best_tseg = tseg / 2; + best_brp = brp; + best_rate = rate; + if (error == 0) + break; + } + + if (best_error) { + /* Error in one-tenth of a percent */ + error = (best_error * 1000) / bt->bitrate; + if (error > CAN_CALC_MAX_ERROR) { + dev_err(dev->dev.parent, + "bitrate error %ld.%ld%% too high\n", + error / 10, error % 10); + return -EDOM; + } else { + dev_warn(dev->dev.parent, "bitrate error %ld.%ld%%\n", + error / 10, error % 10); + } + } + + /* real sample point */ + bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg, + &tseg1, &tseg2); + + v64 = (u64)best_brp * 1000000000UL; + do_div(v64, priv->clock.freq); + bt->tq = (u32)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + bt->sjw = 1; + bt->brp = best_brp; + /* real bit-rate */ + bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1)); + + return 0; +} +#else /* !CONFIG_CAN_CALC_BITTIMING */ +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt) +{ + dev_err(dev->dev.parent, "bit-timing calculation not available\n"); + return -EINVAL; +} +#endif /* CONFIG_CAN_CALC_BITTIMING */ + +/* + * Checks the validity of the specified bit-timing parameters prop_seg, + * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate + * prescaler value brp. You can find more information in the header + * file linux/can/netlink.h. + */ +static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt) +{ + struct can_priv *priv = netdev_priv(dev); + const struct can_bittiming_const *btc = priv->bittiming_const; + int tseg1, alltseg; + u64 brp64; + + if (!priv->bittiming_const) + return -ENOTSUPP; + + tseg1 = bt->prop_seg + bt->phase_seg1; + if (!bt->sjw) + bt->sjw = 1; + if (bt->sjw > btc->sjw_max || + tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || + bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) + return -ERANGE; + + brp64 = (u64)priv->clock.freq * (u64)bt->tq; + if (btc->brp_inc > 1) + do_div(brp64, btc->brp_inc); + brp64 += 500000000UL - 1; + do_div(brp64, 1000000000UL); /* the practicable BRP */ + if (btc->brp_inc > 1) + brp64 *= btc->brp_inc; + bt->brp = (u32)brp64; + + if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + return -EINVAL; + + alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; + bt->bitrate = priv->clock.freq / (bt->brp * alltseg); + bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + + return 0; +} + +int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt) +{ + struct can_priv *priv = netdev_priv(dev); + int err; + + /* Check if the CAN device has bit-timing parameters */ + if (priv->bittiming_const) { + + /* Non-expert mode? Check if the bitrate has been pre-defined */ + if (!bt->tq) + /* Determine bit-timing parameters */ + err = can_calc_bittiming(dev, bt); + else + /* Check bit-timing params and calculate proper brp */ + err = can_fixup_bittiming(dev, bt); + if (err) + return err; + } + + return 0; +} + +/* + * Local echo of CAN messages + * + * CAN network devices *should* support a local echo functionality + * (see Documentation/networking/can.txt). To test the handling of CAN + * interfaces that do not support the local echo both driver types are + * implemented. In the case that the driver does not support the echo + * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core + * to perform the echo as a fallback solution. + */ +static void can_flush_echo_skb(struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + int i; + + for (i = 0; i < CAN_ECHO_SKB_MAX; i++) { + if (priv->echo_skb[i]) { + kfree_skb(priv->echo_skb[i]); + priv->echo_skb[i] = NULL; + stats->tx_dropped++; + stats->tx_aborted_errors++; + } + } +} + +/* + * Put the skb on the stack to be looped backed locally lateron + * + * The function is typically called in the start_xmit function + * of the device driver. The driver must protect access to + * priv->echo_skb, if necessary. + */ +void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx) +{ + struct can_priv *priv = netdev_priv(dev); + + /* check flag whether this packet has to be looped back */ + if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) { + kfree_skb(skb); + return; + } + + if (!priv->echo_skb[idx]) { + struct sock *srcsk = skb->sk; + + if (atomic_read(&skb->users) != 1) { + struct sk_buff *old_skb = skb; + + skb = skb_clone(old_skb, GFP_ATOMIC); + kfree_skb(old_skb); + if (!skb) + return; + } else + skb_orphan(skb); + + skb->sk = srcsk; + + /* make settings for echo to reduce code in irq context */ + skb->protocol = htons(ETH_P_CAN); + skb->pkt_type = PACKET_BROADCAST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->dev = dev; + + /* save this skb for tx interrupt echo handling */ + priv->echo_skb[idx] = skb; + } else { + /* locking problem with netif_stop_queue() ?? */ + dev_err(dev->dev.parent, "%s: BUG! echo_skb is occupied!\n", + __func__); + kfree_skb(skb); + } +} +EXPORT_SYMBOL_GPL(can_put_echo_skb); + +/* + * Get the skb from the stack and loop it back locally + * + * The function is typically called when the TX done interrupt + * is handled in the device driver. The driver must protect + * access to priv->echo_skb, if necessary. + */ +void can_get_echo_skb(struct net_device *dev, int idx) +{ + struct can_priv *priv = netdev_priv(dev); + + if ((dev->flags & IFF_ECHO) && priv->echo_skb[idx]) { + netif_rx(priv->echo_skb[idx]); + priv->echo_skb[idx] = NULL; + } +} +EXPORT_SYMBOL_GPL(can_get_echo_skb); + +/* + * CAN device restart for bus-off recovery + */ +void can_restart(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct can_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct sk_buff *skb; + struct can_frame *cf; + int err; + + BUG_ON(netif_carrier_ok(dev)); + + /* + * No synchronization needed because the device is bus-off and + * no messages can come in or go out. + */ + can_flush_echo_skb(dev); + + /* send restart message upstream */ + skb = dev_alloc_skb(sizeof(struct can_frame)); + if (skb == NULL) { + err = -ENOMEM; + goto out; + } + skb->dev = dev; + skb->protocol = htons(ETH_P_CAN); + cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); + memset(cf, 0, sizeof(struct can_frame)); + cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; + cf->can_dlc = CAN_ERR_DLC; + + netif_rx(skb); + + dev->last_rx = jiffies; + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + dev_dbg(dev->dev.parent, "restarted\n"); + priv->can_stats.restarts++; + + /* Now restart the device */ + err = priv->do_set_mode(dev, CAN_MODE_START); + +out: + netif_carrier_on(dev); + if (err) + dev_err(dev->dev.parent, "Error %d during restart", err); +} + +int can_restart_now(struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + + /* + * A manual restart is only permitted if automatic restart is + * disabled and the device is in the bus-off state + */ + if (priv->restart_ms) + return -EINVAL; + if (priv->state != CAN_STATE_BUS_OFF) + return -EBUSY; + + /* Runs as soon as possible in the timer context */ + mod_timer(&priv->restart_timer, jiffies); + + return 0; +} + +/* + * CAN bus-off + * + * This functions should be called when the device goes bus-off to + * tell the netif layer that no more packets can be sent or received. + * If enabled, a timer is started to trigger bus-off recovery. + */ +void can_bus_off(struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + + dev_dbg(dev->dev.parent, "bus-off\n"); + + netif_carrier_off(dev); + priv->can_stats.bus_off++; + + if (priv->restart_ms) + mod_timer(&priv->restart_timer, + jiffies + (priv->restart_ms * HZ) / 1000); +} +EXPORT_SYMBOL_GPL(can_bus_off); + +static void can_setup(struct net_device *dev) +{ + dev->type = ARPHRD_CAN; + dev->mtu = sizeof(struct can_frame); + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->tx_queue_len = 10; + + /* New-style flags. */ + dev->flags = IFF_NOARP; + dev->features = NETIF_F_NO_CSUM; +} + +/* + * Allocate and setup space for the CAN network device + */ +struct net_device *alloc_candev(int sizeof_priv) +{ + struct net_device *dev; + struct can_priv *priv; + + dev = alloc_netdev(sizeof_priv, "can%d", can_setup); + if (!dev) + return NULL; + + priv = netdev_priv(dev); + + priv->state = CAN_STATE_STOPPED; + + init_timer(&priv->restart_timer); + + return dev; +} +EXPORT_SYMBOL_GPL(alloc_candev); + +/* + * Free space of the CAN network device + */ +void free_candev(struct net_device *dev) +{ + free_netdev(dev); +} +EXPORT_SYMBOL_GPL(free_candev); + +/* + * Common open function when the device gets opened. + * + * This function should be called in the open function of the device + * driver. + */ +int open_candev(struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + + if (!priv->bittiming.tq && !priv->bittiming.bitrate) { + dev_err(dev->dev.parent, "bit-timing not yet defined\n"); + return -EINVAL; + } + + setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); + + return 0; +} +EXPORT_SYMBOL_GPL(open_candev); + +/* + * Common close function for cleanup before the device gets closed. + * + * This function should be called in the close function of the device + * driver. + */ +void close_candev(struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + + if (del_timer_sync(&priv->restart_timer)) + dev_put(dev); + can_flush_echo_skb(dev); +} +EXPORT_SYMBOL_GPL(close_candev); + +/* + * CAN netlink interface + */ +static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { + [IFLA_CAN_STATE] = { .type = NLA_U32 }, + [IFLA_CAN_CTRLMODE] = { .len = sizeof(struct can_ctrlmode) }, + [IFLA_CAN_RESTART_MS] = { .type = NLA_U32 }, + [IFLA_CAN_RESTART] = { .type = NLA_U32 }, + [IFLA_CAN_BITTIMING] = { .len = sizeof(struct can_bittiming) }, + [IFLA_CAN_BITTIMING_CONST] + = { .len = sizeof(struct can_bittiming_const) }, + [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, +}; + +static int can_changelink(struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct can_priv *priv = netdev_priv(dev); + int err; + + /* We need synchronization with dev->stop() */ + ASSERT_RTNL(); + + if (data[IFLA_CAN_CTRLMODE]) { + struct can_ctrlmode *cm; + + /* Do not allow changing controller mode while running */ + if (dev->flags & IFF_UP) + return -EBUSY; + cm = nla_data(data[IFLA_CAN_CTRLMODE]); + priv->ctrlmode &= ~cm->mask; + priv->ctrlmode |= cm->flags; + } + + if (data[IFLA_CAN_BITTIMING]) { + struct can_bittiming bt; + + /* Do not allow changing bittiming while running */ + if (dev->flags & IFF_UP) + return -EBUSY; + memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); + if ((!bt.bitrate && !bt.tq) || (bt.bitrate && bt.tq)) + return -EINVAL; + err = can_get_bittiming(dev, &bt); + if (err) + return err; + memcpy(&priv->bittiming, &bt, sizeof(bt)); + + if (priv->do_set_bittiming) { + /* Finally, set the bit-timing registers */ + err = priv->do_set_bittiming(dev); + if (err) + return err; + } + } + + if (data[IFLA_CAN_RESTART_MS]) { + /* Do not allow changing restart delay while running */ + if (dev->flags & IFF_UP) + return -EBUSY; + priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]); + } + + if (data[IFLA_CAN_RESTART]) { + /* Do not allow a restart while not running */ + if (!(dev->flags & IFF_UP)) + return -EINVAL; + err = can_restart_now(dev); + if (err) + return err; + } + + return 0; +} + +static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + struct can_ctrlmode cm = {.flags = priv->ctrlmode}; + enum can_state state = priv->state; + + if (priv->do_get_state) + priv->do_get_state(dev, &state); + NLA_PUT_U32(skb, IFLA_CAN_STATE, state); + NLA_PUT(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm); + NLA_PUT_U32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms); + NLA_PUT(skb, IFLA_CAN_BITTIMING, + sizeof(priv->bittiming), &priv->bittiming); + NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock); + if (priv->bittiming_const) + NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST, + sizeof(*priv->bittiming_const), priv->bittiming_const); + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + + NLA_PUT(skb, IFLA_INFO_XSTATS, + sizeof(priv->can_stats), &priv->can_stats); + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static struct rtnl_link_ops can_link_ops __read_mostly = { + .kind = "can", + .maxtype = IFLA_CAN_MAX, + .policy = can_policy, + .setup = can_setup, + .changelink = can_changelink, + .fill_info = can_fill_info, + .fill_xstats = can_fill_xstats, +}; + +/* + * Register the CAN network device + */ +int register_candev(struct net_device *dev) +{ + dev->rtnl_link_ops = &can_link_ops; + return register_netdev(dev); +} +EXPORT_SYMBOL_GPL(register_candev); + +/* + * Unregister the CAN network device + */ +void unregister_candev(struct net_device *dev) +{ + unregister_netdev(dev); +} +EXPORT_SYMBOL_GPL(unregister_candev); + +static __init int can_dev_init(void) +{ + int err; + + err = rtnl_link_register(&can_link_ops); + if (!err) + printk(KERN_INFO MOD_DESC "\n"); + + return err; +} +module_init(can_dev_init); + +static __exit void can_dev_exit(void) +{ + rtnl_link_unregister(&can_link_ops); +} +module_exit(can_dev_exit); + +MODULE_ALIAS_RTNL_LINK("can"); diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile new file mode 100644 index 000000000000..9d0c08da273c --- /dev/null +++ b/drivers/net/can/sja1000/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the SJA1000 CAN controller drivers. +# + +obj-$(CONFIG_CAN_SJA1000) += sja1000.o +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o +obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o +obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o +obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c new file mode 100644 index 000000000000..121b64101d72 --- /dev/null +++ b/drivers/net/can/sja1000/ems_pci.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2007 Wolfgang Grandegger + * Copyright (C) 2008 Markus Plessing + * Copyright (C) 2008 Sebastian Haas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sja1000.h" + +#define DRV_NAME "ems_pci" + +MODULE_AUTHOR("Sebastian Haas "); +MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe CAN cards"); +MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe CAN card"); +MODULE_LICENSE("GPL v2"); + +#define EMS_PCI_MAX_CHAN 2 + +struct ems_pci_card { + int channels; + + struct pci_dev *pci_dev; + struct net_device *net_dev[EMS_PCI_MAX_CHAN]; + + void __iomem *conf_addr; + void __iomem *base_addr; +}; + +#define EMS_PCI_CAN_CLOCK (16000000 / 2) + +/* + * Register definitions and descriptions are from LinCAN 0.3.3. + * + * PSB4610 PITA-2 bridge control registers + */ +#define PITA2_ICR 0x00 /* Interrupt Control Register */ +#define PITA2_ICR_INT0 0x00000002 /* [RC] INT0 Active/Clear */ +#define PITA2_ICR_INT0_EN 0x00020000 /* [RW] Enable INT0 */ + +#define PITA2_MISC 0x1c /* Miscellaneous Register */ +#define PITA2_MISC_CONFIG 0x04000000 /* Multiplexed parallel interface */ + +/* + * 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. + */ +#define EMS_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) + +/* + * In the CDR register, you should set CBP to 1. + * You will probably also want to set the clock divider value to 7 + * (meaning direct oscillator output) because the second SJA1000 chip + * 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_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,}, + {0,} +}; +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) +{ + return readb(card->base_addr + (port * EMS_PCI_PORT_BYTES)); +} + +static u8 ems_pci_read_reg(const struct sja1000_priv *priv, int port) +{ + return readb(priv->reg_base + (port * EMS_PCI_PORT_BYTES)); +} + +static void ems_pci_write_reg(const struct sja1000_priv *priv, int port, u8 val) +{ + writeb(val, priv->reg_base + (port * EMS_PCI_PORT_BYTES)); +} + +static void ems_pci_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); +} + +/* + * Check if a CAN controller is present at the specified location + * by trying to set 'em into the PeliCAN mode + */ +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); + + ems_pci_write_reg(priv, REG_CDR, CDR_PELICAN); + + /* read reset-values */ + res = ems_pci_read_reg(priv, REG_CDR); + + if (res == CDR_PELICAN) + return 1; + + return 0; +} + +static void ems_pci_del_card(struct pci_dev *pdev) +{ + struct ems_pci_card *card = pci_get_drvdata(pdev); + struct net_device *dev; + int i = 0; + + for (i = 0; i < card->channels; i++) { + dev = card->net_dev[i]; + + if (!dev) + continue; + + dev_info(&pdev->dev, "Removing %s.\n", dev->name); + unregister_sja1000dev(dev); + free_sja1000dev(dev); + } + + if (card->base_addr != NULL) + pci_iounmap(card->pci_dev, card->base_addr); + + if (card->conf_addr != NULL) + pci_iounmap(card->pci_dev, card->conf_addr); + + kfree(card); + + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +static void ems_pci_card_reset(struct ems_pci_card *card) +{ + /* Request board reset */ + writeb(0, card->base_addr); +} + +/* + * Probe PCI device for EMS CAN signature and register each available + * CAN channel to SJA1000 Socket-CAN subsystem. + */ +static int __devinit ems_pci_add_card(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct sja1000_priv *priv; + struct net_device *dev; + struct ems_pci_card *card; + int err, i; + + /* Enabling PCI device */ + if (pci_enable_device(pdev) < 0) { + dev_err(&pdev->dev, "Enabling PCI device failed\n"); + return -ENODEV; + } + + /* Allocating card structures to hold addresses, ... */ + card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL); + if (card == NULL) { + dev_err(&pdev->dev, "Unable to allocate memory\n"); + pci_disable_device(pdev); + return -ENOMEM; + } + + pci_set_drvdata(pdev, card); + + card->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 (card->conf_addr == NULL) { + err = -ENOMEM; + goto failure_cleanup; + } + + card->base_addr = pci_iomap(pdev, 1, EMS_PCI_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; + } + + ems_pci_card_reset(card); + + /* Detect available channels */ + for (i = 0; i < EMS_PCI_MAX_CHAN; i++) { + dev = alloc_sja1000dev(0); + if (dev == NULL) { + err = -ENOMEM; + goto failure_cleanup; + } + + card->net_dev[i] = dev; + priv = netdev_priv(dev); + priv->priv = card; + priv->irq_flags = IRQF_SHARED; + + dev->irq = pdev->irq; + priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET + + (i * EMS_PCI_CAN_CTRL_SIZE); + + /* 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); + + /* Register SJA1000 device */ + err = register_sja1000dev(dev); + if (err) { + dev_err(&pdev->dev, "Registering device failed " + "(err=%d)\n", err); + free_sja1000dev(dev); + goto failure_cleanup; + } + + card->channels++; + + dev_info(&pdev->dev, "Channel #%d at 0x%p, irq %d\n", + i + 1, priv->reg_base, dev->irq); + } else { + free_sja1000dev(dev); + } + } + + return 0; + +failure_cleanup: + dev_err(&pdev->dev, "Error: %d. Cleaning Up.\n", err); + + ems_pci_del_card(pdev); + + return err; +} + +static struct pci_driver ems_pci_driver = { + .name = DRV_NAME, + .id_table = ems_pci_tbl, + .probe = ems_pci_add_card, + .remove = ems_pci_del_card, +}; + +static int __init ems_pci_init(void) +{ + return pci_register_driver(&ems_pci_driver); +} + +static void __exit ems_pci_exit(void) +{ + pci_unregister_driver(&ems_pci_driver); +} + +module_init(ems_pci_init); +module_exit(ems_pci_exit); + diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c new file mode 100644 index 000000000000..7dd7769b9713 --- /dev/null +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2008 Per Dalen + * + * Parts of this software are based on (derived) the following: + * + * - Kvaser linux driver, version 4.72 BETA + * Copyright (C) 2002-2007 KVASER AB + * + * - Lincan driver, version 0.3.3, OCERA project + * Copyright (C) 2004 Pavel Pisa + * Copyright (C) 2001 Arnaud Westenberg + * + * - Socketcan SJA1000 drivers + * Copyright (C) 2007 Wolfgang Grandegger + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, + * 38106 Braunschweig, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sja1000.h" + +#define DRV_NAME "kvaser_pci" + +MODULE_AUTHOR("Per Dalen "); +MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards"); +MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card"); +MODULE_LICENSE("GPL v2"); + +#define MAX_NO_OF_CHANNELS 4 /* max no of channels on a single card */ + +struct kvaser_pci { + int channel; + struct pci_dev *pci_dev; + struct net_device *slave_dev[MAX_NO_OF_CHANNELS-1]; + void __iomem *conf_addr; + void __iomem *res_addr; + int no_channels; + u8 xilinx_ver; +}; + +#define KVASER_PCI_CAN_CLOCK (16000000 / 2) + +/* + * 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. + */ +#define KVASER_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) + +/* + * In the CDR register, you should set CBP to 1. + * You will probably also want to set the clock divider value to 0 + * (meaning divide-by-2), the Pelican bit, and the clock-off bit + * (you will have no need for CLKOUT anyway). + */ +#define KVASER_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) + +/* + * These register values are valid for revision 14 of the Xilinx logic. + */ +#define XILINX_VERINT 7 /* Lower nibble simulate interrupts, + high nibble version number. */ + +#define XILINX_PRESUMED_VERSION 14 + +/* + * Important S5920 registers + */ +#define S5920_INTCSR 0x38 +#define S5920_PTCR 0x60 +#define INTCSR_ADDON_INTENABLE_M 0x2000 + + +#define KVASER_PCI_PORT_BYTES 0x20 + +#define PCI_CONFIG_PORT_SIZE 0x80 /* size of the config io-memory */ +#define PCI_PORT_SIZE 0x80 /* size of a channel io-memory */ +#define PCI_PORT_XILINX_SIZE 0x08 /* size of a xilinx io-memory */ + +#define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */ +#define KVASER_PCI_DEVICE_ID1 0x8406 + +#define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */ +#define KVASER_PCI_DEVICE_ID2 0x0008 + +static struct pci_device_id kvaser_pci_tbl[] = { + {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,}, + {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,}, + { 0,} +}; + +MODULE_DEVICE_TABLE(pci, kvaser_pci_tbl); + +static u8 kvaser_pci_read_reg(const struct sja1000_priv *priv, int port) +{ + return ioread8(priv->reg_base + port); +} + +static void kvaser_pci_write_reg(const struct sja1000_priv *priv, + int port, u8 val) +{ + iowrite8(val, priv->reg_base + port); +} + +static void kvaser_pci_disable_irq(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + struct kvaser_pci *board = priv->priv; + u32 intcsr; + + /* Disable interrupts from card */ + intcsr = ioread32(board->conf_addr + S5920_INTCSR); + intcsr &= ~INTCSR_ADDON_INTENABLE_M; + iowrite32(intcsr, board->conf_addr + S5920_INTCSR); +} + +static void kvaser_pci_enable_irq(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + struct kvaser_pci *board = priv->priv; + u32 tmp_en_io; + + /* Enable interrupts from card */ + tmp_en_io = ioread32(board->conf_addr + S5920_INTCSR); + tmp_en_io |= INTCSR_ADDON_INTENABLE_M; + iowrite32(tmp_en_io, board->conf_addr + S5920_INTCSR); +} + +static int number_of_sja1000_chip(void __iomem *base_addr) +{ + u8 status; + int i; + + for (i = 0; i < MAX_NO_OF_CHANNELS; i++) { + /* reset chip */ + iowrite8(MOD_RM, base_addr + + (i * KVASER_PCI_PORT_BYTES) + REG_MOD); + status = ioread8(base_addr + + (i * KVASER_PCI_PORT_BYTES) + REG_MOD); + /* check reset bit */ + if (!(status & MOD_RM)) + break; + } + + return i; +} + +static void kvaser_pci_del_chan(struct net_device *dev) +{ + struct sja1000_priv *priv; + struct kvaser_pci *board; + int i; + + if (!dev) + return; + priv = netdev_priv(dev); + board = priv->priv; + if (!board) + return; + + dev_info(&board->pci_dev->dev, "Removing device %s\n", + dev->name); + + /* Disable PCI interrupts */ + kvaser_pci_disable_irq(dev); + + for (i = 0; i < board->no_channels - 1; i++) { + if (board->slave_dev[i]) { + dev_info(&board->pci_dev->dev, "Removing device %s\n", + board->slave_dev[i]->name); + unregister_sja1000dev(board->slave_dev[i]); + free_sja1000dev(board->slave_dev[i]); + } + } + unregister_sja1000dev(dev); + + pci_iounmap(board->pci_dev, priv->reg_base); + pci_iounmap(board->pci_dev, board->conf_addr); + pci_iounmap(board->pci_dev, board->res_addr); + + free_sja1000dev(dev); +} + +static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel, + struct net_device **master_dev, + void __iomem *conf_addr, + void __iomem *res_addr, + void __iomem *base_addr) +{ + struct net_device *dev; + struct sja1000_priv *priv; + struct kvaser_pci *board; + int err, init_step; + + dev = alloc_sja1000dev(sizeof(struct kvaser_pci)); + if (dev == NULL) + return -ENOMEM; + + priv = netdev_priv(dev); + board = priv->priv; + + board->pci_dev = pdev; + board->channel = channel; + + /* S5920 */ + board->conf_addr = conf_addr; + + /* XILINX board wide address */ + board->res_addr = res_addr; + + if (channel == 0) { + board->xilinx_ver = + ioread8(board->res_addr + XILINX_VERINT) >> 4; + init_step = 2; + + /* Assert PTADR# - we're in passive mode so the other bits are + not important */ + iowrite32(0x80808080UL, board->conf_addr + S5920_PTCR); + + /* Enable interrupts from card */ + kvaser_pci_enable_irq(dev); + } else { + struct sja1000_priv *master_priv = netdev_priv(*master_dev); + struct kvaser_pci *master_board = master_priv->priv; + master_board->slave_dev[channel - 1] = dev; + master_board->no_channels = channel + 1; + board->xilinx_ver = master_board->xilinx_ver; + } + + priv->reg_base = base_addr + channel * KVASER_PCI_PORT_BYTES; + + priv->read_reg = kvaser_pci_read_reg; + priv->write_reg = kvaser_pci_write_reg; + + priv->can.clock.freq = KVASER_PCI_CAN_CLOCK; + + priv->ocr = KVASER_PCI_OCR; + priv->cdr = KVASER_PCI_CDR; + + priv->irq_flags = IRQF_SHARED; + dev->irq = pdev->irq; + + init_step = 4; + + dev_info(&pdev->dev, "reg_base=%p conf_addr=%p irq=%d\n", + priv->reg_base, board->conf_addr, dev->irq); + + SET_NETDEV_DEV(dev, &pdev->dev); + + /* Register SJA1000 device */ + err = register_sja1000dev(dev); + if (err) { + dev_err(&pdev->dev, "Registering device failed (err=%d)\n", + err); + goto failure; + } + + if (channel == 0) + *master_dev = dev; + + return 0; + +failure: + kvaser_pci_del_chan(dev); + return err; +} + +static int __devinit kvaser_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int err; + struct net_device *master_dev = NULL; + struct sja1000_priv *priv; + struct kvaser_pci *board; + int no_channels; + void __iomem *base_addr = NULL; + void __iomem *conf_addr = NULL; + void __iomem *res_addr = NULL; + int i; + + dev_info(&pdev->dev, "initializing device %04x:%04x\n", + pdev->vendor, pdev->device); + + err = pci_enable_device(pdev); + if (err) + goto failure; + + err = pci_request_regions(pdev, DRV_NAME); + if (err) + goto failure_release_pci; + + /* S5920 */ + conf_addr = pci_iomap(pdev, 0, PCI_CONFIG_PORT_SIZE); + if (conf_addr == NULL) { + err = -ENODEV; + goto failure_release_regions; + } + + /* XILINX board wide address */ + res_addr = pci_iomap(pdev, 2, PCI_PORT_XILINX_SIZE); + if (res_addr == NULL) { + err = -ENOMEM; + goto failure_iounmap; + } + + base_addr = pci_iomap(pdev, 1, PCI_PORT_SIZE); + if (base_addr == NULL) { + err = -ENOMEM; + goto failure_iounmap; + } + + no_channels = number_of_sja1000_chip(base_addr); + if (no_channels == 0) { + err = -ENOMEM; + goto failure_iounmap; + } + + for (i = 0; i < no_channels; i++) { + err = kvaser_pci_add_chan(pdev, i, &master_dev, + conf_addr, res_addr, + base_addr); + if (err) + goto failure_cleanup; + } + + priv = netdev_priv(master_dev); + board = priv->priv; + + dev_info(&pdev->dev, "xilinx version=%d number of channels=%d\n", + board->xilinx_ver, board->no_channels); + + pci_set_drvdata(pdev, master_dev); + return 0; + +failure_cleanup: + kvaser_pci_del_chan(master_dev); + +failure_iounmap: + if (conf_addr != NULL) + pci_iounmap(pdev, conf_addr); + if (res_addr != NULL) + pci_iounmap(pdev, res_addr); + if (base_addr != NULL) + pci_iounmap(pdev, base_addr); + +failure_release_regions: + pci_release_regions(pdev); + +failure_release_pci: + pci_disable_device(pdev); + +failure: + return err; + +} + +static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + kvaser_pci_del_chan(dev); + + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +static struct pci_driver kvaser_pci_driver = { + .name = DRV_NAME, + .id_table = kvaser_pci_tbl, + .probe = kvaser_pci_init_one, + .remove = __devexit_p(kvaser_pci_remove_one), +}; + +static int __init kvaser_pci_init(void) +{ + return pci_register_driver(&kvaser_pci_driver); +} + +static void __exit kvaser_pci_exit(void) +{ + pci_unregister_driver(&kvaser_pci_driver); +} + +module_init(kvaser_pci_init); +module_exit(kvaser_pci_exit); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c new file mode 100644 index 000000000000..571f133a8fec --- /dev/null +++ b/drivers/net/can/sja1000/sja1000.c @@ -0,0 +1,637 @@ +/* + * sja1000.c - Philips SJA1000 network device driver + * + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, + * 38106 Braunschweig, GERMANY + * + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sja1000.h" + +#define DRV_NAME "sja1000" + +MODULE_AUTHOR("Oliver Hartkopp "); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver"); + +static struct can_bittiming_const sja1000_bittiming_const = { + .name = DRV_NAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; + +static int sja1000_probe_chip(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + + if (priv->reg_base && (priv->read_reg(priv, 0) == 0xFF)) { + printk(KERN_INFO "%s: probing @0x%lX failed\n", + DRV_NAME, dev->base_addr); + return 0; + } + return -1; +} + +static void set_reset_mode(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + unsigned char status = priv->read_reg(priv, REG_MOD); + int i; + + /* disable interrupts */ + priv->write_reg(priv, REG_IER, IRQ_OFF); + + for (i = 0; i < 100; i++) { + /* check reset bit */ + if (status & MOD_RM) { + priv->can.state = CAN_STATE_STOPPED; + return; + } + + priv->write_reg(priv, REG_MOD, MOD_RM); /* reset chip */ + udelay(10); + status = priv->read_reg(priv, REG_MOD); + } + + dev_err(dev->dev.parent, "setting SJA1000 into reset mode failed!\n"); +} + +static void set_normal_mode(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + unsigned char status = priv->read_reg(priv, REG_MOD); + int i; + + for (i = 0; i < 100; i++) { + /* check reset bit */ + if ((status & MOD_RM) == 0) { + priv->can.state = CAN_STATE_ERROR_ACTIVE; + /* enable all interrupts */ + priv->write_reg(priv, REG_IER, IRQ_ALL); + return; + } + + /* set chip to normal mode */ + priv->write_reg(priv, REG_MOD, 0x00); + udelay(10); + status = priv->read_reg(priv, REG_MOD); + } + + dev_err(dev->dev.parent, "setting SJA1000 into normal mode failed!\n"); +} + +static void sja1000_start(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + + /* leave reset mode */ + if (priv->can.state != CAN_STATE_STOPPED) + set_reset_mode(dev); + + /* Clear error counters and error code capture */ + priv->write_reg(priv, REG_TXERR, 0x0); + priv->write_reg(priv, REG_RXERR, 0x0); + priv->read_reg(priv, REG_ECC); + + /* leave reset mode */ + set_normal_mode(dev); +} + +static int sja1000_set_mode(struct net_device *dev, enum can_mode mode) +{ + struct sja1000_priv *priv = netdev_priv(dev); + + if (!priv->open_time) + return -EINVAL; + + switch (mode) { + case CAN_MODE_START: + sja1000_start(dev); + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int sja1000_set_bittiming(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + struct can_bittiming *bt = &priv->can.bittiming; + u8 btr0, btr1; + + btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); + btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) | + (((bt->phase_seg2 - 1) & 0x7) << 4); + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + btr1 |= 0x80; + + dev_info(dev->dev.parent, + "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1); + + priv->write_reg(priv, REG_BTR0, btr0); + priv->write_reg(priv, REG_BTR1, btr1); + + return 0; +} + +/* + * initialize SJA1000 chip: + * - reset chip + * - set output mode + * - set baudrate + * - enable interrupts + * - start operating mode + */ +static void chipset_init(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + + /* set clock divider and output control register */ + priv->write_reg(priv, REG_CDR, priv->cdr | CDR_PELICAN); + + /* set acceptance filter (accept all) */ + priv->write_reg(priv, REG_ACCC0, 0x00); + priv->write_reg(priv, REG_ACCC1, 0x00); + priv->write_reg(priv, REG_ACCC2, 0x00); + priv->write_reg(priv, REG_ACCC3, 0x00); + + priv->write_reg(priv, REG_ACCM0, 0xFF); + priv->write_reg(priv, REG_ACCM1, 0xFF); + priv->write_reg(priv, REG_ACCM2, 0xFF); + priv->write_reg(priv, REG_ACCM3, 0xFF); + + priv->write_reg(priv, REG_OCR, priv->ocr | OCR_MODE_NORMAL); +} + +/* + * transmit a CAN message + * message layout in the sk_buff should be like this: + * xx xx xx xx ff ll 00 11 22 33 44 55 66 77 + * [ can-id ] [flags] [len] [can data (up to 8 bytes] + */ +static int sja1000_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf = (struct can_frame *)skb->data; + uint8_t fi; + uint8_t dlc; + canid_t id; + uint8_t dreg; + int i; + + netif_stop_queue(dev); + + fi = dlc = cf->can_dlc; + id = cf->can_id; + + if (id & CAN_RTR_FLAG) + fi |= FI_RTR; + + if (id & CAN_EFF_FLAG) { + fi |= FI_FF; + dreg = EFF_BUF; + priv->write_reg(priv, REG_FI, fi); + priv->write_reg(priv, REG_ID1, (id & 0x1fe00000) >> (5 + 16)); + priv->write_reg(priv, REG_ID2, (id & 0x001fe000) >> (5 + 8)); + priv->write_reg(priv, REG_ID3, (id & 0x00001fe0) >> 5); + priv->write_reg(priv, REG_ID4, (id & 0x0000001f) << 3); + } else { + dreg = SFF_BUF; + priv->write_reg(priv, REG_FI, fi); + priv->write_reg(priv, REG_ID1, (id & 0x000007f8) >> 3); + priv->write_reg(priv, REG_ID2, (id & 0x00000007) << 5); + } + + for (i = 0; i < dlc; i++) + priv->write_reg(priv, dreg++, cf->data[i]); + + stats->tx_bytes += dlc; + dev->trans_start = jiffies; + + can_put_echo_skb(skb, dev, 0); + + priv->write_reg(priv, REG_CMR, CMD_TR); + + return 0; +} + +static void sja1000_rx(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf; + struct sk_buff *skb; + uint8_t fi; + uint8_t dreg; + canid_t id; + uint8_t dlc; + int i; + + skb = dev_alloc_skb(sizeof(struct can_frame)); + if (skb == NULL) + return; + skb->dev = dev; + skb->protocol = htons(ETH_P_CAN); + + fi = priv->read_reg(priv, REG_FI); + dlc = fi & 0x0F; + + if (fi & FI_FF) { + /* extended frame format (EFF) */ + dreg = EFF_BUF; + id = (priv->read_reg(priv, REG_ID1) << (5 + 16)) + | (priv->read_reg(priv, REG_ID2) << (5 + 8)) + | (priv->read_reg(priv, REG_ID3) << 5) + | (priv->read_reg(priv, REG_ID4) >> 3); + id |= CAN_EFF_FLAG; + } else { + /* standard frame format (SFF) */ + dreg = SFF_BUF; + id = (priv->read_reg(priv, REG_ID1) << 3) + | (priv->read_reg(priv, REG_ID2) >> 5); + } + + if (fi & FI_RTR) + id |= CAN_RTR_FLAG; + + cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); + memset(cf, 0, sizeof(struct can_frame)); + cf->can_id = id; + cf->can_dlc = dlc; + for (i = 0; i < dlc; i++) + cf->data[i] = priv->read_reg(priv, dreg++); + + while (i < 8) + cf->data[i++] = 0; + + /* release receive buffer */ + priv->write_reg(priv, REG_CMR, CMD_RRB); + + netif_rx(skb); + + dev->last_rx = jiffies; + stats->rx_packets++; + stats->rx_bytes += dlc; +} + +static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) +{ + struct sja1000_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf; + struct sk_buff *skb; + enum can_state state = priv->can.state; + uint8_t ecc, alc; + + skb = dev_alloc_skb(sizeof(struct can_frame)); + if (skb == NULL) + return -ENOMEM; + skb->dev = dev; + skb->protocol = htons(ETH_P_CAN); + cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); + memset(cf, 0, sizeof(struct can_frame)); + cf->can_id = CAN_ERR_FLAG; + cf->can_dlc = CAN_ERR_DLC; + + if (isrc & IRQ_DOI) { + /* data overrun interrupt */ + dev_dbg(dev->dev.parent, "data overrun interrupt\n"); + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + stats->rx_over_errors++; + stats->rx_errors++; + priv->write_reg(priv, REG_CMR, CMD_CDO); /* clear bit */ + } + + if (isrc & IRQ_EI) { + /* error warning interrupt */ + dev_dbg(dev->dev.parent, "error warning interrupt\n"); + + if (status & SR_BS) { + state = CAN_STATE_BUS_OFF; + cf->can_id |= CAN_ERR_BUSOFF; + can_bus_off(dev); + } else if (status & SR_ES) { + state = CAN_STATE_ERROR_WARNING; + } else + state = CAN_STATE_ERROR_ACTIVE; + } + if (isrc & IRQ_BEI) { + /* bus error interrupt */ + priv->can.can_stats.bus_error++; + stats->rx_errors++; + + ecc = priv->read_reg(priv, REG_ECC); + + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + switch (ecc & ECC_MASK) { + case ECC_BIT: + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case ECC_FORM: + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case ECC_STUFF: + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + default: + cf->data[2] |= CAN_ERR_PROT_UNSPEC; + cf->data[3] = ecc & ECC_SEG; + break; + } + /* Error occured during transmission? */ + if ((ecc & ECC_DIR) == 0) + cf->data[2] |= CAN_ERR_PROT_TX; + } + if (isrc & IRQ_EPI) { + /* error passive interrupt */ + dev_dbg(dev->dev.parent, "error passive interrupt\n"); + if (status & SR_ES) + state = CAN_STATE_ERROR_PASSIVE; + else + state = CAN_STATE_ERROR_ACTIVE; + } + if (isrc & IRQ_ALI) { + /* arbitration lost interrupt */ + dev_dbg(dev->dev.parent, "arbitration lost interrupt\n"); + alc = priv->read_reg(priv, REG_ALC); + priv->can.can_stats.arbitration_lost++; + stats->rx_errors++; + cf->can_id |= CAN_ERR_LOSTARB; + cf->data[0] = alc & 0x1f; + } + + if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || + state == CAN_STATE_ERROR_PASSIVE)) { + uint8_t rxerr = priv->read_reg(priv, REG_RXERR); + uint8_t txerr = priv->read_reg(priv, REG_TXERR); + cf->can_id |= CAN_ERR_CRTL; + if (state == CAN_STATE_ERROR_WARNING) { + priv->can.can_stats.error_warning++; + cf->data[1] = (txerr > rxerr) ? + CAN_ERR_CRTL_TX_WARNING : + CAN_ERR_CRTL_RX_WARNING; + } else { + priv->can.can_stats.error_passive++; + cf->data[1] = (txerr > rxerr) ? + CAN_ERR_CRTL_TX_PASSIVE : + CAN_ERR_CRTL_RX_PASSIVE; + } + } + + priv->can.state = state; + + netif_rx(skb); + + dev->last_rx = jiffies; + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + + return 0; +} + +irqreturn_t sja1000_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + struct sja1000_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + uint8_t isrc, status; + int n = 0; + + /* Shared interrupts and IRQ off? */ + if (priv->read_reg(priv, REG_IER) == IRQ_OFF) + return IRQ_NONE; + + if (priv->pre_irq) + priv->pre_irq(priv); + + while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) { + n++; + status = priv->read_reg(priv, REG_SR); + + if (isrc & IRQ_WUI) + dev_warn(dev->dev.parent, "wakeup interrupt\n"); + + if (isrc & IRQ_TI) { + /* transmission complete interrupt */ + stats->tx_packets++; + can_get_echo_skb(dev, 0); + netif_wake_queue(dev); + } + if (isrc & IRQ_RI) { + /* receive interrupt */ + while (status & SR_RBS) { + sja1000_rx(dev); + status = priv->read_reg(priv, REG_SR); + } + } + if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { + /* error interrupt */ + if (sja1000_err(dev, isrc, status)) + break; + } + } + + if (priv->post_irq) + priv->post_irq(priv); + + if (n >= SJA1000_MAX_IRQ) + dev_dbg(dev->dev.parent, "%d messages handled in ISR", n); + + return (n) ? IRQ_HANDLED : IRQ_NONE; +} +EXPORT_SYMBOL_GPL(sja1000_interrupt); + +static int sja1000_open(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + int err; + + /* set chip into reset mode */ + set_reset_mode(dev); + + /* common open */ + err = open_candev(dev); + if (err) + return err; + + /* register interrupt handler, if not done by the device driver */ + if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) { + err = request_irq(dev->irq, &sja1000_interrupt, priv->irq_flags, + dev->name, (void *)dev); + if (err) { + close_candev(dev); + return -EAGAIN; + } + } + + /* init and start chi */ + sja1000_start(dev); + priv->open_time = jiffies; + + netif_start_queue(dev); + + return 0; +} + +static int sja1000_close(struct net_device *dev) +{ + struct sja1000_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + set_reset_mode(dev); + + if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) + free_irq(dev->irq, (void *)dev); + + close_candev(dev); + + priv->open_time = 0; + + return 0; +} + +struct net_device *alloc_sja1000dev(int sizeof_priv) +{ + struct net_device *dev; + struct sja1000_priv *priv; + + dev = alloc_candev(sizeof(struct sja1000_priv) + sizeof_priv); + if (!dev) + return NULL; + + priv = netdev_priv(dev); + + priv->dev = dev; + priv->can.bittiming_const = &sja1000_bittiming_const; + priv->can.do_set_bittiming = sja1000_set_bittiming; + priv->can.do_set_mode = sja1000_set_mode; + + if (sizeof_priv) + priv->priv = (void *)priv + sizeof(struct sja1000_priv); + + return dev; +} +EXPORT_SYMBOL_GPL(alloc_sja1000dev); + +void free_sja1000dev(struct net_device *dev) +{ + free_candev(dev); +} +EXPORT_SYMBOL_GPL(free_sja1000dev); + +static const struct net_device_ops sja1000_netdev_ops = { + .ndo_open = sja1000_open, + .ndo_stop = sja1000_close, + .ndo_start_xmit = sja1000_start_xmit, +}; + +int register_sja1000dev(struct net_device *dev) +{ + if (!sja1000_probe_chip(dev)) + return -ENODEV; + + dev->flags |= IFF_ECHO; /* we support local echo */ + dev->netdev_ops = &sja1000_netdev_ops; + + set_reset_mode(dev); + chipset_init(dev); + + return register_candev(dev); +} +EXPORT_SYMBOL_GPL(register_sja1000dev); + +void unregister_sja1000dev(struct net_device *dev) +{ + set_reset_mode(dev); + unregister_candev(dev); +} +EXPORT_SYMBOL_GPL(unregister_sja1000dev); + +static __init int sja1000_init(void) +{ + printk(KERN_INFO "%s CAN netdevice driver\n", DRV_NAME); + + return 0; +} + +module_init(sja1000_init); + +static __exit void sja1000_exit(void) +{ + printk(KERN_INFO "%s: driver removed\n", DRV_NAME); +} + +module_exit(sja1000_exit); diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h new file mode 100644 index 000000000000..302d2c763ad7 --- /dev/null +++ b/drivers/net/can/sja1000/sja1000.h @@ -0,0 +1,181 @@ +/* + * sja1000.h - Philips SJA1000 network device driver + * + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, + * 38106 Braunschweig, GERMANY + * + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Send feedback to + * + */ + +#ifndef SJA1000_DEV_H +#define SJA1000_DEV_H + +#include +#include + +#define SJA1000_MAX_IRQ 20 /* max. number of interrupts handled in ISR */ + +/* SJA1000 registers - manual section 6.4 (Pelican Mode) */ +#define REG_MOD 0x00 +#define REG_CMR 0x01 +#define REG_SR 0x02 +#define REG_IR 0x03 +#define REG_IER 0x04 +#define REG_ALC 0x0B +#define REG_ECC 0x0C +#define REG_EWL 0x0D +#define REG_RXERR 0x0E +#define REG_TXERR 0x0F +#define REG_ACCC0 0x10 +#define REG_ACCC1 0x11 +#define REG_ACCC2 0x12 +#define REG_ACCC3 0x13 +#define REG_ACCM0 0x14 +#define REG_ACCM1 0x15 +#define REG_ACCM2 0x16 +#define REG_ACCM3 0x17 +#define REG_RMC 0x1D +#define REG_RBSA 0x1E + +/* Common registers - manual section 6.5 */ +#define REG_BTR0 0x06 +#define REG_BTR1 0x07 +#define REG_OCR 0x08 +#define REG_CDR 0x1F + +#define REG_FI 0x10 +#define SFF_BUF 0x13 +#define EFF_BUF 0x15 + +#define FI_FF 0x80 +#define FI_RTR 0x40 + +#define REG_ID1 0x11 +#define REG_ID2 0x12 +#define REG_ID3 0x13 +#define REG_ID4 0x14 + +#define CAN_RAM 0x20 + +/* mode register */ +#define MOD_RM 0x01 +#define MOD_LOM 0x02 +#define MOD_STM 0x04 +#define MOD_AFM 0x08 +#define MOD_SM 0x10 + +/* commands */ +#define CMD_SRR 0x10 +#define CMD_CDO 0x08 +#define CMD_RRB 0x04 +#define CMD_AT 0x02 +#define CMD_TR 0x01 + +/* interrupt sources */ +#define IRQ_BEI 0x80 +#define IRQ_ALI 0x40 +#define IRQ_EPI 0x20 +#define IRQ_WUI 0x10 +#define IRQ_DOI 0x08 +#define IRQ_EI 0x04 +#define IRQ_TI 0x02 +#define IRQ_RI 0x01 +#define IRQ_ALL 0xFF +#define IRQ_OFF 0x00 + +/* status register content */ +#define SR_BS 0x80 +#define SR_ES 0x40 +#define SR_TS 0x20 +#define SR_RS 0x10 +#define SR_TCS 0x08 +#define SR_TBS 0x04 +#define SR_DOS 0x02 +#define SR_RBS 0x01 + +#define SR_CRIT (SR_BS|SR_ES) + +/* ECC register */ +#define ECC_SEG 0x1F +#define ECC_DIR 0x20 +#define ECC_ERR 6 +#define ECC_BIT 0x00 +#define ECC_FORM 0x40 +#define ECC_STUFF 0x80 +#define ECC_MASK 0xc0 + +/* + * Flags for sja1000priv.flags + */ +#define SJA1000_CUSTOM_IRQ_HANDLER 0x1 + +/* + * SJA1000 private data structure + */ +struct sja1000_priv { + struct can_priv can; /* must be the first member */ + int open_time; + struct sk_buff *echo_skb; + + /* the lower-layer is responsible for appropriate locking */ + u8 (*read_reg) (const struct sja1000_priv *priv, int reg); + void (*write_reg) (const struct sja1000_priv *priv, int reg, u8 val); + void (*pre_irq) (const struct sja1000_priv *priv); + void (*post_irq) (const struct sja1000_priv *priv); + + void *priv; /* for board-specific data */ + struct net_device *dev; + + void __iomem *reg_base; /* ioremap'ed address to registers */ + unsigned long irq_flags; /* for request_irq() */ + + u16 flags; /* custom mode flags */ + u8 ocr; /* output control register */ + u8 cdr; /* clock divider register */ +}; + +struct net_device *alloc_sja1000dev(int sizeof_priv); +void free_sja1000dev(struct net_device *dev); +int register_sja1000dev(struct net_device *dev); +void unregister_sja1000dev(struct net_device *dev); + +irqreturn_t sja1000_interrupt(int irq, void *dev_id); + +#endif /* SJA1000_DEV_H */ diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c new file mode 100644 index 000000000000..3373560405ba --- /dev/null +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -0,0 +1,235 @@ +/* + * Driver for SJA1000 CAN controllers on the OpenFirmware platform bus + * + * Copyright (C) 2008-2009 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* This is a generic driver for SJA1000 chips on the OpenFirmware platform + * bus found on embedded PowerPC systems. You need a SJA1000 CAN node + * definition in your flattened device tree source (DTS) file similar to: + * + * can@3,100 { + * compatible = "nxp,sja1000"; + * reg = <3 0x100 0x80>; + * interrupts = <2 0>; + * interrupt-parent = <&mpic>; + * nxp,external-clock-frequency = <16000000>; + * }; + * + * See "Documentation/powerpc/dts-bindings/can/sja1000.txt" for further + * information. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "sja1000.h" + +#define DRV_NAME "sja1000_of_platform" + +MODULE_AUTHOR("Wolfgang Grandegger "); +MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the OF platform bus"); +MODULE_LICENSE("GPL v2"); + +#define SJA1000_OFP_CAN_CLOCK (16000000 / 2) + +#define SJA1000_OFP_OCR OCR_TX0_PULLDOWN +#define SJA1000_OFP_CDR (CDR_CBP | CDR_CLK_OFF) + +static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg) +{ + return in_8(priv->reg_base + reg); +} + +static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, + int reg, u8 val) +{ + out_8(priv->reg_base + reg, val); +} + +static int __devexit sja1000_ofp_remove(struct of_device *ofdev) +{ + struct net_device *dev = dev_get_drvdata(&ofdev->dev); + struct sja1000_priv *priv = netdev_priv(dev); + struct device_node *np = ofdev->node; + struct resource res; + + dev_set_drvdata(&ofdev->dev, NULL); + + unregister_sja1000dev(dev); + free_sja1000dev(dev); + iounmap(priv->reg_base); + irq_dispose_mapping(dev->irq); + + of_address_to_resource(np, 0, &res); + release_mem_region(res.start, resource_size(&res)); + + return 0; +} + +static int __devinit sja1000_ofp_probe(struct of_device *ofdev, + const struct of_device_id *id) +{ + struct device_node *np = ofdev->node; + struct net_device *dev; + struct sja1000_priv *priv; + struct resource res; + const u32 *prop; + int err, irq, res_size, prop_size; + void __iomem *base; + + err = of_address_to_resource(np, 0, &res); + if (err) { + dev_err(&ofdev->dev, "invalid address\n"); + return err; + } + + res_size = resource_size(&res); + + if (!request_mem_region(res.start, res_size, DRV_NAME)) { + dev_err(&ofdev->dev, "couldn't request %#llx..%#llx\n", + (unsigned long long)res.start, + (unsigned long long)res.end); + return -EBUSY; + } + + base = ioremap_nocache(res.start, res_size); + if (!base) { + dev_err(&ofdev->dev, "couldn't ioremap %#llx..%#llx\n", + (unsigned long long)res.start, + (unsigned long long)res.end); + err = -ENOMEM; + goto exit_release_mem; + } + + irq = irq_of_parse_and_map(np, 0); + if (irq == NO_IRQ) { + dev_err(&ofdev->dev, "no irq found\n"); + err = -ENODEV; + goto exit_unmap_mem; + } + + dev = alloc_sja1000dev(0); + if (!dev) { + err = -ENOMEM; + goto exit_dispose_irq; + } + + priv = netdev_priv(dev); + + priv->read_reg = sja1000_ofp_read_reg; + priv->write_reg = sja1000_ofp_write_reg; + + prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size); + if (prop && (prop_size == sizeof(u32))) + priv->can.clock.freq = *prop / 2; + else + priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */ + + prop = of_get_property(np, "nxp,tx-output-mode", &prop_size); + if (prop && (prop_size == sizeof(u32))) + priv->ocr |= *prop & OCR_MODE_MASK; + else + priv->ocr |= OCR_MODE_NORMAL; /* default */ + + prop = of_get_property(np, "nxp,tx-output-config", &prop_size); + if (prop && (prop_size == sizeof(u32))) + priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK; + else + priv->ocr |= OCR_TX0_PULLDOWN; /* default */ + + prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size); + if (prop && (prop_size == sizeof(u32)) && *prop) { + u32 divider = priv->can.clock.freq * 2 / *prop; + + if (divider > 1) + priv->cdr |= divider / 2 - 1; + else + priv->cdr |= CDR_CLKOUT_MASK; + } else { + priv->cdr |= CDR_CLK_OFF; /* default */ + } + + prop = of_get_property(np, "nxp,no-comparator-bypass", NULL); + if (!prop) + priv->cdr |= CDR_CBP; /* default */ + + priv->irq_flags = IRQF_SHARED; + priv->reg_base = base; + + dev->irq = irq; + + dev_info(&ofdev->dev, + "reg_base=0x%p irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n", + priv->reg_base, dev->irq, priv->can.clock.freq, + priv->ocr, priv->cdr); + + dev_set_drvdata(&ofdev->dev, dev); + SET_NETDEV_DEV(dev, &ofdev->dev); + + err = register_sja1000dev(dev); + if (err) { + dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", + DRV_NAME, err); + goto exit_free_sja1000; + } + + return 0; + +exit_free_sja1000: + free_sja1000dev(dev); +exit_dispose_irq: + irq_dispose_mapping(irq); +exit_unmap_mem: + iounmap(base); +exit_release_mem: + release_mem_region(res.start, res_size); + + return err; +} + +static struct of_device_id __devinitdata sja1000_ofp_table[] = { + {.compatible = "nxp,sja1000"}, + {}, +}; + +static struct of_platform_driver sja1000_ofp_driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + .probe = sja1000_ofp_probe, + .remove = __devexit_p(sja1000_ofp_remove), + .match_table = sja1000_ofp_table, +}; + +static int __init sja1000_ofp_init(void) +{ + return of_register_platform_driver(&sja1000_ofp_driver); +} +module_init(sja1000_ofp_init); + +static void __exit sja1000_ofp_exit(void) +{ + return of_unregister_platform_driver(&sja1000_ofp_driver); +}; +module_exit(sja1000_ofp_exit); diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c new file mode 100644 index 000000000000..628374c2a05f --- /dev/null +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2005 Sascha Hauer, Pengutronix + * Copyright (C) 2007 Wolfgang Grandegger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sja1000.h" + +#define DRV_NAME "sja1000_platform" + +MODULE_AUTHOR("Sascha Hauer "); +MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus"); +MODULE_LICENSE("GPL v2"); + +static u8 sp_read_reg(const struct sja1000_priv *priv, int reg) +{ + return ioread8(priv->reg_base + reg); +} + +static void sp_write_reg(const struct sja1000_priv *priv, int reg, u8 val) +{ + iowrite8(val, priv->reg_base + reg); +} + +static int sp_probe(struct platform_device *pdev) +{ + int err; + void __iomem *addr; + struct net_device *dev; + struct sja1000_priv *priv; + struct resource *res_mem, *res_irq; + struct sja1000_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "No platform data provided!\n"); + err = -ENODEV; + goto exit; + } + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res_mem || !res_irq) { + err = -ENODEV; + goto exit; + } + + if (!request_mem_region(res_mem->start, resource_size(res_mem), + DRV_NAME)) { + err = -EBUSY; + goto exit; + } + + addr = ioremap_nocache(res_mem->start, resource_size(res_mem)); + if (!addr) { + err = -ENOMEM; + goto exit_release; + } + + dev = alloc_sja1000dev(0); + if (!dev) { + err = -ENOMEM; + goto exit_iounmap; + } + priv = netdev_priv(dev); + + dev->irq = res_irq->start; + priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; + priv->reg_base = addr; + priv->read_reg = sp_read_reg; + priv->write_reg = sp_write_reg; + priv->can.clock.freq = pdata->clock; + priv->ocr = pdata->ocr; + priv->cdr = pdata->cdr; + + dev_set_drvdata(&pdev->dev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + err = register_sja1000dev(dev); + if (err) { + dev_err(&pdev->dev, "registering %s failed (err=%d)\n", + DRV_NAME, err); + goto exit_free; + } + + dev_info(&pdev->dev, "%s device registered (reg_base=%p, irq=%d)\n", + DRV_NAME, priv->reg_base, dev->irq); + return 0; + + exit_free: + free_sja1000dev(dev); + exit_iounmap: + iounmap(addr); + exit_release: + release_mem_region(res_mem->start, resource_size(res_mem)); + exit: + return err; +} + +static int sp_remove(struct platform_device *pdev) +{ + struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct sja1000_priv *priv = netdev_priv(dev); + struct resource *res; + + unregister_sja1000dev(dev); + dev_set_drvdata(&pdev->dev, NULL); + + if (priv->reg_base) + iounmap(priv->reg_base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + free_sja1000dev(dev); + + return 0; +} + +static struct platform_driver sp_driver = { + .probe = sp_probe, + .remove = sp_remove, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init sp_init(void) +{ + return platform_driver_register(&sp_driver); +} + +static void __exit sp_exit(void) +{ + platform_driver_unregister(&sp_driver); +} + +module_init(sp_init); +module_exit(sp_exit); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index f5222764061c..eb066673c2a0 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2934,7 +2934,7 @@ static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev) * individual queues. */ if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb)) - return 1; + return NETDEV_TX_BUSY; dev->trans_start = jiffies; return 0; } diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 4bd2455b0fe3..699d22c5fe09 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h index 79d855e267e0..1f095a9fc739 100644 --- a/drivers/net/chelsio/cphy.h +++ b/drivers/net/chelsio/cphy.h @@ -43,10 +43,11 @@ struct mdio_ops { void (*init)(adapter_t *adapter, const struct board_info *bi); - int (*read)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*write)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + int (*read)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr); + int (*write)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val); + unsigned mode_support; }; /* PHY interrupt types */ @@ -83,11 +84,12 @@ struct cphy_ops { int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex); int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed, int *duplex, int *fc); + + u32 mmds; }; /* A PHY instance */ struct cphy { - int addr; /* PHY address */ int state; /* Link status state machine */ adapter_t *adapter; /* associated adapter */ @@ -101,56 +103,61 @@ struct cphy { u32 elmer_gpo; const struct cphy_ops *ops; /* PHY operations */ - int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + struct mdio_if_info mdio; struct cphy_instance *instance; }; /* Convenience MDIO read/write wrappers */ -static inline int mdio_read(struct cphy *cphy, int mmd, int reg, - unsigned int *valp) +static inline int cphy_mdio_read(struct cphy *cphy, int mmd, int reg, + unsigned int *valp) { - return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp); + int rc = cphy->mdio.mdio_read(cphy->mdio.dev, cphy->mdio.prtad, mmd, + reg); + *valp = (rc >= 0) ? rc : -1; + return (rc >= 0) ? 0 : rc; } -static inline int mdio_write(struct cphy *cphy, int mmd, int reg, - unsigned int val) +static inline int cphy_mdio_write(struct cphy *cphy, int mmd, int reg, + unsigned int val) { - return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val); + return cphy->mdio.mdio_write(cphy->mdio.dev, cphy->mdio.prtad, mmd, + reg, val); } static inline int simple_mdio_read(struct cphy *cphy, int reg, unsigned int *valp) { - return mdio_read(cphy, 0, reg, valp); + return cphy_mdio_read(cphy, MDIO_DEVAD_NONE, reg, valp); } static inline int simple_mdio_write(struct cphy *cphy, int reg, unsigned int val) { - return mdio_write(cphy, 0, reg, val); + return cphy_mdio_write(cphy, MDIO_DEVAD_NONE, reg, val); } /* Convenience initializer */ -static inline void cphy_init(struct cphy *phy, adapter_t *adapter, +static inline void cphy_init(struct cphy *phy, struct net_device *dev, int phy_addr, struct cphy_ops *phy_ops, const struct mdio_ops *mdio_ops) { + struct adapter *adapter = netdev_priv(dev); phy->adapter = adapter; - phy->addr = phy_addr; phy->ops = phy_ops; if (mdio_ops) { - phy->mdio_read = mdio_ops->read; - phy->mdio_write = mdio_ops->write; + phy->mdio.prtad = phy_addr; + phy->mdio.mmds = phy_ops->mmds; + phy->mdio.mode_support = mdio_ops->mode_support; + phy->mdio.mdio_read = mdio_ops->read; + phy->mdio.mdio_write = mdio_ops->write; } + phy->mdio.dev = dev; } /* Operations of the PHY-instance factory */ struct gphy { /* Construct a PHY instance with the given PHY address */ - struct cphy *(*create)(adapter_t *adapter, int phy_addr, + struct cphy *(*create)(struct net_device *dev, int phy_addr, const struct mdio_ops *mdio_ops); /* diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index fa06994f9737..082cdb28b510 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -589,7 +589,7 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) } cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - cmd->phy_address = p->phy->addr; + cmd->phy_address = p->phy->mdio.prtad; cmd->transceiver = XCVR_EXTERNAL; cmd->autoneg = p->link_config.autoneg; cmd->maxtxpkt = 0; @@ -849,39 +849,9 @@ static const struct ethtool_ops t1_ethtool_ops = { static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { struct adapter *adapter = dev->ml_priv; - struct mii_ioctl_data *data = if_mii(req); + struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio; - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = adapter->port[dev->if_port].phy->addr; - /* FALLTHRU */ - case SIOCGMIIREG: { - struct cphy *phy = adapter->port[dev->if_port].phy; - u32 val; - - if (!phy->mdio_read) - return -EOPNOTSUPP; - phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f, - &val); - data->val_out = val; - break; - } - case SIOCSMIIREG: { - struct cphy *phy = adapter->port[dev->if_port].phy; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!phy->mdio_write) - return -EOPNOTSUPP; - phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f, - data->val_in); - break; - } - - default: - return -EOPNOTSUPP; - } - return 0; + return mdio_mii_ioctl(mdio, if_mii(req), cmd); } static int t1_change_mtu(struct net_device *dev, int new_mtu) diff --git a/drivers/net/chelsio/mv88e1xxx.c b/drivers/net/chelsio/mv88e1xxx.c index 0632be0d6494..809047a99e96 100644 --- a/drivers/net/chelsio/mv88e1xxx.c +++ b/drivers/net/chelsio/mv88e1xxx.c @@ -353,15 +353,16 @@ static struct cphy_ops mv88e1xxx_ops = { .get_link_status = mv88e1xxx_get_link_status, }; -static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr, +static struct cphy *mv88e1xxx_phy_create(struct net_device *dev, int phy_addr, const struct mdio_ops *mdio_ops) { + struct adapter *adapter = netdev_priv(dev); struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); if (!cphy) return NULL; - cphy_init(cphy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops); + cphy_init(cphy, dev, phy_addr, &mv88e1xxx_ops, mdio_ops); /* Configure particular PHY's to run in a different mode. */ if ((board_info(adapter)->caps & SUPPORTED_TP) && diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c index cd856041af34..f7136b2fd1e5 100644 --- a/drivers/net/chelsio/mv88x201x.c +++ b/drivers/net/chelsio/mv88x201x.c @@ -53,7 +53,7 @@ static int led_init(struct cphy *cphy) * Writing these bits maps control to another * register. mmd(0x1) addr(0x7) */ - mdio_write(cphy, 0x3, 0x8304, 0xdddd); + cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd); return 0; } @@ -62,14 +62,14 @@ static int led_link(struct cphy *cphy, u32 do_enable) u32 led = 0; #define LINK_ENABLE_BIT 0x1 - mdio_read(cphy, 0x1, 0x7, &led); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led); if (do_enable & LINK_ENABLE_BIT) { led |= LINK_ENABLE_BIT; - mdio_write(cphy, 0x1, 0x7, led); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led); } else { led &= ~LINK_ENABLE_BIT; - mdio_write(cphy, 0x1, 0x7, led); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led); } return 0; } @@ -86,7 +86,8 @@ static int mv88x201x_reset(struct cphy *cphy, int wait) static int mv88x201x_interrupt_enable(struct cphy *cphy) { /* Enable PHY LASI interrupts. */ - mdio_write(cphy, 0x1, 0x9002, 0x1); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, + MDIO_PMA_LASI_LSALARM); /* Enable Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { @@ -102,7 +103,7 @@ static int mv88x201x_interrupt_enable(struct cphy *cphy) static int mv88x201x_interrupt_disable(struct cphy *cphy) { /* Disable PHY LASI interrupts. */ - mdio_write(cphy, 0x1, 0x9002, 0x0); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0x0); /* Disable Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { @@ -122,25 +123,25 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy) #ifdef MV88x2010_LINK_STATUS_BUGS /* Required to read twice before clear takes affect. */ - mdio_read(cphy, 0x1, 0x9003, &val); - mdio_read(cphy, 0x1, 0x9004, &val); - mdio_read(cphy, 0x1, 0x9005, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); /* Read this register after the others above it else * the register doesn't clear correctly. */ - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); #endif /* Clear link status. */ - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); /* Clear PHY LASI interrupts. */ - mdio_read(cphy, 0x1, 0x9005, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); #ifdef MV88x2010_LINK_STATUS_BUGS /* Do it again. */ - mdio_read(cphy, 0x1, 0x9003, &val); - mdio_read(cphy, 0x1, 0x9004, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val); #endif /* Clear Marvell interrupts through Elmer0. */ @@ -172,13 +173,12 @@ static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok, int *speed, int *duplex, int *fc) { u32 val = 0; -#define LINK_STATUS_BIT 0x4 if (link_ok) { /* Read link status. */ - mdio_read(cphy, 0x1, 0x1, &val); - val &= LINK_STATUS_BIT; - *link_ok = (val == LINK_STATUS_BIT); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); + val &= MDIO_STAT1_LSTATUS; + *link_ok = (val == MDIO_STAT1_LSTATUS); /* Turn on/off Link LED */ led_link(cphy, *link_ok); } @@ -205,9 +205,11 @@ static struct cphy_ops mv88x201x_ops = { .interrupt_handler = mv88x201x_interrupt_handler, .get_link_status = mv88x201x_get_link_status, .set_loopback = mv88x201x_set_loopback, + .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS | MDIO_DEVS_WIS), }; -static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr, +static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr, const struct mdio_ops *mdio_ops) { u32 val; @@ -216,15 +218,15 @@ static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr, if (!cphy) return NULL; - cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops); + cphy_init(cphy, dev, phy_addr, &mv88x201x_ops, mdio_ops); /* Commands the PHY to enable XFP's clock. */ - mdio_read(cphy, 0x3, 0x8300, &val); - mdio_write(cphy, 0x3, 0x8300, val | 1); + cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val); + cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1); /* Clear link status. Required because of a bug in the PHY. */ - mdio_read(cphy, 0x1, 0x8, &val); - mdio_read(cphy, 0x3, 0x8, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val); + cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val); /* Allows for Link,Ack LED turn on/off */ led_init(cphy); diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c index 040acd29995a..4c6028512d10 100644 --- a/drivers/net/chelsio/my3126.c +++ b/drivers/net/chelsio/my3126.c @@ -43,11 +43,11 @@ static int my3126_interrupt_handler(struct cphy *cphy) adapter = cphy->adapter; if (cphy->count == 50) { - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val16 = (u16) val; status = cphy->bmsr ^ val16; - if (status & BMSR_LSTATUS) + if (status & MDIO_STAT1_LSTATUS) t1_link_changed(adapter, 0); cphy->bmsr = val16; @@ -114,14 +114,14 @@ static int my3126_get_link_status(struct cphy *cphy, adapter_t *adapter; adapter = cphy->adapter; - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val16 = (u16) val; /* Populate elmer_gpo with the register value */ t1_tpi_read(adapter, A_ELMER0_GPO, &val); cphy->elmer_gpo = val; - *link_ok = (val16 & BMSR_LSTATUS); + *link_ok = (val16 & MDIO_STAT1_LSTATUS); if (*link_ok) { /* Turn on the LED. */ @@ -163,9 +163,11 @@ static struct cphy_ops my3126_ops = { .interrupt_handler = my3126_interrupt_handler, .get_link_status = my3126_get_link_status, .set_loopback = my3126_set_loopback, + .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS), }; -static struct cphy *my3126_phy_create(adapter_t *adapter, +static struct cphy *my3126_phy_create(struct net_device *dev, int phy_addr, const struct mdio_ops *mdio_ops) { struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL); @@ -173,7 +175,7 @@ static struct cphy *my3126_phy_create(adapter_t *adapter, if (!cphy) return NULL; - cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops); + cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops); INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll); cphy->bmsr = 0; diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 58f6fc055f6a..3711d64e45ef 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1149,8 +1149,8 @@ static inline void write_tx_desc(struct cmdQ_e *e, dma_addr_t mapping, unsigned int len, unsigned int gen, unsigned int eop) { - if (unlikely(len > SGE_TX_DESC_MAX_PLEN)) - BUG(); + BUG_ON(len > SGE_TX_DESC_MAX_PLEN); + e->addr_lo = (u32)mapping; e->addr_hi = (u64)mapping >> 32; e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen); @@ -1879,7 +1879,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) cpl->vlan_valid = 0; send: - dev->trans_start = jiffies; ret = t1_sge_tx(skb, adapter, 0, dev); /* If transmit busy, and we reallocated skb's due to headroom limit, diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 7adf30230c4f..17720c6e5bfe 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -284,32 +284,29 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi) /* * Elmer MI1 MDIO read/write operations. */ -static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); - - if (mmd_addr) - return -EINVAL; + unsigned int val; spin_lock(&adapter->tpi_lock); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ); mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); - __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); + __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val); spin_unlock(&adapter->tpi_lock); - return 0; + return val; } -static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); - if (mmd_addr) - return -EINVAL; - spin_lock(&adapter->tpi_lock); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); @@ -324,16 +321,19 @@ static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr, static const struct mdio_ops mi1_mdio_ops = { .init = mi1_mdio_init, .read = mi1_mdio_read, - .write = mi1_mdio_write + .write = mi1_mdio_write, + .mode_support = MDIO_SUPPORTS_C22 }; #endif #endif -static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); + unsigned int val; spin_lock(&adapter->tpi_lock); @@ -350,14 +350,15 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); /* Read the data. */ - __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); + __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val); spin_unlock(&adapter->tpi_lock); - return 0; + return val; } -static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr, + int mmd_addr, u16 reg_addr, u16 val) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); spin_lock(&adapter->tpi_lock); @@ -380,7 +381,8 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, static const struct mdio_ops mi1_mdio_ext_ops = { .init = mi1_mdio_init, .read = mi1_mdio_ext_read, - .write = mi1_mdio_ext_write + .write = mi1_mdio_ext_write, + .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22 }; enum { @@ -1133,8 +1135,8 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, struct cmac *mac; int phy_addr = bi->mdio_phybaseaddr + i; - adapter->port[i].phy = bi->gphy->create(adapter, phy_addr, - bi->mdio_ops); + adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev, + phy_addr, bi->mdio_ops); if (!adapter->port[i].phy) { CH_ERR("%s: PHY %d initialization failed\n", adapter->name, i); diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 3f476c7c0736..58afafbd3b9c 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -202,7 +202,7 @@ struct cpmac_priv { void __iomem *regs; struct mii_bus *mii_bus; struct phy_device *phy; - char phy_name[BUS_ID_SIZE]; + char phy_name[MII_BUS_ID_SIZE + 3]; int oldlink, oldspeed, oldduplex; u32 msg_enable; struct net_device *dev; @@ -615,13 +615,13 @@ static void cpmac_end_xmit(struct net_device *dev, int queue) dev_kfree_skb_irq(desc->skb); desc->skb = NULL; - if (netif_subqueue_stopped(dev, queue)) + if (__netif_subqueue_stopped(dev, queue)) netif_wake_subqueue(dev, queue); } else { if (netif_msg_tx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: end_xmit: spurious interrupt\n", dev->name); - if (netif_subqueue_stopped(dev, queue)) + if (__netif_subqueue_stopped(dev, queue)) netif_wake_subqueue(dev, queue); } } @@ -731,7 +731,6 @@ static void cpmac_clear_tx(struct net_device *dev) static void cpmac_hw_error(struct work_struct *work) { - int i; struct cpmac_priv *priv = container_of(work, struct cpmac_priv, reset_work); @@ -818,7 +817,6 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) static void cpmac_tx_timeout(struct net_device *dev) { - int i; struct cpmac_priv *priv = netdev_priv(dev); spin_lock(&priv->lock); @@ -1093,11 +1091,24 @@ static int cpmac_stop(struct net_device *dev) return 0; } +static const struct net_device_ops cpmac_netdev_ops = { + .ndo_open = cpmac_open, + .ndo_stop = cpmac_stop, + .ndo_start_xmit = cpmac_start_xmit, + .ndo_tx_timeout = cpmac_tx_timeout, + .ndo_set_multicast_list = cpmac_set_multicast_list, + .ndo_so_ioctl = cpmac_ioctl, + .ndo_set_config = cpmac_config, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int external_switch; static int __devinit cpmac_probe(struct platform_device *pdev) { - int rc, phy_id, i; + int rc, phy_id; char *mdio_bus_id = "0"; struct resource *mem; struct cpmac_priv *priv; @@ -1143,14 +1154,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) dev->irq = platform_get_irq_byname(pdev, "irq"); - dev->open = cpmac_open; - dev->stop = cpmac_stop; - dev->set_config = cpmac_config; - dev->hard_start_xmit = cpmac_start_xmit; - dev->do_ioctl = cpmac_ioctl; - dev->set_multicast_list = cpmac_set_multicast_list; - dev->tx_timeout = cpmac_tx_timeout; - dev->ethtool_ops = &cpmac_ethtool_ops; + dev->netdev_ops = &cpmac_netdev_ops; + dev->ethtool_ops = &cpmac_ethtool_ops; netif_napi_add(dev, &priv->napi, cpmac_poll, 64); diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 7433b88eed7e..3eee666a9cd2 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1551,7 +1551,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&lp->lock); if (net_debug) printk("cs89x0: Tx buffer not free!\n"); - return 1; + return NETDEV_TX_BUSY; } /* Write the contents of the packet */ writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); diff --git a/drivers/net/cxgb3/Makefile b/drivers/net/cxgb3/Makefile index 343467985321..29aff78c7820 100644 --- a/drivers/net/cxgb3/Makefile +++ b/drivers/net/cxgb3/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_CHELSIO_T3) += cxgb3.o cxgb3-objs := cxgb3_main.o ael1002.o vsc8211.o t3_hw.o mc5.o \ - xgmac.o sge.o l2t.o cxgb3_offload.o + xgmac.o sge.o l2t.o cxgb3_offload.o aq100x.o diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index c888e97c9671..1694fad38720 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -195,7 +195,7 @@ struct sge_qset { /* an SGE queue set */ struct sge_rspq rspq; struct sge_fl fl[SGE_RXQ_PER_SET]; struct sge_txq txq[SGE_TXQ_PER_SET]; - struct napi_gro_fraginfo lro_frag_tbl; + int nomem; int lro_enabled; void *lro_va; struct net_device *netdev; @@ -253,6 +253,8 @@ struct adapter { struct mutex mdio_lock; spinlock_t stats_lock; spinlock_t work_lock; + + struct sk_buff *nofail_skb; }; static inline u32 t3_read_reg(struct adapter *adapter, u32 reg_addr) diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c index e1b22490ff59..9fe008ec9ba5 100644 --- a/drivers/net/cxgb3/ael1002.c +++ b/drivers/net/cxgb3/ael1002.c @@ -33,14 +33,6 @@ #include "regs.h" enum { - PMD_RSD = 10, /* PMA/PMD receive signal detect register */ - PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */ - PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */ - XS_LN_STAT = 24 /* XS lane status register */ -}; - -enum { - AEL100X_TX_DISABLE = 9, AEL100X_TX_CONFIG1 = 0xc002, AEL1002_PWR_DOWN_HI = 0xc011, AEL1002_PWR_DOWN_LO = 0xc012, @@ -52,12 +44,33 @@ enum { AEL_I2C_STAT = 0xc30c, AEL2005_GPIO_CTRL = 0xc214, AEL2005_GPIO_STAT = 0xc215, + + AEL2020_GPIO_INTR = 0xc103, /* Latch High (LH) */ + AEL2020_GPIO_CTRL = 0xc108, /* Store Clear (SC) */ + AEL2020_GPIO_STAT = 0xc10c, /* Read Only (RO) */ + AEL2020_GPIO_CFG = 0xc110, /* Read Write (RW) */ + + AEL2020_GPIO_SDA = 0, /* IN: i2c serial data */ + AEL2020_GPIO_MODDET = 1, /* IN: Module Detect */ + AEL2020_GPIO_0 = 3, /* IN: unassigned */ + AEL2020_GPIO_1 = 2, /* OUT: unassigned */ + AEL2020_GPIO_LSTAT = AEL2020_GPIO_1, /* wired to link status LED */ }; enum { edc_none, edc_sr, edc_twinax }; /* PHY module I2C device address */ -#define MODULE_DEV_ADDR 0xa0 +enum { + MODULE_DEV_ADDR = 0xa0, + SFF_DEV_ADDR = 0xa2, +}; + +/* PHY transceiver type */ +enum { + phy_transtype_unknown = 0, + phy_transtype_sfp = 3, + phy_transtype_xfp = 6, +}; #define AEL2005_MODDET_IRQ 4 @@ -74,8 +87,8 @@ static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) for (err = 0; rv->mmd_addr && !err; rv++) { if (rv->clear_bits == 0xffff) - err = mdio_write(phy, rv->mmd_addr, rv->reg_addr, - rv->set_bits); + err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr, + rv->set_bits); else err = t3_mdio_change_bits(phy, rv->mmd_addr, rv->reg_addr, rv->clear_bits, @@ -86,21 +99,54 @@ static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) static void ael100x_txon(struct cphy *phy) { - int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; + int tx_on_gpio = + phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; msleep(100); t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); msleep(30); } +/* + * Read an 8-bit word from a device attached to the PHY's i2c bus. + */ +static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) +{ + int i, err; + unsigned int stat, data; + + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL, + (dev_addr << 8) | (1 << 8) | word_addr); + if (err) + return err; + + for (i = 0; i < 200; i++) { + msleep(1); + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat); + if (err) + return err; + if ((stat & 3) == 1) { + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA, + &data); + if (err) + return err; + return data >> 8; + } + } + CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %#x.%#x timed out\n", + phy->mdio.prtad, dev_addr, word_addr); + return -ETIMEDOUT; +} + static int ael1002_power_down(struct cphy *phy, int enable) { int err; - err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable); if (!err) - err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, - BMCR_PDOWN, enable ? BMCR_PDOWN : 0); + err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, + MDIO_MMD_PMAPMD, MDIO_CTRL1, + MDIO_CTRL1_LPOWER, enable); return err; } @@ -109,11 +155,11 @@ static int ael1002_reset(struct cphy *phy, int wait) int err; if ((err = ael1002_power_down(phy, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || - (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) || + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) || + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) || + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) || + (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN, 0, 1 << 5))) return err; return 0; @@ -132,12 +178,15 @@ static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed, { if (link_ok) { unsigned int stat0, stat1, stat2; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, + MDIO_PMA_RXDET, &stat0); if (!err) - err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1); + err = t3_mdio_read(phy, MDIO_MMD_PCS, + MDIO_PCS_10GBRT_STAT1, &stat1); if (!err) - err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); + err = t3_mdio_read(phy, MDIO_MMD_PHYXS, + MDIO_PHYXS_LNSTAT, &stat2); if (err) return err; *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1; @@ -157,6 +206,7 @@ static struct cphy_ops ael1002_ops = { .intr_handler = ael1002_intr_noop, .get_link_status = get_link_status_r, .power_down = ael1002_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -171,13 +221,13 @@ int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, static int ael1006_reset(struct cphy *phy, int wait) { - return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); + return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait); } static int ael1006_power_down(struct cphy *phy, int enable) { - return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, - BMCR_PDOWN, enable ? BMCR_PDOWN : 0); + return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD, + MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable); } static struct cphy_ops ael1006_ops = { @@ -188,6 +238,7 @@ static struct cphy_ops ael1006_ops = { .intr_handler = t3_phy_lasi_intr_handler, .get_link_status = get_link_status_r, .power_down = ael1006_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -200,12 +251,57 @@ int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, return 0; } +/* + * Decode our module type. + */ +static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms) +{ + int v; + + if (delay_ms) + msleep(delay_ms); + + /* see SFF-8472 for below */ + v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3); + if (v < 0) + return v; + + if (v == 0x10) + return phy_modtype_sr; + if (v == 0x20) + return phy_modtype_lr; + if (v == 0x40) + return phy_modtype_lrm; + + v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6); + if (v < 0) + return v; + if (v != 4) + goto unknown; + + v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10); + if (v < 0) + return v; + + if (v & 0x80) { + v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); + if (v < 0) + return v; + return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax; + } +unknown: + return phy_modtype_unknown; +} + +/* + * Code to support the Aeluros/NetLogic 2005 10Gb PHY. + */ static int ael2005_setup_sr_edc(struct cphy *phy) { static struct reg_val regs[] = { - { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 }, - { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a }, - { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 }, + { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 }, + { MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a }, + { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 }, { 0, 0, 0, 0 } }; static u16 sr_edc[] = { @@ -490,8 +586,8 @@ static int ael2005_setup_sr_edc(struct cphy *phy) msleep(50); for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2) - err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i], - sr_edc[i + 1]); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i], + sr_edc[i + 1]); if (!err) phy->priv = edc_sr; return err; @@ -500,12 +596,12 @@ static int ael2005_setup_sr_edc(struct cphy *phy) static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) { static struct reg_val regs[] = { - { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 }, + { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 }, { 0, 0, 0, 0 } }; static struct reg_val preemphasis[] = { - { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 }, - { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 }, + { MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 }, + { MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 }, { 0, 0, 0, 0 } }; static u16 twinax_edc[] = { @@ -887,132 +983,73 @@ 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 = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i], - twinax_edc[i + 1]); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i], + twinax_edc[i + 1]); if (!err) phy->priv = edc_twinax; return err; } -static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) -{ - int i, err; - unsigned int stat, data; - - err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, - (dev_addr << 8) | (1 << 8) | word_addr); - if (err) - return err; - - for (i = 0; i < 5; i++) { - msleep(1); - err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); - if (err) - return err; - if ((stat & 3) == 1) { - err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, - &data); - if (err) - return err; - return data >> 8; - } - } - CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n", - phy->addr, word_addr); - return -ETIMEDOUT; -} - -static int get_module_type(struct cphy *phy, int delay_ms) +static int ael2005_get_module_type(struct cphy *phy, int delay_ms) { int v; unsigned int stat; - v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat); + v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat); if (v) return v; if (stat & (1 << 8)) /* module absent */ return phy_modtype_none; - if (delay_ms) - msleep(delay_ms); - - /* see SFF-8472 for below */ - v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3); - if (v < 0) - return v; - - if (v == 0x10) - return phy_modtype_sr; - if (v == 0x20) - return phy_modtype_lr; - if (v == 0x40) - return phy_modtype_lrm; - - v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6); - if (v < 0) - return v; - if (v != 4) - goto unknown; - - v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10); - if (v < 0) - return v; - - if (v & 0x80) { - v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); - if (v < 0) - return v; - return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax; - } -unknown: - return phy_modtype_unknown; + return ael2xxx_get_module_type(phy, delay_ms); } static int ael2005_intr_enable(struct cphy *phy) { - int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200); + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200); return err ? err : t3_phy_lasi_intr_enable(phy); } static int ael2005_intr_disable(struct cphy *phy) { - int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100); + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100); return err ? err : t3_phy_lasi_intr_disable(phy); } static int ael2005_intr_clear(struct cphy *phy) { - int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00); + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00); return err ? err : t3_phy_lasi_intr_clear(phy); } static int ael2005_reset(struct cphy *phy, int wait) { static struct reg_val regs0[] = { - { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 }, - { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 }, - { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 }, + { MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 }, + { MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 }, + { MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 }, { 0, 0, 0, 0 } }; static struct reg_val regs1[] = { - { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 }, - { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 }, + { MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 }, + { MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 }, { 0, 0, 0, 0 } }; int err; unsigned int lasi_ctrl; - err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl); + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, + &lasi_ctrl); if (err) return err; - err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0); + err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0); if (err) return err; @@ -1024,7 +1061,7 @@ static int ael2005_reset(struct cphy *phy, int wait) msleep(50); - err = get_module_type(phy, 0); + err = ael2005_get_module_type(phy, 0); if (err < 0) return err; phy->modtype = err; @@ -1051,18 +1088,18 @@ static int ael2005_intr_handler(struct cphy *phy) unsigned int stat; int ret, edc_needed, cause = 0; - ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat); + ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat); if (ret) return ret; if (stat & AEL2005_MODDET_IRQ) { - ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, - 0xd00); + ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, + 0xd00); if (ret) return ret; /* modules have max 300 ms init time after hot plug */ - ret = get_module_type(phy, 300); + ret = ael2005_get_module_type(phy, 300); if (ret < 0) return ret; @@ -1098,6 +1135,7 @@ static struct cphy_ops ael2005_ops = { .intr_handler = ael2005_intr_handler, .get_link_status = get_link_status_r, .power_down = ael1002_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -1107,10 +1145,666 @@ int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | SUPPORTED_IRQ, "10GBASE-R"); msleep(125); - return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0, + return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0, 1 << 5); } +/* + * Setup EDC and other parameters for operation with an optical module. + */ +static int ael2020_setup_sr_edc(struct cphy *phy) +{ + static struct reg_val regs[] = { + /* set CDR offset to 10 */ + { MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a }, + + /* adjust 10G RX bias current */ + { MDIO_MMD_PMAPMD, 0xcb1b, 0xffff, 0x0200 }, + { MDIO_MMD_PMAPMD, 0xcb1c, 0xffff, 0x00f0 }, + { MDIO_MMD_PMAPMD, 0xcc06, 0xffff, 0x00e0 }, + + /* end */ + { 0, 0, 0, 0 } + }; + int err; + + err = set_phy_regs(phy, regs); + msleep(50); + if (err) + return err; + + phy->priv = edc_sr; + return 0; +} + +/* + * Setup EDC and other parameters for operation with an TWINAX module. + */ +static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype) +{ + /* set uC to 40MHz */ + static struct reg_val uCclock40MHz[] = { + { MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 }, + { MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 }, + { 0, 0, 0, 0 } + }; + + /* activate uC clock */ + static struct reg_val uCclockActivate[] = { + { MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 }, + { 0, 0, 0, 0 } + }; + + /* set PC to start of SRAM and activate uC */ + static struct reg_val uCactivate[] = { + { MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 }, + { 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 */ + err = set_phy_regs(phy, uCclock40MHz); + msleep(500); + if (err) + return err; + err = set_phy_regs(phy, uCclockActivate); + msleep(500); + 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]); + /* activate uC */ + err = set_phy_regs(phy, uCactivate); + if (!err) + phy->priv = edc_twinax; + return err; +} + +/* + * Return Module Type. + */ +static int ael2020_get_module_type(struct cphy *phy, int delay_ms) +{ + int v; + unsigned int stat; + + v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_STAT, &stat); + if (v) + return v; + + if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) { + /* module absent */ + return phy_modtype_none; + } + + return ael2xxx_get_module_type(phy, delay_ms); +} + +/* + * Enable PHY interrupts. We enable "Module Detection" interrupts (on any + * state transition) and then generic Link Alarm Status Interrupt (LASI). + */ +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); +} + +/* + * Disable PHY interrupts. The mirror of the above ... + */ +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); +} + +/* + * Clear PHY interrupt state. + */ +static int ael2020_intr_clear(struct cphy *phy) +{ + /* + * The GPIO Interrupt register on the AEL2020 is a "Latching High" + * (LH) register which is cleared to the current state when it's read. + * Thus, we simply read the register and discard the result. + */ + unsigned int stat; + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat); + return err ? err : t3_phy_lasi_intr_clear(phy); +} + +/* + * 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; + + /* grab current interrupt state */ + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, + &lasi_ctrl); + if (err) + return err; + + err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 125); + if (err) + return err; + msleep(100); + + /* basic initialization for all module types */ + phy->priv = edc_none; + err = set_phy_regs(phy, regs0); + if (err) + return err; + + /* determine module type and perform appropriate initialization */ + err = ael2020_get_module_type(phy, 0); + if (err < 0) + return err; + phy->modtype = (u8)err; + if (err == phy_modtype_twinax || err == phy_modtype_twinax_long) + err = ael2020_setup_twinax_edc(phy, err); + else + err = ael2020_setup_sr_edc(phy); + if (err) + return err; + + /* reset wipes out interrupts, reenable them if they were on */ + if (lasi_ctrl & 1) + err = ael2005_intr_enable(phy); + return err; +} + +/* + * Handle a PHY interrupt. + */ +static int ael2020_intr_handler(struct cphy *phy) +{ + unsigned int stat; + int ret, edc_needed, cause = 0; + + ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat); + if (ret) + return ret; + + if (stat & (0x1 << AEL2020_GPIO_MODDET)) { + /* modules have max 300 ms init time after hot plug */ + ret = ael2020_get_module_type(phy, 300); + if (ret < 0) + return ret; + + phy->modtype = (u8)ret; + if (ret == phy_modtype_none) + edc_needed = phy->priv; /* on unplug retain EDC */ + else if (ret == phy_modtype_twinax || + ret == phy_modtype_twinax_long) + edc_needed = edc_twinax; + else + edc_needed = edc_sr; + + if (edc_needed != phy->priv) { + ret = ael2020_reset(phy, 0); + return ret ? ret : cphy_cause_module_change; + } + cause = cphy_cause_module_change; + } + + ret = t3_phy_lasi_intr_handler(phy); + if (ret < 0) + return ret; + + ret |= cause; + return ret ? ret : cphy_cause_link_change; +} + +static struct cphy_ops ael2020_ops = { + .reset = ael2020_reset, + .intr_enable = ael2020_intr_enable, + .intr_disable = ael2020_intr_disable, + .intr_clear = ael2020_intr_clear, + .intr_handler = ael2020_intr_handler, + .get_link_status = get_link_status_r, + .power_down = ael1002_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, +}; + +int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, + const struct mdio_ops *mdio_ops) +{ + cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops, + SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | + SUPPORTED_IRQ, "10GBASE-R"); + msleep(125); + return 0; +} + /* * Get link status for a 10GBASE-X device. */ @@ -1119,12 +1813,15 @@ static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, { if (link_ok) { unsigned int stat0, stat1, stat2; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, + MDIO_PMA_RXDET, &stat0); if (!err) - err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1); + err = t3_mdio_read(phy, MDIO_MMD_PCS, + MDIO_PCS_10GBX_STAT1, &stat1); if (!err) - err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); + err = t3_mdio_read(phy, MDIO_MMD_PHYXS, + MDIO_PHYXS_LNSTAT, &stat2); if (err) return err; *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1; @@ -1144,6 +1841,7 @@ static struct cphy_ops qt2045_ops = { .intr_handler = t3_phy_lasi_intr_handler, .get_link_status = get_link_status_x, .power_down = ael1006_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -1159,9 +1857,10 @@ int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, * Some cards where the PHY is supposed to be at address 0 actually * have it at 1. */ - if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && + if (!phy_addr && + !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) && stat == 0xffff) - phy->addr = 1; + phy->mdio.prtad = 1; return 0; } @@ -1175,15 +1874,16 @@ static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, { if (link_ok) { unsigned int status; + int prtad = phy->mdio.prtad; status = t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | + XGM_REG(A_XGM_SERDES_STAT0, prtad)) | t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | + XGM_REG(A_XGM_SERDES_STAT1, prtad)) | t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | + XGM_REG(A_XGM_SERDES_STAT2, prtad)) | t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); + XGM_REG(A_XGM_SERDES_STAT3, prtad)); *link_ok = !(status & F_LOWSIG0); } if (speed) @@ -1211,7 +1911,7 @@ static struct cphy_ops xaui_direct_ops = { int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops) { - cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops, + cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops, SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, "10GBASE-CX4"); return 0; diff --git a/drivers/net/cxgb3/aq100x.c b/drivers/net/cxgb3/aq100x.c new file mode 100644 index 000000000000..b1fd5bf836e4 --- /dev/null +++ b/drivers/net/cxgb3/aq100x.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "common.h" +#include "regs.h" + +enum { + /* MDIO_DEV_PMA_PMD registers */ + AQ_LINK_STAT = 0xe800, + AQ_IMASK_PMA = 0xf000, + + /* MDIO_DEV_XGXS registers */ + AQ_XAUI_RX_CFG = 0xc400, + AQ_XAUI_TX_CFG = 0xe400, + + /* MDIO_DEV_ANEG registers */ + AQ_1G_CTRL = 0xc400, + AQ_ANEG_STAT = 0xc800, + + /* MDIO_DEV_VEND1 registers */ + AQ_FW_VERSION = 0x0020, + AQ_IFLAG_GLOBAL = 0xfc00, + AQ_IMASK_GLOBAL = 0xff00, +}; + +enum { + IMASK_PMA = 1 << 2, + IMASK_GLOBAL = 1 << 15, + ADV_1G_FULL = 1 << 15, + ADV_1G_HALF = 1 << 14, + ADV_10G_FULL = 1 << 12, + AQ_RESET = (1 << 14) | (1 << 15), + AQ_LOWPOWER = 1 << 12, +}; + +static int aq100x_reset(struct cphy *phy, int wait) +{ + /* + * Ignore the caller specified wait time; always wait for the reset to + * complete. Can take up to 3s. + */ + int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000); + + if (err) + CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n", + phy->mdio.prtad, err); + + return err; +} + +static int aq100x_intr_enable(struct cphy *phy) +{ + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AQ_IMASK_PMA, IMASK_PMA); + if (err) + return err; + + err = t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, IMASK_GLOBAL); + return err; +} + +static int aq100x_intr_disable(struct cphy *phy) +{ + return t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, 0); +} + +static int aq100x_intr_clear(struct cphy *phy) +{ + unsigned int v; + + t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &v); + t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v); + + return 0; +} + +static int aq100x_intr_handler(struct cphy *phy) +{ + int err; + unsigned int cause, v; + + err = t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &cause); + if (err) + return err; + + /* Read (and reset) the latching version of the status */ + t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v); + + return cphy_cause_link_change; +} + +static int aq100x_power_down(struct cphy *phy, int off) +{ + return mdio_set_flag(&phy->mdio, phy->mdio.prtad, + MDIO_MMD_PMAPMD, MDIO_CTRL1, + MDIO_CTRL1_LPOWER, off); +} + +static int aq100x_autoneg_enable(struct cphy *phy) +{ + int err; + + err = aq100x_power_down(phy, 0); + if (!err) + err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, + MDIO_MMD_AN, MDIO_CTRL1, + BMCR_ANENABLE | BMCR_ANRESTART, 1); + + return err; +} + +static int aq100x_autoneg_restart(struct cphy *phy) +{ + int err; + + err = aq100x_power_down(phy, 0); + if (!err) + err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, + MDIO_MMD_AN, MDIO_CTRL1, + BMCR_ANENABLE | BMCR_ANRESTART, 1); + + return err; +} + +static int aq100x_advertise(struct cphy *phy, unsigned int advertise_map) +{ + unsigned int adv; + int err; + + /* 10G advertisement */ + adv = 0; + if (advertise_map & ADVERTISED_10000baseT_Full) + adv |= ADV_10G_FULL; + err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + ADV_10G_FULL, adv); + if (err) + return err; + + /* 1G advertisement */ + adv = 0; + if (advertise_map & ADVERTISED_1000baseT_Full) + adv |= ADV_1G_FULL; + if (advertise_map & ADVERTISED_1000baseT_Half) + adv |= ADV_1G_HALF; + err = t3_mdio_change_bits(phy, MDIO_MMD_AN, AQ_1G_CTRL, + ADV_1G_FULL | ADV_1G_HALF, adv); + if (err) + return err; + + /* 100M, pause advertisement */ + adv = 0; + if (advertise_map & ADVERTISED_100baseT_Half) + adv |= ADVERTISE_100HALF; + if (advertise_map & ADVERTISED_100baseT_Full) + adv |= ADVERTISE_100FULL; + if (advertise_map & ADVERTISED_Pause) + adv |= ADVERTISE_PAUSE_CAP; + if (advertise_map & ADVERTISED_Asym_Pause) + adv |= ADVERTISE_PAUSE_ASYM; + err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_ADVERTISE, + 0xfe0, adv); + + return err; +} + +static int aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable) +{ + return mdio_set_flag(&phy->mdio, phy->mdio.prtad, + MDIO_MMD_PMAPMD, MDIO_CTRL1, + BMCR_LOOPBACK, enable); +} + +static int aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex) +{ + /* no can do */ + return -1; +} + +static int aq100x_get_link_status(struct cphy *phy, int *link_ok, + int *speed, int *duplex, int *fc) +{ + int err; + unsigned int v; + + if (link_ok) { + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AQ_LINK_STAT, &v); + if (err) + return err; + + *link_ok = v & 1; + if (!*link_ok) + return 0; + } + + err = t3_mdio_read(phy, MDIO_MMD_AN, AQ_ANEG_STAT, &v); + if (err) + return err; + + if (speed) { + switch (v & 0x6) { + case 0x6: + *speed = SPEED_10000; + break; + case 0x4: + *speed = SPEED_1000; + break; + case 0x2: + *speed = SPEED_100; + break; + case 0x0: + *speed = SPEED_10; + break; + } + } + + if (duplex) + *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF; + + return 0; +} + +static struct cphy_ops aq100x_ops = { + .reset = aq100x_reset, + .intr_enable = aq100x_intr_enable, + .intr_disable = aq100x_intr_disable, + .intr_clear = aq100x_intr_clear, + .intr_handler = aq100x_intr_handler, + .autoneg_enable = aq100x_autoneg_enable, + .autoneg_restart = aq100x_autoneg_restart, + .advertise = aq100x_advertise, + .set_loopback = aq100x_set_loopback, + .set_speed_duplex = aq100x_set_speed_duplex, + .get_link_status = aq100x_get_link_status, + .power_down = aq100x_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, +}; + +int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, + const struct mdio_ops *mdio_ops) +{ + unsigned int v, v2, gpio, wait; + int err; + + cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops, + SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_AUI, "1000/10GBASE-T"); + + /* + * The PHY has been out of reset ever since the system powered up. So + * we do a hard reset over here. + */ + gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL; + t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0); + msleep(1); + t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio); + + /* + * Give it enough time to load the firmware and get ready for mdio. + */ + msleep(1000); + wait = 500; /* in 10ms increments */ + do { + err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v); + if (err || v == 0xffff) { + + /* Allow prep_adapter to succeed when ffff is read */ + + CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n", + phy_addr, err, v); + goto done; + } + + v &= AQ_RESET; + if (v) + msleep(10); + } while (v && --wait); + if (v) { + CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n", + phy_addr, v); + + goto done; /* let prep_adapter succeed */ + } + + /* Datasheet says 3s max but this has been observed */ + wait = (500 - wait) * 10 + 1000; + if (wait > 3000) + CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait); + + /* Firmware version check. */ + t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v); + if (v != 30) { + 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 + * operations. + */ + err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v); + if (err) + return err; + if (v & AQ_LOWPOWER) { + err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1, + AQ_LOWPOWER, 0); + if (err) + return err; + msleep(10); + } else + CH_WARN(adapter, "PHY%d does not start in low power mode.\n", + phy_addr); + + /* + * Verify XAUI settings, but let prep succeed no matter what. + */ + v = v2 = 0; + t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v); + t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2); + if (v != 0x1b || v2 != 0x1b) + CH_WARN(adapter, + "PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n", + phy_addr, v, v2); + +done: + return err; +} diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index e508dc32f3ec..d21b705501a9 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "version.h" #define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__) @@ -184,10 +184,11 @@ struct cphy; struct adapter; struct mdio_ops { - int (*read)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*write)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + int (*read)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr); + int (*write)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val); + unsigned mode_support; }; struct adapter_info { @@ -520,27 +521,6 @@ enum { MAC_RXFIFO_SIZE = 32768 }; -/* IEEE 802.3 specified MDIO devices */ -enum { - MDIO_DEV_PMA_PMD = 1, - MDIO_DEV_WIS = 2, - MDIO_DEV_PCS = 3, - MDIO_DEV_XGXS = 4, - MDIO_DEV_ANEG = 7, - MDIO_DEV_VEND1 = 30, - MDIO_DEV_VEND2 = 31 -}; - -/* LASI control and status registers */ -enum { - RX_ALARM_CTRL = 0x9000, - TX_ALARM_CTRL = 0x9001, - LASI_CTRL = 0x9002, - RX_ALARM_STAT = 0x9003, - TX_ALARM_STAT = 0x9004, - LASI_STAT = 0x9005 -}; - /* PHY loopback direction */ enum { PHY_LOOPBACK_TX = 1, @@ -583,11 +563,12 @@ struct cphy_ops { int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed, int *duplex, int *fc); int (*power_down)(struct cphy *phy, int enable); + + u32 mmds; }; /* A PHY instance */ struct cphy { - u8 addr; /* PHY address */ u8 modtype; /* PHY module type */ short priv; /* scratch pad */ unsigned int caps; /* PHY capabilities */ @@ -595,23 +576,23 @@ struct cphy { const char *desc; /* PHY description */ unsigned long fifo_errors; /* FIFO over/under-flows */ const struct cphy_ops *ops; /* PHY operations */ - int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*mdio_write)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + struct mdio_if_info mdio; }; /* Convenience MDIO read/write wrappers */ -static inline int mdio_read(struct cphy *phy, int mmd, int reg, - unsigned int *valp) +static inline int t3_mdio_read(struct cphy *phy, int mmd, int reg, + unsigned int *valp) { - return phy->mdio_read(phy->adapter, phy->addr, mmd, reg, valp); + int rc = phy->mdio.mdio_read(phy->mdio.dev, phy->mdio.prtad, mmd, reg); + *valp = (rc >= 0) ? rc : -1; + return (rc >= 0) ? 0 : rc; } -static inline int mdio_write(struct cphy *phy, int mmd, int reg, - unsigned int val) +static inline int t3_mdio_write(struct cphy *phy, int mmd, int reg, + unsigned int val) { - return phy->mdio_write(phy->adapter, phy->addr, mmd, reg, val); + return phy->mdio.mdio_write(phy->mdio.dev, phy->mdio.prtad, mmd, + reg, val); } /* Convenience initializer */ @@ -620,14 +601,16 @@ static inline void cphy_init(struct cphy *phy, struct adapter *adapter, const struct mdio_ops *mdio_ops, unsigned int caps, const char *desc) { - phy->addr = phy_addr; phy->caps = caps; phy->adapter = adapter; phy->desc = desc; phy->ops = phy_ops; if (mdio_ops) { - phy->mdio_read = mdio_ops->read; - phy->mdio_write = mdio_ops->write; + phy->mdio.prtad = phy_addr; + phy->mdio.mmds = phy_ops->mmds; + phy->mdio.mode_support = mdio_ops->mode_support; + phy->mdio.mdio_read = mdio_ops->read; + phy->mdio.mdio_write = mdio_ops->write; } } @@ -819,8 +802,12 @@ int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops); int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops); +int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, + int phy_addr, const struct mdio_ops *mdio_ops); int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops); int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops); +int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, + int phy_addr, const struct mdio_ops *mdio_ops); #endif /* __CHELSIO_COMMON_H */ diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 17858b9a5830..538dda4422dc 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,6 +91,8 @@ static const struct pci_device_id cxgb3_pci_tbl[] = { CH_DEVICE(0x31, 3), /* T3B20 */ CH_DEVICE(0x32, 1), /* T3B02 */ CH_DEVICE(0x35, 6), /* T3C20-derived T3C10 */ + CH_DEVICE(0x36, 3), /* S320E-CR */ + CH_DEVICE(0x37, 7), /* N320E-G2 */ {0,} }; @@ -431,40 +433,78 @@ static int init_tp_parity(struct adapter *adap) for (i = 0; i < 16; i++) { struct cpl_smt_write_req *req; - skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); + skb = alloc_skb(sizeof(*req), GFP_KERNEL); + if (!skb) + skb = adap->nofail_skb; + if (!skb) + goto alloc_skb_fail; + req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req)); 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->iff = i; t3_mgmt_tx(adap, skb); + if (skb == adap->nofail_skb) { + await_mgmt_replies(adap, cnt, i + 1); + adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL); + if (!adap->nofail_skb) + goto alloc_skb_fail; + } } for (i = 0; i < 2048; i++) { struct cpl_l2t_write_req *req; - skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); + skb = alloc_skb(sizeof(*req), GFP_KERNEL); + if (!skb) + skb = adap->nofail_skb; + if (!skb) + goto alloc_skb_fail; + req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req)); memset(req, 0, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, i)); req->params = htonl(V_L2T_W_IDX(i)); t3_mgmt_tx(adap, skb); + if (skb == adap->nofail_skb) { + await_mgmt_replies(adap, cnt, 16 + i + 1); + adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL); + if (!adap->nofail_skb) + goto alloc_skb_fail; + } } for (i = 0; i < 2048; i++) { struct cpl_rte_write_req *req; - skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); + skb = alloc_skb(sizeof(*req), GFP_KERNEL); + if (!skb) + skb = adap->nofail_skb; + if (!skb) + goto alloc_skb_fail; + req = (struct cpl_rte_write_req *)__skb_put(skb, sizeof(*req)); memset(req, 0, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RTE_WRITE_REQ, i)); req->l2t_idx = htonl(V_L2T_W_IDX(i)); t3_mgmt_tx(adap, skb); + if (skb == adap->nofail_skb) { + await_mgmt_replies(adap, cnt, 16 + 2048 + i + 1); + adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL); + if (!adap->nofail_skb) + goto alloc_skb_fail; + } } - skb = alloc_skb(sizeof(*greq), GFP_KERNEL | __GFP_NOFAIL); + skb = alloc_skb(sizeof(*greq), GFP_KERNEL); + if (!skb) + skb = adap->nofail_skb; + if (!skb) + goto alloc_skb_fail; + greq = (struct cpl_set_tcb_field *)__skb_put(skb, sizeof(*greq)); memset(greq, 0, sizeof(*greq)); greq->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); @@ -473,8 +513,17 @@ static int init_tp_parity(struct adapter *adap) t3_mgmt_tx(adap, skb); i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1); + if (skb == adap->nofail_skb) { + i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1); + adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL); + } + t3_tp_set_offload_mode(adap, 0); return i; + +alloc_skb_fail: + t3_tp_set_offload_mode(adap, 0); + return -ENOMEM; } /** @@ -869,7 +918,12 @@ static int send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, struct mngt_pktsched_wr *req; int ret; - skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); + skb = alloc_skb(sizeof(*req), GFP_KERNEL); + if (!skb) + skb = adap->nofail_skb; + if (!skb) + return -ENOMEM; + req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req)); req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT)); req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET; @@ -879,6 +933,12 @@ static int send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, req->max = hi; req->binding = port; ret = t3_mgmt_tx(adap, skb); + if (skb == adap->nofail_skb) { + adap->nofail_skb = alloc_skb(sizeof(struct cpl_set_tcb_field), + GFP_KERNEL); + if (!adap->nofail_skb) + ret = -ENOMEM; + } return ret; } @@ -1593,7 +1653,7 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) } cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - cmd->phy_address = p->phy.addr; + cmd->phy_address = p->phy.mdio.prtad; cmd->transceiver = XCVR_EXTERNAL; cmd->autoneg = p->link_config.autoneg; cmd->maxtxpkt = 0; @@ -2308,70 +2368,25 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) struct mii_ioctl_data *data = if_mii(req); struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - int ret, mmd; switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = pi->phy.addr; + case SIOCGMIIREG: + case SIOCSMIIREG: + /* Convert phy_id from older PRTAD/DEVAD format */ + if (is_10G(adapter) && + !mdio_phy_id_is_c45(data->phy_id) && + (data->phy_id & 0x1f00) && + !(data->phy_id & 0xe0e0)) + data->phy_id = mdio_phy_id_c45(data->phy_id >> 8, + data->phy_id & 0x1f); /* FALLTHRU */ - case SIOCGMIIREG:{ - u32 val; - struct cphy *phy = &pi->phy; - - if (!phy->mdio_read) - return -EOPNOTSUPP; - if (is_10G(adapter)) { - mmd = data->phy_id >> 8; - if (!mmd) - mmd = MDIO_DEV_PCS; - else if (mmd > MDIO_DEV_VEND2) - return -EINVAL; - - ret = - phy->mdio_read(adapter, data->phy_id & 0x1f, - mmd, data->reg_num, &val); - } else - ret = - phy->mdio_read(adapter, data->phy_id & 0x1f, - 0, data->reg_num & 0x1f, - &val); - if (!ret) - data->val_out = val; - break; - } - case SIOCSMIIREG:{ - struct cphy *phy = &pi->phy; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!phy->mdio_write) - return -EOPNOTSUPP; - if (is_10G(adapter)) { - mmd = data->phy_id >> 8; - if (!mmd) - mmd = MDIO_DEV_PCS; - else if (mmd > MDIO_DEV_VEND2) - return -EINVAL; - - ret = - phy->mdio_write(adapter, - data->phy_id & 0x1f, mmd, - data->reg_num, - data->val_in); - } else - ret = - phy->mdio_write(adapter, - data->phy_id & 0x1f, 0, - data->reg_num & 0x1f, - data->val_in); - break; - } + case SIOCGMIIPHY: + return mdio_mii_ioctl(&pi->phy.mdio, data, cmd); case SIOCCHIOCTL: return cxgb_extension_ioctl(dev, req->ifr_data); default: return -EOPNOTSUPP; } - return ret; } static int cxgb_change_mtu(struct net_device *dev, int new_mtu) @@ -3063,6 +3078,14 @@ static int __devinit init_one(struct pci_dev *pdev, goto out_disable_device; } + adapter->nofail_skb = + alloc_skb(sizeof(struct cpl_set_tcb_field), GFP_KERNEL); + if (!adapter->nofail_skb) { + dev_err(&pdev->dev, "cannot allocate nofail buffer\n"); + err = -ENOMEM; + goto out_free_adapter; + } + adapter->regs = ioremap_nocache(mmio_start, mmio_len); if (!adapter->regs) { dev_err(&pdev->dev, "cannot map device registers\n"); @@ -3106,7 +3129,6 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len - 1; netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; - netdev->features |= NETIF_F_LLTX; netdev->features |= NETIF_F_GRO; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -3220,6 +3242,8 @@ static void __devexit remove_one(struct pci_dev *pdev) free_netdev(adapter->port[i]); iounmap(adapter->regs); + if (adapter->nofail_skb) + kfree_skb(adapter->nofail_skb); kfree(adapter); pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index 620d80be6aac..f9f54b57b28c 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -566,13 +566,31 @@ static void t3_process_tid_release_list(struct work_struct *work) spin_unlock_bh(&td->tid_release_lock); skb = alloc_skb(sizeof(struct cpl_tid_release), - GFP_KERNEL | __GFP_NOFAIL); + GFP_KERNEL); + if (!skb) + skb = td->nofail_skb; + if (!skb) { + spin_lock_bh(&td->tid_release_lock); + p->ctx = (void *)td->tid_release_list; + td->tid_release_list = (struct t3c_tid_entry *)p; + break; + } mk_tid_release(skb, p - td->tid_maps.tid_tab); cxgb3_ofld_send(tdev, skb); p->ctx = NULL; + if (skb == td->nofail_skb) + td->nofail_skb = + alloc_skb(sizeof(struct cpl_tid_release), + GFP_KERNEL); spin_lock_bh(&td->tid_release_lock); } + td->release_list_incomplete = (td->tid_release_list == NULL) ? 0 : 1; spin_unlock_bh(&td->tid_release_lock); + + if (!td->nofail_skb) + td->nofail_skb = + alloc_skb(sizeof(struct cpl_tid_release), + GFP_KERNEL); } /* use ctx as a next pointer in the tid release list */ @@ -585,7 +603,7 @@ void cxgb3_queue_tid_release(struct t3cdev *tdev, unsigned int tid) p->ctx = (void *)td->tid_release_list; p->client = NULL; td->tid_release_list = p; - if (!p->ctx) + if (!p->ctx || td->release_list_incomplete) schedule_work(&td->tid_release_task); spin_unlock_bh(&td->tid_release_lock); } @@ -1274,6 +1292,9 @@ int cxgb3_offload_activate(struct adapter *adapter) if (list_empty(&adapter_list)) register_netevent_notifier(&nb); + t->nofail_skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_KERNEL); + t->release_list_incomplete = 0; + add_adapter(adapter); return 0; @@ -1298,6 +1319,8 @@ void cxgb3_offload_deactivate(struct adapter *adapter) T3C_DATA(tdev) = NULL; t3_free_l2t(L2DATA(tdev)); L2DATA(tdev) = NULL; + if (t->nofail_skb) + kfree_skb(t->nofail_skb); kfree(t); } diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h index a8e8e5fcdf84..55945f422aec 100644 --- a/drivers/net/cxgb3/cxgb3_offload.h +++ b/drivers/net/cxgb3/cxgb3_offload.h @@ -191,6 +191,9 @@ struct t3c_data { struct t3c_tid_entry *tid_release_list; spinlock_t tid_release_lock; struct work_struct tid_release_task; + + struct sk_buff *nofail_skb; + unsigned int release_list_incomplete; }; /* diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index b3ee2bc1a005..29c79eb43beb 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -653,7 +653,8 @@ static void t3_reset_qset(struct sge_qset *q) q->txq_stopped = 0; q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */ q->rx_reclaim_timer.function = NULL; - q->lro_frag_tbl.nr_frags = q->lro_frag_tbl.len = 0; + q->nomem = 0; + napi_free_frags(&q->napi); } @@ -1239,7 +1240,6 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) q = &qs->txq[TXQ_ETH]; txq = netdev_get_tx_queue(dev, qidx); - spin_lock(&q->lock); reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); credits = q->size - q->in_use; @@ -1250,7 +1250,6 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) dev_err(&adap->pdev->dev, "%s: Tx ring %u full while queue awake!\n", dev->name, q->cntxt_id & 7); - spin_unlock(&q->lock); return NETDEV_TX_BUSY; } @@ -1284,9 +1283,6 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) if (vlan_tx_tag_present(skb) && pi->vlan_grp) qs->port_stats[SGE_PSTAT_VLANINS]++; - dev->trans_start = jiffies; - spin_unlock(&q->lock); - /* * We do not use Tx completion interrupts to free DMAd Tx packets. * This is good for performamce but means that we rely on new Tx @@ -2073,20 +2069,19 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, struct sge_fl *fl, int len, int complete) { struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; + struct sk_buff *skb = NULL; struct cpl_rx_pkt *cpl; - struct skb_frag_struct *rx_frag = qs->lro_frag_tbl.frags; - int nr_frags = qs->lro_frag_tbl.nr_frags; - int frag_len = qs->lro_frag_tbl.len; + struct skb_frag_struct *rx_frag; + int nr_frags; int offset = 0; - if (!nr_frags) { - offset = 2 + sizeof(struct cpl_rx_pkt); - qs->lro_va = cpl = sd->pg_chunk.va + 2; + if (!qs->nomem) { + skb = napi_get_frags(&qs->napi); + qs->nomem = !skb; } fl->credits--; - len -= offset; pci_dma_sync_single_for_cpu(adap->pdev, pci_unmap_addr(sd, dma_addr), fl->buf_size - SGE_PG_RSVD, @@ -2099,21 +2094,38 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, fl->alloc_size, PCI_DMA_FROMDEVICE); + if (!skb) { + put_page(sd->pg_chunk.page); + if (complete) + qs->nomem = 0; + return; + } + + rx_frag = skb_shinfo(skb)->frags; + nr_frags = skb_shinfo(skb)->nr_frags; + + if (!nr_frags) { + offset = 2 + sizeof(struct cpl_rx_pkt); + qs->lro_va = sd->pg_chunk.va + 2; + } + len -= offset; + prefetch(qs->lro_va); rx_frag += nr_frags; rx_frag->page = sd->pg_chunk.page; rx_frag->page_offset = sd->pg_chunk.offset + offset; rx_frag->size = len; - frag_len += len; - qs->lro_frag_tbl.nr_frags++; - qs->lro_frag_tbl.len = frag_len; + skb->len += len; + skb->data_len += len; + skb->truesize += len; + skb_shinfo(skb)->nr_frags++; if (!complete) return; - qs->lro_frag_tbl.ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = CHECKSUM_UNNECESSARY; cpl = qs->lro_va; if (unlikely(cpl->vlan_valid)) { @@ -2122,15 +2134,11 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, struct vlan_group *grp = pi->vlan_grp; if (likely(grp != NULL)) { - vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan), - &qs->lro_frag_tbl); - goto out; + vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan)); + return; } } - napi_gro_frags(&qs->napi, &qs->lro_frag_tbl); - -out: - qs->lro_frag_tbl.nr_frags = qs->lro_frag_tbl.len = 0; + napi_gro_frags(&qs->napi); } /** @@ -2299,8 +2307,6 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, if (fl->use_pages) { void *addr = fl->sdesc[fl->cidx].pg_chunk.va; - prefetch(&qs->lro_frag_tbl); - prefetch(addr); #if L1_CACHE_BYTES < 128 prefetch(addr + L1_CACHE_BYTES); @@ -2846,11 +2852,12 @@ static void sge_timer_tx(unsigned long data) unsigned int tbd[SGE_TXQ_PER_SET] = {0, 0}; unsigned long next_period; - if (spin_trylock(&qs->txq[TXQ_ETH].lock)) { - tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH], - TX_RECLAIM_TIMER_CHUNK); - spin_unlock(&qs->txq[TXQ_ETH].lock); + if (__netif_tx_trylock(qs->tx_q)) { + tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH], + TX_RECLAIM_TIMER_CHUNK); + __netif_tx_unlock(qs->tx_q); } + if (spin_trylock(&qs->txq[TXQ_OFLD].lock)) { tbd[TXQ_OFLD] = reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD], TX_RECLAIM_TIMER_CHUNK); @@ -2858,8 +2865,8 @@ static void sge_timer_tx(unsigned long data) } next_period = TX_RECLAIM_PERIOD >> - (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) / - TX_RECLAIM_TIMER_CHUNK); + (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) / + TX_RECLAIM_TIMER_CHUNK); mod_timer(&qs->tx_reclaim_timer, jiffies + next_period); } diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 4950d5d789ae..870d44992c70 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -204,35 +204,33 @@ static void mi1_init(struct adapter *adap, const struct adapter_info *ai) /* * MI1 read/write operations for clause 22 PHYs. */ -static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); - if (mmd_addr) - return -EINVAL; - mutex_lock(&adapter->mdio_lock); t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); t3_write_reg(adapter, A_MI1_ADDR, addr); t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); if (!ret) - *valp = t3_read_reg(adapter, A_MI1_DATA); + ret = t3_read_reg(adapter, A_MI1_DATA); mutex_unlock(&adapter->mdio_lock); return ret; } -static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); - if (mmd_addr) - return -EINVAL; - mutex_lock(&adapter->mdio_lock); t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); t3_write_reg(adapter, A_MI1_ADDR, addr); @@ -244,8 +242,9 @@ static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, } static const struct mdio_ops mi1_mdio_ops = { - t3_mi1_read, - t3_mi1_write + .read = t3_mi1_read, + .write = t3_mi1_write, + .mode_support = MDIO_SUPPORTS_C22 }; /* @@ -268,9 +267,11 @@ static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr, /* * MI1 read/write operations for indirect-addressed PHYs. */ -static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; mutex_lock(&adapter->mdio_lock); @@ -280,15 +281,17 @@ static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); if (!ret) - *valp = t3_read_reg(adapter, A_MI1_DATA); + ret = t3_read_reg(adapter, A_MI1_DATA); } mutex_unlock(&adapter->mdio_lock); return ret; } -static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; mutex_lock(&adapter->mdio_lock); @@ -304,8 +307,9 @@ static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, } static const struct mdio_ops mi1_mdio_ext_ops = { - mi1_ext_read, - mi1_ext_write + .read = mi1_ext_read, + .write = mi1_ext_write, + .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22 }; /** @@ -325,10 +329,10 @@ int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, int ret; unsigned int val; - ret = mdio_read(phy, mmd, reg, &val); + ret = t3_mdio_read(phy, mmd, reg, &val); if (!ret) { val &= ~clear; - ret = mdio_write(phy, mmd, reg, val | set); + ret = t3_mdio_write(phy, mmd, reg, val | set); } return ret; } @@ -348,15 +352,16 @@ int t3_phy_reset(struct cphy *phy, int mmd, int wait) int err; unsigned int ctl; - err = t3_mdio_change_bits(phy, mmd, MII_BMCR, BMCR_PDOWN, BMCR_RESET); + err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER, + MDIO_CTRL1_RESET); if (err || !wait) return err; do { - err = mdio_read(phy, mmd, MII_BMCR, &ctl); + err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl); if (err) return err; - ctl &= BMCR_RESET; + ctl &= MDIO_CTRL1_RESET; if (ctl) msleep(1); } while (ctl && --wait); @@ -377,7 +382,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) int err; unsigned int val = 0; - err = mdio_read(phy, 0, MII_CTRL1000, &val); + err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val); if (err) return err; @@ -387,7 +392,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) if (advert & ADVERTISED_1000baseT_Full) val |= ADVERTISE_1000FULL; - err = mdio_write(phy, 0, MII_CTRL1000, val); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val); if (err) return err; @@ -404,7 +409,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) val |= ADVERTISE_PAUSE_CAP; if (advert & ADVERTISED_Asym_Pause) val |= ADVERTISE_PAUSE_ASYM; - return mdio_write(phy, 0, MII_ADVERTISE, val); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val); } /** @@ -427,7 +432,7 @@ int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert) val |= ADVERTISE_1000XPAUSE; if (advert & ADVERTISED_Asym_Pause) val |= ADVERTISE_1000XPSE_ASYM; - return mdio_write(phy, 0, MII_ADVERTISE, val); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val); } /** @@ -444,7 +449,7 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) int err; unsigned int ctl; - err = mdio_read(phy, 0, MII_BMCR, &ctl); + err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl); if (err) return err; @@ -462,34 +467,36 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) } if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */ ctl |= BMCR_ANENABLE; - return mdio_write(phy, 0, MII_BMCR, ctl); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl); } int t3_phy_lasi_intr_enable(struct cphy *phy) { - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); + return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, + MDIO_PMA_LASI_LSALARM); } int t3_phy_lasi_intr_disable(struct cphy *phy) { - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); + return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0); } int t3_phy_lasi_intr_clear(struct cphy *phy) { u32 val; - return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); + return t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); } int t3_phy_lasi_intr_handler(struct cphy *phy) { unsigned int status; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, + &status); if (err) return err; - return (status & 1) ? cphy_cause_link_change : 0; + return (status & MDIO_PMA_LASI_LSALARM) ? cphy_cause_link_change : 0; } static const struct adapter_info t3_adap_info[] = { @@ -519,6 +526,11 @@ static const struct adapter_info t3_adap_info[] = { F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T310" }, + {1, 0, 0, + F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | + F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL, + { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, + &mi1_mdio_ext_ops, "Chelsio N320E-G2" }, }; /* @@ -545,6 +557,8 @@ static const struct port_type_info port_types[] = { { t3_qt2045_phy_prep }, { t3_ael1006_phy_prep }, { NULL }, + { t3_aq100x_phy_prep }, + { t3_ael2020_phy_prep }, }; #define VPD_ENTRY(name, len) \ @@ -3864,6 +3878,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, return -EINVAL; } + p->phy.mdio.dev = adapter->port[i]; ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, ai->mdio_ops); if (ret) @@ -3923,7 +3938,7 @@ int t3_replay_prep_adapter(struct adapter *adapter) ; pti = &port_types[adapter->params.vpd.port_type[j]]; - ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL); + ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL); if (ret) return ret; p->phy.ops->power_down(&p->phy, 1); diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index 7bf963ec5548..9d0bd9dd9ab1 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -35,10 +35,10 @@ #define DRV_DESC "Chelsio T3 Network Driver" #define DRV_NAME "cxgb3" /* Driver version */ -#define DRV_VERSION "1.1.2-ko" +#define DRV_VERSION "1.1.3-ko" /* Firmware version */ #define FW_VERSION_MAJOR 7 -#define FW_VERSION_MINOR 1 +#define FW_VERSION_MINOR 4 #define FW_VERSION_MICRO 0 #endif /* __CHELSIO_VERSION_H */ diff --git a/drivers/net/cxgb3/vsc8211.c b/drivers/net/cxgb3/vsc8211.c index d07130971b8f..4f9a1c2724f4 100644 --- a/drivers/net/cxgb3/vsc8211.c +++ b/drivers/net/cxgb3/vsc8211.c @@ -91,17 +91,18 @@ enum { */ static int vsc8211_reset(struct cphy *cphy, int wait) { - return t3_phy_reset(cphy, 0, 0); + return t3_phy_reset(cphy, MDIO_DEVAD_NONE, 0); } static int vsc8211_intr_enable(struct cphy *cphy) { - return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, INTR_MASK); + return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE, + INTR_MASK); } static int vsc8211_intr_disable(struct cphy *cphy) { - return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, 0); + return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE, 0); } static int vsc8211_intr_clear(struct cphy *cphy) @@ -109,18 +110,20 @@ static int vsc8211_intr_clear(struct cphy *cphy) u32 val; /* Clear PHY interrupts by reading the register. */ - return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val); + return t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &val); } static int vsc8211_autoneg_enable(struct cphy *cphy) { - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, + return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR, + BMCR_PDOWN | BMCR_ISOLATE, BMCR_ANENABLE | BMCR_ANRESTART); } static int vsc8211_autoneg_restart(struct cphy *cphy) { - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, + return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR, + BMCR_PDOWN | BMCR_ISOLATE, BMCR_ANRESTART); } @@ -130,9 +133,9 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, unsigned int bmcr, status, lpa, adv; int err, sp = -1, dplx = -1, pause = 0; - err = mdio_read(cphy, 0, MII_BMCR, &bmcr); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr); if (!err) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status); if (err) return err; @@ -142,7 +145,8 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, * once more to get the current link state. */ if (!(status & BMSR_LSTATUS)) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, + &status); if (err) return err; *link_ok = (status & BMSR_LSTATUS) != 0; @@ -156,7 +160,8 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, else sp = SPEED_10; } else if (status & BMSR_ANEGCOMPLETE) { - err = mdio_read(cphy, 0, VSC8211_AUX_CTRL_STAT, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_AUX_CTRL_STAT, + &status); if (err) return err; @@ -170,9 +175,11 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, sp = SPEED_1000; if (fc && dplx == DUPLEX_FULL) { - err = mdio_read(cphy, 0, MII_LPA, &lpa); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA, + &lpa); if (!err) - err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, + MII_ADVERTISE, &adv); if (err) return err; @@ -202,9 +209,9 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, unsigned int bmcr, status, lpa, adv; int err, sp = -1, dplx = -1, pause = 0; - err = mdio_read(cphy, 0, MII_BMCR, &bmcr); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr); if (!err) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status); if (err) return err; @@ -214,7 +221,8 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, * once more to get the current link state. */ if (!(status & BMSR_LSTATUS)) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, + &status); if (err) return err; *link_ok = (status & BMSR_LSTATUS) != 0; @@ -228,9 +236,10 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, else sp = SPEED_10; } else if (status & BMSR_ANEGCOMPLETE) { - err = mdio_read(cphy, 0, MII_LPA, &lpa); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA, &lpa); if (!err) - err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_ADVERTISE, + &adv); if (err) return err; @@ -270,23 +279,23 @@ static int vsc8211_set_automdi(struct cphy *phy, int enable) { int err; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0x52b5); if (err) return err; - err = mdio_write(phy, 0, 18, 0x12); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 18, 0x12); if (err) return err; - err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 17, enable ? 0x2803 : 0x3003); if (err) return err; - err = mdio_write(phy, 0, 16, 0x87fa); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 16, 0x87fa); if (err) return err; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0); if (err) return err; @@ -315,7 +324,7 @@ static int vsc8211_intr_handler(struct cphy *cphy) unsigned int cause; int err, cphy_cause = 0; - err = mdio_read(cphy, 0, VSC8211_INTR_STATUS, &cause); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &cause); if (err) return err; @@ -367,12 +376,13 @@ int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T"); msleep(20); /* PHY needs ~10ms to start responding to MDIO */ - err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val); + err = t3_mdio_read(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL, &val); if (err) return err; if (val & VSC_CTRL_MEDIA_MODE_HI) { /* copper interface, just need to configure the LEDs */ - return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_LED_CTRL, + 0x100); } phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | @@ -380,20 +390,20 @@ int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, phy->desc = "1000BASE-X"; phy->ops = &vsc8211_fiber_ops; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 1); if (err) return err; - err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_SIGDET_CTRL, 1); if (err) return err; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0); if (err) return err; - err = mdio_write(phy, 0, VSC8211_EXT_CTRL, - val | VSC_CTRL_CLAUSE37_VIEW); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL, + val | VSC_CTRL_CLAUSE37_VIEW); if (err) return err; diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c new file mode 100644 index 000000000000..0e9b9f9632c1 --- /dev/null +++ b/drivers/net/davinci_emac.c @@ -0,0 +1,2830 @@ +/* + * DaVinci Ethernet Medium Access Controller + * + * DaVinci EMAC is based upon CPPI 3.0 TI DMA engine + * + * Copyright (C) 2009 Texas Instruments. + * + * --------------------------------------------------------------------------- + * + * 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. + * --------------------------------------------------------------------------- + * History: + * 0-5 A number of folks worked on this driver in bits and pieces but the major + * contribution came from Suraj Iyer and Anant Gole + * 6.0 Anant Gole - rewrote the driver as per Linux conventions + * 6.1 Chaithrika U S - added support for Gigabit and RMII features, + * PHY layer usage + */ + +/** Pending Items in this driver: + * 1. Use Linux cache infrastcture for DMA'ed memory (dma_xxx functions) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static int debug_level; +module_param(debug_level, int, 0); +MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); + +/* Netif debug messages possible */ +#define DAVINCI_EMAC_DEBUG (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_TIMER | \ + NETIF_MSG_IFDOWN | \ + NETIF_MSG_IFUP | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR | \ + NETIF_MSG_TX_QUEUED | \ + NETIF_MSG_INTR | \ + NETIF_MSG_TX_DONE | \ + NETIF_MSG_RX_STATUS | \ + NETIF_MSG_PKTDATA | \ + NETIF_MSG_HW | \ + NETIF_MSG_WOL) + +/* version info */ +#define EMAC_MAJOR_VERSION 6 +#define EMAC_MINOR_VERSION 1 +#define EMAC_MODULE_VERSION "6.1" +MODULE_VERSION(EMAC_MODULE_VERSION); +static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; + +/* Configuration items */ +#define EMAC_DEF_PASS_CRC (0) /* Do not pass CRC upto frames */ +#define EMAC_DEF_QOS_EN (0) /* EMAC proprietary QoS disabled */ +#define EMAC_DEF_NO_BUFF_CHAIN (0) /* No buffer chain */ +#define EMAC_DEF_MACCTRL_FRAME_EN (0) /* Discard Maccontrol frames */ +#define EMAC_DEF_SHORT_FRAME_EN (0) /* Discard short frames */ +#define EMAC_DEF_ERROR_FRAME_EN (0) /* Discard error frames */ +#define EMAC_DEF_PROM_EN (0) /* Promiscous disabled */ +#define EMAC_DEF_PROM_CH (0) /* Promiscous channel is 0 */ +#define EMAC_DEF_BCAST_EN (1) /* Broadcast enabled */ +#define EMAC_DEF_BCAST_CH (0) /* Broadcast channel is 0 */ +#define EMAC_DEF_MCAST_EN (1) /* Multicast enabled */ +#define EMAC_DEF_MCAST_CH (0) /* Multicast channel is 0 */ + +#define EMAC_DEF_TXPRIO_FIXED (1) /* TX Priority is fixed */ +#define EMAC_DEF_TXPACING_EN (0) /* TX pacing NOT supported*/ + +#define EMAC_DEF_BUFFER_OFFSET (0) /* Buffer offset to DMA (future) */ +#define EMAC_DEF_MIN_ETHPKTSIZE (60) /* Minimum ethernet pkt size */ +#define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) +#define EMAC_DEF_TX_CH (0) /* Default 0th channel */ +#define EMAC_DEF_RX_CH (0) /* Default 0th channel */ +#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ +#define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ +#define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ +#define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ + +/* Buffer descriptor parameters */ +#define EMAC_DEF_TX_MAX_SERVICE (32) /* TX max service BD's */ +#define EMAC_DEF_RX_MAX_SERVICE (64) /* should = netdev->weight */ + +/* EMAC register related defines */ +#define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) +#define EMAC_NUM_MULTICAST_BITS (64) +#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) +#define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) +#define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) +#define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) +#define EMAC_RX_UNICAST_CLEAR_ALL (0xFF) +#define EMAC_INT_MASK_CLEAR (0xFF) + +/* RX MBP register bit positions */ +#define EMAC_RXMBP_PASSCRC_MASK BIT(30) +#define EMAC_RXMBP_QOSEN_MASK BIT(29) +#define EMAC_RXMBP_NOCHAIN_MASK BIT(28) +#define EMAC_RXMBP_CMFEN_MASK BIT(24) +#define EMAC_RXMBP_CSFEN_MASK BIT(23) +#define EMAC_RXMBP_CEFEN_MASK BIT(22) +#define EMAC_RXMBP_CAFEN_MASK BIT(21) +#define EMAC_RXMBP_PROMCH_SHIFT (16) +#define EMAC_RXMBP_PROMCH_MASK (0x7 << 16) +#define EMAC_RXMBP_BROADEN_MASK BIT(13) +#define EMAC_RXMBP_BROADCH_SHIFT (8) +#define EMAC_RXMBP_BROADCH_MASK (0x7 << 8) +#define EMAC_RXMBP_MULTIEN_MASK BIT(5) +#define EMAC_RXMBP_MULTICH_SHIFT (0) +#define EMAC_RXMBP_MULTICH_MASK (0x7) +#define EMAC_RXMBP_CHMASK (0x7) + +/* EMAC register definitions/bit maps used */ +# define EMAC_MBP_RXPROMISC (0x00200000) +# define EMAC_MBP_PROMISCCH(ch) (((ch) & 0x7) << 16) +# define EMAC_MBP_RXBCAST (0x00002000) +# define EMAC_MBP_BCASTCHAN(ch) (((ch) & 0x7) << 8) +# define EMAC_MBP_RXMCAST (0x00000020) +# define EMAC_MBP_MCASTCHAN(ch) ((ch) & 0x7) + +/* EMAC mac_control register */ +#define EMAC_MACCONTROL_TXPTYPE (0x200) +#define EMAC_MACCONTROL_TXPACEEN (0x40) +#define EMAC_MACCONTROL_MIIEN (0x20) +#define EMAC_MACCONTROL_GIGABITEN (0x80) +#define EMAC_MACCONTROL_GIGABITEN_SHIFT (7) +#define EMAC_MACCONTROL_FULLDUPLEXEN (0x1) +#define EMAC_MACCONTROL_RMIISPEED_MASK BIT(15) + +/* GIGABIT MODE related bits */ +#define EMAC_DM646X_MACCONTORL_GMIIEN BIT(5) +#define EMAC_DM646X_MACCONTORL_GIG BIT(7) +#define EMAC_DM646X_MACCONTORL_GIGFORCE BIT(17) + +/* EMAC mac_status register */ +#define EMAC_MACSTATUS_TXERRCODE_MASK (0xF00000) +#define EMAC_MACSTATUS_TXERRCODE_SHIFT (20) +#define EMAC_MACSTATUS_TXERRCH_MASK (0x7) +#define EMAC_MACSTATUS_TXERRCH_SHIFT (16) +#define EMAC_MACSTATUS_RXERRCODE_MASK (0xF000) +#define EMAC_MACSTATUS_RXERRCODE_SHIFT (12) +#define EMAC_MACSTATUS_RXERRCH_MASK (0x7) +#define EMAC_MACSTATUS_RXERRCH_SHIFT (8) + +/* EMAC RX register masks */ +#define EMAC_RX_MAX_LEN_MASK (0xFFFF) +#define EMAC_RX_BUFFER_OFFSET_MASK (0xFFFF) + +/* MAC_IN_VECTOR (0x180) register bit fields */ +#define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT (0x20000) +#define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT (0x10000) +#define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC (0x0100) +#define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC (0x01) + +/** NOTE:: For DM646x the IN_VECTOR has changed */ +#define EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC BIT(EMAC_DEF_RX_CH) +#define EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC BIT(16 + EMAC_DEF_TX_CH) + +/* CPPI bit positions */ +#define EMAC_CPPI_SOP_BIT BIT(31) +#define EMAC_CPPI_EOP_BIT BIT(30) +#define EMAC_CPPI_OWNERSHIP_BIT BIT(29) +#define EMAC_CPPI_EOQ_BIT BIT(28) +#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT BIT(27) +#define EMAC_CPPI_PASS_CRC_BIT BIT(26) +#define EMAC_RX_BD_BUF_SIZE (0xFFFF) +#define EMAC_BD_LENGTH_FOR_CACHE (16) /* only CPPI bytes */ +#define EMAC_RX_BD_PKT_LENGTH_MASK (0xFFFF) + +/* Max hardware defines */ +#define EMAC_MAX_TXRX_CHANNELS (8) /* Max hardware channels */ +#define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ + +/* EMAC Peripheral Device Register Memory Layout structure */ +#define EMAC_TXIDVER 0x0 +#define EMAC_TXCONTROL 0x4 +#define EMAC_TXTEARDOWN 0x8 +#define EMAC_RXIDVER 0x10 +#define EMAC_RXCONTROL 0x14 +#define EMAC_RXTEARDOWN 0x18 +#define EMAC_TXINTSTATRAW 0x80 +#define EMAC_TXINTSTATMASKED 0x84 +#define EMAC_TXINTMASKSET 0x88 +#define EMAC_TXINTMASKCLEAR 0x8C +#define EMAC_MACINVECTOR 0x90 + +#define EMAC_DM646X_MACEOIVECTOR 0x94 + +#define EMAC_RXINTSTATRAW 0xA0 +#define EMAC_RXINTSTATMASKED 0xA4 +#define EMAC_RXINTMASKSET 0xA8 +#define EMAC_RXINTMASKCLEAR 0xAC +#define EMAC_MACINTSTATRAW 0xB0 +#define EMAC_MACINTSTATMASKED 0xB4 +#define EMAC_MACINTMASKSET 0xB8 +#define EMAC_MACINTMASKCLEAR 0xBC + +#define EMAC_RXMBPENABLE 0x100 +#define EMAC_RXUNICASTSET 0x104 +#define EMAC_RXUNICASTCLEAR 0x108 +#define EMAC_RXMAXLEN 0x10C +#define EMAC_RXBUFFEROFFSET 0x110 +#define EMAC_RXFILTERLOWTHRESH 0x114 + +#define EMAC_MACCONTROL 0x160 +#define EMAC_MACSTATUS 0x164 +#define EMAC_EMCONTROL 0x168 +#define EMAC_FIFOCONTROL 0x16C +#define EMAC_MACCONFIG 0x170 +#define EMAC_SOFTRESET 0x174 +#define EMAC_MACSRCADDRLO 0x1D0 +#define EMAC_MACSRCADDRHI 0x1D4 +#define EMAC_MACHASH1 0x1D8 +#define EMAC_MACHASH2 0x1DC +#define EMAC_MACADDRLO 0x500 +#define EMAC_MACADDRHI 0x504 +#define EMAC_MACINDEX 0x508 + +/* EMAC HDP and Completion registors */ +#define EMAC_TXHDP(ch) (0x600 + (ch * 4)) +#define EMAC_RXHDP(ch) (0x620 + (ch * 4)) +#define EMAC_TXCP(ch) (0x640 + (ch * 4)) +#define EMAC_RXCP(ch) (0x660 + (ch * 4)) + +/* EMAC statistics registers */ +#define EMAC_RXGOODFRAMES 0x200 +#define EMAC_RXBCASTFRAMES 0x204 +#define EMAC_RXMCASTFRAMES 0x208 +#define EMAC_RXPAUSEFRAMES 0x20C +#define EMAC_RXCRCERRORS 0x210 +#define EMAC_RXALIGNCODEERRORS 0x214 +#define EMAC_RXOVERSIZED 0x218 +#define EMAC_RXJABBER 0x21C +#define EMAC_RXUNDERSIZED 0x220 +#define EMAC_RXFRAGMENTS 0x224 +#define EMAC_RXFILTERED 0x228 +#define EMAC_RXQOSFILTERED 0x22C +#define EMAC_RXOCTETS 0x230 +#define EMAC_TXGOODFRAMES 0x234 +#define EMAC_TXBCASTFRAMES 0x238 +#define EMAC_TXMCASTFRAMES 0x23C +#define EMAC_TXPAUSEFRAMES 0x240 +#define EMAC_TXDEFERRED 0x244 +#define EMAC_TXCOLLISION 0x248 +#define EMAC_TXSINGLECOLL 0x24C +#define EMAC_TXMULTICOLL 0x250 +#define EMAC_TXEXCESSIVECOLL 0x254 +#define EMAC_TXLATECOLL 0x258 +#define EMAC_TXUNDERRUN 0x25C +#define EMAC_TXCARRIERSENSE 0x260 +#define EMAC_TXOCTETS 0x264 +#define EMAC_NETOCTETS 0x280 +#define EMAC_RXSOFOVERRUNS 0x284 +#define EMAC_RXMOFOVERRUNS 0x288 +#define EMAC_RXDMAOVERRUNS 0x28C + +/* EMAC DM644x control registers */ +#define EMAC_CTRL_EWCTL (0x4) +#define EMAC_CTRL_EWINTTCNT (0x8) + +/* EMAC MDIO related */ +/* Mask & Control defines */ +#define MDIO_CONTROL_CLKDIV (0xFF) +#define MDIO_CONTROL_ENABLE BIT(30) +#define MDIO_USERACCESS_GO BIT(31) +#define MDIO_USERACCESS_WRITE BIT(30) +#define MDIO_USERACCESS_READ (0) +#define MDIO_USERACCESS_REGADR (0x1F << 21) +#define MDIO_USERACCESS_PHYADR (0x1F << 16) +#define MDIO_USERACCESS_DATA (0xFFFF) +#define MDIO_USERPHYSEL_LINKSEL BIT(7) +#define MDIO_VER_MODID (0xFFFF << 16) +#define MDIO_VER_REVMAJ (0xFF << 8) +#define MDIO_VER_REVMIN (0xFF) + +#define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) +#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) +#define MDIO_CONTROL (0x04) + +/* EMAC DM646X control module registers */ +#define EMAC_DM646X_CMRXINTEN (0x14) +#define EMAC_DM646X_CMTXINTEN (0x18) + +/* EMAC EOI codes for C0 */ +#define EMAC_DM646X_MAC_EOI_C0_RXEN (0x01) +#define EMAC_DM646X_MAC_EOI_C0_TXEN (0x02) + +/** net_buf_obj: EMAC network bufferdata structure + * + * EMAC network buffer data structure + */ +struct emac_netbufobj { + void *buf_token; + char *data_ptr; + int length; +}; + +/** net_pkt_obj: EMAC network packet data structure + * + * EMAC network packet data structure - supports buffer list (for future) + */ +struct emac_netpktobj { + void *pkt_token; /* data token may hold tx/rx chan id */ + struct emac_netbufobj *buf_list; /* array of network buffer objects */ + int num_bufs; + int pkt_length; +}; + +/** emac_tx_bd: EMAC TX Buffer descriptor data structure + * + * EMAC TX Buffer descriptor data structure + */ +struct emac_tx_bd { + int h_next; + int buff_ptr; + int off_b_len; + int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ + struct emac_tx_bd __iomem *next; + void *buf_token; +}; + +/** emac_txch: EMAC TX Channel data structure + * + * EMAC TX Channel data structure + */ +struct emac_txch { + /* Config related */ + u32 num_bd; + u32 service_max; + + /* CPPI specific */ + u32 alloc_size; + void __iomem *bd_mem; + struct emac_tx_bd __iomem *bd_pool_head; + struct emac_tx_bd __iomem *active_queue_head; + struct emac_tx_bd __iomem *active_queue_tail; + struct emac_tx_bd __iomem *last_hw_bdprocessed; + u32 queue_active; + u32 teardown_pending; + u32 *tx_complete; + + /** statistics */ + u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ + u32 mis_queued_packets; + u32 queue_reinit; + u32 end_of_queue_add; + u32 out_of_tx_bd; + u32 no_active_pkts; /* IRQ when there were no packets to process */ + u32 active_queue_count; +}; + +/** emac_rx_bd: EMAC RX Buffer descriptor data structure + * + * EMAC RX Buffer descriptor data structure + */ +struct emac_rx_bd { + int h_next; + int buff_ptr; + int off_b_len; + int mode; + struct emac_rx_bd __iomem *next; + void *data_ptr; + void *buf_token; +}; + +/** emac_rxch: EMAC RX Channel data structure + * + * EMAC RX Channel data structure + */ +struct emac_rxch { + /* configuration info */ + u32 num_bd; + u32 service_max; + u32 buf_size; + char mac_addr[6]; + + /** CPPI specific */ + u32 alloc_size; + void __iomem *bd_mem; + struct emac_rx_bd __iomem *bd_pool_head; + struct emac_rx_bd __iomem *active_queue_head; + struct emac_rx_bd __iomem *active_queue_tail; + u32 queue_active; + u32 teardown_pending; + + /* packet and buffer objects */ + struct emac_netpktobj pkt_queue; + struct emac_netbufobj buf_queue; + + /** statistics */ + u32 proc_count; /* number of times emac_rx_bdproc is called */ + u32 processed_bd; + u32 recycled_bd; + u32 out_of_rx_bd; + u32 out_of_rx_buffers; + u32 queue_reinit; + u32 end_of_queue_add; + u32 end_of_queue; + u32 mis_queued_packets; +}; + +/* emac_priv: EMAC private data structure + * + * EMAC adapter private data structure + */ +struct emac_priv { + u32 msg_enable; + struct net_device *ndev; + struct platform_device *pdev; + struct napi_struct napi; + char mac_addr[6]; + spinlock_t tx_lock; + spinlock_t rx_lock; + void __iomem *remap_addr; + u32 emac_base_phys; + void __iomem *emac_base; + void __iomem *ctrl_base; + void __iomem *emac_ctrl_ram; + u32 ctrl_ram_size; + struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; + struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; + u32 link; /* 1=link on, 0=link off */ + u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ + u32 duplex; /* Link duplex: 0=Half, 1=Full */ + u32 rx_buf_size; + u32 isr_count; + u8 rmii_en; + u8 version; + struct net_device_stats net_dev_stats; + u32 mac_hash1; + u32 mac_hash2; + u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; + u32 rx_addr_type; + /* periodic timer required for MDIO polling */ + struct timer_list periodic_timer; + u32 periodic_ticks; + u32 timer_active; + u32 phy_mask; + /* mii_bus,phy members */ + struct mii_bus *mii_bus; + struct phy_device *phydev; + spinlock_t lock; +}; + +/* clock frequency for EMAC */ +static struct clk *emac_clk; +static unsigned long emac_bus_frequency; +static unsigned long mdio_max_freq; + +/* EMAC internal utility function */ +static inline u32 emac_virt_to_phys(void __iomem *addr) +{ + return (u32 __force) io_v2p(addr); +} + +/* Cache macros - Packet buffers would be from skb pool which is cached */ +#define EMAC_VIRT_NOCACHE(addr) (addr) +#define EMAC_CACHE_INVALIDATE(addr, size) \ + dma_cache_maint((void *)addr, size, DMA_FROM_DEVICE) +#define EMAC_CACHE_WRITEBACK(addr, size) \ + dma_cache_maint((void *)addr, size, DMA_TO_DEVICE) +#define EMAC_CACHE_WRITEBACK_INVALIDATE(addr, size) \ + dma_cache_maint((void *)addr, size, DMA_BIDIRECTIONAL) + +/* DM644x does not have BD's in cached memory - so no cache functions */ +#define BD_CACHE_INVALIDATE(addr, size) +#define BD_CACHE_WRITEBACK(addr, size) +#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) + +/* EMAC TX Host Error description strings */ +static char *emac_txhost_errcodes[16] = { + "No error", "SOP error", "Ownership bit not set in SOP buffer", + "Zero Next Buffer Descriptor Pointer Without EOP", + "Zero Buffer Pointer", "Zero Buffer Length", "Packet Length Error", + "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved" +}; + +/* EMAC RX Host Error description strings */ +static char *emac_rxhost_errcodes[16] = { + "No error", "Reserved", "Ownership bit not set in input buffer", + "Reserved", "Zero Buffer Pointer", "Reserved", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved" +}; + +/* Helper macros */ +#define emac_read(reg) ioread32(priv->emac_base + (reg)) +#define emac_write(reg, val) iowrite32(val, priv->emac_base + (reg)) + +#define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) +#define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) + +#define emac_mdio_read(reg) ioread32(bus->priv + (reg)) +#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) + +/** + * emac_dump_regs: Dump important EMAC registers to debug terminal + * @priv: The DaVinci EMAC private adapter structure + * + * Executes ethtool set cmd & sets phy mode + * + */ +static void emac_dump_regs(struct emac_priv *priv) +{ + struct device *emac_dev = &priv->ndev->dev; + + /* Print important registers in EMAC */ + dev_info(emac_dev, "EMAC Basic registers\n"); + dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n", + emac_ctrl_read(EMAC_CTRL_EWCTL), + emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); + dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", + emac_read(EMAC_TXIDVER), + ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), + emac_read(EMAC_RXIDVER), + ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); + dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ + "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), + emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); + dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ + "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), + emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); + dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ + "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), + emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); + dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", + emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); + dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ + "RXMaxLen=%08X\n", emac_read(EMAC_RXMBPENABLE), + emac_read(EMAC_RXUNICASTSET), emac_read(EMAC_RXMAXLEN)); + dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ + "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), + emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); + dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", + emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); + dev_info(emac_dev, "EMAC Statistics\n"); + dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", + emac_read(EMAC_RXGOODFRAMES)); + dev_info(emac_dev, "EMAC: rx_broadcast_frames:%d\n", + emac_read(EMAC_RXBCASTFRAMES)); + dev_info(emac_dev, "EMAC: rx_multicast_frames:%d\n", + emac_read(EMAC_RXMCASTFRAMES)); + dev_info(emac_dev, "EMAC: rx_pause_frames:%d\n", + emac_read(EMAC_RXPAUSEFRAMES)); + dev_info(emac_dev, "EMAC: rx_crcerrors:%d\n", + emac_read(EMAC_RXCRCERRORS)); + dev_info(emac_dev, "EMAC: rx_align_code_errors:%d\n", + emac_read(EMAC_RXALIGNCODEERRORS)); + dev_info(emac_dev, "EMAC: rx_oversized_frames:%d\n", + emac_read(EMAC_RXOVERSIZED)); + dev_info(emac_dev, "EMAC: rx_jabber_frames:%d\n", + emac_read(EMAC_RXJABBER)); + dev_info(emac_dev, "EMAC: rx_undersized_frames:%d\n", + emac_read(EMAC_RXUNDERSIZED)); + dev_info(emac_dev, "EMAC: rx_fragments:%d\n", + emac_read(EMAC_RXFRAGMENTS)); + dev_info(emac_dev, "EMAC: rx_filtered_frames:%d\n", + emac_read(EMAC_RXFILTERED)); + dev_info(emac_dev, "EMAC: rx_qos_filtered_frames:%d\n", + emac_read(EMAC_RXQOSFILTERED)); + dev_info(emac_dev, "EMAC: rx_octets:%d\n", + emac_read(EMAC_RXOCTETS)); + dev_info(emac_dev, "EMAC: tx_goodframes:%d\n", + emac_read(EMAC_TXGOODFRAMES)); + dev_info(emac_dev, "EMAC: tx_bcastframes:%d\n", + emac_read(EMAC_TXBCASTFRAMES)); + dev_info(emac_dev, "EMAC: tx_mcastframes:%d\n", + emac_read(EMAC_TXMCASTFRAMES)); + dev_info(emac_dev, "EMAC: tx_pause_frames:%d\n", + emac_read(EMAC_TXPAUSEFRAMES)); + dev_info(emac_dev, "EMAC: tx_deferred_frames:%d\n", + emac_read(EMAC_TXDEFERRED)); + dev_info(emac_dev, "EMAC: tx_collision_frames:%d\n", + emac_read(EMAC_TXCOLLISION)); + dev_info(emac_dev, "EMAC: tx_single_coll_frames:%d\n", + emac_read(EMAC_TXSINGLECOLL)); + dev_info(emac_dev, "EMAC: tx_mult_coll_frames:%d\n", + emac_read(EMAC_TXMULTICOLL)); + dev_info(emac_dev, "EMAC: tx_excessive_collisions:%d\n", + emac_read(EMAC_TXEXCESSIVECOLL)); + dev_info(emac_dev, "EMAC: tx_late_collisions:%d\n", + emac_read(EMAC_TXLATECOLL)); + dev_info(emac_dev, "EMAC: tx_underrun:%d\n", + emac_read(EMAC_TXUNDERRUN)); + dev_info(emac_dev, "EMAC: tx_carrier_sense_errors:%d\n", + emac_read(EMAC_TXCARRIERSENSE)); + dev_info(emac_dev, "EMAC: tx_octets:%d\n", + emac_read(EMAC_TXOCTETS)); + dev_info(emac_dev, "EMAC: net_octets:%d\n", + emac_read(EMAC_NETOCTETS)); + dev_info(emac_dev, "EMAC: rx_sof_overruns:%d\n", + emac_read(EMAC_RXSOFOVERRUNS)); + dev_info(emac_dev, "EMAC: rx_mof_overruns:%d\n", + emac_read(EMAC_RXMOFOVERRUNS)); + dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", + emac_read(EMAC_RXDMAOVERRUNS)); +} + +/************************************************************************* + * EMAC MDIO/Phy Functionality + *************************************************************************/ +/** + * emac_get_drvinfo: Get EMAC driver information + * @ndev: The DaVinci EMAC network adapter + * @info: ethtool info structure containing name and version + * + * Returns EMAC driver information (name and version) + * + */ +static void emac_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, emac_version_string); + strcpy(info->version, EMAC_MODULE_VERSION); +} + +/** + * emac_get_settings: Get EMAC settings + * @ndev: The DaVinci EMAC network adapter + * @ecmd: ethtool command + * + * Executes ethool get command + * + */ +static int emac_get_settings(struct net_device *ndev, + struct ethtool_cmd *ecmd) +{ + struct emac_priv *priv = netdev_priv(ndev); + if (priv->phy_mask) + return phy_ethtool_gset(priv->phydev, ecmd); + else + return -EOPNOTSUPP; + +} + +/** + * emac_set_settings: Set EMAC settings + * @ndev: The DaVinci EMAC network adapter + * @ecmd: ethtool command + * + * Executes ethool set command + * + */ +static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) +{ + struct emac_priv *priv = netdev_priv(ndev); + if (priv->phy_mask) + return phy_ethtool_sset(priv->phydev, ecmd); + else + return -EOPNOTSUPP; + +} + +/** + * ethtool_ops: DaVinci EMAC Ethtool structure + * + * Ethtool support for EMAC adapter + * + */ +static const struct ethtool_ops ethtool_ops = { + .get_drvinfo = emac_get_drvinfo, + .get_settings = emac_get_settings, + .set_settings = emac_set_settings, + .get_link = ethtool_op_get_link, +}; + +/** + * emac_update_phystatus: Update Phy status + * @priv: The DaVinci EMAC private adapter structure + * + * Updates phy status and takes action for network queue if required + * based upon link status + * + */ +static void emac_update_phystatus(struct emac_priv *priv) +{ + u32 mac_control; + u32 new_duplex; + u32 cur_duplex; + struct net_device *ndev = priv->ndev; + + mac_control = emac_read(EMAC_MACCONTROL); + cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? + DUPLEX_FULL : DUPLEX_HALF; + if (priv->phy_mask) + new_duplex = priv->phydev->duplex; + else + new_duplex = DUPLEX_FULL; + + /* We get called only if link has changed (speed/duplex/status) */ + if ((priv->link) && (new_duplex != cur_duplex)) { + priv->duplex = new_duplex; + if (DUPLEX_FULL == priv->duplex) + mac_control |= (EMAC_MACCONTROL_FULLDUPLEXEN); + else + mac_control &= ~(EMAC_MACCONTROL_FULLDUPLEXEN); + } + + if (priv->speed == SPEED_1000 && (priv->version == EMAC_VERSION_2)) { + mac_control = emac_read(EMAC_MACCONTROL); + mac_control |= (EMAC_DM646X_MACCONTORL_GMIIEN | + EMAC_DM646X_MACCONTORL_GIG | + EMAC_DM646X_MACCONTORL_GIGFORCE); + } else { + /* Clear the GIG bit and GIGFORCE bit */ + mac_control &= ~(EMAC_DM646X_MACCONTORL_GIGFORCE | + EMAC_DM646X_MACCONTORL_GIG); + + if (priv->rmii_en && (priv->speed == SPEED_100)) + mac_control |= EMAC_MACCONTROL_RMIISPEED_MASK; + else + mac_control &= ~EMAC_MACCONTROL_RMIISPEED_MASK; + } + + /* Update mac_control if changed */ + emac_write(EMAC_MACCONTROL, mac_control); + + if (priv->link) { + /* link ON */ + if (!netif_carrier_ok(ndev)) + netif_carrier_on(ndev); + /* reactivate the transmit queue if it is stopped */ + if (netif_running(ndev) && netif_queue_stopped(ndev)) + netif_wake_queue(ndev); + } else { + /* link OFF */ + if (netif_carrier_ok(ndev)) + netif_carrier_off(ndev); + if (!netif_queue_stopped(ndev)) + netif_stop_queue(ndev); + } +} + +/** + * hash_get: Calculate hash value from mac address + * @addr: mac address to delete from hash table + * + * Calculates hash value from mac address + * + */ +static u32 hash_get(u8 *addr) +{ + u32 hash; + u8 tmpval; + int cnt; + hash = 0; + + for (cnt = 0; cnt < 2; cnt++) { + tmpval = *addr++; + hash ^= (tmpval >> 2) ^ (tmpval << 4); + tmpval = *addr++; + hash ^= (tmpval >> 4) ^ (tmpval << 2); + tmpval = *addr++; + hash ^= (tmpval >> 6) ^ (tmpval); + } + + return hash & 0x3F; +} + +/** + * hash_add: Hash function to add mac addr from hash table + * @priv: The DaVinci EMAC private adapter structure + * mac_addr: mac address to delete from hash table + * + * Adds mac address to the internal hash table + * + */ +static int hash_add(struct emac_priv *priv, u8 *mac_addr) +{ + struct device *emac_dev = &priv->ndev->dev; + u32 rc = 0; + u32 hash_bit; + u32 hash_value = hash_get(mac_addr); + + if (hash_value >= EMAC_NUM_MULTICAST_BITS) { + if (netif_msg_drv(priv)) { + dev_err(emac_dev, "DaVinci EMAC: hash_add(): Invalid "\ + "Hash %08x, should not be greater than %08x", + hash_value, (EMAC_NUM_MULTICAST_BITS - 1)); + } + return -1; + } + + /* set the hash bit only if not previously set */ + if (priv->multicast_hash_cnt[hash_value] == 0) { + rc = 1; /* hash value changed */ + if (hash_value < 32) { + hash_bit = BIT(hash_value); + priv->mac_hash1 |= hash_bit; + } else { + hash_bit = BIT((hash_value - 32)); + priv->mac_hash2 |= hash_bit; + } + } + + /* incr counter for num of mcast addr's mapped to "this" hash bit */ + ++priv->multicast_hash_cnt[hash_value]; + + return rc; +} + +/** + * hash_del: Hash function to delete mac addr from hash table + * @priv: The DaVinci EMAC private adapter structure + * mac_addr: mac address to delete from hash table + * + * Removes mac address from the internal hash table + * + */ +static int hash_del(struct emac_priv *priv, u8 *mac_addr) +{ + u32 hash_value; + u32 hash_bit; + + hash_value = hash_get(mac_addr); + if (priv->multicast_hash_cnt[hash_value] > 0) { + /* dec cntr for num of mcast addr's mapped to this hash bit */ + --priv->multicast_hash_cnt[hash_value]; + } + + /* if counter still > 0, at least one multicast address refers + * to this hash bit. so return 0 */ + if (priv->multicast_hash_cnt[hash_value] > 0) + return 0; + + if (hash_value < 32) { + hash_bit = BIT(hash_value); + priv->mac_hash1 &= ~hash_bit; + } else { + hash_bit = BIT((hash_value - 32)); + priv->mac_hash2 &= ~hash_bit; + } + + /* return 1 to indicate change in mac_hash registers reqd */ + return 1; +} + +/* EMAC multicast operation */ +#define EMAC_MULTICAST_ADD 0 +#define EMAC_MULTICAST_DEL 1 +#define EMAC_ALL_MULTI_SET 2 +#define EMAC_ALL_MULTI_CLR 3 + +/** + * emac_add_mcast: Set multicast address in the EMAC adapter (Internal) + * @priv: The DaVinci EMAC private adapter structure + * @action: multicast operation to perform + * mac_addr: mac address to set + * + * Set multicast addresses in EMAC adapter - internal function + * + */ +static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr) +{ + struct device *emac_dev = &priv->ndev->dev; + int update = -1; + + switch (action) { + case EMAC_MULTICAST_ADD: + update = hash_add(priv, mac_addr); + break; + case EMAC_MULTICAST_DEL: + update = hash_del(priv, mac_addr); + break; + case EMAC_ALL_MULTI_SET: + update = 1; + priv->mac_hash1 = EMAC_ALL_MULTI_REG_VALUE; + priv->mac_hash2 = EMAC_ALL_MULTI_REG_VALUE; + break; + case EMAC_ALL_MULTI_CLR: + update = 1; + priv->mac_hash1 = 0; + priv->mac_hash2 = 0; + memset(&(priv->multicast_hash_cnt[0]), 0, + sizeof(priv->multicast_hash_cnt[0]) * + EMAC_NUM_MULTICAST_BITS); + break; + default: + if (netif_msg_drv(priv)) + dev_err(emac_dev, "DaVinci EMAC: add_mcast"\ + ": bad operation %d", action); + break; + } + + /* write to the hardware only if the register status chances */ + if (update > 0) { + emac_write(EMAC_MACHASH1, priv->mac_hash1); + emac_write(EMAC_MACHASH2, priv->mac_hash2); + } +} + +/** + * emac_dev_mcast_set: Set multicast address in the EMAC adapter + * @ndev: The DaVinci EMAC network adapter + * + * Set multicast addresses in EMAC adapter + * + */ +static void emac_dev_mcast_set(struct net_device *ndev) +{ + u32 mbp_enable; + struct emac_priv *priv = netdev_priv(ndev); + + mbp_enable = emac_read(EMAC_RXMBPENABLE); + if (ndev->flags & IFF_PROMISC) { + mbp_enable &= (~EMAC_MBP_PROMISCCH(EMAC_DEF_PROM_CH)); + mbp_enable |= (EMAC_MBP_RXPROMISC); + } else { + mbp_enable = (mbp_enable & ~EMAC_MBP_RXPROMISC); + if ((ndev->flags & IFF_ALLMULTI) || + (ndev->mc_count > EMAC_DEF_MAX_MULTICAST_ADDRESSES)) { + mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); + emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); + } + if (ndev->mc_count > 0) { + struct dev_mc_list *mc_ptr; + mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); + emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); + /* program multicast address list into EMAC hardware */ + for (mc_ptr = ndev->mc_list; mc_ptr; + mc_ptr = mc_ptr->next) { + emac_add_mcast(priv, EMAC_MULTICAST_ADD, + (u8 *)mc_ptr->dmi_addr); + } + } else { + mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST); + emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); + } + } + /* Set mbp config register */ + emac_write(EMAC_RXMBPENABLE, mbp_enable); +} + +/************************************************************************* + * EMAC Hardware manipulation + *************************************************************************/ + +/** + * emac_int_disable: Disable EMAC module interrupt (from adapter) + * @priv: The DaVinci EMAC private adapter structure + * + * Disable EMAC interrupt on the adapter + * + */ +static void emac_int_disable(struct emac_priv *priv) +{ + if (priv->version == EMAC_VERSION_2) { + unsigned long flags; + + local_irq_save(flags); + + /* Program C0_Int_En to zero to turn off + * interrupts to the CPU */ + emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0); + emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0); + /* NOTE: Rx Threshold and Misc interrupts are not disabled */ + + local_irq_restore(flags); + + } else { + /* Set DM644x control registers for interrupt control */ + emac_ctrl_write(EMAC_CTRL_EWCTL, 0x0); + } +} + +/** + * emac_int_enable: Enable EMAC module interrupt (from adapter) + * @priv: The DaVinci EMAC private adapter structure + * + * Enable EMAC interrupt on the adapter + * + */ +static void emac_int_enable(struct emac_priv *priv) +{ + if (priv->version == EMAC_VERSION_2) { + emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff); + emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff); + + /* In addition to turning on interrupt Enable, we need + * ack by writing appropriate values to the EOI + * register */ + + /* NOTE: Rx Threshold and Misc interrupts are not enabled */ + + /* ack rxen only then a new pulse will be generated */ + emac_write(EMAC_DM646X_MACEOIVECTOR, + EMAC_DM646X_MAC_EOI_C0_RXEN); + + /* ack txen- only then a new pulse will be generated */ + emac_write(EMAC_DM646X_MACEOIVECTOR, + EMAC_DM646X_MAC_EOI_C0_TXEN); + + } else { + /* Set DM644x control registers for interrupt control */ + emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1); + } +} + +/** + * emac_irq: EMAC interrupt handler + * @irq: interrupt number + * @dev_id: EMAC network adapter data structure ptr + * + * EMAC Interrupt handler - we only schedule NAPI and not process any packets + * here. EVen the interrupt status is checked (TX/RX/Err) in NAPI poll function + * + * Returns interrupt handled condition + */ +static irqreturn_t emac_irq(int irq, void *dev_id) +{ + struct net_device *ndev = (struct net_device *)dev_id; + struct emac_priv *priv = netdev_priv(ndev); + + ++priv->isr_count; + if (likely(netif_running(priv->ndev))) { + emac_int_disable(priv); + napi_schedule(&priv->napi); + } else { + /* we are closing down, so dont process anything */ + } + return IRQ_HANDLED; +} + +/** EMAC on-chip buffer descriptor memory + * + * WARNING: Please note that the on chip memory is used for both TX and RX + * buffer descriptor queues and is equally divided between TX and RX desc's + * If the number of TX or RX descriptors change this memory pointers need + * to be adjusted. If external memory is allocated then these pointers can + * pointer to the memory + * + */ +#define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) +#define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ + (((priv)->ctrl_ram_size) >> 1)) + +/** + * emac_init_txch: TX channel initialization + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * + * Called during device init to setup a TX channel (allocate buffer desc + * create free pool and keep ready for transmission + * + * Returns success(0) or mem alloc failures error code + */ +static int emac_init_txch(struct emac_priv *priv, u32 ch) +{ + struct device *emac_dev = &priv->ndev->dev; + u32 cnt, bd_size; + void __iomem *mem; + struct emac_tx_bd __iomem *curr_bd; + struct emac_txch *txch = NULL; + + txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); + if (NULL == txch) { + dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); + return -ENOMEM; + } + priv->txch[ch] = txch; + txch->service_max = EMAC_DEF_TX_MAX_SERVICE; + txch->active_queue_head = NULL; + txch->active_queue_tail = NULL; + txch->queue_active = 0; + txch->teardown_pending = 0; + + /* allocate memory for TX CPPI channel on a 4 byte boundry */ + txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), + GFP_KERNEL); + if (NULL == txch->tx_complete) { + dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); + kfree(txch); + return -ENOMEM; + } + + /* allocate buffer descriptor pool align every BD on four word + * boundry for future requirements */ + bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; + txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; + txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); + + /* alloc TX BD memory */ + txch->bd_mem = EMAC_TX_BD_MEM(priv); + __memzero((void __force *)txch->bd_mem, txch->alloc_size); + + /* initialize the BD linked list */ + mem = (void __force __iomem *) + (((u32 __force) txch->bd_mem + 0xF) & ~0xF); + txch->bd_pool_head = NULL; + for (cnt = 0; cnt < txch->num_bd; cnt++) { + curr_bd = mem + (cnt * bd_size); + curr_bd->next = txch->bd_pool_head; + txch->bd_pool_head = curr_bd; + } + + /* reset statistics counters */ + txch->out_of_tx_bd = 0; + txch->no_active_pkts = 0; + txch->active_queue_count = 0; + + return 0; +} + +/** + * emac_cleanup_txch: Book-keep function to clean TX channel resources + * @priv: The DaVinci EMAC private adapter structure + * @ch: TX channel number + * + * Called to clean up TX channel resources + * + */ +static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) +{ + struct emac_txch *txch = priv->txch[ch]; + + if (txch) { + if (txch->bd_mem) + txch->bd_mem = NULL; + kfree(txch->tx_complete); + kfree(txch); + priv->txch[ch] = NULL; + } +} + +/** + * emac_net_tx_complete: TX packet completion function + * @priv: The DaVinci EMAC private adapter structure + * @net_data_tokens: packet token - skb pointer + * @num_tokens: number of skb's to free + * @ch: TX channel number + * + * Frees the skb once packet is transmitted + * + */ +static int emac_net_tx_complete(struct emac_priv *priv, + void **net_data_tokens, + int num_tokens, u32 ch) +{ + u32 cnt; + + if (unlikely(num_tokens && netif_queue_stopped(priv->ndev))) + netif_start_queue(priv->ndev); + for (cnt = 0; cnt < num_tokens; cnt++) { + struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; + if (skb == NULL) + continue; + priv->net_dev_stats.tx_packets++; + priv->net_dev_stats.tx_bytes += skb->len; + dev_kfree_skb_any(skb); + } + return 0; +} + +/** + * emac_txch_teardown: TX channel teardown + * @priv: The DaVinci EMAC private adapter structure + * @ch: TX channel number + * + * Called to teardown TX channel + * + */ +static void emac_txch_teardown(struct emac_priv *priv, u32 ch) +{ + struct device *emac_dev = &priv->ndev->dev; + u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ + struct emac_txch *txch = priv->txch[ch]; + struct emac_tx_bd __iomem *curr_bd; + + while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != + EMAC_TEARDOWN_VALUE) { + /* wait till tx teardown complete */ + cpu_relax(); /* TODO: check if this helps ... */ + --teardown_cnt; + if (0 == teardown_cnt) { + dev_err(emac_dev, "EMAC: TX teardown aborted\n"); + break; + } + } + emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); + + /* process sent packets and return skb's to upper layer */ + if (1 == txch->queue_active) { + curr_bd = txch->active_queue_head; + while (curr_bd != NULL) { + emac_net_tx_complete(priv, (void __force *) + &curr_bd->buf_token, 1, ch); + if (curr_bd != txch->active_queue_tail) + curr_bd = curr_bd->next; + else + break; + } + txch->bd_pool_head = txch->active_queue_head; + txch->active_queue_head = + txch->active_queue_tail = NULL; + } +} + +/** + * emac_stop_txch: Stop TX channel operation + * @priv: The DaVinci EMAC private adapter structure + * @ch: TX channel number + * + * Called to stop TX channel operation + * + */ +static void emac_stop_txch(struct emac_priv *priv, u32 ch) +{ + struct emac_txch *txch = priv->txch[ch]; + + if (txch) { + txch->teardown_pending = 1; + emac_write(EMAC_TXTEARDOWN, 0); + emac_txch_teardown(priv, ch); + txch->teardown_pending = 0; + emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); + } +} + +/** + * emac_tx_bdproc: TX buffer descriptor (packet) processing + * @priv: The DaVinci EMAC private adapter structure + * @ch: TX channel number to process buffer descriptors for + * @budget: number of packets allowed to process + * @pending: indication to caller that packets are pending to process + * + * Processes TX buffer descriptors after packets are transmitted - checks + * ownership bit on the TX * descriptor and requeues it to free pool & frees + * the SKB buffer. Only "budget" number of packets are processed and + * indication of pending packets provided to the caller + * + * Returns number of packets processed + */ +static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) +{ + struct device *emac_dev = &priv->ndev->dev; + unsigned long flags; + u32 frame_status; + u32 pkts_processed = 0; + u32 tx_complete_cnt = 0; + struct emac_tx_bd __iomem *curr_bd; + struct emac_txch *txch = priv->txch[ch]; + u32 *tx_complete_ptr = txch->tx_complete; + + if (unlikely(1 == txch->teardown_pending)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) { + dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ + "teardown pending\n"); + } + return 0; /* dont handle any pkt completions */ + } + + ++txch->proc_count; + spin_lock_irqsave(&priv->tx_lock, flags); + curr_bd = txch->active_queue_head; + if (NULL == curr_bd) { + emac_write(EMAC_TXCP(ch), + emac_virt_to_phys(txch->last_hw_bdprocessed)); + txch->no_active_pkts++; + spin_unlock_irqrestore(&priv->tx_lock, flags); + return 0; + } + BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); + frame_status = curr_bd->mode; + while ((curr_bd) && + ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && + (pkts_processed < budget)) { + emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd)); + txch->active_queue_head = curr_bd->next; + if (frame_status & EMAC_CPPI_EOQ_BIT) { + if (curr_bd->next) { /* misqueued packet */ + emac_write(EMAC_TXHDP(ch), curr_bd->h_next); + ++txch->mis_queued_packets; + } else { + txch->queue_active = 0; /* end of queue */ + } + } + *tx_complete_ptr = (u32) curr_bd->buf_token; + ++tx_complete_ptr; + ++tx_complete_cnt; + curr_bd->next = txch->bd_pool_head; + txch->bd_pool_head = curr_bd; + --txch->active_queue_count; + pkts_processed++; + txch->last_hw_bdprocessed = curr_bd; + curr_bd = txch->active_queue_head; + if (curr_bd) { + BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); + frame_status = curr_bd->mode; + } + } /* end of pkt processing loop */ + + emac_net_tx_complete(priv, + (void *)&txch->tx_complete[0], + tx_complete_cnt, ch); + spin_unlock_irqrestore(&priv->tx_lock, flags); + return pkts_processed; +} + +#define EMAC_ERR_TX_OUT_OF_BD -1 + +/** + * emac_send: EMAC Transmit function (internal) + * @priv: The DaVinci EMAC private adapter structure + * @pkt: packet pointer (contains skb ptr) + * @ch: TX channel number + * + * Called by the transmit function to queue the packet in EMAC hardware queue + * + * Returns success(0) or error code (typically out of desc's) + */ +static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) +{ + unsigned long flags; + struct emac_tx_bd __iomem *curr_bd; + struct emac_txch *txch; + struct emac_netbufobj *buf_list; + + txch = priv->txch[ch]; + buf_list = pkt->buf_list; /* get handle to the buffer array */ + + /* check packet size and pad if short */ + if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { + buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); + pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; + } + + spin_lock_irqsave(&priv->tx_lock, flags); + curr_bd = txch->bd_pool_head; + if (curr_bd == NULL) { + txch->out_of_tx_bd++; + spin_unlock_irqrestore(&priv->tx_lock, flags); + return EMAC_ERR_TX_OUT_OF_BD; + } + + txch->bd_pool_head = curr_bd->next; + curr_bd->buf_token = buf_list->buf_token; + /* FIXME buff_ptr = dma_map_single(... data_ptr ...) */ + curr_bd->buff_ptr = virt_to_phys(buf_list->data_ptr); + curr_bd->off_b_len = buf_list->length; + curr_bd->h_next = 0; + curr_bd->next = NULL; + curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | + EMAC_CPPI_EOP_BIT | pkt->pkt_length); + + /* flush the packet from cache if write back cache is present */ + BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); + + /* send the packet */ + if (txch->active_queue_head == NULL) { + txch->active_queue_head = curr_bd; + txch->active_queue_tail = curr_bd; + if (1 != txch->queue_active) { + emac_write(EMAC_TXHDP(ch), + emac_virt_to_phys(curr_bd)); + txch->queue_active = 1; + } + ++txch->queue_reinit; + } else { + register struct emac_tx_bd __iomem *tail_bd; + register u32 frame_status; + + tail_bd = txch->active_queue_tail; + tail_bd->next = curr_bd; + txch->active_queue_tail = curr_bd; + tail_bd = EMAC_VIRT_NOCACHE(tail_bd); + tail_bd->h_next = (int)emac_virt_to_phys(curr_bd); + frame_status = tail_bd->mode; + if (frame_status & EMAC_CPPI_EOQ_BIT) { + emac_write(EMAC_TXHDP(ch), emac_virt_to_phys(curr_bd)); + frame_status &= ~(EMAC_CPPI_EOQ_BIT); + tail_bd->mode = frame_status; + ++txch->end_of_queue_add; + } + } + txch->active_queue_count++; + spin_unlock_irqrestore(&priv->tx_lock, flags); + return 0; +} + +/** + * emac_dev_xmit: EMAC Transmit function + * @skb: SKB pointer + * @ndev: The DaVinci EMAC network adapter + * + * Called by the system to transmit a packet - we queue the packet in + * EMAC hardware transmit queue + * + * Returns success(NETDEV_TX_OK) or error code (typically out of desc's) + */ +static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct device *emac_dev = &ndev->dev; + int ret_code; + struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ + struct emac_netpktobj tx_packet; /* packet object */ + struct emac_priv *priv = netdev_priv(ndev); + + /* If no link, return */ + if (unlikely(!priv->link)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); + return NETDEV_TX_BUSY; + } + + /* Build the buffer and packet objects - Since only single fragment is + * supported, need not set length and token in both packet & object. + * Doing so for completeness sake & to show that this needs to be done + * in multifragment case + */ + tx_packet.buf_list = &tx_buf; + tx_packet.num_bufs = 1; /* only single fragment supported */ + tx_packet.pkt_length = skb->len; + tx_packet.pkt_token = (void *)skb; + tx_buf.length = skb->len; + tx_buf.buf_token = (void *)skb; + tx_buf.data_ptr = skb->data; + EMAC_CACHE_WRITEBACK((unsigned long)skb->data, skb->len); + ndev->trans_start = jiffies; + ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); + if (unlikely(ret_code != 0)) { + if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ + " err. Out of TX BD's"); + netif_stop_queue(priv->ndev); + } + priv->net_dev_stats.tx_dropped++; + return NETDEV_TX_BUSY; + } + + return NETDEV_TX_OK; +} + +/** + * emac_dev_tx_timeout: EMAC Transmit timeout function + * @ndev: The DaVinci EMAC network adapter + * + * Called when system detects that a skb timeout period has expired + * potentially due to a fault in the adapter in not being able to send + * it out on the wire. We teardown the TX channel assuming a hardware + * error and re-initialize the TX channel for hardware operation + * + */ +static void emac_dev_tx_timeout(struct net_device *ndev) +{ + struct emac_priv *priv = netdev_priv(ndev); + struct device *emac_dev = &ndev->dev; + + if (netif_msg_tx_err(priv)) + dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); + + priv->net_dev_stats.tx_errors++; + emac_int_disable(priv); + emac_stop_txch(priv, EMAC_DEF_TX_CH); + emac_cleanup_txch(priv, EMAC_DEF_TX_CH); + emac_init_txch(priv, EMAC_DEF_TX_CH); + emac_write(EMAC_TXHDP(0), 0); + emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); + emac_int_enable(priv); +} + +/** + * emac_net_alloc_rx_buf: Allocate a skb for RX + * @priv: The DaVinci EMAC private adapter structure + * @buf_size: size of SKB data buffer to allocate + * @data_token: data token returned (skb handle for storing in buffer desc) + * @ch: RX channel number + * + * Called during RX channel setup - allocates skb buffer of required size + * and provides the skb handle and allocated buffer data pointer to caller + * + * Returns skb data pointer or 0 on failure to alloc skb + */ +static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, + void **data_token, u32 ch) +{ + struct net_device *ndev = priv->ndev; + struct device *emac_dev = &ndev->dev; + struct sk_buff *p_skb; + + p_skb = dev_alloc_skb(buf_size); + if (unlikely(NULL == p_skb)) { + if (netif_msg_rx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); + return NULL; + } + + /* set device pointer in skb and reserve space for extra bytes */ + p_skb->dev = ndev; + skb_reserve(p_skb, NET_IP_ALIGN); + *data_token = (void *) p_skb; + EMAC_CACHE_WRITEBACK_INVALIDATE((unsigned long)p_skb->data, buf_size); + return p_skb->data; +} + +/** + * emac_init_rxch: RX channel initialization + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * @param: mac address for RX channel + * + * Called during device init to setup a RX channel (allocate buffers and + * buffer descriptors, create queue and keep ready for reception + * + * Returns success(0) or mem alloc failures error code + */ +static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) +{ + struct device *emac_dev = &priv->ndev->dev; + u32 cnt, bd_size; + void __iomem *mem; + struct emac_rx_bd __iomem *curr_bd; + struct emac_rxch *rxch = NULL; + + rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); + if (NULL == rxch) { + dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); + return -ENOMEM; + } + priv->rxch[ch] = rxch; + rxch->buf_size = priv->rx_buf_size; + rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; + rxch->queue_active = 0; + rxch->teardown_pending = 0; + + /* save mac address */ + for (cnt = 0; cnt < 6; cnt++) + rxch->mac_addr[cnt] = param[cnt]; + + /* allocate buffer descriptor pool align every BD on four word + * boundry for future requirements */ + bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; + rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; + rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); + rxch->bd_mem = EMAC_RX_BD_MEM(priv); + __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); + rxch->pkt_queue.buf_list = &rxch->buf_queue; + + /* allocate RX buffer and initialize the BD linked list */ + mem = (void __force __iomem *) + (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); + rxch->active_queue_head = NULL; + rxch->active_queue_tail = mem; + for (cnt = 0; cnt < rxch->num_bd; cnt++) { + curr_bd = mem + (cnt * bd_size); + /* for future use the last parameter contains the BD ptr */ + curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, + rxch->buf_size, + (void __force **)&curr_bd->buf_token, + EMAC_DEF_RX_CH); + if (curr_bd->data_ptr == NULL) { + dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ + "failed for ch %d\n", ch); + kfree(rxch); + return -ENOMEM; + } + + /* populate the hardware descriptor */ + curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head); + /* FIXME buff_ptr = dma_map_single(... data_ptr ...) */ + curr_bd->buff_ptr = virt_to_phys(curr_bd->data_ptr); + curr_bd->off_b_len = rxch->buf_size; + curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; + + /* write back to hardware memory */ + BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, + EMAC_BD_LENGTH_FOR_CACHE); + curr_bd->next = rxch->active_queue_head; + rxch->active_queue_head = curr_bd; + } + + /* At this point rxCppi->activeQueueHead points to the first + RX BD ready to be given to RX HDP and rxch->active_queue_tail + points to the last RX BD + */ + return 0; +} + +/** + * emac_rxch_teardown: RX channel teardown + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * + * Called during device stop to teardown RX channel + * + */ +static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) +{ + struct device *emac_dev = &priv->ndev->dev; + u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ + + while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != + EMAC_TEARDOWN_VALUE) { + /* wait till tx teardown complete */ + cpu_relax(); /* TODO: check if this helps ... */ + --teardown_cnt; + if (0 == teardown_cnt) { + dev_err(emac_dev, "EMAC: RX teardown aborted\n"); + break; + } + } + emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); +} + +/** + * emac_stop_rxch: Stop RX channel operation + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * + * Called during device stop to stop RX channel operation + * + */ +static void emac_stop_rxch(struct emac_priv *priv, u32 ch) +{ + struct emac_rxch *rxch = priv->rxch[ch]; + + if (rxch) { + rxch->teardown_pending = 1; + emac_write(EMAC_RXTEARDOWN, ch); + /* wait for teardown complete */ + emac_rxch_teardown(priv, ch); + rxch->teardown_pending = 0; + emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); + } +} + +/** + * emac_cleanup_rxch: Book-keep function to clean RX channel resources + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * + * Called during device stop to clean up RX channel resources + * + */ +static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) +{ + struct emac_rxch *rxch = priv->rxch[ch]; + struct emac_rx_bd __iomem *curr_bd; + + if (rxch) { + /* free the receive buffers previously allocated */ + curr_bd = rxch->active_queue_head; + while (curr_bd) { + if (curr_bd->buf_token) { + dev_kfree_skb_any((struct sk_buff *)\ + curr_bd->buf_token); + } + curr_bd = curr_bd->next; + } + if (rxch->bd_mem) + rxch->bd_mem = NULL; + kfree(rxch); + priv->rxch[ch] = NULL; + } +} + +/** + * emac_set_type0addr: Set EMAC Type0 mac address + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * @mac_addr: MAC address to set in device + * + * Called internally to set Type0 mac address of the adapter (Device) + * + * Returns success (0) or appropriate error code (none as of now) + */ +static void emac_set_type0addr(struct emac_priv *priv, u32 ch, char *mac_addr) +{ + u32 val; + val = ((mac_addr[5] << 8) | (mac_addr[4])); + emac_write(EMAC_MACSRCADDRLO, val); + + val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \ + (mac_addr[1] << 8) | (mac_addr[0])); + emac_write(EMAC_MACSRCADDRHI, val); + val = emac_read(EMAC_RXUNICASTSET); + val |= BIT(ch); + emac_write(EMAC_RXUNICASTSET, val); + val = emac_read(EMAC_RXUNICASTCLEAR); + val &= ~BIT(ch); + emac_write(EMAC_RXUNICASTCLEAR, val); +} + +/** + * emac_set_type1addr: Set EMAC Type1 mac address + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * @mac_addr: MAC address to set in device + * + * Called internally to set Type1 mac address of the adapter (Device) + * + * Returns success (0) or appropriate error code (none as of now) + */ +static void emac_set_type1addr(struct emac_priv *priv, u32 ch, char *mac_addr) +{ + u32 val; + emac_write(EMAC_MACINDEX, ch); + val = ((mac_addr[5] << 8) | mac_addr[4]); + emac_write(EMAC_MACADDRLO, val); + val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \ + (mac_addr[1] << 8) | (mac_addr[0])); + emac_write(EMAC_MACADDRHI, val); + emac_set_type0addr(priv, ch, mac_addr); +} + +/** + * emac_set_type2addr: Set EMAC Type2 mac address + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * @mac_addr: MAC address to set in device + * @index: index into RX address entries + * @match: match parameter for RX address matching logic + * + * Called internally to set Type2 mac address of the adapter (Device) + * + * Returns success (0) or appropriate error code (none as of now) + */ +static void emac_set_type2addr(struct emac_priv *priv, u32 ch, + char *mac_addr, int index, int match) +{ + u32 val; + emac_write(EMAC_MACINDEX, index); + val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \ + (mac_addr[1] << 8) | (mac_addr[0])); + emac_write(EMAC_MACADDRHI, val); + val = ((mac_addr[5] << 8) | mac_addr[4] | ((ch & 0x7) << 16) | \ + (match << 19) | BIT(20)); + emac_write(EMAC_MACADDRLO, val); + emac_set_type0addr(priv, ch, mac_addr); +} + +/** + * emac_setmac: Set mac address in the adapter (internal function) + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number + * @mac_addr: MAC address to set in device + * + * Called internally to set the mac address of the adapter (Device) + * + * Returns success (0) or appropriate error code (none as of now) + */ +static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) +{ + struct device *emac_dev = &priv->ndev->dev; + + if (priv->rx_addr_type == 0) { + emac_set_type0addr(priv, ch, mac_addr); + } else if (priv->rx_addr_type == 1) { + u32 cnt; + for (cnt = 0; cnt < EMAC_MAX_TXRX_CHANNELS; cnt++) + emac_set_type1addr(priv, ch, mac_addr); + } else if (priv->rx_addr_type == 2) { + emac_set_type2addr(priv, ch, mac_addr, ch, 1); + emac_set_type0addr(priv, ch, mac_addr); + } else { + if (netif_msg_drv(priv)) + dev_err(emac_dev, "DaVinci EMAC: Wrong addressing\n"); + } +} + +/** + * emac_dev_setmac_addr: Set mac address in the adapter + * @ndev: The DaVinci EMAC network adapter + * @addr: MAC address to set in device + * + * Called by the system to set the mac address of the adapter (Device) + * + * Returns success (0) or appropriate error code (none as of now) + */ +static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) +{ + struct emac_priv *priv = netdev_priv(ndev); + struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; + struct device *emac_dev = &priv->ndev->dev; + struct sockaddr *sa = addr; + + /* Store mac addr in priv and rx channel and set it in EMAC hw */ + memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); + memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); + memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + + if (netif_msg_drv(priv)) + dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", + priv->mac_addr); + + return 0; +} + +/** + * emac_addbd_to_rx_queue: Recycle RX buffer descriptor + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number to process buffer descriptors for + * @curr_bd: current buffer descriptor + * @buffer: buffer pointer for descriptor + * @buf_token: buffer token (stores skb information) + * + * Prepares the recycled buffer descriptor and addes it to hardware + * receive queue - if queue empty this descriptor becomes the head + * else addes the descriptor to end of queue + * + */ +static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, + struct emac_rx_bd __iomem *curr_bd, + char *buffer, void *buf_token) +{ + struct emac_rxch *rxch = priv->rxch[ch]; + + /* populate the hardware descriptor */ + curr_bd->h_next = 0; + /* FIXME buff_ptr = dma_map_single(... buffer ...) */ + curr_bd->buff_ptr = virt_to_phys(buffer); + curr_bd->off_b_len = rxch->buf_size; + curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; + curr_bd->next = NULL; + curr_bd->data_ptr = buffer; + curr_bd->buf_token = buf_token; + + /* write back */ + BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); + if (rxch->active_queue_head == NULL) { + rxch->active_queue_head = curr_bd; + rxch->active_queue_tail = curr_bd; + if (0 != rxch->queue_active) { + emac_write(EMAC_RXHDP(ch), + emac_virt_to_phys(rxch->active_queue_head)); + rxch->queue_active = 1; + } + } else { + struct emac_rx_bd __iomem *tail_bd; + u32 frame_status; + + tail_bd = rxch->active_queue_tail; + rxch->active_queue_tail = curr_bd; + tail_bd->next = curr_bd; + tail_bd = EMAC_VIRT_NOCACHE(tail_bd); + tail_bd->h_next = emac_virt_to_phys(curr_bd); + frame_status = tail_bd->mode; + if (frame_status & EMAC_CPPI_EOQ_BIT) { + emac_write(EMAC_RXHDP(ch), + emac_virt_to_phys(curr_bd)); + frame_status &= ~(EMAC_CPPI_EOQ_BIT); + tail_bd->mode = frame_status; + ++rxch->end_of_queue_add; + } + } + ++rxch->recycled_bd; +} + +/** + * emac_net_rx_cb: Prepares packet and sends to upper layer + * @priv: The DaVinci EMAC private adapter structure + * @net_pkt_list: Network packet list (received packets) + * + * Invalidates packet buffer memory and sends the received packet to upper + * layer + * + * Returns success or appropriate error code (none as of now) + */ +static int emac_net_rx_cb(struct emac_priv *priv, + struct emac_netpktobj *net_pkt_list) +{ + struct sk_buff *p_skb; + p_skb = (struct sk_buff *)net_pkt_list->pkt_token; + /* set length of packet */ + skb_put(p_skb, net_pkt_list->pkt_length); + EMAC_CACHE_INVALIDATE((unsigned long)p_skb->data, p_skb->len); + p_skb->protocol = eth_type_trans(p_skb, priv->ndev); + p_skb->dev->last_rx = jiffies; + netif_receive_skb(p_skb); + priv->net_dev_stats.rx_bytes += net_pkt_list->pkt_length; + priv->net_dev_stats.rx_packets++; + return 0; +} + +/** + * emac_rx_bdproc: RX buffer descriptor (packet) processing + * @priv: The DaVinci EMAC private adapter structure + * @ch: RX channel number to process buffer descriptors for + * @budget: number of packets allowed to process + * @pending: indication to caller that packets are pending to process + * + * Processes RX buffer descriptors - checks ownership bit on the RX buffer + * descriptor, sends the receive packet to upper layer, allocates a new SKB + * and recycles the buffer descriptor (requeues it in hardware RX queue). + * Only "budget" number of packets are processed and indication of pending + * packets provided to the caller. + * + * Returns number of packets processed (and indication of pending packets) + */ +static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) +{ + unsigned long flags; + u32 frame_status; + u32 pkts_processed = 0; + char *new_buffer; + struct emac_rx_bd __iomem *curr_bd; + struct emac_rx_bd __iomem *last_bd; + struct emac_netpktobj *curr_pkt, pkt_obj; + struct emac_netbufobj buf_obj; + struct emac_netbufobj *rx_buf_obj; + void *new_buf_token; + struct emac_rxch *rxch = priv->rxch[ch]; + + if (unlikely(1 == rxch->teardown_pending)) + return 0; + ++rxch->proc_count; + spin_lock_irqsave(&priv->rx_lock, flags); + pkt_obj.buf_list = &buf_obj; + curr_pkt = &pkt_obj; + curr_bd = rxch->active_queue_head; + BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); + frame_status = curr_bd->mode; + + while ((curr_bd) && + ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && + (pkts_processed < budget)) { + + new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, + &new_buf_token, EMAC_DEF_RX_CH); + if (unlikely(NULL == new_buffer)) { + ++rxch->out_of_rx_buffers; + goto end_emac_rx_bdproc; + } + + /* populate received packet data structure */ + rx_buf_obj = &curr_pkt->buf_list[0]; + rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; + rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; + rx_buf_obj->buf_token = curr_bd->buf_token; + curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; + curr_pkt->num_bufs = 1; + curr_pkt->pkt_length = + (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); + emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd)); + ++rxch->processed_bd; + last_bd = curr_bd; + curr_bd = last_bd->next; + rxch->active_queue_head = curr_bd; + + /* check if end of RX queue ? */ + if (frame_status & EMAC_CPPI_EOQ_BIT) { + if (curr_bd) { + ++rxch->mis_queued_packets; + emac_write(EMAC_RXHDP(ch), + emac_virt_to_phys(curr_bd)); + } else { + ++rxch->end_of_queue; + rxch->queue_active = 0; + } + } + + /* recycle BD */ + emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, + new_buf_token); + + /* return the packet to the user - BD ptr passed in + * last parameter for potential *future* use */ + spin_unlock_irqrestore(&priv->rx_lock, flags); + emac_net_rx_cb(priv, curr_pkt); + spin_lock_irqsave(&priv->rx_lock, flags); + curr_bd = rxch->active_queue_head; + if (curr_bd) { + BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); + frame_status = curr_bd->mode; + } + ++pkts_processed; + } + +end_emac_rx_bdproc: + spin_unlock_irqrestore(&priv->rx_lock, flags); + return pkts_processed; +} + +/** + * emac_hw_enable: Enable EMAC hardware for packet transmission/reception + * @priv: The DaVinci EMAC private adapter structure + * + * Enables EMAC hardware for packet processing - enables PHY, enables RX + * for packet reception and enables device interrupts and then NAPI + * + * Returns success (0) or appropriate error code (none right now) + */ +static int emac_hw_enable(struct emac_priv *priv) +{ + u32 ch, val, mbp_enable, mac_control; + + /* Soft reset */ + emac_write(EMAC_SOFTRESET, 1); + while (emac_read(EMAC_SOFTRESET)) + cpu_relax(); + + /* Disable interrupt & Set pacing for more interrupts initially */ + emac_int_disable(priv); + + /* Full duplex enable bit set when auto negotiation happens */ + mac_control = + (((EMAC_DEF_TXPRIO_FIXED) ? (EMAC_MACCONTROL_TXPTYPE) : 0x0) | + ((priv->speed == 1000) ? EMAC_MACCONTROL_GIGABITEN : 0x0) | + ((EMAC_DEF_TXPACING_EN) ? (EMAC_MACCONTROL_TXPACEEN) : 0x0) | + ((priv->duplex == DUPLEX_FULL) ? 0x1 : 0)); + emac_write(EMAC_MACCONTROL, mac_control); + + mbp_enable = + (((EMAC_DEF_PASS_CRC) ? (EMAC_RXMBP_PASSCRC_MASK) : 0x0) | + ((EMAC_DEF_QOS_EN) ? (EMAC_RXMBP_QOSEN_MASK) : 0x0) | + ((EMAC_DEF_NO_BUFF_CHAIN) ? (EMAC_RXMBP_NOCHAIN_MASK) : 0x0) | + ((EMAC_DEF_MACCTRL_FRAME_EN) ? (EMAC_RXMBP_CMFEN_MASK) : 0x0) | + ((EMAC_DEF_SHORT_FRAME_EN) ? (EMAC_RXMBP_CSFEN_MASK) : 0x0) | + ((EMAC_DEF_ERROR_FRAME_EN) ? (EMAC_RXMBP_CEFEN_MASK) : 0x0) | + ((EMAC_DEF_PROM_EN) ? (EMAC_RXMBP_CAFEN_MASK) : 0x0) | + ((EMAC_DEF_PROM_CH & EMAC_RXMBP_CHMASK) << \ + EMAC_RXMBP_PROMCH_SHIFT) | + ((EMAC_DEF_BCAST_EN) ? (EMAC_RXMBP_BROADEN_MASK) : 0x0) | + ((EMAC_DEF_BCAST_CH & EMAC_RXMBP_CHMASK) << \ + EMAC_RXMBP_BROADCH_SHIFT) | + ((EMAC_DEF_MCAST_EN) ? (EMAC_RXMBP_MULTIEN_MASK) : 0x0) | + ((EMAC_DEF_MCAST_CH & EMAC_RXMBP_CHMASK) << \ + EMAC_RXMBP_MULTICH_SHIFT)); + emac_write(EMAC_RXMBPENABLE, mbp_enable); + emac_write(EMAC_RXMAXLEN, (EMAC_DEF_MAX_FRAME_SIZE & + EMAC_RX_MAX_LEN_MASK)); + emac_write(EMAC_RXBUFFEROFFSET, (EMAC_DEF_BUFFER_OFFSET & + EMAC_RX_BUFFER_OFFSET_MASK)); + emac_write(EMAC_RXFILTERLOWTHRESH, 0); + emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); + priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; + + val = emac_read(EMAC_TXCONTROL); + val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; + emac_write(EMAC_TXCONTROL, val); + val = emac_read(EMAC_RXCONTROL); + val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; + emac_write(EMAC_RXCONTROL, val); + emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); + + for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { + emac_write(EMAC_TXHDP(ch), 0); + emac_write(EMAC_TXINTMASKSET, BIT(ch)); + } + for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { + struct emac_rxch *rxch = priv->rxch[ch]; + emac_setmac(priv, ch, rxch->mac_addr); + emac_write(EMAC_RXINTMASKSET, BIT(ch)); + rxch->queue_active = 1; + emac_write(EMAC_RXHDP(ch), + emac_virt_to_phys(rxch->active_queue_head)); + } + + /* Enable MII */ + val = emac_read(EMAC_MACCONTROL); + val |= (EMAC_MACCONTROL_MIIEN); + emac_write(EMAC_MACCONTROL, val); + + /* Enable NAPI and interrupts */ + napi_enable(&priv->napi); + emac_int_enable(priv); + return 0; + +} + +/** + * emac_poll: EMAC NAPI Poll function + * @ndev: The DaVinci EMAC network adapter + * @budget: Number of receive packets to process (as told by NAPI layer) + * + * NAPI Poll function implemented to process packets as per budget. We check + * the type of interrupt on the device and accordingly call the TX or RX + * packet processing functions. We follow the budget for RX processing and + * also put a cap on number of TX pkts processed through config param. The + * NAPI schedule function is called if more packets pending. + * + * Returns number of packets received (in most cases; else TX pkts - rarely) + */ +static int emac_poll(struct napi_struct *napi, int budget) +{ + unsigned int mask; + struct emac_priv *priv = container_of(napi, struct emac_priv, napi); + struct net_device *ndev = priv->ndev; + struct device *emac_dev = &ndev->dev; + u32 status = 0; + u32 num_pkts = 0; + + if (!netif_running(ndev)) + return 0; + + /* Check interrupt vectors and call packet processing */ + status = emac_read(EMAC_MACINVECTOR); + + mask = EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC; + + if (priv->version == EMAC_VERSION_2) + mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; + + if (status & mask) { + num_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, + EMAC_DEF_TX_MAX_SERVICE); + } /* TX processing */ + + if (num_pkts) + return budget; + + mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; + + if (priv->version == EMAC_VERSION_2) + mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; + + if (status & mask) { + num_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + } /* RX processing */ + + if (num_pkts < budget) { + napi_complete(napi); + emac_int_enable(priv); + } + + if (unlikely(status & EMAC_DM644X_MAC_IN_VECTOR_HOST_INT)) { + u32 ch, cause; + dev_err(emac_dev, "DaVinci EMAC: Fatal Hardware Error\n"); + netif_stop_queue(ndev); + napi_disable(&priv->napi); + + status = emac_read(EMAC_MACSTATUS); + cause = ((status & EMAC_MACSTATUS_TXERRCODE_MASK) >> + EMAC_MACSTATUS_TXERRCODE_SHIFT); + if (cause) { + ch = ((status & EMAC_MACSTATUS_TXERRCH_MASK) >> + EMAC_MACSTATUS_TXERRCH_SHIFT); + if (net_ratelimit()) { + dev_err(emac_dev, "TX Host error %s on ch=%d\n", + &emac_txhost_errcodes[cause][0], ch); + } + } + cause = ((status & EMAC_MACSTATUS_RXERRCODE_MASK) >> + EMAC_MACSTATUS_RXERRCODE_SHIFT); + if (cause) { + ch = ((status & EMAC_MACSTATUS_RXERRCH_MASK) >> + EMAC_MACSTATUS_RXERRCH_SHIFT); + if (netif_msg_hw(priv) && net_ratelimit()) + dev_err(emac_dev, "RX Host error %s on ch=%d\n", + &emac_rxhost_errcodes[cause][0], ch); + } + } /* Host error processing */ + + return num_pkts; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/** + * emac_poll_controller: EMAC Poll controller function + * @ndev: The DaVinci EMAC network adapter + * + * Polled functionality used by netconsole and others in non interrupt mode + * + */ +void emac_poll_controller(struct net_device *ndev) +{ + struct emac_priv *priv = netdev_priv(ndev); + + emac_int_disable(priv); + emac_irq(ndev->irq, priv); + emac_int_enable(priv); +} +#endif + +/* PHY/MII bus related */ + +/* Wait until mdio is ready for next command */ +#define MDIO_WAIT_FOR_USER_ACCESS\ + while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ + MDIO_USERACCESS_GO) != 0) + +static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) +{ + unsigned int phy_data = 0; + unsigned int phy_control; + + /* Wait until mdio is ready for next command */ + MDIO_WAIT_FOR_USER_ACCESS; + + phy_control = (MDIO_USERACCESS_GO | + MDIO_USERACCESS_READ | + ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | + ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | + (phy_data & MDIO_USERACCESS_DATA)); + emac_mdio_write(MDIO_USERACCESS(0), phy_control); + + /* Wait until mdio is ready for next command */ + MDIO_WAIT_FOR_USER_ACCESS; + + return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; + +} + +static int emac_mii_write(struct mii_bus *bus, int phy_id, + int phy_reg, u16 phy_data) +{ + + unsigned int control; + + /* until mdio is ready for next command */ + MDIO_WAIT_FOR_USER_ACCESS; + + control = (MDIO_USERACCESS_GO | + MDIO_USERACCESS_WRITE | + ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | + ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | + (phy_data & MDIO_USERACCESS_DATA)); + emac_mdio_write(MDIO_USERACCESS(0), control); + + return 0; +} + +static int emac_mii_reset(struct mii_bus *bus) +{ + unsigned int clk_div; + int mdio_bus_freq = emac_bus_frequency; + + if (mdio_max_freq & mdio_bus_freq) + clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); + else + clk_div = 0xFF; + + clk_div &= MDIO_CONTROL_CLKDIV; + + /* Set enable and clock divider in MDIOControl */ + emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); + + return 0; + +} + +static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; + +/* emac_driver: EMAC MII bus structure */ + +static struct mii_bus *emac_mii; + +static void emac_adjust_link(struct net_device *ndev) +{ + struct emac_priv *priv = netdev_priv(ndev); + struct phy_device *phydev = priv->phydev; + unsigned long flags; + int new_state = 0; + + spin_lock_irqsave(&priv->lock, flags); + + if (phydev->link) { + /* check the mode of operation - full/half duplex */ + if (phydev->duplex != priv->duplex) { + new_state = 1; + priv->duplex = phydev->duplex; + } + if (phydev->speed != priv->speed) { + new_state = 1; + priv->speed = phydev->speed; + } + if (!priv->link) { + new_state = 1; + priv->link = 1; + } + + } else if (priv->link) { + new_state = 1; + priv->link = 0; + priv->speed = 0; + priv->duplex = ~0; + } + if (new_state) { + emac_update_phystatus(priv); + phy_print_status(priv->phydev); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +/************************************************************************* + * Linux Driver Model + *************************************************************************/ + +/** + * emac_devioctl: EMAC adapter ioctl + * @ndev: The DaVinci EMAC network adapter + * @ifrq: request parameter + * @cmd: command parameter + * + * EMAC driver ioctl function + * + * Returns success(0) or appropriate error code + */ +static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) +{ + dev_warn(&ndev->dev, "DaVinci EMAC: ioctl not supported\n"); + + if (!(netif_running(ndev))) + return -EINVAL; + + /* TODO: Add phy read and write and private statistics get feature */ + + return -EOPNOTSUPP; +} + +/** + * emac_dev_open: EMAC device open + * @ndev: The DaVinci EMAC network adapter + * + * Called when system wants to start the interface. We init TX/RX channels + * and enable the hardware for packet reception/transmission and start the + * network queue. + * + * Returns 0 for a successful open, or appropriate error code + */ +static int emac_dev_open(struct net_device *ndev) +{ + struct device *emac_dev = &ndev->dev; + u32 rc, cnt, ch; + int phy_addr; + struct resource *res; + int q, m; + int i = 0; + int k = 0; + struct emac_priv *priv = netdev_priv(ndev); + + netif_carrier_off(ndev); + for (cnt = 0; cnt <= ETH_ALEN; cnt++) + ndev->dev_addr[cnt] = priv->mac_addr[cnt]; + + /* Configuration items */ + priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; + + /* Clear basic hardware */ + for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { + emac_write(EMAC_TXHDP(ch), 0); + emac_write(EMAC_RXHDP(ch), 0); + emac_write(EMAC_RXHDP(ch), 0); + emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); + emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); + } + priv->mac_hash1 = 0; + priv->mac_hash2 = 0; + emac_write(EMAC_MACHASH1, 0); + emac_write(EMAC_MACHASH2, 0); + + /* multi ch not supported - open 1 TX, 1RX ch by default */ + rc = emac_init_txch(priv, EMAC_DEF_TX_CH); + if (0 != rc) { + dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); + return rc; + } + rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); + if (0 != rc) { + dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); + return rc; + } + + /* Request IRQ */ + + while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { + for (i = res->start; i <= res->end; i++) { + if (request_irq(i, emac_irq, IRQF_DISABLED, + ndev->name, ndev)) + goto rollback; + } + k++; + } + + /* Start/Enable EMAC hardware */ + emac_hw_enable(priv); + + /* find the first phy */ + priv->phydev = NULL; + if (priv->phy_mask) { + emac_mii_reset(priv->mii_bus); + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + if (priv->mii_bus->phy_map[phy_addr]) { + priv->phydev = priv->mii_bus->phy_map[phy_addr]; + break; + } + } + + if (!priv->phydev) { + printk(KERN_ERR "%s: no PHY found\n", ndev->name); + return -1; + } + + priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), + &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); + + if (IS_ERR(priv->phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", + ndev->name); + return PTR_ERR(priv->phydev); + } + + priv->link = 0; + priv->speed = 0; + priv->duplex = ~0; + + printk(KERN_INFO "%s: attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, + priv->phydev->drv->name, dev_name(&priv->phydev->dev), + priv->phydev->phy_id); + } else{ + /* No PHY , fix the link, speed and duplex settings */ + priv->link = 1; + priv->speed = SPEED_100; + priv->duplex = DUPLEX_FULL; + emac_update_phystatus(priv); + } + + if (!netif_running(ndev)) /* debug only - to avoid compiler warning */ + emac_dump_regs(priv); + + if (netif_msg_drv(priv)) + dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); + + if (priv->phy_mask) + phy_start(priv->phydev); + + return 0; + +rollback: + + dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); + + for (q = k; k >= 0; k--) { + for (m = i; m >= res->start; m--) + free_irq(m, ndev); + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); + m = res->end; + } + return -EBUSY; +} + +/** + * emac_dev_stop: EMAC device stop + * @ndev: The DaVinci EMAC network adapter + * + * Called when system wants to stop or down the interface. We stop the network + * queue, disable interrupts and cleanup TX/RX channels. + * + * We return the statistics in net_device_stats structure pulled from emac + */ +static int emac_dev_stop(struct net_device *ndev) +{ + struct resource *res; + int i = 0; + int irq_num; + struct emac_priv *priv = netdev_priv(ndev); + struct device *emac_dev = &ndev->dev; + + /* inform the upper layers. */ + netif_stop_queue(ndev); + napi_disable(&priv->napi); + + netif_carrier_off(ndev); + emac_int_disable(priv); + emac_stop_txch(priv, EMAC_DEF_TX_CH); + emac_stop_rxch(priv, EMAC_DEF_RX_CH); + emac_cleanup_txch(priv, EMAC_DEF_TX_CH); + emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); + emac_write(EMAC_SOFTRESET, 1); + + if (priv->phydev) + phy_disconnect(priv->phydev); + + /* Free IRQ */ + while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) + free_irq(irq_num, priv->ndev); + i++; + } + + if (netif_msg_drv(priv)) + dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); + + return 0; +} + +/** + * emac_dev_getnetstats: EMAC get statistics function + * @ndev: The DaVinci EMAC network adapter + * + * Called when system wants to get statistics from the device. + * + * We return the statistics in net_device_stats structure pulled from emac + */ +static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev) +{ + struct emac_priv *priv = netdev_priv(ndev); + + /* update emac hardware stats and reset the registers*/ + + priv->net_dev_stats.multicast += emac_read(EMAC_RXMCASTFRAMES); + emac_write(EMAC_RXMCASTFRAMES, EMAC_ALL_MULTI_REG_VALUE); + + priv->net_dev_stats.collisions += (emac_read(EMAC_TXCOLLISION) + + emac_read(EMAC_TXSINGLECOLL) + + emac_read(EMAC_TXMULTICOLL)); + emac_write(EMAC_TXCOLLISION, EMAC_ALL_MULTI_REG_VALUE); + emac_write(EMAC_TXSINGLECOLL, EMAC_ALL_MULTI_REG_VALUE); + emac_write(EMAC_TXMULTICOLL, EMAC_ALL_MULTI_REG_VALUE); + + priv->net_dev_stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) + + emac_read(EMAC_RXJABBER) + + emac_read(EMAC_RXUNDERSIZED)); + emac_write(EMAC_RXOVERSIZED, EMAC_ALL_MULTI_REG_VALUE); + emac_write(EMAC_RXJABBER, EMAC_ALL_MULTI_REG_VALUE); + emac_write(EMAC_RXUNDERSIZED, EMAC_ALL_MULTI_REG_VALUE); + + priv->net_dev_stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) + + emac_read(EMAC_RXMOFOVERRUNS)); + emac_write(EMAC_RXSOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE); + emac_write(EMAC_RXMOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE); + + priv->net_dev_stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS); + emac_write(EMAC_RXDMAOVERRUNS, EMAC_ALL_MULTI_REG_VALUE); + + priv->net_dev_stats.tx_carrier_errors += + emac_read(EMAC_TXCARRIERSENSE); + emac_write(EMAC_TXCARRIERSENSE, EMAC_ALL_MULTI_REG_VALUE); + + priv->net_dev_stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN); + emac_write(EMAC_TXUNDERRUN, EMAC_ALL_MULTI_REG_VALUE); + + return &priv->net_dev_stats; +} + +static const struct net_device_ops emac_netdev_ops = { + .ndo_open = emac_dev_open, + .ndo_stop = emac_dev_stop, + .ndo_start_xmit = emac_dev_xmit, + .ndo_set_multicast_list = emac_dev_mcast_set, + .ndo_set_mac_address = emac_dev_setmac_addr, + .ndo_do_ioctl = emac_devioctl, + .ndo_tx_timeout = emac_dev_tx_timeout, + .ndo_get_stats = emac_dev_getnetstats, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = emac_poll_controller, +#endif +}; + +/** + * davinci_emac_probe: EMAC device probe + * @pdev: The DaVinci EMAC device that we are removing + * + * Called when probing for emac devicesr. We get details of instances and + * resource information from platform init and register a network device + * and allocate resources necessary for driver to perform + */ +static int __devinit davinci_emac_probe(struct platform_device *pdev) +{ + int rc = 0; + struct resource *res; + struct net_device *ndev; + struct emac_priv *priv; + unsigned long size; + struct emac_platform_data *pdata; + struct device *emac_dev; + + /* obtain emac clock from kernel */ + emac_clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(emac_clk)) { + printk(KERN_ERR "DaVinci EMAC: Failed to get EMAC clock\n"); + return -EBUSY; + } + emac_bus_frequency = clk_get_rate(emac_clk); + /* TODO: Probe PHY here if possible */ + + ndev = alloc_etherdev(sizeof(struct emac_priv)); + if (!ndev) { + printk(KERN_ERR "DaVinci EMAC: Error allocating net_device\n"); + clk_put(emac_clk); + return -ENOMEM; + } + + platform_set_drvdata(pdev, ndev); + priv = netdev_priv(ndev); + priv->pdev = pdev; + priv->ndev = ndev; + priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); + + spin_lock_init(&priv->tx_lock); + spin_lock_init(&priv->rx_lock); + spin_lock_init(&priv->lock); + + pdata = pdev->dev.platform_data; + if (!pdata) { + printk(KERN_ERR "DaVinci EMAC: No platfrom data\n"); + return -ENODEV; + } + + /* MAC addr and PHY mask , RMII enable info from platform_data */ + memcpy(priv->mac_addr, pdata->mac_addr, 6); + priv->phy_mask = pdata->phy_mask; + priv->rmii_en = pdata->rmii_en; + priv->version = pdata->version; + emac_dev = &ndev->dev; + /* Get EMAC platform data */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(emac_dev, "DaVinci EMAC: Error getting res\n"); + rc = -ENOENT; + goto probe_quit; + } + + priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; + size = res->end - res->start + 1; + if (!request_mem_region(res->start, size, ndev->name)) { + dev_err(emac_dev, "DaVinci EMAC: failed request_mem_region() \ + for regs\n"); + rc = -ENXIO; + goto probe_quit; + } + + priv->remap_addr = ioremap(res->start, size); + if (!priv->remap_addr) { + dev_err(emac_dev, "Unable to map IO\n"); + rc = -ENOMEM; + release_mem_region(res->start, size); + goto probe_quit; + } + priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset; + ndev->base_addr = (unsigned long)priv->remap_addr; + + priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; + priv->ctrl_ram_size = pdata->ctrl_ram_size; + priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(emac_dev, "DaVinci EMAC: Error getting irq res\n"); + rc = -ENOENT; + goto no_irq_res; + } + ndev->irq = res->start; + + if (!is_valid_ether_addr(priv->mac_addr)) { + /* Use random MAC if none passed */ + random_ether_addr(priv->mac_addr); + printk(KERN_WARNING "%s: using random MAC addr: %pM\n", + __func__, priv->mac_addr); + } + + ndev->netdev_ops = &emac_netdev_ops; + SET_ETHTOOL_OPS(ndev, ðtool_ops); + netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT); + + /* register the network device */ + SET_NETDEV_DEV(ndev, &pdev->dev); + rc = register_netdev(ndev); + if (rc) { + dev_err(emac_dev, "DaVinci EMAC: Error in register_netdev\n"); + rc = -ENODEV; + goto netdev_reg_err; + } + + clk_enable(emac_clk); + + /* MII/Phy intialisation, mdio bus registration */ + emac_mii = mdiobus_alloc(); + if (emac_mii == NULL) { + dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); + rc = -ENOMEM; + goto mdio_alloc_err; + } + + priv->mii_bus = emac_mii; + emac_mii->name = "emac-mii", + emac_mii->read = emac_mii_read, + emac_mii->write = emac_mii_write, + emac_mii->reset = emac_mii_reset, + emac_mii->irq = mii_irqs, + emac_mii->phy_mask = ~(priv->phy_mask); + emac_mii->parent = &pdev->dev; + emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); + mdio_max_freq = pdata->mdio_max_freq; + emac_mii->reset(emac_mii); + + /* Register the MII bus */ + rc = mdiobus_register(emac_mii); + if (rc) + goto mdiobus_quit; + + if (netif_msg_probe(priv)) { + dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ + "(regs: %p, irq: %d)\n", + (void *)priv->emac_base_phys, ndev->irq); + } + return 0; + +mdiobus_quit: + mdiobus_free(emac_mii); + +netdev_reg_err: +mdio_alloc_err: +no_irq_res: + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + iounmap(priv->remap_addr); + +probe_quit: + clk_put(emac_clk); + free_netdev(ndev); + return rc; +} + +/** + * davinci_emac_remove: EMAC device remove + * @pdev: The DaVinci EMAC device that we are removing + * + * Called when removing the device driver. We disable clock usage and release + * the resources taken up by the driver and unregister network device + */ +static int __devexit davinci_emac_remove(struct platform_device *pdev) +{ + struct resource *res; + struct net_device *ndev = platform_get_drvdata(pdev); + struct emac_priv *priv = netdev_priv(ndev); + + dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); + + clk_disable(emac_clk); + platform_set_drvdata(pdev, NULL); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mdiobus_unregister(priv->mii_bus); + mdiobus_free(priv->mii_bus); + + release_mem_region(res->start, res->end - res->start + 1); + + unregister_netdev(ndev); + free_netdev(ndev); + iounmap(priv->remap_addr); + + clk_disable(emac_clk); + clk_put(emac_clk); + + return 0; +} + +/** + * davinci_emac_driver: EMAC platform driver structure + * + * We implement only probe and remove functions - suspend/resume and + * others not supported by this module + */ +static struct platform_driver davinci_emac_driver = { + .driver = { + .name = "davinci_emac", + .owner = THIS_MODULE, + }, + .probe = davinci_emac_probe, + .remove = __devexit_p(davinci_emac_remove), +}; + +/** + * davinci_emac_init: EMAC driver module init + * + * Called when initializing the driver. We register the driver with + * the platform. + */ +static int __init davinci_emac_init(void) +{ + return platform_driver_register(&davinci_emac_driver); +} +module_init(davinci_emac_init); + +/** + * davinci_emac_exit: EMAC driver module exit + * + * Called when exiting the driver completely. We unregister the driver with + * the platform and exit + */ +static void __exit davinci_emac_exit(void) +{ + platform_driver_unregister(&davinci_emac_driver); +} +module_exit(davinci_emac_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("DaVinci EMAC Maintainer: Anant Gole "); +MODULE_AUTHOR("DaVinci EMAC Maintainer: Chaithrika U S "); +MODULE_DESCRIPTION("DaVinci EMAC Ethernet driver"); diff --git a/drivers/net/de600.c b/drivers/net/de600.c index de63f1d41d32..e1af089064bc 100644 --- a/drivers/net/de600.c +++ b/drivers/net/de600.c @@ -38,14 +38,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $, Bjorn Ekwall (bj /* Add more time here if your adapter won't work OK: */ #define DE600_SLOW_DOWN udelay(delay_time) -/* use 0 for production, 1 for verification, >2 for debug */ -#ifdef DE600_DEBUG -#define PRINTK(x) if (de600_debug >= 2) printk x -#else -#define DE600_DEBUG 0 -#define PRINTK(x) /**/ -#endif - #include #include #include @@ -67,10 +59,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $, Bjorn Ekwall (bj #include "de600.h" -static unsigned int de600_debug = DE600_DEBUG; -module_param(de600_debug, int, 0); -MODULE_PARM_DESC(de600_debug, "DE-600 debug level (0-2)"); - static unsigned int check_lost = 1; module_param(check_lost, bool, 0); MODULE_PARM_DESC(check_lost, "If set then check for unplugged de600"); @@ -180,20 +168,20 @@ static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev) if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) - return 1; + return NETDEV_TX_BUSY; /* else */ printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem"); /* Restart the adapter. */ spin_lock_irqsave(&de600_lock, flags); if (adapter_init(dev)) { spin_unlock_irqrestore(&de600_lock, flags); - return 1; + return NETDEV_TX_BUSY; } spin_unlock_irqrestore(&de600_lock, flags); } /* Start real output */ - PRINTK(("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages)); + pr_debug("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages); if ((len = skb->len) < RUNT) len = RUNT; @@ -211,7 +199,7 @@ static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev) if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) { if (adapter_init(dev)) { spin_unlock_irqrestore(&de600_lock, flags); - return 1; + return NETDEV_TX_BUSY; } } } @@ -259,7 +247,7 @@ static irqreturn_t de600_interrupt(int irq, void *dev_id) irq_status = de600_read_status(dev); do { - PRINTK(("de600_interrupt (%02X)\n", irq_status)); + pr_debug("de600_interrupt (%02X)\n", irq_status); if (irq_status & RX_GOOD) de600_rx_intr(dev); @@ -407,8 +395,7 @@ static struct net_device * __init de600_probe(void) printk(KERN_INFO "%s: D-Link DE-600 pocket adapter", dev->name); /* Alpha testers must have the version number to report bugs. */ - if (de600_debug > 1) - printk(version); + pr_debug("%s", version); /* probe for adapter */ err = -ENODEV; diff --git a/drivers/net/de620.c b/drivers/net/de620.c index d52f34cc9526..55d2bb67cffa 100644 --- a/drivers/net/de620.c +++ b/drivers/net/de620.c @@ -48,7 +48,6 @@ static const char version[] = * Compile-time options: (see below for descriptions) * -DDE620_IO=0x378 (lpt1) * -DDE620_IRQ=7 (lpt1) - * -DDE602_DEBUG=... * -DSHUTDOWN_WHEN_LOST * -DCOUNT_LOOPS * -DLOWSPEED @@ -98,15 +97,6 @@ static const char version[] = #define SHUTDOWN_WHEN_LOST */ -/* - * Enable debugging by "-DDE620_DEBUG=3" when compiling, - * OR by enabling the following #define - * - * use 0 for production, 1 for verification, >2 for debug - * -#define DE620_DEBUG 3 - */ - #ifdef LOWSPEED /* * Enable this #define if you want to see debugging output that show how long @@ -160,14 +150,6 @@ typedef unsigned char byte; #define RUNT 60 /* Too small Ethernet packet */ #define GIANT 1514 /* largest legal size packet, no fcs */ -#ifdef DE620_DEBUG /* Compile-time configurable */ -#define PRINTK(x) if (de620_debug >= 2) printk x -#else -#define DE620_DEBUG 0 -#define PRINTK(x) /**/ -#endif - - /* * Force media with insmod: * insmod de620.o bnc=1 @@ -186,8 +168,6 @@ static int io = DE620_IO; static int irq = DE620_IRQ; static int clone = DE620_CLONE; -static unsigned int de620_debug = DE620_DEBUG; - static spinlock_t de620_lock; module_param(bnc, int, 0); @@ -195,13 +175,11 @@ module_param(utp, int, 0); module_param(io, int, 0); module_param(irq, int, 0); module_param(clone, int, 0); -module_param(de620_debug, int, 0); MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)"); MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)"); MODULE_PARM_DESC(io, "DE-620 I/O base address,required"); MODULE_PARM_DESC(irq, "DE-620 IRQ number,required"); MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)"); -MODULE_PARM_DESC(de620_debug, "DE-620 debug level (0-2)"); /*********************************************** * * @@ -533,9 +511,9 @@ static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Start real output */ - spin_lock_irqsave(&de620_lock, flags) - PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n", - (int)skb->len, using_txbuf)); + spin_lock_irqsave(&de620_lock, flags); + pr_debug("de620_start_xmit: len=%d, bufs 0x%02x\n", + (int)skb->len, using_txbuf); /* select a free tx buffer. if there is one... */ switch (using_txbuf) { @@ -553,7 +531,7 @@ static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev) case (TXBF0 | TXBF1): /* NONE!!! */ printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name); spin_unlock_irqrestore(&de620_lock, flags); - return 1; + return NETDEV_TX_BUSY; } de620_write_block(dev, buffer, skb->len, len-skb->len); @@ -585,12 +563,12 @@ de620_interrupt(int irq_in, void *dev_id) /* Read the status register (_not_ the status port) */ irq_status = de620_get_register(dev, R_STS); - PRINTK(("de620_interrupt (%2.2X)\n", irq_status)); + pr_debug("de620_interrupt (%2.2X)\n", irq_status); if (irq_status & RXGOOD) { do { again = de620_rx_intr(dev); - PRINTK(("again=%d\n", again)); + pr_debug("again=%d\n", again); } while (again && (++bogus_count < 100)); } @@ -622,7 +600,7 @@ static int de620_rx_intr(struct net_device *dev) byte pagelink; byte curr_page; - PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page)); + pr_debug("de620_rx_intr: next_rx_page = %d\n", next_rx_page); /* Tell the adapter that we are going to read data, and from where */ de620_send_command(dev, W_CR | RRN); @@ -631,8 +609,9 @@ static int de620_rx_intr(struct net_device *dev) /* Deep breath, and away we goooooo */ de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf)); - PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n", - header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount)); + pr_debug("page status=0x%02x, nextpage=%d, packetsize=%d\n", + header_buf.status, header_buf.Rx_NextPage, + header_buf.Rx_ByteCount); /* Plausible page header? */ pagelink = header_buf.Rx_NextPage; @@ -683,7 +662,7 @@ static int de620_rx_intr(struct net_device *dev) buffer = skb_put(skb,size); /* copy the packet into the buffer */ de620_read_block(dev, buffer, size); - PRINTK(("Read %d bytes\n", size)); + pr_debug("Read %d bytes\n", size); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); /* deliver it "upstairs" */ /* count all receives */ @@ -696,7 +675,7 @@ static int de620_rx_intr(struct net_device *dev) /* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */ curr_page = de620_get_register(dev, R_CPR); de620_set_register(dev, W_NPRF, next_rx_page); - PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page)); + pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page); return (next_rx_page != curr_page); /* That was slightly tricky... */ } @@ -830,8 +809,7 @@ struct net_device * __init de620_probe(int unit) netdev_boot_setup_check(dev); } - if (de620_debug) - printk(version); + pr_debug("%s", version); printk(KERN_INFO "D-Link DE-620 pocket adapter"); @@ -878,14 +856,13 @@ struct net_device * __init de620_probe(int unit) /* base_addr and irq are already set, see above! */ /* dump eeprom */ - if (de620_debug) { - printk("\nEEPROM contents:\n"); - printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size); - printk("NodeID = %pM\n", nic_data.NodeID); - printk("Model = %d\n", nic_data.Model); - printk("Media = %d\n", nic_data.Media); - printk("SCR = 0x%02x\n", nic_data.SCR); - } + pr_debug("\nEEPROM contents:\n" + "RAM_Size = 0x%02X\n" + "NodeID = %pM\n" + "Model = %d\n" + "Media = %d\n" + "SCR = 0x%02x\n", nic_data.RAM_Size, nic_data.NodeID, + nic_data.Model, nic_data.Media, nic_data.SCR); err = register_netdev(dev); if (err) diff --git a/drivers/net/declance.c b/drivers/net/declance.c index b62405a69180..2b22e580c4de 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -895,6 +895,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; volatile u16 *ib = (volatile u16 *)dev->mem_start; + unsigned long flags; int entry, len; len = skb->len; @@ -907,6 +908,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_bytes += len; + spin_lock_irqsave(&lp->lock, flags); + entry = lp->tx_new; *lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len); *lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0; @@ -925,6 +928,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Kick the lance: transmit now */ writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD); + spin_unlock_irqrestore(&lp->lock, flags); + dev->trans_start = jiffies; dev_kfree_skb(skb); diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 4ec055dc7174..102b8d439714 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -3318,7 +3318,7 @@ static int dfx_xmt_queue_pkt( { skb_pull(skb,3); spin_unlock_irqrestore(&bp->lock, flags); - return(1); /* requeue packet for later */ + return NETDEV_TX_BUSY; /* requeue packet for later */ } /* diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 357f565851ed..97ea2d6d3fe1 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -810,7 +810,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) dev->mem_start = 0; - device->driver_data = dev; + dev_set_drvdata(device, dev); SET_NETDEV_DEV (dev, device); status = register_netdev(dev); @@ -957,7 +957,7 @@ static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL) netif_start_queue(dev); } else - status = -1; + status = NETDEV_TX_LOCKED; out: return status; @@ -1614,7 +1614,7 @@ static int __devexit depca_device_remove (struct device *device) struct depca_private *lp; int bus; - dev = device->driver_data; + dev = dev_get_drvdata(device); lp = netdev_priv(dev); unregister_netdev (dev); @@ -1839,7 +1839,7 @@ static int load_packet(struct net_device *dev, struct sk_buff *skb) lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ } else { - status = -1; + status = NETDEV_TX_LOCKED; } return status; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 4a1b554654eb..895d72143ee0 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -539,7 +539,7 @@ rio_tx_timeout (struct net_device *dev) dev->name, readl (ioaddr + TxStatus)); rio_free_tx(dev, 0); dev->if_port = 0; - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ } /* allocate and initialize Tx and Rx descriptors */ @@ -610,7 +610,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) if (np->link_status == 0) { /* Link Down */ dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } ioaddr = dev->base_addr; entry = np->cur_tx % TX_RING_SIZE; @@ -665,9 +665,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) writel (0, dev->base_addr + TFDListPtr1); } - /* NETDEV WATCHDOG timer */ - dev->trans_start = jiffies; - return 0; + return NETDEV_TX_OK; } static irqreturn_t diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index d8350860c0f8..dd771dea6ae6 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -756,7 +756,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) dm9000_dbg(db, 3, "%s:\n", __func__); if (db->tx_pkt_cnt > 1) - return 1; + return NETDEV_TX_BUSY; spin_lock_irqsave(&db->lock, flags); @@ -1170,6 +1170,21 @@ dm9000_stop(struct net_device *ndev) return 0; } +static const struct net_device_ops dm9000_netdev_ops = { + .ndo_open = dm9000_open, + .ndo_stop = dm9000_stop, + .ndo_start_xmit = dm9000_start_xmit, + .ndo_tx_timeout = dm9000_timeout, + .ndo_set_multicast_list = dm9000_hash_table, + .ndo_do_ioctl = dm9000_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = dm9000_poll_controller, +#endif +}; + #define res_size(_r) (((_r)->end - (_r)->start) + 1) /* @@ -1339,18 +1354,9 @@ dm9000_probe(struct platform_device *pdev) /* driver system function */ ether_setup(ndev); - ndev->open = &dm9000_open; - ndev->hard_start_xmit = &dm9000_start_xmit; - ndev->tx_timeout = &dm9000_timeout; - ndev->watchdog_timeo = msecs_to_jiffies(watchdog); - ndev->stop = &dm9000_stop; - ndev->set_multicast_list = &dm9000_hash_table; - ndev->ethtool_ops = &dm9000_ethtool_ops; - ndev->do_ioctl = &dm9000_ioctl; - -#ifdef CONFIG_NET_POLL_CONTROLLER - ndev->poll_controller = &dm9000_poll_controller; -#endif + ndev->netdev_ops = &dm9000_netdev_ops; + ndev->watchdog_timeo = msecs_to_jiffies(watchdog); + ndev->ethtool_ops = &dm9000_ethtool_ops; db->msg_enable = NETIF_MSG_LINK; db->mii.phy_id_mask = 0x1f; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index af5364f49550..f7929e89eb03 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -143,6 +143,8 @@ * FIXES: * 2005/12/02 - Michael O'Donnell * - Stratus87247: protect MDI control register manipulations + * 2009/06/01 - Andreas Mohr + * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs */ #include @@ -372,6 +374,7 @@ enum eeprom_op { enum eeprom_offsets { eeprom_cnfg_mdix = 0x03, + eeprom_phy_iface = 0x06, eeprom_id = 0x0A, eeprom_config_asf = 0x0D, eeprom_smbus_addr = 0x90, @@ -381,6 +384,18 @@ enum eeprom_cnfg_mdix { eeprom_mdix_enabled = 0x0080, }; +enum eeprom_phy_iface { + NoSuchPhy = 0, + I82553AB, + I82553C, + I82503, + DP83840, + S80C240, + S80C24, + I82555, + DP83840A = 10, +}; + enum eeprom_id { eeprom_id_wol = 0x0020, }; @@ -545,6 +560,7 @@ struct nic { u32 msg_enable ____cacheline_aligned; struct net_device *netdev; struct pci_dev *pdev; + u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); struct rx *rxs ____cacheline_aligned; struct rx *rx_to_use; @@ -899,7 +915,21 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, return err; } -static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) +static int mdio_read(struct net_device *netdev, int addr, int reg) +{ + struct nic *nic = netdev_priv(netdev); + return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); +} + +static void mdio_write(struct net_device *netdev, int addr, int reg, int data) +{ + struct nic *nic = netdev_priv(netdev); + + nic->mdio_ctrl(nic, addr, mdi_write, reg, data); +} + +/* the standard mdio_ctrl() function for usual MII-compliant hardware */ +static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) { u32 data_out = 0; unsigned int i; @@ -938,30 +968,83 @@ static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) return (u16)data_out; } -static int mdio_read(struct net_device *netdev, int addr, int reg) +/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ +static u16 mdio_ctrl_phy_82552_v(struct nic *nic, + u32 addr, + u32 dir, + u32 reg, + u16 data) { - return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0); + if ((reg == MII_BMCR) && (dir == mdi_write)) { + if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { + u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, + MII_ADVERTISE); + + /* + * Workaround Si issue where sometimes the part will not + * autoneg to 100Mbps even when advertised. + */ + if (advert & ADVERTISE_100FULL) + data |= BMCR_SPEED100 | BMCR_FULLDPLX; + else if (advert & ADVERTISE_100HALF) + data |= BMCR_SPEED100; + } + } + return mdio_ctrl_hw(nic, addr, dir, reg, data); } -static void mdio_write(struct net_device *netdev, int addr, int reg, int data) +/* Fully software-emulated mdio_ctrl() function for cards without + * MII-compliant PHYs. + * For now, this is mainly geared towards 80c24 support; in case of further + * requirements for other types (i82503, ...?) either extend this mechanism + * or split it, whichever is cleaner. + */ +static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, + u32 addr, + u32 dir, + u32 reg, + u16 data) { - struct nic *nic = netdev_priv(netdev); + /* might need to allocate a netdev_priv'ed register array eventually + * to be able to record state changes, but for now + * some fully hardcoded register handling ought to be ok I guess. */ - if ((nic->phy == phy_82552_v) && (reg == MII_BMCR) && - (data & (BMCR_ANRESTART | BMCR_ANENABLE))) { - u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); - - /* - * Workaround Si issue where sometimes the part will not - * autoneg to 100Mbps even when advertised. - */ - if (advert & ADVERTISE_100FULL) - data |= BMCR_SPEED100 | BMCR_FULLDPLX; - else if (advert & ADVERTISE_100HALF) - data |= BMCR_SPEED100; + if (dir == mdi_read) { + switch (reg) { + case MII_BMCR: + /* Auto-negotiation, right? */ + return BMCR_ANENABLE | + BMCR_FULLDPLX; + case MII_BMSR: + return BMSR_LSTATUS /* for mii_link_ok() */ | + BMSR_ANEGCAPABLE | + BMSR_10FULL; + case MII_ADVERTISE: + /* 80c24 is a "combo card" PHY, right? */ + return ADVERTISE_10HALF | + ADVERTISE_10FULL; + default: + DPRINTK(HW, DEBUG, + "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", + dir == mdi_read ? "READ" : "WRITE", addr, reg, data); + return 0xFFFF; + } + } else { + switch (reg) { + default: + DPRINTK(HW, DEBUG, + "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", + dir == mdi_read ? "READ" : "WRITE", addr, reg, data); + return 0xFFFF; + } } - - mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); +} +static inline int e100_phy_supports_mii(struct nic *nic) +{ + /* for now, just check it by comparing whether we + are using MII software emulation. + */ + return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); } static void e100_get_defaults(struct nic *nic) @@ -1013,7 +1096,8 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ config->tx_underrun_retry = 0x3; /* # of underrun retries */ - config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ + if (e100_phy_supports_mii(nic)) + config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ config->pad10 = 0x6; config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ @@ -1270,6 +1354,42 @@ static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) offsetof(struct mem, dump_buf)); } +static int e100_phy_check_without_mii(struct nic *nic) +{ + u8 phy_type; + int without_mii; + + phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; + + switch (phy_type) { + case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ + case I82503: /* Non-MII PHY; UNTESTED! */ + case S80C24: /* Non-MII PHY; tested and working */ + /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": + * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter + * doesn't have a programming interface of any sort. The + * media is sensed automatically based on how the link partner + * is configured. This is, in essence, manual configuration. + */ + DPRINTK(PROBE, INFO, + "found MII-less i82503 or 80c24 or other PHY\n"); + + nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; + nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ + + /* these might be needed for certain MII-less cards... + * nic->flags |= ich; + * nic->flags |= ich_10h_workaround; */ + + without_mii = 1; + break; + default: + without_mii = 0; + break; + } + return without_mii; +} + #define NCONFIG_AUTO_SWITCH 0x0080 #define MII_NSC_CONG MII_RESV1 #define NSC_CONG_ENABLE 0x0100 @@ -1290,9 +1410,21 @@ static int e100_phy_init(struct nic *nic) if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) break; } - DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - if (addr == 32) - return -EAGAIN; + if (addr == 32) { + /* uhoh, no PHY detected: check whether we seem to be some + * weird, rare variant which is *known* to not have any MII. + * But do this AFTER MII checking only, since this does + * lookup of EEPROM values which may easily be unreliable. */ + if (e100_phy_check_without_mii(nic)) + return 0; /* simply return and hope for the best */ + else { + /* for unknown cases log a fatal error */ + DPRINTK(HW, ERR, + "Failed to locate any known PHY, aborting.\n"); + return -EAGAIN; + } + } else + DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); /* Isolate all the PHY ids */ for (addr = 0; addr < 32; addr++) @@ -1320,6 +1452,9 @@ static int e100_phy_init(struct nic *nic) if (nic->phy == phy_82552_v) { u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); + /* assign special tweaked mdio_ctrl() function */ + nic->mdio_ctrl = mdio_ctrl_phy_82552_v; + /* Workaround Si not advertising flow-control during autoneg */ advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); @@ -1581,7 +1716,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* This is a hard error - log it. */ DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); netif_stop_queue(netdev); - return 1; + return NETDEV_TX_BUSY; } netdev->trans_start = jiffies; @@ -2585,6 +2720,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->netdev = netdev; nic->pdev = pdev; nic->msg_enable = (1 << debug) - 1; + nic->mdio_ctrl = mdio_ctrl_hw; pci_set_drvdata(pdev, netdev); if ((err = pci_enable_device(pdev))) { @@ -2822,12 +2958,13 @@ static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - /* Similar to calling e100_down(), but avoids adapter I/O. */ - e100_close(netdev); - - /* Detach; put netif into a state similar to hotplug unplug. */ - napi_enable(&nic->napi); netif_device_detach(netdev); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + if (netif_running(netdev)) + e100_down(nic); pci_disable_device(pdev); /* Request a slot reset. */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fffb006b7d95..8d36743c8140 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -498,6 +498,8 @@ int e1000_up(struct e1000_adapter *adapter) e1000_irq_enable(adapter); + netif_wake_queue(adapter->netdev); + /* fire a link change interrupt to start the watchdog */ ew32(ICS, E1000_ICS_LSC); return 0; @@ -1234,15 +1236,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, !e1000_check_mng_mode(hw)) e1000_get_hw_control(adapter); - /* tell the stack to leave us alone until e1000_open() is called */ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); cards_found++; @@ -1441,6 +1442,8 @@ static int e1000_open(struct net_device *netdev) if (test_bit(__E1000_TESTING, &adapter->flags)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = e1000_setup_all_tx_resources(adapter); if (err) @@ -2327,7 +2330,8 @@ static void e1000_set_rx_mode(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct dev_addr_list *uc_ptr; + struct netdev_hw_addr *ha; + bool use_uc = false; struct dev_addr_list *mc_ptr; u32 rctl; u32 hash_value; @@ -2366,12 +2370,11 @@ static void e1000_set_rx_mode(struct net_device *netdev) rctl |= E1000_RCTL_VFE; } - uc_ptr = NULL; if (netdev->uc_count > rar_entries - 1) { rctl |= E1000_RCTL_UPE; } else if (!(netdev->flags & IFF_PROMISC)) { rctl &= ~E1000_RCTL_UPE; - uc_ptr = netdev->uc_list; + use_uc = true; } ew32(RCTL, rctl); @@ -2389,13 +2392,20 @@ static void e1000_set_rx_mode(struct net_device *netdev) * if there are not 14 addresses, go ahead and clear the filters * -- with 82571 controllers only 0-13 entries are filled here */ + i = 1; + if (use_uc) + list_for_each_entry(ha, &netdev->uc_list, list) { + if (i == rar_entries) + break; + e1000_rar_set(hw, ha->addr, i++); + } + + WARN_ON(i == rar_entries); + mc_ptr = netdev->mc_list; - for (i = 1; i < rar_entries; i++) { - if (uc_ptr) { - e1000_rar_set(hw, uc_ptr->da_addr, i); - uc_ptr = uc_ptr->next; - } else if (mc_ptr) { + for (; i < rar_entries; i++) { + if (mc_ptr) { e1000_rar_set(hw, mc_ptr->da_addr, i); mc_ptr = mc_ptr->next; } else { @@ -2405,7 +2415,6 @@ static void e1000_set_rx_mode(struct net_device *netdev) E1000_WRITE_FLUSH(); } } - WARN_ON(uc_ptr != NULL); /* load any remaining addresses into the hash table */ @@ -2590,7 +2599,6 @@ static void e1000_watchdog(unsigned long data) ew32(TCTL, tctl); netif_carrier_on(netdev); - netif_wake_queue(netdev); mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); adapter->smartspeed = 0; } else { @@ -2607,7 +2615,6 @@ static void e1000_watchdog(unsigned long data) printk(KERN_INFO "e1000: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_stop_queue(netdev); mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); /* 80003ES2LAN workaround-- @@ -2645,6 +2652,8 @@ static void e1000_watchdog(unsigned long data) * (Do the reset outside of interrupt context). */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } } @@ -2989,7 +2998,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = map[0] + offset; + buffer_info->dma = skb_shinfo(skb)->dma_head + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; @@ -3030,7 +3039,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = map[f + 1] + offset; + buffer_info->dma = map[f] + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; @@ -3362,7 +3371,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (count) { e1000_tx_queue(adapter, tx_ring, tx_flags, count); - netdev->trans_start = jiffies; /* Make sure there is space in the ring for the next send. */ e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 6c01a2072c87..b53b40ba88a8 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -71,6 +71,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw); static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); static s32 e1000_led_on_82574(struct e1000_hw *hw); +static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); /** * e1000_init_phy_params_82571 - Init PHY func ptrs. @@ -212,6 +213,9 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; struct e1000_mac_operations *func = &mac->ops; + u32 swsm = 0; + u32 swsm2 = 0; + bool force_clear_smbi = false; /* Set media type */ switch (adapter->pdev->device) { @@ -276,6 +280,50 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) break; } + /* + * Ensure that the inter-port SWSM.SMBI lock bit is clear before + * first NVM or PHY acess. This should be done for single-port + * devices, and for one port only on dual-port devices so that + * for those devices we can still use the SMBI lock to synchronize + * inter-port accesses to the PHY & NVM. + */ + switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + swsm2 = er32(SWSM2); + + if (!(swsm2 & E1000_SWSM2_LOCK)) { + /* Only do this for the first interface on this card */ + ew32(SWSM2, + swsm2 | E1000_SWSM2_LOCK); + force_clear_smbi = true; + } else + force_clear_smbi = false; + break; + default: + force_clear_smbi = true; + break; + } + + if (force_clear_smbi) { + /* Make sure SWSM.SMBI is clear */ + swsm = er32(SWSM); + if (swsm & E1000_SWSM_SMBI) { + /* This bit should not be set on a first interface, and + * indicates that the bootagent or EFI code has + * improperly left this bit enabled + */ + hw_dbg(hw, "Please update your 82571 Bootagent\n"); + } + ew32(SWSM, swsm & ~E1000_SWSM_SMBI); + } + + /* + * Initialze device specific counter of SMBI acquisition + * timeouts. + */ + hw->dev_spec.e82571.smb_counter = 0; + return 0; } @@ -341,8 +389,10 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1, &eeprom_data) < 0) break; - if (eeprom_data & NVM_WORD1A_ASPM_MASK) - adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; + if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) { + adapter->flags |= FLAG_HAS_JUMBO_FRAMES; + adapter->max_hw_frame_size = DEFAULT_JUMBO; + } } break; default: @@ -411,11 +461,37 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) { u32 swsm; - s32 timeout = hw->nvm.word_size + 1; + s32 sw_timeout = hw->nvm.word_size + 1; + s32 fw_timeout = hw->nvm.word_size + 1; s32 i = 0; + /* + * If we have timedout 3 times on trying to acquire + * the inter-port SMBI semaphore, there is old code + * operating on the other port, and it is not + * releasing SMBI. Modify the number of times that + * we try for the semaphore to interwork with this + * older code. + */ + if (hw->dev_spec.e82571.smb_counter > 2) + sw_timeout = 1; + + /* Get the SW semaphore */ + while (i < sw_timeout) { + swsm = er32(SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + + udelay(50); + i++; + } + + if (i == sw_timeout) { + hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n"); + hw->dev_spec.e82571.smb_counter++; + } /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < fw_timeout; i++) { swsm = er32(SWSM); ew32(SWSM, swsm | E1000_SWSM_SWESMBI); @@ -426,9 +502,9 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) udelay(50); } - if (i == timeout) { + if (i == fw_timeout) { /* Release semaphores */ - e1000e_put_hw_semaphore(hw); + e1000_put_hw_semaphore_82571(hw); hw_dbg(hw, "Driver can't access the NVM\n"); return -E1000_ERR_NVM; } @@ -447,9 +523,7 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) u32 swsm; swsm = er32(SWSM); - - swsm &= ~E1000_SWSM_SWESMBI; - + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); ew32(SWSM, swsm); } @@ -1585,6 +1659,7 @@ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) static struct e1000_mac_operations e82571_mac_ops = { /* .check_mng_mode: mac type dependent */ /* .check_for_link: media type dependent */ + .id_led_init = e1000e_id_led_init, .cleanup_led = e1000e_cleanup_led_generic, .clear_hw_cntrs = e1000_clear_hw_cntrs_82571, .get_bus_info = e1000e_get_bus_info_pcie, @@ -1596,6 +1671,7 @@ static struct e1000_mac_operations e82571_mac_ops = { .init_hw = e1000_init_hw_82571, .setup_link = e1000_setup_link_82571, /* .setup_physical_interface: media type dependent */ + .setup_led = e1000e_setup_led_generic, }; static struct e1000_phy_operations e82_phy_ops_igp = { @@ -1672,6 +1748,7 @@ struct e1000_info e1000_82571_info = { | FLAG_TARC_SPEED_MODE_BIT /* errata */ | FLAG_APME_CHECK_PORT_B, .pba = 38, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_igp, @@ -1688,6 +1765,7 @@ struct e1000_info e1000_82572_info = { | FLAG_HAS_CTRLEXT_ON_LOAD | FLAG_TARC_SPEED_MODE_BIT, /* errata */ .pba = 38, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_igp, @@ -1706,6 +1784,7 @@ struct e1000_info e1000_82573_info = { | FLAG_HAS_ERT | FLAG_HAS_SWSM_ON_LOAD, .pba = 20, + .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_m88, @@ -1724,6 +1803,7 @@ struct e1000_info e1000_82574_info = { | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, .pba = 20, + .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_bm, @@ -1740,6 +1820,7 @@ struct e1000_info e1000_82583_info = { | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, .pba = 20, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_bm, diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 243aa499fe90..8890c97e1120 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -56,6 +56,7 @@ /* Wake Up Control */ #define E1000_WUC_APME 0x00000001 /* APM Enable */ #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ +#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ /* Wake Up Filter Control */ #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ @@ -65,6 +66,13 @@ #define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ +/* Wake Up Status */ +#define E1000_WUS_LNKC E1000_WUFC_LNKC +#define E1000_WUS_MAG E1000_WUFC_MAG +#define E1000_WUS_EX E1000_WUFC_EX +#define E1000_WUS_MC E1000_WUFC_MC +#define E1000_WUS_BC E1000_WUFC_BC + /* Extended Device Control */ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ @@ -77,6 +85,7 @@ #define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ #define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ +#define E1000_CTRL_EXT_PHYPDEN 0x00100000 /* Receive Descriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ @@ -140,6 +149,7 @@ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min threshold size */ #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ #define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */ @@ -153,6 +163,7 @@ #define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ #define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ #define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ +#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ @@ -255,11 +266,16 @@ #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX /* LED Control */ +#define E1000_PHY_LED0_MODE_MASK 0x00000007 +#define E1000_PHY_LED0_IVRT 0x00000008 +#define E1000_PHY_LED0_MASK 0x0000001F + #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 #define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_MODE_LINK_UP 0x2 #define E1000_LEDCTL_MODE_LED_ON 0xE #define E1000_LEDCTL_MODE_LED_OFF 0xF @@ -360,6 +376,8 @@ #define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ +#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ + /* Interrupt Cause Read */ #define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ #define E1000_ICR_LSC 0x00000004 /* Link Status Change */ @@ -469,6 +487,8 @@ #define AUTO_READ_DONE_TIMEOUT 10 /* Flow Control */ +#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ +#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ /* Transmit Configuration Word */ @@ -674,6 +694,8 @@ #define IFE_C_E_PHY_ID 0x02A80310 #define BME1000_E_PHY_ID 0x01410CB0 #define BME1000_E_PHY_ID_R2 0x01410CB1 +#define I82577_E_PHY_ID 0x01540050 +#define I82578_E_PHY_ID 0x004DD040 /* M88E1000 Specific Registers */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ @@ -727,6 +749,9 @@ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 +#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 +#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C + /* BME1000 PHY Specific Control Register */ #define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 44f0bf23dafc..981936c1fb46 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -96,6 +96,51 @@ struct e1000_info; /* Number of packet split data buffers (not including the header buffer) */ #define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) +#define DEFAULT_JUMBO 9234 + +/* BM/HV Specific Registers */ +#define BM_PORT_CTRL_PAGE 769 + +#define PHY_UPPER_SHIFT 21 +#define BM_PHY_REG(page, reg) \ + (((reg) & MAX_PHY_REG_ADDRESS) |\ + (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ + (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) + +/* PHY Wakeup Registers and defines */ +#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) +#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) +#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) +#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) +#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) +#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) +#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) +#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) +#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) + +#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ +#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ +#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ +#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ +#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ +#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ +#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ + +#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */ +#define HV_SCC_LOWER PHY_REG(778, 17) +#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */ +#define HV_ECOL_LOWER PHY_REG(778, 19) +#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */ +#define HV_MCC_LOWER PHY_REG(778, 21) +#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */ +#define HV_LATECOL_LOWER PHY_REG(778, 24) +#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */ +#define HV_COLC_LOWER PHY_REG(778, 26) +#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */ +#define HV_DC_LOWER PHY_REG(778, 28) +#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ +#define HV_TNCRS_LOWER PHY_REG(778, 30) + enum e1000_boards { board_82571, board_82572, @@ -106,6 +151,7 @@ enum e1000_boards { board_ich8lan, board_ich9lan, board_ich10lan, + board_pchlan, }; struct e1000_queue_stats { @@ -293,6 +339,7 @@ struct e1000_adapter { u32 eeprom_wol; u32 wol; u32 pba; + u32 max_hw_frame_size; bool fc_autoneg; @@ -302,6 +349,7 @@ struct e1000_adapter { unsigned int flags2; struct work_struct downshift_task; struct work_struct update_phy_task; + struct work_struct led_blink_task; }; struct e1000_info { @@ -309,6 +357,7 @@ struct e1000_info { unsigned int flags; unsigned int flags2; u32 pba; + u32 max_hw_frame_size; s32 (*get_variants)(struct e1000_adapter *); struct e1000_mac_operations *mac_ops; struct e1000_phy_operations *phy_ops; @@ -351,6 +400,7 @@ struct e1000_info { /* CRC Stripping defines */ #define FLAG2_CRC_STRIPPING (1 << 0) +#define FLAG2_HAS_PHY_WAKEUP (1 << 1) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) @@ -404,6 +454,7 @@ extern struct e1000_info e1000_82583_info; extern struct e1000_info e1000_ich8_info; extern struct e1000_info e1000_ich9_info; extern struct e1000_info e1000_ich10_info; +extern struct e1000_info e1000_pch_info; extern struct e1000_info e1000_es2_info; extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); @@ -425,6 +476,7 @@ extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw); extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); extern s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); +extern s32 e1000e_setup_led_generic(struct e1000_hw *hw); extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); extern s32 e1000e_led_on_generic(struct e1000_hw *hw); extern s32 e1000e_led_off_generic(struct e1000_hw *hw); @@ -493,6 +545,15 @@ extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000e_check_downshift(struct e1000_hw *hw); +extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); +extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); +extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow); +extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); +extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); +extern s32 e1000_check_polarity_82577(struct e1000_hw *hw); +extern s32 e1000_get_phy_info_82577(struct e1000_hw *hw); +extern s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); +extern s32 e1000_get_cable_length_82577(struct e1000_hw *hw); static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) { diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index 8964838c686b..ae5d73689353 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -1366,6 +1366,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) } static struct e1000_mac_operations es2_mac_ops = { + .id_led_init = e1000e_id_led_init, .check_mng_mode = e1000e_check_mng_mode_generic, /* check_for_link dependent on media type */ .cleanup_led = e1000e_cleanup_led_generic, @@ -1379,6 +1380,7 @@ static struct e1000_mac_operations es2_mac_ops = { .init_hw = e1000_init_hw_80003es2lan, .setup_link = e1000e_setup_link, /* setup_physical_interface dependent on media type */ + .setup_led = e1000e_setup_led_generic, }; static struct e1000_phy_operations es2_phy_ops = { @@ -1422,6 +1424,7 @@ struct e1000_info e1000_es2_info = { | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ | FLAG_TIPG_MEDIUM_FOR_80003ESLAN, .pba = 38, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_80003es2lan, .mac_ops = &es2_mac_ops, .phy_ops = &es2_phy_ops, diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 4d25ede88369..1bf4d2a5d34f 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -167,6 +167,15 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; + + /* MDI-X => 2; MDI =>1; Invalid =>0 */ + if ((hw->phy.media_type == e1000_media_type_copper) && + !hw->mac.get_link_status) + ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : + ETH_TP_MDI; + else + ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + return 0; } @@ -776,6 +785,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) u32 after; u32 i; u32 toggle; + u32 mask; /* * The status register is Read Only, so a write should fail. @@ -788,17 +798,9 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) case e1000_80003es2lan: toggle = 0x7FFFF3FF; break; - case e1000_82573: - case e1000_82574: - case e1000_82583: - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: + default: toggle = 0x7FFFF033; break; - default: - toggle = 0xFFFFF833; - break; } before = er32(STATUS); @@ -844,11 +846,18 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); + mask = 0x8003FFFF; + switch (mac->type) { + case e1000_ich10lan: + case e1000_pchlan: + mask |= (1 << 18); + break; + default: + break; + } for (i = 0; i < mac->rar_entry_count; i++) REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), - ((mac->type == e1000_ich10lan) ? - 0x8007FFFF : 0x8003FFFF), - 0xFFFFFFFF); + mask, 0xFFFFFFFF); for (i = 0; i < mac->mta_reg_count; i++) REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); @@ -1786,15 +1795,22 @@ static int e1000_set_wol(struct net_device *netdev, /* bit defines for adapter->led_status */ #define E1000_LED_ON 0 -static void e1000_led_blink_callback(unsigned long data) +static void e1000e_led_blink_task(struct work_struct *work) { - struct e1000_adapter *adapter = (struct e1000_adapter *) data; + struct e1000_adapter *adapter = container_of(work, + struct e1000_adapter, led_blink_task); if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) adapter->hw.mac.ops.led_off(&adapter->hw); else adapter->hw.mac.ops.led_on(&adapter->hw); +} +static void e1000_led_blink_callback(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + + schedule_work(&adapter->led_blink_task); mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); } @@ -1807,7 +1823,9 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) data = INT_MAX; if ((hw->phy.type == e1000_phy_ife) || + (hw->mac.type == e1000_pchlan) || (hw->mac.type == e1000_82574)) { + INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); if (!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index d8b82296f41e..163c1c0cfee7 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -193,7 +193,11 @@ enum e1e_registers { E1000_RXCSUM = 0x05000, /* Rx Checksum Control - RW */ E1000_RFCTL = 0x05008, /* Receive Filter Control */ E1000_MTA = 0x05200, /* Multicast Table Array - RW Array */ - E1000_RA = 0x05400, /* Receive Address - RW Array */ + E1000_RAL_BASE = 0x05400, /* Receive Address Low - RW */ +#define E1000_RAL(_n) (E1000_RAL_BASE + ((_n) * 8)) +#define E1000_RA (E1000_RAL(0)) + E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */ +#define E1000_RAH(_n) (E1000_RAH_BASE + ((_n) * 8)) E1000_VFTA = 0x05600, /* VLAN Filter Table Array - RW Array */ E1000_WUC = 0x05800, /* Wakeup Control - RW */ E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */ @@ -210,6 +214,7 @@ enum e1e_registers { E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */ E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ + E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ E1000_HICR = 0x08F00, /* Host Interface Control */ }; @@ -253,7 +258,7 @@ enum e1e_registers { #define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 #define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0008 +#define IGP01E1000_PSSR_MDIX 0x0800 #define IGP01E1000_PSSR_SPEED_MASK 0xC000 #define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 @@ -368,6 +373,10 @@ enum e1e_registers { #define E1000_DEV_ID_ICH10_R_BM_V 0x10CE #define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE #define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF +#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA +#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB +#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF +#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 #define E1000_REVISION_4 4 @@ -383,6 +392,7 @@ enum e1000_mac_type { e1000_ich8lan, e1000_ich9lan, e1000_ich10lan, + e1000_pchlan, }; enum e1000_media_type { @@ -417,6 +427,8 @@ enum e1000_phy_type { e1000_phy_igp_3, e1000_phy_ife, e1000_phy_bm, + e1000_phy_82578, + e1000_phy_82577, }; enum e1000_bus_width { @@ -720,6 +732,7 @@ struct e1000_host_mng_command_info { /* Function pointers and static data for the MAC. */ struct e1000_mac_operations { + s32 (*id_led_init)(struct e1000_hw *); bool (*check_mng_mode)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); s32 (*cleanup_led)(struct e1000_hw *); @@ -733,11 +746,13 @@ struct e1000_mac_operations { s32 (*init_hw)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); s32 (*setup_physical_interface)(struct e1000_hw *); + s32 (*setup_led)(struct e1000_hw *); }; /* Function pointers for the PHY. */ struct e1000_phy_operations { s32 (*acquire_phy)(struct e1000_hw *); + s32 (*check_polarity)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); s32 (*commit_phy)(struct e1000_hw *); s32 (*force_speed_duplex)(struct e1000_hw *); @@ -869,6 +884,7 @@ struct e1000_fc_info { struct e1000_dev_spec_82571 { bool laa_is_present; bool alt_mac_addr_is_present; + u32 smb_counter; }; struct e1000_shadow_ram { diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 6d1aab6316ba..9e23f50fb9cd 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -48,6 +48,10 @@ * 82567LF-3 Gigabit Network Connection * 82567LM-3 Gigabit Network Connection * 82567LM-4 Gigabit Network Connection + * 82577LM Gigabit Network Connection + * 82577LC Gigabit Network Connection + * 82578DM Gigabit Network Connection + * 82578DC Gigabit Network Connection */ #include @@ -116,6 +120,8 @@ #define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 #define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 +#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ + /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { @@ -186,6 +192,14 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); +static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); +static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); +static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); +static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); +static s32 e1000_setup_led_pchlan(struct e1000_hw *hw); +static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); +static s32 e1000_led_on_pchlan(struct e1000_hw *hw); +static s32 e1000_led_off_pchlan(struct e1000_hw *hw); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -212,6 +226,41 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) #define ew16flash(reg,val) __ew16flash(hw, (reg), (val)) #define ew32flash(reg,val) __ew32flash(hw, (reg), (val)) +/** + * e1000_init_phy_params_pchlan - Initialize PHY function pointers + * @hw: pointer to the HW structure + * + * Initialize family-specific PHY parameters and function pointers. + **/ +static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = 0; + + phy->addr = 1; + phy->reset_delay_us = 100; + + phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan; + phy->ops.read_phy_reg = e1000_read_phy_reg_hv; + phy->ops.write_phy_reg = e1000_write_phy_reg_hv; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + + phy->id = e1000_phy_unknown; + e1000e_get_phy_id(hw); + phy->type = e1000e_get_phy_type_from_id(phy->id); + + if (phy->type == e1000_phy_82577) { + phy->ops.check_polarity = e1000_check_polarity_82577; + phy->ops.force_speed_duplex = + e1000_phy_force_speed_duplex_82577; + phy->ops.get_cable_length = e1000_get_cable_length_82577; + phy->ops.get_phy_info = e1000_get_phy_info_82577; + phy->ops.commit_phy = e1000e_phy_sw_reset; + } + + return ret_val; +} + /** * e1000_init_phy_params_ich8lan - Initialize PHY function pointers * @hw: pointer to the HW structure @@ -273,6 +322,8 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) break; } + phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan; + return 0; } @@ -358,6 +409,36 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) /* Set if manageability features are enabled. */ mac->arc_subsystem_valid = 1; + /* LED operations */ + switch (mac->type) { + case e1000_ich8lan: + case e1000_ich9lan: + case e1000_ich10lan: + /* ID LED init */ + mac->ops.id_led_init = e1000e_id_led_init; + /* setup LED */ + mac->ops.setup_led = e1000e_setup_led_generic; + /* cleanup LED */ + mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; + /* turn on/off LED */ + mac->ops.led_on = e1000_led_on_ich8lan; + mac->ops.led_off = e1000_led_off_ich8lan; + break; + case e1000_pchlan: + /* ID LED init */ + mac->ops.id_led_init = e1000_id_led_init_pchlan; + /* setup LED */ + mac->ops.setup_led = e1000_setup_led_pchlan; + /* cleanup LED */ + mac->ops.cleanup_led = e1000_cleanup_led_pchlan; + /* turn on/off LED */ + mac->ops.led_on = e1000_led_on_pchlan; + mac->ops.led_off = e1000_led_off_pchlan; + break; + default: + break; + } + /* Enable PCS Lock-loss workaround for ICH8 */ if (mac->type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, 1); @@ -378,10 +459,18 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) if (rc) return rc; - rc = e1000_init_phy_params_ich8lan(hw); + if (hw->mac.type == e1000_pchlan) + rc = e1000_init_phy_params_pchlan(hw); + else + rc = e1000_init_phy_params_ich8lan(hw); if (rc) return rc; + if (adapter->hw.phy.type == e1000_phy_ife) { + adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; + adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN; + } + if ((adapter->hw.mac.type == e1000_ich8lan) && (adapter->hw.phy.type == e1000_phy_igp_3)) adapter->flags |= FLAG_LSC_GIG_SPEED_DROP; @@ -410,12 +499,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) while (timeout) { extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - extcnf_ctrl = er32(EXTCNF_CTRL); - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) - break; + if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) { + extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; + ew32(EXTCNF_CTRL, extcnf_ctrl); + + extcnf_ctrl = er32(EXTCNF_CTRL); + if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) + break; + } mdelay(1); timeout--; } @@ -554,6 +646,53 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) return 0; } +/** + * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be + * done after every PHY reset. + **/ +static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) +{ + s32 ret_val = 0; + + if (hw->mac.type != e1000_pchlan) + return ret_val; + + if (((hw->phy.type == e1000_phy_82577) && + ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || + ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { + /* Disable generation of early preamble */ + ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431); + if (ret_val) + return ret_val; + + /* Preamble tuning for SSC */ + ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204); + if (ret_val) + return ret_val; + } + + if (hw->phy.type == e1000_phy_82578) { + /* + * Return registers to default by doing a soft reset then + * writing 0x3140 to the control register. + */ + if (hw->phy.revision < 2) { + e1000e_phy_sw_reset(hw); + ret_val = e1e_wphy(hw, PHY_CONTROL, 0x3140); + } + } + + /* Select page 0 */ + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + hw->phy.addr = 1; + e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + hw->phy.ops.release_phy(hw); + + return ret_val; +} + /** * e1000_phy_hw_reset_ich8lan - Performs a PHY reset * @hw: pointer to the HW structure @@ -575,6 +714,12 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + if (ret_val) + return ret_val; + } + /* * Initialize the PHY from the NVM on ICH platforms. This * is needed due to an issue where the NVM configuration is @@ -701,7 +846,7 @@ static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw) phy->polarity_correction = (!(data & IFE_PSC_AUTO_POLARITY_DISABLE)); if (phy->polarity_correction) { - ret_val = e1000_check_polarity_ife_ich8lan(hw); + ret_val = phy->ops.check_polarity(hw); if (ret_val) return ret_val; } else { @@ -741,6 +886,8 @@ static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) break; case e1000_phy_igp_3: case e1000_phy_bm: + case e1000_phy_82578: + case e1000_phy_82577: return e1000e_get_phy_info_igp(hw); break; default: @@ -1851,6 +1998,79 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) return 0; } +/** + * e1000_id_led_init_pchlan - store LED configurations + * @hw: pointer to the HW structure + * + * PCH does not control LEDs via the LEDCTL register, rather it uses + * the PHY LED configuration register. + * + * PCH also does not have an "always on" or "always off" mode which + * complicates the ID feature. Instead of using the "on" mode to indicate + * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()), + * use "link_up" mode. The LEDs will still ID on request if there is no + * link based on logic in e1000_led_[on|off]_pchlan(). + **/ +static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; + const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; + const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; + u16 data, i, temp, shift; + + /* Get default ID LED modes */ + ret_val = hw->nvm.ops.valid_led_default(hw, &data); + if (ret_val) + goto out; + + mac->ledctl_default = er32(LEDCTL); + mac->ledctl_mode1 = mac->ledctl_default; + mac->ledctl_mode2 = mac->ledctl_default; + + for (i = 0; i < 4; i++) { + temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; + shift = (i * 5); + switch (temp) { + case ID_LED_ON1_DEF2: + case ID_LED_ON1_ON2: + case ID_LED_ON1_OFF2: + mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); + mac->ledctl_mode1 |= (ledctl_on << shift); + break; + case ID_LED_OFF1_DEF2: + case ID_LED_OFF1_ON2: + case ID_LED_OFF1_OFF2: + mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); + mac->ledctl_mode1 |= (ledctl_off << shift); + break; + default: + /* Do nothing */ + break; + } + switch (temp) { + case ID_LED_DEF1_ON2: + case ID_LED_ON1_ON2: + case ID_LED_OFF1_ON2: + mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); + mac->ledctl_mode2 |= (ledctl_on << shift); + break; + case ID_LED_DEF1_OFF2: + case ID_LED_ON1_OFF2: + case ID_LED_OFF1_OFF2: + mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); + mac->ledctl_mode2 |= (ledctl_off << shift); + break; + default: + /* Do nothing */ + break; + } + } + +out: + return ret_val; +} + /** * e1000_get_bus_info_ich8lan - Get/Set the bus type and width * @hw: pointer to the HW structure @@ -1960,6 +2180,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) kab |= E1000_KABGTXD_BGSQLBIAS; ew32(KABGTXD, kab); + if (hw->mac.type == e1000_pchlan) + ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + return ret_val; } @@ -1985,7 +2208,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) e1000_initialize_hw_bits_ich8lan(hw); /* Initialize identification LED */ - ret_val = e1000e_id_led_init(hw); + ret_val = mac->ops.id_led_init(hw); if (ret_val) { hw_dbg(hw, "Error initializing identification LED\n"); return ret_val; @@ -2030,6 +2253,16 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) ctrl_ext |= E1000_CTRL_EXT_RO_DIS; ew32(CTRL_EXT, ctrl_ext); + /* + * The 82578 Rx buffer will stall if wakeup is enabled in host and + * the ME. Reading the BM_WUC register will clear the host wakeup bit. + * Reset the phy after disabling host wakeup to reset the Rx buffer. + */ + if (hw->phy.type == e1000_phy_82578) { + e1e_rphy(hw, BM_WUC, &i); + e1000e_phy_hw_reset_generic(hw); + } + /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link @@ -2054,6 +2287,9 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) /* Extended Device Control */ reg = er32(CTRL_EXT); reg |= (1 << 22); + /* Enable PHY low-power state when MAC is at D3 w/o WoL */ + if (hw->mac.type >= e1000_pchlan) + reg |= E1000_CTRL_EXT_PHYPDEN; ew32(CTRL_EXT, reg); /* Transmit Descriptor Control 0 */ @@ -2112,8 +2348,13 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) * the default flow control setting, so we explicitly * set it to full. */ - if (hw->fc.requested_mode == e1000_fc_default) - hw->fc.requested_mode = e1000_fc_full; + if (hw->fc.requested_mode == e1000_fc_default) { + /* Workaround h/w hang when Tx flow control enabled */ + if (hw->mac.type == e1000_pchlan) + hw->fc.requested_mode = e1000_fc_rx_pause; + else + hw->fc.requested_mode = e1000_fc_full; + } /* * Save off the requested flow control mode for use later. Depending @@ -2130,6 +2371,14 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) return ret_val; ew32(FCTTV, hw->fc.pause_time); + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82577)) { + ret_val = hw->phy.ops.write_phy_reg(hw, + PHY_REG(BM_PORT_CTRL_PAGE, 27), + hw->fc.pause_time); + if (ret_val) + return ret_val; + } return e1000e_set_fc_watermarks(hw); } @@ -2169,18 +2418,26 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; - if (hw->phy.type == e1000_phy_igp_3) { + switch (hw->phy.type) { + case e1000_phy_igp_3: ret_val = e1000e_copper_link_setup_igp(hw); if (ret_val) return ret_val; - } else if (hw->phy.type == e1000_phy_bm) { + break; + case e1000_phy_bm: + case e1000_phy_82578: ret_val = e1000e_copper_link_setup_m88(hw); if (ret_val) return ret_val; - } - - if (hw->phy.type == e1000_phy_ife) { - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, ®_data); + break; + case e1000_phy_82577: + ret_val = e1000_copper_link_setup_82577(hw); + if (ret_val) + return ret_val; + break; + case e1000_phy_ife: + ret_val = hw->phy.ops.read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, + ®_data); if (ret_val) return ret_val; @@ -2198,9 +2455,13 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) reg_data |= IFE_PMC_AUTO_MDIX; break; } - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, reg_data); + ret_val = hw->phy.ops.write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, + reg_data); if (ret_val) return ret_val; + break; + default: + break; } return e1000e_setup_copper_link(hw); } @@ -2417,18 +2678,26 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation * to a lower speed. * - * Should only be called for ICH9 and ICH10 devices. + * Should only be called for applicable parts. **/ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) { u32 phy_ctrl; - if ((hw->mac.type == e1000_ich10lan) || - (hw->mac.type == e1000_ich9lan)) { + switch (hw->mac.type) { + case e1000_ich9lan: + case e1000_ich10lan: + case e1000_pchlan: phy_ctrl = er32(PHY_CTRL); phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; ew32(PHY_CTRL, phy_ctrl); + + /* Workaround SWFLAG unexpectedly set during S0->Sx */ + if (hw->mac.type == e1000_pchlan) + udelay(500); + default: + break; } return; @@ -2481,6 +2750,92 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) return 0; } +/** + * e1000_setup_led_pchlan - Configures SW controllable LED + * @hw: pointer to the HW structure + * + * This prepares the SW controllable LED for use. + **/ +static s32 e1000_setup_led_pchlan(struct e1000_hw *hw) +{ + return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG, + (u16)hw->mac.ledctl_mode1); +} + +/** + * e1000_cleanup_led_pchlan - Restore the default LED operation + * @hw: pointer to the HW structure + * + * Return the LED back to the default configuration. + **/ +static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw) +{ + return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG, + (u16)hw->mac.ledctl_default); +} + +/** + * e1000_led_on_pchlan - Turn LEDs on + * @hw: pointer to the HW structure + * + * Turn on the LEDs. + **/ +static s32 e1000_led_on_pchlan(struct e1000_hw *hw) +{ + u16 data = (u16)hw->mac.ledctl_mode2; + u32 i, led; + + /* + * If no link, then turn LED on by setting the invert bit + * for each LED that's mode is "link_up" in ledctl_mode2. + */ + if (!(er32(STATUS) & E1000_STATUS_LU)) { + for (i = 0; i < 3; i++) { + led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; + if ((led & E1000_PHY_LED0_MODE_MASK) != + E1000_LEDCTL_MODE_LINK_UP) + continue; + if (led & E1000_PHY_LED0_IVRT) + data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); + else + data |= (E1000_PHY_LED0_IVRT << (i * 5)); + } + } + + return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG, data); +} + +/** + * e1000_led_off_pchlan - Turn LEDs off + * @hw: pointer to the HW structure + * + * Turn off the LEDs. + **/ +static s32 e1000_led_off_pchlan(struct e1000_hw *hw) +{ + u16 data = (u16)hw->mac.ledctl_mode1; + u32 i, led; + + /* + * If no link, then turn LED off by clearing the invert bit + * for each LED that's mode is "link_up" in ledctl_mode1. + */ + if (!(er32(STATUS) & E1000_STATUS_LU)) { + for (i = 0; i < 3; i++) { + led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; + if ((led & E1000_PHY_LED0_MODE_MASK) != + E1000_LEDCTL_MODE_LINK_UP) + continue; + if (led & E1000_PHY_LED0_IVRT) + data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); + else + data |= (E1000_PHY_LED0_IVRT << (i * 5)); + } + } + + return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG, data); +} + /** * e1000_get_cfg_done_ich8lan - Read config done bit * @hw: pointer to the HW structure @@ -2488,7 +2843,7 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) * Read the management control register for the config done bit for * completion status. NOTE: silicon which is EEPROM-less will fail trying * to read the config done bit, so an error is *ONLY* logged and returns - * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon + * 0. If we were to return with error, EEPROM-less silicon * would not be able to be reset or change link. **/ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) @@ -2498,7 +2853,8 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) e1000e_get_cfg_done(hw); /* If EEPROM is not marked present, init the IGP 3 PHY manually */ - if (hw->mac.type != e1000_ich10lan) { + if ((hw->mac.type != e1000_ich10lan) && + (hw->mac.type != e1000_pchlan)) { if (((er32(EECD) & E1000_EECD_PRES) == 0) && (hw->phy.type == e1000_phy_igp_3)) { e1000e_phy_init_script_igp3(hw); @@ -2524,6 +2880,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) { u32 temp; + u16 phy_data; e1000e_clear_hw_cntrs_base(hw); @@ -2541,22 +2898,42 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) temp = er32(IAC); temp = er32(ICRXOC); + /* Clear PHY statistics registers */ + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82577)) { + hw->phy.ops.read_phy_reg(hw, HV_SCC_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_SCC_LOWER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_ECOL_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_ECOL_LOWER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_MCC_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_MCC_LOWER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_LATECOL_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_LATECOL_LOWER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_COLC_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_COLC_LOWER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_DC_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_DC_LOWER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_TNCRS_UPPER, &phy_data); + hw->phy.ops.read_phy_reg(hw, HV_TNCRS_LOWER, &phy_data); + } } static struct e1000_mac_operations ich8_mac_ops = { + .id_led_init = e1000e_id_led_init, .check_mng_mode = e1000_check_mng_mode_ich8lan, .check_for_link = e1000e_check_for_copper_link, - .cleanup_led = e1000_cleanup_led_ich8lan, + /* cleanup_led dependent on mac type */ .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, .get_bus_info = e1000_get_bus_info_ich8lan, .get_link_up_info = e1000_get_link_up_info_ich8lan, - .led_on = e1000_led_on_ich8lan, - .led_off = e1000_led_off_ich8lan, + /* led_on dependent on mac type */ + /* led_off dependent on mac type */ .update_mc_addr_list = e1000e_update_mc_addr_list_generic, .reset_hw = e1000_reset_hw_ich8lan, .init_hw = e1000_init_hw_ich8lan, .setup_link = e1000_setup_link_ich8lan, .setup_physical_interface= e1000_setup_copper_link_ich8lan, + /* id_led_init dependent on mac type */ }; static struct e1000_phy_operations ich8_phy_ops = { @@ -2595,6 +2972,7 @@ struct e1000_info e1000_ich8_info = { | FLAG_HAS_FLASH | FLAG_APME_IN_WUC, .pba = 8, + .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_ich8lan, .mac_ops = &ich8_mac_ops, .phy_ops = &ich8_phy_ops, @@ -2613,6 +2991,7 @@ struct e1000_info e1000_ich9_info = { | FLAG_HAS_FLASH | FLAG_APME_IN_WUC, .pba = 10, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_ich8lan, .mac_ops = &ich8_mac_ops, .phy_ops = &ich8_phy_ops, @@ -2631,6 +3010,25 @@ struct e1000_info e1000_ich10_info = { | FLAG_HAS_FLASH | FLAG_APME_IN_WUC, .pba = 10, + .max_hw_frame_size = DEFAULT_JUMBO, + .get_variants = e1000_get_variants_ich8lan, + .mac_ops = &ich8_mac_ops, + .phy_ops = &ich8_phy_ops, + .nvm_ops = &ich8_nvm_ops, +}; + +struct e1000_info e1000_pch_info = { + .mac = e1000_pchlan, + .flags = FLAG_IS_ICH + | FLAG_HAS_WOL + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_CTRLEXT_ON_LOAD + | FLAG_HAS_AMT + | FLAG_HAS_FLASH + | FLAG_HAS_JUMBO_FRAMES + | FLAG_APME_IN_WUC, + .pba = 26, + .max_hw_frame_size = 4096, .get_variants = e1000_get_variants_ich8lan, .mac_ops = &ich8_mac_ops, .phy_ops = &ich8_phy_ops, diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 18a4f5902f3b..be6d9e990374 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -378,6 +378,12 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) mac->get_link_status = 0; + if (hw->phy.type == e1000_phy_82578) { + ret_val = e1000_link_stall_workaround_hv(hw); + if (ret_val) + return ret_val; + } + /* * Check if there was DownShift, must be checked * immediately after link-up @@ -1405,6 +1411,38 @@ s32 e1000e_id_led_init(struct e1000_hw *hw) return 0; } +/** + * e1000e_setup_led_generic - Configures SW controllable LED + * @hw: pointer to the HW structure + * + * This prepares the SW controllable LED for use and saves the current state + * of the LED so it can be later restored. + **/ +s32 e1000e_setup_led_generic(struct e1000_hw *hw) +{ + u32 ledctl; + + if (hw->mac.ops.setup_led != e1000e_setup_led_generic) { + return -E1000_ERR_CONFIG; + } + + if (hw->phy.media_type == e1000_media_type_fiber) { + ledctl = er32(LEDCTL); + hw->mac.ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | + E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << + E1000_LEDCTL_LED0_MODE_SHIFT); + ew32(LEDCTL, ledctl); + } else if (hw->phy.media_type == e1000_media_type_copper) { + ew32(LEDCTL, hw->mac.ledctl_mode1); + } + + return 0; +} + /** * e1000e_cleanup_led_generic - Set LED config to default operation * @hw: pointer to the HW structure diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ca82f19a7ed1..677f60490f67 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -48,7 +48,7 @@ #include "e1000.h" -#define DRV_VERSION "0.3.3.4-k4" +#define DRV_VERSION "1.0.2-k2" char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; @@ -62,6 +62,7 @@ static const struct e1000_info *e1000_info_tbl[] = { [board_ich8lan] = &e1000_ich8_info, [board_ich9lan] = &e1000_ich9_info, [board_ich10lan] = &e1000_ich10_info, + [board_pchlan] = &e1000_pch_info, }; #ifdef DEBUG @@ -2255,8 +2256,6 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) ew32(TARC(1), tarc); } - e1000e_config_collision_dist(hw); - /* Setup Transmit Descriptor Settings for eop descriptor */ adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; @@ -2269,6 +2268,8 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) ew32(TCTL, tctl); + e1000e_config_collision_dist(hw); + adapter->tx_queue_len = adapter->netdev->tx_queue_len; } @@ -2308,6 +2309,23 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) if (adapter->flags2 & FLAG2_CRC_STRIPPING) rctl |= E1000_RCTL_SECRC; + /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */ + if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { + u16 phy_data; + + e1e_rphy(hw, PHY_REG(770, 26), &phy_data); + phy_data &= 0xfff8; + phy_data |= (1 << 2); + e1e_wphy(hw, PHY_REG(770, 26), phy_data); + + e1e_rphy(hw, 22, &phy_data); + phy_data &= 0x0fff; + phy_data |= (1 << 14); + e1e_wphy(hw, 0x10, 0x2823); + e1e_wphy(hw, 0x11, 0x0003); + e1e_wphy(hw, 22, phy_data); + } + /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -2751,23 +2769,25 @@ void e1000e_reset(struct e1000_adapter *adapter) /* * flow control settings * - * The high water mark must be low enough to fit one full frame + * The high water mark must be low enough to fit two 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 + * - the full Rx FIFO size minus two full frames */ - if (adapter->flags & FLAG_HAS_ERT) + if ((adapter->flags & FLAG_HAS_ERT) && + (adapter->netdev->mtu > ETH_DATA_LEN)) hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - (E1000_ERT_2048 << 3))); else hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - adapter->max_frame_size)); + ((pba << 10) - (2 * adapter->max_frame_size))); - fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */ - fc->low_water = fc->high_water - 8; + fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ + fc->low_water = (fc->high_water - (2 * adapter->max_frame_size)); + fc->low_water &= E1000_FCRTL_RTL; /* 8-byte granularity */ if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) fc->pause_time = 0xFFFF; @@ -2787,6 +2807,8 @@ void e1000e_reset(struct e1000_adapter *adapter) e1000_get_hw_control(adapter); ew32(WUC, 0); + if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) + e1e_wphy(&adapter->hw, BM_WUC, 0); if (mac->ops.init_hw(hw)) e_err("Hardware Error\n"); @@ -2799,7 +2821,8 @@ void e1000e_reset(struct e1000_adapter *adapter) e1000e_reset_adaptive(hw); e1000_get_phy_info(hw); - if (!(adapter->flags & FLAG_SMART_POWER_DOWN)) { + if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && + !(adapter->flags & FLAG_SMART_POWER_DOWN)) { u16 phy_data = 0; /* * speed up time to link by disabling smart power down, ignore @@ -2826,6 +2849,8 @@ int e1000e_up(struct e1000_adapter *adapter) e1000_configure_msix(adapter); e1000_irq_enable(adapter); + netif_wake_queue(adapter->netdev); + /* fire a link change interrupt to start the watchdog */ ew32(ICS, E1000_ICS_LSC); return 0; @@ -2848,7 +2873,7 @@ void e1000e_down(struct e1000_adapter *adapter) ew32(RCTL, rctl & ~E1000_RCTL_EN); /* flush and sleep below */ - netif_tx_stop_all_queues(netdev); + netif_stop_queue(netdev); /* disable transmits in the hardware */ tctl = er32(TCTL); @@ -3072,6 +3097,8 @@ static int e1000_open(struct net_device *netdev) if (test_bit(__E1000_TESTING, &adapter->state)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = e1000e_setup_tx_resources(adapter); if (err) @@ -3128,7 +3155,7 @@ static int e1000_open(struct net_device *netdev) e1000_irq_enable(adapter); - netif_tx_start_all_queues(netdev); + netif_start_queue(netdev); /* fire a link status change interrupt to start the watchdog */ ew32(ICS, E1000_ICS_LSC); @@ -3262,6 +3289,7 @@ void e1000e_update_stats(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; + u16 phy_data; /* * Prevent stats update while adapter is being reset, or if the pci @@ -3281,11 +3309,34 @@ void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.roc += er32(ROC); adapter->stats.mpc += er32(MPC); - adapter->stats.scc += er32(SCC); - adapter->stats.ecol += er32(ECOL); - adapter->stats.mcc += er32(MCC); - adapter->stats.latecol += er32(LATECOL); - adapter->stats.dc += er32(DC); + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82577)) { + e1e_rphy(hw, HV_SCC_UPPER, &phy_data); + e1e_rphy(hw, HV_SCC_LOWER, &phy_data); + adapter->stats.scc += phy_data; + + e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); + e1e_rphy(hw, HV_ECOL_LOWER, &phy_data); + adapter->stats.ecol += phy_data; + + e1e_rphy(hw, HV_MCC_UPPER, &phy_data); + e1e_rphy(hw, HV_MCC_LOWER, &phy_data); + adapter->stats.mcc += phy_data; + + e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); + e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data); + adapter->stats.latecol += phy_data; + + e1e_rphy(hw, HV_DC_UPPER, &phy_data); + e1e_rphy(hw, HV_DC_LOWER, &phy_data); + adapter->stats.dc += phy_data; + } else { + adapter->stats.scc += er32(SCC); + adapter->stats.ecol += er32(ECOL); + adapter->stats.mcc += er32(MCC); + adapter->stats.latecol += er32(LATECOL); + adapter->stats.dc += er32(DC); + } adapter->stats.xonrxc += er32(XONRXC); adapter->stats.xontxc += er32(XONTXC); adapter->stats.xoffrxc += er32(XOFFRXC); @@ -3303,13 +3354,28 @@ void e1000e_update_stats(struct e1000_adapter *adapter) hw->mac.tx_packet_delta = er32(TPT); adapter->stats.tpt += hw->mac.tx_packet_delta; - hw->mac.collision_delta = er32(COLC); + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82577)) { + e1e_rphy(hw, HV_COLC_UPPER, &phy_data); + e1e_rphy(hw, HV_COLC_LOWER, &phy_data); + hw->mac.collision_delta = phy_data; + } else { + hw->mac.collision_delta = er32(COLC); + } adapter->stats.colc += hw->mac.collision_delta; adapter->stats.algnerrc += er32(ALGNERRC); adapter->stats.rxerrc += er32(RXERRC); - if ((hw->mac.type != e1000_82574) && (hw->mac.type != e1000_82583)) - adapter->stats.tncrs += er32(TNCRS); + if ((hw->phy.type == e1000_phy_82578) || + (hw->phy.type == e1000_phy_82577)) { + e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); + e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data); + adapter->stats.tncrs += phy_data; + } else { + if ((hw->mac.type != e1000_82574) && + (hw->mac.type != e1000_82583)) + adapter->stats.tncrs += er32(TNCRS); + } adapter->stats.cexterr += er32(CEXTERR); adapter->stats.tsctc += er32(TSCTC); adapter->stats.tsctfc += er32(TSCTFC); @@ -3598,7 +3664,6 @@ static void e1000_watchdog_task(struct work_struct *work) phy->ops.cfg_on_link_up(hw); netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, @@ -3612,7 +3677,6 @@ static void e1000_watchdog_task(struct work_struct *work) printk(KERN_INFO "e1000e: %s NIC Link is Down\n", adapter->netdev->name); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); @@ -3649,6 +3713,8 @@ static void e1000_watchdog_task(struct work_struct *work) */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } } @@ -3850,7 +3916,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, buffer_info->length = size; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = map[0] + offset; + buffer_info->dma = skb_shinfo(skb)->dma_head + offset; count++; len -= size; @@ -3881,7 +3947,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, buffer_info->length = size; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = map[f + 1] + offset; + buffer_info->dma = map[f] + offset; len -= size; offset += size; @@ -4145,7 +4211,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); if (count) { e1000_tx_queue(adapter, tx_flags, count); - netdev->trans_start = jiffies; /* Make sure there is space in the ring for the next send. */ e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); @@ -4206,27 +4271,17 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) struct e1000_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - e_err("Invalid MTU setting\n"); + /* Jumbo frame support */ + if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && + !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { + e_err("Jumbo Frames not supported.\n"); return -EINVAL; } - /* Jumbo frame size limits */ - if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { - if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - e_err("Jumbo Frames not supported.\n"); - return -EINVAL; - } - if (adapter->hw.phy.type == e1000_phy_ife) { - e_err("Jumbo Frames not supported.\n"); - return -EINVAL; - } - } - -#define MAX_STD_JUMBO_FRAME_SIZE 9234 - if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { - e_err("MTU > 9216 not supported.\n"); + /* Supported frame sizes */ + if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || + (max_frame > adapter->max_hw_frame_size)) { + e_err("Unsupported MTU setting\n"); return -EINVAL; } @@ -4346,6 +4401,81 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } } +static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) +{ + struct e1000_hw *hw = &adapter->hw; + u32 i, mac_reg; + u16 phy_reg; + int retval = 0; + + /* copy MAC RARs to PHY RARs */ + for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) { + mac_reg = er32(RAL(i)); + e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); + e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); + mac_reg = er32(RAH(i)); + e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); + e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF)); + } + + /* copy MAC MTA to PHY MTA */ + for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { + mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); + e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF)); + e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF)); + } + + /* configure PHY Rx Control register */ + e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg); + mac_reg = er32(RCTL); + if (mac_reg & E1000_RCTL_UPE) + phy_reg |= BM_RCTL_UPE; + if (mac_reg & E1000_RCTL_MPE) + phy_reg |= BM_RCTL_MPE; + phy_reg &= ~(BM_RCTL_MO_MASK); + if (mac_reg & E1000_RCTL_MO_3) + phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) + << BM_RCTL_MO_SHIFT); + if (mac_reg & E1000_RCTL_BAM) + phy_reg |= BM_RCTL_BAM; + if (mac_reg & E1000_RCTL_PMCF) + phy_reg |= BM_RCTL_PMCF; + mac_reg = er32(CTRL); + if (mac_reg & E1000_CTRL_RFCE) + phy_reg |= BM_RCTL_RFCE; + e1e_wphy(&adapter->hw, BM_RCTL, phy_reg); + + /* enable PHY wakeup in MAC register */ + ew32(WUFC, wufc); + ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); + + /* configure and enable PHY wakeup in PHY registers */ + e1e_wphy(&adapter->hw, BM_WUFC, wufc); + e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); + + /* activate PHY wakeup */ + retval = hw->phy.ops.acquire_phy(hw); + if (retval) { + e_err("Could not acquire PHY\n"); + return retval; + } + e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); + retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); + if (retval) { + e_err("Could not read PHY page 769\n"); + goto out; + } + phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; + retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + if (retval) + e_err("Could not set PHY Host Wakeup bit\n"); +out: + hw->phy.ops.release_phy(hw); + + return retval; +} + static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -4388,8 +4518,9 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) #define E1000_CTRL_ADVD3WUC 0x00100000 /* phy power management enable */ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 - ctrl |= E1000_CTRL_ADVD3WUC | - E1000_CTRL_EN_PHY_PWR_MGMT; + ctrl |= E1000_CTRL_ADVD3WUC; + if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)) + ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; ew32(CTRL, ctrl); if (adapter->hw.phy.media_type == e1000_media_type_fiber || @@ -4407,8 +4538,17 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) /* Allow time for pending master requests to run */ e1000e_disable_pcie_master(&adapter->hw); - ew32(WUC, E1000_WUC_PME_EN); - ew32(WUFC, wufc); + if ((adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) && + !(hw->mac.ops.check_mng_mode(hw))) { + /* enable wakeup by the PHY */ + retval = e1000_init_phy_wakeup(adapter, wufc); + if (retval) + return retval; + } else { + /* enable wakeup by the MAC */ + ew32(WUFC, wufc); + ew32(WUC, E1000_WUC_PME_EN); + } } else { ew32(WUC, 0); ew32(WUFC, 0); @@ -4551,8 +4691,37 @@ static int e1000_resume(struct pci_dev *pdev) } e1000e_power_up_phy(adapter); + + /* report the system wakeup cause from S3/S4 */ + if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { + u16 phy_data; + + e1e_rphy(&adapter->hw, BM_WUS, &phy_data); + if (phy_data) { + e_info("PHY Wakeup cause - %s\n", + phy_data & E1000_WUS_EX ? "Unicast Packet" : + phy_data & E1000_WUS_MC ? "Multicast Packet" : + phy_data & E1000_WUS_BC ? "Broadcast Packet" : + phy_data & E1000_WUS_MAG ? "Magic Packet" : + phy_data & E1000_WUS_LNKC ? "Link Status " + " Change" : "other"); + } + e1e_wphy(&adapter->hw, BM_WUS, ~0); + } else { + u32 wus = er32(WUS); + if (wus) { + e_info("MAC Wakeup cause - %s\n", + wus & E1000_WUS_EX ? "Unicast Packet" : + wus & E1000_WUS_MC ? "Multicast Packet" : + wus & E1000_WUS_BC ? "Broadcast Packet" : + wus & E1000_WUS_MAG ? "Magic Packet" : + wus & E1000_WUS_LNKC ? "Link Status Change" : + "other"); + } + ew32(WUS, ~0); + } + e1000e_reset(adapter); - ew32(WUS, ~0); e1000_init_manageability(adapter); @@ -4842,6 +5011,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->flags2 = ei->flags2; adapter->hw.adapter = adapter; adapter->hw.mac.type = ei->mac; + adapter->max_hw_frame_size = ei->max_hw_frame_size; adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; mmio_start = pci_resource_start(pdev, 0); @@ -4997,6 +5167,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* APME bit in EEPROM is mapped to WUC.APME */ eeprom_data = er32(WUC); eeprom_apme_mask = E1000_WUC_APME; + if (eeprom_data & E1000_WUC_PHY_WAKE) + adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP; } else if (adapter->flags & FLAG_APME_IN_CTRL3) { if (adapter->flags & FLAG_APME_CHECK_PORT_B && (adapter->hw.bus.func == 1)) @@ -5037,15 +5209,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (!(adapter->flags & FLAG_HAS_AMT)) e1000_get_hw_control(adapter); - /* tell the stack to leave us alone until e1000_open() is called */ - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + e1000_print_device_info(adapter); return 0; @@ -5199,6 +5370,11 @@ static struct pci_device_id e1000_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan }, + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index e909f96698e8..1342e0b1815c 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -427,6 +427,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) e1000_validate_option(&crc_stripping, &opt, adapter); if (crc_stripping == OPTION_ENABLED) adapter->flags2 |= FLAG2_CRC_STRIPPING; + } else { + adapter->flags2 |= FLAG2_CRC_STRIPPING; } } { /* Kumeran Lock Loss Workaround */ diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index dc4a9cba6a73..e23459cf3d0e 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -37,6 +37,9 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw); static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read); +static u32 e1000_get_phy_addr_for_hv_page(u32 page); +static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, + u16 *data, bool read); /* Cable length tables */ static const u16 e1000_m88_cable_length_table[] = @@ -54,6 +57,55 @@ static const u16 e1000_igp_2_cable_length_table[] = #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ ARRAY_SIZE(e1000_igp_2_cable_length_table) +#define BM_PHY_REG_PAGE(offset) \ + ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) +#define BM_PHY_REG_NUM(offset) \ + ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ + (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ + ~MAX_PHY_REG_ADDRESS))) + +#define HV_INTC_FC_PAGE_START 768 +#define I82578_ADDR_REG 29 +#define I82577_ADDR_REG 16 +#define I82577_CFG_REG 22 +#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) +#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ +#define I82577_CTRL_REG 23 +#define I82577_CTRL_DOWNSHIFT_MASK (7 << 10) + +/* 82577 specific PHY registers */ +#define I82577_PHY_CTRL_2 18 +#define I82577_PHY_STATUS_2 26 +#define I82577_PHY_DIAG_STATUS 31 + +/* I82577 PHY Status 2 */ +#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 +#define I82577_PHY_STATUS2_MDIX 0x0800 +#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 +#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 + +/* I82577 PHY Control 2 */ +#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 +#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 + +/* I82577 PHY Diagnostics Status */ +#define I82577_DSTATUS_CABLE_LENGTH 0x03FC +#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 + +/* BM PHY Copper Specific Control 1 */ +#define BM_CS_CTRL1 16 + +/* BM PHY Copper Specific Status */ +#define BM_CS_STATUS 17 +#define BM_CS_STATUS_LINK_UP 0x0400 +#define BM_CS_STATUS_RESOLVED 0x0800 +#define BM_CS_STATUS_SPEED_MASK 0xC000 +#define BM_CS_STATUS_SPEED_1000 0x8000 + +#define HV_MUX_DATA_CTRL PHY_REG(776, 16) +#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 +#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 + /** * e1000e_check_reset_block_generic - Check if PHY reset is blocked * @hw: pointer to the HW structure @@ -82,23 +134,48 @@ s32 e1000e_check_reset_block_generic(struct e1000_hw *hw) s32 e1000e_get_phy_id(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; + s32 ret_val = 0; u16 phy_id; + u16 retry_count = 0; - ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); - if (ret_val) - return ret_val; + if (!(phy->ops.read_phy_reg)) + goto out; - phy->id = (u32)(phy_id << 16); - udelay(20); - ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); - if (ret_val) - return ret_val; + while (retry_count < 2) { + ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); + if (ret_val) + goto out; - phy->id |= (u32)(phy_id & PHY_REVISION_MASK); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + phy->id = (u32)(phy_id << 16); + udelay(20); + ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); + if (ret_val) + goto out; - return 0; + phy->id |= (u32)(phy_id & PHY_REVISION_MASK); + phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); + + if (phy->id != 0 && phy->id != PHY_REVISION_MASK) + goto out; + + /* + * If the PHY ID is still unknown, we may have an 82577i + * without link. We will try again after setting Slow + * MDIC mode. No harm in trying again in this case since + * the PHY ID is unknown at this point anyway + */ + ret_val = e1000_set_mdio_slow_mode_hv(hw, true); + if (ret_val) + goto out; + + retry_count++; + } +out: + /* Revert to MDIO fast mode, if applicable */ + if (retry_count) + ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + + return ret_val; } /** @@ -409,6 +486,43 @@ s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) return ret_val; } +/** + * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link + * @hw: pointer to the HW structure + * + * Sets up Carrier-sense on Transmit and downshift values. + **/ +s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + + /* Enable CRS on TX. This must be set for half-duplex operation. */ + ret_val = phy->ops.read_phy_reg(hw, I82577_CFG_REG, &phy_data); + if (ret_val) + goto out; + + phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; + + /* Enable downshift */ + phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; + + ret_val = phy->ops.write_phy_reg(hw, I82577_CFG_REG, phy_data); + if (ret_val) + goto out; + + /* Set number of link attempts before downshift */ + ret_val = phy->ops.read_phy_reg(hw, I82577_CTRL_REG, &phy_data); + if (ret_val) + goto out; + phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK; + ret_val = phy->ops.write_phy_reg(hw, I82577_CTRL_REG, phy_data); + +out: + return ret_val; +} + /** * e1000e_copper_link_setup_m88 - Setup m88 PHY's for copper link * @hw: pointer to the HW structure @@ -427,8 +541,8 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) if (ret_val) return ret_val; - /* For newer PHYs this bit is downshift enable */ - if (phy->type == e1000_phy_m88) + /* For BM PHY this bit is downshift enable */ + if (phy->type != e1000_phy_bm) phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; /* @@ -520,10 +634,27 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) /* Commit the changes. */ ret_val = e1000e_commit_phy(hw); - if (ret_val) + if (ret_val) { hw_dbg(hw, "Error committing the PHY changes\n"); + return ret_val; + } - return ret_val; + if (phy->type == e1000_phy_82578) { + ret_val = phy->ops.read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* 82578 PHY - set the downshift count to 1x. */ + phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; + phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; + ret_val = phy->ops.write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if (ret_val) + return ret_val; + } + + return 0; } /** @@ -1251,6 +1382,8 @@ s32 e1000e_check_downshift(struct e1000_hw *hw) switch (phy->type) { case e1000_phy_m88: case e1000_phy_gg82563: + case e1000_phy_82578: + case e1000_phy_82577: offset = M88E1000_PHY_SPEC_STATUS; mask = M88E1000_PSSR_DOWNSHIFT; break; @@ -1886,6 +2019,12 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) case BME1000_E_PHY_ID_R2: phy_type = e1000_phy_bm; break; + case I82578_E_PHY_ID: + phy_type = e1000_phy_82578; + break; + case I82577_E_PHY_ID: + phy_type = e1000_phy_82577; + break; default: phy_type = e1000_phy_unknown; break; @@ -2181,11 +2320,16 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read) { s32 ret_val; - u16 reg = ((u16)offset) & PHY_REG_MASK; + u16 reg = BM_PHY_REG_NUM(offset); u16 phy_reg = 0; u8 phy_acquired = 1; + /* Gig must be disabled for MDIO accesses to page 800 */ + if ((hw->mac.type == e1000_pchlan) && + (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) + hw_dbg(hw, "Attempting to access page 800 while gig enabled\n"); + ret_val = hw->phy.ops.acquire_phy(hw); if (ret_val) { phy_acquired = 0; @@ -2289,3 +2433,524 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) return 0; } + +s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) +{ + s32 ret_val = 0; + u16 data = 0; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + + /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ + hw->phy.addr = 1; + ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); + if (ret_val) { + hw->phy.ops.release_phy(hw); + return ret_val; + } + ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, + (0x2180 | (slow << 10))); + + /* dummy read when reverting to fast mode - throw away result */ + if (!slow) + e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); + + hw->phy.ops.release_phy(hw); + + return ret_val; +} + +/** + * e1000_read_phy_reg_hv - Read HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retrieved information in data. Release any acquired + * semaphore before exiting. + **/ +s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) +{ + s32 ret_val; + u16 page = BM_PHY_REG_PAGE(offset); + u16 reg = BM_PHY_REG_NUM(offset); + bool in_slow_mode = false; + + /* Workaround failure in MDIO access while cable is disconnected */ + if ((hw->phy.type == e1000_phy_82577) && + !(er32(STATUS) & E1000_STATUS_LU)) { + ret_val = e1000_set_mdio_slow_mode_hv(hw, true); + if (ret_val) + goto out; + + in_slow_mode = true; + } + + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, + data, true); + goto out; + } + + if (page > 0 && page < HV_INTC_FC_PAGE_START) { + ret_val = e1000_access_phy_debug_regs_hv(hw, offset, + data, true); + goto out; + } + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + + hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); + + if (page == HV_INTC_FC_PAGE_START) + page = 0; + + if (reg > MAX_PHY_MULTI_PAGE_REG) { + if ((hw->phy.type != e1000_phy_82578) || + ((reg != I82578_ADDR_REG) && + (reg != I82578_ADDR_REG + 1))) { + u32 phy_addr = hw->phy.addr; + + hw->phy.addr = 1; + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (page << IGP_PAGE_SHIFT)); + if (ret_val) { + hw->phy.ops.release_phy(hw); + goto out; + } + hw->phy.addr = phy_addr; + } + } + + ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, + data); + hw->phy.ops.release_phy(hw); + +out: + /* Revert to MDIO fast mode, if applicable */ + if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) + ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + + return ret_val; +} + +/** + * e1000_write_phy_reg_hv - Write HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ +s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) +{ + s32 ret_val; + u16 page = BM_PHY_REG_PAGE(offset); + u16 reg = BM_PHY_REG_NUM(offset); + bool in_slow_mode = false; + + /* Workaround failure in MDIO access while cable is disconnected */ + if ((hw->phy.type == e1000_phy_82577) && + !(er32(STATUS) & E1000_STATUS_LU)) { + ret_val = e1000_set_mdio_slow_mode_hv(hw, true); + if (ret_val) + goto out; + + in_slow_mode = true; + } + + /* Page 800 works differently than the rest so it has its own func */ + if (page == BM_WUC_PAGE) { + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, + &data, false); + goto out; + } + + if (page > 0 && page < HV_INTC_FC_PAGE_START) { + ret_val = e1000_access_phy_debug_regs_hv(hw, offset, + &data, false); + goto out; + } + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + + hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); + + if (page == HV_INTC_FC_PAGE_START) + page = 0; + + /* + * Workaround MDIO accesses being disabled after entering IEEE Power + * Down (whenever bit 11 of the PHY Control register is set) + */ + if ((hw->phy.type == e1000_phy_82578) && + (hw->phy.revision >= 1) && + (hw->phy.addr == 2) && + ((MAX_PHY_REG_ADDRESS & reg) == 0) && + (data & (1 << 11))) { + u16 data2 = 0x7EFF; + hw->phy.ops.release_phy(hw); + ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, + &data2, false); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + } + + if (reg > MAX_PHY_MULTI_PAGE_REG) { + if ((hw->phy.type != e1000_phy_82578) || + ((reg != I82578_ADDR_REG) && + (reg != I82578_ADDR_REG + 1))) { + u32 phy_addr = hw->phy.addr; + + hw->phy.addr = 1; + + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000e_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, + (page << IGP_PAGE_SHIFT)); + if (ret_val) { + hw->phy.ops.release_phy(hw); + goto out; + } + hw->phy.addr = phy_addr; + } + } + + ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, + data); + hw->phy.ops.release_phy(hw); + +out: + /* Revert to MDIO fast mode, if applicable */ + if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) + ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + + return ret_val; +} + +/** + * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page + * @page: page to be accessed + **/ +static u32 e1000_get_phy_addr_for_hv_page(u32 page) +{ + u32 phy_addr = 2; + + if (page >= HV_INTC_FC_PAGE_START) + phy_addr = 1; + + return phy_addr; +} + +/** + * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers + * @hw: pointer to the HW structure + * @offset: register offset to be read or written + * @data: pointer to the data to be read or written + * @read: determines if operation is read or written + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and storing the retreived information in data. Release any acquired + * semaphores before exiting. Note that the procedure to read these regs + * uses the address port and data port to read/write. + **/ +static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, + u16 *data, bool read) +{ + s32 ret_val; + u32 addr_reg = 0; + u32 data_reg = 0; + u8 phy_acquired = 1; + + /* This takes care of the difference with desktop vs mobile phy */ + addr_reg = (hw->phy.type == e1000_phy_82578) ? + I82578_ADDR_REG : I82577_ADDR_REG; + data_reg = addr_reg + 1; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) { + hw_dbg(hw, "Could not acquire PHY\n"); + phy_acquired = 0; + goto out; + } + + /* All operations in this function are phy address 2 */ + hw->phy.addr = 2; + + /* masking with 0x3F to remove the page from offset */ + ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); + if (ret_val) { + hw_dbg(hw, "Could not write PHY the HV address register\n"); + goto out; + } + + /* Read or write the data value next */ + if (read) + ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data); + else + ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); + + if (ret_val) { + hw_dbg(hw, "Could not read data value from HV data register\n"); + goto out; + } + +out: + if (phy_acquired == 1) + hw->phy.ops.release_phy(hw); + return ret_val; +} + +/** + * e1000_link_stall_workaround_hv - Si workaround + * @hw: pointer to the HW structure + * + * This function works around a Si bug where the link partner can get + * a link up indication before the PHY does. If small packets are sent + * by the link partner they can be placed in the packet buffer without + * being properly accounted for by the PHY and will stall preventing + * further packets from being received. The workaround is to clear the + * packet buffer after the PHY detects link up. + **/ +s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 data; + + if (hw->phy.type != e1000_phy_82578) + goto out; + + /* check if link is up and at 1Gbps */ + ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data); + if (ret_val) + goto out; + + data &= BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_MASK; + + if (data != (BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_1000)) + goto out; + + mdelay(200); + + /* flush the packets in the fifo buffer */ + ret_val = hw->phy.ops.write_phy_reg(hw, HV_MUX_DATA_CTRL, + HV_MUX_DATA_CTRL_GEN_TO_MAC | + HV_MUX_DATA_CTRL_FORCE_SPEED); + if (ret_val) + goto out; + + ret_val = hw->phy.ops.write_phy_reg(hw, HV_MUX_DATA_CTRL, + HV_MUX_DATA_CTRL_GEN_TO_MAC); + +out: + return ret_val; +} + +/** + * e1000_check_polarity_82577 - Checks the polarity. + * @hw: pointer to the HW structure + * + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) + * + * Polarity is determined based on the PHY specific status register. + **/ +s32 e1000_check_polarity_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + + ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_STATUS_2, &data); + + if (!ret_val) + phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + + return ret_val; +} + +/** + * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY + * @hw: pointer to the HW structure + * + * Calls the PHY setup function to force speed and duplex. Clears the + * auto-crossover to force MDI manually. Waits for link and returns + * successful if link up is successful, else -E1000_ERR_PHY (-2). + **/ +s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + bool link; + + ret_val = phy->ops.read_phy_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + + e1000e_phy_force_speed_duplex_setup(hw, &phy_data); + + ret_val = phy->ops.write_phy_reg(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + + /* + * Clear Auto-Crossover to force MDI manually. 82577 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_CTRL_2, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX; + phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX; + + ret_val = phy->ops.write_phy_reg(hw, I82577_PHY_CTRL_2, phy_data); + if (ret_val) + goto out; + + hw_dbg(hw, "I82577_PHY_CTRL_2: %X\n", phy_data); + + udelay(1); + + if (phy->autoneg_wait_to_complete) { + hw_dbg(hw, "Waiting for forced speed/duplex link on 82577 phy\n"); + + ret_val = e1000e_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + + if (!link) + hw_dbg(hw, "Link taking longer than expected.\n"); + + /* Try once more */ + ret_val = e1000e_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + } + +out: + return ret_val; +} + +/** + * e1000_get_phy_info_82577 - Retrieve I82577 PHY information + * @hw: pointer to the HW structure + * + * Read PHY status to determine if link is up. If link is up, then + * set/determine 10base-T extended distance and polarity correction. Read + * PHY port status to determine MDI/MDIx and speed. Based on the speed, + * determine on the cable length, local and remote receiver. + **/ +s32 e1000_get_phy_info_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) { + hw_dbg(hw, "Phy info is only valid if link is up\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + phy->polarity_correction = true; + + ret_val = e1000_check_polarity_82577(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_STATUS_2, &data); + if (ret_val) + goto out; + + phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false; + + if ((data & I82577_PHY_STATUS2_SPEED_MASK) == + I82577_PHY_STATUS2_SPEED_1000MBPS) { + ret_val = hw->phy.ops.get_cable_length(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_phy_reg(hw, PHY_1000T_STATUS, &data); + if (ret_val) + goto out; + + phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + + phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + } else { + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + } + +out: + return ret_val; +} + +/** + * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY + * @hw: pointer to the HW structure + * + * Reads the diagnostic status register and verifies result is valid before + * placing it in the phy_cable_length field. + **/ +s32 e1000_get_cable_length_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data, length; + + ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data); + if (ret_val) + goto out; + + length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >> + I82577_DSTATUS_CABLE_LENGTH_SHIFT; + + if (length == E1000_CABLE_LENGTH_UNDEFINED) + ret_val = E1000_ERR_PHY; + + phy->cable_length = length; + +out: + return ret_val; +} diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index b22dab9153f6..147c4b088fb3 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3261,7 +3261,7 @@ static ssize_t ehea_probe_port(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ehea_adapter *adapter = dev->driver_data; + struct ehea_adapter *adapter = dev_get_drvdata(dev); struct ehea_port *port; struct device_node *eth_dn = NULL; int i; @@ -3316,7 +3316,7 @@ static ssize_t ehea_remove_port(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ehea_adapter *adapter = dev->driver_data; + struct ehea_adapter *adapter = dev_get_drvdata(dev); struct ehea_port *port; int i; u32 logical_port_id; @@ -3404,7 +3404,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, adapter->pd = EHEA_PD_ID; - dev->dev.driver_data = adapter; + dev_set_drvdata(&dev->dev, adapter); /* initialize adapter and ports */ @@ -3468,7 +3468,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, static int __devexit ehea_remove(struct of_device *dev) { - struct ehea_adapter *adapter = dev->dev.driver_data; + struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); int i; for (i = 0; i < EHEA_MAX_PORTS; i++) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 9080f07da8fe..8005b602f776 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -661,8 +661,6 @@ static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + 1) netif_stop_queue(netdev); - netdev->trans_start = jiffies; - spin_unlock_irqrestore(&enic->wq_lock[0], flags); return NETDEV_TX_OK; diff --git a/drivers/net/eql.c b/drivers/net/eql.c index 5210bb1027cc..19b7dd983944 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -194,6 +194,7 @@ static void __init eql_setup(struct net_device *dev) dev->type = ARPHRD_SLIP; dev->tx_queue_len = 5; /* Hands them off fast */ + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } static int eql_open(struct net_device *dev) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 91a9b1a33764..ceb6a9c357ad 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -811,7 +811,7 @@ static int ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb->len > ETHOC_BUFSIZ)) { priv->stats.tx_errors++; - return -EMSGSIZE; + goto out; } entry = priv->cur_tx % priv->num_tx; @@ -840,9 +840,9 @@ static int ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) } dev->trans_start = jiffies; - dev_kfree_skb(skb); - spin_unlock_irq(&priv->lock); +out: + dev_kfree_skb(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 1a685a04d4b2..1e9723281405 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -873,7 +873,7 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev) err_out: ENABLE_IRQs; spin_unlock_irq (&lp->hw_lock); - return 1; + return NETDEV_TX_BUSY; } /* diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 682e7f0b5581..0f19b743749b 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -86,8 +86,7 @@ static unsigned char fec_mac_default[] = { #endif #endif /* CONFIG_M5272 */ -/* Forward declarations of some structures to support different PHYs -*/ +/* Forward declarations of some structures to support different PHYs */ typedef struct { uint mii_data; @@ -123,8 +122,7 @@ typedef struct { #error "FEC: descriptor ring size constants too large" #endif -/* Interrupt events/masks. -*/ +/* Interrupt events/masks. */ #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ #define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ #define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ @@ -165,7 +163,7 @@ typedef struct { */ struct fec_enet_private { /* Hardware registers of the FEC device */ - volatile fec_t *hwp; + void __iomem *hwp; struct net_device *netdev; @@ -174,16 +172,20 @@ struct fec_enet_private { /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; + struct sk_buff* rx_skbuff[RX_RING_SIZE]; ushort skb_cur; ushort skb_dirty; - /* CPM dual port RAM relative addresses. - */ + /* CPM dual port RAM relative addresses */ dma_addr_t bd_dma; - cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ - cbd_t *tx_bd_base; - cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ - cbd_t *dirty_tx; /* The ring entries to be free()ed. */ + /* Address of Rx and Tx buffers */ + struct bufdesc *rx_bd_base; + struct bufdesc *tx_bd_base; + /* The next free ring entry */ + struct bufdesc *cur_rx, *cur_tx; + /* The ring entries to be free()ed */ + struct bufdesc *dirty_tx; + uint tx_full; /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ spinlock_t hw_lock; @@ -209,17 +211,13 @@ struct fec_enet_private { int full_duplex; }; -static int fec_enet_open(struct net_device *dev); -static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); static void fec_enet_mii(struct net_device *dev); static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); static void fec_enet_tx(struct net_device *dev); static void fec_enet_rx(struct net_device *dev); static int fec_enet_close(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); static void fec_restart(struct net_device *dev, int duplex); static void fec_stop(struct net_device *dev); -static void fec_set_mac_address(struct net_device *dev); /* MII processing. We keep this as simple as possible. Requests are @@ -241,19 +239,16 @@ static mii_list_t *mii_tail; static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *)); -/* Make MII read/write commands for the FEC. -*/ +/* Make MII read/write commands for the FEC */ #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ (VAL & 0xffff)) #define mk_mii_end 0 -/* Transmitter timeout. -*/ -#define TX_TIMEOUT (2*HZ) +/* Transmitter timeout */ +#define TX_TIMEOUT (2 * HZ) -/* Register definitions for the PHY. -*/ +/* Register definitions for the PHY */ #define MII_REG_CR 0 /* Control Register */ #define MII_REG_SR 1 /* Status Register */ @@ -288,18 +283,14 @@ static int mii_queue(struct net_device *dev, int request, static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct fec_enet_private *fep; - volatile fec_t *fecp; - volatile cbd_t *bdp; + struct fec_enet_private *fep = netdev_priv(dev); + struct bufdesc *bdp; unsigned short status; unsigned long flags; - fep = netdev_priv(dev); - fecp = (volatile fec_t*)dev->base_addr; - if (!fep->link) { /* Link is down or autonegotiation is in progress. */ - return 1; + return NETDEV_TX_BUSY; } spin_lock_irqsave(&fep->hw_lock, flags); @@ -307,30 +298,27 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) bdp = fep->cur_tx; status = bdp->cbd_sc; -#ifndef final_version + if (status & BD_ENET_TX_READY) { /* Ooops. All transmit buffers are full. Bail out. * This should not happen, since dev->tbusy should be set. */ printk("%s: tx queue full!.\n", dev->name); spin_unlock_irqrestore(&fep->hw_lock, flags); - return 1; + return NETDEV_TX_BUSY; } -#endif - /* Clear all of the status flags. - */ + /* Clear all of the status flags */ status &= ~BD_ENET_TX_STATS; - /* Set buffer length and buffer pointer. - */ + /* Set buffer length and buffer pointer */ bdp->cbd_bufaddr = __pa(skb->data); bdp->cbd_datlen = skb->len; /* - * On some FEC implementations data must be aligned on - * 4-byte boundaries. Use bounce buffers to copy data - * and get it aligned. Ugh. + * On some FEC implementations data must be aligned on + * 4-byte boundaries. Use bounce buffers to copy data + * and get it aligned. Ugh. */ if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { unsigned int index; @@ -339,8 +327,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } - /* Save skb pointer. - */ + /* Save skb pointer */ fep->tx_skbuff[fep->skb_cur] = skb; dev->stats.tx_bytes += skb->len; @@ -349,13 +336,12 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Push the data cache so the CPM does not get stale memory * data. */ - dma_sync_single(NULL, bdp->cbd_bufaddr, - bdp->cbd_datlen, DMA_TO_DEVICE); + bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, + FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ - status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; @@ -363,22 +349,20 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; /* Trigger transmission start */ - fecp->fec_x_des_active = 0; + writel(0, fep->hwp + FEC_X_DES_ACTIVE); - /* If this was the last BD in the ring, start at the beginning again. - */ - if (status & BD_ENET_TX_WRAP) { + /* If this was the last BD in the ring, start at the beginning again. */ + if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; - } else { + else bdp++; - } if (bdp == fep->dirty_tx) { fep->tx_full = 1; netif_stop_queue(dev); } - fep->cur_tx = (cbd_t *)bdp; + fep->cur_tx = bdp; spin_unlock_irqrestore(&fep->hw_lock, flags); @@ -390,75 +374,33 @@ fec_timeout(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - printk("%s: transmit timed out.\n", dev->name); dev->stats.tx_errors++; -#ifndef final_version - { - int i; - cbd_t *bdp; - printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", - (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", - (unsigned long)fep->dirty_tx, - (unsigned long)fep->cur_rx); - - bdp = fep->tx_bd_base; - printk(" tx: %u buffers\n", TX_RING_SIZE); - for (i = 0 ; i < TX_RING_SIZE; i++) { - printk(" %08x: %04x %04x %08x\n", - (uint) bdp, - bdp->cbd_sc, - bdp->cbd_datlen, - (int) bdp->cbd_bufaddr); - bdp++; - } - - bdp = fep->rx_bd_base; - printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE); - for (i = 0 ; i < RX_RING_SIZE; i++) { - printk(" %08x: %04x %04x %08x\n", - (uint) bdp, - bdp->cbd_sc, - bdp->cbd_datlen, - (int) bdp->cbd_bufaddr); - bdp++; - } - } -#endif fec_restart(dev, fep->full_duplex); netif_wake_queue(dev); } -/* The interrupt handler. - * This is called from the MPC core interrupt. - */ static irqreturn_t fec_enet_interrupt(int irq, void * dev_id) { struct net_device *dev = dev_id; - volatile fec_t *fecp; + struct fec_enet_private *fep = netdev_priv(dev); uint int_events; irqreturn_t ret = IRQ_NONE; - fecp = (volatile fec_t*)dev->base_addr; - - /* Get the interrupt events that caused us to be here. - */ do { - int_events = fecp->fec_ievent; - fecp->fec_ievent = int_events; + int_events = readl(fep->hwp + FEC_IEVENT); + writel(int_events, fep->hwp + FEC_IEVENT); - /* Handle receive event in its own function. - */ if (int_events & FEC_ENET_RXF) { ret = IRQ_HANDLED; fec_enet_rx(dev); } /* Transmit OK, or non-fatal error. Update the buffer - descriptors. FEC handles all errors, we just discover - them as part of the transmit process. - */ + * descriptors. FEC handles all errors, we just discover + * them as part of the transmit process. + */ if (int_events & FEC_ENET_TXF) { ret = IRQ_HANDLED; fec_enet_tx(dev); @@ -479,7 +421,7 @@ static void fec_enet_tx(struct net_device *dev) { struct fec_enet_private *fep; - volatile cbd_t *bdp; + struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; @@ -488,7 +430,11 @@ fec_enet_tx(struct net_device *dev) bdp = fep->dirty_tx; while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { - if (bdp == fep->cur_tx && fep->tx_full == 0) break; + if (bdp == fep->cur_tx && fep->tx_full == 0) + break; + + dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); + bdp->cbd_bufaddr = 0; skb = fep->tx_skbuff[fep->skb_dirty]; /* Check for errors. */ @@ -510,31 +456,27 @@ fec_enet_tx(struct net_device *dev) dev->stats.tx_packets++; } -#ifndef final_version if (status & BD_ENET_TX_READY) printk("HEY! Enet xmit interrupt and TX_READY.\n"); -#endif + /* Deferred means some collisions occurred during transmit, * but we eventually sent the packet OK. */ if (status & BD_ENET_TX_DEF) dev->stats.collisions++; - /* Free the sk buffer associated with this last transmit. - */ + /* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any(skb); fep->tx_skbuff[fep->skb_dirty] = NULL; fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; - /* Update pointer to next buffer descriptor to be transmitted. - */ + /* Update pointer to next buffer descriptor to be transmitted */ if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; else bdp++; - /* Since we have freed up a buffer, the ring is no longer - * full. + /* Since we have freed up a buffer, the ring is no longer full */ if (fep->tx_full) { fep->tx_full = 0; @@ -542,7 +484,7 @@ fec_enet_tx(struct net_device *dev) netif_wake_queue(dev); } } - fep->dirty_tx = (cbd_t *)bdp; + fep->dirty_tx = bdp; spin_unlock_irq(&fep->hw_lock); } @@ -555,9 +497,8 @@ fec_enet_tx(struct net_device *dev) static void fec_enet_rx(struct net_device *dev) { - struct fec_enet_private *fep; - volatile fec_t *fecp; - volatile cbd_t *bdp; + struct fec_enet_private *fep = netdev_priv(dev); + struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; ushort pkt_len; @@ -567,9 +508,6 @@ fec_enet_rx(struct net_device *dev) flush_cache_all(); #endif - fep = netdev_priv(dev); - fecp = (volatile fec_t*)dev->base_addr; - spin_lock_irq(&fep->hw_lock); /* First, grab all of the stats for the incoming packet. @@ -577,143 +515,121 @@ fec_enet_rx(struct net_device *dev) */ bdp = fep->cur_rx; -while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { + while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { -#ifndef final_version - /* Since we have allocated space to hold a complete frame, - * the last indicator should be set. - */ - if ((status & BD_ENET_RX_LAST) == 0) - printk("FEC ENET: rcv is not +last\n"); -#endif + /* Since we have allocated space to hold a complete frame, + * the last indicator should be set. + */ + if ((status & BD_ENET_RX_LAST) == 0) + printk("FEC ENET: rcv is not +last\n"); - if (!fep->opened) - goto rx_processing_done; + if (!fep->opened) + goto rx_processing_done; - /* Check for errors. */ - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | + /* Check for errors. */ + if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) { - dev->stats.rx_errors++; - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { - /* Frame too long or too short. */ - dev->stats.rx_length_errors++; + dev->stats.rx_errors++; + if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { + /* Frame too long or too short. */ + dev->stats.rx_length_errors++; + } + if (status & BD_ENET_RX_NO) /* Frame alignment */ + dev->stats.rx_frame_errors++; + if (status & BD_ENET_RX_CR) /* CRC Error */ + dev->stats.rx_crc_errors++; + if (status & BD_ENET_RX_OV) /* FIFO overrun */ + dev->stats.rx_fifo_errors++; } - if (status & BD_ENET_RX_NO) /* Frame alignment */ + + /* Report late collisions as a frame error. + * On this error, the BD is closed, but we don't know what we + * have in the buffer. So, just drop this frame on the floor. + */ + if (status & BD_ENET_RX_CL) { + dev->stats.rx_errors++; dev->stats.rx_frame_errors++; - if (status & BD_ENET_RX_CR) /* CRC Error */ - dev->stats.rx_crc_errors++; - if (status & BD_ENET_RX_OV) /* FIFO overrun */ - dev->stats.rx_fifo_errors++; + goto rx_processing_done; + } + + /* Process the incoming frame. */ + dev->stats.rx_packets++; + pkt_len = bdp->cbd_datlen; + dev->stats.rx_bytes += pkt_len; + data = (__u8*)__va(bdp->cbd_bufaddr); + + dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, + DMA_FROM_DEVICE); + + /* This does 16 byte alignment, exactly what we need. + * The packet length includes FCS, but we don't want to + * include that when passing upstream as it messes up + * bridging applications. + */ + skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN); + + if (unlikely(!skb)) { + printk("%s: Memory squeeze, dropping packet.\n", + dev->name); + dev->stats.rx_dropped++; + } else { + skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, pkt_len - 4); /* Make room */ + skb_copy_to_linear_data(skb, data, pkt_len - 4); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + } + + bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen, + DMA_FROM_DEVICE); +rx_processing_done: + /* Clear the status flags for this buffer */ + status &= ~BD_ENET_RX_STATS; + + /* Mark the buffer empty */ + status |= BD_ENET_RX_EMPTY; + bdp->cbd_sc = status; + + /* Update BD pointer to next entry */ + if (status & BD_ENET_RX_WRAP) + bdp = fep->rx_bd_base; + else + bdp++; + /* Doing this here will keep the FEC running while we process + * incoming frames. On a heavily loaded network, we should be + * able to keep up at the expense of system resources. + */ + writel(0, fep->hwp + FEC_R_DES_ACTIVE); } - - /* Report late collisions as a frame error. - * On this error, the BD is closed, but we don't know what we - * have in the buffer. So, just drop this frame on the floor. - */ - if (status & BD_ENET_RX_CL) { - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; - goto rx_processing_done; - } - - /* Process the incoming frame. - */ - dev->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; - dev->stats.rx_bytes += pkt_len; - data = (__u8*)__va(bdp->cbd_bufaddr); - - dma_sync_single(NULL, (unsigned long)__pa(data), - pkt_len - 4, DMA_FROM_DEVICE); - - /* This does 16 byte alignment, exactly what we need. - * The packet length includes FCS, but we don't want to - * include that when passing upstream as it messes up - * bridging applications. - */ - skb = dev_alloc_skb(pkt_len-4); - - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - dev->stats.rx_dropped++; - } else { - skb_put(skb,pkt_len-4); /* Make room */ - skb_copy_to_linear_data(skb, data, pkt_len-4); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - } - rx_processing_done: - - /* Clear the status flags for this buffer. - */ - status &= ~BD_ENET_RX_STATS; - - /* Mark the buffer empty. - */ - status |= BD_ENET_RX_EMPTY; - bdp->cbd_sc = status; - - /* Update BD pointer to next entry. - */ - if (status & BD_ENET_RX_WRAP) - bdp = fep->rx_bd_base; - else - bdp++; - -#if 1 - /* Doing this here will keep the FEC running while we process - * incoming frames. On a heavily loaded network, we should be - * able to keep up at the expense of system resources. - */ - fecp->fec_r_des_active = 0; -#endif - } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */ - fep->cur_rx = (cbd_t *)bdp; - -#if 0 - /* Doing this here will allow us to process all frames in the - * ring before the FEC is allowed to put more there. On a heavily - * loaded network, some frames may be lost. Unfortunately, this - * increases the interrupt overhead since we can potentially work - * our way back to the interrupt return only to come right back - * here. - */ - fecp->fec_r_des_active = 0; -#endif + fep->cur_rx = bdp; spin_unlock_irq(&fep->hw_lock); } - /* called from interrupt context */ static void fec_enet_mii(struct net_device *dev) { struct fec_enet_private *fep; - volatile fec_t *ep; mii_list_t *mip; - uint mii_reg; fep = netdev_priv(dev); spin_lock_irq(&fep->mii_lock); - ep = fep->hwp; - mii_reg = ep->fec_mii_data; - if ((mip = mii_head) == NULL) { printk("MII and no head!\n"); goto unlock; } if (mip->mii_func != NULL) - (*(mip->mii_func))(mii_reg, dev); + (*(mip->mii_func))(readl(fep->hwp + FEC_MII_DATA), dev); mii_head = mip->mii_next; mip->mii_next = mii_free; mii_free = mip; if ((mip = mii_head) != NULL) - ep->fec_mii_data = mip->mii_regval; + writel(mip->mii_regval, fep->hwp + FEC_MII_DATA); unlock: spin_unlock_irq(&fep->mii_lock); @@ -727,8 +643,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi mii_list_t *mip; int retval; - /* Add PHY address to register command. - */ + /* Add PHY address to register command */ fep = netdev_priv(dev); spin_lock_irqsave(&fep->mii_lock, flags); @@ -745,7 +660,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi mii_tail = mip; } else { mii_head = mii_tail = mip; - fep->hwp->fec_mii_data = regval; + writel(regval, fep->hwp + FEC_MII_DATA); } } else { retval = 1; @@ -1246,11 +1161,8 @@ static void __inline__ fec_phy_ack_intr(void) static void __inline__ fec_get_mac(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - volatile fec_t *fecp; unsigned char *iap, tmpaddr[ETH_ALEN]; - fecp = fep->hwp; - if (FEC_FLASHMAC) { /* * Get MAC address from FLASH. @@ -1264,8 +1176,8 @@ static void __inline__ fec_get_mac(struct net_device *dev) (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) iap = fec_mac_default; } else { - *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; - *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); + *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW); + *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16); iap = &tmpaddr[0]; } @@ -1375,11 +1287,6 @@ static void mii_relink(struct work_struct *work) fec_restart(dev, duplex); } else fec_stop(dev); - -#if 0 - enable_irq(fep->mii_irq); -#endif - } /* mii_queue_relink is called in interrupt context from mii_link_interrupt */ @@ -1388,12 +1295,12 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) struct fec_enet_private *fep = netdev_priv(dev); /* - ** We cannot queue phy_task twice in the workqueue. It - ** would cause an endless loop in the workqueue. - ** Fortunately, if the last mii_relink entry has not yet been - ** executed now, it will do the job for the current interrupt, - ** which is just what we want. - */ + * We cannot queue phy_task twice in the workqueue. It + * would cause an endless loop in the workqueue. + * Fortunately, if the last mii_relink entry has not yet been + * executed now, it will do the job for the current interrupt, + * which is just what we want. + */ if (fep->mii_phy_task_queued) return; @@ -1424,8 +1331,7 @@ phy_cmd_t const phy_cmd_config[] = { { mk_mii_end, } }; -/* Read remainder of PHY ID. -*/ +/* Read remainder of PHY ID. */ static void mii_discover_phy3(uint mii_reg, struct net_device *dev) { @@ -1457,17 +1363,14 @@ static void mii_discover_phy(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep; - volatile fec_t *fecp; uint phytype; fep = netdev_priv(dev); - fecp = fep->hwp; if (fep->phy_addr < 32) { if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) { - /* Got first part of ID, now get remainder. - */ + /* Got first part of ID, now get remainder */ fep->phy_id = phytype << 16; mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3); @@ -1479,15 +1382,15 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) } else { printk("FEC: No PHY device found.\n"); /* Disable external MII interface */ - fecp->fec_mii_speed = fep->phy_speed = 0; + writel(0, fep->hwp + FEC_MII_SPEED); + fep->phy_speed = 0; #ifdef HAVE_mii_link_interrupt fec_disable_phy_intr(); #endif } } -/* This interrupt occurs when the PHY detects a link change. -*/ +/* This interrupt occurs when the PHY detects a link change */ #ifdef HAVE_mii_link_interrupt static irqreturn_t mii_link_interrupt(int irq, void * dev_id) @@ -1497,10 +1400,6 @@ mii_link_interrupt(int irq, void * dev_id) fec_phy_ack_intr(); -#if 0 - disable_irq(fep->mii_irq); /* disable now, enable later */ -#endif - mii_do_cmd(dev, fep->phy->ack_int); mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ @@ -1508,19 +1407,91 @@ mii_link_interrupt(int irq, void * dev_id) } #endif +static void fec_enet_free_buffers(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + int i; + struct sk_buff *skb; + struct bufdesc *bdp; + + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + skb = fep->rx_skbuff[i]; + + if (bdp->cbd_bufaddr) + dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); + if (skb) + dev_kfree_skb(skb); + bdp++; + } + + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) + kfree(fep->tx_bounce[i]); +} + +static int fec_enet_alloc_buffers(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + int i; + struct sk_buff *skb; + struct bufdesc *bdp; + + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE); + if (!skb) { + fec_enet_free_buffers(dev); + return -ENOMEM; + } + fep->rx_skbuff[i] = skb; + + bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, + FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); + bdp->cbd_sc = BD_ENET_RX_EMPTY; + bdp++; + } + + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) { + fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); + + bdp->cbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; + } + + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + return 0; +} + static int fec_enet_open(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); + int ret; /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ - fec_set_mac_address(dev); + + ret = fec_enet_alloc_buffers(dev); + if (ret) + return ret; fep->sequence_done = 0; fep->link = 0; + fec_restart(dev, 1); + if (fep->phy) { mii_do_cmd(dev, fep->phy->ack_int); mii_do_cmd(dev, fep->phy->config); @@ -1537,21 +1508,17 @@ fec_enet_open(struct net_device *dev) schedule(); mii_do_cmd(dev, fep->phy->startup); - - /* Set the initial link state to true. A lot of hardware - * based on this device does not implement a PHY interrupt, - * so we are never notified of link change. - */ - fep->link = 1; - } else { - fep->link = 1; /* lets just try it and see */ - /* no phy, go full duplex, it's most likely a hub chip */ - fec_restart(dev, 1); } + /* Set the initial link state to true. A lot of hardware + * based on this device does not implement a PHY interrupt, + * so we are never notified of link change. + */ + fep->link = 1; + netif_start_queue(dev); fep->opened = 1; - return 0; /* Success */ + return 0; } static int @@ -1559,12 +1526,13 @@ fec_enet_close(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - /* Don't know what to do yet. - */ + /* Don't know what to do yet. */ fep->opened = 0; netif_stop_queue(dev); fec_stop(dev); + fec_enet_free_buffers(dev); + return 0; } @@ -1583,87 +1551,102 @@ fec_enet_close(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct fec_enet_private *fep; - volatile fec_t *ep; + struct fec_enet_private *fep = netdev_priv(dev); struct dev_mc_list *dmi; - unsigned int i, j, bit, data, crc; + unsigned int i, j, bit, data, crc, tmp; unsigned char hash; - fep = netdev_priv(dev); - ep = fep->hwp; + if (dev->flags & IFF_PROMISC) { + tmp = readl(fep->hwp + FEC_R_CNTRL); + tmp |= 0x8; + writel(tmp, fep->hwp + FEC_R_CNTRL); + return; + } - if (dev->flags&IFF_PROMISC) { - ep->fec_r_cntrl |= 0x0008; - } else { + tmp = readl(fep->hwp + FEC_R_CNTRL); + tmp &= ~0x8; + writel(tmp, fep->hwp + FEC_R_CNTRL); - ep->fec_r_cntrl &= ~0x0008; + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's + */ + writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - if (dev->flags & IFF_ALLMULTI) { - /* Catch all multicast addresses, so set the - * filter to all 1's. - */ - ep->fec_grp_hash_table_high = 0xffffffff; - ep->fec_grp_hash_table_low = 0xffffffff; - } else { - /* Clear filter and add the addresses in hash register. - */ - ep->fec_grp_hash_table_high = 0; - ep->fec_grp_hash_table_low = 0; + return; + } - dmi = dev->mc_list; + /* Clear filter and add the addresses in hash register + */ + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) - { - /* Only support group multicast for now. - */ - if (!(dmi->dmi_addr[0] & 1)) - continue; + dmi = dev->mc_list; - /* calculate crc32 value of mac address - */ - crc = 0xffffffff; + for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) { + /* Only support group multicast for now */ + if (!(dmi->dmi_addr[0] & 1)) + continue; - for (i = 0; i < dmi->dmi_addrlen; i++) - { - data = dmi->dmi_addr[i]; - for (bit = 0; bit < 8; bit++, data >>= 1) - { - crc = (crc >> 1) ^ - (((crc ^ data) & 1) ? CRC32_POLY : 0); - } - } + /* calculate crc32 value of mac address */ + crc = 0xffffffff; - /* only upper 6 bits (HASH_BITS) are used - which point to specific bit in he hash registers - */ - hash = (crc >> (32 - HASH_BITS)) & 0x3f; - - if (hash > 31) - ep->fec_grp_hash_table_high |= 1 << (hash - 32); - else - ep->fec_grp_hash_table_low |= 1 << hash; + for (i = 0; i < dmi->dmi_addrlen; i++) { + data = dmi->dmi_addr[i]; + for (bit = 0; bit < 8; bit++, data >>= 1) { + crc = (crc >> 1) ^ + (((crc ^ data) & 1) ? CRC32_POLY : 0); } } + + /* only upper 6 bits (HASH_BITS) are used + * which point to specific bit in he hash registers + */ + hash = (crc >> (32 - HASH_BITS)) & 0x3f; + + if (hash > 31) { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + tmp |= 1 << (hash - 32); + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + } else { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); + tmp |= 1 << hash; + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + } } } -/* Set a MAC change in hardware. - */ -static void -fec_set_mac_address(struct net_device *dev) +/* Set a MAC change in hardware. */ +static int +fec_set_mac_address(struct net_device *dev, void *p) { - volatile fec_t *fecp; + struct fec_enet_private *fep = netdev_priv(dev); + struct sockaddr *addr = p; - fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp; + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; - /* Set station address. */ - fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) | - (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24); - fecp->fec_addr_high = (dev->dev_addr[5] << 16) | - (dev->dev_addr[4] << 24); + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) | + (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), + fep->hwp + FEC_ADDR_LOW); + writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), + fep + FEC_ADDR_HIGH); + return 0; } +static const struct net_device_ops fec_netdev_ops = { + .ndo_open = fec_enet_open, + .ndo_stop = fec_enet_close, + .ndo_start_xmit = fec_enet_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_tx_timeout = fec_timeout, + .ndo_set_mac_address = fec_set_mac_address, +}; + /* * XXX: We need to clean up on failure exits here. * @@ -1672,17 +1655,13 @@ fec_set_mac_address(struct net_device *dev) int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); - unsigned long mem_addr; - volatile cbd_t *bdp; - cbd_t *cbd_base; - volatile fec_t *fecp; - int i, j; + struct bufdesc *cbd_base; + int i; - /* Allocate memory for buffer descriptors. - */ - mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE, - &fep->bd_dma, GFP_KERNEL); - if (mem_addr == 0) { + /* Allocate memory for buffer descriptors. */ + cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, + GFP_KERNEL); + if (!cbd_base) { printk("FEC: allocate descriptor memory failed?\n"); return -ENOMEM; } @@ -1690,146 +1669,47 @@ int __init fec_enet_init(struct net_device *dev, int index) spin_lock_init(&fep->hw_lock); spin_lock_init(&fep->mii_lock); - /* Create an Ethernet device instance. - */ - fecp = (volatile fec_t *)dev->base_addr; - fep->index = index; - fep->hwp = fecp; + fep->hwp = (void __iomem *)dev->base_addr; fep->netdev = dev; - /* Whack a reset. We should wait for this. - */ - fecp->fec_ecntrl = 1; - udelay(10); - /* Set the Ethernet address */ #ifdef CONFIG_M5272 fec_get_mac(dev); #else { unsigned long l; - l = fecp->fec_addr_low; + l = readl(fep->hwp + FEC_ADDR_LOW); dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); - l = fecp->fec_addr_high; + l = readl(fep->hwp + FEC_ADDR_HIGH); dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); } #endif - cbd_base = (cbd_t *)mem_addr; - - /* Set receive and transmit descriptor base. - */ + /* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; fep->tx_bd_base = cbd_base + RX_RING_SIZE; - fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; - fep->cur_rx = fep->rx_bd_base; - - fep->skb_cur = fep->skb_dirty = 0; - - /* Initialize the receive buffer descriptors. - */ - bdp = fep->rx_bd_base; - for (i=0; icbd_sc = BD_ENET_RX_EMPTY; - bdp->cbd_bufaddr = __pa(mem_addr); - mem_addr += FEC_ENET_RX_FRSIZE; - bdp++; - } - } - - /* Set the last buffer to wrap. - */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - /* ...and the same for transmmit. - */ - bdp = fep->tx_bd_base; - for (i=0, j=FEC_ENET_TX_FRPPG; i= FEC_ENET_TX_FRPPG) { - mem_addr = __get_free_page(GFP_KERNEL); - j = 1; - } else { - mem_addr += FEC_ENET_TX_FRSIZE; - j++; - } - fep->tx_bounce[i] = (unsigned char *) mem_addr; - - /* Initialize the BD for every fragment in the page. - */ - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } - - /* Set the last buffer to wrap. - */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - /* Set receive and transmit descriptor base. - */ - fecp->fec_r_des_start = fep->bd_dma; - fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) - * RX_RING_SIZE; - #ifdef HAVE_mii_link_interrupt fec_request_mii_intr(dev); #endif - - fecp->fec_grp_hash_table_high = 0; - fecp->fec_grp_hash_table_low = 0; - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fecp->fec_ecntrl = 2; - fecp->fec_r_des_active = 0; -#ifndef CONFIG_M5272 - fecp->fec_hash_table_high = 0; - fecp->fec_hash_table_low = 0; -#endif - - /* The FEC Ethernet specific entries in the device structure. */ - dev->open = fec_enet_open; - dev->hard_start_xmit = fec_enet_start_xmit; - dev->tx_timeout = fec_timeout; + /* The FEC Ethernet specific entries in the device structure */ dev->watchdog_timeo = TX_TIMEOUT; - dev->stop = fec_enet_close; - dev->set_multicast_list = set_multicast_list; + dev->netdev_ops = &fec_netdev_ops; for (i=0; ifec_r_cntrl = OPT_FRAME_SIZE | 0x04; - fecp->fec_x_cntrl = 0x00; - - /* - * Set MII speed to 2.5 MHz - */ + /* Set MII speed to 2.5 MHz */ fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1; - fecp->fec_mii_speed = fep->phy_speed; fec_restart(dev, 0); - /* Clear and enable interrupts */ - fecp->fec_ievent = 0xffc00000; - fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII); - /* Queue up command to detect the PHY and initialize the * remainder of the interface. */ @@ -1847,145 +1727,118 @@ int __init fec_enet_init(struct net_device *dev, int index) static void fec_restart(struct net_device *dev, int duplex) { - struct fec_enet_private *fep; - volatile cbd_t *bdp; - volatile fec_t *fecp; + struct fec_enet_private *fep = netdev_priv(dev); + struct bufdesc *bdp; int i; - fep = netdev_priv(dev); - fecp = fep->hwp; - - /* Whack a reset. We should wait for this. - */ - fecp->fec_ecntrl = 1; + /* Whack a reset. We should wait for this. */ + writel(1, fep->hwp + FEC_ECNTRL); udelay(10); - /* Clear any outstanding interrupt. - */ - fecp->fec_ievent = 0xffc00000; + /* Clear any outstanding interrupt. */ + writel(0xffc00000, fep->hwp + FEC_IEVENT); - /* Set station address. - */ - fec_set_mac_address(dev); + /* Reset all multicast. */ + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); +#ifndef CONFIG_M5272 + writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_HASH_TABLE_LOW); +#endif - /* Reset all multicast. - */ - fecp->fec_grp_hash_table_high = 0; - fecp->fec_grp_hash_table_low = 0; + /* Set maximum receive buffer size. */ + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); - /* Set maximum receive buffer size. - */ - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - - /* Set receive and transmit descriptor base. - */ - fecp->fec_r_des_start = fep->bd_dma; - fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) - * RX_RING_SIZE; + /* Set receive and transmit descriptor base. */ + writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); + writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, + fep->hwp + FEC_X_DES_START); fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->cur_rx = fep->rx_bd_base; - /* Reset SKB transmit buffers. - */ + /* Reset SKB transmit buffers. */ fep->skb_cur = fep->skb_dirty = 0; - for (i=0; i<=TX_RING_MOD_MASK; i++) { - if (fep->tx_skbuff[i] != NULL) { + for (i = 0; i <= TX_RING_MOD_MASK; i++) { + if (fep->tx_skbuff[i]) { dev_kfree_skb_any(fep->tx_skbuff[i]); fep->tx_skbuff[i] = NULL; } } - /* Initialize the receive buffer descriptors. - */ + /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; - for (i=0; icbd_sc = BD_ENET_RX_EMPTY; bdp++; } - /* Set the last buffer to wrap. - */ + /* Set the last buffer to wrap */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* ...and the same for transmmit. - */ + /* ...and the same for transmit */ bdp = fep->tx_bd_base; - for (i=0; icbd_sc = 0; bdp->cbd_bufaddr = 0; bdp++; } - /* Set the last buffer to wrap. - */ + /* Set the last buffer to wrap */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* Enable MII mode. - */ + /* Enable MII mode */ if (duplex) { - fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */ - fecp->fec_x_cntrl = 0x04; /* FD enable */ + /* MII enable / FD enable */ + writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); + writel(0x04, fep->hwp + FEC_X_CNTRL); } else { - /* MII enable|No Rcv on Xmit */ - fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06; - fecp->fec_x_cntrl = 0x00; + /* MII enable / No Rcv on Xmit */ + writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL); + writel(0x0, fep->hwp + FEC_X_CNTRL); } fep->full_duplex = duplex; - /* Set MII speed. - */ - fecp->fec_mii_speed = fep->phy_speed; + /* Set MII speed */ + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - /* And last, enable the transmit and receive processing. - */ - fecp->fec_ecntrl = 2; - fecp->fec_r_des_active = 0; + /* And last, enable the transmit and receive processing */ + writel(2, fep->hwp + FEC_ECNTRL); + writel(0, fep->hwp + FEC_R_DES_ACTIVE); - /* Enable interrupts we wish to service. - */ - fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII); + /* Enable interrupts we wish to service */ + writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, + fep->hwp + FEC_IMASK); } static void fec_stop(struct net_device *dev) { - volatile fec_t *fecp; - struct fec_enet_private *fep; + struct fec_enet_private *fep = netdev_priv(dev); - fep = netdev_priv(dev); - fecp = fep->hwp; - - /* - ** We cannot expect a graceful transmit stop without link !!! - */ - if (fep->link) - { - fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ + /* We cannot expect a graceful transmit stop without link !!! */ + if (fep->link) { + writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ udelay(10); - if (!(fecp->fec_ievent & FEC_ENET_GRA)) + if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA)) printk("fec_stop : Graceful transmit stop did not complete !\n"); - } + } - /* Whack a reset. We should wait for this. - */ - fecp->fec_ecntrl = 1; + /* Whack a reset. We should wait for this. */ + writel(1, fep->hwp + FEC_ECNTRL); udelay(10); - /* Clear outstanding MII command interrupts. - */ - fecp->fec_ievent = FEC_ENET_MII; + /* Clear outstanding MII command interrupts. */ + writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); - fecp->fec_imask = FEC_ENET_MII; - fecp->fec_mii_speed = fep->phy_speed; + writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); } static int __devinit diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 76c64c92e190..30b7dd671336 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -20,82 +20,55 @@ * registers in the same peripheral device on different models * of the ColdFire! */ -typedef struct fec { - unsigned long fec_reserved0; - unsigned long fec_ievent; /* Interrupt event reg */ - unsigned long fec_imask; /* Interrupt mask reg */ - unsigned long fec_reserved1; - unsigned long fec_r_des_active; /* Receive descriptor reg */ - unsigned long fec_x_des_active; /* Transmit descriptor reg */ - unsigned long fec_reserved2[3]; - unsigned long fec_ecntrl; /* Ethernet control reg */ - unsigned long fec_reserved3[6]; - unsigned long fec_mii_data; /* MII manage frame reg */ - unsigned long fec_mii_speed; /* MII speed control reg */ - unsigned long fec_reserved4[7]; - unsigned long fec_mib_ctrlstat; /* MIB control/status reg */ - unsigned long fec_reserved5[7]; - unsigned long fec_r_cntrl; /* Receive control reg */ - unsigned long fec_reserved6[15]; - unsigned long fec_x_cntrl; /* Transmit Control reg */ - unsigned long fec_reserved7[7]; - unsigned long fec_addr_low; /* Low 32bits MAC address */ - unsigned long fec_addr_high; /* High 16bits MAC address */ - unsigned long fec_opd; /* Opcode + Pause duration */ - unsigned long fec_reserved8[10]; - unsigned long fec_hash_table_high; /* High 32bits hash table */ - unsigned long fec_hash_table_low; /* Low 32bits hash table */ - unsigned long fec_grp_hash_table_high;/* High 32bits hash table */ - unsigned long fec_grp_hash_table_low; /* Low 32bits hash table */ - unsigned long fec_reserved9[7]; - unsigned long fec_x_wmrk; /* FIFO transmit water mark */ - unsigned long fec_reserved10; - unsigned long fec_r_bound; /* FIFO receive bound reg */ - unsigned long fec_r_fstart; /* FIFO receive start reg */ - unsigned long fec_reserved11[11]; - unsigned long fec_r_des_start; /* Receive descriptor ring */ - unsigned long fec_x_des_start; /* Transmit descriptor ring */ - unsigned long fec_r_buff_size; /* Maximum receive buff size */ -} fec_t; +#define FEC_IEVENT 0x004 /* Interrupt event reg */ +#define FEC_IMASK 0x008 /* Interrupt mask reg */ +#define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ +#define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ +#define FEC_ECNTRL 0x024 /* Ethernet control reg */ +#define FEC_MII_DATA 0x040 /* MII manage frame reg */ +#define FEC_MII_SPEED 0x044 /* MII speed control reg */ +#define FEC_MIB_CTRLSTAT 0x064 /* MIB control/status reg */ +#define FEC_R_CNTRL 0x084 /* Receive control reg */ +#define FEC_X_CNTRL 0x0c4 /* Transmit Control reg */ +#define FEC_ADDR_LOW 0x0e4 /* Low 32bits MAC address */ +#define FEC_ADDR_HIGH 0x0e8 /* High 16bits MAC address */ +#define FEC_OPD 0x0ec /* Opcode + Pause duration */ +#define FEC_HASH_TABLE_HIGH 0x118 /* High 32bits hash table */ +#define FEC_HASH_TABLE_LOW 0x11c /* Low 32bits hash table */ +#define FEC_GRP_HASH_TABLE_HIGH 0x120 /* High 32bits hash table */ +#define FEC_GRP_HASH_TABLE_LOW 0x124 /* Low 32bits hash table */ +#define FEC_X_WMRK 0x144 /* FIFO transmit water mark */ +#define FEC_R_BOUND 0x14c /* FIFO receive bound reg */ +#define FEC_R_FSTART 0x150 /* FIFO receive start reg */ +#define FEC_R_DES_START 0x180 /* Receive descriptor ring */ +#define FEC_X_DES_START 0x184 /* Transmit descriptor ring */ +#define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ #else -/* - * Define device register set address map. - */ -typedef struct fec { - unsigned long fec_ecntrl; /* Ethernet control reg */ - unsigned long fec_ievent; /* Interrupt even reg */ - unsigned long fec_imask; /* Interrupt mask reg */ - unsigned long fec_ivec; /* Interrupt vec status reg */ - unsigned long fec_r_des_active; /* Receive descriptor reg */ - unsigned long fec_x_des_active; /* Transmit descriptor reg */ - unsigned long fec_reserved1[10]; - unsigned long fec_mii_data; /* MII manage frame reg */ - unsigned long fec_mii_speed; /* MII speed control reg */ - unsigned long fec_reserved2[17]; - unsigned long fec_r_bound; /* FIFO receive bound reg */ - unsigned long fec_r_fstart; /* FIFO receive start reg */ - unsigned long fec_reserved3[4]; - unsigned long fec_x_wmrk; /* FIFO transmit water mark */ - unsigned long fec_reserved4; - unsigned long fec_x_fstart; /* FIFO transmit start reg */ - unsigned long fec_reserved5[21]; - unsigned long fec_r_cntrl; /* Receive control reg */ - unsigned long fec_max_frm_len; /* Maximum frame length reg */ - unsigned long fec_reserved6[14]; - unsigned long fec_x_cntrl; /* Transmit Control reg */ - unsigned long fec_reserved7[158]; - unsigned long fec_addr_low; /* Low 32bits MAC address */ - unsigned long fec_addr_high; /* High 16bits MAC address */ - unsigned long fec_grp_hash_table_high;/* High 32bits hash table */ - unsigned long fec_grp_hash_table_low; /* Low 32bits hash table */ - unsigned long fec_r_des_start; /* Receive descriptor ring */ - unsigned long fec_x_des_start; /* Transmit descriptor ring */ - unsigned long fec_r_buff_size; /* Maximum receive buff size */ - unsigned long reserved8[9]; - unsigned long fec_fifo_ram[112]; /* FIFO RAM buffer */ -} fec_t; +#define FEC_ECNTRL; 0x000 /* Ethernet control reg */ +#define FEC_IEVENT; 0x004 /* Interrupt even reg */ +#define FEC_IMASK; 0x008 /* Interrupt mask reg */ +#define FEC_IVEC; 0x00c /* Interrupt vec status reg */ +#define FEC_R_DES_ACTIVE; 0x010 /* Receive descriptor reg */ +#define FEC_X_DES_ACTIVE; 0x01c /* Transmit descriptor reg */ +#define FEC_MII_DATA 0x040 /* MII manage frame reg */ +#define FEC_MII_SPEED 0x044 /* MII speed control reg */ +#define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ +#define FEC_R_FSTART 0x090 /* FIFO receive start reg */ +#define FEC_X_WMRK 0x0a4 /* FIFO transmit water mark */ +#define FEC_X_FSTART 0x0ac /* FIFO transmit start reg */ +#define FEC_R_CNTRL 0x104 /* Receive control reg */ +#define FEC_MAX_FRM_LEN 0x108 /* Maximum frame length reg */ +#define FEC_X_CNTRL 0x144 /* Transmit Control reg */ +#define FEC_ADDR_LOW 0x3c0 /* Low 32bits MAC address */ +#define FEC_ADDR_HIGH 0x3c4 /* High 16bits MAC address */ +#define FEC_GRP_HASH_TABLE_HIGH 0x3c8 /* High 32bits hash table */ +#define FEC_GRP_HASH_TABLE_LOW 0x3cc /* Low 32bits hash table */ +#define FEC_R_DES_START 0x3d0 /* Receive descriptor ring */ +#define FEC_X_DES_START 0x3d4 /* Transmit descriptor ring */ +#define FEC_R_BUFF_SIZE 0x3d8 /* Maximum receive buff size */ +#define FEC_FIFO_RAM 0x400 /* FIFO RAM buffer */ #endif /* CONFIG_M5272 */ @@ -104,17 +77,17 @@ typedef struct fec { * Define the buffer descriptor structure. */ #ifdef CONFIG_ARCH_MXC -typedef struct bufdesc { +struct bufdesc { unsigned short cbd_datlen; /* Data length */ unsigned short cbd_sc; /* Control and status info */ unsigned long cbd_bufaddr; /* Buffer address */ -} cbd_t; +}; #else -typedef struct bufdesc { +struct bufdesc { unsigned short cbd_sc; /* Control and status info */ unsigned short cbd_datlen; /* Data length */ unsigned long cbd_bufaddr; /* Buffer address */ -} cbd_t; +}; #endif /* diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 8bbe7f617994..7d443405bbe2 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -43,11 +44,9 @@ #define DRIVER_NAME "mpc52xx-fec" -#define FEC5200_PHYADDR_NONE (-1) -#define FEC5200_PHYADDR_7WIRE (-2) - /* Private driver data structure */ struct mpc52xx_fec_priv { + struct net_device *ndev; int duplex; int speed; int r_irq; @@ -59,10 +58,11 @@ struct mpc52xx_fec_priv { int msg_enable; /* MDIO link details */ - int phy_addr; - unsigned int phy_speed; + unsigned int mdio_speed; + struct device_node *phy_node; struct phy_device *phydev; enum phy_state link; + int seven_wire_mode; }; @@ -211,85 +211,25 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev) phy_print_status(phydev); } -static int mpc52xx_fec_init_phy(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct phy_device *phydev; - char phy_id[BUS_ID_SIZE]; - - snprintf(phy_id, sizeof(phy_id), "%x:%02x", - (unsigned int)dev->base_addr, priv->phy_addr); - - priv->link = PHY_DOWN; - priv->speed = 0; - priv->duplex = -1; - - phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(phydev)) { - dev_err(&dev->dev, "phy_connect failed\n"); - return PTR_ERR(phydev); - } - dev_info(&dev->dev, "attached phy %i to driver %s\n", - phydev->addr, phydev->drv->name); - - priv->phydev = phydev; - - return 0; -} - -static int mpc52xx_fec_phy_start(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - int err; - - if (priv->phy_addr < 0) - return 0; - - err = mpc52xx_fec_init_phy(dev); - if (err) { - dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n"); - return err; - } - - /* reset phy - this also wakes it from PDOWN */ - phy_write(priv->phydev, MII_BMCR, BMCR_RESET); - phy_start(priv->phydev); - - return 0; -} - -static void mpc52xx_fec_phy_stop(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - if (!priv->phydev) - return; - - phy_disconnect(priv->phydev); - /* power down phy */ - phy_stop(priv->phydev); - phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN); -} - -static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv) -{ - struct mpc52xx_fec __iomem *fec = priv->fec; - - if (priv->phydev) - return; - - out_be32(&fec->mii_speed, priv->phy_speed); -} - static int mpc52xx_fec_open(struct net_device *dev) { struct mpc52xx_fec_priv *priv = netdev_priv(dev); int err = -EBUSY; + if (priv->phy_node) { + priv->phydev = of_phy_connect(priv->ndev, priv->phy_node, + mpc52xx_fec_adjust_link, 0, 0); + if (!priv->phydev) { + dev_err(&dev->dev, "of_phy_connect failed\n"); + return -ENODEV; + } + phy_start(priv->phydev); + } + if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_SHARED, DRIVER_NAME "_ctrl", dev)) { dev_err(&dev->dev, "ctrl interrupt request failed\n"); - goto out; + goto free_phy; } if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, 0, DRIVER_NAME "_rx", dev)) { @@ -311,10 +251,6 @@ static int mpc52xx_fec_open(struct net_device *dev) goto free_irqs; } - err = mpc52xx_fec_phy_start(dev); - if (err) - goto free_skbs; - bcom_enable(priv->rx_dmatsk); bcom_enable(priv->tx_dmatsk); @@ -324,16 +260,18 @@ static int mpc52xx_fec_open(struct net_device *dev) return 0; - free_skbs: - mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); - free_irqs: free_irq(priv->t_irq, dev); free_2irqs: free_irq(priv->r_irq, dev); free_ctrl_irq: free_irq(dev->irq, dev); - out: + free_phy: + if (priv->phydev) { + phy_stop(priv->phydev); + phy_disconnect(priv->phydev); + priv->phydev = NULL; + } return err; } @@ -352,7 +290,12 @@ static int mpc52xx_fec_close(struct net_device *dev) free_irq(priv->r_irq, dev); free_irq(priv->t_irq, dev); - mpc52xx_fec_phy_stop(dev); + if (priv->phydev) { + /* power down phy */ + phy_stop(priv->phydev); + phy_disconnect(priv->phydev); + priv->phydev = NULL; + } return 0; } @@ -696,7 +639,7 @@ static void mpc52xx_fec_hw_init(struct net_device *dev) /* set phy speed. * this can't be done in phy driver, since it needs to be called * before fec stuff (even on resume) */ - mpc52xx_fec_phy_hw_init(priv); + out_be32(&fec->mii_speed, priv->mdio_speed); } /** @@ -732,7 +675,7 @@ static void mpc52xx_fec_start(struct net_device *dev) rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ rcntrl |= FEC_RCNTRL_FCE; - if (priv->phy_addr != FEC5200_PHYADDR_7WIRE) + if (!priv->seven_wire_mode) rcntrl |= FEC_RCNTRL_MII_MODE; if (priv->duplex == DUPLEX_FULL) @@ -798,8 +741,6 @@ static void mpc52xx_fec_stop(struct net_device *dev) /* Stop FEC */ out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); - - return; } /* reset fec and bestcomm tasks */ @@ -817,9 +758,11 @@ static void mpc52xx_fec_reset(struct net_device *dev) mpc52xx_fec_hw_init(dev); - phy_stop(priv->phydev); - phy_write(priv->phydev, MII_BMCR, BMCR_RESET); - phy_start(priv->phydev); + if (priv->phydev) { + phy_stop(priv->phydev); + phy_write(priv->phydev, MII_BMCR, BMCR_RESET); + phy_start(priv->phydev); + } bcom_fec_rx_reset(priv->rx_dmatsk); bcom_fec_tx_reset(priv->tx_dmatsk); @@ -919,8 +862,6 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) struct net_device *ndev; struct mpc52xx_fec_priv *priv = NULL; struct resource mem; - struct device_node *phy_node; - const phandle *phy_handle; const u32 *prop; int prop_size; @@ -933,6 +874,7 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) return -ENOMEM; priv = netdev_priv(ndev); + priv->ndev = ndev; /* Reserve FEC control zone */ rv = of_address_to_resource(op->node, 0, &mem); @@ -956,6 +898,7 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; ndev->base_addr = mem.start; + SET_NETDEV_DEV(ndev, &op->dev); spin_lock_init(&priv->lock); @@ -1003,14 +946,9 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) */ /* Start with safe defaults for link connection */ - priv->phy_addr = FEC5200_PHYADDR_NONE; priv->speed = 100; priv->duplex = DUPLEX_HALF; - priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; - - /* the 7-wire property means don't use MII mode */ - if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) - priv->phy_addr = FEC5200_PHYADDR_7WIRE; + priv->mdio_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; /* The current speed preconfigures the speed of the MII link */ prop = of_get_property(op->node, "current-speed", &prop_size); @@ -1019,43 +957,23 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; } - /* If there is a phy handle, setup link to that phy */ - phy_handle = of_get_property(op->node, "phy-handle", &prop_size); - if (phy_handle && (prop_size >= sizeof(phandle))) { - phy_node = of_find_node_by_phandle(*phy_handle); - prop = of_get_property(phy_node, "reg", &prop_size); - if (prop && (prop_size >= sizeof(u32))) - if ((*prop >= 0) && (*prop < PHY_MAX_ADDR)) - priv->phy_addr = *prop; - of_node_put(phy_node); + /* If there is a phy handle, then get the PHY node */ + priv->phy_node = of_parse_phandle(op->node, "phy-handle", 0); + + /* the 7-wire property means don't use MII mode */ + if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) { + priv->seven_wire_mode = 1; + dev_info(&ndev->dev, "using 7-wire PHY mode\n"); } /* Hardware init */ mpc52xx_fec_hw_init(ndev); - mpc52xx_fec_reset_stats(ndev); - SET_NETDEV_DEV(ndev, &op->dev); - - /* Register the new network device */ rv = register_netdev(ndev); if (rv < 0) goto probe_error; - /* Now report the link setup */ - switch (priv->phy_addr) { - case FEC5200_PHYADDR_NONE: - dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n", - priv->speed, priv->duplex ? 'F' : 'H'); - break; - case FEC5200_PHYADDR_7WIRE: - dev_info(&ndev->dev, "using 7-wire PHY mode\n"); - break; - default: - dev_info(&ndev->dev, "Using PHY at MDIO address %i\n", - priv->phy_addr); - } - /* We're done ! */ dev_set_drvdata(&op->dev, ndev); @@ -1065,6 +983,10 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) /* Error handling - free everything that might be allocated */ probe_error: + if (priv->phy_node) + of_node_put(priv->phy_node); + priv->phy_node = NULL; + irq_dispose_mapping(ndev->irq); if (priv->rx_dmatsk) @@ -1093,6 +1015,10 @@ mpc52xx_fec_remove(struct of_device *op) unregister_netdev(ndev); + if (priv->phy_node) + of_node_put(priv->phy_node); + priv->phy_node = NULL; + irq_dispose_mapping(ndev->irq); bcom_fec_rx_release(priv->rx_dmatsk); diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index dd9bfa42ac34..fec9f245116b 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #include "fec_mpc52xx.h" struct mpc52xx_fec_mdio_priv { struct mpc52xx_fec __iomem *regs; + int mdio_irqs[PHY_MAX_ADDR]; }; static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, @@ -27,7 +29,7 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, { struct mpc52xx_fec_mdio_priv *priv = bus->priv; struct mpc52xx_fec __iomem *fec; - int tries = 100; + int tries = 3; value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; @@ -38,7 +40,7 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, /* wait for it to finish, this takes about 23 us on lite5200b */ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) - udelay(5); + msleep(1); if (!tries) return -ETIMEDOUT; @@ -64,7 +66,6 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, { struct device *dev = &of->dev; struct device_node *np = of->node; - struct device_node *child = NULL; struct mii_bus *bus; struct mpc52xx_fec_mdio_priv *priv; struct resource res = {}; @@ -85,22 +86,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, bus->write = mpc52xx_fec_mdio_write; /* setup irqs */ - bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL); - if (bus->irq == NULL) { - err = -ENOMEM; - goto out_free; - } - for (i=0; iirq[i] = PHY_POLL; - - while ((child = of_get_next_child(np, child)) != NULL) { - int irq = irq_of_parse_and_map(child, 0); - if (irq != NO_IRQ) { - const u32 *id = of_get_property(child, "reg", NULL); - if (id) - bus->irq[*id] = irq; - } - } + bus->irq = priv->mdio_irqs; /* setup registers */ err = of_address_to_resource(np, 0, &res); @@ -122,7 +108,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); - err = mdiobus_register(bus); + err = of_mdiobus_register(bus, np); if (err) goto out_unmap; diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 9f6a68fb7b45..b60a3041b64c 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -77,27 +77,31 @@ * Hardware access: */ -#define DEV_NEED_TIMERIRQ 0x000001 /* set the timer irq flag in the irq mask */ -#define DEV_NEED_LINKTIMER 0x000002 /* poll link settings. Relies on the timer irq */ -#define DEV_HAS_LARGEDESC 0x000004 /* device supports jumbo frames and needs packet format 2 */ -#define DEV_HAS_HIGH_DMA 0x000008 /* device supports 64bit dma */ -#define DEV_HAS_CHECKSUM 0x000010 /* device supports tx and rx checksum offloads */ -#define DEV_HAS_VLAN 0x000020 /* device supports vlan tagging and striping */ -#define DEV_HAS_MSI 0x000040 /* device supports MSI */ -#define DEV_HAS_MSI_X 0x000080 /* device supports MSI-X */ -#define DEV_HAS_POWER_CNTRL 0x000100 /* device supports power savings */ -#define DEV_HAS_STATISTICS_V1 0x000200 /* device supports hw statistics version 1 */ -#define DEV_HAS_STATISTICS_V2 0x000600 /* device supports hw statistics version 2 */ -#define DEV_HAS_STATISTICS_V3 0x000e00 /* device supports hw statistics version 3 */ -#define DEV_HAS_TEST_EXTENDED 0x001000 /* device supports extended diagnostic test */ -#define DEV_HAS_MGMT_UNIT 0x002000 /* device supports management unit */ -#define DEV_HAS_CORRECT_MACADDR 0x004000 /* device supports correct mac address order */ -#define DEV_HAS_COLLISION_FIX 0x008000 /* device supports tx collision fix */ -#define DEV_HAS_PAUSEFRAME_TX_V1 0x010000 /* device supports tx pause frames version 1 */ -#define DEV_HAS_PAUSEFRAME_TX_V2 0x020000 /* device supports tx pause frames version 2 */ -#define DEV_HAS_PAUSEFRAME_TX_V3 0x040000 /* device supports tx pause frames version 3 */ -#define DEV_NEED_TX_LIMIT 0x080000 /* device needs to limit tx */ -#define DEV_HAS_GEAR_MODE 0x100000 /* device supports gear mode */ +#define DEV_NEED_TIMERIRQ 0x0000001 /* set the timer irq flag in the irq mask */ +#define DEV_NEED_LINKTIMER 0x0000002 /* poll link settings. Relies on the timer irq */ +#define DEV_HAS_LARGEDESC 0x0000004 /* device supports jumbo frames and needs packet format 2 */ +#define DEV_HAS_HIGH_DMA 0x0000008 /* device supports 64bit dma */ +#define DEV_HAS_CHECKSUM 0x0000010 /* device supports tx and rx checksum offloads */ +#define DEV_HAS_VLAN 0x0000020 /* device supports vlan tagging and striping */ +#define DEV_HAS_MSI 0x0000040 /* device supports MSI */ +#define DEV_HAS_MSI_X 0x0000080 /* device supports MSI-X */ +#define DEV_HAS_POWER_CNTRL 0x0000100 /* device supports power savings */ +#define DEV_HAS_STATISTICS_V1 0x0000200 /* device supports hw statistics version 1 */ +#define DEV_HAS_STATISTICS_V2 0x0000600 /* device supports hw statistics version 2 */ +#define DEV_HAS_STATISTICS_V3 0x0000e00 /* device supports hw statistics version 3 */ +#define DEV_HAS_TEST_EXTENDED 0x0001000 /* device supports extended diagnostic test */ +#define DEV_HAS_MGMT_UNIT 0x0002000 /* device supports management unit */ +#define DEV_HAS_CORRECT_MACADDR 0x0004000 /* device supports correct mac address order */ +#define DEV_HAS_COLLISION_FIX 0x0008000 /* device supports tx collision fix */ +#define DEV_HAS_PAUSEFRAME_TX_V1 0x0010000 /* device supports tx pause frames version 1 */ +#define DEV_HAS_PAUSEFRAME_TX_V2 0x0020000 /* device supports tx pause frames version 2 */ +#define DEV_HAS_PAUSEFRAME_TX_V3 0x0040000 /* device supports tx pause frames version 3 */ +#define DEV_NEED_TX_LIMIT 0x0080000 /* device needs to limit tx */ +#define DEV_NEED_TX_LIMIT2 0x0180000 /* device needs to limit tx, expect for some revs */ +#define DEV_HAS_GEAR_MODE 0x0200000 /* device supports gear mode */ +#define DEV_NEED_PHY_INIT_FIX 0x0400000 /* device needs specific phy workaround */ +#define DEV_NEED_LOW_POWER_FIX 0x0800000 /* device needs special power up workaround */ +#define DEV_NEED_MSI_FIX 0x1000000 /* device needs msi workaround */ enum { NvRegIrqStatus = 0x000, @@ -343,6 +347,7 @@ enum { #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15 #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 #define NVREG_POWERSTATE2_PHY_RESET 0x0004 +#define NVREG_POWERSTATE2_GATE_CLOCKS 0x0F00 }; /* Big endian: should work, but is untested */ @@ -1023,6 +1028,23 @@ static int using_multi_irqs(struct net_device *dev) return 1; } +static void nv_txrx_gate(struct net_device *dev, bool gate) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 powerstate; + + if (!np->mac_in_use && + (np->driver_data & DEV_HAS_POWER_CNTRL)) { + powerstate = readl(base + NvRegPowerState2); + if (gate) + powerstate |= NVREG_POWERSTATE2_GATE_CLOCKS; + else + powerstate &= ~NVREG_POWERSTATE2_GATE_CLOCKS; + writel(powerstate, base + NvRegPowerState2); + } +} + static void nv_enable_irq(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); @@ -1253,14 +1275,7 @@ static int phy_init(struct net_device *dev) } } if (np->phy_model == PHY_MODEL_REALTEK_8201) { - if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) { + if (np->driver_data & DEV_NEED_PHY_INIT_FIX) { phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); phy_reserved |= PHY_REALTEK_INIT7; if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) { @@ -1451,14 +1466,7 @@ static int phy_init(struct net_device *dev) } } if (np->phy_model == PHY_MODEL_REALTEK_8201) { - if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 || - np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) { + if (np->driver_data & DEV_NEED_PHY_INIT_FIX) { phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); phy_reserved |= PHY_REALTEK_INIT7; if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) { @@ -3403,12 +3411,14 @@ static void nv_linkchange(struct net_device *dev) if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); printk(KERN_INFO "%s: link up.\n", dev->name); + nv_txrx_gate(dev, false); nv_start_rx(dev); } } else { if (netif_carrier_ok(dev)) { netif_carrier_off(dev); printk(KERN_INFO "%s: link down.\n", dev->name); + nv_txrx_gate(dev, true); nv_stop_rx(dev); } } @@ -5336,6 +5346,7 @@ static int nv_open(struct net_device *dev) mii_rw(dev, np->phyaddr, MII_BMCR, mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN); + nv_txrx_gate(dev, false); /* erase previous misconfiguration */ if (np->driver_data & DEV_HAS_POWER_CNTRL) nv_mac_reset(dev); @@ -5523,12 +5534,14 @@ static int nv_close(struct net_device *dev) nv_drain_rxtx(dev); if (np->wolenabled || !phy_power_down) { + nv_txrx_gate(dev, false); writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); nv_start_rx(dev); } else { /* power down phy */ mii_rw(dev, np->phyaddr, MII_BMCR, mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN); + nv_txrx_gate(dev, true); } /* FIXME: power down nic */ @@ -5821,8 +5834,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* take phy and nic out of low power mode */ powerstate = readl(base + NvRegPowerState2); powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; - if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && + if ((id->driver_data & DEV_NEED_LOW_POWER_FIX) && pci_dev->revision >= 0xA3) powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; writel(powerstate, base + NvRegPowerState2); @@ -5878,14 +5890,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* Limit the number of tx's outstanding for hw bug */ if (id->driver_data & DEV_NEED_TX_LIMIT) { np->tx_limit = 1; - if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_32 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_33 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_34 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_35 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_36 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_37 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_38 || - id->device == PCI_DEVICE_ID_NVIDIA_NVENET_39) && + if ((id->driver_data & DEV_NEED_TX_LIMIT2) && pci_dev->revision >= 0xA2) np->tx_limit = 0; } @@ -6135,7 +6140,8 @@ static int nv_resume(struct pci_dev *pdev) for (i = 0;i <= np->register_size/sizeof(u32); i++) writel(np->saved_config_space[i], base+i*sizeof(u32)); - pci_write_config_dword(pdev, NV_MSI_PRIV_OFFSET, NV_MSI_PRIV_VALUE); + if (np->driver_data & DEV_NEED_MSI_FIX) + pci_write_config_dword(pdev, NV_MSI_PRIV_OFFSET, NV_MSI_PRIV_VALUE); /* restore phy state, including autoneg */ phy_init(dev); @@ -6184,160 +6190,164 @@ static void nv_shutdown(struct pci_dev *pdev) static struct pci_device_id pci_tbl[] = { { /* nForce Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1), + PCI_DEVICE(0x10DE, 0x01C3), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce2 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_2), + PCI_DEVICE(0x10DE, 0x0066), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_3), + PCI_DEVICE(0x10DE, 0x00D6), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4), + PCI_DEVICE(0x10DE, 0x0086), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM, }, { /* nForce3 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5), + PCI_DEVICE(0x10DE, 0x008C), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM, }, { /* nForce3 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6), + PCI_DEVICE(0x10DE, 0x00E6), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM, }, { /* nForce3 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7), + PCI_DEVICE(0x10DE, 0x00DF), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM, }, { /* CK804 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8), + PCI_DEVICE(0x10DE, 0x0056), .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* CK804 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9), + PCI_DEVICE(0x10DE, 0x0057), .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* MCP04 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10), + PCI_DEVICE(0x10DE, 0x0037), .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* MCP04 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11), + PCI_DEVICE(0x10DE, 0x0038), .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* MCP51 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, + PCI_DEVICE(0x10DE, 0x0268), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1|DEV_NEED_LOW_POWER_FIX, }, { /* MCP51 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, + PCI_DEVICE(0x10DE, 0x0269), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1|DEV_NEED_LOW_POWER_FIX, }, { /* MCP55 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT, + PCI_DEVICE(0x10DE, 0x0372), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX, }, { /* MCP55 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT, + PCI_DEVICE(0x10DE, 0x0373), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + PCI_DEVICE(0x10DE, 0x03E5), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + PCI_DEVICE(0x10DE, 0x03E6), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + PCI_DEVICE(0x10DE, 0x03EE), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP61 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + PCI_DEVICE(0x10DE, 0x03EF), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0450), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0451), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0452), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP65 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0453), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x054C), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x054D), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x054E), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP67 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x054F), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x07DC), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x07DD), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x07DE), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP73 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x07DF), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0760), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0761), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0762), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP77 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0763), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0AB0), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0AB1), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0AB2), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, }, { /* MCP79 Ethernet Controller */ - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + PCI_DEVICE(0x10DE, 0x0AB3), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX, + }, + { /* MCP89 Ethernet Controller */ + PCI_DEVICE(0x10DE, 0x0D7D), + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX, }, {0,}, }; diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index a9cbc3191a2a..b892c3ad9a74 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -752,9 +754,10 @@ static int fs_init_phy(struct net_device *dev) fep->oldlink = 0; fep->oldspeed = 0; fep->oldduplex = -1; - if(fep->fpi->bus_id) - phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + if(fep->fpi->phy_node) + phydev = of_phy_connect(dev, fep->fpi->phy_node, + &fs_adjust_link, 0, + PHY_INTERFACE_MODE_MII); else { printk("No phy bus ID specified in BSP code\n"); return -EINVAL; @@ -938,81 +941,6 @@ extern void fs_mii_disconnect(struct net_device *dev); /**************************************************************************************/ -/* handy pointer to the immap */ -void __iomem *fs_enet_immap = NULL; - -static int setup_immap(void) -{ -#ifdef CONFIG_CPM1 - fs_enet_immap = ioremap(IMAP_ADDR, 0x4000); - WARN_ON(!fs_enet_immap); -#elif defined(CONFIG_CPM2) - fs_enet_immap = cpm2_immr; -#endif - - return 0; -} - -static void cleanup_immap(void) -{ -#if defined(CONFIG_CPM1) - iounmap(fs_enet_immap); -#endif -} - -/**************************************************************************************/ - -static int __devinit find_phy(struct device_node *np, - struct fs_platform_info *fpi) -{ - struct device_node *phynode, *mdionode; - int ret = 0, len, bus_id; - const u32 *data; - - data = of_get_property(np, "fixed-link", NULL); - if (data) { - snprintf(fpi->bus_id, 16, "%x:%02x", 0, *data); - return 0; - } - - data = of_get_property(np, "phy-handle", &len); - if (!data || len != 4) - return -EINVAL; - - phynode = of_find_node_by_phandle(*data); - if (!phynode) - return -EINVAL; - - data = of_get_property(phynode, "reg", &len); - if (!data || len != 4) { - ret = -EINVAL; - goto out_put_phy; - } - - mdionode = of_get_parent(phynode); - if (!mdionode) { - ret = -EINVAL; - goto out_put_phy; - } - - bus_id = of_get_gpio(mdionode, 0); - if (bus_id < 0) { - struct resource res; - ret = of_address_to_resource(mdionode, 0, &res); - if (ret) - goto out_put_mdio; - bus_id = res.start; - } - - snprintf(fpi->bus_id, 16, "%x:%02x", bus_id, *data); - -out_put_mdio: - of_node_put(mdionode); -out_put_phy: - of_node_put(phynode); - return ret; -} - #ifdef CONFIG_FS_ENET_HAS_FEC #define IS_FEC(match) ((match)->data == &fs_fec_ops) #else @@ -1062,9 +990,9 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, fpi->rx_copybreak = 240; fpi->use_napi = 1; fpi->napi_weight = 17; - - ret = find_phy(ofdev->node, fpi); - if (ret) + fpi->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0); + if ((!fpi->phy_node) && (!of_get_property(ofdev->node, "fixed-link", + NULL))) goto out_free_fpi; privsize = sizeof(*fep) + @@ -1136,6 +1064,7 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, out_free_dev: free_netdev(ndev); dev_set_drvdata(&ofdev->dev, NULL); + of_node_put(fpi->phy_node); out_free_fpi: kfree(fpi); return ret; @@ -1151,7 +1080,7 @@ static int fs_enet_remove(struct of_device *ofdev) fep->ops->free_bd(ndev); fep->ops->cleanup_data(ndev); dev_set_drvdata(fep->dev, NULL); - + of_node_put(fep->fpi->phy_node); free_netdev(ndev); return 0; } @@ -1191,25 +1120,12 @@ static struct of_platform_driver fs_enet_driver = { static int __init fs_init(void) { - int r = setup_immap(); - if (r != 0) - return r; - - r = of_register_platform_driver(&fs_enet_driver); - if (r != 0) - goto out; - - return 0; - -out: - cleanup_immap(); - return r; + return of_register_platform_driver(&fs_enet_driver); } static void __exit fs_cleanup(void) { of_unregister_platform_driver(&fs_enet_driver); - cleanup_immap(); } #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 85a4bab7f630..ef01e09781a5 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -194,9 +194,4 @@ extern const struct fs_ops fs_scc_ops; /*******************************************************************/ -/* handy pointer to the immap */ -extern void __iomem *fs_enet_immap; - -/*******************************************************************/ - #endif diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 14e575313c89..ca7bcb8ab3a1 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -245,10 +245,6 @@ static void set_multicast_list(struct net_device *dev) static void restart(struct net_device *dev) { -#ifdef CONFIG_DUET - immap_t *immap = fs_enet_immap; - u32 cptr; -#endif struct fs_enet_private *fep = netdev_priv(dev); fec_t __iomem *fecp = fep->fec.fecp; const struct fs_platform_info *fpi = fep->fpi; @@ -315,36 +311,6 @@ static void restart(struct net_device *dev) FW(fecp, ievent, 0xffc0); FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); - /* - * adjust to speed (only for DUET & RMII) - */ -#ifdef CONFIG_DUET - if (fpi->use_rmii) { - cptr = in_be32(&immap->im_cpm.cp_cptr); - switch (fs_get_fec_index(fpi->fs_no)) { - case 0: - cptr |= 0x100; - if (fep->speed == 10) - cptr |= 0x0000010; - else if (fep->speed == 100) - cptr &= ~0x0000010; - break; - case 1: - cptr |= 0x80; - if (fep->speed == 10) - cptr |= 0x0000008; - else if (fep->speed == 100) - cptr &= ~0x0000008; - break; - default: - BUG(); /* should never happen */ - break; - } - out_be32(&immap->im_cpm.cp_cptr, cptr); - } -#endif - - FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ /* * adjust to duplex mode diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 49b6645d7e0c..93b481b0e3c7 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "fs_enet.h" @@ -149,31 +150,12 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, return 0; } -static void __devinit add_phy(struct mii_bus *bus, struct device_node *np) -{ - const u32 *data; - int len, id, irq; - - data = of_get_property(np, "reg", &len); - if (!data || len != 4) - return; - - id = *data; - bus->phy_mask &= ~(1 << id); - - irq = of_irq_to_resource(np, 0, NULL); - if (irq != NO_IRQ) - bus->irq[id] = irq; -} - static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) { - struct device_node *np = NULL; struct mii_bus *new_bus; struct bb_info *bitbang; int ret = -ENOMEM; - int i; bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); if (!bitbang) @@ -196,17 +178,10 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, if (!new_bus->irq) goto out_unmap_regs; - for (i = 0; i < PHY_MAX_ADDR; i++) - new_bus->irq[i] = -1; - - while ((np = of_get_next_child(ofdev->node, np))) - if (!strcmp(np->type, "ethernet-phy")) - add_phy(new_bus, np); - new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); - ret = mdiobus_register(new_bus); + ret = of_mdiobus_register(new_bus, ofdev->node); if (ret) goto out_free_irqs; diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 28077cc1b949..75a09994d665 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -54,8 +54,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) fec_t __iomem *fecp = fec->fecp; int i, ret = -1; - if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) - BUG(); + BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); /* Add PHY address to register command. */ out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); @@ -79,8 +78,7 @@ static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, int i; /* this must never happen */ - if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) - BUG(); + BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); /* Add PHY address to register command. */ out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); @@ -102,23 +100,6 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) return 0; } -static void __devinit add_phy(struct mii_bus *bus, struct device_node *np) -{ - const u32 *data; - int len, id, irq; - - data = of_get_property(np, "reg", &len); - if (!data || len != 4) - return; - - id = *data; - bus->phy_mask &= ~(1 << id); - - irq = of_irq_to_resource(np, 0, NULL); - if (irq != NO_IRQ) - bus->irq[id] = irq; -} - static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) { @@ -165,17 +146,10 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, if (!new_bus->irq) goto out_unmap_regs; - for (i = 0; i < PHY_MAX_ADDR; i++) - new_bus->irq[i] = -1; - - while ((np = of_get_next_child(ofdev->node, np))) - if (!strcmp(np->type, "ethernet-phy")) - add_phy(new_bus, np); - new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); - ret = mdiobus_register(new_bus); + ret = of_mdiobus_register(new_bus, ofdev->node); if (ret) goto out_free_irqs; diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index aa1eb88c21fc..3af581303ca2 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -154,44 +155,6 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus) return 0; } -/* Allocate an array which provides irq #s for each PHY on the given bus */ -static int *create_irq_map(struct device_node *np) -{ - int *irqs; - int i; - struct device_node *child = NULL; - - irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); - - if (!irqs) - return NULL; - - for (i = 0; i < PHY_MAX_ADDR; i++) - irqs[i] = PHY_POLL; - - while ((child = of_get_next_child(np, child)) != NULL) { - int irq = irq_of_parse_and_map(child, 0); - const u32 *id; - - if (irq == NO_IRQ) - continue; - - id = of_get_property(child, "reg", NULL); - - if (!id) - continue; - - if (*id < PHY_MAX_ADDR && *id >= 0) - irqs[*id] = irq; - else - printk(KERN_WARNING "%s: " - "%d is not a valid PHY address\n", - np->full_name, *id); - } - - return irqs; -} - void fsl_pq_mdio_bus_name(char *name, struct device_node *np) { const u32 *addr; @@ -315,7 +278,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, new_bus->priv = (void __force *)regs; - new_bus->irq = create_irq_map(np); + new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); if (NULL == new_bus->irq) { err = -ENOMEM; @@ -338,13 +301,17 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, of_device_is_compatible(np, "ucc_geth_phy")) { #ifdef CONFIG_UCC_GETH u32 id; + static u32 mii_mng_master; tbipa = ®s->utbipar; if ((err = get_ucc_id_for_range(addr, addr + size, &id))) goto err_free_irqs; - ucc_set_qe_mux_mii_mng(id - 1); + if (!mii_mng_master) { + mii_mng_master = id; + ucc_set_qe_mux_mii_mng(id - 1); + } #else err = -ENODEV; goto err_free_irqs; @@ -384,15 +351,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, out_be32(tbipa, tbiaddr); - /* - * The TBIPHY-only buses will find PHYs at every address, - * so we mask them all but the TBI - */ - if (of_device_is_compatible(np, "fsl,gianfar-tbi")) - new_bus->phy_mask = ~(1 << tbiaddr); - - err = mdiobus_register(new_bus); - + err = of_mdiobus_register(new_bus, np); if (err) { printk (KERN_ERR "%s: Cannot register as MDIO bus\n", new_bus->name); @@ -460,10 +419,10 @@ int __init fsl_pq_mdio_init(void) { return of_register_platform_driver(&fsl_pq_mdio_driver); } +module_init(fsl_pq_mdio_init); void fsl_pq_mdio_exit(void) { of_unregister_platform_driver(&fsl_pq_mdio_driver); } -subsys_initcall_sync(fsl_pq_mdio_init); module_exit(fsl_pq_mdio_exit); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a0519184e54e..4ae1d259fced 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -168,17 +169,13 @@ static inline int gfar_uses_fcb(struct gfar_private *priv) static int gfar_of_init(struct net_device *dev) { - struct device_node *phy, *mdio; - const unsigned int *id; const char *model; const char *ctype; const void *mac_addr; - const phandle *ph; u64 addr, size; int err = 0; struct gfar_private *priv = netdev_priv(dev); struct device_node *np = priv->node; - char bus_name[MII_BUS_ID_SIZE]; const u32 *stash; const u32 *stash_len; const u32 *stash_idx; @@ -264,8 +261,8 @@ static int gfar_of_init(struct net_device *dev) if (of_get_property(np, "fsl,magic-packet", NULL)) priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; - ph = of_get_property(np, "phy-handle", NULL); - if (ph == NULL) { + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy_node) { u32 *fixed_link; fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL); @@ -273,57 +270,10 @@ static int gfar_of_init(struct net_device *dev) err = -ENODEV; goto err_out; } - - snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), - PHY_ID_FMT, "0", fixed_link[0]); - } else { - phy = of_find_node_by_phandle(*ph); - - if (phy == NULL) { - err = -ENODEV; - goto err_out; - } - - mdio = of_get_parent(phy); - - id = of_get_property(phy, "reg", NULL); - - of_node_put(phy); - - fsl_pq_mdio_bus_name(bus_name, mdio); - of_node_put(mdio); - snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", - bus_name, *id); } /* Find the TBI PHY. If it's not there, we don't support SGMII */ - ph = of_get_property(np, "tbi-handle", NULL); - if (ph) { - struct device_node *tbi = of_find_node_by_phandle(*ph); - struct of_device *ofdev; - struct mii_bus *bus; - - if (!tbi) - return 0; - - mdio = of_get_parent(tbi); - if (!mdio) - return 0; - - ofdev = of_find_device_by_node(mdio); - - of_node_put(mdio); - - id = of_get_property(tbi, "reg", NULL); - if (!id) - return 0; - - of_node_put(tbi); - - bus = dev_get_drvdata(&ofdev->dev); - - priv->tbiphy = bus->phy_map[*id]; - } + priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0); return 0; @@ -529,6 +479,10 @@ static int gfar_probe(struct of_device *ofdev, register_fail: iounmap(priv->regs); regs_fail: + if (priv->phy_node) + of_node_put(priv->phy_node); + if (priv->tbi_node) + of_node_put(priv->tbi_node); free_netdev(dev); return err; } @@ -537,6 +491,11 @@ static int gfar_remove(struct of_device *ofdev) { struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); + if (priv->phy_node) + of_node_put(priv->phy_node); + if (priv->tbi_node) + of_node_put(priv->tbi_node); + dev_set_drvdata(&ofdev->dev, NULL); iounmap(priv->regs); @@ -690,7 +649,6 @@ static int init_phy(struct net_device *dev) uint gigabit_support = priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? SUPPORTED_1000baseT_Full : 0; - struct phy_device *phydev; phy_interface_t interface; priv->oldlink = 0; @@ -699,21 +657,21 @@ static int init_phy(struct net_device *dev) interface = gfar_get_interface(dev); - phydev = phy_connect(dev, priv->phy_bus_id, &adjust_link, 0, interface); + if (priv->phy_node) { + priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, + 0, interface); + if (!priv->phydev) { + dev_err(&dev->dev, "error: Could not attach to PHY\n"); + return -ENODEV; + } + } if (interface == PHY_INTERFACE_MODE_SGMII) gfar_configure_serdes(dev); - if (IS_ERR(phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); - } - /* Remove any features not supported by the controller */ - phydev->supported &= (GFAR_SUPPORTED | gigabit_support); - phydev->advertising = phydev->supported; - - priv->phydev = phydev; + priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support); + priv->phydev->advertising = priv->phydev->supported; return 0; } @@ -730,10 +688,17 @@ static int init_phy(struct net_device *dev) static void gfar_configure_serdes(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + struct phy_device *tbiphy; - if (!priv->tbiphy) { - printk(KERN_WARNING "SGMII mode requires that the device " - "tree specify a tbi-handle\n"); + if (!priv->tbi_node) { + dev_warn(&dev->dev, "error: SGMII mode requires that the " + "device tree specify a tbi-handle\n"); + return; + } + + tbiphy = of_phy_find_device(priv->tbi_node); + if (!tbiphy) { + dev_err(&dev->dev, "error: Could not get TBI device\n"); return; } @@ -743,17 +708,17 @@ static void gfar_configure_serdes(struct net_device *dev) * everything for us? Resetting it takes the link down and requires * several seconds for it to come back. */ - if (phy_read(priv->tbiphy, MII_BMSR) & BMSR_LSTATUS) + if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) return; /* Single clk mode, mii mode off(for serdes communication) */ - phy_write(priv->tbiphy, MII_TBICON, TBICON_CLK_SELECT); + phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT); - phy_write(priv->tbiphy, MII_ADVERTISE, + phy_write(tbiphy, MII_ADVERTISE, ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM); - phy_write(priv->tbiphy, MII_BMCR, BMCR_ANENABLE | + phy_write(tbiphy, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); } @@ -1242,7 +1207,8 @@ static int gfar_enet_open(struct net_device *dev) static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb) { struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN); - cacheable_memzero(fcb, GMAC_FCB_LEN); + + memset(fcb, 0, GMAC_FCB_LEN); return fcb; } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index cf352961ae9b..2cd94338b5d3 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -779,7 +779,8 @@ struct gfar_private { spinlock_t bflock; phy_interface_t interface; - char phy_bus_id[BUS_ID_SIZE]; + struct device_node *phy_node; + struct device_node *tbi_node; u32 device_flags; unsigned char rx_csum_enable:1, extended_hash:1, @@ -793,7 +794,6 @@ struct gfar_private { /* PHY stuff */ struct phy_device *phydev; - struct phy_device *tbiphy; struct mii_bus *mii_bus; int oldspeed; int oldduplex; diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 310ee035067c..9d5b62cb30f7 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1163,7 +1163,7 @@ static void hamachi_tx_timeout(struct net_device *dev) hmp->rx_ring[RX_RING_SIZE-1].status_n_length |= cpu_to_le32(DescEndRing); /* Trigger an immediate transmit demand. */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ hmp->stats.tx_errors++; /* Restart the chip's Tx/Rx processes . */ @@ -1280,7 +1280,7 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev) status=readw(hmp->base + TxStatus); if( !(status & 0x0001) || (status & 0x0002)) writew(0x0001, hmp->base + TxCmd); - return 1; + return NETDEV_TX_BUSY; } /* Caution: the write order is important here, set the field @@ -1364,7 +1364,6 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev) hmp->tx_full = 1; netif_stop_queue(dev); } - dev->trans_start = jiffies; if (hamachi_debug > 4) { printk(KERN_DEBUG "%s: Hamachi transmit frame #%d queued in slot %d.\n", diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index bb78c11559cd..5e4b7afd0683 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -777,7 +777,7 @@ static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev) return 0; } if (bc->skb) - return -1; + return NETDEV_TX_LOCKED; /* strip KISS byte */ if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) { dev_kfree_skb(skb); diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index d509b371a562..5105548ad50c 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -274,7 +274,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) if ((newskb = skb_realloc_headroom(skb, AX25_BPQ_HEADER_LEN)) == NULL) { printk(KERN_WARNING "bpqether: out of memory\n"); kfree_skb(skb); - return -ENOMEM; + return NETDEV_TX_OK; } if (skb->sk != NULL) @@ -294,7 +294,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) if ((dev = bpq_get_ether_dev(dev)) == NULL) { dev->stats.tx_dropped++; kfree_skb(skb); - return -ENODEV; + return NETDEV_TX_OK; } skb->protocol = ax25_type_trans(skb, dev); diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 61de56e45eed..d034f8ca63cb 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -409,7 +409,7 @@ static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev) return 0; } if (sm->skb) - return -1; + return NETDEV_TX_LOCKED; netif_stop_queue(dev); sm->skb = skb; return 0; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 032c0db4c410..fda2fc83e9a1 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -531,7 +531,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev) if (!netif_running(dev)) { printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } if (netif_queue_stopped(dev)) { @@ -541,7 +541,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev) */ if (time_before(jiffies, dev->trans_start + 20 * HZ)) { /* 20 sec timeout not reached */ - return 1; + return NETDEV_TX_BUSY; } printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name, diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index de3f49f991a3..8feda9fe8297 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -2864,7 +2864,7 @@ static int __init hp100_eisa_probe (struct device *gendev) printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name, dev->base_addr); #endif - gendev->driver_data = dev; + dev_set_drvdata(gendev, dev); return 0; out1: free_netdev(dev); @@ -2873,7 +2873,7 @@ static int __init hp100_eisa_probe (struct device *gendev) static int __devexit hp100_eisa_remove (struct device *gendev) { - struct net_device *dev = gendev->driver_data; + struct net_device *dev = dev_get_drvdata(gendev); cleanup_dev(dev); return 0; } diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 2e802634d366..3e3528ade259 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -71,6 +71,19 @@ static struct dio_driver hplance_driver = { .remove = __devexit_p(hplance_remove_one), }; +static const struct net_device_ops hplance_netdev_ops = { + .ndo_open = hplance_open, + .ndo_stop = hplance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = lance_set_multicast, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = lance_poll, +#endif +}; + /* Find all the HP Lance boards and initialise them... */ static int __devinit hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent) @@ -135,13 +148,7 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d) /* Fill the dev fields */ dev->base_addr = va; - dev->open = &hplance_open; - dev->stop = &hplance_close; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = lance_poll; -#endif - dev->hard_start_xmit = &lance_start_xmit; - dev->set_multicast_list = &lance_set_multicast; + dev->netdev_ops = &hplance_netdev_ops; dev->dma = 0; for (i=0; i<6; i++) { diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 806533c831c7..beb84213b671 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -1484,7 +1484,7 @@ static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev) stop_queue: netif_stop_queue(ndev); DBG2(dev, "stopped TX queue" NL); - return 1; + return NETDEV_TX_BUSY; } /* Tx lock BHs */ diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index c25bc0bc0b25..448098d3b39b 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -815,7 +815,7 @@ static int ibmlana_close(struct net_device *dev) static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev) { ibmlana_priv *priv = netdev_priv(dev); - int retval = 0, tmplen, addr; + int tmplen, addr; unsigned long flags; tda_t tda; int baddr; @@ -824,7 +824,6 @@ static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev) the upper layer is in deep desperation and we simply ignore the frame. */ if (priv->txusedcnt >= TXBUFCNT) { - retval = -EIO; dev->stats.tx_dropped++; goto tx_done; } @@ -874,7 +873,7 @@ static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&priv->lock, flags); tx_done: dev_kfree_skb(skb); - return retval; + return NETDEV_TX_OK; } /* switch receiver mode. */ diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 5c6315df86b9..0995c438f286 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1203,6 +1203,20 @@ static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev) return ret; } +static const struct net_device_ops ibmveth_netdev_ops = { + .ndo_open = ibmveth_open, + .ndo_stop = ibmveth_close, + .ndo_start_xmit = ibmveth_start_xmit, + .ndo_set_multicast_list = ibmveth_set_multicast_list, + .ndo_do_ioctl = ibmveth_ioctl, + .ndo_change_mtu = ibmveth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ibmveth_poll_controller, +#endif +}; + static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { int rc, i; @@ -1241,7 +1255,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ return -ENOMEM; adapter = netdev_priv(netdev); - dev->dev.driver_data = netdev; + dev_set_drvdata(&dev->dev, netdev); adapter->vdev = dev; adapter->netdev = netdev; @@ -1265,21 +1279,13 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ memcpy(&adapter->mac_addr, mac_addr_p, 6); netdev->irq = dev->irq; - netdev->open = ibmveth_open; - netdev->stop = ibmveth_close; - netdev->hard_start_xmit = ibmveth_start_xmit; - netdev->set_multicast_list = ibmveth_set_multicast_list; - netdev->do_ioctl = ibmveth_ioctl; - netdev->ethtool_ops = &netdev_ethtool_ops; - netdev->change_mtu = ibmveth_change_mtu; + netdev->netdev_ops = &ibmveth_netdev_ops; + netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = ibmveth_poll_controller; -#endif netdev->features |= NETIF_F_LLTX; spin_lock_init(&adapter->stats_lock); - memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); + memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); for(i = 0; irx_buff_pool[i].kobj; @@ -1335,7 +1341,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ static int __devexit ibmveth_remove(struct vio_dev *dev) { - struct net_device *netdev = dev->dev.driver_data; + struct net_device *netdev = dev_get_drvdata(&dev->dev); struct ibmveth_adapter *adapter = netdev_priv(netdev); int i; @@ -1368,8 +1374,8 @@ static void ibmveth_proc_unregister_driver(void) static int ibmveth_show(struct seq_file *seq, void *v) { struct ibmveth_adapter *adapter = seq->private; - char *current_mac = ((char*) &adapter->netdev->dev_addr); - char *firmware_mac = ((char*) &adapter->mac_addr) ; + char *current_mac = (char *) adapter->netdev->dev_addr; + char *firmware_mac = (char *) &adapter->mac_addr; seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); @@ -1468,8 +1474,8 @@ const char * buf, size_t count) struct ibmveth_buff_pool *pool = container_of(kobj, struct ibmveth_buff_pool, kobj); - struct net_device *netdev = - container_of(kobj->parent, struct device, kobj)->driver_data; + struct net_device *netdev = dev_get_drvdata( + container_of(kobj->parent, struct device, kobj)); struct ibmveth_adapter *adapter = netdev_priv(netdev); long value = simple_strtol(buf, NULL, 10); long rc; diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 60a263001933..96713ef06298 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -156,6 +156,7 @@ static void ifb_setup(struct net_device *dev) dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; random_ether_addr(dev->dev_addr); } diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index eaf977050368..0f16abab2565 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -130,6 +130,7 @@ struct e1000_adv_tx_context_desc { #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ +#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */ /* IPSec Encrypt Enable for ESP */ #define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index ad2d319d0f8b..3bda3db73f1f 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -289,8 +289,9 @@ #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 /* Receive Checksum Control */ +#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ +#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ #define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c index 840782fb5736..ed9058eca45c 100644 --- a/drivers/net/igb/e1000_mbx.c +++ b/drivers/net/igb/e1000_mbx.c @@ -140,13 +140,13 @@ static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; - if (!mbx->ops.check_for_msg) + if (!countdown || !mbx->ops.check_for_msg) goto out; while (mbx->ops.check_for_msg(hw, mbx_id)) { + countdown--; if (!countdown) break; - countdown--; udelay(mbx->usec_delay); } out: @@ -165,13 +165,13 @@ static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; - if (!mbx->ops.check_for_ack) + if (!countdown || !mbx->ops.check_for_ack) goto out; while (mbx->ops.check_for_ack(hw, mbx_id)) { + countdown--; if (!countdown) break; - countdown--; udelay(mbx->usec_delay); } out: diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 3228a862031f..ebe4b616db8a 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -80,7 +80,7 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw); #define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ #define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 #define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0008 +#define IGP01E1000_PSSR_MDIX 0x0800 #define IGP01E1000_PSSR_SPEED_MASK 0xC000 #define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 #define IGP02E1000_PHY_CHANNEL_NUM 4 diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 0bd7728fe469..6e5924511e40 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -142,6 +142,7 @@ enum { #define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ #define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ +#define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) /* Split and Replication RX Control - RW */ /* * Convenience macros diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 4e8464b9df2e..b2c98dea9eed 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -137,11 +137,17 @@ struct igb_buffer { }; }; -struct igb_queue_stats { +struct igb_tx_queue_stats { u64 packets; u64 bytes; }; +struct igb_rx_queue_stats { + u64 packets; + u64 bytes; + u64 drops; +}; + struct igb_ring { struct igb_adapter *adapter; /* backlink */ void *desc; /* descriptor ring memory */ @@ -167,12 +173,13 @@ struct igb_ring { union { /* TX */ struct { - struct igb_queue_stats tx_stats; + struct igb_tx_queue_stats tx_stats; bool detect_tx_hung; }; /* RX */ struct { - struct igb_queue_stats rx_stats; + struct igb_rx_queue_stats rx_stats; + u64 rx_queue_drops; struct napi_struct napi; int set_itr; struct igb_ring *buddy; @@ -238,7 +245,6 @@ struct igb_adapter { u64 hw_csum_err; u64 hw_csum_good; u32 alloc_rx_buff_failed; - bool rx_csum; u32 gorc; u64 gorc_old; u16 rx_ps_hdr_size; @@ -286,6 +292,7 @@ struct igb_adapter { #define IGB_FLAG_DCA_ENABLED (1 << 1) #define IGB_FLAG_QUAD_PORT_A (1 << 2) #define IGB_FLAG_NEED_CTX_IDX (1 << 3) +#define IGB_FLAG_RX_CSUM_DISABLED (1 << 4) enum e1000_state_t { __IGB_TESTING, diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 27eae49e79c2..9598ac09f4b8 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -64,6 +64,7 @@ static const struct igb_stats igb_gstrings_stats[] = { { "rx_crc_errors", IGB_STAT(stats.crcerrs) }, { "rx_frame_errors", IGB_STAT(net_stats.rx_frame_errors) }, { "rx_no_buffer_count", IGB_STAT(stats.rnbc) }, + { "rx_queue_drop_packet_count", IGB_STAT(net_stats.rx_fifo_errors) }, { "rx_missed_errors", IGB_STAT(stats.mpc) }, { "tx_aborted_errors", IGB_STAT(stats.ecol) }, { "tx_carrier_errors", IGB_STAT(stats.tncrs) }, @@ -96,9 +97,10 @@ static const struct igb_stats igb_gstrings_stats[] = { }; #define IGB_QUEUE_STATS_LEN \ - ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues + \ - ((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \ - (sizeof(struct igb_queue_stats) / sizeof(u64))) + (((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues)* \ + (sizeof(struct igb_rx_queue_stats) / sizeof(u64))) + \ + ((((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \ + (sizeof(struct igb_tx_queue_stats) / sizeof(u64)))) #define IGB_GLOBAL_STATS_LEN \ sizeof(igb_gstrings_stats) / sizeof(struct igb_stats) #define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN) @@ -275,13 +277,17 @@ static int igb_set_pauseparam(struct net_device *netdev, static u32 igb_get_rx_csum(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); - return adapter->rx_csum; + return !(adapter->flags & IGB_FLAG_RX_CSUM_DISABLED); } static int igb_set_rx_csum(struct net_device *netdev, u32 data) { struct igb_adapter *adapter = netdev_priv(netdev); - adapter->rx_csum = data; + + if (data) + adapter->flags &= ~IGB_FLAG_RX_CSUM_DISABLED; + else + adapter->flags |= IGB_FLAG_RX_CSUM_DISABLED; return 0; } @@ -293,10 +299,16 @@ static u32 igb_get_tx_csum(struct net_device *netdev) static int igb_set_tx_csum(struct net_device *netdev, u32 data) { - if (data) + struct igb_adapter *adapter = netdev_priv(netdev); + + if (data) { netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + if (adapter->hw.mac.type == e1000_82576) + netdev->features |= NETIF_F_SCTP_CSUM; + } else { + netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SCTP_CSUM); + } return 0; } @@ -1950,7 +1962,8 @@ static void igb_get_ethtool_stats(struct net_device *netdev, { struct igb_adapter *adapter = netdev_priv(netdev); u64 *queue_stat; - int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64); + int stat_count_tx = sizeof(struct igb_tx_queue_stats) / sizeof(u64); + int stat_count_rx = sizeof(struct igb_rx_queue_stats) / sizeof(u64); int j; int i; @@ -1963,14 +1976,14 @@ static void igb_get_ethtool_stats(struct net_device *netdev, for (j = 0; j < adapter->num_tx_queues; j++) { int k; queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats; - for (k = 0; k < stat_count; k++) + for (k = 0; k < stat_count_tx; k++) data[i + k] = queue_stat[k]; i += k; } for (j = 0; j < adapter->num_rx_queues; j++) { int k; queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats; - for (k = 0; k < stat_count; k++) + for (k = 0; k < stat_count_rx; k++) data[i + k] = queue_stat[k]; i += k; } @@ -2004,6 +2017,8 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_drops", i); + p += ETH_GSTRING_LEN; } /* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ break; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e25343588fc7..ea17319624aa 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -942,6 +942,8 @@ int igb_up(struct igb_adapter *adapter) rd32(E1000_ICR); igb_irq_enable(adapter); + netif_tx_start_all_queues(adapter->netdev); + /* Fire a link change interrupt to start the watchdog. */ wr32(E1000_ICS, E1000_ICS_LSC); return 0; @@ -994,6 +996,11 @@ void igb_down(struct igb_adapter *adapter) igb_reset(adapter); igb_clean_all_tx_rings(adapter); igb_clean_all_rx_rings(adapter); +#ifdef CONFIG_IGB_DCA + + /* since we reset the hardware DCA settings were cleared */ + igb_setup_dca(adapter); +#endif } void igb_reinit_locked(struct igb_adapter *adapter) @@ -1343,6 +1350,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + if (adapter->hw.mac.type == e1000_82576) + netdev->features |= NETIF_F_SCTP_CSUM; + adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw); /* before reading the NVM, reset the controller to put the device in a @@ -1390,8 +1400,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, igb_validate_mdi_setting(hw); - adapter->rx_csum = 1; - /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM, * enable the ACPI Magic Packet filter */ @@ -1442,22 +1450,18 @@ static int __devinit igb_probe(struct pci_dev *pdev, * driver. */ igb_get_hw_control(adapter); - /* tell the stack to leave us alone until igb_open() is called */ - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + #ifdef CONFIG_IGB_DCA if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&pdev->dev, "DCA enabled\n"); - /* Always use CB2 mode, difference is masked - * in the CB driver. */ - wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); igb_setup_dca(adapter); } #endif @@ -1699,6 +1703,8 @@ static int igb_open(struct net_device *netdev) if (test_bit(__IGB_TESTING, &adapter->state)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = igb_setup_all_tx_resources(adapter); if (err) @@ -2231,29 +2237,24 @@ static void igb_configure_rx(struct igb_adapter *adapter) mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX | E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); - wr32(E1000_MRQC, mrqc); - - /* Multiqueue and raw packet checksumming are mutually - * exclusive. Note that this not the same as TCP/IP - * checksumming, which works fine. */ - rxcsum = rd32(E1000_RXCSUM); - rxcsum |= E1000_RXCSUM_PCSD; - wr32(E1000_RXCSUM, rxcsum); - } else { + } else if (adapter->vfs_allocated_count) { /* Enable multi-queue for sr-iov */ - if (adapter->vfs_allocated_count) - wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ); - /* Enable Receive Checksum Offload for TCP and UDP */ - rxcsum = rd32(E1000_RXCSUM); - if (adapter->rx_csum) - rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE; - else - rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE); - - wr32(E1000_RXCSUM, rxcsum); + wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ); } + /* Enable Receive Checksum Offload for TCP and UDP */ + rxcsum = rd32(E1000_RXCSUM); + /* Disable raw packet checksumming */ + rxcsum |= E1000_RXCSUM_PCSD; + + if (adapter->hw.mac.type == e1000_82576) + /* Enable Receive Checksum Offload for SCTP */ + rxcsum |= E1000_RXCSUM_CRCOFL; + + /* Don't need to set TUOFL or IPOFL, they default to 1 */ + wr32(E1000_RXCSUM, rxcsum); + /* Set the default pool for the PF's first queue */ igb_configure_vt_default_pool(adapter); @@ -2661,7 +2662,6 @@ static void igb_watchdog_task(struct work_struct *work) } netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); igb_ping_all_vfs(adapter); @@ -2678,7 +2678,6 @@ static void igb_watchdog_task(struct work_struct *work) printk(KERN_INFO "igb: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); igb_ping_all_vfs(adapter); @@ -2712,6 +2711,8 @@ static void igb_watchdog_task(struct work_struct *work) * (Do the reset outside of interrupt context). */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } } @@ -2895,13 +2896,13 @@ static void igb_set_itr(struct igb_adapter *adapter) switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency: - new_itr = 70000; + new_itr = 56; /* aka 70,000 ints/sec */ break; case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ + new_itr = 196; /* aka 20,000 ints/sec */ break; case bulk_latency: - new_itr = 4000; + new_itr = 980; /* aka 4,000 ints/sec */ break; default: break; @@ -2920,7 +2921,8 @@ static void igb_set_itr(struct igb_adapter *adapter) * by adding intermediate steps when interrupt rate is * increasing */ new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : + max((new_itr * adapter->itr) / + (new_itr + (adapter->itr >> 2)), new_itr) : new_itr; /* Don't write the value here; it resets the adapter's * internal timer, and causes us to delay far longer than @@ -2929,7 +2931,7 @@ static void igb_set_itr(struct igb_adapter *adapter) * ends up being correct. */ adapter->itr = new_itr; - adapter->rx_ring->itr_val = 1000000000 / (new_itr * 256); + adapter->rx_ring->itr_val = new_itr; adapter->rx_ring->set_itr = 1; } @@ -3068,11 +3070,15 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; if (ip_hdr(skb)->protocol == IPPROTO_TCP) tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; + else if (ip_hdr(skb)->protocol == IPPROTO_SCTP) + tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; break; case cpu_to_be16(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; + else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP) + tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; break; default: if (unlikely(net_ratelimit())) @@ -3133,8 +3139,7 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter, /* set time_stamp *before* dma to help avoid a possible race */ buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = map[count]; - count++; + buffer_info->dma = skb_shinfo(skb)->dma_head; for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; @@ -3158,7 +3163,7 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter, tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - return count; + return count + 1; } static inline void igb_tx_queue_adv(struct igb_adapter *adapter, @@ -3338,7 +3343,6 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, if (count) { igb_tx_queue_adv(adapter, tx_ring, tx_flags, count, skb->len, hdr_len); - netdev->trans_start = jiffies; /* Make sure there is space in the ring for the next send. */ igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4); } else { @@ -3582,8 +3586,35 @@ void igb_update_stats(struct igb_adapter *adapter) /* Rx Errors */ + if (hw->mac.type != e1000_82575) { + u32 rqdpc_tmp; + u64 rqdpc_total = 0; + int i; + /* Read out drops stats per RX queue. Notice RQDPC (Receive + * Queue Drop Packet Count) stats only gets incremented, if + * the DROP_EN but it set (in the SRRCTL register for that + * queue). If DROP_EN bit is NOT set, then the some what + * equivalent count is stored in RNBC (not per queue basis). + * Also note the drop count is due to lack of available + * descriptors. + */ + for (i = 0; i < adapter->num_rx_queues; i++) { + rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0xFFF; + adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp; + rqdpc_total += adapter->rx_ring[i].rx_stats.drops; + } + adapter->net_stats.rx_fifo_errors = rqdpc_total; + } + + /* Note RNBC (Receive No Buffers Count) is an not an exact + * drop count as the hardware FIFO might save the day. Thats + * one of the reason for saving it in rx_fifo_errors, as its + * potentially not a true drop. + */ + adapter->net_stats.rx_fifo_errors += adapter->stats.rnbc; + /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC */ + * our own version based on RUC and ROC */ adapter->net_stats.rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc + @@ -3767,11 +3798,15 @@ static void igb_update_tx_dca(struct igb_ring *tx_ring) static void igb_setup_dca(struct igb_adapter *adapter) { + struct e1000_hw *hw = &adapter->hw; int i; if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) return; + /* Always use CB2 mode, difference is masked in the CB driver. */ + wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); + for (i = 0; i < adapter->num_tx_queues; i++) { adapter->tx_ring[i].cpu = -1; igb_update_tx_dca(&adapter->tx_ring[i]); @@ -4434,20 +4469,12 @@ static void igb_receive_skb(struct igb_ring *ring, u8 status, bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP)); skb_record_rx_queue(skb, ring->queue_index); - if (skb->ip_summed == CHECKSUM_UNNECESSARY) { - if (vlan_extracted) - vlan_gro_receive(&ring->napi, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.upper.vlan), - skb); - else - napi_gro_receive(&ring->napi, skb); - } else { - if (vlan_extracted) - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.upper.vlan)); - else - netif_receive_skb(skb); - } + if (vlan_extracted) + vlan_gro_receive(&ring->napi, adapter->vlgrp, + le16_to_cpu(rx_desc->wb.upper.vlan), + skb); + else + napi_gro_receive(&ring->napi, skb); } static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, @@ -4456,19 +4483,28 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, skb->ip_summed = CHECKSUM_NONE; /* Ignore Checksum bit is set or checksum is disabled through ethtool */ - if ((status_err & E1000_RXD_STAT_IXSM) || !adapter->rx_csum) + if ((status_err & E1000_RXD_STAT_IXSM) || + (adapter->flags & IGB_FLAG_RX_CSUM_DISABLED)) return; /* TCP/UDP checksum error bit is set */ if (status_err & (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { + /* + * work around errata with sctp packets where the TCPE aka + * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) + * packets, (aka let the stack check the crc32c) + */ + if (!((adapter->hw.mac.type == e1000_82576) && + (skb->len == 60))) + adapter->hw_csum_err++; /* let the stack verify checksum errors */ - adapter->hw_csum_err++; return; } /* It must be a TCP or UDP packet with a valid checksum */ if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) skb->ip_summed = CHECKSUM_UNNECESSARY; + dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err); adapter->hw_csum_good++; } diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index 1dcaa6905312..ee17a097d1ca 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -133,6 +133,24 @@ static int igbvf_set_pauseparam(struct net_device *netdev, return -EOPNOTSUPP; } +static u32 igbvf_get_rx_csum(struct net_device *netdev) +{ + struct igbvf_adapter *adapter = netdev_priv(netdev); + return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED); +} + +static int igbvf_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct igbvf_adapter *adapter = netdev_priv(netdev); + + if (data) + adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED; + else + adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED; + + return 0; +} + static u32 igbvf_get_tx_csum(struct net_device *netdev) { return ((netdev->features & NETIF_F_IP_CSUM) != 0); @@ -150,8 +168,6 @@ static int igbvf_set_tx_csum(struct net_device *netdev, u32 data) static int igbvf_set_tso(struct net_device *netdev, u32 data) { struct igbvf_adapter *adapter = netdev_priv(netdev); - int i; - struct net_device *v_netdev; if (data) { netdev->features |= NETIF_F_TSO; @@ -159,24 +175,10 @@ static int igbvf_set_tso(struct net_device *netdev, u32 data) } else { netdev->features &= ~NETIF_F_TSO; netdev->features &= ~NETIF_F_TSO6; - /* disable TSO on all VLANs if they're present */ - if (!adapter->vlgrp) - goto tso_out; - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { - v_netdev = vlan_group_get_device(adapter->vlgrp, i); - if (!v_netdev) - continue; - - v_netdev->features &= ~NETIF_F_TSO; - v_netdev->features &= ~NETIF_F_TSO6; - vlan_group_set_device(adapter->vlgrp, i, v_netdev); - } } -tso_out: dev_info(&adapter->pdev->dev, "TSO is %s\n", data ? "Enabled" : "Disabled"); - adapter->flags |= FLAG_TSO_FORCE; return 0; } @@ -517,6 +519,8 @@ static const struct ethtool_ops igbvf_ethtool_ops = { .set_ringparam = igbvf_set_ringparam, .get_pauseparam = igbvf_get_pauseparam, .set_pauseparam = igbvf_set_pauseparam, + .get_rx_csum = igbvf_get_rx_csum, + .set_rx_csum = igbvf_set_rx_csum, .get_tx_csum = igbvf_get_tx_csum, .set_tx_csum = igbvf_set_tx_csum, .get_sg = ethtool_op_get_sg, diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index d488733893a6..8e9b67ebbf8b 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -286,11 +286,7 @@ struct igbvf_info { }; /* hardware capability, feature, and workaround flags */ -#define FLAG_HAS_HW_VLAN_FILTER (1 << 0) -#define FLAG_HAS_JUMBO_FRAMES (1 << 1) -#define FLAG_MSI_ENABLED (1 << 2) -#define FLAG_RX_CSUM_ENABLED (1 << 3) -#define FLAG_TSO_FORCE (1 << 4) +#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0) #define IGBVF_RX_DESC_ADV(R, i) \ (&((((R).desc))[i].rx_desc)) diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index b774666ad3cf..22aadb7884fa 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -58,8 +58,7 @@ static void igbvf_reset_interrupt_capability(struct igbvf_adapter *); static struct igbvf_info igbvf_vf_info = { .mac = e1000_vfadapt, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_RX_CSUM_ENABLED, + .flags = 0, .pba = 10, .init_ops = e1000_init_function_pointers_vf, }; @@ -107,8 +106,10 @@ static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, skb->ip_summed = CHECKSUM_NONE; /* Ignore Checksum bit is set or checksum is disabled through ethtool */ - if ((status_err & E1000_RXD_STAT_IXSM)) + if ((status_err & E1000_RXD_STAT_IXSM) || + (adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED)) return; + /* TCP/UDP checksum error bit is set */ if (status_err & (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { @@ -116,6 +117,7 @@ static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, adapter->hw_csum_err++; return; } + /* It must be a TCP or UDP packet with a valid checksum */ if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2117,8 +2119,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, /* set time_stamp *before* dma to help avoid a possible race */ buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = map[count]; - count++; + buffer_info->dma = skb_shinfo(skb)->dma_head; for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; @@ -2142,7 +2143,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - return count; + return count + 1; } static inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter, @@ -2268,7 +2269,6 @@ static int igbvf_xmit_frame_ring_adv(struct sk_buff *skb, if (count) { igbvf_tx_queue_adv(adapter, tx_ring, tx_flags, count, skb->len, hdr_len); - netdev->trans_start = jiffies; /* Make sure there is space in the ring for the next send. */ igbvf_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 4); } else { @@ -2351,15 +2351,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } - /* Jumbo frame size limits */ - if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { - if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - dev_err(&adapter->pdev->dev, - "Jumbo Frames not supported.\n"); - return -EINVAL; - } - } - #define MAX_STD_JUMBO_FRAME_SIZE 9234 if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n"); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index c5593f4665a4..e3cfefab670c 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -530,7 +530,7 @@ static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len) * case where the checksum is right the higher layers will still * drop the packet as appropriate. */ - if (eh->h_proto != ntohs(ETH_P_IP)) + if (eh->h_proto != htons(ETH_P_IP)) return; ih = (struct iphdr *) ((char *)eh + ETH_HLEN); diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index e6317557a531..f76384221422 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -17,6 +17,51 @@ config IRTTY_SIR If unsure, say Y. +config BFIN_SIR + tristate "Blackfin SIR on UART" + depends on BLACKFIN && IRDA + default n + help + Say Y here if your want to enable SIR function on Blackfin UART + devices. + + To activate this driver you can start irattach like: + "irattach irda0 -s" + + Saying M, it will be built as a module named bfin_sir. + + Note that you need to turn off one of the serial drivers for SIR + to use that UART. + +config BFIN_SIR0 + bool "Blackfin SIR on UART0" + depends on BFIN_SIR && !SERIAL_BFIN_UART0 + +config BFIN_SIR1 + bool "Blackfin SIR on UART1" + depends on BFIN_SIR && !SERIAL_BFIN_UART1 && (!BF531 && !BF532 && !BF533 && !BF561) + +config BFIN_SIR2 + bool "Blackfin SIR on UART2" + depends on BFIN_SIR && !SERIAL_BFIN_UART2 && (BF54x || BF538 || BF539) + +config BFIN_SIR3 + bool "Blackfin SIR on UART3" + depends on BFIN_SIR && !SERIAL_BFIN_UART3 && (BF54x) + +choice + prompt "SIR Mode" + depends on BFIN_SIR + default SIR_BFIN_DMA + +config SIR_BFIN_DMA + bool "DMA mode" + depends on !DMA_UNCACHED_NONE + +config SIR_BFIN_PIO + bool "PIO mode" +endchoice + comment "Dongle support" config DONGLE diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 5d20fde32a24..d82e1e3bd8c8 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_MCS_FIR) += mcs7780.o obj-$(CONFIG_AU1000_FIR) += au1k_ir.o # SIR drivers obj-$(CONFIG_IRTTY_SIR) += irtty-sir.o sir-dev.o +obj-$(CONFIG_BFIN_SIR) += bfin_sir.o # dongle drivers for SIR drivers obj-$(CONFIG_ESI_DONGLE) += esi-sir.o obj-$(CONFIG_TEKRAM_DONGLE) += tekram-sir.o diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 941164076a2b..c4361d466597 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -198,6 +199,17 @@ static int au1k_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } +static const struct net_device_ops au1k_irda_netdev_ops = { + .ndo_open = au1k_irda_start, + .ndo_stop = au1k_irda_stop, + .ndo_start_xmit = au1k_irda_hard_xmit, + .ndo_tx_timeout = au1k_tx_timeout, + .ndo_do_ioctl = au1k_irda_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int au1k_irda_net_init(struct net_device *dev) { struct au1k_private *aup = netdev_priv(dev); @@ -209,11 +221,7 @@ static int au1k_irda_net_init(struct net_device *dev) if (err) goto out1; - dev->open = au1k_irda_start; - dev->hard_start_xmit = au1k_irda_hard_xmit; - dev->stop = au1k_irda_stop; - dev->do_ioctl = au1k_irda_ioctl; - dev->tx_timeout = au1k_tx_timeout; + dev->netdev_ops = &au1k_irda_netdev_ops; irda_init_max_qos_capabilies(&aup->qos); @@ -504,13 +512,13 @@ static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) printk(KERN_DEBUG "%s: tx_full\n", dev->name); netif_stop_queue(dev); aup->tx_full = 1; - return 1; + return NETDEV_TX_BUSY; } else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) { printk(KERN_DEBUG "%s: tx_full\n", dev->name); netif_stop_queue(dev); aup->tx_full = 1; - return 1; + return NETDEV_TX_BUSY; } pDB = aup->tx_db_inuse[aup->tx_head]; diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c new file mode 100644 index 000000000000..f3eed6a8fba5 --- /dev/null +++ b/drivers/net/irda/bfin_sir.c @@ -0,0 +1,820 @@ +/* + * Blackfin Infra-red Driver + * + * Copyright 2006-2009 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + * + */ +#include "bfin_sir.h" + +#ifdef CONFIG_SIR_BFIN_DMA +#define DMA_SIR_RX_XCNT 10 +#define DMA_SIR_RX_YCNT (PAGE_SIZE / DMA_SIR_RX_XCNT) +#define DMA_SIR_RX_FLUSH_JIFS (HZ * 4 / 250) +#endif + +#if ANOMALY_05000447 +static int max_rate = 57600; +#else +static int max_rate = 115200; +#endif + +static void turnaround_delay(unsigned long last_jif, int mtt) +{ + long ticks; + + mtt = mtt < 10000 ? 10000 : mtt; + ticks = 1 + mtt / (USEC_PER_SEC / HZ); + schedule_timeout_uninterruptible(ticks); +} + +static void __devinit bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev) +{ + int i; + struct resource *res; + + for (i = 0; i < pdev->num_resources; i++) { + res = &pdev->resource[i]; + switch (res->flags) { + case IORESOURCE_MEM: + sp->membase = (void __iomem *)res->start; + break; + case IORESOURCE_IRQ: + sp->irq = res->start; + break; + case IORESOURCE_DMA: + sp->rx_dma_channel = res->start; + sp->tx_dma_channel = res->end; + break; + default: + break; + } + } + + sp->clk = get_sclk(); +#ifdef CONFIG_SIR_BFIN_DMA + sp->tx_done = 1; + init_timer(&(sp->rx_dma_timer)); +#endif +} + +static void bfin_sir_stop_tx(struct bfin_sir_port *port) +{ +#ifdef CONFIG_SIR_BFIN_DMA + disable_dma(port->tx_dma_channel); +#endif + + while (!(SIR_UART_GET_LSR(port) & THRE)) { + cpu_relax(); + continue; + } + + SIR_UART_STOP_TX(port); +} + +static void bfin_sir_enable_tx(struct bfin_sir_port *port) +{ + SIR_UART_ENABLE_TX(port); +} + +static void bfin_sir_stop_rx(struct bfin_sir_port *port) +{ + SIR_UART_STOP_RX(port); +} + +static void bfin_sir_enable_rx(struct bfin_sir_port *port) +{ + SIR_UART_ENABLE_RX(port); +} + +static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) +{ + int ret = -EINVAL; + unsigned int quot; + unsigned short val, lsr, lcr; + static int utime; + int count = 10; + + lcr = WLS(8); + + switch (speed) { + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + + quot = (port->clk + (8 * speed)) / (16 * speed)\ + - ANOMALY_05000230; + + do { + udelay(utime); + lsr = SIR_UART_GET_LSR(port); + } while (!(lsr & TEMT) && count--); + + /* The useconds for 1 bits to transmit */ + utime = 1000000 / speed + 1; + + /* Clear UCEN bit to reset the UART state machine + * and control registers + */ + val = SIR_UART_GET_GCTL(port); + val &= ~UCEN; + SIR_UART_PUT_GCTL(port, val); + + /* Set DLAB in LCR to Access THR RBR IER */ + SIR_UART_SET_DLAB(port); + SSYNC(); + + SIR_UART_PUT_DLL(port, quot & 0xFF); + SIR_UART_PUT_DLH(port, (quot >> 8) & 0xFF); + SSYNC(); + + /* Clear DLAB in LCR */ + SIR_UART_CLEAR_DLAB(port); + SSYNC(); + + SIR_UART_PUT_LCR(port, lcr); + + val = SIR_UART_GET_GCTL(port); + val |= UCEN; + SIR_UART_PUT_GCTL(port, val); + + ret = 0; + break; + default: + printk(KERN_WARNING "bfin_sir: Invalid speed %d\n", speed); + break; + } + + val = SIR_UART_GET_GCTL(port); + /* If not add the 'RPOLC', we can't catch the receive interrupt. + * It's related with the HW layout and the IR transiver. + */ + val |= IREN | RPOLC; + SIR_UART_PUT_GCTL(port, val); + return ret; +} + +static int bfin_sir_is_receiving(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + + if (!(SIR_UART_GET_IER(port) & ERBFI)) + return 0; + return self->rx_buff.state != OUTSIDE_FRAME; +} + +#ifdef CONFIG_SIR_BFIN_PIO +static void bfin_sir_tx_chars(struct net_device *dev) +{ + unsigned int chr; + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + + if (self->tx_buff.len != 0) { + chr = *(self->tx_buff.data); + SIR_UART_PUT_CHAR(port, chr); + self->tx_buff.data++; + self->tx_buff.len--; + } else { + self->stats.tx_packets++; + self->stats.tx_bytes += self->tx_buff.data - self->tx_buff.head; + if (self->newspeed) { + bfin_sir_set_speed(port, self->newspeed); + self->speed = self->newspeed; + self->newspeed = 0; + } + bfin_sir_stop_tx(port); + bfin_sir_enable_rx(port); + /* I'm hungry! */ + netif_wake_queue(dev); + } +} + +static void bfin_sir_rx_chars(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + unsigned char ch; + + SIR_UART_CLEAR_LSR(port); + ch = SIR_UART_GET_CHAR(port); + async_unwrap_char(dev, &self->stats, &self->rx_buff, ch); + dev->last_rx = jiffies; +} + +static irqreturn_t bfin_sir_rx_int(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + + spin_lock(&self->lock); + while ((SIR_UART_GET_LSR(port) & DR)) + bfin_sir_rx_chars(dev); + spin_unlock(&self->lock); + + return IRQ_HANDLED; +} + +static irqreturn_t bfin_sir_tx_int(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + + spin_lock(&self->lock); + if (SIR_UART_GET_LSR(port) & THRE) + bfin_sir_tx_chars(dev); + spin_unlock(&self->lock); + + return IRQ_HANDLED; +} +#endif /* CONFIG_SIR_BFIN_PIO */ + +#ifdef CONFIG_SIR_BFIN_DMA +static void bfin_sir_dma_tx_chars(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + + if (!port->tx_done) + return; + port->tx_done = 0; + + if (self->tx_buff.len == 0) { + self->stats.tx_packets++; + if (self->newspeed) { + bfin_sir_set_speed(port, self->newspeed); + self->speed = self->newspeed; + self->newspeed = 0; + } + bfin_sir_enable_rx(port); + port->tx_done = 1; + netif_wake_queue(dev); + return; + } + + blackfin_dcache_flush_range((unsigned long)(self->tx_buff.data), + (unsigned long)(self->tx_buff.data+self->tx_buff.len)); + set_dma_config(port->tx_dma_channel, + set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, + INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, + DMA_SYNC_RESTART)); + set_dma_start_addr(port->tx_dma_channel, + (unsigned long)(self->tx_buff.data)); + set_dma_x_count(port->tx_dma_channel, self->tx_buff.len); + set_dma_x_modify(port->tx_dma_channel, 1); + enable_dma(port->tx_dma_channel); +} + +static irqreturn_t bfin_sir_dma_tx_int(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + + spin_lock(&self->lock); + if (!(get_dma_curr_irqstat(port->tx_dma_channel) & DMA_RUN)) { + clear_dma_irqstat(port->tx_dma_channel); + bfin_sir_stop_tx(port); + + self->stats.tx_packets++; + self->stats.tx_bytes += self->tx_buff.len; + self->tx_buff.len = 0; + if (self->newspeed) { + bfin_sir_set_speed(port, self->newspeed); + self->speed = self->newspeed; + self->newspeed = 0; + } + bfin_sir_enable_rx(port); + /* I'm hungry! */ + netif_wake_queue(dev); + port->tx_done = 1; + } + spin_unlock(&self->lock); + + return IRQ_HANDLED; +} + +static void bfin_sir_dma_rx_chars(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + int i; + + SIR_UART_CLEAR_LSR(port); + + for (i = port->rx_dma_buf.head; i < port->rx_dma_buf.tail; i++) + async_unwrap_char(dev, &self->stats, &self->rx_buff, port->rx_dma_buf.buf[i]); +} + +void bfin_sir_rx_dma_timeout(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + int x_pos, pos; + unsigned long flags; + + spin_lock_irqsave(&self->lock, flags); + x_pos = DMA_SIR_RX_XCNT - get_dma_curr_xcount(port->rx_dma_channel); + if (x_pos == DMA_SIR_RX_XCNT) + x_pos = 0; + + pos = port->rx_dma_nrows * DMA_SIR_RX_XCNT + x_pos; + + if (pos > port->rx_dma_buf.tail) { + port->rx_dma_buf.tail = pos; + bfin_sir_dma_rx_chars(dev); + port->rx_dma_buf.head = port->rx_dma_buf.tail; + } + spin_unlock_irqrestore(&self->lock, flags); +} + +static irqreturn_t bfin_sir_dma_rx_int(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + unsigned short irqstat; + + spin_lock(&self->lock); + + port->rx_dma_nrows++; + port->rx_dma_buf.tail = DMA_SIR_RX_XCNT * port->rx_dma_nrows; + bfin_sir_dma_rx_chars(dev); + if (port->rx_dma_nrows >= DMA_SIR_RX_YCNT) { + port->rx_dma_nrows = 0; + port->rx_dma_buf.tail = 0; + } + port->rx_dma_buf.head = port->rx_dma_buf.tail; + + irqstat = get_dma_curr_irqstat(port->rx_dma_channel); + clear_dma_irqstat(port->rx_dma_channel); + spin_unlock(&self->lock); + + mod_timer(&port->rx_dma_timer, jiffies + DMA_SIR_RX_FLUSH_JIFS); + return IRQ_HANDLED; +} +#endif /* CONFIG_SIR_BFIN_DMA */ + +static int bfin_sir_startup(struct bfin_sir_port *port, struct net_device *dev) +{ +#ifdef CONFIG_SIR_BFIN_DMA + dma_addr_t dma_handle; +#endif /* CONFIG_SIR_BFIN_DMA */ + + if (request_dma(port->rx_dma_channel, "BFIN_UART_RX") < 0) { + dev_warn(&dev->dev, "Unable to attach SIR RX DMA channel\n"); + return -EBUSY; + } + + if (request_dma(port->tx_dma_channel, "BFIN_UART_TX") < 0) { + dev_warn(&dev->dev, "Unable to attach SIR TX DMA channel\n"); + free_dma(port->rx_dma_channel); + return -EBUSY; + } + +#ifdef CONFIG_SIR_BFIN_DMA + + set_dma_callback(port->rx_dma_channel, bfin_sir_dma_rx_int, dev); + set_dma_callback(port->tx_dma_channel, bfin_sir_dma_tx_int, dev); + + port->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA); + port->rx_dma_buf.head = 0; + port->rx_dma_buf.tail = 0; + port->rx_dma_nrows = 0; + + set_dma_config(port->rx_dma_channel, + set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO, + INTR_ON_ROW, DIMENSION_2D, + DATA_SIZE_8, DMA_SYNC_RESTART)); + set_dma_x_count(port->rx_dma_channel, DMA_SIR_RX_XCNT); + set_dma_x_modify(port->rx_dma_channel, 1); + set_dma_y_count(port->rx_dma_channel, DMA_SIR_RX_YCNT); + set_dma_y_modify(port->rx_dma_channel, 1); + set_dma_start_addr(port->rx_dma_channel, (unsigned long)port->rx_dma_buf.buf); + enable_dma(port->rx_dma_channel); + + port->rx_dma_timer.data = (unsigned long)(dev); + port->rx_dma_timer.function = (void *)bfin_sir_rx_dma_timeout; + +#else + + if (request_irq(port->irq, bfin_sir_rx_int, IRQF_DISABLED, "BFIN_SIR_RX", dev)) { + dev_warn(&dev->dev, "Unable to attach SIR RX interrupt\n"); + return -EBUSY; + } + + if (request_irq(port->irq+1, bfin_sir_tx_int, IRQF_DISABLED, "BFIN_SIR_TX", dev)) { + dev_warn(&dev->dev, "Unable to attach SIR TX interrupt\n"); + free_irq(port->irq, dev); + return -EBUSY; + } +#endif + + return 0; +} + +static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev) +{ + unsigned short val; + + bfin_sir_stop_rx(port); + SIR_UART_DISABLE_INTS(port); + + val = SIR_UART_GET_GCTL(port); + val &= ~(UCEN | IREN | RPOLC); + SIR_UART_PUT_GCTL(port, val); + +#ifdef CONFIG_SIR_BFIN_DMA + disable_dma(port->tx_dma_channel); + disable_dma(port->rx_dma_channel); + del_timer(&(port->rx_dma_timer)); + dma_free_coherent(NULL, PAGE_SIZE, port->rx_dma_buf.buf, 0); +#else + free_irq(port->irq+1, dev); + free_irq(port->irq, dev); +#endif + free_dma(port->tx_dma_channel); + free_dma(port->rx_dma_channel); +} + +#ifdef CONFIG_PM +static int bfin_sir_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct bfin_sir_port *sir_port; + struct net_device *dev; + struct bfin_sir_self *self; + + sir_port = platform_get_drvdata(pdev); + if (!sir_port) + return 0; + + dev = sir_port->dev; + self = netdev_priv(dev); + if (self->open) { + flush_work(&self->work); + bfin_sir_shutdown(self->sir_port, dev); + netif_device_detach(dev); + } + + return 0; +} +static int bfin_sir_resume(struct platform_device *pdev) +{ + struct bfin_sir_port *sir_port; + struct net_device *dev; + struct bfin_sir_self *self; + struct bfin_sir_port *port; + + sir_port = platform_get_drvdata(pdev); + if (!sir_port) + return 0; + + dev = sir_port->dev; + self = netdev_priv(dev); + port = self->sir_port; + if (self->open) { + if (self->newspeed) { + self->speed = self->newspeed; + self->newspeed = 0; + } + bfin_sir_startup(port, dev); + bfin_sir_set_speed(port, 9600); + bfin_sir_enable_rx(port); + netif_device_attach(dev); + } + return 0; +} +#else +#define bfin_sir_suspend NULL +#define bfin_sir_resume NULL +#endif + +static void bfin_sir_send_work(struct work_struct *work) +{ + struct bfin_sir_self *self = container_of(work, struct bfin_sir_self, work); + struct net_device *dev = self->sir_port->dev; + struct bfin_sir_port *port = self->sir_port; + unsigned short val; + int tx_cnt = 10; + + while (bfin_sir_is_receiving(dev) && --tx_cnt) + turnaround_delay(dev->last_rx, self->mtt); + + bfin_sir_stop_rx(port); + + /* To avoid losting RX interrupt, we reset IR function before + * sending data. We also can set the speed, which will + * reset all the UART. + */ + val = SIR_UART_GET_GCTL(port); + val &= ~(IREN | RPOLC); + SIR_UART_PUT_GCTL(port, val); + SSYNC(); + val |= IREN | RPOLC; + SIR_UART_PUT_GCTL(port, val); + SSYNC(); + /* bfin_sir_set_speed(port, self->speed); */ + +#ifdef CONFIG_SIR_BFIN_DMA + bfin_sir_dma_tx_chars(dev); +#endif + bfin_sir_enable_tx(port); + dev->trans_start = jiffies; +} + +static int bfin_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + int speed = irda_get_next_speed(skb); + + netif_stop_queue(dev); + + self->mtt = irda_get_mtt(skb); + + if (speed != self->speed && speed != -1) + self->newspeed = speed; + + self->tx_buff.data = self->tx_buff.head; + if (skb->len == 0) + self->tx_buff.len = 0; + else + self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, self->tx_buff.truesize); + + schedule_work(&self->work); + dev_kfree_skb(skb); + + return 0; +} + +static int bfin_sir_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) +{ + struct if_irda_req *rq = (struct if_irda_req *)ifreq; + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + int ret = 0; + + switch (cmd) { + case SIOCSBANDWIDTH: + if (capable(CAP_NET_ADMIN)) { + if (self->open) { + ret = bfin_sir_set_speed(port, rq->ifr_baudrate); + bfin_sir_enable_rx(port); + } else { + dev_warn(&dev->dev, "SIOCSBANDWIDTH: !netif_running\n"); + ret = 0; + } + } + break; + + case SIOCSMEDIABUSY: + ret = -EPERM; + if (capable(CAP_NET_ADMIN)) { + irda_device_set_media_busy(dev, TRUE); + ret = 0; + } + break; + + case SIOCGRECEIVING: + rq->ifr_receiving = bfin_sir_is_receiving(dev); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static struct net_device_stats *bfin_sir_stats(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + + return &self->stats; +} + +static int bfin_sir_open(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + struct bfin_sir_port *port = self->sir_port; + int err = -ENOMEM; + + self->newspeed = 0; + self->speed = 9600; + + spin_lock_init(&self->lock); + + err = bfin_sir_startup(port, dev); + if (err) + goto err_startup; + + bfin_sir_set_speed(port, 9600); + + self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME); + if (!self->irlap) + goto err_irlap; + + INIT_WORK(&self->work, bfin_sir_send_work); + + /* + * Now enable the interrupt then start the queue + */ + self->open = 1; + bfin_sir_enable_rx(port); + + netif_start_queue(dev); + + return 0; + +err_irlap: + self->open = 0; + bfin_sir_shutdown(port, dev); +err_startup: + return err; +} + +static int bfin_sir_stop(struct net_device *dev) +{ + struct bfin_sir_self *self = netdev_priv(dev); + + flush_work(&self->work); + bfin_sir_shutdown(self->sir_port, dev); + + if (self->rxskb) { + dev_kfree_skb(self->rxskb); + self->rxskb = NULL; + } + + /* Stop IrLAP */ + if (self->irlap) { + irlap_close(self->irlap); + self->irlap = NULL; + } + + netif_stop_queue(dev); + self->open = 0; + + return 0; +} + +static int bfin_sir_init_iobuf(iobuff_t *io, int size) +{ + io->head = kmalloc(size, GFP_KERNEL); + if (!io->head) + return -ENOMEM; + io->truesize = size; + io->in_frame = FALSE; + io->state = OUTSIDE_FRAME; + io->data = io->head; + return 0; +} + +static int __devinit bfin_sir_probe(struct platform_device *pdev) +{ + struct net_device *dev; + struct bfin_sir_self *self; + unsigned int baudrate_mask; + struct bfin_sir_port *sir_port; + int err; + + if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(per) && \ + per[pdev->id][3] == pdev->id) { + err = peripheral_request_list(per[pdev->id], DRIVER_NAME); + if (err) + return err; + } else { + dev_err(&pdev->dev, "Invalid pdev id, please check board file\n"); + return -ENODEV; + } + + err = -ENOMEM; + sir_port = kmalloc(sizeof(*sir_port), GFP_KERNEL); + if (!sir_port) + goto err_mem_0; + + bfin_sir_init_ports(sir_port, pdev); + + dev = alloc_irdadev(sizeof(*self)); + if (!dev) + goto err_mem_1; + + self = netdev_priv(dev); + self->dev = &pdev->dev; + self->sir_port = sir_port; + sir_port->dev = dev; + + err = bfin_sir_init_iobuf(&self->rx_buff, IRDA_SKB_MAX_MTU); + if (err) + goto err_mem_2; + err = bfin_sir_init_iobuf(&self->tx_buff, IRDA_SIR_MAX_FRAME); + if (err) + goto err_mem_3; + + dev->hard_start_xmit = bfin_sir_hard_xmit; + dev->open = bfin_sir_open; + dev->stop = bfin_sir_stop; + dev->do_ioctl = bfin_sir_ioctl; + dev->get_stats = bfin_sir_stats; + dev->irq = sir_port->irq; + + irda_init_max_qos_capabilies(&self->qos); + + baudrate_mask = IR_9600; + + switch (max_rate) { + case 115200: + baudrate_mask |= IR_115200; + case 57600: + baudrate_mask |= IR_57600; + case 38400: + baudrate_mask |= IR_38400; + case 19200: + baudrate_mask |= IR_19200; + case 9600: + break; + default: + dev_warn(&pdev->dev, "Invalid maximum baud rate, using 9600\n"); + } + + self->qos.baud_rate.bits &= baudrate_mask; + + self->qos.min_turn_time.bits = 1; /* 10 ms or more */ + + irda_qos_bits_to_value(&self->qos); + + err = register_netdev(dev); + + if (err) { + kfree(self->tx_buff.head); +err_mem_3: + kfree(self->rx_buff.head); +err_mem_2: + free_netdev(dev); +err_mem_1: + kfree(sir_port); +err_mem_0: + peripheral_free_list(per[pdev->id]); + } else + platform_set_drvdata(pdev, sir_port); + + return err; +} + +static int __devexit bfin_sir_remove(struct platform_device *pdev) +{ + struct bfin_sir_port *sir_port; + struct net_device *dev = NULL; + struct bfin_sir_self *self; + + sir_port = platform_get_drvdata(pdev); + if (!sir_port) + return 0; + dev = sir_port->dev; + self = netdev_priv(dev); + unregister_netdev(dev); + kfree(self->tx_buff.head); + kfree(self->rx_buff.head); + free_netdev(dev); + kfree(sir_port); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver bfin_ir_driver = { + .probe = bfin_sir_probe, + .remove = __devexit_p(bfin_sir_remove), + .suspend = bfin_sir_suspend, + .resume = bfin_sir_resume, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init bfin_sir_init(void) +{ + return platform_driver_register(&bfin_ir_driver); +} + +static void __exit bfin_sir_exit(void) +{ + platform_driver_unregister(&bfin_ir_driver); +} + +module_init(bfin_sir_init); +module_exit(bfin_sir_exit); + +module_param(max_rate, int, 0); +MODULE_PARM_DESC(max_rate, "Maximum baud rate (115200, 57600, 38400, 19200, 9600)"); + +MODULE_AUTHOR("Graf Yang "); +MODULE_DESCRIPTION("Blackfin IrDA driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/bfin_sir.h b/drivers/net/irda/bfin_sir.h new file mode 100644 index 000000000000..dac71b1f4f9b --- /dev/null +++ b/drivers/net/irda/bfin_sir.h @@ -0,0 +1,148 @@ +/* + * Blackfin Infra-red Driver + * + * Copyright 2006-2009 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_SIR_BFIN_DMA +struct dma_rx_buf { + char *buf; + int head; + int tail; +}; +#endif + +struct bfin_sir_port { + unsigned char __iomem *membase; + unsigned int irq; + unsigned int lsr; + unsigned long clk; + struct net_device *dev; +#ifdef CONFIG_SIR_BFIN_DMA + int tx_done; + struct dma_rx_buf rx_dma_buf; + struct timer_list rx_dma_timer; + int rx_dma_nrows; +#endif + unsigned int tx_dma_channel; + unsigned int rx_dma_channel; +}; + +struct bfin_sir_port_res { + unsigned long base_addr; + int irq; + unsigned int rx_dma_channel; + unsigned int tx_dma_channel; +}; + +struct bfin_sir_self { + struct bfin_sir_port *sir_port; + spinlock_t lock; + unsigned int open; + int speed; + int newspeed; + + struct sk_buff *txskb; + struct sk_buff *rxskb; + struct net_device_stats stats; + struct device *dev; + struct irlap_cb *irlap; + struct qos_info qos; + + iobuff_t tx_buff; + iobuff_t rx_buff; + + struct work_struct work; + int mtt; +}; + +#define DRIVER_NAME "bfin_sir" + +#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR) +#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL) +#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH) +#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR) +#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL) + +#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v) +#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v) +#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v) +#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v) +#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v) + +#ifdef CONFIG_BF54x +#define SIR_UART_GET_LSR(port) bfin_read16((port)->membase + OFFSET_LSR) +#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER_SET) +#define SIR_UART_SET_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_SET), v) +#define SIR_UART_CLEAR_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v) +#define SIR_UART_PUT_LSR(port, v) bfin_write16(((port)->membase + OFFSET_LSR), v) +#define SIR_UART_CLEAR_LSR(port) bfin_write16(((port)->membase + OFFSET_LSR), -1) + +#define SIR_UART_SET_DLAB(port) +#define SIR_UART_CLEAR_DLAB(port) + +#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_SET_IER(port, v) +#define SIR_UART_DISABLE_INTS(port) SIR_UART_CLEAR_IER(port, 0xF) +#define SIR_UART_STOP_TX(port) do { SIR_UART_PUT_LSR(port, TFI); SIR_UART_CLEAR_IER(port, ETBEI); } while (0) +#define SIR_UART_ENABLE_TX(port) do { SIR_UART_SET_IER(port, ETBEI); } while (0) +#define SIR_UART_STOP_RX(port) do { SIR_UART_CLEAR_IER(port, ERBFI); } while (0) +#define SIR_UART_ENABLE_RX(port) do { SIR_UART_SET_IER(port, ERBFI); } while (0) +#else + +#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR) +#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER) +#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v) + +#define SIR_UART_SET_DLAB(port) do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) | DLAB); } while (0) +#define SIR_UART_CLEAR_DLAB(port) do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) & ~DLAB); } while (0) + +#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_PUT_IER(port, v) +#define SIR_UART_DISABLE_INTS(port) SIR_UART_PUT_IER(port, 0) +#define SIR_UART_STOP_TX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ETBEI); } while (0) +#define SIR_UART_ENABLE_TX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ETBEI); } while (0) +#define SIR_UART_STOP_RX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ERBFI); } while (0) +#define SIR_UART_ENABLE_RX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ERBFI); } while (0) + +static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port) +{ + unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR); + port->lsr |= (lsr & (BI|FE|PE|OE)); + return lsr | port->lsr; +} + +static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port) +{ + port->lsr = 0; + bfin_read16(port->membase + OFFSET_LSR); +} +#endif + +static const unsigned short per[][4] = { + /* rx pin tx pin NULL uart_number */ + {P_UART0_RX, P_UART0_TX, 0, 0}, + {P_UART1_RX, P_UART1_TX, 0, 1}, + {P_UART2_RX, P_UART2_TX, 0, 2}, + {P_UART3_RX, P_UART3_TX, 0, 3}, +}; diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 6b6548b9fda0..9a0346e751ac 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -994,11 +994,11 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) /* change speed pending, wait for its execution */ if (self->new_speed) - return -EBUSY; + return NETDEV_TX_BUSY; /* device stopped (apm) wait for restart */ if (self->stopped) - return -EBUSY; + return NETDEV_TX_BUSY; toshoboe_checkstuck (self); @@ -1049,7 +1049,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) if (self->txpending) { spin_unlock_irqrestore(&self->spinlock, flags); - return -EBUSY; + return NETDEV_TX_BUSY; } /* If in SIR mode we need to generate a string of XBOFs */ @@ -1105,7 +1105,7 @@ dumpbufs(skb->data,skb->len,'>'); ,skb->len, self->ring->tx[self->txs].control, self->txpending); toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); spin_unlock_irqrestore(&self->spinlock, flags); - return -EBUSY; + return NETDEV_TX_BUSY; } if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 006ba23110db..0c0831c03f64 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -389,7 +389,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) s32 speed; s16 xbofs; int res, mtt; - int err = 1; /* Failed */ IRDA_DEBUG(4, "%s() on %s\n", __func__, netdev->name); @@ -430,7 +429,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) irda_usb_change_speed_xbofs(self); netdev->trans_start = jiffies; /* Will netif_wake_queue() in callback */ - err = 0; /* No error */ goto drop; } } @@ -542,7 +540,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) /* Drop silently the skb and exit */ dev_kfree_skb(skb); spin_unlock_irqrestore(&self->lock, flags); - return err; /* Usually 1 */ + return NETDEV_TX_OK; } /*------------------------------------------------------------------*/ @@ -1859,6 +1857,42 @@ static void irda_usb_disconnect(struct usb_interface *intf) IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __func__); } +#ifdef CONFIG_PM +/* USB suspend, so power off the transmitter/receiver */ +static int irda_usb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct irda_usb_cb *self = usb_get_intfdata(intf); + int i; + + netif_device_detach(self->netdev); + + if (self->tx_urb != NULL) + usb_kill_urb(self->tx_urb); + if (self->speed_urb != NULL) + usb_kill_urb(self->speed_urb); + for (i = 0; i < self->max_rx_urb; i++) { + if (self->rx_urb[i] != NULL) + usb_kill_urb(self->rx_urb[i]); + } + return 0; +} + +/* Coming out of suspend, so reset hardware */ +static int irda_usb_resume(struct usb_interface *intf) +{ + struct irda_usb_cb *self = usb_get_intfdata(intf); + int i; + + for (i = 0; i < self->max_rx_urb; i++) { + if (self->rx_urb[i] != NULL) + usb_submit_urb(self->rx_urb[i], GFP_KERNEL); + } + + netif_device_attach(self->netdev); + return 0; +} +#endif + /*------------------------------------------------------------------*/ /* * USB device callbacks @@ -1868,6 +1902,10 @@ static struct usb_driver irda_driver = { .probe = irda_usb_probe, .disconnect = irda_usb_disconnect, .id_table = dongles, +#ifdef CONFIG_PM + .suspend = irda_usb_suspend, + .resume = irda_usb_resume, +#endif }; /************************* MODULE CALLBACKS *************************/ diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c index 9d813bc4502e..c3e4e2c435ba 100644 --- a/drivers/net/irda/kingsun-sir.c +++ b/drivers/net/irda/kingsun-sir.c @@ -156,9 +156,6 @@ static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev) int wraplen; int ret = 0; - if (skb == NULL || netdev == NULL) - return -EINVAL; - netif_stop_queue(netdev); /* the IRDA wrapping routines don't deal with non linear skb */ @@ -197,7 +194,7 @@ static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev) dev_kfree_skb(skb); spin_unlock(&kingsun->lock); - return ret; + return NETDEV_TX_OK; } /* Receive callback function */ diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index b6ffe9715b61..d73b8b64fcb9 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -391,9 +391,6 @@ static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev) unsigned int wraplen; int ret = 0; - if (skb == NULL || netdev == NULL) - return -EINVAL; - netif_stop_queue(netdev); /* the IRDA wrapping routines don't deal with non linear skb */ @@ -428,7 +425,7 @@ static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev) dev_kfree_skb(skb); spin_unlock(&kingsun->lock); - return ret; + return NETDEV_TX_OK; } /* Receive callback function */ diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 64df27f2bfd4..1ef45ec74422 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -304,9 +304,6 @@ static int ksdazzle_hard_xmit(struct sk_buff *skb, struct net_device *netdev) unsigned int wraplen; int ret = 0; - if (skb == NULL || netdev == NULL) - return -EINVAL; - netif_stop_queue(netdev); /* the IRDA wrapping routines don't deal with non linear skb */ @@ -341,7 +338,7 @@ static int ksdazzle_hard_xmit(struct sk_buff *skb, struct net_device *netdev) dev_kfree_skb(skb); spin_unlock(&kingsun->lock); - return ret; + return NETDEV_TX_OK; } /* Receive callback function */ diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index fac504d0cfd8..f4df1001983c 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -824,10 +824,6 @@ static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev) int wraplen; int ret = 0; - - if (skb == NULL || ndev == NULL) - return -EINVAL; - netif_stop_queue(ndev); mcs = netdev_priv(ndev); @@ -870,7 +866,7 @@ static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev) dev_kfree_skb(skb); spin_unlock_irqrestore(&mcs->lock, flags); - return ret; + return NETDEV_TX_OK; } static const struct net_device_ops mcs_netdev_ops = { diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index e775338b525f..3376a4f39e0a 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -14,6 +14,7 @@ */ #include #include +#include #include #include @@ -797,6 +798,16 @@ static int pxa_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } +static const struct net_device_ops pxa_irda_netdev_ops = { + .ndo_open = pxa_irda_start, + .ndo_stop = pxa_irda_stop, + .ndo_start_xmit = pxa_irda_hard_xmit, + .ndo_do_ioctl = pxa_irda_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int pxa_irda_probe(struct platform_device *pdev) { struct net_device *dev; @@ -845,10 +856,7 @@ static int pxa_irda_probe(struct platform_device *pdev) if (err) goto err_startup; - dev->hard_start_xmit = pxa_irda_hard_xmit; - dev->open = pxa_irda_start; - dev->stop = pxa_irda_stop; - dev->do_ioctl = pxa_irda_ioctl; + dev->netdev_ops = &pxa_irda_netdev_ops; irda_init_max_qos_capabilies(&si->qos); diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 7a2b003954ca..2aeb2e6aec1b 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -875,6 +876,16 @@ static int sa1100_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } +static const struct net_device_ops sa1100_irda_netdev_ops = { + .ndo_open = sa1100_irda_start, + .ndo_stop = sa1100_irda_stop, + .ndo_start_xmit = sa1100_irda_hard_xmit, + .ndo_do_ioctl = sa1100_irda_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int sa1100_irda_probe(struct platform_device *pdev) { struct net_device *dev; @@ -913,11 +924,8 @@ static int sa1100_irda_probe(struct platform_device *pdev) if (err) goto err_mem_5; - dev->hard_start_xmit = sa1100_irda_hard_xmit; - dev->open = sa1100_irda_start; - dev->stop = sa1100_irda_stop; - dev->do_ioctl = sa1100_irda_ioctl; - dev->irq = IRQ_Ser2ICP; + dev->netdev_ops = &sa1100_irda_netdev_ops; + dev->irq = IRQ_Ser2ICP; irda_init_max_qos_capabilies(&si->qos); diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index d940809762ec..fd0796c3db3c 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -607,7 +607,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev) * stopped so the network layer will retry after the * fsm completes and wakes the queue. */ - return 1; + return NETDEV_TX_BUSY; } else if (unlikely(err)) { /* other fatal error - forget the speed change and diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 59d79807b4d5..d0797adb5f8e 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -2124,7 +2124,7 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self) while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT)) udelay(1); - if (count == 0) + if (count < 0) IRDA_DEBUG(0, "%s(): stuck transmitter\n", __func__); } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index cb793c2bade2..e44215cb1882 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1021,6 +1021,16 @@ static const struct ethtool_ops ops = { .get_link = veth_get_link, }; +static const struct net_device_ops veth_netdev_ops = { + .ndo_open = veth_open, + .ndo_stop = veth_close, + .ndo_start_xmit = veth_start_xmit, + .ndo_change_mtu = veth_change_mtu, + .ndo_set_multicast_list = veth_set_multicast_list, + .ndo_set_mac_address = NULL, + .ndo_validate_addr = eth_validate_addr, +}; + static struct net_device *veth_probe_one(int vlan, struct vio_dev *vio_dev) { @@ -1067,12 +1077,7 @@ static struct net_device *veth_probe_one(int vlan, memcpy(&port->mac_addr, mac_addr, ETH_ALEN); - dev->open = veth_open; - dev->hard_start_xmit = veth_start_xmit; - dev->stop = veth_close; - dev->change_mtu = veth_change_mtu; - dev->set_mac_address = NULL; - dev->set_multicast_list = veth_set_multicast_list; + dev->netdev_ops = &veth_netdev_ops; SET_ETHTOOL_OPS(dev, &ops); SET_NETDEV_DEV(dev, vdev); diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c index 11dcda0f453e..ff67a84e6802 100644 --- a/drivers/net/ixgb/ixgb_hw.c +++ b/drivers/net/ixgb/ixgb_hw.c @@ -192,7 +192,7 @@ ixgb_identify_xpak_vendor(struct ixgb_hw *hw) vendor_name[i] = ixgb_read_phy_reg(hw, MDIO_PMA_PMD_XPAK_VENDOR_NAME + i, IXGB_PHY_ADDRESS, - MDIO_PMA_PMD_DID); + MDIO_MMD_PMAPMD); } /* Determine the actual vendor */ @@ -1225,15 +1225,15 @@ ixgb_optics_reset(struct ixgb_hw *hw) u16 mdio_reg; ixgb_write_phy_reg(hw, - MDIO_PMA_PMD_CR1, - IXGB_PHY_ADDRESS, - MDIO_PMA_PMD_DID, - MDIO_PMA_PMD_CR1_RESET); + MDIO_CTRL1, + IXGB_PHY_ADDRESS, + MDIO_MMD_PMAPMD, + MDIO_CTRL1_RESET); - mdio_reg = ixgb_read_phy_reg( hw, - MDIO_PMA_PMD_CR1, - IXGB_PHY_ADDRESS, - MDIO_PMA_PMD_DID); + mdio_reg = ixgb_read_phy_reg(hw, + MDIO_CTRL1, + IXGB_PHY_ADDRESS, + MDIO_MMD_PMAPMD); } return; diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h index 831fe0c58b2b..af6ca3aab5ad 100644 --- a/drivers/net/ixgb/ixgb_hw.h +++ b/drivers/net/ixgb/ixgb_hw.h @@ -29,6 +29,8 @@ #ifndef _IXGB_HW_H_ #define _IXGB_HW_H_ +#include + #include "ixgb_osdep.h" /* Enums */ @@ -507,18 +509,6 @@ typedef enum { /* Definitions for the optics devices on the MDIO bus. */ #define IXGB_PHY_ADDRESS 0x0 /* Single PHY, multiple "Devices" */ -/* Standard five-bit Device IDs. See IEEE 802.3ae, clause 45 */ -#define MDIO_PMA_PMD_DID 0x01 -#define MDIO_WIS_DID 0x02 -#define MDIO_PCS_DID 0x03 -#define MDIO_XGXS_DID 0x04 - -/* Standard PMA/PMD registers and bit definitions. */ -/* Note: This is a very limited set of definitions, */ -/* only implemented features are defined. */ -#define MDIO_PMA_PMD_CR1 0x0000 -#define MDIO_PMA_PMD_CR1_RESET 0x8000 - #define MDIO_PMA_PMD_XPAK_VENDOR_NAME 0x803A /* XPAK/XENPAK devices only */ /* Vendor-specific MDIO registers */ diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 4a0826b8f6f2..9c897cf86b9f 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -266,6 +266,8 @@ ixgb_up(struct ixgb_adapter *adapter) napi_enable(&adapter->napi); ixgb_irq_enable(adapter); + netif_wake_queue(netdev); + mod_timer(&adapter->watchdog_timer, jiffies); return 0; @@ -471,10 +473,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_register; - /* we're going to reset, so assume we have no link for now */ - + /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - netif_stop_queue(netdev); DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n"); ixgb_check_options(adapter); @@ -592,6 +592,8 @@ ixgb_open(struct net_device *netdev) if (err) goto err_setup_tx; + netif_carrier_off(netdev); + /* allocate receive descriptors */ err = ixgb_setup_rx_resources(adapter); @@ -602,6 +604,8 @@ ixgb_open(struct net_device *netdev) if (err) goto err_up; + netif_start_queue(netdev); + return 0; err_up: @@ -1116,7 +1120,6 @@ ixgb_watchdog(unsigned long data) adapter->link_speed = 10000; adapter->link_duplex = FULL_DUPLEX; netif_carrier_on(netdev); - netif_wake_queue(netdev); } } else { if (netif_carrier_ok(netdev)) { @@ -1125,8 +1128,6 @@ ixgb_watchdog(unsigned long data) printk(KERN_INFO "ixgb: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_stop_queue(netdev); - } } @@ -1139,6 +1140,8 @@ ixgb_watchdog(unsigned long data) * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ schedule_work(&adapter->tx_timeout_task); + /* return immediately since reset is imminent */ + return; } } @@ -1297,7 +1300,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, buffer_info->length = size; WARN_ON(buffer_info->dma != 0); buffer_info->time_stamp = jiffies; - buffer_info->dma = map[0] + offset; + buffer_info->dma = skb_shinfo(skb)->dma_head + offset; pci_map_single(adapter->pdev, skb->data + offset, size, @@ -1337,7 +1340,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, buffer_info->length = size; buffer_info->time_stamp = jiffies; - buffer_info->dma = map[f + 1] + offset; + buffer_info->dma = map[f] + offset; buffer_info->next_to_watch = 0; len -= size; @@ -1485,7 +1488,6 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (count) { ixgb_tx_queue(adapter, count, vlan_id, tx_flags); - netdev->trans_start = jiffies; /* Make sure there is space in the ring for the next send. */ ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED); diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h index d92e72bd627a..371a6be4d965 100644 --- a/drivers/net/ixgb/ixgb_osdep.h +++ b/drivers/net/ixgb/ixgb_osdep.h @@ -40,7 +40,7 @@ #include #undef ASSERT -#define ASSERT(x) if (!(x)) BUG() +#define ASSERT(x) BUG_ON(!(x)) #define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) #ifdef DBG diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index b3f8208ec7be..21b41f42b61c 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -37,3 +37,5 @@ ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o + +ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index c26433d14605..cd22323cfd22 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -36,6 +36,10 @@ #include "ixgbe_type.h" #include "ixgbe_common.h" #include "ixgbe_dcb.h" +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) +#define IXGBE_FCOE +#include "ixgbe_fcoe.h" +#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */ #ifdef CONFIG_IXGBE_DCA #include #endif @@ -71,6 +75,8 @@ #define IXGBE_RXBUFFER_128 128 /* Used for packet split */ #define IXGBE_RXBUFFER_256 256 /* Used for packet split */ #define IXGBE_RXBUFFER_2048 2048 +#define IXGBE_RXBUFFER_4096 4096 +#define IXGBE_RXBUFFER_8192 8192 #define IXGBE_MAX_RXBUFFER 16384 /* largest size for a single descriptor */ #define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_256 @@ -84,6 +90,8 @@ #define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1) #define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) #define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) +#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 4) +#define IXGBE_TX_FLAGS_FSO (u32)(1 << 5) #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 @@ -113,17 +121,18 @@ struct ixgbe_queue_stats { struct ixgbe_ring { void *desc; /* descriptor ring memory */ - dma_addr_t dma; /* phys. address of descriptor ring */ - unsigned int size; /* length in bytes */ - unsigned int count; /* amount of descriptors */ - unsigned int next_to_use; - unsigned int next_to_clean; - - int queue_index; /* needed for multiqueue queue management */ union { struct ixgbe_tx_buffer *tx_buffer_info; struct ixgbe_rx_buffer *rx_buffer_info; }; + u8 atr_sample_rate; + u8 atr_count; + u16 count; /* amount of descriptors */ + u16 rx_buf_len; + u16 next_to_use; + u16 next_to_clean; + + u8 queue_index; /* needed for multiqueue queue management */ u16 head; u16 tail; @@ -131,22 +140,24 @@ struct ixgbe_ring { unsigned int total_bytes; unsigned int total_packets; - u16 reg_idx; /* holds the special value that gets the hardware register - * offset associated with this ring, which is different - * for DCB and RSS modes */ - #ifdef CONFIG_IXGBE_DCA /* cpu for tx queue */ int cpu; #endif + + u16 work_limit; /* max work per interrupt */ + u16 reg_idx; /* holds the special value that gets + * the hardware register offset + * associated with this ring, which is + * different for DCB and RSS modes + */ + struct ixgbe_queue_stats stats; - u64 v_idx; /* maps directly to the index for this ring in the hardware - * vector array, can also be used for finding the bit in EICR - * and friends that represents the vector for this ring */ + unsigned long reinit_state; + u64 rsc_count; /* stat for coalesced packets */ - - u16 work_limit; /* max work per interrupt */ - u16 rx_buf_len; + unsigned int size; /* length in bytes */ + dma_addr_t dma; /* phys. address of descriptor ring */ }; enum ixgbe_ring_f_enum { @@ -154,6 +165,10 @@ enum ixgbe_ring_f_enum { RING_F_DCB, RING_F_VMDQ, RING_F_RSS, + RING_F_FDIR, +#ifdef IXGBE_FCOE + RING_F_FCOE, +#endif /* IXGBE_FCOE */ RING_F_ARRAY_SIZE /* must be last in enum set */ }; @@ -161,6 +176,10 @@ enum ixgbe_ring_f_enum { #define IXGBE_MAX_DCB_INDICES 8 #define IXGBE_MAX_RSS_INDICES 16 #define IXGBE_MAX_VMDQ_INDICES 16 +#define IXGBE_MAX_FDIR_INDICES 64 +#ifdef IXGBE_FCOE +#define IXGBE_MAX_FCOE_INDICES 8 +#endif /* IXGBE_FCOE */ struct ixgbe_ring_feature { int indices; int mask; @@ -178,6 +197,9 @@ struct ixgbe_ring_feature { */ struct ixgbe_q_vector { struct ixgbe_adapter *adapter; + unsigned int v_idx; /* index of q_vector within array, also used for + * finding the bit in EICR and friends that + * represents the vector for this ring */ struct napi_struct napi; DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */ DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ @@ -207,7 +229,15 @@ 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 */ +#define IXGBE_FCOE_JUMBO_FRAME_SIZE 3072 +#endif /* IXGBE_FCOE */ #define OTHER_VECTOR 1 #define NON_Q_VECTORS (OTHER_VECTOR) @@ -229,11 +259,12 @@ struct ixgbe_adapter { struct vlan_group *vlgrp; u16 bd_number; struct work_struct reset_task; - struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS]; + struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; char name[MAX_MSIX_COUNT][IFNAMSIZ + 9]; struct ixgbe_dcb_config dcb_cfg; struct ixgbe_dcb_config temp_dcb_cfg; u8 dcb_set_bitmap; + enum ixgbe_fc_mode last_lfc_mode; /* Interrupt Throttle Rate */ u32 itr_setting; @@ -294,7 +325,13 @@ struct ixgbe_adapter { #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23) #define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 24) #define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 25) +#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 26) +#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 27) +#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29) + u32 flags2; +#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) +#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) /* default to trying for four seconds */ #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) @@ -303,6 +340,10 @@ struct ixgbe_adapter { struct pci_dev *pdev; struct net_device_stats net_stats; + u32 test_icr; + struct ixgbe_ring test_tx_ring; + struct ixgbe_ring test_rx_ring; + /* structs defined in ixgbe_hw.h */ struct ixgbe_hw hw; u16 msg_enable; @@ -325,6 +366,14 @@ struct ixgbe_adapter { struct timer_list sfp_timer; struct work_struct multispeed_fiber_task; struct work_struct sfp_config_module_task; + u32 fdir_pballoc; + u32 atr_sample_rate; + spinlock_t fdir_perfect_lock; + struct work_struct fdir_reinit_task; +#ifdef IXGBE_FCOE + struct ixgbe_fcoe fcoe; +#endif /* IXGBE_FCOE */ + u64 rsc_count; u32 wol; u16 eeprom_version; }; @@ -333,6 +382,7 @@ enum ixbge_state_t { __IXGBE_TESTING, __IXGBE_RESETTING, __IXGBE_DOWN, + __IXGBE_FDIR_INIT_DONE, __IXGBE_SFP_MODULE_NOT_FOUND }; @@ -363,10 +413,77 @@ extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *) extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); -extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); -void ixgbe_napi_add_all(struct ixgbe_adapter *adapter); -void ixgbe_napi_del_all(struct ixgbe_adapter *adapter); -extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32); +extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); +extern void ixgbe_write_eitr(struct ixgbe_q_vector *); +extern int ethtool_ioctl(struct ifreq *ifr); +extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw); +extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc); +extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc); +extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, + struct ixgbe_atr_input *input, + u8 queue); +extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, + struct ixgbe_atr_input *input, + u16 soft_id, + u8 queue); +extern u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *input, u32 key); +extern s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, + u16 vlan_id); +extern s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, + u32 src_addr); +extern s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, + u32 dst_addr); +extern s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, + u32 src_addr_1, u32 src_addr_2, + u32 src_addr_3, u32 src_addr_4); +extern s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, + u32 dst_addr_1, u32 dst_addr_2, + u32 dst_addr_3, u32 dst_addr_4); +extern s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, + u16 src_port); +extern s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, + u16 dst_port); +extern s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, + u16 flex_byte); +extern s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, + u8 vm_pool); +extern s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, + u8 l4type); +extern s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, + u16 *vlan_id); +extern s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, + u32 *src_addr); +extern s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, + u32 *dst_addr); +extern s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, + u32 *src_addr_1, u32 *src_addr_2, + u32 *src_addr_3, u32 *src_addr_4); +extern s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, + u32 *dst_addr_1, u32 *dst_addr_2, + u32 *dst_addr_3, u32 *dst_addr_4); +extern s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, + u16 *src_port); +extern s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, + u16 *dst_port); +extern s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, + u16 *flex_byte); +extern s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, + u8 *vm_pool); +extern s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, + u8 *l4type); +#ifdef IXGBE_FCOE +extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); +extern int ixgbe_fso(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring, struct sk_buff *skb, + u32 tx_flags, u8 *hdr_len); +extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); +extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb); +extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, + struct scatterlist *sgl, unsigned int sgc); +extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid); +#endif /* IXGBE_FCOE */ #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 4791238c3f6e..b9923047ce11 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -75,18 +75,49 @@ static u16 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw) static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; - struct ixgbe_phy_info *phy = &hw->phy; - s32 ret_val = 0; - u16 list_offset, data_offset; - - /* Set the bus information prior to PHY identification */ - mac->ops.get_bus_info(hw); /* Call PHY identify routine to get the phy type */ ixgbe_identify_phy_generic(hw); - /* PHY Init */ - switch (phy->type) { + mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; + mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; + mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; + mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw); + + return 0; +} + +/** + * ixgbe_init_phy_ops_82598 - PHY/SFP specific init + * @hw: pointer to hardware structure + * + * Initialize any function pointers that were not able to be + * set during get_invariants because the PHY/SFP type was + * not known. Perform the SFP init if necessary. + * + **/ +s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + struct ixgbe_phy_info *phy = &hw->phy; + s32 ret_val = 0; + u16 list_offset, data_offset; + + /* Identify the PHY */ + phy->ops.identify(hw); + + /* Overwrite the link function pointers if copper PHY */ + if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { + mac->ops.setup_link = &ixgbe_setup_copper_link_82598; + mac->ops.setup_link_speed = + &ixgbe_setup_copper_link_speed_82598; + mac->ops.get_link_capabilities = + &ixgbe_get_copper_link_capabilities_82598; + } + + switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = @@ -106,8 +137,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) /* Check to see if SFP+ module is supported */ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, - &list_offset, - &data_offset); + &list_offset, + &data_offset); if (ret_val != 0) { ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; @@ -117,21 +148,6 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) break; } - if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { - mac->ops.setup_link = &ixgbe_setup_copper_link_82598; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82598; - mac->ops.get_link_capabilities = - &ixgbe_get_copper_link_capabilities_82598; - } - - mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; - mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; - mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; - mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; - mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; - mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw); - out: return ret_val; } @@ -149,12 +165,19 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, bool *autoneg) { s32 status = 0; + u32 autoc = 0; /* * Determine link capabilities based on the stored value of AUTOC, - * which represents EEPROM defaults. + * which represents EEPROM defaults. If AUTOC value has not been + * stored, use the current register value. */ - switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) { + if (hw->mac.orig_link_settings_stored) + autoc = hw->mac.orig_autoc; + else + autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; @@ -173,9 +196,9 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) + if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; @@ -206,14 +229,13 @@ static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, *speed = 0; *autoneg = true; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, &speed_ability); if (status == 0) { - if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + if (speed_ability & MDIO_SPEED_10G) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + if (speed_ability & MDIO_PMA_SPEED_1000) *speed |= IXGBE_LINK_SPEED_1GB_FULL; } @@ -271,6 +293,17 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) u32 rmcs_reg; u32 reg; +#ifdef CONFIG_DCB + if (hw->fc.requested_mode == ixgbe_fc_pfc) + goto out; + +#endif /* CONFIG_DCB */ + /* Negotiate the fc mode to use */ + ret_val = ixgbe_fc_autoneg(hw); + if (ret_val) + goto out; + + /* Disable any previous flow control settings */ fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); @@ -282,14 +315,20 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but + * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. +#ifdef CONFIG_DCB + * 4: Priority Flow Control is enabled. +#endif */ switch (hw->fc.current_mode) { case ixgbe_fc_none: - /* Flow control completely disabled by software override. */ + /* + * Flow control is disabled by software override or autoneg. + * The code below will actually disable it in the HW. + */ break; case ixgbe_fc_rx_pause: /* @@ -314,6 +353,11 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) fctrl_reg |= IXGBE_FCTRL_RFCE; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; +#ifdef CONFIG_DCB + case ixgbe_fc_pfc: + goto out; + break; +#endif /* CONFIG_DCB */ default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = -IXGBE_ERR_CONFIG; @@ -321,7 +365,8 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) break; } - /* Enable 802.3x based flow control settings. */ + /* Set 802.3x based flow control settings. */ + fctrl_reg |= IXGBE_FCTRL_DPF; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); @@ -340,7 +385,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) } /* Configure pause time (2 TCs per register) */ - reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num)); + reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2)); if ((packetbuf_num & 1) == 0) reg = (reg & 0xFFFF0000) | hw->fc.pause_time; else @@ -353,77 +398,6 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) return ret_val; } -/** - * ixgbe_setup_fc_82598 - Configure flow control settings - * @hw: pointer to hardware structure - * @packetbuf_num: packet buffer number (0-7) - * - * Configures the flow control settings based on SW configuration. This - * function is used for 802.3x flow control configuration only. - **/ -static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) -{ - s32 ret_val = 0; - ixgbe_link_speed speed; - bool link_up; - - /* Validate the packetbuf configuration */ - if (packetbuf_num < 0 || packetbuf_num > 7) { - hw_dbg(hw, "Invalid packet buffer number [%d], expected range is" - " 0-7\n", packetbuf_num); - ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; - goto out; - } - - /* - * Validate the water mark configuration. Zero water marks are invalid - * because it causes the controller to just blast out fc packets. - */ - if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { - hw_dbg(hw, "Invalid water mark configuration\n"); - ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; - goto out; - } - - /* - * Validate the requested mode. Strict IEEE mode does not allow - * ixgbe_fc_rx_pause because it will cause testing anomalies. - */ - if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { - hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); - ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; - goto out; - } - - /* - * 10gig parts do not have a word in the EEPROM to determine the - * default flow control setting, so we explicitly set it to full. - */ - if (hw->fc.requested_mode == ixgbe_fc_default) - hw->fc.requested_mode = ixgbe_fc_full; - - /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - - hw->fc.current_mode = hw->fc.requested_mode; - - /* Decide whether to use autoneg or not. */ - hw->mac.ops.check_link(hw, &speed, &link_up, false); - if (!hw->fc.disable_fc_autoneg && hw->phy.multispeed_fiber && - (speed == IXGBE_LINK_SPEED_1GB_FULL)) - ret_val = ixgbe_fc_autoneg(hw); - - if (ret_val) - goto out; - - ret_val = ixgbe_fc_enable_82598(hw, packetbuf_num); - -out: - return ret_val; -} - /** * ixgbe_setup_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure @@ -463,13 +437,6 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) } } - /* - * 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. - */ - ixgbe_setup_fc_82598(hw, 0); - /* Add delay to filter out noises during initial link setup */ msleep(50); @@ -500,9 +467,9 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, * clear indicates active; set indicates inactive. */ if (hw->phy.type == ixgbe_phy_nl) { - hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); - hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); - hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, + hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg); + hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg); + hw->phy.ops.read_reg(hw, 0xC00C, MDIO_MMD_PMAPMD, &adapt_comp_reg); if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { @@ -515,10 +482,10 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, } msleep(100); hw->phy.ops.read_reg(hw, 0xC79F, - IXGBE_TWINAX_DEV, + MDIO_MMD_PMAPMD, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, - IXGBE_TWINAX_DEV, + MDIO_MMD_PMAPMD, &adapt_comp_reg); } } else { @@ -556,6 +523,11 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, else *speed = IXGBE_LINK_SPEED_1GB_FULL; + /* if link is down, zero out the current_mode */ + if (*link_up == false) { + hw->fc.current_mode = ixgbe_fc_none; + hw->fc.fc_was_autonegged = false; + } out: return 0; } @@ -673,6 +645,7 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) { s32 status = 0; + s32 phy_status = 0; u32 ctrl; u32 gheccr; u32 i; @@ -716,14 +689,27 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) } /* Reset PHY */ - if (hw->phy.reset_disable == false) - hw->phy.ops.reset(hw); + if (hw->phy.reset_disable == false) { + /* PHY ops must be identified and initialized prior to reset */ + /* Init PHY and function pointers, perform SFP setup */ + phy_status = hw->phy.ops.init(hw); + if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto reset_hw_out; + else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT) + goto no_phy_reset; + + + hw->phy.ops.reset(hw); + } + +no_phy_reset: /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ - if (ixgbe_disable_pcie_master(hw) != 0) { + status = ixgbe_disable_pcie_master(hw); + if (status != 0) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); } @@ -767,9 +753,19 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); } + /* + * Store MAC address from RAR0, clear receive address registers, and + * clear the multicast table + */ + hw->mac.ops.init_rx_addrs(hw); + /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); +reset_hw_out: + if (phy_status) + status = phy_status; + return status; } @@ -954,14 +950,14 @@ static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK); hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + MDIO_MMD_PMAPMD, sfp_addr); /* Poll status */ for (i = 0; i < 100; i++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + MDIO_MMD_PMAPMD, &sfp_stat); sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK; if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS) @@ -977,7 +973,7 @@ static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, /* Read data */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data); + MDIO_MMD_PMAPMD, &sfp_data); *eeprom_data = (u8)(sfp_data >> 8); } else { @@ -998,35 +994,56 @@ static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; + u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; + u16 ext_ability = 0; - switch (hw->device_id) { - case IXGBE_DEV_ID_82598: - /* Default device ID is mezzanine card KX/KX4 */ - physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | - IXGBE_PHYSICAL_LAYER_1000BASE_KX); + hw->phy.ops.identify(hw); + + /* Copper PHY must be checked before AUTOC LMS to determine correct + * physical layer because 10GBase-T PHYs use LMS = KX4/KX */ + if (hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_cu_unknown) { + hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD, + &ext_ability); + if (ext_ability & MDIO_PMA_EXTABLE_10GBT) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; + if (ext_ability & MDIO_PMA_EXTABLE_1000BT) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; + if (ext_ability & MDIO_PMA_EXTABLE_100BTX) + physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; + goto out; + } + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { + case IXGBE_AUTOC_LMS_1G_AN: + case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: + if (pma_pmd_1g == IXGBE_AUTOC_1G_KX) + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX; + else + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; break; - case IXGBE_DEV_ID_82598_BX: - physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; - case IXGBE_DEV_ID_82598EB_CX4: - case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; + case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: + if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; + else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; + else /* XAUI */ + physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; - case IXGBE_DEV_ID_82598_DA_DUAL_PORT: - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + case IXGBE_AUTOC_LMS_KX4_AN: + case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: + if (autoc & IXGBE_AUTOC_KX_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; + if (autoc & IXGBE_AUTOC_KX4_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; break; - case IXGBE_DEV_ID_82598AF_DUAL_PORT: - case IXGBE_DEV_ID_82598AF_SINGLE_PORT: - case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + default: break; - case IXGBE_DEV_ID_82598EB_XF_LR: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; - break; - case IXGBE_DEV_ID_82598AT: - physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T | - IXGBE_PHYSICAL_LAYER_1000BASE_T); - break; - case IXGBE_DEV_ID_82598EB_SFP_LOM: + } + + if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.identify_sfp(hw); switch (hw->phy.sfp_type) { @@ -1043,13 +1060,25 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } - break; + } + switch (hw->device_id) { + case IXGBE_DEV_ID_82598_DA_DUAL_PORT: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + break; + case IXGBE_DEV_ID_82598AF_DUAL_PORT: + case IXGBE_DEV_ID_82598AF_SINGLE_PORT: + case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + break; + case IXGBE_DEV_ID_82598EB_XF_LR: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + break; default: - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } +out: return physical_layer; } @@ -1086,7 +1115,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = { .disable_mc = &ixgbe_disable_mc_generic, .clear_vfta = &ixgbe_clear_vfta_82598, .set_vfta = &ixgbe_set_vfta_82598, - .setup_fc = &ixgbe_setup_fc_82598, + .fc_enable = &ixgbe_fc_enable_82598, }; static struct ixgbe_eeprom_operations eeprom_ops_82598 = { @@ -1099,6 +1128,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = { static struct ixgbe_phy_operations phy_ops_82598 = { .identify = &ixgbe_identify_phy_generic, .identify_sfp = &ixgbe_identify_sfp_module_generic, + .init = &ixgbe_init_phy_ops_82598, .reset = &ixgbe_reset_phy_generic, .read_reg = &ixgbe_read_phy_reg_generic, .write_reg = &ixgbe_write_phy_reg_generic, diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 29771fbaa42d..1984cab7d48b 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -71,10 +71,10 @@ s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw); s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw); s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val); -s32 ixgbe_start_hw_rev_0_82599(struct ixgbe_hw *hw); s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw); s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); +static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { @@ -100,22 +100,36 @@ s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { ixgbe_init_mac_link_ops_82599(hw); + + hw->phy.ops.reset = NULL; + ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != 0) goto setup_sfp_out; + /* PHY config will finish before releasing the semaphore */ + ret_val = ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); + if (ret_val != 0) { + ret_val = IXGBE_ERR_SWFW_SYNC; + goto setup_sfp_out; + } + hw->eeprom.ops.read(hw, ++data_offset, &data_value); while (data_value != 0xffff) { IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value); IXGBE_WRITE_FLUSH(hw); hw->eeprom.ops.read(hw, ++data_offset, &data_value); } - /* Now restart DSP */ - IXGBE_WRITE_REG(hw, IXGBE_CORECTL, 0x00000102); - IXGBE_WRITE_REG(hw, IXGBE_CORECTL, 0x00000b1d); - IXGBE_WRITE_FLUSH(hw); + /* Now restart DSP by setting Restart_AN */ + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, + (IXGBE_READ_REG(hw, IXGBE_AUTOC) | IXGBE_AUTOC_AN_RESTART)); + + /* Release the semaphore */ + ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); + /* Delay obtaining semaphore again to allow FW access */ + msleep(hw->eeprom.semaphore_delay); } setup_sfp_out: @@ -146,43 +160,9 @@ u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw) static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; - struct ixgbe_phy_info *phy = &hw->phy; - s32 ret_val; - - /* Set the bus information prior to PHY identification */ - mac->ops.get_bus_info(hw); - - /* Call PHY identify routine to get the Cu or SFI phy type */ - ret_val = phy->ops.identify(hw); - - if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) - goto get_invariants_out; ixgbe_init_mac_link_ops_82599(hw); - /* Setup SFP module if there is one present. */ - ret_val = mac->ops.setup_sfp(hw); - - /* If copper media, overwrite with copper function pointers */ - if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { - mac->ops.setup_link = &ixgbe_setup_copper_link_82599; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82599; - mac->ops.get_link_capabilities = - &ixgbe_get_copper_link_capabilities_82599; - } - - /* PHY Init */ - switch (hw->phy.type) { - case ixgbe_phy_tn: - phy->ops.check_link = &ixgbe_check_phy_link_tnx; - phy->ops.get_firmware_version = - &ixgbe_get_phy_firmware_version_tnx; - break; - default: - break; - } - mac->mcft_size = IXGBE_82599_MC_TBL_SIZE; mac->vft_size = IXGBE_82599_VFT_TBL_SIZE; mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES; @@ -190,7 +170,50 @@ static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw) mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw); -get_invariants_out: + return 0; +} + +/** + * ixgbe_init_phy_ops_82599 - PHY/SFP specific init + * @hw: pointer to hardware structure + * + * Initialize any function pointers that were not able to be + * set during get_invariants because the PHY/SFP type was + * not known. Perform the SFP init if necessary. + * + **/ +s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + struct ixgbe_phy_info *phy = &hw->phy; + s32 ret_val = 0; + + /* Identify the PHY or SFP module */ + ret_val = phy->ops.identify(hw); + + /* Setup function pointers based on detected SFP module and speeds */ + ixgbe_init_mac_link_ops_82599(hw); + + /* If copper media, overwrite with copper function pointers */ + if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { + mac->ops.setup_link = &ixgbe_setup_copper_link_82599; + mac->ops.setup_link_speed = + &ixgbe_setup_copper_link_speed_82599; + mac->ops.get_link_capabilities = + &ixgbe_get_copper_link_capabilities_82599; + } + + /* Set necessary function pointers based on phy type */ + switch (hw->phy.type) { + case ixgbe_phy_tn: + phy->ops.check_link = &ixgbe_check_phy_link_tnx; + phy->ops.get_firmware_version = + &ixgbe_get_phy_firmware_version_tnx; + break; + default: + break; + } + return ret_val; } @@ -207,8 +230,19 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, bool *negotiation) { s32 status = 0; + u32 autoc = 0; - switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) { + /* + * Determine link capabilities based on the stored value of AUTOC, + * which represents EEPROM defaults. If AUTOC value has not been + * stored, use the current register value. + */ + if (hw->mac.orig_link_settings_stored) + autoc = hw->mac.orig_autoc; + else + autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *negotiation = false; @@ -232,22 +266,22 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, case IXGBE_AUTOC_LMS_KX4_KX_KR: case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP) + if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) + if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII: *speed = IXGBE_LINK_SPEED_100_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP) + if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) + if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; @@ -291,14 +325,13 @@ static s32 ixgbe_get_copper_link_capabilities_82599(struct ixgbe_hw *hw, *speed = 0; *autoneg = true; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, &speed_ability); if (status == 0) { - if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + if (speed_ability & MDIO_SPEED_10G) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + if (speed_ability & MDIO_PMA_SPEED_1000) *speed |= IXGBE_LINK_SPEED_1GB_FULL; } @@ -323,8 +356,8 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) } switch (hw->device_id) { - case IXGBE_DEV_ID_82599: case IXGBE_DEV_ID_82599_KX4: + case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; @@ -380,9 +413,6 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw) } } - /* Set up flow control */ - status = ixgbe_setup_fc_generic(hw, 0); - /* Add delay to filter out noises during initial link setup */ msleep(50); @@ -428,11 +458,31 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); bool link_up = false; bool negotiation; + int i; /* Mask off requested but non-supported speeds */ hw->mac.ops.get_link_capabilities(hw, &phy_link_speed, &negotiation); speed &= phy_link_speed; + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + /* + * When the driver changes the link speeds that it can support, + * it sets autotry_restart to true to indicate that we need to + * initiate a new autotry session with the link partner. To do + * so, we set the speed then disable and re-enable the tx laser, to + * alert the link partner that it also needs to restart autotry on its + * end. This is consistent with true clause 37 autoneg, which also + * involves a loss of signal. + */ + /* * Try each speed one by one, highest priority first. We do this in * software because 10gb fiber doesn't support speed autonegotiation. @@ -441,21 +491,52 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, speedcnt++; highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; - /* Set hardware SDP's */ + /* If we already have link at this speed, just jump out */ + hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false); + + if ((phy_link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) + goto out; + + /* Set the module link speed */ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); - ixgbe_setup_mac_link_speed_82599(hw, - IXGBE_LINK_SPEED_10GB_FULL, - autoneg, - autoneg_wait_to_complete); + /* Allow module to change analog characteristics (1G->10G) */ + msleep(40); - msleep(50); - - /* If we have link, just jump out */ - hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false); - if (link_up) + status = ixgbe_setup_mac_link_speed_82599(hw, + IXGBE_LINK_SPEED_10GB_FULL, + autoneg, + autoneg_wait_to_complete); + if (status != 0) goto out; + + /* Flap the tx laser if it has not already been done */ + if (hw->mac.autotry_restart) { + /* Disable tx laser; allow 100us to go dark per spec */ + esdp_reg |= IXGBE_ESDP_SDP3; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); + udelay(100); + + /* Enable tx laser; allow 2ms to light up per spec */ + esdp_reg &= ~IXGBE_ESDP_SDP3; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); + msleep(2); + + hw->mac.autotry_restart = false; + } + + /* The controller may take up to 500ms at 10g to acquire link */ + for (i = 0; i < 5; i++) { + /* Wait for the link partner to also set speed */ + msleep(100); + + /* If we have link, just jump out */ + hw->mac.ops.check_link(hw, &phy_link_speed, + &link_up, false); + if (link_up) + goto out; + } } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { @@ -463,16 +544,44 @@ s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; - /* Set hardware SDP's */ + /* If we already have link at this speed, just jump out */ + hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false); + + if ((phy_link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) + goto out; + + /* Set the module link speed */ esdp_reg &= ~IXGBE_ESDP_SDP5; esdp_reg |= IXGBE_ESDP_SDP5_DIR; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); - ixgbe_setup_mac_link_speed_82599( - hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg, - autoneg_wait_to_complete); + /* Allow module to change analog characteristics (10G->1G) */ + msleep(40); - msleep(50); + status = ixgbe_setup_mac_link_speed_82599(hw, + IXGBE_LINK_SPEED_1GB_FULL, + autoneg, + autoneg_wait_to_complete); + if (status != 0) + goto out; + + /* Flap the tx laser if it has not already been done */ + if (hw->mac.autotry_restart) { + /* Disable tx laser; allow 100us to go dark per spec */ + esdp_reg |= IXGBE_ESDP_SDP3; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); + udelay(100); + + /* Enable tx laser; allow 2ms to light up per spec */ + esdp_reg &= ~IXGBE_ESDP_SDP3; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); + msleep(2); + + hw->mac.autotry_restart = false; + } + + /* Wait for the link partner to also set speed */ + msleep(100); /* If we have link, just jump out */ hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false); @@ -538,6 +647,11 @@ s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, else *speed = IXGBE_LINK_SPEED_100_FULL; + /* if link is down, zero out the current_mode */ + if (*link_up == false) { + hw->fc.current_mode = ixgbe_fc_none; + hw->fc.fc_was_autonegged = false; + } return 0; } @@ -558,6 +672,8 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, s32 status = 0; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); + u32 start_autoc = autoc; + u32 orig_autoc = 0; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; @@ -571,15 +687,25 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, if (speed == IXGBE_LINK_SPEED_UNKNOWN) { status = IXGBE_ERR_LINK_SETUP; - } else if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || - link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || - link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { + goto out; + } + + /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/ + if (hw->mac.orig_link_settings_stored) + orig_autoc = hw->mac.orig_autoc; + else + orig_autoc = autoc; + + + if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || + link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || + link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { /* Set KX4/KX/KR support according to speed requested */ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); if (speed & IXGBE_LINK_SPEED_10GB_FULL) - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP) + if (orig_autoc & IXGBE_AUTOC_KR_SUPP) autoc |= IXGBE_AUTOC_KR_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; @@ -605,7 +731,7 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, } } - if (status == 0) { + if (autoc != start_autoc) { /* Restart link */ autoc |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); @@ -632,13 +758,11 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, } } - /* Set up flow control */ - status = ixgbe_setup_fc_generic(hw, 0); - /* Add delay to filter out noises during initial link setup */ msleep(50); } +out: return status; } @@ -705,14 +829,30 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); + /* PHY ops must be identified and initialized prior to reset */ + + /* Init PHY and function pointers, perform SFP setup */ + status = hw->phy.ops.init(hw); + + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto reset_hw_out; + + /* Setup SFP module if there is one present. */ + if (hw->phy.sfp_setup_needed) { + status = hw->mac.ops.setup_sfp(hw); + hw->phy.sfp_setup_needed = false; + } + /* Reset PHY */ - hw->phy.ops.reset(hw); + if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL) + hw->phy.ops.reset(hw); /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ - if (ixgbe_disable_pcie_master(hw) != 0) { + status = ixgbe_disable_pcie_master(hw); + if (status != 0) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); } @@ -770,9 +910,30 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) } } + /* + * Store MAC address from RAR0, clear receive address registers, and + * clear the multicast table. Also reset num_rar_entries to 128, + * since we modify this value when programming the SAN MAC address. + */ + hw->mac.num_rar_entries = 128; + hw->mac.ops.init_rx_addrs(hw); + /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); + /* Store the permanent SAN mac address */ + hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); + + /* Add the SAN MAC address to the RAR only if it's a valid address */ + if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { + hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, + hw->mac.san_addr, 0, IXGBE_RAH_AV); + + /* Reserve the last RAR for the SAN MAC address */ + hw->mac.num_rar_entries--; + } + +reset_hw_out: return status; } @@ -1003,6 +1164,931 @@ s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw) return 0; } +/** + * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables. + * @hw: pointer to hardware structure + **/ +s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw) +{ + int i; + u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); + fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE; + + /* + * Before starting reinitialization process, + * FDIRCMD.CMD must be zero. + */ + for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) { + if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & + IXGBE_FDIRCMD_CMD_MASK)) + break; + udelay(10); + } + if (i >= IXGBE_FDIRCMD_CMD_POLL) { + hw_dbg(hw ,"Flow Director previous command isn't complete, " + "aborting table re-initialization. \n"); + return IXGBE_ERR_FDIR_REINIT_FAILED; + } + + IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0); + IXGBE_WRITE_FLUSH(hw); + /* + * 82599 adapters flow director init flow cannot be restarted, + * Workaround 82599 silicon errata by performing the following steps + * before re-writing the FDIRCTRL control register with the same value. + * - write 1 to bit 8 of FDIRCMD register & + * - write 0 to bit 8 of FDIRCMD register + */ + IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, + (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) | + IXGBE_FDIRCMD_CLEARHT)); + IXGBE_WRITE_FLUSH(hw); + IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, + (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & + ~IXGBE_FDIRCMD_CLEARHT)); + IXGBE_WRITE_FLUSH(hw); + /* + * Clear FDIR Hash register to clear any leftover hashes + * waiting to be programmed. + */ + IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00); + IXGBE_WRITE_FLUSH(hw); + + IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); + IXGBE_WRITE_FLUSH(hw); + + /* Poll init-done after we write FDIRCTRL register */ + for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { + if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & + IXGBE_FDIRCTRL_INIT_DONE) + break; + udelay(10); + } + if (i >= IXGBE_FDIR_INIT_DONE_POLL) { + hw_dbg(hw, "Flow Director Signature poll time exceeded!\n"); + return IXGBE_ERR_FDIR_REINIT_FAILED; + } + + /* Clear FDIR statistics registers (read to clear) */ + IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT); + IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT); + IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); + IXGBE_READ_REG(hw, IXGBE_FDIRMISS); + IXGBE_READ_REG(hw, IXGBE_FDIRLEN); + + return 0; +} + +/** + * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters + * @hw: pointer to hardware structure + * @pballoc: which mode to allocate filters with + **/ +s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc) +{ + u32 fdirctrl = 0; + u32 pbsize; + int i; + + /* + * Before enabling Flow Director, the Rx Packet Buffer size + * must be reduced. The new value is the current size minus + * flow director memory usage size. + */ + pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc)); + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), + (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize)); + + /* + * The defaults in the HW for RX PB 1-7 are not zero and so should be + * intialized to zero for non DCB mode otherwise actual total RX PB + * would be bigger than programmed and filter space would run into + * the PB 0 region. + */ + for (i = 1; i < 8; i++) + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); + + /* Send interrupt when 64 filters are left */ + fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT; + + /* Set the maximum length per hash bucket to 0xA filters */ + fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT; + + switch (pballoc) { + case IXGBE_FDIR_PBALLOC_64K: + /* 8k - 1 signature filters */ + fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K; + break; + case IXGBE_FDIR_PBALLOC_128K: + /* 16k - 1 signature filters */ + fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K; + break; + case IXGBE_FDIR_PBALLOC_256K: + /* 32k - 1 signature filters */ + fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K; + break; + default: + /* bad value */ + return IXGBE_ERR_CONFIG; + }; + + /* Move the flexible bytes to use the ethertype - shift 6 words */ + fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT); + + fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS; + + /* Prime the keys for hashing */ + IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, + htonl(IXGBE_ATR_BUCKET_HASH_KEY)); + IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, + htonl(IXGBE_ATR_SIGNATURE_HASH_KEY)); + + /* + * Poll init-done after we write the register. Estimated times: + * 10G: PBALLOC = 11b, timing is 60us + * 1G: PBALLOC = 11b, timing is 600us + * 100M: PBALLOC = 11b, timing is 6ms + * + * Multiple these timings by 4 if under full Rx load + * + * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for + * 1 msec per poll time. If we're at line rate and drop to 100M, then + * this might not finish in our poll time, but we can live with that + * for now. + */ + IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); + IXGBE_WRITE_FLUSH(hw); + for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { + if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & + IXGBE_FDIRCTRL_INIT_DONE) + break; + msleep(1); + } + if (i >= IXGBE_FDIR_INIT_DONE_POLL) + hw_dbg(hw, "Flow Director Signature poll time exceeded!\n"); + + return 0; +} + +/** + * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters + * @hw: pointer to hardware structure + * @pballoc: which mode to allocate filters with + **/ +s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc) +{ + u32 fdirctrl = 0; + u32 pbsize; + int i; + + /* + * Before enabling Flow Director, the Rx Packet Buffer size + * must be reduced. The new value is the current size minus + * flow director memory usage size. + */ + pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc)); + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), + (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize)); + + /* + * The defaults in the HW for RX PB 1-7 are not zero and so should be + * intialized to zero for non DCB mode otherwise actual total RX PB + * would be bigger than programmed and filter space would run into + * the PB 0 region. + */ + for (i = 1; i < 8; i++) + IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); + + /* Send interrupt when 64 filters are left */ + fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT; + + switch (pballoc) { + case IXGBE_FDIR_PBALLOC_64K: + /* 2k - 1 perfect filters */ + fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K; + break; + case IXGBE_FDIR_PBALLOC_128K: + /* 4k - 1 perfect filters */ + fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K; + break; + case IXGBE_FDIR_PBALLOC_256K: + /* 8k - 1 perfect filters */ + fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K; + break; + default: + /* bad value */ + return IXGBE_ERR_CONFIG; + }; + + /* Turn perfect match filtering on */ + fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH; + fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS; + + /* Move the flexible bytes to use the ethertype - shift 6 words */ + fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT); + + /* Prime the keys for hashing */ + IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, + htonl(IXGBE_ATR_BUCKET_HASH_KEY)); + IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, + htonl(IXGBE_ATR_SIGNATURE_HASH_KEY)); + + /* + * Poll init-done after we write the register. Estimated times: + * 10G: PBALLOC = 11b, timing is 60us + * 1G: PBALLOC = 11b, timing is 600us + * 100M: PBALLOC = 11b, timing is 6ms + * + * Multiple these timings by 4 if under full Rx load + * + * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for + * 1 msec per poll time. If we're at line rate and drop to 100M, then + * this might not finish in our poll time, but we can live with that + * for now. + */ + + /* Set the maximum length per hash bucket to 0xA filters */ + fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT); + + IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); + IXGBE_WRITE_FLUSH(hw); + for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { + if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & + IXGBE_FDIRCTRL_INIT_DONE) + break; + msleep(1); + } + if (i >= IXGBE_FDIR_INIT_DONE_POLL) + hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n"); + + return 0; +} + + +/** + * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR + * @stream: input bitstream to compute the hash on + * @key: 32-bit hash key + **/ +u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key) +{ + /* + * The algorithm is as follows: + * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350 + * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n] + * and A[n] x B[n] is bitwise AND between same length strings + * + * K[n] is 16 bits, defined as: + * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15] + * for n modulo 32 < 15, K[n] = + * K[(n % 32:0) | (31:31 - (14 - (n % 32)))] + * + * S[n] is 16 bits, defined as: + * for n >= 15, S[n] = S[n:n - 15] + * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))] + * + * To simplify for programming, the algorithm is implemented + * in software this way: + * + * Key[31:0], Stream[335:0] + * + * tmp_key[11 * 32 - 1:0] = 11{Key[31:0] = key concatenated 11 times + * int_key[350:0] = tmp_key[351:1] + * int_stream[365:0] = Stream[14:0] | Stream[335:0] | Stream[335:321] + * + * hash[15:0] = 0; + * for (i = 0; i < 351; i++) { + * if (int_key[i]) + * hash ^= int_stream[(i + 15):i]; + * } + */ + + union { + u64 fill[6]; + u32 key[11]; + u8 key_stream[44]; + } tmp_key; + + u8 *stream = (u8 *)atr_input; + u8 int_key[44]; /* upper-most bit unused */ + u8 hash_str[46]; /* upper-most 2 bits unused */ + u16 hash_result = 0; + int i, j, k, h; + + /* + * Initialize the fill member to prevent warnings + * on some compilers + */ + tmp_key.fill[0] = 0; + + /* First load the temporary key stream */ + for (i = 0; i < 6; i++) { + u64 fillkey = ((u64)key << 32) | key; + tmp_key.fill[i] = fillkey; + } + + /* + * Set the interim key for the hashing. Bit 352 is unused, so we must + * shift and compensate when building the key. + */ + + int_key[0] = tmp_key.key_stream[0] >> 1; + for (i = 1, j = 0; i < 44; i++) { + unsigned int this_key = tmp_key.key_stream[j] << 7; + j++; + int_key[i] = (u8)(this_key | (tmp_key.key_stream[j] >> 1)); + } + + /* + * Set the interim bit string for the hashing. Bits 368 and 367 are + * unused, so shift and compensate when building the string. + */ + hash_str[0] = (stream[40] & 0x7f) >> 1; + for (i = 1, j = 40; i < 46; i++) { + unsigned int this_str = stream[j] << 7; + j++; + if (j > 41) + j = 0; + hash_str[i] = (u8)(this_str | (stream[j] >> 1)); + } + + /* + * Now compute the hash. i is the index into hash_str, j is into our + * key stream, k is counting the number of bits, and h interates within + * each byte. + */ + for (i = 45, j = 43, k = 0; k < 351 && i >= 2 && j >= 0; i--, j--) { + for (h = 0; h < 8 && k < 351; h++, k++) { + if (int_key[j] & (1 << h)) { + /* + * Key bit is set, XOR in the current 16-bit + * string. Example of processing: + * h = 0, + * tmp = (hash_str[i - 2] & 0 << 16) | + * (hash_str[i - 1] & 0xff << 8) | + * (hash_str[i] & 0xff >> 0) + * So tmp = hash_str[15 + k:k], since the + * i + 2 clause rolls off the 16-bit value + * h = 7, + * tmp = (hash_str[i - 2] & 0x7f << 9) | + * (hash_str[i - 1] & 0xff << 1) | + * (hash_str[i] & 0x80 >> 7) + */ + int tmp = (hash_str[i] >> h); + tmp |= (hash_str[i - 1] << (8 - h)); + tmp |= (int)(hash_str[i - 2] & ((1 << h) - 1)) + << (16 - h); + hash_result ^= (u16)tmp; + } + } + } + + return hash_result; +} + +/** + * ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream + * @input: input stream to modify + * @vlan: the VLAN id to load + **/ +s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) +{ + input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8; + input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff; + + return 0; +} + +/** + * ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address + * @input: input stream to modify + * @src_addr: the IP address to load + **/ +s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) +{ + input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24; + input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] = + (src_addr >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] = + (src_addr >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET] = src_addr & 0xff; + + return 0; +} + +/** + * ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address + * @input: input stream to modify + * @dst_addr: the IP address to load + **/ +s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) +{ + input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24; + input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] = + (dst_addr >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] = + (dst_addr >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET] = dst_addr & 0xff; + + return 0; +} + +/** + * ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address + * @input: input stream to modify + * @src_addr_1: the first 4 bytes of the IP address to load + * @src_addr_2: the second 4 bytes of the IP address to load + * @src_addr_3: the third 4 bytes of the IP address to load + * @src_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, + u32 src_addr_1, u32 src_addr_2, + u32 src_addr_3, u32 src_addr_4) +{ + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] = + (src_addr_4 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] = + (src_addr_4 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24; + + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] = + (src_addr_3 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] = + (src_addr_3 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24; + + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] = + (src_addr_2 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] = + (src_addr_2 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24; + + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] = + (src_addr_1 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] = + (src_addr_1 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24; + + return 0; +} + +/** + * ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address + * @input: input stream to modify + * @dst_addr_1: the first 4 bytes of the IP address to load + * @dst_addr_2: the second 4 bytes of the IP address to load + * @dst_addr_3: the third 4 bytes of the IP address to load + * @dst_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, + u32 dst_addr_1, u32 dst_addr_2, + u32 dst_addr_3, u32 dst_addr_4) +{ + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] = + (dst_addr_4 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] = + (dst_addr_4 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24; + + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] = + (dst_addr_3 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] = + (dst_addr_3 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24; + + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] = + (dst_addr_2 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] = + (dst_addr_2 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24; + + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] = + (dst_addr_1 >> 8) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] = + (dst_addr_1 >> 16) & 0xff; + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24; + + return 0; +} + +/** + * ixgbe_atr_set_src_port_82599 - Sets the source port + * @input: input stream to modify + * @src_port: the source port to load + **/ +s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) +{ + input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8; + input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff; + + return 0; +} + +/** + * ixgbe_atr_set_dst_port_82599 - Sets the destination port + * @input: input stream to modify + * @dst_port: the destination port to load + **/ +s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port) +{ + input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8; + input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff; + + return 0; +} + +/** + * ixgbe_atr_set_flex_byte_82599 - Sets the flexible bytes + * @input: input stream to modify + * @flex_bytes: the flexible bytes to load + **/ +s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte) +{ + input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8; + input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff; + + return 0; +} + +/** + * ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool + * @input: input stream to modify + * @vm_pool: the Virtual Machine pool to load + **/ +s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool) +{ + input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool; + + return 0; +} + +/** + * ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type + * @input: input stream to modify + * @l4type: the layer 4 type value to load + **/ +s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type) +{ + input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type; + + return 0; +} + +/** + * ixgbe_atr_get_vlan_id_82599 - Gets the VLAN id from the ATR input stream + * @input: input stream to search + * @vlan: the VLAN id to load + **/ +s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan) +{ + *vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET]; + *vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8; + + return 0; +} + +/** + * ixgbe_atr_get_src_ipv4_82599 - Gets the source IPv4 address + * @input: input stream to search + * @src_addr: the IP address to load + **/ +s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr) +{ + *src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET]; + *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8; + *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16; + *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] << 24; + + return 0; +} + +/** + * ixgbe_atr_get_dst_ipv4_82599 - Gets the destination IPv4 address + * @input: input stream to search + * @dst_addr: the IP address to load + **/ +s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr) +{ + *dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET]; + *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8; + *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16; + *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] << 24; + + return 0; +} + +/** + * ixgbe_atr_get_src_ipv6_82599 - Gets the source IPv6 address + * @input: input stream to search + * @src_addr_1: the first 4 bytes of the IP address to load + * @src_addr_2: the second 4 bytes of the IP address to load + * @src_addr_3: the third 4 bytes of the IP address to load + * @src_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, + u32 *src_addr_1, u32 *src_addr_2, + u32 *src_addr_3, u32 *src_addr_4) +{ + *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12]; + *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8; + *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16; + *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] << 24; + + *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8]; + *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] << 8; + *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] << 16; + *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] << 24; + + *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4]; + *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] << 8; + *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] << 16; + *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] << 24; + + *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET]; + *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] << 8; + *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] << 16; + *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] << 24; + + return 0; +} + +/** + * ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address + * @input: input stream to search + * @dst_addr_1: the first 4 bytes of the IP address to load + * @dst_addr_2: the second 4 bytes of the IP address to load + * @dst_addr_3: the third 4 bytes of the IP address to load + * @dst_addr_4: the fourth 4 bytes of the IP address to load + **/ +s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, + u32 *dst_addr_1, u32 *dst_addr_2, + u32 *dst_addr_3, u32 *dst_addr_4) +{ + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12]; + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8; + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16; + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24; + + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8]; + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8; + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16; + *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24; + + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4]; + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8; + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16; + *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24; + + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET]; + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8; + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16; + *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24; + + return 0; +} + +/** + * ixgbe_atr_get_src_port_82599 - Gets the source port + * @input: input stream to modify + * @src_port: the source port to load + * + * Even though the input is given in big-endian, the FDIRPORT registers + * expect the ports to be programmed in little-endian. Hence the need to swap + * endianness when retrieving the data. This can be confusing since the + * internal hash engine expects it to be big-endian. + **/ +s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port) +{ + *src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8; + *src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1]; + + return 0; +} + +/** + * ixgbe_atr_get_dst_port_82599 - Gets the destination port + * @input: input stream to modify + * @dst_port: the destination port to load + * + * Even though the input is given in big-endian, the FDIRPORT registers + * expect the ports to be programmed in little-endian. Hence the need to swap + * endianness when retrieving the data. This can be confusing since the + * internal hash engine expects it to be big-endian. + **/ +s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port) +{ + *dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8; + *dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1]; + + return 0; +} + +/** + * ixgbe_atr_get_flex_byte_82599 - Gets the flexible bytes + * @input: input stream to modify + * @flex_bytes: the flexible bytes to load + **/ +s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte) +{ + *flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET]; + *flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8; + + return 0; +} + +/** + * ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool + * @input: input stream to modify + * @vm_pool: the Virtual Machine pool to load + **/ +s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool) +{ + *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET]; + + return 0; +} + +/** + * ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type + * @input: input stream to modify + * @l4type: the layer 4 type value to load + **/ +s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type) +{ + *l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET]; + + return 0; +} + +/** + * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter + * @hw: pointer to hardware structure + * @stream: input bitstream + * @queue: queue index to direct traffic to + **/ +s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, + struct ixgbe_atr_input *input, + u8 queue) +{ + u64 fdirhashcmd; + u64 fdircmd; + u32 fdirhash; + u16 bucket_hash, sig_hash; + u8 l4type; + + bucket_hash = ixgbe_atr_compute_hash_82599(input, + IXGBE_ATR_BUCKET_HASH_KEY); + + /* bucket_hash is only 15 bits */ + bucket_hash &= IXGBE_ATR_HASH_MASK; + + sig_hash = ixgbe_atr_compute_hash_82599(input, + IXGBE_ATR_SIGNATURE_HASH_KEY); + + /* Get the l4type in order to program FDIRCMD properly */ + /* lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */ + ixgbe_atr_get_l4type_82599(input, &l4type); + + /* + * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits + * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH. + */ + fdirhash = sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash; + + fdircmd = (IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | + IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN); + + switch (l4type & IXGBE_ATR_L4TYPE_MASK) { + case IXGBE_ATR_L4TYPE_TCP: + fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP; + break; + case IXGBE_ATR_L4TYPE_UDP: + fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP; + break; + case IXGBE_ATR_L4TYPE_SCTP: + fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP; + break; + default: + hw_dbg(hw, "Error on l4type input\n"); + return IXGBE_ERR_CONFIG; + } + + if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) + fdircmd |= IXGBE_FDIRCMD_IPV6; + + fdircmd |= ((u64)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT); + fdirhashcmd = ((fdircmd << 32) | fdirhash); + + IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd); + + return 0; +} + +/** + * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter + * @hw: pointer to hardware structure + * @input: input bitstream + * @queue: queue index to direct traffic to + * + * Note that the caller to this function must lock before calling, since the + * hardware writes must be protected from one another. + **/ +s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, + struct ixgbe_atr_input *input, + u16 soft_id, + u8 queue) +{ + u32 fdircmd = 0; + u32 fdirhash; + u32 src_ipv4, dst_ipv4; + u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4; + u16 src_port, dst_port, vlan_id, flex_bytes; + u16 bucket_hash; + u8 l4type; + + /* Get our input values */ + ixgbe_atr_get_l4type_82599(input, &l4type); + + /* + * Check l4type formatting, and bail out before we touch the hardware + * if there's a configuration issue + */ + switch (l4type & IXGBE_ATR_L4TYPE_MASK) { + case IXGBE_ATR_L4TYPE_TCP: + fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP; + break; + case IXGBE_ATR_L4TYPE_UDP: + fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP; + break; + case IXGBE_ATR_L4TYPE_SCTP: + fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP; + break; + default: + hw_dbg(hw, "Error on l4type input\n"); + return IXGBE_ERR_CONFIG; + } + + bucket_hash = ixgbe_atr_compute_hash_82599(input, + IXGBE_ATR_BUCKET_HASH_KEY); + + /* bucket_hash is only 15 bits */ + bucket_hash &= IXGBE_ATR_HASH_MASK; + + ixgbe_atr_get_vlan_id_82599(input, &vlan_id); + ixgbe_atr_get_src_port_82599(input, &src_port); + ixgbe_atr_get_dst_port_82599(input, &dst_port); + ixgbe_atr_get_flex_byte_82599(input, &flex_bytes); + + fdirhash = soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash; + + /* Now figure out if we're IPv4 or IPv6 */ + if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) { + /* IPv6 */ + ixgbe_atr_get_src_ipv6_82599(input, &src_ipv6_1, &src_ipv6_2, + &src_ipv6_3, &src_ipv6_4); + + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), src_ipv6_1); + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), src_ipv6_2); + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), src_ipv6_3); + /* The last 4 bytes is the same register as IPv4 */ + IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv6_4); + + fdircmd |= IXGBE_FDIRCMD_IPV6; + fdircmd |= IXGBE_FDIRCMD_IPv6DMATCH; + } else { + /* IPv4 */ + ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4); + IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4); + + } + + ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4); + IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, dst_ipv4); + + IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id | + (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT))); + IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port | + (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); + + fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW; + fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE; + fdircmd |= IXGBE_FDIRCMD_LAST; + fdircmd |= IXGBE_FDIRCMD_QUEUE_EN; + fdircmd |= queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; + + IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); + IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); + + return 0; +} /** * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register * @hw: pointer to hardware structure @@ -1056,8 +2142,9 @@ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) { u32 q_num; + s32 ret_val; - ixgbe_start_hw_generic(hw); + ret_val = ixgbe_start_hw_generic(hw); /* Clear the rate limiters */ for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) { @@ -1066,7 +2153,13 @@ s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) } IXGBE_WRITE_FLUSH(hw); - return 0; + /* We need to run link autotry after the driver loads */ + hw->mac.autotry_restart = true; + + if (ret_val == 0) + ret_val = ixgbe_verify_fw_version_82599(hw); + + return ret_val; } /** @@ -1093,53 +2186,100 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); + u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; + u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; + u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; + u16 ext_ability = 0; u8 comp_codes_10g = 0; - switch (hw->device_id) { - case IXGBE_DEV_ID_82599: - case IXGBE_DEV_ID_82599_KX4: - /* Default device ID is mezzanine card KX/KX4 */ - physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | - IXGBE_PHYSICAL_LAYER_1000BASE_KX); - break; - case IXGBE_DEV_ID_82599_SFP: - hw->phy.ops.identify_sfp(hw); + hw->phy.ops.identify(hw); - switch (hw->phy.sfp_type) { - case ixgbe_sfp_type_da_cu: - case ixgbe_sfp_type_da_cu_core0: - case ixgbe_sfp_type_da_cu_core1: - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; - break; - case ixgbe_sfp_type_sr: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; - break; - case ixgbe_sfp_type_lr: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; - break; - case ixgbe_sfp_type_srlr_core0: - case ixgbe_sfp_type_srlr_core1: - hw->phy.ops.read_i2c_eeprom(hw, - IXGBE_SFF_10GBE_COMP_CODES, - &comp_codes_10g); - if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) - physical_layer = - IXGBE_PHYSICAL_LAYER_10GBASE_SR; - else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) - physical_layer = - IXGBE_PHYSICAL_LAYER_10GBASE_LR; - else - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; - default: - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; - break; - } + if (hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_cu_unknown) { + hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD, + &ext_ability); + if (ext_ability & MDIO_PMA_EXTABLE_10GBT) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; + if (ext_ability & MDIO_PMA_EXTABLE_1000BT) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; + if (ext_ability & MDIO_PMA_EXTABLE_100BTX) + physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; + goto out; + } + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { + case IXGBE_AUTOC_LMS_1G_AN: + case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: + if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) { + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX | + IXGBE_PHYSICAL_LAYER_1000BASE_BX; + goto out; + } else + /* SFI mode so read SFP module */ + goto sfp_check; + break; + case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: + if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; + else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; + else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI; + goto out; + break; + case IXGBE_AUTOC_LMS_10G_SERIAL: + if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) { + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR; + goto out; + } else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) + goto sfp_check; + break; + case IXGBE_AUTOC_LMS_KX4_KX_KR: + case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: + if (autoc & IXGBE_AUTOC_KX_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; + if (autoc & IXGBE_AUTOC_KX4_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; + if (autoc & IXGBE_AUTOC_KR_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR; + goto out; break; default: - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + goto out; break; } +sfp_check: + /* SFP check must be done last since DA modules are sometimes used to + * test KR mode - we need to id KR mode correctly before SFP module. + * Call identify_sfp because the pluggable module may have changed */ + hw->phy.ops.identify_sfp(hw); + if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) + goto out; + + switch (hw->phy.type) { + case ixgbe_phy_tw_tyco: + case ixgbe_phy_tw_unknown: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + break; + case ixgbe_phy_sfp_avago: + case ixgbe_phy_sfp_ftl: + case ixgbe_phy_sfp_intel: + case ixgbe_phy_sfp_unknown: + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); + if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + break; + default: + break; + } + +out: return physical_layer; } @@ -1187,6 +2327,138 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) return 0; } +/** + * ixgbe_get_device_caps_82599 - Get additional device capabilities + * @hw: pointer to hardware structure + * @device_caps: the EEPROM word with the extra device capabilities + * + * This function will read the EEPROM location for the device capabilities, + * and return the word through device_caps. + **/ +s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps) +{ + hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); + + return 0; +} + +/** + * ixgbe_get_san_mac_addr_offset_82599 - SAN MAC address offset for 82599 + * @hw: pointer to hardware structure + * @san_mac_offset: SAN MAC address offset + * + * This function will read the EEPROM location for the SAN MAC address + * pointer, and returns the value at that location. This is used in both + * get and set mac_addr routines. + **/ +s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw, + u16 *san_mac_offset) +{ + /* + * First read the EEPROM pointer to see if the MAC addresses are + * available. + */ + hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); + + return 0; +} + +/** + * ixgbe_get_san_mac_addr_82599 - SAN MAC address retrieval for 82599 + * @hw: pointer to hardware structure + * @san_mac_addr: SAN MAC address + * + * Reads the SAN MAC address from the EEPROM, if it's available. This is + * per-port, so set_lan_id() must be called before reading the addresses. + * set_lan_id() is called by identify_sfp(), but this cannot be relied + * upon for non-SFP connections, so we must call it here. + **/ +s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr) +{ + u16 san_mac_data, san_mac_offset; + u8 i; + + /* + * First read the EEPROM pointer to see if the MAC addresses are + * available. If they're not, no point in calling set_lan_id() here. + */ + ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset); + + if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { + /* + * No addresses available in this EEPROM. It's not an + * error though, so just wipe the local address and return. + */ + for (i = 0; i < 6; i++) + san_mac_addr[i] = 0xFF; + + goto san_mac_addr_out; + } + + /* make sure we know which port we need to program */ + hw->mac.ops.set_lan_id(hw); + /* apply the port offset to the address offset */ + (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : + (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); + for (i = 0; i < 3; i++) { + hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); + san_mac_addr[i * 2] = (u8)(san_mac_data); + san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); + san_mac_offset++; + } + +san_mac_addr_out: + return 0; +} + +/** + * ixgbe_verify_fw_version_82599 - verify fw version for 82599 + * @hw: pointer to hardware structure + * + * Verifies that installed the firmware version is 0.6 or higher + * for SFI devices. All 82599 SFI devices should have version 0.6 or higher. + * + * Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or + * if the FW version is not supported. + **/ +static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_ERR_EEPROM_VERSION; + u16 fw_offset, fw_ptp_cfg_offset; + u16 fw_version = 0; + + /* firmware check is only necessary for SFI devices */ + if (hw->phy.media_type != ixgbe_media_type_fiber) { + status = 0; + goto fw_version_out; + } + + /* get the offset to the Firmware Module block */ + hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset); + + if ((fw_offset == 0) || (fw_offset == 0xFFFF)) + goto fw_version_out; + + /* get the offset to the Pass Through Patch Configuration block */ + hw->eeprom.ops.read(hw, (fw_offset + + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR), + &fw_ptp_cfg_offset); + + if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF)) + goto fw_version_out; + + /* get the firmware version */ + hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset + + IXGBE_FW_PATCH_VERSION_4), + &fw_version); + + if (fw_version > 0x5) + status = 0; + +fw_version_out: + return status; +} + static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, @@ -1196,6 +2468,8 @@ static struct ixgbe_mac_operations mac_ops_82599 = { .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82599, .enable_rx_dma = &ixgbe_enable_rx_dma_82599, .get_mac_addr = &ixgbe_get_mac_addr_generic, + .get_san_mac_addr = &ixgbe_get_san_mac_addr_82599, + .get_device_caps = &ixgbe_get_device_caps_82599, .stop_adapter = &ixgbe_stop_adapter_generic, .get_bus_info = &ixgbe_get_bus_info_generic, .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, @@ -1220,7 +2494,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { .disable_mc = &ixgbe_disable_mc_generic, .clear_vfta = &ixgbe_clear_vfta_82599, .set_vfta = &ixgbe_set_vfta_82599, - .setup_fc = &ixgbe_setup_fc_generic, + .fc_enable = &ixgbe_fc_enable_generic, .init_uta_tables = &ixgbe_init_uta_tables_82599, .setup_sfp = &ixgbe_setup_sfp_modules_82599, }; @@ -1236,6 +2510,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = { static struct ixgbe_phy_operations phy_ops_82599 = { .identify = &ixgbe_identify_phy_82599, .identify_sfp = &ixgbe_identify_sfp_module_generic, + .init = &ixgbe_init_phy_ops_82599, .reset = &ixgbe_reset_phy_generic, .read_reg = &ixgbe_read_phy_reg_generic, .write_reg = &ixgbe_write_phy_reg_generic, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 186a65069b33..96a185953777 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "ixgbe.h" #include "ixgbe_common.h" @@ -71,12 +73,6 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) /* Identify the PHY */ hw->phy.ops.identify(hw); - /* - * Store MAC address from RAR0, clear receive address registers, and - * clear the multicast table - */ - hw->mac.ops.init_rx_addrs(hw); - /* Clear the VLAN filter table */ hw->mac.ops.clear_vfta(hw); @@ -89,6 +85,9 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); + /* Setup flow control */ + ixgbe_setup_fc(hw, 0); + /* Clear adapter stopped flag */ hw->adapter_stopped = false; @@ -107,13 +106,17 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) **/ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) { + s32 status; + /* Reset the hardware */ - hw->mac.ops.reset_hw(hw); + status = hw->mac.ops.reset_hw(hw); - /* Start the HW */ - hw->mac.ops.start_hw(hw); + if (status == 0) { + /* Start the HW */ + status = hw->mac.ops.start_hw(hw); + } - return 0; + return status; } /** @@ -1362,15 +1365,14 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) * Drivers using secondary unicast addresses must set user_set_promisc when * manually putting the device into promiscuous mode. **/ -s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, - u32 addr_count, ixgbe_mc_addr_itr next) +s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, + struct list_head *uc_list) { - u8 *addr; u32 i; u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; u32 uc_addr_in_use; u32 fctrl; - u32 vmdq; + struct netdev_hw_addr *ha; /* * Clear accounting of old secondary address list, @@ -1388,10 +1390,9 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, } /* Add the new addresses */ - for (i = 0; i < addr_count; i++) { + list_for_each_entry(ha, uc_list, list) { hw_dbg(hw, " Adding the secondary addresses:\n"); - addr = next(hw, &addr_list, &vmdq); - ixgbe_add_uc_addr(hw, addr, vmdq); + ixgbe_add_uc_addr(hw, ha->addr, 0); } if (hw->addr_ctrl.overflow_promisc) { @@ -1583,19 +1584,30 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) } /** - * ixgbe_fc_enable - Enable flow control + * ixgbe_fc_enable_generic - Enable flow control * @hw: pointer to hardware structure * @packetbuf_num: packet buffer number (0-7) * * Enable flow control according to the current settings. **/ -s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) +s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) { s32 ret_val = 0; - u32 mflcn_reg; - u32 fccfg_reg; + u32 mflcn_reg, fccfg_reg; u32 reg; + u32 rx_pba_size; +#ifdef CONFIG_DCB + if (hw->fc.requested_mode == ixgbe_fc_pfc) + goto out; + +#endif /* CONFIG_DCB */ + /* Negotiate the fc mode to use */ + ret_val = ixgbe_fc_autoneg(hw); + if (ret_val) + goto out; + + /* Disable any previous flow control settings */ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE); @@ -1615,7 +1627,10 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) */ switch (hw->fc.current_mode) { case ixgbe_fc_none: - /* Flow control completely disabled by software override. */ + /* + * Flow control is disabled by software override or autoneg. + * The code below will actually disable it in the HW. + */ break; case ixgbe_fc_rx_pause: /* @@ -1644,7 +1659,7 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) case ixgbe_fc_pfc: goto out; break; -#endif +#endif /* CONFIG_DCB */ default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = -IXGBE_ERR_CONFIG; @@ -1652,25 +1667,48 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) break; } - /* Enable 802.3x based flow control settings. */ + /* Set 802.3x based flow control settings. */ + mflcn_reg |= IXGBE_MFLCN_DPF; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); - /* Set up and enable Rx high/low water mark thresholds, enable XON. */ - if (hw->fc.current_mode & ixgbe_fc_tx_pause) { - if (hw->fc.send_xon) - IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), - (hw->fc.low_water | IXGBE_FCRTL_XONE)); - else - IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), - hw->fc.low_water); + reg = IXGBE_READ_REG(hw, IXGBE_MTQC); + /* Thresholds are different for link flow control when in DCB mode */ + if (reg & IXGBE_MTQC_RT_ENA) { + rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); - IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), - (hw->fc.high_water | IXGBE_FCRTH_FCEN)); + /* Always disable XON for LFC when in DCB mode */ + reg = (rx_pba_size >> 5) & 0xFFE0; + IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg); + + reg = (rx_pba_size >> 2) & 0xFFE0; + if (hw->fc.current_mode & ixgbe_fc_tx_pause) + reg |= IXGBE_FCRTH_FCEN; + IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg); + } else { + /* + * Set up and enable Rx high/low water mark thresholds, + * enable XON. + */ + if (hw->fc.current_mode & ixgbe_fc_tx_pause) { + if (hw->fc.send_xon) { + IXGBE_WRITE_REG(hw, + IXGBE_FCRTL_82599(packetbuf_num), + (hw->fc.low_water | + IXGBE_FCRTL_XONE)); + } else { + IXGBE_WRITE_REG(hw, + IXGBE_FCRTL_82599(packetbuf_num), + hw->fc.low_water); + } + + IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), + (hw->fc.high_water | IXGBE_FCRTH_FCEN)); + } } /* Configure pause time (2 TCs per register) */ - reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num)); + reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2)); if ((packetbuf_num & 1) == 0) reg = (reg & 0xFFFF0000) | hw->fc.pause_time; else @@ -1687,100 +1725,41 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) * ixgbe_fc_autoneg - Configure flow control * @hw: pointer to hardware structure * - * Negotiates flow control capabilities with link partner using autoneg and - * applies the results. + * Compares our advertised flow control capabilities to those advertised by + * our link partner, and determines the proper flow control mode to use. **/ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) { s32 ret_val = 0; - u32 i, reg, pcs_anadv_reg, pcs_lpab_reg; - - reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + ixgbe_link_speed speed; + u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; + bool link_up; /* - * The possible values of fc.current_mode are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but - * we do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - * 4: Priority Flow Control is enabled. - * other: Invalid. + * AN should have completed when the cable was plugged in. + * Look for reasons to bail out. Bail out if: + * - FC autoneg is disabled, or if + * - we don't have multispeed fiber, or if + * - we're not running at 1G, or if + * - link is not up, or if + * - link is up but AN did not complete, or if + * - link is up and AN completed but timed out + * + * Since we're being called from an LSC, link is already know to be up. + * So use link_up_wait_to_complete=false. */ - switch (hw->fc.current_mode) { - case ixgbe_fc_none: - /* Flow control completely disabled by software override. */ - reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); - break; - case ixgbe_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is - * disabled by software override. Since there really - * isn't a way to advertise that we are capable of RX - * Pause ONLY, we will advertise that we support both - * symmetric and asymmetric Rx PAUSE. Later, we will - * disable the adapter's ability to send PAUSE frames. - */ - reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); - break; - case ixgbe_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is - * disabled by software override. - */ - reg |= (IXGBE_PCS1GANA_ASM_PAUSE); - reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE); - break; - case ixgbe_fc_full: - /* Flow control (both Rx and Tx) is enabled by SW override. */ - reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); - break; -#ifdef CONFIG_DCB - case ixgbe_fc_pfc: - goto out; - break; -#endif - default: - hw_dbg(hw, "Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; - goto out; - break; - } + hw->mac.ops.check_link(hw, &speed, &link_up, false); + linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); - IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); - reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); - - /* Set PCS register for autoneg */ - /* Enable and restart autoneg */ - reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART; - - /* Disable AN timeout */ - if (hw->fc.strict_ieee) - reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; - - hw_dbg(hw, "Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg); - IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); - - /* See if autonegotiation has succeeded */ - hw->mac.autoneg_succeeded = 0; - for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - msleep(10); - reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); - if ((reg & (IXGBE_PCS1GLSTA_LINK_OK | - IXGBE_PCS1GLSTA_AN_COMPLETE)) == - (IXGBE_PCS1GLSTA_LINK_OK | - IXGBE_PCS1GLSTA_AN_COMPLETE)) { - if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT)) - hw->mac.autoneg_succeeded = 1; - break; - } - } - - if (!hw->mac.autoneg_succeeded) { - /* Autoneg failed to achieve a link, so we turn fc off */ - hw->fc.current_mode = ixgbe_fc_none; - hw_dbg(hw, "Flow Control = NONE.\n"); + if (hw->fc.disable_fc_autoneg || + !hw->phy.multispeed_fiber || + (speed != IXGBE_LINK_SPEED_1GB_FULL) || + !link_up || + ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || + ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; + hw_dbg(hw, "Autoneg FC was skipped.\n"); goto out; } @@ -1823,21 +1802,23 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) hw_dbg(hw, "Flow Control = NONE.\n"); } + /* Record that current_mode is the result of a successful autoneg */ + hw->fc.fc_was_autonegged = true; + out: return ret_val; } /** - * ixgbe_setup_fc_generic - Set up flow control + * ixgbe_setup_fc - Set up flow control * @hw: pointer to hardware structure * - * Sets up flow control. + * Called at init time to set up flow control. **/ -s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num) +s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) { s32 ret_val = 0; - ixgbe_link_speed speed; - bool link_up; + u32 reg; #ifdef CONFIG_DCB if (hw->fc.requested_mode == ixgbe_fc_pfc) { @@ -1866,7 +1847,7 @@ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num) /* * Validate the requested mode. Strict IEEE mode does not allow - * ixgbe_fc_rx_pause because it will cause testing anomalies. + * ixgbe_fc_rx_pause because it will cause us to fail at UNH. */ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict " @@ -1883,21 +1864,77 @@ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num) hw->fc.requested_mode = ixgbe_fc_full; /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. + * Set up the 1G flow control advertisement registers so the HW will be + * able to do fc autoneg once the cable is plugged in. If we end up + * using 10g instead, this is harmless. */ - hw->fc.current_mode = hw->fc.requested_mode; + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); - /* Decide whether to use autoneg or not. */ - hw->mac.ops.check_link(hw, &speed, &link_up, false); - if (!hw->fc.disable_fc_autoneg && hw->phy.multispeed_fiber && - (speed == IXGBE_LINK_SPEED_1GB_FULL)) - ret_val = ixgbe_fc_autoneg(hw); - - if (ret_val) + /* + * The possible values of fc.requested_mode are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. +#ifdef CONFIG_DCB + * 4: Priority Flow Control is enabled. +#endif + * other: Invalid. + */ + switch (hw->fc.requested_mode) { + case ixgbe_fc_none: + /* Flow control completely disabled by software override. */ + reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); + break; + case ixgbe_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); + break; + case ixgbe_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. + */ + reg |= (IXGBE_PCS1GANA_ASM_PAUSE); + reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE); + break; + case ixgbe_fc_full: + /* Flow control (both Rx and Tx) is enabled by SW override. */ + reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); + break; +#ifdef CONFIG_DCB + case ixgbe_fc_pfc: goto out; + break; +#endif /* CONFIG_DCB */ + default: + hw_dbg(hw, "Flow control param set incorrectly\n"); + ret_val = -IXGBE_ERR_CONFIG; + goto out; + break; + } - ret_val = ixgbe_fc_enable(hw, packetbuf_num); + IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); + + /* Enable and restart autoneg to inform the link partner */ + reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART; + + /* Disable AN timeout */ + if (hw->fc.strict_ieee) + reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; + + IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); + hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg); out: return ret_val; @@ -2044,6 +2081,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) { + autoc_reg |= IXGBE_AUTOC_AN_RESTART; autoc_reg |= IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); msleep(10); diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index dd260890ad0a..0d34d4d8244c 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -59,13 +59,13 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw); s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func); -s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, - u32 addr_count, ixgbe_mc_addr_itr func); +s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, + struct list_head *uc_list); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); -s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num); -s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packtetbuf_num); +s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); +s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packtetbuf_num); s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw); s32 ixgbe_validate_mac_addr(u8 *mac_addr); diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index 62206273d888..f30263898ebc 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -294,6 +294,9 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u32 reg, rx_pba_size; u8 i; + if (!dcb_config->pfc_mode_enable) + goto out; + /* Enable Transmit Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_RMCS); reg &= ~IXGBE_RMCS_TFCE_802_3X; @@ -341,6 +344,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400); +out: return 0; } diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index f4417fc3b0fd..589f62c7062a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -295,7 +295,7 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, /* If PFC is disabled globally then fall back to LFC. */ if (!dcb_config->pfc_mode_enable) { for (i = 0; i < MAX_TRAFFIC_CLASS; i++) - hw->mac.ops.setup_fc(hw, i); + hw->mac.ops.fc_enable(hw, i); goto out; } diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index bd0a0c276952..d56890f5c9d5 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -28,15 +28,22 @@ #include "ixgbe.h" #include +#include "ixgbe_dcb_82598.h" +#include "ixgbe_dcb_82599.h" /* Callbacks for DCB netlink in the kernel */ #define BIT_DCB_MODE 0x01 #define BIT_PFC 0x02 #define BIT_PG_RX 0x04 #define BIT_PG_TX 0x08 -#define BIT_BCN 0x10 +#define BIT_RESETLINK 0x40 #define BIT_LINKSPEED 0x80 +/* Responses for the DCB_C_SET_ALL command */ +#define DCB_HW_CHG_RST 0 /* DCB configuration changed with reset */ +#define DCB_NO_HW_CHG 1 /* DCB configuration did not change */ +#define DCB_HW_CHG 2 /* DCB configuration changed, no reset */ + int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) { @@ -124,15 +131,12 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); - ixgbe_reset_interrupt_capability(adapter); - ixgbe_napi_del_all(adapter); - INIT_LIST_HEAD(&netdev->napi_list); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - adapter->tx_ring = NULL; - adapter->rx_ring = NULL; + ixgbe_clear_interrupt_scheme(adapter); - adapter->hw.fc.requested_mode = ixgbe_fc_pfc; + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + adapter->last_lfc_mode = adapter->hw.fc.current_mode; + adapter->hw.fc.requested_mode = ixgbe_fc_none; + } adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; adapter->flags |= IXGBE_FLAG_DCB_ENABLED; ixgbe_init_interrupt_scheme(adapter); @@ -141,17 +145,13 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) } else { /* Turn off DCB */ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - adapter->hw.fc.requested_mode = ixgbe_fc_default; if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); - ixgbe_reset_interrupt_capability(adapter); - ixgbe_napi_del_all(adapter); - INIT_LIST_HEAD(&netdev->napi_list); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - adapter->tx_ring = NULL; - adapter->rx_ring = NULL; + ixgbe_clear_interrupt_scheme(adapter); + adapter->hw.fc.requested_mode = adapter->last_lfc_mode; + adapter->temp_dcb_cfg.pfc_mode_enable = false; + adapter->dcb_cfg.pfc_mode_enable = false; adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; ixgbe_init_interrupt_scheme(adapter); @@ -167,10 +167,15 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, u8 *perm_addr) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - int i; + int i, j; for (i = 0; i < netdev->addr_len; i++) perm_addr[i] = adapter->hw.mac.perm_addr[i]; + + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + for (j = 0; j < netdev->addr_len; j++, i++) + perm_addr[i] = adapter->hw.mac.san_addr[j]; + } } static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, @@ -197,8 +202,10 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != - adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) + adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) { adapter->dcb_set_bitmap |= BIT_PG_TX; + adapter->dcb_set_bitmap |= BIT_RESETLINK; + } } static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, @@ -209,8 +216,10 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != - adapter->dcb_cfg.bw_percentage[0][bwg_id]) + adapter->dcb_cfg.bw_percentage[0][bwg_id]) { adapter->dcb_set_bitmap |= BIT_PG_RX; + adapter->dcb_set_bitmap |= BIT_RESETLINK; + } } static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, @@ -237,8 +246,10 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != - adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) + adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) { adapter->dcb_set_bitmap |= BIT_PG_RX; + adapter->dcb_set_bitmap |= BIT_RESETLINK; + } } static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, @@ -249,8 +260,10 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != - adapter->dcb_cfg.bw_percentage[1][bwg_id]) + adapter->dcb_cfg.bw_percentage[1][bwg_id]) { adapter->dcb_set_bitmap |= BIT_PG_RX; + adapter->dcb_set_bitmap |= BIT_RESETLINK; + } } static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, @@ -319,28 +332,60 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) struct ixgbe_adapter *adapter = netdev_priv(netdev); int ret; - adapter->dcb_set_bitmap &= ~BIT_BCN; /* no set for BCN */ if (!adapter->dcb_set_bitmap) - return 1; + return DCB_NO_HW_CHG; - while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) - msleep(1); + /* + * Only take down the adapter if the configuration change + * requires a reset. + */ + if (adapter->dcb_set_bitmap & BIT_RESETLINK) { + while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) + msleep(1); - if (netif_running(netdev)) - ixgbe_down(adapter); + if (netif_running(netdev)) + ixgbe_down(adapter); + } ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, adapter->ring_feature[RING_F_DCB].indices); if (ret) { - clear_bit(__IXGBE_RESETTING, &adapter->state); - return ret; + if (adapter->dcb_set_bitmap & BIT_RESETLINK) + clear_bit(__IXGBE_RESETTING, &adapter->state); + return DCB_NO_HW_CHG; } - if (netif_running(netdev)) - ixgbe_up(adapter); + if (adapter->dcb_cfg.pfc_mode_enable) { + if ((adapter->hw.mac.type != ixgbe_mac_82598EB) && + (adapter->hw.fc.current_mode != ixgbe_fc_pfc)) + adapter->last_lfc_mode = adapter->hw.fc.current_mode; + adapter->hw.fc.requested_mode = ixgbe_fc_pfc; + } else { + if (adapter->hw.mac.type != ixgbe_mac_82598EB) + adapter->hw.fc.requested_mode = adapter->last_lfc_mode; + else + adapter->hw.fc.requested_mode = ixgbe_fc_none; + } + if (adapter->dcb_set_bitmap & BIT_RESETLINK) { + if (netif_running(netdev)) + ixgbe_up(adapter); + ret = DCB_HW_CHG_RST; + } else if (adapter->dcb_set_bitmap & BIT_PFC) { + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + ixgbe_dcb_config_pfc_82598(&adapter->hw, + &adapter->dcb_cfg); + else if (adapter->hw.mac.type == ixgbe_mac_82599EB) + ixgbe_dcb_config_pfc_82599(&adapter->hw, + &adapter->dcb_cfg); + ret = DCB_HW_CHG; + } + if (adapter->dcb_cfg.pfc_mode_enable) + adapter->hw.fc.current_mode = ixgbe_fc_pfc; + + if (adapter->dcb_set_bitmap & BIT_RESETLINK) + clear_bit(__IXGBE_RESETTING, &adapter->state); adapter->dcb_set_bitmap = 0x00; - clear_bit(__IXGBE_RESETTING, &adapter->state); return ret; } @@ -416,11 +461,17 @@ static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); + return adapter->dcb_cfg.pfc_mode_enable; } static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) { + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + adapter->temp_dcb_cfg.pfc_mode_enable = state; + if (adapter->temp_dcb_cfg.pfc_mode_enable != + adapter->dcb_cfg.pfc_mode_enable) + adapter->dcb_set_bitmap |= BIT_PFC; return; } diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index f0a20facc650..86f4f3e36f27 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -67,6 +67,9 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"rx_over_errors", IXGBE_STAT(net_stats.rx_over_errors)}, {"rx_crc_errors", IXGBE_STAT(net_stats.rx_crc_errors)}, {"rx_frame_errors", IXGBE_STAT(net_stats.rx_frame_errors)}, + {"hw_rsc_count", IXGBE_STAT(rsc_count)}, + {"fdir_match", IXGBE_STAT(stats.fdirmatch)}, + {"fdir_miss", IXGBE_STAT(stats.fdirmiss)}, {"rx_fifo_errors", IXGBE_STAT(net_stats.rx_fifo_errors)}, {"rx_missed_errors", IXGBE_STAT(net_stats.rx_missed_errors)}, {"tx_aborted_errors", IXGBE_STAT(net_stats.tx_aborted_errors)}, @@ -90,6 +93,14 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)}, {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)}, {"rx_no_dma_resources", IXGBE_STAT(hw_rx_no_dma_resources)}, +#ifdef IXGBE_FCOE + {"fcoe_bad_fccrc", IXGBE_STAT(stats.fccrc)}, + {"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)}, + {"rx_fcoe_packets", IXGBE_STAT(stats.fcoeprc)}, + {"rx_fcoe_dwords", IXGBE_STAT(stats.fcoedwrc)}, + {"tx_fcoe_packets", IXGBE_STAT(stats.fcoeptc)}, + {"tx_fcoe_dwords", IXGBE_STAT(stats.fcoedwtc)}, +#endif /* IXGBE_FCOE */ }; #define IXGBE_QUEUE_STATS_LEN \ @@ -109,6 +120,13 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { IXGBE_PB_STATS_LEN + \ IXGBE_QUEUE_STATS_LEN) +static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { + "Register test (offline)", "Eeprom test (offline)", + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" +}; +#define IXGBE_TEST_LEN sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN + static int ixgbe_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { @@ -120,11 +138,12 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->supported = SUPPORTED_10000baseT_Full; ecmd->autoneg = AUTONEG_ENABLE; ecmd->transceiver = XCVR_EXTERNAL; - if (hw->phy.media_type == ixgbe_media_type_copper) { + if ((hw->phy.media_type == ixgbe_media_type_copper) || + (hw->mac.type == ixgbe_mac_82599EB)) { ecmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_TP | SUPPORTED_Autoneg); + SUPPORTED_Autoneg); - ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg); + ecmd->advertising = ADVERTISED_Autoneg; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) ecmd->advertising |= ADVERTISED_10000baseT_Full; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) @@ -139,7 +158,15 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->advertising |= (ADVERTISED_10000baseT_Full | ADVERTISED_1000baseT_Full); - ecmd->port = PORT_TP; + if (hw->phy.media_type == ixgbe_media_type_copper) { + ecmd->supported |= SUPPORTED_TP; + ecmd->advertising |= ADVERTISED_TP; + ecmd->port = PORT_TP; + } else { + ecmd->supported |= SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_FIBRE; + ecmd->port = PORT_FIBRE; + } } else if (hw->phy.media_type == ixgbe_media_type_backplane) { /* Set as FIBRE until SERDES defined in kernel */ switch (hw->device_id) { @@ -187,16 +214,10 @@ static int ixgbe_set_settings(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 advertised, old; - s32 err; + s32 err = 0; - switch (hw->phy.media_type) { - case ixgbe_media_type_fiber: - if ((ecmd->autoneg == AUTONEG_ENABLE) || - (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) - return -EINVAL; - /* in this case we currently only support 10Gb/FULL */ - break; - case ixgbe_media_type_copper: + if ((hw->phy.media_type == ixgbe_media_type_copper) || + (hw->mac.type == ixgbe_mac_82599EB)) { /* 10000/copper and 1000/copper must autoneg * this function does not support any duplex forcing, but can * limit the advertising of the adapter to only 10000 or 1000 */ @@ -212,20 +233,23 @@ static int ixgbe_set_settings(struct net_device *netdev, advertised |= IXGBE_LINK_SPEED_1GB_FULL; if (old == advertised) - break; + return err; /* this sets the link speed and restarts auto-neg */ + hw->mac.autotry_restart = true; err = hw->mac.ops.setup_link_speed(hw, advertised, true, true); if (err) { DPRINTK(PROBE, INFO, "setup link failed with code %d\n", err); hw->mac.ops.setup_link_speed(hw, old, true, true); } - break; - default: - break; + } else { + /* in this case we currently only support 10Gb/FULL */ + if ((ecmd->autoneg == AUTONEG_ENABLE) || + (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) + return -EINVAL; } - return 0; + return err; } static void ixgbe_get_pauseparam(struct net_device *netdev, @@ -245,6 +269,13 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, else pause->autoneg = 1; +#ifdef CONFIG_DCB + if (hw->fc.current_mode == ixgbe_fc_pfc) { + pause->rx_pause = 0; + pause->tx_pause = 0; + } + +#endif if (hw->fc.current_mode == ixgbe_fc_rx_pause) { pause->rx_pause = 1; } else if (hw->fc.current_mode == ixgbe_fc_tx_pause) { @@ -260,24 +291,46 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_fc_info fc; + +#ifdef CONFIG_DCB + if (adapter->dcb_cfg.pfc_mode_enable || + ((hw->mac.type == ixgbe_mac_82598EB) && + (adapter->flags & IXGBE_FLAG_DCB_ENABLED))) + return -EINVAL; + +#endif + + fc = hw->fc; if (pause->autoneg != AUTONEG_ENABLE) - hw->fc.disable_fc_autoneg = true; + fc.disable_fc_autoneg = true; else - hw->fc.disable_fc_autoneg = false; + fc.disable_fc_autoneg = false; if (pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = ixgbe_fc_full; + fc.requested_mode = ixgbe_fc_full; else if (pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = ixgbe_fc_rx_pause; + fc.requested_mode = ixgbe_fc_rx_pause; else if (!pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = ixgbe_fc_tx_pause; + fc.requested_mode = ixgbe_fc_tx_pause; else if (!pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = ixgbe_fc_none; + fc.requested_mode = ixgbe_fc_none; else return -EINVAL; - hw->mac.ops.setup_fc(hw, 0); +#ifdef CONFIG_DCB + adapter->last_lfc_mode = fc.requested_mode; +#endif + + /* if the thing changed then we'll update and use new autoneg */ + if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) { + hw->fc = fc; + if (netif_running(netdev)) + ixgbe_reinit_locked(adapter); + else + ixgbe_reset(adapter); + } return 0; } @@ -311,10 +364,17 @@ static u32 ixgbe_get_tx_csum(struct net_device *netdev) static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data) { - if (data) + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + if (data) { netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + netdev->features |= NETIF_F_SCTP_CSUM; + } else { netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + netdev->features &= ~NETIF_F_SCTP_CSUM; + } return 0; } @@ -710,6 +770,7 @@ static void ixgbe_get_drvinfo(struct net_device *netdev, strncpy(drvinfo->fw_version, firmware_version, 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); drvinfo->n_stats = IXGBE_STATS_LEN; + drvinfo->testinfo_len = IXGBE_TEST_LEN; drvinfo->regdump_len = ixgbe_get_regs_len(netdev); } @@ -781,7 +842,6 @@ static int ixgbe_set_ringparam(struct net_device *netdev, } goto err_setup; } - temp_tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; } need_update = true; } @@ -811,7 +871,6 @@ static int ixgbe_set_ringparam(struct net_device *netdev, } goto err_setup; } - temp_rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; } need_update = true; } @@ -851,6 +910,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, static int ixgbe_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { + case ETH_SS_TEST: + return IXGBE_TEST_LEN; case ETH_SS_STATS: return IXGBE_STATS_LEN; default: @@ -905,6 +966,10 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, int i; switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *ixgbe_gstrings_test, + IXGBE_TEST_LEN * ETH_GSTRING_LEN); + break; case ETH_SS_STATS: for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { memcpy(p, ixgbe_gstrings_stats[i].stat_string, @@ -942,6 +1007,815 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, } } +static int ixgbe_link_test(struct ixgbe_adapter *adapter, u64 *data) +{ + struct ixgbe_hw *hw = &adapter->hw; + bool link_up; + u32 link_speed = 0; + *data = 0; + + hw->mac.ops.check_link(hw, &link_speed, &link_up, true); + if (link_up) + return *data; + else + *data = 1; + return *data; +} + +/* ethtool register test data */ +struct ixgbe_reg_test { + u16 reg; + u8 array_len; + u8 test_type; + u32 mask; + u32 write; +}; + +/* In the hardware, registers are laid out either singly, in arrays + * spaced 0x40 bytes apart, or in contiguous tables. We assume + * most tests take place on arrays or single registers (handled + * as a single-element array) and special-case the tables. + * Table tests are always pattern tests. + * + * We also make provision for some required setup steps by specifying + * registers to be written without any read-back testing. + */ + +#define PATTERN_TEST 1 +#define SET_READ_TEST 2 +#define WRITE_NO_TEST 3 +#define TABLE32_TEST 4 +#define TABLE64_TEST_LO 5 +#define TABLE64_TEST_HI 6 + +/* default 82599 register test */ +static struct ixgbe_reg_test reg_test_82599[] = { + { IXGBE_FCRTL_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, + { IXGBE_FCRTH_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, + { IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 }, + { IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, + { IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, + { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, + { IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 }, + { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, + { IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, + { IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000001, 0x00000001 }, + { IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x8001FFFF, 0x800CFFFF }, + { IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { 0, 0, 0, 0 } +}; + +/* default 82598 register test */ +static struct ixgbe_reg_test reg_test_82598[] = { + { IXGBE_FCRTL(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, + { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, + { IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 }, + { IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, + /* Enable all four RX queues before testing. */ + { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, + /* RDH is read-only for 82598, only test RDT. */ + { IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 }, + { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, + { IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_TIPG, 1, PATTERN_TEST, 0x000000FF, 0x000000FF }, + { IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, + { IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000003, 0x00000003 }, + { IXGBE_DTXCTL, 1, SET_READ_TEST, 0x00000005, 0x00000005 }, + { IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x800CFFFF, 0x800CFFFF }, + { IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { 0, 0, 0, 0 } +}; + +#define REG_PATTERN_TEST(R, M, W) \ +{ \ + u32 pat, val, before; \ + const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ + for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { \ + before = readl(adapter->hw.hw_addr + R); \ + writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \ + val = readl(adapter->hw.hw_addr + R); \ + if (val != (_test[pat] & W & M)) { \ + DPRINTK(DRV, ERR, "pattern test reg %04X failed: got "\ + "0x%08X expected 0x%08X\n", \ + R, val, (_test[pat] & W & M)); \ + *data = R; \ + writel(before, adapter->hw.hw_addr + R); \ + return 1; \ + } \ + writel(before, adapter->hw.hw_addr + R); \ + } \ +} + +#define REG_SET_AND_CHECK(R, M, W) \ +{ \ + u32 val, before; \ + before = readl(adapter->hw.hw_addr + R); \ + writel((W & M), (adapter->hw.hw_addr + R)); \ + val = readl(adapter->hw.hw_addr + R); \ + if ((W & M) != (val & M)) { \ + DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ + "expected 0x%08X\n", R, (val & M), (W & M)); \ + *data = R; \ + writel(before, (adapter->hw.hw_addr + R)); \ + return 1; \ + } \ + writel(before, (adapter->hw.hw_addr + R)); \ +} + +static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) +{ + struct ixgbe_reg_test *test; + u32 value, before, after; + u32 i, toggle; + + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + toggle = 0x7FFFF30F; + test = reg_test_82599; + } else { + toggle = 0x7FFFF3FF; + test = reg_test_82598; + } + + /* + * Because the status register is such a special case, + * we handle it separately from the rest of the register + * tests. Some bits are read-only, some toggle, and some + * are writeable on newer MACs. + */ + before = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS); + value = (IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, toggle); + after = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle; + if (value != after) { + DPRINTK(DRV, ERR, "failed STATUS register test got: " + "0x%08X expected: 0x%08X\n", after, value); + *data = 1; + return 1; + } + /* restore previous status */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, before); + + /* + * Perform the remainder of the register test, looping through + * the test table until we either fail or reach the null entry. + */ + while (test->reg) { + for (i = 0; i < test->array_len; i++) { + switch (test->test_type) { + case PATTERN_TEST: + REG_PATTERN_TEST(test->reg + (i * 0x40), + test->mask, + test->write); + break; + case SET_READ_TEST: + REG_SET_AND_CHECK(test->reg + (i * 0x40), + test->mask, + test->write); + break; + case WRITE_NO_TEST: + writel(test->write, + (adapter->hw.hw_addr + test->reg) + + (i * 0x40)); + break; + case TABLE32_TEST: + REG_PATTERN_TEST(test->reg + (i * 4), + test->mask, + test->write); + break; + case TABLE64_TEST_LO: + REG_PATTERN_TEST(test->reg + (i * 8), + test->mask, + test->write); + break; + case TABLE64_TEST_HI: + REG_PATTERN_TEST((test->reg + 4) + (i * 8), + test->mask, + test->write); + break; + } + } + test++; + } + + *data = 0; + return 0; +} + +static int ixgbe_eeprom_test(struct ixgbe_adapter *adapter, u64 *data) +{ + struct ixgbe_hw *hw = &adapter->hw; + if (hw->eeprom.ops.validate_checksum(hw, NULL)) + *data = 1; + else + *data = 0; + return *data; +} + +static irqreturn_t ixgbe_test_intr(int irq, void *data) +{ + struct net_device *netdev = (struct net_device *) data; + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + adapter->test_icr |= IXGBE_READ_REG(&adapter->hw, IXGBE_EICR); + + return IRQ_HANDLED; +} + +static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) +{ + struct net_device *netdev = adapter->netdev; + u32 mask, i = 0, shared_int = true; + u32 irq = adapter->pdev->irq; + + *data = 0; + + /* Hook up test interrupt handler just for this test */ + if (adapter->msix_entries) { + /* NOTE: we don't test MSI-X interrupts here, yet */ + return 0; + } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) { + shared_int = false; + if (request_irq(irq, &ixgbe_test_intr, 0, netdev->name, + netdev)) { + *data = 1; + return -1; + } + } else if (!request_irq(irq, &ixgbe_test_intr, IRQF_PROBE_SHARED, + netdev->name, netdev)) { + shared_int = false; + } else if (request_irq(irq, &ixgbe_test_intr, IRQF_SHARED, + netdev->name, netdev)) { + *data = 1; + return -1; + } + DPRINTK(HW, INFO, "testing %s interrupt\n", + (shared_int ? "shared" : "unshared")); + + /* Disable all the interrupts */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); + msleep(10); + + /* Test each interrupt */ + for (; i < 10; i++) { + /* Interrupt to test */ + mask = 1 << i; + + if (!shared_int) { + /* + * Disable the interrupts to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, + ~mask & 0x00007FFF); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, + ~mask & 0x00007FFF); + msleep(10); + + if (adapter->test_icr & mask) { + *data = 3; + break; + } + } + + /* + * Enable the interrupt to be reported in the cause + * register and then force the same interrupt and see + * if one gets posted. If an interrupt was not posted + * to the bus, the test failed. + */ + adapter->test_icr = 0; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); + msleep(10); + + if (!(adapter->test_icr &mask)) { + *data = 4; + break; + } + + if (!shared_int) { + /* + * Disable the other interrupts to be reported in + * the cause register and then force the other + * interrupts and see if any get posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, + ~mask & 0x00007FFF); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, + ~mask & 0x00007FFF); + msleep(10); + + if (adapter->test_icr) { + *data = 5; + break; + } + } + } + + /* Disable all the interrupts */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); + msleep(10); + + /* Unhook test interrupt handler */ + free_irq(irq, netdev); + + return *data; +} + +static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) +{ + struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; + struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; + struct ixgbe_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; + u32 reg_ctl; + int i; + + /* shut down the DMA engines now so they can be reinitialized later */ + + /* first Rx */ + reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + reg_ctl &= ~IXGBE_RXCTRL_RXEN; + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl); + reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(0)); + reg_ctl &= ~IXGBE_RXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(0), reg_ctl); + + /* now Tx */ + reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(0)); + reg_ctl &= ~IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(0), reg_ctl); + if (hw->mac.type == ixgbe_mac_82599EB) { + reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); + reg_ctl &= ~IXGBE_DMATXCTL_TE; + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl); + } + + ixgbe_reset(adapter); + + if (tx_ring->desc && tx_ring->tx_buffer_info) { + for (i = 0; i < tx_ring->count; i++) { + struct ixgbe_tx_buffer *buf = + &(tx_ring->tx_buffer_info[i]); + if (buf->dma) + pci_unmap_single(pdev, buf->dma, buf->length, + PCI_DMA_TODEVICE); + if (buf->skb) + dev_kfree_skb(buf->skb); + } + } + + if (rx_ring->desc && rx_ring->rx_buffer_info) { + for (i = 0; i < rx_ring->count; i++) { + struct ixgbe_rx_buffer *buf = + &(rx_ring->rx_buffer_info[i]); + if (buf->dma) + pci_unmap_single(pdev, buf->dma, + IXGBE_RXBUFFER_2048, + PCI_DMA_FROMDEVICE); + if (buf->skb) + dev_kfree_skb(buf->skb); + } + } + + if (tx_ring->desc) { + pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, + tx_ring->dma); + tx_ring->desc = NULL; + } + if (rx_ring->desc) { + pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, + rx_ring->dma); + rx_ring->desc = NULL; + } + + kfree(tx_ring->tx_buffer_info); + tx_ring->tx_buffer_info = NULL; + kfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + + return; +} + +static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) +{ + struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; + struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + u32 rctl, reg_data; + int i, ret_val; + + /* Setup Tx descriptor ring and Tx buffers */ + + if (!tx_ring->count) + tx_ring->count = IXGBE_DEFAULT_TXD; + + tx_ring->tx_buffer_info = kcalloc(tx_ring->count, + sizeof(struct ixgbe_tx_buffer), + GFP_KERNEL); + if (!(tx_ring->tx_buffer_info)) { + ret_val = 1; + goto err_nomem; + } + + tx_ring->size = tx_ring->count * sizeof(struct ixgbe_legacy_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + if (!(tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, + &tx_ring->dma))) { + ret_val = 2; + goto err_nomem; + } + tx_ring->next_to_use = tx_ring->next_to_clean = 0; + + IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAL(0), + ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); + 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)); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); + reg_data |= IXGBE_HLREG0_TXPADEN; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); + + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL); + reg_data |= IXGBE_DMATXCTL_TE; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data); + } + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(0)); + reg_data |= IXGBE_TXDCTL_ENABLE; + 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); + struct sk_buff *skb; + unsigned int size = 1024; + + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) { + ret_val = 3; + goto err_nomem; + } + skb_put(skb, size); + tx_ring->tx_buffer_info[i].skb = skb; + 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; + } + + /* Setup Rx Descriptor ring and Rx buffers */ + + if (!rx_ring->count) + rx_ring->count = IXGBE_DEFAULT_RXD; + + rx_ring->rx_buffer_info = kcalloc(rx_ring->count, + sizeof(struct ixgbe_rx_buffer), + GFP_KERNEL); + if (!(rx_ring->rx_buffer_info)) { + ret_val = 4; + goto err_nomem; + } + + rx_ring->size = rx_ring->count * sizeof(struct ixgbe_legacy_rx_desc); + rx_ring->size = ALIGN(rx_ring->size, 4096); + if (!(rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size, + &rx_ring->dma))) { + ret_val = 5; + goto err_nomem; + } + rx_ring->next_to_use = rx_ring->next_to_clean = 0; + + rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl & ~IXGBE_RXCTRL_RXEN); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAL(0), + ((u64)rx_ring->dma & 0xFFFFFFFF)); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAH(0), + ((u64) rx_ring->dma >> 32)); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDLEN(0), rx_ring->size); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDH(0), 0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), 0); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); + reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); + reg_data &= ~IXGBE_HLREG0_LPBK; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RDRXCTL); +#define IXGBE_RDRXCTL_RDMTS_MASK 0x00000003 /* Receive Descriptor Minimum + Threshold Size mask */ + reg_data &= ~IXGBE_RDRXCTL_RDMTS_MASK; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDRXCTL, reg_data); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MCSTCTRL); +#define IXGBE_MCSTCTRL_MO_MASK 0x00000003 /* Multicast Offset mask */ + reg_data &= ~IXGBE_MCSTCTRL_MO_MASK; + reg_data |= adapter->hw.mac.mc_filter_type; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_MCSTCTRL, reg_data); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(0)); + reg_data |= IXGBE_RXDCTL_ENABLE; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + int j = adapter->rx_ring[0].reg_idx; + u32 k; + for (k = 0; k < 10; k++) { + if (IXGBE_READ_REG(&adapter->hw, + IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE) + break; + else + msleep(1); + } + } + + rctl |= IXGBE_RXCTRL_RXEN | IXGBE_RXCTRL_DMBYPS; + 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); + struct sk_buff *skb; + + skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL); + if (!skb) { + ret_val = 6; + goto err_nomem; + } + skb_reserve(skb, NET_IP_ALIGN); + rx_ring->rx_buffer_info[i].skb = skb; + rx_ring->rx_buffer_info[i].dma = + pci_map_single(pdev, skb->data, IXGBE_RXBUFFER_2048, + PCI_DMA_FROMDEVICE); + rx_desc->buffer_addr = + cpu_to_le64(rx_ring->rx_buffer_info[i].dma); + memset(skb->data, 0x00, skb->len); + } + + return 0; + +err_nomem: + ixgbe_free_desc_rings(adapter); + return ret_val; +} + +static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 reg_data; + + /* right now we only support MAC loopback in the driver */ + + /* Setup MAC loopback */ + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); + reg_data |= IXGBE_HLREG0_LPBK; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC); + reg_data &= ~IXGBE_AUTOC_LMS_MASK; + reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data); + + /* Disable Atlas Tx lanes; re-enabled in reset path */ + if (hw->mac.type == ixgbe_mac_82598EB) { + u8 atlas; + + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &atlas); + atlas |= IXGBE_ATLAS_PDN_TX_REG_EN; + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, atlas); + + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &atlas); + atlas |= IXGBE_ATLAS_PDN_TX_10G_QL_ALL; + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, atlas); + + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &atlas); + atlas |= IXGBE_ATLAS_PDN_TX_1G_QL_ALL; + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, atlas); + + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &atlas); + atlas |= IXGBE_ATLAS_PDN_TX_AN_QL_ALL; + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, atlas); + } + + return 0; +} + +static void ixgbe_loopback_cleanup(struct ixgbe_adapter *adapter) +{ + u32 reg_data; + + reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); + reg_data &= ~IXGBE_HLREG0_LPBK; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); +} + +static void ixgbe_create_lbtest_frame(struct sk_buff *skb, + unsigned int frame_size) +{ + memset(skb->data, 0xFF, frame_size); + frame_size &= ~1; + memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); + memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); + memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); +} + +static int ixgbe_check_lbtest_frame(struct sk_buff *skb, + unsigned int frame_size) +{ + frame_size &= ~1; + if (*(skb->data + 3) == 0xFF) { + if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && + (*(skb->data + frame_size / 2 + 12) == 0xAF)) { + return 0; + } + } + return 13; +} + +static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) +{ + struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; + struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + int i, j, k, l, lc, good_cnt, ret_val = 0; + unsigned long time; + + IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), rx_ring->count - 1); + + /* + * Calculate the loop count based on the largest descriptor ring + * The idea is to wrap the largest ring a number of times using 64 + * send/receive pairs during each loop + */ + + if (rx_ring->count <= tx_ring->count) + lc = ((tx_ring->count / 64) * 2) + 1; + else + lc = ((rx_ring->count / 64) * 2) + 1; + + k = l = 0; + for (j = 0; j <= lc; j++) { + for (i = 0; i < 64; i++) { + ixgbe_create_lbtest_frame( + tx_ring->tx_buffer_info[k].skb, + 1024); + pci_dma_sync_single_for_device(pdev, + tx_ring->tx_buffer_info[k].dma, + tx_ring->tx_buffer_info[k].length, + PCI_DMA_TODEVICE); + if (unlikely(++k == tx_ring->count)) + k = 0; + } + IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), k); + msleep(200); + /* set the start time for the receive */ + time = jiffies; + good_cnt = 0; + do { + /* receive the sent packets */ + pci_dma_sync_single_for_cpu(pdev, + rx_ring->rx_buffer_info[l].dma, + IXGBE_RXBUFFER_2048, + PCI_DMA_FROMDEVICE); + ret_val = ixgbe_check_lbtest_frame( + rx_ring->rx_buffer_info[l].skb, 1024); + if (!ret_val) + good_cnt++; + if (++l == rx_ring->count) + l = 0; + /* + * time + 20 msecs (200 msecs on 2.4) is more than + * enough time to complete the receives, if it's + * exceeded, break and error off + */ + } while (good_cnt < 64 && jiffies < (time + 20)); + if (good_cnt != 64) { + /* ret_val is the same as mis-compare */ + ret_val = 13; + break; + } + if (jiffies >= (time + 20)) { + /* Error code for time out error */ + ret_val = 14; + break; + } + } + + return ret_val; +} + +static int ixgbe_loopback_test(struct ixgbe_adapter *adapter, u64 *data) +{ + *data = ixgbe_setup_desc_rings(adapter); + if (*data) + goto out; + *data = ixgbe_setup_loopback_test(adapter); + if (*data) + goto err_loopback; + *data = ixgbe_run_loopback_test(adapter); + ixgbe_loopback_cleanup(adapter); + +err_loopback: + ixgbe_free_desc_rings(adapter); +out: + return *data; +} + +static void ixgbe_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + bool if_running = netif_running(netdev); + + set_bit(__IXGBE_TESTING, &adapter->state); + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { + /* Offline tests */ + + DPRINTK(HW, INFO, "offline testing starting\n"); + + /* Link test performed before hardware reset so autoneg doesn't + * interfere with test result */ + if (ixgbe_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if (if_running) + /* indicate we're in test mode */ + dev_close(netdev); + else + ixgbe_reset(adapter); + + DPRINTK(HW, INFO, "register testing starting\n"); + if (ixgbe_reg_test(adapter, &data[0])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + ixgbe_reset(adapter); + DPRINTK(HW, INFO, "eeprom testing starting\n"); + if (ixgbe_eeprom_test(adapter, &data[1])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + ixgbe_reset(adapter); + DPRINTK(HW, INFO, "interrupt testing starting\n"); + if (ixgbe_intr_test(adapter, &data[2])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + ixgbe_reset(adapter); + DPRINTK(HW, INFO, "loopback testing starting\n"); + if (ixgbe_loopback_test(adapter, &data[3])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + ixgbe_reset(adapter); + + clear_bit(__IXGBE_TESTING, &adapter->state); + if (if_running) + dev_open(netdev); + } else { + DPRINTK(HW, INFO, "online testing starting\n"); + /* Online tests */ + if (ixgbe_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* Online tests aren't run; pass by default */ + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0; + + clear_bit(__IXGBE_TESTING, &adapter->state); + } + msleep_interruptible(4 * 1000); +} static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, struct ethtool_wolinfo *wol) @@ -1106,20 +1980,40 @@ static int ixgbe_set_coalesce(struct net_device *netdev, } for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; + struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; if (q_vector->txr_count && !q_vector->rxr_count) /* tx vector gets half the rate */ q_vector->eitr = (adapter->eitr_param >> 1); else /* rx only or mixed */ q_vector->eitr = adapter->eitr_param; - ixgbe_write_eitr(adapter, i, - EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); + ixgbe_write_eitr(q_vector); } return 0; } +static int ixgbe_set_flags(struct net_device *netdev, u32 data) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + ethtool_op_set_flags(netdev, data); + + if (!(adapter->flags & IXGBE_FLAG2_RSC_CAPABLE)) + return 0; + + /* if state changes we need to update adapter->flags and reset */ + if ((!!(data & ETH_FLAG_LRO)) != + (!!(adapter->flags & IXGBE_FLAG2_RSC_ENABLED))) { + adapter->flags ^= IXGBE_FLAG2_RSC_ENABLED; + if (netif_running(netdev)) + ixgbe_reinit_locked(adapter); + else + ixgbe_reset(adapter); + } + return 0; + +} static const struct ethtool_ops ixgbe_ethtool_ops = { .get_settings = ixgbe_get_settings, @@ -1147,6 +2041,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .set_msglevel = ixgbe_set_msglevel, .get_tso = ethtool_op_get_tso, .set_tso = ixgbe_set_tso, + .self_test = ixgbe_diag_test, .get_strings = ixgbe_get_strings, .phys_id = ixgbe_phys_id, .get_sset_count = ixgbe_get_sset_count, @@ -1154,7 +2049,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .get_coalesce = ixgbe_get_coalesce, .set_coalesce = ixgbe_set_coalesce, .get_flags = ethtool_op_get_flags, - .set_flags = ethtool_op_set_flags, + .set_flags = ixgbe_set_flags, }; void ixgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c new file mode 100644 index 000000000000..3c3bf1f07b81 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -0,0 +1,556 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + +#include "ixgbe.h" +#include +#include +#include +#include +#include +#include +#include + +/** + * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type + * @rx_desc: advanced rx descriptor + * + * Returns : true if it is FCoE pkt + */ +static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc) +{ + u16 p; + + p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info); + if (p & IXGBE_RXDADV_PKTTYPE_ETQF) { + p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK; + p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT; + return p == IXGBE_ETQF_FILTER_FCOE; + } + return false; +} + +/** + * ixgbe_fcoe_clear_ddp - clear the given ddp context + * @ddp - ptr to the ixgbe_fcoe_ddp + * + * Returns : none + * + */ +static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp) +{ + ddp->len = 0; + ddp->err = 0; + ddp->udl = NULL; + ddp->udp = 0UL; + ddp->sgl = NULL; + ddp->sgc = 0; +} + +/** + * ixgbe_fcoe_ddp_put - free the ddp context for a given xid + * @netdev: the corresponding net_device + * @xid: the xid that corresponding ddp will be freed + * + * This is the implementation of net_device_ops.ndo_fcoe_ddp_done + * and it is expected to be called by ULD, i.e., FCP layer of libfc + * to release the corresponding ddp context when the I/O is done. + * + * Returns : data length already ddp-ed in bytes + */ +int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid) +{ + int len = 0; + struct ixgbe_fcoe *fcoe; + struct ixgbe_adapter *adapter; + struct ixgbe_fcoe_ddp *ddp; + + if (!netdev) + goto out_ddp_put; + + if (xid >= IXGBE_FCOE_DDP_MAX) + goto out_ddp_put; + + adapter = netdev_priv(netdev); + fcoe = &adapter->fcoe; + ddp = &fcoe->ddp[xid]; + if (!ddp->udl) + goto out_ddp_put; + + len = ddp->len; + /* if there an error, force to invalidate ddp context */ + if (ddp->err) { + spin_lock_bh(&fcoe->lock); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLT, 0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLTRW, + (xid | IXGBE_FCFLTRW_WE)); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW, + (xid | IXGBE_FCDMARW_WE)); + spin_unlock_bh(&fcoe->lock); + } + if (ddp->sgl) + pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc, + DMA_FROM_DEVICE); + pci_pool_free(fcoe->pool, ddp->udl, ddp->udp); + ixgbe_fcoe_clear_ddp(ddp); + +out_ddp_put: + return len; +} + +/** + * ixgbe_fcoe_ddp_get - called to set up ddp context + * @netdev: the corresponding net_device + * @xid: the exchange id requesting ddp + * @sgl: the scatter-gather list for this request + * @sgc: the number of scatter-gather items + * + * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup + * and is expected to be called from ULD, e.g., FCP layer of libfc + * to set up ddp for the corresponding xid of the given sglist for + * the corresponding I/O. + * + * Returns : 1 for success and 0 for no ddp + */ +int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, + struct scatterlist *sgl, unsigned int sgc) +{ + struct ixgbe_adapter *adapter; + struct ixgbe_hw *hw; + struct ixgbe_fcoe *fcoe; + struct ixgbe_fcoe_ddp *ddp; + struct scatterlist *sg; + unsigned int i, j, dmacount; + unsigned int len; + static const unsigned int bufflen = 4096; + unsigned int firstoff = 0; + unsigned int lastsize; + unsigned int thisoff = 0; + unsigned int thislen = 0; + u32 fcbuff, fcdmarw, fcfltrw; + dma_addr_t addr; + + if (!netdev || !sgl) + return 0; + + adapter = netdev_priv(netdev); + if (xid >= IXGBE_FCOE_DDP_MAX) { + DPRINTK(DRV, WARNING, "xid=0x%x out-of-range\n", xid); + return 0; + } + + fcoe = &adapter->fcoe; + if (!fcoe->pool) { + DPRINTK(DRV, WARNING, "xid=0x%x no ddp pool for fcoe\n", xid); + return 0; + } + + ddp = &fcoe->ddp[xid]; + if (ddp->sgl) { + DPRINTK(DRV, ERR, "xid 0x%x w/ non-null sgl=%p nents=%d\n", + xid, ddp->sgl, ddp->sgc); + return 0; + } + ixgbe_fcoe_clear_ddp(ddp); + + /* setup dma from scsi command sgl */ + dmacount = pci_map_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE); + if (dmacount == 0) { + DPRINTK(DRV, ERR, "xid 0x%x DMA map error\n", xid); + return 0; + } + + /* alloc the udl from our ddp pool */ + ddp->udl = pci_pool_alloc(fcoe->pool, GFP_KERNEL, &ddp->udp); + if (!ddp->udl) { + DPRINTK(DRV, ERR, "failed allocated ddp context\n"); + goto out_noddp_unmap; + } + ddp->sgl = sgl; + ddp->sgc = sgc; + + j = 0; + for_each_sg(sgl, sg, dmacount, i) { + addr = sg_dma_address(sg); + len = sg_dma_len(sg); + while (len) { + /* get the offset of length of current buffer */ + thisoff = addr & ((dma_addr_t)bufflen - 1); + thislen = min((bufflen - thisoff), len); + /* + * all but the 1st buffer (j == 0) + * must be aligned on bufflen + */ + if ((j != 0) && (thisoff)) + goto out_noddp_free; + /* + * all but the last buffer + * ((i == (dmacount - 1)) && (thislen == len)) + * must end at bufflen + */ + if (((i != (dmacount - 1)) || (thislen != len)) + && ((thislen + thisoff) != bufflen)) + goto out_noddp_free; + + ddp->udl[j] = (u64)(addr - thisoff); + /* only the first buffer may have none-zero offset */ + if (j == 0) + firstoff = thisoff; + len -= thislen; + addr += thislen; + j++; + /* max number of buffers allowed in one DDP context */ + if (j > IXGBE_BUFFCNT_MAX) { + DPRINTK(DRV, ERR, "xid=%x:%d,%d,%d:addr=%llx " + "not enough descriptors\n", + xid, i, j, dmacount, (u64)addr); + goto out_noddp_free; + } + } + } + /* only the last buffer may have non-full bufflen */ + lastsize = thisoff + thislen; + + fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT); + fcbuff |= (j << IXGBE_FCBUFF_BUFFCNT_SHIFT); + fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT); + fcbuff |= (IXGBE_FCBUFF_VALID); + + fcdmarw = xid; + fcdmarw |= IXGBE_FCDMARW_WE; + fcdmarw |= (lastsize << IXGBE_FCDMARW_LASTSIZE_SHIFT); + + fcfltrw = xid; + fcfltrw |= IXGBE_FCFLTRW_WE; + + /* program DMA context */ + hw = &adapter->hw; + spin_lock_bh(&fcoe->lock); + IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_32BIT_MASK); + IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32); + IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff); + IXGBE_WRITE_REG(hw, IXGBE_FCDMARW, fcdmarw); + /* program filter context */ + IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0); + IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID); + IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw); + spin_unlock_bh(&fcoe->lock); + + return 1; + +out_noddp_free: + pci_pool_free(fcoe->pool, ddp->udl, ddp->udp); + ixgbe_fcoe_clear_ddp(ddp); + +out_noddp_unmap: + pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE); + return 0; +} + +/** + * ixgbe_fcoe_ddp - check ddp status and mark it done + * @adapter: ixgbe adapter + * @rx_desc: advanced rx descriptor + * @skb: the skb holding the received data + * + * This checks ddp status. + * + * Returns : < 0 indicates an error or not a FCiE ddp, 0 indicates + * not passing the skb to ULD, > 0 indicates is the length of data + * being ddped. + */ +int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u16 xid; + u32 sterr, fceofe, fcerr, fcstat; + int rc = -EINVAL; + struct ixgbe_fcoe *fcoe; + struct ixgbe_fcoe_ddp *ddp; + struct fc_frame_header *fh; + + if (!ixgbe_rx_is_fcoe(rx_desc)) + goto ddp_out; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + sterr = le32_to_cpu(rx_desc->wb.upper.status_error); + fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR); + fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE); + if (fcerr == IXGBE_FCERR_BADCRC) + skb->ip_summed = CHECKSUM_NONE; + + skb_reset_network_header(skb); + skb_set_transport_header(skb, skb_network_offset(skb) + + sizeof(struct fcoe_hdr)); + fh = (struct fc_frame_header *)skb_transport_header(skb); + xid = be16_to_cpu(fh->fh_ox_id); + if (xid >= IXGBE_FCOE_DDP_MAX) + goto ddp_out; + + fcoe = &adapter->fcoe; + ddp = &fcoe->ddp[xid]; + if (!ddp->udl) + goto ddp_out; + + ddp->err = (fcerr | fceofe); + if (ddp->err) + goto ddp_out; + + fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT); + if (fcstat) { + /* update length of DDPed data */ + ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); + /* unmap the sg list when FCP_RSP is received */ + if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_FCPRSP) { + pci_unmap_sg(adapter->pdev, ddp->sgl, + ddp->sgc, DMA_FROM_DEVICE); + ddp->sgl = NULL; + ddp->sgc = 0; + } + /* return 0 to bypass going to ULD for DDPed data */ + if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_DDP) + rc = 0; + else + rc = ddp->len; + } + +ddp_out: + return rc; +} + +/** + * ixgbe_fso - ixgbe FCoE Sequence Offload (FSO) + * @adapter: ixgbe adapter + * @tx_ring: tx desc ring + * @skb: associated skb + * @tx_flags: tx flags + * @hdr_len: hdr_len to be returned + * + * This sets up large send offload for FCoE + * + * Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error + */ +int ixgbe_fso(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring, struct sk_buff *skb, + u32 tx_flags, u8 *hdr_len) +{ + u8 sof, eof; + u32 vlan_macip_lens; + u32 fcoe_sof_eof; + u32 type_tucmd; + u32 mss_l4len_idx; + int mss = 0; + unsigned int i; + struct ixgbe_tx_buffer *tx_buffer_info; + struct ixgbe_adv_tx_context_desc *context_desc; + struct fc_frame_header *fh; + + if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) { + DPRINTK(DRV, ERR, "Wrong gso type %d:expecting SKB_GSO_FCOE\n", + skb_shinfo(skb)->gso_type); + return -EINVAL; + } + + /* resets the header to point fcoe/fc */ + skb_set_network_header(skb, skb->mac_len); + skb_set_transport_header(skb, skb->mac_len + + sizeof(struct fcoe_hdr)); + + /* sets up SOF and ORIS */ + fcoe_sof_eof = 0; + sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof; + switch (sof) { + case FC_SOF_I2: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS; + break; + case FC_SOF_I3: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF; + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS; + break; + case FC_SOF_N2: + break; + case FC_SOF_N3: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF; + break; + default: + DPRINTK(DRV, WARNING, "unknown sof = 0x%x\n", sof); + return -EINVAL; + } + + /* the first byte of the last dword is EOF */ + skb_copy_bits(skb, skb->len - 4, &eof, 1); + /* sets up EOF and ORIE */ + switch (eof) { + case FC_EOF_N: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N; + break; + case FC_EOF_T: + /* lso needs ORIE */ + if (skb_is_gso(skb)) { + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N; + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE; + } else { + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T; + } + break; + case FC_EOF_NI: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI; + break; + case FC_EOF_A: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A; + break; + default: + DPRINTK(DRV, WARNING, "unknown eof = 0x%x\n", eof); + return -EINVAL; + } + + /* sets up PARINC indicating data offset */ + fh = (struct fc_frame_header *)skb_transport_header(skb); + if (fh->fh_f_ctl[2] & FC_FC_REL_OFF) + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC; + + /* hdr_len includes fc_hdr if FCoE lso is enabled */ + *hdr_len = sizeof(struct fcoe_crc_eof); + if (skb_is_gso(skb)) + *hdr_len += (skb_transport_offset(skb) + + sizeof(struct fc_frame_header)); + /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ + vlan_macip_lens = (skb_transport_offset(skb) + + sizeof(struct fc_frame_header)); + vlan_macip_lens |= ((skb_transport_offset(skb) - 4) + << IXGBE_ADVTXD_MACLEN_SHIFT); + vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK); + + /* type_tycmd and mss: set TUCMD.FCoE to enable offload */ + type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT | + IXGBE_ADVTXT_TUCMD_FCOE; + if (skb_is_gso(skb)) + mss = skb_shinfo(skb)->gso_size; + /* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */ + mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) | + (1 << IXGBE_ADVTXD_IDX_SHIFT); + + /* write context desc */ + i = tx_ring->next_to_use; + context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); + + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + tx_buffer_info->time_stamp = jiffies; + tx_buffer_info->next_to_watch = i; + + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; + + return skb_is_gso(skb); +} + +/** + * ixgbe_configure_fcoe - configures registers for fcoe at start + * @adapter: ptr to ixgbe adapter + * + * This sets up FCoE related registers + * + * Returns : none + */ +void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) +{ + int i, fcoe_q, fcoe_i; + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_fcoe *fcoe = &adapter->fcoe; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; + + /* create the pool for ddp if not created yet */ + if (!fcoe->pool) { + /* allocate ddp pool */ + fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp", + adapter->pdev, IXGBE_FCPTR_MAX, + IXGBE_FCPTR_ALIGN, PAGE_SIZE); + if (!fcoe->pool) + DPRINTK(DRV, ERR, + "failed to allocated FCoE DDP pool\n"); + + spin_lock_init(&fcoe->lock); + } + + /* Enable L2 eth type filter for FCoE */ + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE), + (ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN)); + if (adapter->ring_feature[RING_F_FCOE].indices) { + /* Use multiple rx queues for FCoE by redirection table */ + for (i = 0; i < IXGBE_FCRETA_SIZE; i++) { + fcoe_i = f->mask + i % f->indices; + fcoe_i &= IXGBE_FCRETA_ENTRY_MASK; + fcoe_q = adapter->rx_ring[fcoe_i].reg_idx; + IXGBE_WRITE_REG(hw, IXGBE_FCRETA(i), fcoe_q); + } + IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, IXGBE_FCRECTL_ENA); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), 0); + } else { + /* Use single rx queue for FCoE */ + fcoe_i = f->mask; + fcoe_q = adapter->rx_ring[fcoe_i].reg_idx; + IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), + IXGBE_ETQS_QUEUE_EN | + (fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT)); + } + + IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, + IXGBE_FCRXCTRL_FCOELLI | + IXGBE_FCRXCTRL_FCCRCBO | + (FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT)); +} + +/** + * ixgbe_cleanup_fcoe - release all fcoe ddp context resources + * @adapter : ixgbe adapter + * + * Cleans up outstanding ddp context resources + * + * Returns : none + */ +void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter) +{ + int i; + struct ixgbe_fcoe *fcoe = &adapter->fcoe; + + /* release ddp resource */ + if (fcoe->pool) { + for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++) + ixgbe_fcoe_ddp_put(adapter->netdev, i); + pci_pool_destroy(fcoe->pool); + fcoe->pool = NULL; + } +} diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h new file mode 100644 index 000000000000..c5b50026a897 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_fcoe.h @@ -0,0 +1,67 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBE_FCOE_H +#define _IXGBE_FCOE_H + +#include +#include + +/* shift bits within STAT fo FCSTAT */ +#define IXGBE_RXDADV_FCSTAT_SHIFT 4 + +/* ddp user buffer */ +#define IXGBE_BUFFCNT_MAX 256 /* 8 bits bufcnt */ +#define IXGBE_FCPTR_ALIGN 16 +#define IXGBE_FCPTR_MAX (IXGBE_BUFFCNT_MAX * sizeof(dma_addr_t)) +#define IXGBE_FCBUFF_4KB 0x0 +#define IXGBE_FCBUFF_8KB 0x1 +#define IXGBE_FCBUFF_16KB 0x2 +#define IXGBE_FCBUFF_64KB 0x3 +#define IXGBE_FCBUFF_MAX 65536 /* 64KB max */ +#define IXGBE_FCBUFF_MIN 4096 /* 4KB min */ +#define IXGBE_FCOE_DDP_MAX 512 /* 9 bits xid */ + +/* fcerr */ +#define IXGBE_FCERR_BADCRC 0x00100000 + +struct ixgbe_fcoe_ddp { + int len; + u32 err; + unsigned int sgc; + struct scatterlist *sgl; + dma_addr_t udp; + u64 *udl; +}; + +struct ixgbe_fcoe { + spinlock_t lock; + struct pci_pool *pool; + struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX]; +}; + +#endif /* _IXGBE_FCOE_H */ diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 07e778d3e5d2..a551a96ce676 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "ixgbe.h" #include "ixgbe_common.h" @@ -47,7 +48,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.8-k2" +#define DRV_VERSION "2.0.34-k2" const char ixgbe_driver_version[] = DRV_VERSION; static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; @@ -89,6 +90,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM), + board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), board_82599 }, @@ -183,6 +186,22 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction, } } +static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter, + u64 qmask) +{ + u32 mask; + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + mask = (IXGBE_EIMS_RTX_QUEUE & qmask); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); + } else { + mask = (qmask & 0xFFFFFFFF); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask); + mask = (qmask >> 32); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask); + } +} + static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, struct ixgbe_tx_buffer *tx_buffer_info) @@ -245,14 +264,13 @@ static void ixgbe_tx_timeout(struct net_device *netdev); /** * ixgbe_clean_tx_irq - Reclaim resources after transmit completes - * @adapter: board private structure + * @q_vector: structure containing interrupt and ring information * @tx_ring: tx ring to clean - * - * returns true if transmit work is done **/ -static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, +static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *tx_ring) { + struct ixgbe_adapter *adapter = q_vector->adapter; struct net_device *netdev = adapter->netdev; union ixgbe_adv_tx_desc *tx_desc, *eop_desc; struct ixgbe_tx_buffer *tx_buffer_info; @@ -275,12 +293,24 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, if (cleaned && skb) { unsigned int segs, bytecount; + unsigned int hlen = skb_headlen(skb); /* gso_segs is currently only valid for tcp */ segs = skb_shinfo(skb)->gso_segs ?: 1; +#ifdef IXGBE_FCOE + /* adjust for FCoE Sequence Offload */ + if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + && (skb->protocol == htons(ETH_P_FCOE)) && + skb_is_gso(skb)) { + hlen = skb_transport_offset(skb) + + sizeof(struct fc_frame_header) + + sizeof(struct fcoe_crc_eof); + segs = DIV_ROUND_UP(skb->len - hlen, + skb_shinfo(skb)->gso_size); + } +#endif /* IXGBE_FCOE */ /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + - skb->len; + bytecount = ((segs - 1) * hlen) + skb->len; total_packets += segs; total_bytes += bytecount; } @@ -327,7 +357,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, /* re-arm the interrupt */ if (count >= tx_ring->work_limit) - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx); + ixgbe_irq_rearm_queues(adapter, ((u64)1 << q_vector->v_idx)); tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; @@ -398,6 +428,9 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED)) return; + /* always use CB2 mode, difference is masked in the CB driver */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); + for (i = 0; i < adapter->num_tx_queues; i++) { adapter->tx_ring[i].cpu = -1; ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]); @@ -419,9 +452,6 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) /* if we're already enabled, don't do it again */ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) break; - /* Always use CB2 mode, difference is masked - * in the CB driver. */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); if (dca_add_requester(dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; ixgbe_setup_dca(adapter); @@ -451,6 +481,7 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) **/ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, struct sk_buff *skb, u8 status, + struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { struct ixgbe_adapter *adapter = q_vector->adapter; @@ -458,24 +489,17 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]); - if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + skb_record_rx_queue(skb, ring->queue_index); + if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag != 0)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); else napi_gro_receive(napi, skb); } else { - if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { - if (adapter->vlgrp && is_vlan && (tag != 0)) - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag); - else - netif_receive_skb(skb); - } else { - if (adapter->vlgrp && is_vlan && (tag != 0)) - vlan_hwaccel_rx(skb, adapter->vlgrp, tag); - else - netif_rx(skb); - } + if (adapter->vlgrp && is_vlan && (tag != 0)) + vlan_hwaccel_rx(skb, adapter->vlgrp, tag); + else + netif_rx(skb); } } @@ -622,6 +646,40 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; } +static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc) +{ + return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) & + IXGBE_RXDADV_RSCCNT_MASK) >> + IXGBE_RXDADV_RSCCNT_SHIFT; +} + +/** + * ixgbe_transform_rsc_queue - change rsc queue into a full packet + * @skb: pointer to the last skb in the rsc queue + * + * This function changes a queue full of hw rsc buffers into a completed + * packet. It uses the ->prev pointers to find the first packet and then + * turns it into the frag list owner. + **/ +static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb) +{ + unsigned int frag_list_size = 0; + + while (skb->prev) { + struct sk_buff *prev = skb->prev; + frag_list_size += skb->len; + skb->prev = NULL; + skb = prev; + } + + skb_shinfo(skb)->frag_list = skb->next; + skb->next = NULL; + skb->len += frag_list_size; + skb->data_len += frag_list_size; + skb->truesize += frag_list_size; + return skb; +} + static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) @@ -631,12 +689,15 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, union ixgbe_adv_rx_desc *rx_desc, *next_rxd; struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer; struct sk_buff *skb; - unsigned int i; + unsigned int i, rsc_count = 0; u32 len, staterr; u16 hdr_info; bool cleaned = false; int cleaned_count = 0; unsigned int total_rx_bytes = 0, total_rx_packets = 0; +#ifdef IXGBE_FCOE + int ddp_bytes = 0; +#endif /* IXGBE_FCOE */ i = rx_ring->next_to_clean; rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); @@ -667,7 +728,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, prefetch(skb->data - NET_IP_ALIGN); rx_buffer_info->skb = NULL; - if (len && !skb_shinfo(skb)->nr_frags) { + if (rx_buffer_info->dma) { pci_unmap_single(pdev, rx_buffer_info->dma, rx_ring->rx_buf_len, PCI_DMA_FROMDEVICE); @@ -697,20 +758,38 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, i++; if (i == rx_ring->count) i = 0; - next_buffer = &rx_ring->rx_buffer_info[i]; next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i); prefetch(next_rxd); - cleaned_count++; + + if (adapter->flags & IXGBE_FLAG2_RSC_CAPABLE) + rsc_count = ixgbe_get_rsc_count(rx_desc); + + if (rsc_count) { + u32 nextp = (staterr & IXGBE_RXDADV_NEXTP_MASK) >> + IXGBE_RXDADV_NEXTP_SHIFT; + next_buffer = &rx_ring->rx_buffer_info[nextp]; + rx_ring->rsc_count += (rsc_count - 1); + } else { + next_buffer = &rx_ring->rx_buffer_info[i]; + } + if (staterr & IXGBE_RXD_STAT_EOP) { + if (skb->prev) + skb = ixgbe_transform_rsc_queue(skb); rx_ring->stats.packets++; rx_ring->stats.bytes += skb->len; } else { - rx_buffer_info->skb = next_buffer->skb; - rx_buffer_info->dma = next_buffer->dma; - next_buffer->skb = skb; - next_buffer->dma = 0; + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + rx_buffer_info->skb = next_buffer->skb; + rx_buffer_info->dma = next_buffer->dma; + next_buffer->skb = skb; + next_buffer->dma = 0; + } else { + skb->next = next_buffer->skb; + skb->next->prev = skb; + } adapter->non_eop_descs++; goto next_desc; } @@ -727,7 +806,15 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, total_rx_packets++; skb->protocol = eth_type_trans(skb, adapter->netdev); - ixgbe_receive_skb(q_vector, skb, staterr, rx_desc); +#ifdef IXGBE_FCOE + /* if ddp, not passing to ULD unless for FCP_RSP or error */ + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb); + if (!ddp_bytes) + goto next_desc; + } +#endif /* IXGBE_FCOE */ + ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc); next_desc: rx_desc->wb.upper.status_error = 0; @@ -740,7 +827,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, /* use prefetched values */ rx_desc = next_rxd; - rx_buffer_info = next_buffer; + rx_buffer_info = &rx_ring->rx_buffer_info[i]; staterr = le32_to_cpu(rx_desc->wb.upper.status_error); } @@ -751,6 +838,21 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, if (cleaned_count) ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); +#ifdef IXGBE_FCOE + /* include DDPed FCoE data */ + if (ddp_bytes > 0) { + unsigned int mss; + + mss = adapter->netdev->mtu - sizeof(struct fcoe_hdr) - + sizeof(struct fc_frame_header) - + sizeof(struct fcoe_crc_eof); + if (mss > 512) + mss &= ~511; + total_rx_bytes += ddp_bytes; + total_rx_packets += DIV_ROUND_UP(ddp_bytes, mss); + } +#endif /* IXGBE_FCOE */ + rx_ring->total_packets += total_rx_packets; rx_ring->total_bytes += total_rx_bytes; adapter->net_stats.rx_bytes += total_rx_bytes; @@ -780,7 +882,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) * corresponding register. */ for (v_idx = 0; v_idx < q_vectors; v_idx++) { - q_vector = &adapter->q_vector[v_idx]; + q_vector = adapter->q_vector[v_idx]; /* XXX for_each_bit(...) */ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); @@ -810,12 +912,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) /* rx only */ q_vector->eitr = adapter->eitr_param; - /* - * since this is initial set up don't need to call - * ixgbe_write_eitr helper - */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), - EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); + ixgbe_write_eitr(q_vector); } if (adapter->hw.mac.type == ixgbe_mac_82598EB) @@ -900,17 +997,19 @@ static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter, /** * ixgbe_write_eitr - write EITR register in hardware specific way - * @adapter: pointer to adapter struct - * @v_idx: vector index into q_vector array - * @itr_reg: new value to be written in *register* format, not ints/s + * @q_vector: structure containing interrupt and ring information * * This function is made to be called by ethtool and by the driver * when it needs to update EITR registers at runtime. Hardware * specific quirks/differences are taken care of here. */ -void ixgbe_write_eitr(struct ixgbe_adapter *adapter, int v_idx, u32 itr_reg) +void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) { + struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_hw *hw = &adapter->hw; + int v_idx = q_vector->v_idx; + u32 itr_reg = EITR_INTS_PER_SEC_TO_REG(q_vector->eitr); + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { /* must write high and low 16 bits to reset counter */ itr_reg |= (itr_reg << 16); @@ -929,8 +1028,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) struct ixgbe_adapter *adapter = q_vector->adapter; u32 new_itr; u8 current_itr, ret_itr; - int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) / - sizeof(struct ixgbe_q_vector); + int i, r_idx; struct ixgbe_ring *rx_ring, *tx_ring; r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); @@ -980,14 +1078,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) } if (new_itr != q_vector->eitr) { - u32 itr_reg; + /* do an exponential smoothing */ + new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); /* save the algorithm value here, not the smoothed one */ q_vector->eitr = new_itr; - /* do an exponential smoothing */ - new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); - itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); - ixgbe_write_eitr(adapter, v_idx, itr_reg); + + ixgbe_write_eitr(q_vector); } return; @@ -1058,14 +1155,64 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) if (hw->mac.type == ixgbe_mac_82598EB) ixgbe_check_fan_failure(adapter, eicr); - if (hw->mac.type == ixgbe_mac_82599EB) + if (hw->mac.type == ixgbe_mac_82599EB) { ixgbe_check_sfp_event(adapter, eicr); + + /* Handle Flow Director Full threshold interrupt */ + if (eicr & IXGBE_EICR_FLOW_DIR) { + int i; + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR); + /* Disable transmits before FDIR Re-initialization */ + netif_tx_stop_all_queues(netdev); + for (i = 0; i < adapter->num_tx_queues; i++) { + struct ixgbe_ring *tx_ring = + &adapter->tx_ring[i]; + if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE, + &tx_ring->reinit_state)) + schedule_work(&adapter->fdir_reinit_task); + } + } + } if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); return IRQ_HANDLED; } +static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, + u64 qmask) +{ + u32 mask; + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + mask = (IXGBE_EIMS_RTX_QUEUE & qmask); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + } else { + mask = (qmask & 0xFFFFFFFF); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask); + mask = (qmask >> 32); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask); + } + /* skip the flush */ +} + +static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, + u64 qmask) +{ + u32 mask; + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + mask = (IXGBE_EIMS_RTX_QUEUE & qmask); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask); + } else { + mask = (qmask & 0xFFFFFFFF); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), mask); + mask = (qmask >> 32); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), mask); + } + /* skip the flush */ +} + static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) { struct ixgbe_q_vector *q_vector = data; @@ -1079,17 +1226,16 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { tx_ring = &(adapter->tx_ring[r_idx]); -#ifdef CONFIG_IXGBE_DCA - if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) - ixgbe_update_tx_dca(adapter, tx_ring); -#endif tx_ring->total_bytes = 0; tx_ring->total_packets = 0; - ixgbe_clean_tx_irq(adapter, tx_ring); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx + 1); } + /* disable interrupts on this vector only */ + ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx)); + napi_schedule(&q_vector->napi); + return IRQ_HANDLED; } @@ -1121,7 +1267,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); rx_ring = &(adapter->rx_ring[r_idx]); /* disable interrupts on this vector only */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); + ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx)); napi_schedule(&q_vector->napi); return IRQ_HANDLED; @@ -1129,8 +1275,36 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) { - ixgbe_msix_clean_rx(irq, data); - ixgbe_msix_clean_tx(irq, data); + struct ixgbe_q_vector *q_vector = data; + struct ixgbe_adapter *adapter = q_vector->adapter; + struct ixgbe_ring *ring; + int r_idx; + int i; + + if (!q_vector->txr_count && !q_vector->rxr_count) + return IRQ_HANDLED; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + ring = &(adapter->tx_ring[r_idx]); + ring->total_bytes = 0; + ring->total_packets = 0; + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); + } + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + ring = &(adapter->rx_ring[r_idx]); + ring->total_bytes = 0; + ring->total_packets = 0; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + /* disable interrupts on this vector only */ + ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx)); + napi_schedule(&q_vector->napi); return IRQ_HANDLED; } @@ -1167,29 +1341,42 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx); + ixgbe_irq_enable_queues(adapter, + ((u64)1 << q_vector->v_idx)); } return work_done; } /** - * ixgbe_clean_rxonly_many - msix (aka one shot) rx clean routine + * ixgbe_clean_rxtx_many - msix (aka one shot) rx clean routine * @napi: napi struct with our devices info in it * @budget: amount of work driver is allowed to do this pass, in packets * * This function will clean more than one rx queue associated with a * q_vector. **/ -static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) +static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) { struct ixgbe_q_vector *q_vector = container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; - struct ixgbe_ring *rx_ring = NULL; + struct ixgbe_ring *ring = NULL; int work_done = 0, i; long r_idx; - u16 enable_mask = 0; + bool tx_clean_complete = true; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + ring = &(adapter->tx_ring[r_idx]); +#ifdef CONFIG_IXGBE_DCA + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + ixgbe_update_tx_dca(adapter, ring); +#endif + tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); + } /* attempt to distribute budget to each queue fairly, but don't allow * the budget to go below 1 because we'll exit polling */ @@ -1197,47 +1384,87 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) budget = max(budget, 1); r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - rx_ring = &(adapter->rx_ring[r_idx]); + ring = &(adapter->rx_ring[r_idx]); #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) - ixgbe_update_rx_dca(adapter, rx_ring); + ixgbe_update_rx_dca(adapter, ring); #endif - ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget); - enable_mask |= rx_ring->v_idx; + ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); } r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - rx_ring = &(adapter->rx_ring[r_idx]); + ring = &(adapter->rx_ring[r_idx]); /* If all Rx work done, exit the polling mode */ if (work_done < budget) { napi_complete(napi); if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask); + ixgbe_irq_enable_queues(adapter, + ((u64)1 << q_vector->v_idx)); return 0; } return work_done; } + +/** + * ixgbe_clean_txonly - msix (aka one shot) tx clean routine + * @napi: napi struct with our devices info in it + * @budget: amount of work driver is allowed to do this pass, in packets + * + * This function is optimized for cleaning one queue only on a single + * q_vector!!! + **/ +static int ixgbe_clean_txonly(struct napi_struct *napi, int budget) +{ + struct ixgbe_q_vector *q_vector = + container_of(napi, struct ixgbe_q_vector, napi); + struct ixgbe_adapter *adapter = q_vector->adapter; + struct ixgbe_ring *tx_ring = NULL; + int work_done = 0; + long r_idx; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + tx_ring = &(adapter->tx_ring[r_idx]); +#ifdef CONFIG_IXGBE_DCA + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + ixgbe_update_tx_dca(adapter, tx_ring); +#endif + + if (!ixgbe_clean_tx_irq(q_vector, tx_ring)) + work_done = budget; + + /* If all Rx work done, exit the polling mode */ + if (work_done < budget) { + napi_complete(napi); + if (adapter->itr_setting & 1) + ixgbe_set_itr_msix(q_vector); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); + } + + return work_done; +} + static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, int r_idx) { - a->q_vector[v_idx].adapter = a; - set_bit(r_idx, a->q_vector[v_idx].rxr_idx); - a->q_vector[v_idx].rxr_count++; - a->rx_ring[r_idx].v_idx = 1 << v_idx; + struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; + + set_bit(r_idx, q_vector->rxr_idx); + q_vector->rxr_count++; } static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, - int r_idx) + int t_idx) { - a->q_vector[v_idx].adapter = a; - set_bit(r_idx, a->q_vector[v_idx].txr_idx); - a->q_vector[v_idx].txr_count++; - a->tx_ring[r_idx].v_idx = 1 << v_idx; + struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; + + set_bit(t_idx, q_vector->txr_idx); + q_vector->txr_count++; } /** @@ -1333,7 +1560,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \ &ixgbe_msix_clean_many) for (vector = 0; vector < q_vectors; vector++) { - handler = SET_HANDLER(&adapter->q_vector[vector]); + handler = SET_HANDLER(adapter->q_vector[vector]); if(handler == &ixgbe_msix_clean_rx) { sprintf(adapter->name[vector], "%s-%s-%d", @@ -1349,7 +1576,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) err = request_irq(adapter->msix_entries[vector].vector, handler, 0, adapter->name[vector], - &(adapter->q_vector[vector])); + adapter->q_vector[vector]); if (err) { DPRINTK(PROBE, ERR, "request_irq failed for MSIX interrupt " @@ -1372,7 +1599,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) free_queue_irqs: for (i = vector - 1; i >= 0; i--) free_irq(adapter->msix_entries[--vector].vector, - &(adapter->q_vector[i])); + adapter->q_vector[i]); adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); @@ -1383,7 +1610,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) static void ixgbe_set_itr(struct ixgbe_adapter *adapter) { - struct ixgbe_q_vector *q_vector = adapter->q_vector; + struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; u8 current_itr; u32 new_itr = q_vector->eitr; struct ixgbe_ring *rx_ring = &adapter->rx_ring[0]; @@ -1416,14 +1643,13 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) } if (new_itr != q_vector->eitr) { - u32 itr_reg; + /* do an exponential smoothing */ + new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); /* save the algorithm value here, not the smoothed one */ q_vector->eitr = new_itr; - /* do an exponential smoothing */ - new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); - itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); - ixgbe_write_eitr(adapter, 0, itr_reg); + + ixgbe_write_eitr(q_vector); } return; @@ -1436,7 +1662,8 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) { u32 mask; - mask = IXGBE_EIMS_ENABLE_MASK; + + mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) mask |= IXGBE_EIMS_GPI_SDP1; if (adapter->hw.mac.type == ixgbe_mac_82599EB) { @@ -1444,16 +1671,12 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; } + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || + adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) + mask |= IXGBE_EIMS_FLOW_DIR; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - /* enable the rest of the queue vectors */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), - (IXGBE_EIMS_RTX_QUEUE << 16)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), - ((IXGBE_EIMS_RTX_QUEUE << 16) | - IXGBE_EIMS_RTX_QUEUE)); - } + ixgbe_irq_enable_queues(adapter, ~0); IXGBE_WRITE_FLUSH(&adapter->hw); } @@ -1467,6 +1690,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data) struct net_device *netdev = data; struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; u32 eicr; /* @@ -1494,13 +1718,13 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); - if (napi_schedule_prep(&adapter->q_vector[0].napi)) { + if (napi_schedule_prep(&(q_vector->napi))) { adapter->tx_ring[0].total_packets = 0; adapter->tx_ring[0].total_bytes = 0; adapter->rx_ring[0].total_packets = 0; adapter->rx_ring[0].total_bytes = 0; /* would disable interrupts here but EIAM disabled it */ - __napi_schedule(&adapter->q_vector[0].napi); + __napi_schedule(&(q_vector->napi)); } return IRQ_HANDLED; @@ -1511,7 +1735,7 @@ static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter) int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; for (i = 0; i < q_vectors; i++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; + struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES); bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES); q_vector->rxr_count = 0; @@ -1562,7 +1786,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) i--; for (; i >= 0; i--) { free_irq(adapter->msix_entries[i].vector, - &(adapter->q_vector[i])); + adapter->q_vector[i]); } ixgbe_reset_q_vectors(adapter); @@ -1577,10 +1801,12 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) **/ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) { - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); + } else { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(2), ~0); } IXGBE_WRITE_FLUSH(&adapter->hw); if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { @@ -1592,18 +1818,6 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) } } -static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter) -{ - u32 mask = IXGBE_EIMS_RTX_QUEUE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask << 16); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), - (mask << 16 | mask)); - } - /* skip the flush */ -} - /** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * @@ -1673,11 +1887,34 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) u32 srrctl; int queue0 = 0; unsigned long mask; + struct ixgbe_ring_feature *feature = adapter->ring_feature; if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - queue0 = index; + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + int dcb_i = feature[RING_F_DCB].indices; + if (dcb_i == 8) + queue0 = index >> 4; + else if (dcb_i == 4) + queue0 = index >> 5; + else + dev_err(&adapter->pdev->dev, "Invalid DCB " + "configuration\n"); +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + struct ixgbe_ring_feature *f; + + rx_ring = &adapter->rx_ring[queue0]; + f = &adapter->ring_feature[RING_F_FCOE]; + if ((queue0 == 0) && (index > rx_ring->reg_idx)) + queue0 = f->mask + index - + rx_ring->reg_idx - 1; + } +#endif /* IXGBE_FCOE */ + } else { + queue0 = index; + } } else { - mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask; + mask = (unsigned long) feature[RING_F_RSS].mask; queue0 = index & mask; index = index & mask; } @@ -1689,33 +1926,55 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; + srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & + IXGBE_SRRCTL_BSIZEHDR_MASK; + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { - u16 bufsz = IXGBE_RXBUFFER_2048; - /* grow the amount we can receive on large page machines */ - if (bufsz < (PAGE_SIZE / 2)) - bufsz = (PAGE_SIZE / 2); - /* cap the bufsz at our largest descriptor size */ - bufsz = min((u16)IXGBE_MAX_RXBUFFER, bufsz); - - srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; +#if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER + srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; +#else + srrctl |= (PAGE_SIZE / 2) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; +#endif srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; - srrctl |= ((IXGBE_RX_HDR_SIZE << - IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & - IXGBE_SRRCTL_BSIZEHDR_MASK); } else { + srrctl |= ALIGN(rx_ring->rx_buf_len, 1024) >> + IXGBE_SRRCTL_BSIZEPKT_SHIFT; srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; - - if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE) - srrctl |= IXGBE_RXBUFFER_2048 >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; - else - srrctl |= rx_ring->rx_buf_len >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; } IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); } +static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) +{ + u32 mrqc = 0; + int mask; + + if (!(adapter->hw.mac.type == ixgbe_mac_82599EB)) + return mrqc; + + mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED +#ifdef CONFIG_IXGBE_DCB + | IXGBE_FLAG_DCB_ENABLED +#endif + ); + + switch (mask) { + case (IXGBE_FLAG_RSS_ENABLED): + mrqc = IXGBE_MRQC_RSSEN; + break; +#ifdef CONFIG_IXGBE_DCB + case (IXGBE_FLAG_DCB_ENABLED): + mrqc = IXGBE_MRQC_RT8TCEN; + break; +#endif /* CONFIG_IXGBE_DCB */ + default: + break; + } + + return mrqc; +} + /** * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset * @adapter: board private structure @@ -1736,11 +1995,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) u32 fctrl, hlreg0; u32 reta = 0, mrqc = 0; u32 rdrxctl; + u32 rscctrl; int rx_buf_len; /* Decide whether to use packet split mode or not */ adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; +#endif /* IXGBE_FCOE */ + /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { rx_buf_len = IXGBE_RX_HDR_SIZE; @@ -1749,11 +2014,13 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) u32 psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR | IXGBE_PSRTYPE_IPV4HDR | - IXGBE_PSRTYPE_IPV6HDR; + IXGBE_PSRTYPE_IPV6HDR | + IXGBE_PSRTYPE_L2HDR; IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); } } else { - if (netdev->mtu <= ETH_DATA_LEN) + if (!(adapter->flags & IXGBE_FLAG2_RSC_ENABLED) && + (netdev->mtu <= ETH_DATA_LEN)) rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; else rx_buf_len = ALIGN(max_frame, 1024); @@ -1770,6 +2037,10 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; else hlreg0 |= IXGBE_HLREG0_JUMBOEN; +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + hlreg0 |= IXGBE_HLREG0_JUMBOEN; +#endif IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc); @@ -1777,8 +2048,10 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring */ + /* + * Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ for (i = 0; i < adapter->num_rx_queues; i++) { rdba = adapter->rx_ring[i].dma; j = adapter->rx_ring[i].reg_idx; @@ -1791,6 +2064,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) adapter->rx_ring[i].tail = IXGBE_RDT(j); adapter->rx_ring[i].rx_buf_len = rx_buf_len; +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + struct ixgbe_ring_feature *f; + f = &adapter->ring_feature[RING_F_FCOE]; + if ((rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) && + (i >= f->mask) && (i < f->mask + f->indices)) + adapter->rx_ring[i].rx_buf_len = + IXGBE_FCOE_JUMBO_FRAME_SIZE; + } + +#endif /* IXGBE_FCOE */ ixgbe_configure_srrctl(adapter, j); } @@ -1811,23 +2095,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) } /* Program MRQC for the distribution of queues */ - if (hw->mac.type == ixgbe_mac_82599EB) { - int mask = adapter->flags & ( - IXGBE_FLAG_RSS_ENABLED - | IXGBE_FLAG_DCB_ENABLED - ); + mrqc = ixgbe_setup_mrqc(adapter); - switch (mask) { - case (IXGBE_FLAG_RSS_ENABLED): - mrqc = IXGBE_MRQC_RSSEN; - break; - case (IXGBE_FLAG_DCB_ENABLED): - mrqc = IXGBE_MRQC_RT8TCEN; - break; - default: - break; - } - } if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { /* Fill out redirection table */ for (i = 0, j = 0; i < 128; i++, j++) { @@ -1875,8 +2144,45 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82599EB) { rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; + rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } + + if (adapter->flags & IXGBE_FLAG2_RSC_ENABLED) { + /* Enable 82599 HW-RSC */ + for (i = 0; i < adapter->num_rx_queues; i++) { + j = adapter->rx_ring[i].reg_idx; + rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); + rscctrl |= IXGBE_RSCCTL_RSCEN; + /* + * we must limit the number of descriptors so that the + * total size of max desc * buf_len is not greater + * than 65535 + */ + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { +#if (MAX_SKB_FRAGS > 16) + rscctrl |= IXGBE_RSCCTL_MAXDESC_16; +#elif (MAX_SKB_FRAGS > 8) + rscctrl |= IXGBE_RSCCTL_MAXDESC_8; +#elif (MAX_SKB_FRAGS > 4) + rscctrl |= IXGBE_RSCCTL_MAXDESC_4; +#else + rscctrl |= IXGBE_RSCCTL_MAXDESC_1; +#endif + } else { + if (rx_buf_len < IXGBE_RXBUFFER_4096) + rscctrl |= IXGBE_RSCCTL_MAXDESC_16; + else if (rx_buf_len < IXGBE_RXBUFFER_8192) + rscctrl |= IXGBE_RSCCTL_MAXDESC_8; + else + rscctrl |= IXGBE_RSCCTL_MAXDESC_4; + } + IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl); + } + /* Disable RSC for ACK packets */ + IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, + (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); + } } static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) @@ -2015,11 +2321,7 @@ static void ixgbe_set_rx_mode(struct net_device *netdev) IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); /* reprogram secondary unicast list */ - addr_count = netdev->uc_count; - if (addr_count) - addr_list = netdev->uc_list->dmi_addr; - hw->mac.ops.update_uc_addr_list(hw, addr_list, addr_count, - ixgbe_addr_list_itr); + hw->mac.ops.update_uc_addr_list(hw, &netdev->uc_list); /* reprogram multicast list */ addr_count = netdev->mc_count; @@ -2041,13 +2343,16 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) for (q_idx = 0; q_idx < q_vectors; q_idx++) { struct napi_struct *napi; - q_vector = &adapter->q_vector[q_idx]; - if (!q_vector->rxr_count) - continue; + q_vector = adapter->q_vector[q_idx]; napi = &q_vector->napi; - if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) && - (q_vector->rxr_count > 1)) - napi->poll = &ixgbe_clean_rxonly_many; + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + if (!q_vector->rxr_count || !q_vector->txr_count) { + if (q_vector->txr_count == 1) + napi->poll = &ixgbe_clean_txonly; + else if (q_vector->rxr_count == 1) + napi->poll = &ixgbe_clean_rxonly; + } + } napi_enable(napi); } @@ -2064,9 +2369,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) q_vectors = 1; for (q_idx = 0; q_idx < q_vectors; q_idx++) { - q_vector = &adapter->q_vector[q_idx]; - if (!q_vector->rxr_count) - continue; + q_vector = adapter->q_vector[q_idx]; napi_disable(&q_vector->napi); } } @@ -2124,6 +2427,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) static void ixgbe_configure(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; int i; ixgbe_set_rx_mode(netdev); @@ -2140,6 +2444,20 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) netif_set_gso_max_size(netdev, 65536); #endif +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + ixgbe_configure_fcoe(adapter); + +#endif /* IXGBE_FCOE */ + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i].atr_sample_rate = + adapter->atr_sample_rate; + ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc); + } else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) { + ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc); + } + ixgbe_configure_tx(adapter); ixgbe_configure_rx(adapter); for (i = 0; i < adapter->num_rx_queues; i++) @@ -2294,6 +2612,13 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); } +#ifdef IXGBE_FCOE + /* adjust max frame to be able to do baby jumbo for FCoE */ + if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && + (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE)) + max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE; + +#endif /* IXGBE_FCOE */ mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) { mhadd &= ~IXGBE_MHADD_MFS_MASK; @@ -2356,6 +2681,17 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ixgbe_irq_enable(adapter); + /* + * If this adapter has a fan, check to see if we had a failure + * before we enabled the interrupt. + */ + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { + u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (esdp & IXGBE_ESDP_SDP1) + DPRINTK(DRV, CRIT, + "Fan has stopped, replace the adapter\n"); + } + /* * For hot-pluggable SFP+ devices, a new SFP+ module may have * arrived before interrupts were enabled. We need to kick off @@ -2378,6 +2714,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) DPRINTK(PROBE, ERR, "link_config FAILED %d\n", err); } + for (i = 0; i < adapter->num_tx_queues; i++) + set_bit(__IXGBE_FDIR_INIT_DONE, + &(adapter->tx_ring[i].reinit_state)); + /* enable transmits */ netif_tx_start_all_queues(netdev); @@ -2404,20 +2744,37 @@ int ixgbe_up(struct ixgbe_adapter *adapter) /* hardware has been reset, we need to reload some things */ ixgbe_configure(adapter); - ixgbe_napi_add_all(adapter); - return ixgbe_up_complete(adapter); } void ixgbe_reset(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - if (hw->mac.ops.init_hw(hw)) - dev_err(&adapter->pdev->dev, "Hardware Error\n"); + int err; + + err = hw->mac.ops.init_hw(hw); + switch (err) { + case 0: + case IXGBE_ERR_SFP_NOT_PRESENT: + break; + case IXGBE_ERR_MASTER_REQUESTS_PENDING: + dev_err(&adapter->pdev->dev, "master disable timed out\n"); + break; + case IXGBE_ERR_EEPROM_VERSION: + /* We are running on a pre-production device, log a warning */ + dev_warn(&adapter->pdev->dev, "This device is a pre-production " + "adapter/LOM. Please be aware there may be issues " + "associated with your hardware. If you are " + "experiencing problems please contact your Intel or " + "hardware representative who provided you with this " + "hardware.\n"); + break; + default: + dev_err(&adapter->pdev->dev, "Hardware Error: %d\n", err); + } /* reprogram the RAR[0] in case user changed it. */ hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); - } /** @@ -2445,8 +2802,13 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_buffer_info->dma = 0; } if (rx_buffer_info->skb) { - dev_kfree_skb(rx_buffer_info->skb); + struct sk_buff *skb = rx_buffer_info->skb; rx_buffer_info->skb = NULL; + do { + struct sk_buff *this = skb; + skb = skb->prev; + dev_kfree_skb(this); + } while (skb); } if (!rx_buffer_info->page) continue; @@ -2560,6 +2922,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter) del_timer_sync(&adapter->watchdog_timer); cancel_work_sync(&adapter->watchdog_task); + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || + adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) + cancel_work_sync(&adapter->fdir_reinit_task); + /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { j = adapter->tx_ring[i].reg_idx; @@ -2575,13 +2941,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_carrier_off(netdev); -#ifdef CONFIG_IXGBE_DCA - if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { - adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; - dca_remove_requester(&adapter->pdev->dev); - } - -#endif if (!pci_channel_offline(adapter->pdev)) ixgbe_reset(adapter); ixgbe_clean_all_tx_rings(adapter); @@ -2589,13 +2948,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) #ifdef CONFIG_IXGBE_DCA /* since we reset the hardware DCA settings were cleared */ - if (dca_add_requester(&adapter->pdev->dev) == 0) { - adapter->flags |= IXGBE_FLAG_DCA_ENABLED; - /* always use CB2 mode, difference is masked - * in the CB driver */ - IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); - ixgbe_setup_dca(adapter); - } + ixgbe_setup_dca(adapter); #endif } @@ -2620,7 +2973,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) } #endif - tx_clean_complete = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); + tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring); ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget); if (!tx_clean_complete) @@ -2632,7 +2985,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) if (adapter->itr_setting & 1) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable_queues(adapter); + ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); } return work_done; } @@ -2668,17 +3021,15 @@ static void ixgbe_reset_task(struct work_struct *work) static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) { bool ret = false; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB]; - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - adapter->ring_feature[RING_F_DCB].mask = 0x7 << 3; - adapter->num_rx_queues = - adapter->ring_feature[RING_F_DCB].indices; - adapter->num_tx_queues = - adapter->ring_feature[RING_F_DCB].indices; - ret = true; - } else { - ret = false; - } + if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) + return ret; + + f->mask = 0x7 << 3; + adapter->num_rx_queues = f->indices; + adapter->num_tx_queues = f->indices; + ret = true; return ret; } @@ -2695,13 +3046,12 @@ static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) { bool ret = false; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_RSS]; if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - adapter->ring_feature[RING_F_RSS].mask = 0xF; - adapter->num_rx_queues = - adapter->ring_feature[RING_F_RSS].indices; - adapter->num_tx_queues = - adapter->ring_feature[RING_F_RSS].indices; + f->mask = 0xF; + adapter->num_rx_queues = f->indices; + adapter->num_tx_queues = f->indices; ret = true; } else { ret = false; @@ -2710,6 +3060,79 @@ static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) return ret; } +/** + * ixgbe_set_fdir_queues: Allocate queues for Flow Director + * @adapter: board private structure to initialize + * + * Flow Director is an advanced Rx filter, attempting to get Rx flows back + * to the original CPU that initiated the Tx session. This runs in addition + * to RSS, so if a packet doesn't match an FDIR filter, we can still spread the + * Rx load across CPUs using RSS. + * + **/ +static bool inline ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter) +{ + bool ret = false; + struct ixgbe_ring_feature *f_fdir = &adapter->ring_feature[RING_F_FDIR]; + + f_fdir->indices = min((int)num_online_cpus(), f_fdir->indices); + f_fdir->mask = 0; + + /* Flow Director must have RSS enabled */ + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED && + ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)))) { + adapter->num_tx_queues = f_fdir->indices; + adapter->num_rx_queues = f_fdir->indices; + ret = true; + } else { + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + } + return ret; +} + +#ifdef IXGBE_FCOE +/** + * ixgbe_set_fcoe_queues: Allocate queues for Fiber Channel over Ethernet (FCoE) + * @adapter: board private structure to initialize + * + * FCoE RX FCRETA can use up to 8 rx queues for up to 8 different exchanges. + * The ring feature mask is not used as a mask for FCoE, as it can take any 8 + * rx queues out of the max number of rx queues, instead, it is used as the + * index of the first rx queue used by FCoE. + * + **/ +static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) +{ + bool ret = false; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; + + f->indices = min((int)num_online_cpus(), f->indices); + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { +#ifdef CONFIG_IXGBE_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + DPRINTK(PROBE, INFO, "FCOE enabled with DCB \n"); + ixgbe_set_dcb_queues(adapter); + } +#endif + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); + ixgbe_set_rss_queues(adapter); + } + /* adding FCoE rx rings to the end */ + f->mask = adapter->num_rx_queues; + adapter->num_rx_queues += f->indices; + if (adapter->num_tx_queues == 0) + adapter->num_tx_queues = f->indices; + + ret = true; + } + + return ret; +} + +#endif /* IXGBE_FCOE */ /* * ixgbe_set_num_queues: Allocate queues for device, feature dependant * @adapter: board private structure to initialize @@ -2723,11 +3146,19 @@ static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) **/ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) { +#ifdef IXGBE_FCOE + if (ixgbe_set_fcoe_queues(adapter)) + goto done; + +#endif /* IXGBE_FCOE */ #ifdef CONFIG_IXGBE_DCB if (ixgbe_set_dcb_queues(adapter)) goto done; #endif + if (ixgbe_set_fdir_queues(adapter)) + goto done; + if (ixgbe_set_rss_queues(adapter)) goto done; @@ -2778,9 +3209,6 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; kfree(adapter->msix_entries); adapter->msix_entries = NULL; - adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; - adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; - ixgbe_set_num_queues(adapter); } else { adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */ /* @@ -2901,6 +3329,64 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) } #endif +/** + * ixgbe_cache_ring_fdir - Descriptor ring to register mapping for Flow Director + * @adapter: board private structure to initialize + * + * Cache the descriptor ring offsets for Flow Director to the assigned rings. + * + **/ +static bool inline ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter) +{ + int i; + bool ret = false; + + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED && + ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) { + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i].reg_idx = i; + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i].reg_idx = i; + ret = true; + } + + return ret; +} + +#ifdef IXGBE_FCOE +/** + * ixgbe_cache_ring_fcoe - Descriptor ring to register mapping for the FCoE + * @adapter: board private structure to initialize + * + * Cache the descriptor ring offsets for FCoE mode to the assigned rings. + * + */ +static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) +{ + int i, fcoe_i = 0; + bool ret = false; + struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; + + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { +#ifdef CONFIG_IXGBE_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + ixgbe_cache_ring_dcb(adapter); + fcoe_i = adapter->rx_ring[0].reg_idx + 1; + } +#endif /* CONFIG_IXGBE_DCB */ + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + ixgbe_cache_ring_rss(adapter); + fcoe_i = f->mask; + } + for (i = 0; i < f->indices; i++, fcoe_i++) + adapter->rx_ring[f->mask + i].reg_idx = fcoe_i; + ret = true; + } + return ret; +} + +#endif /* IXGBE_FCOE */ /** * ixgbe_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize @@ -2918,11 +3404,19 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) adapter->rx_ring[0].reg_idx = 0; adapter->tx_ring[0].reg_idx = 0; +#ifdef IXGBE_FCOE + if (ixgbe_cache_ring_fcoe(adapter)) + return; + +#endif /* IXGBE_FCOE */ #ifdef CONFIG_IXGBE_DCB if (ixgbe_cache_ring_dcb(adapter)) return; #endif + if (ixgbe_cache_ring_fdir(adapter)) + return; + if (ixgbe_cache_ring_rss(adapter)) return; } @@ -3004,31 +3498,23 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) * mean we disable MSI-X capabilities of the adapter. */ adapter->msix_entries = kcalloc(v_budget, sizeof(struct msix_entry), GFP_KERNEL); - if (!adapter->msix_entries) { - adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; - adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; - ixgbe_set_num_queues(adapter); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - err = ixgbe_alloc_queues(adapter); - if (err) { - DPRINTK(PROBE, ERR, "Unable to allocate memory " - "for queues\n"); - goto out; - } + if (adapter->msix_entries) { + for (vector = 0; vector < v_budget; vector++) + adapter->msix_entries[vector].entry = vector; - goto try_msi; + ixgbe_acquire_msix_vectors(adapter, v_budget); + + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + goto out; } - for (vector = 0; vector < v_budget; vector++) - adapter->msix_entries[vector].entry = vector; + adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; + adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + adapter->atr_sample_rate = 0; + ixgbe_set_num_queues(adapter); - ixgbe_acquire_msix_vectors(adapter, v_budget); - - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) - goto out; - -try_msi: err = pci_enable_msi(adapter->pdev); if (!err) { adapter->flags |= IXGBE_FLAG_MSI_ENABLED; @@ -3043,6 +3529,79 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) return err; } +/** + * ixgbe_alloc_q_vectors - Allocate memory for interrupt vectors + * @adapter: board private structure to initialize + * + * We allocate one q_vector per queue interrupt. If allocation fails we + * return -ENOMEM. + **/ +static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) +{ + int q_idx, num_q_vectors; + struct ixgbe_q_vector *q_vector; + int napi_vectors; + int (*poll)(struct napi_struct *, int); + + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + napi_vectors = adapter->num_rx_queues; + poll = &ixgbe_clean_rxtx_many; + } else { + num_q_vectors = 1; + napi_vectors = 1; + poll = &ixgbe_poll; + } + + for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { + q_vector = kzalloc(sizeof(struct ixgbe_q_vector), GFP_KERNEL); + if (!q_vector) + goto err_out; + q_vector->adapter = adapter; + q_vector->eitr = adapter->eitr_param; + q_vector->v_idx = q_idx; + netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); + adapter->q_vector[q_idx] = q_vector; + } + + return 0; + +err_out: + while (q_idx) { + q_idx--; + q_vector = adapter->q_vector[q_idx]; + netif_napi_del(&q_vector->napi); + kfree(q_vector); + adapter->q_vector[q_idx] = NULL; + } + return -ENOMEM; +} + +/** + * ixgbe_free_q_vectors - Free memory allocated for interrupt vectors + * @adapter: board private structure to initialize + * + * This function frees the memory allocated to the q_vectors. In addition if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + **/ +static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter) +{ + int q_idx, num_q_vectors; + + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + else + num_q_vectors = 1; + + for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { + struct ixgbe_q_vector *q_vector = adapter->q_vector[q_idx]; + adapter->q_vector[q_idx] = NULL; + netif_napi_del(&q_vector->napi); + kfree(q_vector); + } +} + void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) { if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { @@ -3074,18 +3633,25 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) /* Number of supported queues */ ixgbe_set_num_queues(adapter); - err = ixgbe_alloc_queues(adapter); - if (err) { - DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); - goto err_alloc_queues; - } - err = ixgbe_set_interrupt_capability(adapter); if (err) { DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n"); goto err_set_interrupt; } + err = ixgbe_alloc_q_vectors(adapter); + if (err) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queue " + "vectors\n"); + goto err_alloc_q_vectors; + } + + err = ixgbe_alloc_queues(adapter); + if (err) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + goto err_alloc_queues; + } + DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, " "Tx Queue count = %u\n", (adapter->num_rx_queues > 1) ? "Enabled" : @@ -3095,11 +3661,30 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) return 0; +err_alloc_queues: + ixgbe_free_q_vectors(adapter); +err_alloc_q_vectors: + ixgbe_reset_interrupt_capability(adapter); err_set_interrupt: + return err; +} + +/** + * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings + * @adapter: board private structure to clear interrupt scheme on + * + * We go through and clear interrupt specific resources and reset the structure + * to pre-load conditions + **/ +void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) +{ kfree(adapter->tx_ring); kfree(adapter->rx_ring); -err_alloc_queues: - return err; + adapter->tx_ring = NULL; + adapter->rx_ring = NULL; + + ixgbe_free_q_vectors(adapter); + ixgbe_reset_interrupt_capability(adapter); } /** @@ -3185,10 +3770,24 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_RSS].indices = rss; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES; - if (hw->mac.type == ixgbe_mac_82598EB) + if (hw->mac.type == ixgbe_mac_82598EB) { + if (hw->device_id == IXGBE_DEV_ID_82598AT) + adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; - else if (hw->mac.type == ixgbe_mac_82599EB) + } else if (hw->mac.type == ixgbe_mac_82599EB) { adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; + adapter->flags |= IXGBE_FLAG2_RSC_CAPABLE; + adapter->flags |= IXGBE_FLAG2_RSC_ENABLED; + adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->ring_feature[RING_F_FDIR].indices = + IXGBE_MAX_FDIR_INDICES; + adapter->atr_sample_rate = 20; + adapter->fdir_pballoc = 0; +#ifdef IXGBE_FCOE + adapter->flags |= IXGBE_FLAG_FCOE_ENABLED; + adapter->ring_feature[RING_F_FCOE].indices = IXGBE_FCRETA_SIZE; +#endif /* IXGBE_FCOE */ + } #ifdef CONFIG_IXGBE_DCB /* Configure DCB traffic classes */ @@ -3203,6 +3802,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100; adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100; adapter->dcb_cfg.rx_pba_cfg = pba_equal; + adapter->dcb_cfg.pfc_mode_enable = false; adapter->dcb_cfg.round_robin_enable = false; adapter->dcb_set_bitmap = 0x00; ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg, @@ -3213,6 +3813,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* default flow control settings */ hw->fc.requested_mode = ixgbe_fc_full; hw->fc.current_mode = ixgbe_fc_full; /* init for ethtool output */ +#ifdef CONFIG_DCB + adapter->last_lfc_mode = hw->fc.current_mode; +#endif hw->fc.high_water = IXGBE_DEFAULT_FCRTH; hw->fc.low_water = IXGBE_DEFAULT_FCRTL; hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; @@ -3503,6 +4106,8 @@ static int ixgbe_open(struct net_device *netdev) if (test_bit(__IXGBE_TESTING, &adapter->state)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = ixgbe_setup_all_tx_resources(adapter); if (err) @@ -3515,8 +4120,6 @@ static int ixgbe_open(struct net_device *netdev) ixgbe_configure(adapter); - ixgbe_napi_add_all(adapter); - err = ixgbe_request_irq(adapter); if (err) goto err_req_irq; @@ -3568,55 +4171,6 @@ static int ixgbe_close(struct net_device *netdev) return 0; } -/** - * ixgbe_napi_add_all - prep napi structs for use - * @adapter: private struct - * - * helper function to napi_add each possible q_vector->napi - */ -void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) -{ - int q_idx, q_vectors; - struct net_device *netdev = adapter->netdev; - int (*poll)(struct napi_struct *, int); - - /* check if we already have our netdev->napi_list populated */ - if (&netdev->napi_list != netdev->napi_list.next) - return; - - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - poll = &ixgbe_clean_rxonly; - /* Only enable as many vectors as we have rx queues. */ - q_vectors = adapter->num_rx_queues; - } else { - poll = &ixgbe_poll; - /* only one q_vector for legacy modes */ - q_vectors = 1; - } - - for (q_idx = 0; q_idx < q_vectors; q_idx++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; - netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); - } -} - -void ixgbe_napi_del_all(struct ixgbe_adapter *adapter) -{ - int q_idx; - int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - - /* legacy and MSI only use one vector */ - if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) - q_vectors = 1; - - for (q_idx = 0; q_idx < q_vectors; q_idx++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; - if (!q_vector->rxr_count) - continue; - netif_napi_del(&q_vector->napi); - } -} - #ifdef CONFIG_PM static int ixgbe_resume(struct pci_dev *pdev) { @@ -3626,7 +4180,8 @@ static int ixgbe_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - err = pci_enable_device(pdev); + + err = pci_enable_device_mem(pdev); if (err) { printk(KERN_ERR "ixgbe: Cannot enable PCI device from " "suspend\n"); @@ -3634,8 +4189,7 @@ static int ixgbe_resume(struct pci_dev *pdev) } pci_set_master(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); + pci_wake_from_d3(pdev, false); err = ixgbe_init_interrupt_scheme(adapter); if (err) { @@ -3679,11 +4233,7 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) ixgbe_free_all_tx_resources(adapter); ixgbe_free_all_rx_resources(adapter); } - ixgbe_reset_interrupt_capability(adapter); - ixgbe_napi_del_all(adapter); - INIT_LIST_HEAD(&netdev->napi_list); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); + ixgbe_clear_interrupt_scheme(adapter); #ifdef CONFIG_PM retval = pci_save_state(pdev); @@ -3711,13 +4261,10 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); } - if (wufc && hw->mac.type == ixgbe_mac_82599EB) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } + if (wufc && hw->mac.type == ixgbe_mac_82599EB) + pci_wake_from_d3(pdev, true); + else + pci_wake_from_d3(pdev, false); *enable_wake = !!wufc; @@ -3772,9 +4319,13 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; if (hw->mac.type == ixgbe_mac_82599EB) { + u64 rsc_count = 0; for (i = 0; i < 16; i++) adapter->hw_rx_no_dma_resources += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); + for (i = 0; i < adapter->num_rx_queues; i++) + rsc_count += adapter->rx_ring[i].rsc_count; + adapter->rsc_count = rsc_count; } adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); @@ -3821,6 +4372,16 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */ adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); + adapter->stats.fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); + adapter->stats.fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS); +#ifdef IXGBE_FCOE + adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); + adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); + adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); + adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); + adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); + adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); +#endif /* IXGBE_FCOE */ } else { adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); @@ -3888,64 +4449,43 @@ static void ixgbe_watchdog(unsigned long data) { struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; struct ixgbe_hw *hw = &adapter->hw; + u64 eics = 0; + int i; - /* Do the watchdog outside of interrupt context due to the lovely - * delays that some of the newer hardware requires */ - if (!test_bit(__IXGBE_DOWN, &adapter->state)) { - u64 eics = 0; - int i; + /* + * Do the watchdog outside of interrupt context due to the lovely + * delays that some of the newer hardware requires + */ - for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) - eics |= (1 << i); + if (test_bit(__IXGBE_DOWN, &adapter->state)) + goto watchdog_short_circuit; - /* Cause software interrupt to ensure rx rings are cleaned */ - switch (hw->mac.type) { - case ixgbe_mac_82598EB: - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - IXGBE_WRITE_REG(hw, IXGBE_EICS, (u32)eics); - } else { - /* - * for legacy and MSI interrupts don't set any - * bits that are enabled for EIAM, because this - * operation would set *both* EIMS and EICS for - * any bit in EIAM - */ - IXGBE_WRITE_REG(hw, IXGBE_EICS, - (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); - } - break; - case ixgbe_mac_82599EB: - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - /* - * EICS(0..15) first 0-15 q vectors - * EICS[1] (16..31) q vectors 16-31 - * EICS[2] (0..31) q vectors 32-63 - */ - IXGBE_WRITE_REG(hw, IXGBE_EICS, - (u32)(eics & 0xFFFF)); - IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(1), - (u32)(eics & 0xFFFF0000)); - IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(2), - (u32)(eics >> 32)); - } else { - /* - * for legacy and MSI interrupts don't set any - * bits that are enabled for EIAM, because this - * operation would set *both* EIMS and EICS for - * any bit in EIAM - */ - IXGBE_WRITE_REG(hw, IXGBE_EICS, - (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); - } - break; - default: - break; - } - /* Reset the timer */ - mod_timer(&adapter->watchdog_timer, - round_jiffies(jiffies + 2 * HZ)); + if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { + /* + * for legacy and MSI interrupts don't set any bits + * that are enabled for EIAM, because this operation + * would set *both* EIMS and EICS for any bit in EIAM + */ + IXGBE_WRITE_REG(hw, IXGBE_EICS, + (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); + goto watchdog_reschedule; } + /* get one bit for every active tx/rx interrupt vector */ + for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { + struct ixgbe_q_vector *qv = adapter->q_vector[i]; + if (qv->rxr_count || qv->txr_count) + eics |= ((u64)1 << i); + } + + /* Cause software interrupt to ensure rx rings are cleaned */ + ixgbe_irq_rearm_queues(adapter, eics); + +watchdog_reschedule: + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); + +watchdog_short_circuit: schedule_work(&adapter->watchdog_task); } @@ -3998,6 +4538,30 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) adapter->flags &= ~IXGBE_FLAG_IN_SFP_MOD_TASK; } +/** + * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table + * @work: pointer to work_struct containing our data + **/ +static void ixgbe_fdir_reinit_task(struct work_struct *work) +{ + struct ixgbe_adapter *adapter = container_of(work, + struct ixgbe_adapter, + fdir_reinit_task); + struct ixgbe_hw *hw = &adapter->hw; + int i; + + if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { + for (i = 0; i < adapter->num_tx_queues; i++) + set_bit(__IXGBE_FDIR_INIT_DONE, + &(adapter->tx_ring[i].reinit_state)); + } else { + DPRINTK(PROBE, ERR, "failed to finish FDIR re-initialization, " + "ignored adding FDIR ATR filters \n"); + } + /* Done FDIR Re-initialization, enable transmits */ + netif_tx_start_all_queues(adapter->netdev); +} + /** * ixgbe_watchdog_task - worker thread to bring link up * @work: pointer to work_struct containing our data @@ -4011,16 +4575,32 @@ static void ixgbe_watchdog_task(struct work_struct *work) struct ixgbe_hw *hw = &adapter->hw; u32 link_speed = adapter->link_speed; bool link_up = adapter->link_up; + int i; + struct ixgbe_ring *tx_ring; + int some_tx_pending = 0; adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); + if (link_up) { +#ifdef CONFIG_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + for (i = 0; i < MAX_TRAFFIC_CLASS; i++) + hw->mac.ops.fc_enable(hw, i); + } else { + hw->mac.ops.fc_enable(hw, 0); + } +#else + hw->mac.ops.fc_enable(hw, 0); +#endif + } + if (link_up || time_after(jiffies, (adapter->link_check_timeout + IXGBE_TRY_LINK_TIMEOUT))) { - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); } adapter->link_up = link_up; adapter->link_speed = link_speed; @@ -4068,6 +4648,25 @@ static void ixgbe_watchdog_task(struct work_struct *work) } } + if (!netif_carrier_ok(netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) { + tx_ring = &adapter->tx_ring[i]; + if (tx_ring->next_to_use != tx_ring->next_to_clean) { + some_tx_pending = 1; + break; + } + } + + if (some_tx_pending) { + /* We've lost link, so the controller stops DMA, + * but we've got queued Tx work that's never going + * to get done, so reset controller to flush Tx. + * (Do the reset outside of interrupt context). + */ + schedule_work(&adapter->reset_task); + } + } + ixgbe_update_stats(adapter); adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK; } @@ -4196,12 +4795,18 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, if (ip_hdr(skb)->protocol == IPPROTO_TCP) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + else if (ip_hdr(skb)->protocol == IPPROTO_SCTP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_SCTP; break; case cpu_to_be16(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_SCTP; break; default: if (unlikely(net_ratelimit())) { @@ -4234,10 +4839,12 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, static int ixgbe_tx_map(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, - struct sk_buff *skb, unsigned int first) + struct sk_buff *skb, u32 tx_flags, + unsigned int first) { struct ixgbe_tx_buffer *tx_buffer_info; - unsigned int len = skb_headlen(skb); + unsigned int len; + unsigned int total = skb->len; unsigned int offset = 0, size, count = 0, i; unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; @@ -4252,16 +4859,22 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, map = skb_shinfo(skb)->dma_maps; + if (tx_flags & IXGBE_TX_FLAGS_FCOE) + /* excluding fcoe_crc_eof for FCoE */ + total -= sizeof(struct fcoe_crc_eof); + + len = min(skb_headlen(skb), total); while (len) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD); tx_buffer_info->length = size; - tx_buffer_info->dma = map[0] + offset; + tx_buffer_info->dma = skb_shinfo(skb)->dma_head + offset; tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; len -= size; + total -= size; offset += size; count++; @@ -4276,7 +4889,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, struct skb_frag_struct *frag; frag = &skb_shinfo(skb)->frags[f]; - len = frag->size; + len = min((unsigned int)frag->size, total); offset = 0; while (len) { @@ -4288,14 +4901,17 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD); tx_buffer_info->length = size; - tx_buffer_info->dma = map[f + 1] + offset; + tx_buffer_info->dma = map[f] + offset; tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; len -= size; + total -= size; offset += size; count++; } + if (total == 0) + break; } tx_ring->tx_buffer_info[i].skb = skb; @@ -4337,6 +4953,13 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, olinfo_status |= IXGBE_TXD_POPTS_TXSM << IXGBE_ADVTXD_POPTS_SHIFT; + if (tx_flags & IXGBE_TX_FLAGS_FCOE) { + olinfo_status |= IXGBE_ADVTXD_CC; + olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT); + if (tx_flags & IXGBE_TX_FLAGS_FSO) + cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE; + } + olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT); i = tx_ring->next_to_use; @@ -4366,6 +4989,58 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, writel(i, adapter->hw.hw_addr + tx_ring->tail); } +static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb, + int queue, u32 tx_flags) +{ + /* Right now, we support IPv4 only */ + struct ixgbe_atr_input atr_input; + struct tcphdr *th; + struct udphdr *uh; + struct iphdr *iph = ip_hdr(skb); + struct ethhdr *eth = (struct ethhdr *)skb->data; + u16 vlan_id, src_port, dst_port, flex_bytes; + u32 src_ipv4_addr, dst_ipv4_addr; + u8 l4type = 0; + + /* check if we're UDP or TCP */ + if (iph->protocol == IPPROTO_TCP) { + th = tcp_hdr(skb); + src_port = th->source; + dst_port = th->dest; + l4type |= IXGBE_ATR_L4TYPE_TCP; + /* l4type IPv4 type is 0, no need to assign */ + } else if(iph->protocol == IPPROTO_UDP) { + uh = udp_hdr(skb); + src_port = uh->source; + dst_port = uh->dest; + l4type |= IXGBE_ATR_L4TYPE_UDP; + /* l4type IPv4 type is 0, no need to assign */ + } else { + /* Unsupported L4 header, just bail here */ + return; + } + + memset(&atr_input, 0, sizeof(struct ixgbe_atr_input)); + + vlan_id = (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK) >> + IXGBE_TX_FLAGS_VLAN_SHIFT; + src_ipv4_addr = iph->saddr; + dst_ipv4_addr = iph->daddr; + flex_bytes = eth->h_proto; + + ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id); + ixgbe_atr_set_src_port_82599(&atr_input, dst_port); + ixgbe_atr_set_dst_port_82599(&atr_input, src_port); + ixgbe_atr_set_flex_byte_82599(&atr_input, flex_bytes); + ixgbe_atr_set_l4type_82599(&atr_input, l4type); + /* src and dst are inverted, think how the receiver sees them */ + ixgbe_atr_set_src_ipv4_82599(&atr_input, dst_ipv4_addr); + ixgbe_atr_set_dst_ipv4_82599(&atr_input, src_ipv4_addr); + + /* This assumes the Rx queue and Tx queue are bound to the same CPU */ + ixgbe_fdir_add_signature_filter_82599(&adapter->hw, &atr_input, queue); +} + static int __ixgbe_maybe_stop_tx(struct net_device *netdev, struct ixgbe_ring *tx_ring, int size) { @@ -4400,6 +5075,9 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) { struct ixgbe_adapter *adapter = netdev_priv(dev); + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) + return smp_processor_id(); + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) return 0; /* All traffic should default to class 0 */ @@ -4433,10 +5111,16 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; tx_flags |= IXGBE_TX_FLAGS_VLAN; } - /* three things can cause us to need a context descriptor */ + + if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && + (skb->protocol == htons(ETH_P_FCOE))) + tx_flags |= IXGBE_TX_FLAGS_FCOE; + + /* four things can cause us to need a context descriptor */ if (skb_is_gso(skb) || (skb->ip_summed == CHECKSUM_PARTIAL) || - (tx_flags & IXGBE_TX_FLAGS_VLAN)) + (tx_flags & IXGBE_TX_FLAGS_VLAN) || + (tx_flags & IXGBE_TX_FLAGS_FCOE)) count++; count += TXD_USE_COUNT(skb_headlen(skb)); @@ -4448,27 +5132,49 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } - if (skb->protocol == htons(ETH_P_IP)) - tx_flags |= IXGBE_TX_FLAGS_IPV4; first = tx_ring->next_to_use; - tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len); - if (tso < 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; + if (tx_flags & IXGBE_TX_FLAGS_FCOE) { +#ifdef IXGBE_FCOE + /* setup tx offload for FCoE */ + tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + if (tso) + tx_flags |= IXGBE_TX_FLAGS_FSO; +#endif /* IXGBE_FCOE */ + } else { + if (skb->protocol == htons(ETH_P_IP)) + tx_flags |= IXGBE_TX_FLAGS_IPV4; + tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (tso) + tx_flags |= IXGBE_TX_FLAGS_TSO; + else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) && + (skb->ip_summed == CHECKSUM_PARTIAL)) + tx_flags |= IXGBE_TX_FLAGS_CSUM; } - if (tso) - tx_flags |= IXGBE_TX_FLAGS_TSO; - else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) && - (skb->ip_summed == CHECKSUM_PARTIAL)) - tx_flags |= IXGBE_TX_FLAGS_CSUM; - - count = ixgbe_tx_map(adapter, tx_ring, skb, first); - + count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first); if (count) { + /* add the ATR filter if ATR is on */ + if (tx_ring->atr_sample_rate) { + ++tx_ring->atr_count; + if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) && + test_bit(__IXGBE_FDIR_INIT_DONE, + &tx_ring->reinit_state)) { + ixgbe_atr(adapter, skb, tx_ring->queue_index, + tx_flags); + tx_ring->atr_count = 0; + } + } ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len, hdr_len); - netdev->trans_start = jiffies; ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); } else { @@ -4519,6 +5225,82 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p) return 0; } +static int +ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u16 value; + int rc; + + if (prtad != hw->phy.mdio.prtad) + return -EINVAL; + rc = hw->phy.ops.read_reg(hw, addr, devad, &value); + if (!rc) + rc = value; + return rc; +} + +static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad, + u16 addr, u16 value) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + + if (prtad != hw->phy.mdio.prtad) + return -EINVAL; + return hw->phy.ops.write_reg(hw, addr, devad, value); +} + +static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd); +} + +/** + * ixgbe_add_sanmac_netdev - Add the SAN MAC address to the corresponding + * netdev->dev_addr_list + * @netdev: network interface device structure + * + * Returns non-zero on failure + **/ +static int ixgbe_add_sanmac_netdev(struct net_device *dev) +{ + int err = 0; + struct ixgbe_adapter *adapter = netdev_priv(dev); + struct ixgbe_mac_info *mac = &adapter->hw.mac; + + if (is_valid_ether_addr(mac->san_addr)) { + rtnl_lock(); + err = dev_addr_add(dev, mac->san_addr, NETDEV_HW_ADDR_T_SAN); + rtnl_unlock(); + } + return err; +} + +/** + * ixgbe_del_sanmac_netdev - Removes the SAN MAC address to the corresponding + * netdev->dev_addr_list + * @netdev: network interface device structure + * + * Returns non-zero on failure + **/ +static int ixgbe_del_sanmac_netdev(struct net_device *dev) +{ + int err = 0; + struct ixgbe_adapter *adapter = netdev_priv(dev); + struct ixgbe_mac_info *mac = &adapter->hw.mac; + + if (is_valid_ether_addr(mac->san_addr)) { + rtnl_lock(); + err = dev_addr_del(dev, mac->san_addr, NETDEV_HW_ADDR_T_SAN); + rtnl_unlock(); + } + return err; +} + #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs @@ -4552,9 +5334,14 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_vlan_rx_register = ixgbe_vlan_rx_register, .ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid, + .ndo_do_ioctl = ixgbe_ioctl, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ixgbe_netpoll, #endif +#ifdef IXGBE_FCOE + .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get, + .ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put, +#endif /* IXGBE_FCOE */ }; /** @@ -4577,9 +5364,12 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; static int cards_found; int i, err, pci_using_dac; +#ifdef IXGBE_FCOE + u16 device_caps; +#endif u32 part_num, eec; - err = pci_enable_device(pdev); + err = pci_enable_device_mem(pdev); if (err) return err; @@ -4599,9 +5389,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, pci_using_dac = 0; } - err = pci_request_regions(pdev, ixgbe_driver_name); + err = pci_request_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM), ixgbe_driver_name); if (err) { - dev_err(&pdev->dev, "pci_request_regions failed 0x%x\n", err); + dev_err(&pdev->dev, + "pci_request_selected_regions failed 0x%x\n", err); goto err_pci_reg; } @@ -4665,6 +5457,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* PHY */ memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops)); hw->phy.sfp_type = ixgbe_sfp_type_unknown; + /* ixgbe_identify_phy_generic will set prtad and mmds properly */ + hw->phy.mdio.prtad = MDIO_PRTAD_NONE; + hw->phy.mdio.mmds = 0; + hw->phy.mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + hw->phy.mdio.dev = netdev; + hw->phy.mdio.mdio_read = ixgbe_mdio_read; + hw->phy.mdio.mdio_write = ixgbe_mdio_write; /* set up this timer and work struct before calling get_invariants * which might start the timer @@ -4682,29 +5481,42 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, INIT_WORK(&adapter->sfp_config_module_task, ixgbe_sfp_config_module_task); - err = ii->get_invariants(hw); - if (err == IXGBE_ERR_SFP_NOT_PRESENT) { - /* start a kernel thread to watch for a module to arrive */ - set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); - mod_timer(&adapter->sfp_timer, - round_jiffies(jiffies + (2 * HZ))); - err = 0; - } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - DPRINTK(PROBE, ERR, "failed to load because an " - "unsupported SFP+ module type was detected.\n"); - goto err_hw_init; - } else if (err) { - goto err_hw_init; - } + ii->get_invariants(hw); /* setup the private structure */ err = ixgbe_sw_init(adapter); if (err) goto err_sw_init; + /* + * If there is a fan on this device and it has failed log the + * failure. + */ + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { + u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (esdp & IXGBE_ESDP_SDP1) + DPRINTK(PROBE, CRIT, + "Fan has stopped, replace the adapter\n"); + } + /* reset_hw fills in the perm_addr as well */ err = hw->mac.ops.reset_hw(hw); - if (err) { + if (err == IXGBE_ERR_SFP_NOT_PRESENT && + hw->mac.type == ixgbe_mac_82598EB) { + /* + * Start a kernel thread to watch for a module to arrive. + * Only do this for 82598, since 82599 will generate + * interrupts on module arrival. + */ + set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); + mod_timer(&adapter->sfp_timer, + round_jiffies(jiffies + (2 * HZ))); + err = 0; + } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { + dev_err(&adapter->pdev->dev, "failed to load because an " + "unsupported SFP+ module type was detected.\n"); + goto err_sw_init; + } else if (err) { dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); goto err_sw_init; } @@ -4720,6 +5532,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO6; netdev->features |= NETIF_F_GRO; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + netdev->features |= NETIF_F_SCTP_CSUM; + netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_IP_CSUM; @@ -4732,9 +5547,32 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->dcbnl_ops = &dcbnl_ops; #endif +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + if (hw->mac.ops.get_device_caps) { + hw->mac.ops.get_device_caps(hw, &device_caps); + if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) { + netdev->features |= NETIF_F_FCOE_CRC; + netdev->features |= NETIF_F_FSO; + netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; + DPRINTK(DRV, INFO, "FCoE enabled, " + "disabling Flow Director\n"); + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags &= + ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + adapter->atr_sample_rate = 0; + } else { + adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; + } + } + } +#endif /* IXGBE_FCOE */ if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + if (adapter->flags & IXGBE_FLAG2_RSC_ENABLED) + netdev->features |= NETIF_F_LRO; + /* make sure the EEPROM is good */ if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) { dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n"); @@ -4766,6 +5604,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, case IXGBE_DEV_ID_82599_KX4: adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | IXGBE_WUFC_MC | IXGBE_WUFC_BC); + /* Enable ACPI wakeup in GRC */ + IXGBE_WRITE_REG(hw, IXGBE_GRC, + (IXGBE_READ_REG(hw, IXGBE_GRC) & ~IXGBE_GRC_APME)); break; default: adapter->wol = 0; @@ -4774,6 +5615,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, device_init_wakeup(&adapter->pdev->dev, true); device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + /* pick up the PCI bus settings for reporting later */ + hw->mac.ops.get_bus_info(hw); + /* print bus type/speed/width info */ dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n", ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s": @@ -4805,24 +5649,37 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version); /* reset the hardware with the new settings */ - hw->mac.ops.start_hw(hw); - - netif_carrier_off(netdev); + err = hw->mac.ops.start_hw(hw); + if (err == IXGBE_ERR_EEPROM_VERSION) { + /* We are running on a pre-production device, log a warning */ + dev_warn(&pdev->dev, "This device is a pre-production " + "adapter/LOM. Please be aware there may be issues " + "associated with your hardware. If you are " + "experiencing problems please contact your Intel or " + "hardware representative who provided you with this " + "hardware.\n"); + } strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || + adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) + INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task); + #ifdef CONFIG_IXGBE_DCA if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; - /* always use CB2 mode, difference is masked - * in the CB driver */ - IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); ixgbe_setup_dca(adapter); } #endif + /* add san mac addr to netdev */ + ixgbe_add_sanmac_netdev(netdev); dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n"); cards_found++; @@ -4830,9 +5687,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err_register: ixgbe_release_hw_control(adapter); -err_hw_init: + ixgbe_clear_interrupt_scheme(adapter); err_sw_init: - ixgbe_reset_interrupt_capability(adapter); err_eeprom: clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); del_timer_sync(&adapter->sfp_timer); @@ -4843,7 +5699,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err_ioremap: free_netdev(netdev); err_alloc_etherdev: - pci_release_regions(pdev); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); err_pci_reg: err_dma: pci_disable_device(pdev); @@ -4877,6 +5734,9 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->sfp_task); cancel_work_sync(&adapter->multispeed_fiber_task); cancel_work_sync(&adapter->sfp_config_module_task); + if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || + adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) + cancel_work_sync(&adapter->fdir_reinit_task); flush_scheduled_work(); #ifdef CONFIG_IXGBE_DCA @@ -4887,19 +5747,27 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) } #endif +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + ixgbe_cleanup_fcoe(adapter); + +#endif /* IXGBE_FCOE */ + + /* remove the added san mac */ + ixgbe_del_sanmac_netdev(netdev); + if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); - ixgbe_reset_interrupt_capability(adapter); + ixgbe_clear_interrupt_scheme(adapter); ixgbe_release_hw_control(adapter); iounmap(adapter->hw.hw_addr); - pci_release_regions(pdev); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); DPRINTK(PROBE, INFO, "complete\n"); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); free_netdev(netdev); @@ -4927,6 +5795,9 @@ static pci_ers_result_t ixgbe_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)) ixgbe_down(adapter); pci_disable_device(pdev); @@ -4948,7 +5819,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) pci_ers_result_t result; int err; - if (pci_enable_device(pdev)) { + if (pci_enable_device_mem(pdev)) { DPRINTK(PROBE, ERR, "Cannot re-enable PCI device after reset.\n"); result = PCI_ERS_RESULT_DISCONNECT; @@ -4956,8 +5827,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); + pci_wake_from_d3(pdev, false); ixgbe_reset(adapter); IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 14e9606aa3b3..453e966762f0 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -44,7 +44,6 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data); static bool ixgbe_get_i2c_data(u32 *i2cctl); static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw); -static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw); @@ -61,8 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { - if (ixgbe_validate_phy_addr(hw, phy_addr)) { - hw->phy.addr = phy_addr; + if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { ixgbe_get_phy_id(hw); hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); @@ -77,26 +75,6 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) return status; } -/** - * ixgbe_validate_phy_addr - Determines phy address is valid - * @hw: pointer to hardware structure - * - **/ -static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) -{ - u16 phy_id = 0; - bool valid = false; - - hw->phy.addr = phy_addr; - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); - - if (phy_id != 0xFFFF && phy_id != 0x0) - valid = true; - - return valid; -} - /** * ixgbe_get_phy_id - Get the phy type * @hw: pointer to hardware structure @@ -108,14 +86,12 @@ static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw) u16 phy_id_high = 0; u16 phy_id_low = 0; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_DEVID1, MDIO_MMD_PMAPMD, &phy_id_high); if (status == 0) { hw->phy.id = (u32)(phy_id_high << 16); - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_DEVID2, MDIO_MMD_PMAPMD, &phy_id_low); hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK); hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); @@ -160,9 +136,8 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) * Perform soft PHY reset to the PHY_XS. * This will cause a soft reset to the PHY */ - return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, - IXGBE_MDIO_PHY_XS_RESET); + return hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, + MDIO_CTRL1_RESET); } /** @@ -192,7 +167,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -223,7 +198,8 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << + IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -292,7 +268,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -323,7 +299,8 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << + IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -365,7 +342,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) s32 status = IXGBE_NOT_IMPLEMENTED; u32 time_out; u32 max_time_out = 10; - u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; + u16 autoneg_reg; /* * Set advertisement settings in PHY based on autoneg_advertised @@ -373,36 +350,31 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) * tnx devices cannot be "forced" to a autoneg 10G and fail. But can * for a 1G. */ - hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg); if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) - autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */ + autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; else - autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */ + autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; - hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg); /* Restart PHY autonegotiation and wait for completion */ - hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, &autoneg_reg); - autoneg_reg |= IXGBE_MII_RESTART; + autoneg_reg |= MDIO_AN_CTRL1_RESTART; - hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, autoneg_reg); /* Wait for autonegotiation to finish */ for (time_out = 0; time_out < max_time_out; time_out++) { udelay(10); /* Restart PHY autonegotiation and wait for completion */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &autoneg_reg); - autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; - if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) { + autoneg_reg &= MDIO_AN_STAT1_COMPLETE; + if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) { status = 0; break; } @@ -457,23 +429,21 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) s32 ret_val = 0; u32 i; - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data); /* reset the PHY and poll for completion */ - hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, - (phy_data | IXGBE_MDIO_PHY_XS_RESET)); + hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, + (phy_data | MDIO_CTRL1_RESET)); for (i = 0; i < 100; i++) { - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); - if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0) + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, + &phy_data); + if ((phy_data & MDIO_CTRL1_RESET) == 0) break; msleep(10); } - if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) { + if ((phy_data & MDIO_CTRL1_RESET) != 0) { hw_dbg(hw, "PHY reset did not complete.\n"); ret_val = IXGBE_ERR_PHY; goto out; @@ -509,7 +479,7 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) for (i = 0; i < edata; i++) { hw->eeprom.ops.read(hw, data_offset, &eword); hw->phy.ops.write_reg(hw, phy_offset, - IXGBE_TWINAX_DEV, eword); + MDIO_MMD_PMAPMD, eword); hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword, phy_offset); data_offset++; @@ -552,18 +522,30 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 vendor_oui = 0; + enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; u8 identifier = 0; u8 comp_codes_1g = 0; u8 comp_codes_10g = 0; u8 oui_bytes[3] = {0, 0, 0}; - u8 transmission_media = 0; + u8 cable_tech = 0; u16 enforce_sfp = 0; + if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) { + hw->phy.sfp_type = ixgbe_sfp_type_not_present; + status = IXGBE_ERR_SFP_NOT_PRESENT; + goto out; + } + status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, &identifier); - if (status == IXGBE_ERR_SFP_NOT_PRESENT) { + if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) { + status = IXGBE_ERR_SFP_NOT_PRESENT; hw->phy.sfp_type = ixgbe_sfp_type_not_present; + if (hw->phy.type != ixgbe_phy_nl) { + hw->phy.id = 0; + hw->phy.type = ixgbe_phy_unknown; + } goto out; } @@ -572,8 +554,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) &comp_codes_1g); hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); - hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_TRANSMISSION_MEDIA, - &transmission_media); + hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY, + &cable_tech); /* ID Module * ========= @@ -586,7 +568,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) * 6 SFP_SR/LR_CORE1 - 82599-specific */ if (hw->mac.type == ixgbe_mac_82598EB) { - if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE) + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.sfp_type = ixgbe_sfp_type_da_cu; else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) hw->phy.sfp_type = ixgbe_sfp_type_sr; @@ -595,7 +577,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) else hw->phy.sfp_type = ixgbe_sfp_type_unknown; } else if (hw->mac.type == ixgbe_mac_82599EB) { - if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE) + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0; @@ -620,8 +602,19 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.sfp_type = ixgbe_sfp_type_unknown; } + if (hw->phy.sfp_type != stored_sfp_type) + hw->phy.sfp_setup_needed = true; + + /* Determine if the SFP+ PHY is dual speed or not. */ + hw->phy.multispeed_fiber = false; + if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) && + (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) || + ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && + (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) + hw->phy.multispeed_fiber = true; + /* Determine PHY vendor */ - if (hw->phy.type == ixgbe_phy_unknown) { + if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = identifier; hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE0, @@ -640,8 +633,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) switch (vendor_oui) { case IXGBE_SFF_VENDOR_OUI_TYCO: - if (transmission_media & - IXGBE_SFF_TWIN_AX_CAPABLE) + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.type = ixgbe_phy_tw_tyco; break; case IXGBE_SFF_VENDOR_OUI_FTL: @@ -654,31 +646,42 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.type = ixgbe_phy_sfp_intel; break; default: - if (transmission_media & - IXGBE_SFF_TWIN_AX_CAPABLE) + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.type = ixgbe_phy_tw_unknown; else hw->phy.type = ixgbe_phy_sfp_unknown; break; } } - if (hw->mac.type == ixgbe_mac_82598EB || - (hw->phy.sfp_type != ixgbe_sfp_type_sr && - hw->phy.sfp_type != ixgbe_sfp_type_lr && - hw->phy.sfp_type != ixgbe_sfp_type_srlr_core0 && - hw->phy.sfp_type != ixgbe_sfp_type_srlr_core1)) { + + /* All passive DA cables are supported */ + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) { status = 0; goto out; } - hw->eeprom.ops.read(hw, IXGBE_PHY_ENFORCE_INTEL_SFP_OFFSET, - &enforce_sfp); - if (!(enforce_sfp & IXGBE_PHY_ALLOW_ANY_SFP)) { + /* 1G SFP modules are not supported */ + if (comp_codes_10g == 0) { + hw->phy.type = ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; + goto out; + } + + /* Anything else 82598-based is supported */ + if (hw->mac.type == ixgbe_mac_82598EB) { + status = 0; + goto out; + } + + /* This is guaranteed to be 82599, no need to check for NULL */ + hw->mac.ops.get_device_caps(hw, &enforce_sfp); + if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) { status = 0; } else { hw_dbg(hw, "SFP+ module not supported\n"); + hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } } else { @@ -1279,7 +1282,7 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, udelay(10); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, &phy_data); phy_link = phy_data & IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; @@ -1307,8 +1310,7 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, { s32 status = 0; - status = hw->phy.ops.read_reg(hw, TNX_FW_REV, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, TNX_FW_REV, MDIO_MMD_VEND1, firmware_version); return status; diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index cc5f1b3287e1..9b700f5bf1ed 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -39,11 +39,12 @@ #define IXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define IXGBE_SFF_1GBE_COMP_CODES 0x6 #define IXGBE_SFF_10GBE_COMP_CODES 0x3 -#define IXGBE_SFF_TRANSMISSION_MEDIA 0x9 +#define IXGBE_SFF_CABLE_TECHNOLOGY 0x8 /* Bitmasks */ -#define IXGBE_SFF_TWIN_AX_CAPABLE 0x80 +#define IXGBE_SFF_DA_PASSIVE_CABLE 0x4 #define IXGBE_SFF_1GBASESX_CAPABLE 0x1 +#define IXGBE_SFF_1GBASELX_CAPABLE 0x2 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 #define IXGBE_SFF_10GBASELR_CAPABLE 0x20 #define IXGBE_I2C_EEPROM_READ_MASK 0x100 diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 030ff0a9ea67..fa87309dc087 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -29,6 +29,8 @@ #define _IXGBE_TYPE_H_ #include +#include +#include /* Vendor ID */ #define IXGBE_INTEL_VENDOR_ID 0x8086 @@ -45,9 +47,9 @@ #define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 -#define IXGBE_DEV_ID_82599 0x10D8 #define IXGBE_DEV_ID_82599_KX4 0x10F7 #define IXGBE_DEV_ID_82599_SFP 0x10FB +#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC /* General Registers */ #define IXGBE_CTRL 0x00000 @@ -229,6 +231,34 @@ #define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */ #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */ +/* Flow Director registers */ +#define IXGBE_FDIRCTRL 0x0EE00 +#define IXGBE_FDIRHKEY 0x0EE68 +#define IXGBE_FDIRSKEY 0x0EE6C +#define IXGBE_FDIRDIP4M 0x0EE3C +#define IXGBE_FDIRSIP4M 0x0EE40 +#define IXGBE_FDIRTCPM 0x0EE44 +#define IXGBE_FDIRUDPM 0x0EE48 +#define IXGBE_FDIRIP6M 0x0EE74 +#define IXGBE_FDIRM 0x0EE70 + +/* Flow Director Stats registers */ +#define IXGBE_FDIRFREE 0x0EE38 +#define IXGBE_FDIRLEN 0x0EE4C +#define IXGBE_FDIRUSTAT 0x0EE50 +#define IXGBE_FDIRFSTAT 0x0EE54 +#define IXGBE_FDIRMATCH 0x0EE58 +#define IXGBE_FDIRMISS 0x0EE5C + +/* Flow Director Programming registers */ +#define IXGBE_FDIRSIPv6(_i) (0x0EE0C + ((_i) * 4)) /* 3 of these (0-2) */ +#define IXGBE_FDIRIPSA 0x0EE18 +#define IXGBE_FDIRIPDA 0x0EE1C +#define IXGBE_FDIRPORT 0x0EE20 +#define IXGBE_FDIRVLAN 0x0EE24 +#define IXGBE_FDIRHASH 0x0EE28 +#define IXGBE_FDIRCMD 0x0EE2C + /* Transmit DMA registers */ #define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of these (0-31)*/ #define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40)) @@ -443,6 +473,21 @@ #define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE 0x4 +/* HW RSC registers */ +#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ + (0x0D02C + ((_i - 64) * 0x40))) +#define IXGBE_RSCDBU 0x03028 +#define IXGBE_RSCCTL_RSCEN 0x01 +#define IXGBE_RSCCTL_MAXDESC_1 0x00 +#define IXGBE_RSCCTL_MAXDESC_4 0x04 +#define IXGBE_RSCCTL_MAXDESC_8 0x08 +#define IXGBE_RSCCTL_MAXDESC_16 0x0C +#define IXGBE_RXDADV_RSCCNT_SHIFT 17 +#define IXGBE_GPIE_RSC_DELAY_SHIFT 11 +#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 +#define IXGBE_RSCDBU_RSCACKDIS 0x00000080 +#define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 + /* DCB registers */ #define IXGBE_RTRPCS 0x02430 #define IXGBE_RTTDCS 0x04900 @@ -462,6 +507,63 @@ #define IXGBE_RTTDTECC_NO_BCN 0x00000100 #define IXGBE_RTTBCNRC 0x04984 +/* FCoE registers */ +#define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */ +#define IXGBE_FCPTRH 0x02414 /* FC USer Desc. PTR High */ +#define IXGBE_FCBUFF 0x02418 /* FC Buffer Control */ +#define IXGBE_FCDMARW 0x02420 /* FC Receive DMA RW */ +#define IXGBE_FCINVST0 0x03FC0 /* FC Invalid DMA Context Status Reg 0 */ +#define IXGBE_FCINVST(_i) (IXGBE_FCINVST0 + ((_i) * 4)) +#define IXGBE_FCBUFF_VALID (1 << 0) /* DMA Context Valid */ +#define IXGBE_FCBUFF_BUFFSIZE (3 << 3) /* User Buffer Size */ +#define IXGBE_FCBUFF_WRCONTX (1 << 7) /* 0: Initiator, 1: Target */ +#define IXGBE_FCBUFF_BUFFCNT 0x0000ff00 /* Number of User Buffers */ +#define IXGBE_FCBUFF_OFFSET 0xffff0000 /* User Buffer Offset */ +#define IXGBE_FCBUFF_BUFFSIZE_SHIFT 3 +#define IXGBE_FCBUFF_BUFFCNT_SHIFT 8 +#define IXGBE_FCBUFF_OFFSET_SHIFT 16 +#define IXGBE_FCDMARW_WE (1 << 14) /* Write enable */ +#define IXGBE_FCDMARW_RE (1 << 15) /* Read enable */ +#define IXGBE_FCDMARW_FCOESEL 0x000001ff /* FC X_ID: 11 bits */ +#define IXGBE_FCDMARW_LASTSIZE 0xffff0000 /* Last User Buffer Size */ +#define IXGBE_FCDMARW_LASTSIZE_SHIFT 16 + +/* FCoE SOF/EOF */ +#define IXGBE_TEOFF 0x04A94 /* Tx FC EOF */ +#define IXGBE_TSOFF 0x04A98 /* Tx FC SOF */ +#define IXGBE_REOFF 0x05158 /* Rx FC EOF */ +#define IXGBE_RSOFF 0x051F8 /* Rx FC SOF */ +/* FCoE Filter Context Registers */ +#define IXGBE_FCFLT 0x05108 /* FC FLT Context */ +#define IXGBE_FCFLTRW 0x05110 /* FC Filter RW Control */ +#define IXGBE_FCPARAM 0x051d8 /* FC Offset Parameter */ +#define IXGBE_FCFLT_VALID (1 << 0) /* Filter Context Valid */ +#define IXGBE_FCFLT_FIRST (1 << 1) /* Filter First */ +#define IXGBE_FCFLT_SEQID 0x00ff0000 /* Sequence ID */ +#define IXGBE_FCFLT_SEQCNT 0xff000000 /* Sequence Count */ +#define IXGBE_FCFLTRW_RVALDT (1 << 13) /* Fast Re-Validation */ +#define IXGBE_FCFLTRW_WE (1 << 14) /* Write Enable */ +#define IXGBE_FCFLTRW_RE (1 << 15) /* Read Enable */ +/* FCoE Receive Control */ +#define IXGBE_FCRXCTRL 0x05100 /* FC Receive Control */ +#define IXGBE_FCRXCTRL_FCOELLI (1 << 0) /* Low latency interrupt */ +#define IXGBE_FCRXCTRL_SAVBAD (1 << 1) /* Save Bad Frames */ +#define IXGBE_FCRXCTRL_FRSTRDH (1 << 2) /* EN 1st Read Header */ +#define IXGBE_FCRXCTRL_LASTSEQH (1 << 3) /* EN Last Header in Seq */ +#define IXGBE_FCRXCTRL_ALLH (1 << 4) /* EN All Headers */ +#define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5) /* EN 1st Seq. Header */ +#define IXGBE_FCRXCTRL_ICRC (1 << 6) /* Ignore Bad FC CRC */ +#define IXGBE_FCRXCTRL_FCCRCBO (1 << 7) /* FC CRC Byte Ordering */ +#define IXGBE_FCRXCTRL_FCOEVER 0x00000f00 /* FCoE Version: 4 bits */ +#define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8 +/* FCoE Redirection */ +#define IXGBE_FCRECTL 0x0ED00 /* FC Redirection Control */ +#define IXGBE_FCRETA0 0x0ED10 /* FC Redirection Table 0 */ +#define IXGBE_FCRETA(_i) (IXGBE_FCRETA0 + ((_i) * 4)) /* FCoE Redir */ +#define IXGBE_FCRECTL_ENA 0x1 /* FCoE Redir Table Enable */ +#define IXGBE_FCRETA_SIZE 8 /* Max entries in FCRETA */ +#define IXGBE_FCRETA_ENTRY_MASK 0x0000007f /* 7 bits for the queue index */ + /* Stats registers */ #define IXGBE_CRCERRS 0x04000 #define IXGBE_ILLERRC 0x04004 @@ -533,6 +635,13 @@ #define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */ #define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */ +#define IXGBE_FCCRC 0x05118 /* Count of Good Eth CRC w/ Bad FC CRC */ +#define IXGBE_FCOERPDC 0x0241C /* FCoE Rx Packets Dropped Count */ +#define IXGBE_FCLAST 0x02424 /* FCoE Last Error Count */ +#define IXGBE_FCOEPRC 0x02428 /* Number of FCoE Packets Received */ +#define IXGBE_FCOEDWRC 0x0242C /* Number of FCoE DWords Received */ +#define IXGBE_FCOEPTC 0x08784 /* Number of FCoE Packets Transmitted */ +#define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */ /* Management */ #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */ @@ -833,13 +942,7 @@ /* Omer bit masks */ #define IXGBE_CORECTL_WRITE_CMD 0x00010000 -/* Device Type definitions for new protocol MDIO commands */ -#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 -#define IXGBE_MDIO_PCS_DEV_TYPE 0x3 -#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4 -#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ -#define IXGBE_TWINAX_DEV 1 +/* MDIO definitions */ #define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ @@ -850,31 +953,10 @@ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED 0x0018 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED 0x0010 -#define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */ -#define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */ -#define IXGBE_MDIO_PHY_XS_CONTROL 0x0 /* PHY_XS Control Reg */ -#define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */ -#define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ -#define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ -#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */ -#define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */ -#define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */ -#define IXGBE_MDIO_PHY_EXT_ABILITY 0xB /* Ext Ability Reg */ -#define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */ -#define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */ - #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ -/* MII clause 22/28 definitions */ -#define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 - -#define IXGBE_MII_SPEED_SELECTION_REG 0x10 -#define IXGBE_MII_RESTART 0x200 -#define IXGBE_MII_AUTONEG_COMPLETE 0x20 -#define IXGBE_MII_AUTONEG_REG 0x0 - #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 #define IXGBE_MAX_PHY_ADDR 32 @@ -898,8 +980,6 @@ #define IXGBE_CONTROL_NL 0x000F #define IXGBE_CONTROL_EOL_NL 0x0FFF #define IXGBE_CONTROL_SOL_NL 0x0000 -#define IXGBE_PHY_ENFORCE_INTEL_SFP_OFFSET 0x002C -#define IXGBE_PHY_ALLOW_ANY_SFP 0x1 /* General purpose Interrupt Enable */ #define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */ @@ -958,6 +1038,8 @@ #define IXGBE_VT_CTL_DIS_DEFPL 0x20000000 /* disable default pool */ #define IXGBE_VT_CTL_REPLEN 0x40000000 /* replication enabled */ #define IXGBE_VT_CTL_VT_ENABLE 0x00000001 /* Enable VT Mode */ +#define IXGBE_VT_CTL_POOL_SHIFT 7 +#define IXGBE_VT_CTL_POOL_MASK (0x3F << IXGBE_VT_CTL_POOL_SHIFT) /* VMOLR bitmasks */ #define IXGBE_VMOLR_AUPE 0x01000000 /* accept untagged packets */ @@ -1148,6 +1230,7 @@ /* Interrupt Vector Allocation Registers */ #define IXGBE_IVAR_REG_NUM 25 +#define IXGBE_IVAR_REG_NUM_82599 64 #define IXGBE_IVAR_TXRX_ENTRY 96 #define IXGBE_IVAR_RX_ENTRY 64 #define IXGBE_IVAR_RX_QUEUE(_i) (0 + (_i)) @@ -1163,6 +1246,7 @@ /* ETYPE Queue Filter/Select Bit Masks */ #define IXGBE_MAX_ETQF_FILTERS 8 +#define IXGBE_ETQF_FCOE 0x08000000 /* bit 27 */ #define IXGBE_ETQF_BCN 0x10000000 /* bit 28 */ #define IXGBE_ETQF_1588 0x40000000 /* bit 30 */ #define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */ @@ -1185,6 +1269,7 @@ */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_BCN 1 +#define IXGBE_ETQF_FILTER_FCOE 2 #define IXGBE_ETQF_FILTER_1588 3 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ @@ -1208,8 +1293,10 @@ #define IXGBE_STATUS_LAN_ID_1 0x00000004 /* LAN ID 1 */ /* ESDP Bit Masks */ -#define IXGBE_ESDP_SDP0 0x00000001 -#define IXGBE_ESDP_SDP1 0x00000002 +#define IXGBE_ESDP_SDP0 0x00000001 /* SDP0 Data Value */ +#define IXGBE_ESDP_SDP1 0x00000002 /* SDP1 Data Value */ +#define IXGBE_ESDP_SDP2 0x00000004 /* SDP2 Data Value */ +#define IXGBE_ESDP_SDP3 0x00000008 /* SDP3 Data Value */ #define IXGBE_ESDP_SDP4 0x00000010 /* SDP4 Data Value */ #define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */ #define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */ @@ -1309,8 +1396,6 @@ #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ -#define FIBER_LINK_UP_LIMIT 50 - /* PCS1GLSTA Bit Masks */ #define IXGBE_PCS1GLSTA_LINK_OK 1 #define IXGBE_PCS1GLSTA_SYNK_OK 0x10 @@ -1382,6 +1467,8 @@ #define IXGBE_FW_PTR 0x0F #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 +#define IXGBE_DEVICE_CAPS 0x2C +#define IXGBE_SAN_MAC_ADDR_PTR 0x28 #define IXGBE_PCIE_MSIX_82599_CAPS 0x72 #define IXGBE_PCIE_MSIX_82598_CAPS 0x62 @@ -1425,6 +1512,13 @@ #define IXGBE_EERD_ATTEMPTS 100000 #endif +#define IXGBE_SAN_MAC_ADDR_PORT0_OFFSET 0x0 +#define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3 +#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 +#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 +#define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 +#define IXGBE_FW_PATCH_VERSION_4 0x7 + /* PCI Bus Info */ #define IXGBE_PCI_LINK_STATUS 0xB2 #define IXGBE_PCI_LINK_WIDTH 0x3F0 @@ -1553,7 +1647,8 @@ #define IXGBE_MTQC_RT_ENA 0x1 /* DCB Enable */ #define IXGBE_MTQC_VT_ENA 0x2 /* VMDQ2 Enable */ #define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */ -#define IXGBE_MTQC_64VF 0x8 /* 2 TX Queues per pool w/64VF's */ +#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */ +#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */ #define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */ /* Receive Descriptor bit definitions */ @@ -1585,6 +1680,11 @@ #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ #define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */ #define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ +#define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCoEFe/IPE */ +#define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */ +#define IXGBE_RXDADV_ERR_FDIR_LEN 0x00100000 /* FDIR Length error */ +#define IXGBE_RXDADV_ERR_FDIR_DROP 0x00200000 /* FDIR Drop error */ +#define IXGBE_RXDADV_ERR_FDIR_COLL 0x00400000 /* FDIR Collision error */ #define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */ #define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */ #define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */ @@ -1604,12 +1704,19 @@ #define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM /* FDir Match */ #define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP /* IEEE VLAN Pkt */ #define IXGBE_RXDADV_STAT_MASK 0x000fffff /* Stat/NEXTP: bit 0-19 */ +#define IXGBE_RXDADV_STAT_FCEOFS 0x00000040 /* FCoE EOF/SOF Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT 0x00000030 /* FCoE Pkt Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */ +#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */ +#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */ +#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */ /* PSRTYPE bit definitions */ #define IXGBE_PSRTYPE_TCPHDR 0x00000010 #define IXGBE_PSRTYPE_UDPHDR 0x00000020 #define IXGBE_PSRTYPE_IPV4HDR 0x00000100 #define IXGBE_PSRTYPE_IPV6HDR 0x00000200 +#define IXGBE_PSRTYPE_L2HDR 0x00001000 /* SRRCTL bit definitions */ #define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ @@ -1710,6 +1817,82 @@ #endif +enum ixgbe_fdir_pballoc_type { + IXGBE_FDIR_PBALLOC_64K = 0, + IXGBE_FDIR_PBALLOC_128K, + IXGBE_FDIR_PBALLOC_256K, +}; +#define IXGBE_FDIR_PBALLOC_SIZE_SHIFT 16 + +/* Flow Director register values */ +#define IXGBE_FDIRCTRL_PBALLOC_64K 0x00000001 +#define IXGBE_FDIRCTRL_PBALLOC_128K 0x00000002 +#define IXGBE_FDIRCTRL_PBALLOC_256K 0x00000003 +#define IXGBE_FDIRCTRL_INIT_DONE 0x00000008 +#define IXGBE_FDIRCTRL_PERFECT_MATCH 0x00000010 +#define IXGBE_FDIRCTRL_REPORT_STATUS 0x00000020 +#define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080 +#define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8 +#define IXGBE_FDIRCTRL_FLEX_SHIFT 16 +#define IXGBE_FDIRCTRL_SEARCHLIM 0x00800000 +#define IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT 24 +#define IXGBE_FDIRCTRL_FULL_THRESH_MASK 0xF0000000 +#define IXGBE_FDIRCTRL_FULL_THRESH_SHIFT 28 + +#define IXGBE_FDIRTCPM_DPORTM_SHIFT 16 +#define IXGBE_FDIRUDPM_DPORTM_SHIFT 16 +#define IXGBE_FDIRIP6M_DIPM_SHIFT 16 +#define IXGBE_FDIRM_VLANID 0x00000001 +#define IXGBE_FDIRM_VLANP 0x00000002 +#define IXGBE_FDIRM_POOL 0x00000004 +#define IXGBE_FDIRM_L3P 0x00000008 +#define IXGBE_FDIRM_L4P 0x00000010 +#define IXGBE_FDIRM_FLEX 0x00000020 +#define IXGBE_FDIRM_DIPv6 0x00000040 + +#define IXGBE_FDIRFREE_FREE_MASK 0xFFFF +#define IXGBE_FDIRFREE_FREE_SHIFT 0 +#define IXGBE_FDIRFREE_COLL_MASK 0x7FFF0000 +#define IXGBE_FDIRFREE_COLL_SHIFT 16 +#define IXGBE_FDIRLEN_MAXLEN_MASK 0x3F +#define IXGBE_FDIRLEN_MAXLEN_SHIFT 0 +#define IXGBE_FDIRLEN_MAXHASH_MASK 0x7FFF0000 +#define IXGBE_FDIRLEN_MAXHASH_SHIFT 16 +#define IXGBE_FDIRUSTAT_ADD_MASK 0xFFFF +#define IXGBE_FDIRUSTAT_ADD_SHIFT 0 +#define IXGBE_FDIRUSTAT_REMOVE_MASK 0xFFFF0000 +#define IXGBE_FDIRUSTAT_REMOVE_SHIFT 16 +#define IXGBE_FDIRFSTAT_FADD_MASK 0x00FF +#define IXGBE_FDIRFSTAT_FADD_SHIFT 0 +#define IXGBE_FDIRFSTAT_FREMOVE_MASK 0xFF00 +#define IXGBE_FDIRFSTAT_FREMOVE_SHIFT 8 +#define IXGBE_FDIRPORT_DESTINATION_SHIFT 16 +#define IXGBE_FDIRVLAN_FLEX_SHIFT 16 +#define IXGBE_FDIRHASH_BUCKET_VALID_SHIFT 15 +#define IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT 16 + +#define IXGBE_FDIRCMD_CMD_MASK 0x00000003 +#define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001 +#define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002 +#define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003 +#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH 0x00000007 +#define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008 +#define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010 +#define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020 +#define IXGBE_FDIRCMD_L4TYPE_TCP 0x00000040 +#define IXGBE_FDIRCMD_L4TYPE_SCTP 0x00000060 +#define IXGBE_FDIRCMD_IPV6 0x00000080 +#define IXGBE_FDIRCMD_CLEARHT 0x00000100 +#define IXGBE_FDIRCMD_DROP 0x00000200 +#define IXGBE_FDIRCMD_INT 0x00000400 +#define IXGBE_FDIRCMD_LAST 0x00000800 +#define IXGBE_FDIRCMD_COLLISION 0x00001000 +#define IXGBE_FDIRCMD_QUEUE_EN 0x00008000 +#define IXGBE_FDIRCMD_RX_QUEUE_SHIFT 16 +#define IXGBE_FDIRCMD_VT_POOL_SHIFT 24 +#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 */ @@ -1836,6 +2019,16 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ #define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ #define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */ +#define IXGBE_ADVTXT_TUCMD_FCOE 0x00008000 /* FCoE Frame Type */ +#define IXGBE_ADVTXD_FCOEF_EOF_MASK (0x3 << 10) /* FC EOF index */ +#define IXGBE_ADVTXD_FCOEF_SOF ((1 << 2) << 10) /* FC SOF index */ +#define IXGBE_ADVTXD_FCOEF_PARINC ((1 << 3) << 10) /* Rel_Off in F_CTL */ +#define IXGBE_ADVTXD_FCOEF_ORIE ((1 << 4) << 10) /* Orientation: End */ +#define IXGBE_ADVTXD_FCOEF_ORIS ((1 << 5) << 10) /* Orientation: Start */ +#define IXGBE_ADVTXD_FCOEF_EOF_N (0x0 << 10) /* 00: EOFn */ +#define IXGBE_ADVTXD_FCOEF_EOF_T (0x1 << 10) /* 01: EOFt */ +#define IXGBE_ADVTXD_FCOEF_EOF_NI (0x2 << 10) /* 10: EOFni */ +#define IXGBE_ADVTXD_FCOEF_EOF_A (0x3 << 10) /* 11: EOFa */ #define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ @@ -1861,7 +2054,7 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_UNKNOWN 0 #define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001 #define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002 -#define IXGBE_PHYSICAL_LAYER_100BASE_T 0x0004 +#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004 #define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008 #define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010 #define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020 @@ -1870,6 +2063,47 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100 #define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200 #define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400 +#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800 +#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000 + +/* Software ATR hash keys */ +#define IXGBE_ATR_BUCKET_HASH_KEY 0xE214AD3D +#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x14364D17 + +/* Software ATR input stream offsets and masks */ +#define IXGBE_ATR_VLAN_OFFSET 0 +#define IXGBE_ATR_SRC_IPV6_OFFSET 2 +#define IXGBE_ATR_SRC_IPV4_OFFSET 14 +#define IXGBE_ATR_DST_IPV6_OFFSET 18 +#define IXGBE_ATR_DST_IPV4_OFFSET 30 +#define IXGBE_ATR_SRC_PORT_OFFSET 34 +#define IXGBE_ATR_DST_PORT_OFFSET 36 +#define IXGBE_ATR_FLEX_BYTE_OFFSET 38 +#define IXGBE_ATR_VM_POOL_OFFSET 40 +#define IXGBE_ATR_L4TYPE_OFFSET 41 + +#define IXGBE_ATR_L4TYPE_MASK 0x3 +#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4 +#define IXGBE_ATR_L4TYPE_UDP 0x1 +#define IXGBE_ATR_L4TYPE_TCP 0x2 +#define IXGBE_ATR_L4TYPE_SCTP 0x3 +#define IXGBE_ATR_HASH_MASK 0x7fff + +/* Flow Director ATR input struct. */ +struct ixgbe_atr_input { + /* Byte layout in order, all values with MSB first: + * + * vlan_id - 2 bytes + * src_ip - 16 bytes + * dst_ip - 16 bytes + * src_port - 2 bytes + * dst_port - 2 bytes + * flex_bytes - 2 bytes + * vm_pool - 1 byte + * l4type - 1 byte + */ + u8 byte_stream[42]; +}; enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, @@ -1897,6 +2131,7 @@ enum ixgbe_phy_type { ixgbe_phy_sfp_ftl, ixgbe_phy_sfp_unknown, ixgbe_phy_sfp_intel, + ixgbe_phy_sfp_unsupported, ixgbe_phy_generic }; @@ -2005,7 +2240,8 @@ struct ixgbe_fc_info { u16 pause_time; /* Flow Control Pause timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ - bool disable_fc_autoneg; /* Turn off autoneg FC mode */ + bool disable_fc_autoneg; /* Do not autonegotiate FC */ + bool fc_was_autonegged; /* Is current_mode the result of autonegging? */ enum ixgbe_fc_mode current_mode; /* FC mode in effect */ enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */ }; @@ -2075,6 +2311,12 @@ struct ixgbe_hw_stats { u64 fdirfstat_fremove; u64 fdirmatch; u64 fdirmiss; + u64 fccrc; + u64 fcoerpdc; + u64 fcoeprc; + u64 fcoeptc; + u64 fcoedwrc; + u64 fcoedwtc; }; /* forward declaration */ @@ -2101,6 +2343,8 @@ struct ixgbe_mac_operations { enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); u32 (*get_supported_physical_layer)(struct ixgbe_hw *); s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); + s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *); + s32 (*get_device_caps)(struct ixgbe_hw *, u16 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); void (*set_lan_id)(struct ixgbe_hw *); @@ -2129,8 +2373,7 @@ struct ixgbe_mac_operations { s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*init_rx_addrs)(struct ixgbe_hw *); - s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32, - ixgbe_mc_addr_itr); + s32 (*update_uc_addr_list)(struct ixgbe_hw *, struct list_head *); s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32, ixgbe_mc_addr_itr); s32 (*enable_mc)(struct ixgbe_hw *); @@ -2140,12 +2383,13 @@ struct ixgbe_mac_operations { s32 (*init_uta_tables)(struct ixgbe_hw *); /* Flow Control */ - s32 (*setup_fc)(struct ixgbe_hw *, s32); + s32 (*fc_enable)(struct ixgbe_hw *, s32); }; struct ixgbe_phy_operations { s32 (*identify)(struct ixgbe_hw *); s32 (*identify_sfp)(struct ixgbe_hw *); + s32 (*init)(struct ixgbe_hw *); s32 (*reset)(struct ixgbe_hw *); s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *); s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16); @@ -2173,6 +2417,7 @@ struct ixgbe_mac_info { enum ixgbe_mac_type type; u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; + u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; s32 mc_filter_type; u32 mcft_size; u32 vft_size; @@ -2185,14 +2430,16 @@ struct ixgbe_mac_info { bool orig_link_settings_stored; bool autoneg; bool autoneg_succeeded; + bool autotry_restart; }; struct ixgbe_phy_info { struct ixgbe_phy_operations ops; + struct mdio_if_info mdio; enum ixgbe_phy_type type; - u32 addr; u32 id; enum ixgbe_sfp_type sfp_type; + bool sfp_setup_needed; u32 revision; enum ixgbe_media_type media_type; bool reset_disable; @@ -2249,6 +2496,8 @@ struct ixgbe_info { #define IXGBE_ERR_SFP_NOT_SUPPORTED -19 #define IXGBE_ERR_SFP_NOT_PRESENT -20 #define IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT -21 +#define IXGBE_ERR_FDIR_REINIT_FAILED -23 +#define IXGBE_ERR_EEPROM_VERSION -24 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF #endif /* _IXGBE_TYPE_H_ */ diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index d3bf2f017cc2..2a0174b62e96 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -270,6 +270,18 @@ static int ixpdev_close(struct net_device *dev) return 0; } +static const struct net_device_ops ixpdev_netdev_ops = { + .ndo_open = ixpdev_open, + .ndo_stop = ixpdev_close, + .ndo_start_xmit = ixpdev_xmit, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ixpdev_poll_controller, +#endif +}; + struct net_device *ixpdev_alloc(int channel, int sizeof_priv) { struct net_device *dev; @@ -279,12 +291,7 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv) if (dev == NULL) return NULL; - dev->hard_start_xmit = ixpdev_xmit; - dev->open = ixpdev_open; - dev->stop = ixpdev_close; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ixpdev_poll_controller; -#endif + dev->netdev_ops = &ixpdev_netdev_ops; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 14248cfc3dfd..d12106b47bf2 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -96,6 +96,18 @@ static int jazzsonic_close(struct net_device* dev) return err; } +static const struct net_device_ops sonic_netdev_ops = { + .ndo_open = jazzsonic_open, + .ndo_stop = jazzsonic_close, + .ndo_start_xmit = sonic_send_packet, + .ndo_get_stats = sonic_get_stats, + .ndo_set_multicast_list = sonic_multicast_list, + .ndo_tx_timeout = sonic_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int __init sonic_probe1(struct net_device *dev) { static unsigned version_printed; @@ -179,12 +191,7 @@ static int __init sonic_probe1(struct net_device *dev) lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS * SONIC_BUS_SCALE(lp->dma_bitmode)); - dev->open = jazzsonic_open; - dev->stop = jazzsonic_close; - dev->hard_start_xmit = sonic_send_packet; - dev->get_stats = sonic_get_stats; - dev->set_multicast_list = &sonic_multicast_list; - dev->tx_timeout = sonic_tx_timeout; + dev->netdev_ops = &sonic_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; /* diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 621a7c0c46ba..1e3c63d67b91 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -1939,7 +1939,6 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) TXCS_SELECT_QUEUE0 | TXCS_QUEUE0S | TXCS_ENABLE); - netdev->trans_start = jiffies; tx_dbg(jme, "xmit: %d+%d@%lu\n", idx, skb_shinfo(skb)->nr_frags + 2, diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 38d6649a29c4..b4cf602c32b0 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -133,6 +133,7 @@ struct korina_private { int dma_halt_cnt; int dma_run_cnt; struct napi_struct napi; + struct timer_list media_check_timer; struct mii_if_info mii_if; struct net_device *dev; int phy_addr; @@ -664,6 +665,15 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) &lp->eth_regs->ethmac2); } +static void korina_poll_media(unsigned long data) +{ + struct net_device *dev = (struct net_device *) data; + struct korina_private *lp = netdev_priv(dev); + + korina_check_media(dev, 0); + mod_timer(&lp->media_check_timer, jiffies + HZ); +} + static void korina_set_carrier(struct mii_if_info *mii) { if (mii->force_media) { @@ -1034,6 +1044,7 @@ static int korina_open(struct net_device *dev) dev->name, lp->und_irq); goto err_free_ovr_irq; } + mod_timer(&lp->media_check_timer, jiffies + 1); out: return ret; @@ -1053,6 +1064,8 @@ static int korina_close(struct net_device *dev) struct korina_private *lp = netdev_priv(dev); u32 tmp; + del_timer(&lp->media_check_timer); + /* Disable interrupts */ disable_irq(lp->rx_irq); disable_irq(lp->tx_irq); @@ -1081,6 +1094,21 @@ static int korina_close(struct net_device *dev) return 0; } +static const struct net_device_ops korina_netdev_ops = { + .ndo_open = korina_open, + .ndo_stop = korina_close, + .ndo_start_xmit = korina_send_packet, + .ndo_set_multicast_list = korina_multicast_list, + .ndo_tx_timeout = korina_tx_timeout, + .ndo_do_ioctl = korina_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = korina_poll_controller, +#endif +}; + static int korina_probe(struct platform_device *pdev) { struct korina_device *bif = platform_get_drvdata(pdev); @@ -1149,17 +1177,9 @@ static int korina_probe(struct platform_device *pdev) dev->irq = lp->rx_irq; lp->dev = dev; - dev->open = korina_open; - dev->stop = korina_close; - dev->hard_start_xmit = korina_send_packet; - dev->set_multicast_list = &korina_multicast_list; + dev->netdev_ops = &korina_netdev_ops; dev->ethtool_ops = &netdev_ethtool_ops; - dev->tx_timeout = korina_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - dev->do_ioctl = &korina_ioctl; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = korina_poll_controller; -#endif netif_napi_add(dev, &lp->napi, korina_poll, 64); lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); @@ -1176,6 +1196,7 @@ static int korina_probe(struct platform_device *pdev) ": cannot register net device %d\n", rc); goto probe_err_register; } + setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev); out: return rc; diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c new file mode 100644 index 000000000000..39b0aea2aab3 --- /dev/null +++ b/drivers/net/ks8842.c @@ -0,0 +1,732 @@ +/* + * ks8842_main.c timberdale KS8842 ethernet driver + * Copyright (c) 2009 Intel 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * The Micrel KS8842 behind the timberdale FPGA + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "ks8842" + +/* Timberdale specific Registers */ +#define REG_TIMB_RST 0x1c + +/* KS8842 registers */ + +#define REG_SELECT_BANK 0x0e + +/* bank 0 registers */ +#define REG_QRFCR 0x04 + +/* bank 2 registers */ +#define REG_MARL 0x00 +#define REG_MARM 0x02 +#define REG_MARH 0x04 + +/* bank 3 registers */ +#define REG_GRR 0x06 + +/* bank 16 registers */ +#define REG_TXCR 0x00 +#define REG_TXSR 0x02 +#define REG_RXCR 0x04 +#define REG_TXMIR 0x08 +#define REG_RXMIR 0x0A + +/* bank 17 registers */ +#define REG_TXQCR 0x00 +#define REG_RXQCR 0x02 +#define REG_TXFDPR 0x04 +#define REG_RXFDPR 0x06 +#define REG_QMU_DATA_LO 0x08 +#define REG_QMU_DATA_HI 0x0A + +/* bank 18 registers */ +#define REG_IER 0x00 +#define IRQ_LINK_CHANGE 0x8000 +#define IRQ_TX 0x4000 +#define IRQ_RX 0x2000 +#define IRQ_RX_OVERRUN 0x0800 +#define IRQ_TX_STOPPED 0x0200 +#define IRQ_RX_STOPPED 0x0100 +#define IRQ_RX_ERROR 0x0080 +#define ENABLED_IRQS (IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \ + IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR) +#define REG_ISR 0x02 +#define REG_RXSR 0x04 +#define RXSR_VALID 0x8000 +#define RXSR_BROADCAST 0x80 +#define RXSR_MULTICAST 0x40 +#define RXSR_UNICAST 0x20 +#define RXSR_FRAMETYPE 0x08 +#define RXSR_TOO_LONG 0x04 +#define RXSR_RUNT 0x02 +#define RXSR_CRC_ERROR 0x01 +#define RXSR_ERROR (RXSR_TOO_LONG | RXSR_RUNT | RXSR_CRC_ERROR) + +/* bank 32 registers */ +#define REG_SW_ID_AND_ENABLE 0x00 +#define REG_SGCR1 0x02 +#define REG_SGCR2 0x04 +#define REG_SGCR3 0x06 + +/* bank 39 registers */ +#define REG_MACAR1 0x00 +#define REG_MACAR2 0x02 +#define REG_MACAR3 0x04 + +/* bank 45 registers */ +#define REG_P1MBCR 0x00 +#define REG_P1MBSR 0x02 + +/* bank 46 registers */ +#define REG_P2MBCR 0x00 +#define REG_P2MBSR 0x02 + +/* bank 48 registers */ +#define REG_P1CR2 0x02 + +/* bank 49 registers */ +#define REG_P1CR4 0x02 +#define REG_P1SR 0x04 + +struct ks8842_adapter { + void __iomem *hw_addr; + int irq; + struct tasklet_struct tasklet; + spinlock_t lock; /* spinlock to be interrupt safe */ + struct platform_device *pdev; +}; + +static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank) +{ + iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK); +} + +static inline void ks8842_write8(struct ks8842_adapter *adapter, u16 bank, + u8 value, int offset) +{ + ks8842_select_bank(adapter, bank); + iowrite8(value, adapter->hw_addr + offset); +} + +static inline void ks8842_write16(struct ks8842_adapter *adapter, u16 bank, + u16 value, int offset) +{ + ks8842_select_bank(adapter, bank); + iowrite16(value, adapter->hw_addr + offset); +} + +static inline void ks8842_enable_bits(struct ks8842_adapter *adapter, u16 bank, + u16 bits, int offset) +{ + u16 reg; + ks8842_select_bank(adapter, bank); + reg = ioread16(adapter->hw_addr + offset); + reg |= bits; + iowrite16(reg, adapter->hw_addr + offset); +} + +static inline void ks8842_clear_bits(struct ks8842_adapter *adapter, u16 bank, + u16 bits, int offset) +{ + u16 reg; + ks8842_select_bank(adapter, bank); + reg = ioread16(adapter->hw_addr + offset); + reg &= ~bits; + iowrite16(reg, adapter->hw_addr + offset); +} + +static inline void ks8842_write32(struct ks8842_adapter *adapter, u16 bank, + u32 value, int offset) +{ + ks8842_select_bank(adapter, bank); + iowrite32(value, adapter->hw_addr + offset); +} + +static inline u8 ks8842_read8(struct ks8842_adapter *adapter, u16 bank, + int offset) +{ + ks8842_select_bank(adapter, bank); + return ioread8(adapter->hw_addr + offset); +} + +static inline u16 ks8842_read16(struct ks8842_adapter *adapter, u16 bank, + int offset) +{ + ks8842_select_bank(adapter, bank); + return ioread16(adapter->hw_addr + offset); +} + +static inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank, + int offset) +{ + ks8842_select_bank(adapter, bank); + return ioread32(adapter->hw_addr + offset); +} + +static void ks8842_reset(struct ks8842_adapter *adapter) +{ + /* The KS8842 goes haywire when doing softare reset + * a work around in the timberdale IP is implemented to + * do a hardware reset instead + ks8842_write16(adapter, 3, 1, REG_GRR); + msleep(10); + iowrite16(0, adapter->hw_addr + REG_GRR); + */ + iowrite16(32, adapter->hw_addr + REG_SELECT_BANK); + iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST); + msleep(20); +} + +static void ks8842_update_link_status(struct net_device *netdev, + struct ks8842_adapter *adapter) +{ + /* check the status of the link */ + if (ks8842_read16(adapter, 45, REG_P1MBSR) & 0x4) { + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } else { + netif_stop_queue(netdev); + netif_carrier_off(netdev); + } +} + +static void ks8842_enable_tx(struct ks8842_adapter *adapter) +{ + ks8842_enable_bits(adapter, 16, 0x01, REG_TXCR); +} + +static void ks8842_disable_tx(struct ks8842_adapter *adapter) +{ + ks8842_clear_bits(adapter, 16, 0x01, REG_TXCR); +} + +static void ks8842_enable_rx(struct ks8842_adapter *adapter) +{ + ks8842_enable_bits(adapter, 16, 0x01, REG_RXCR); +} + +static void ks8842_disable_rx(struct ks8842_adapter *adapter) +{ + ks8842_clear_bits(adapter, 16, 0x01, REG_RXCR); +} + +static void ks8842_reset_hw(struct ks8842_adapter *adapter) +{ + /* reset the HW */ + ks8842_reset(adapter); + + /* Enable QMU Transmit flow control / transmit padding / Transmit CRC */ + ks8842_write16(adapter, 16, 0x000E, REG_TXCR); + + /* enable the receiver, uni + multi + broadcast + flow ctrl + + crc strip */ + ks8842_write16(adapter, 16, 0x8 | 0x20 | 0x40 | 0x80 | 0x400, + REG_RXCR); + + /* TX frame pointer autoincrement */ + ks8842_write16(adapter, 17, 0x4000, REG_TXFDPR); + + /* RX frame pointer autoincrement */ + ks8842_write16(adapter, 17, 0x4000, REG_RXFDPR); + + /* RX 2 kb high watermark */ + ks8842_write16(adapter, 0, 0x1000, REG_QRFCR); + + /* aggresive back off in half duplex */ + ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1); + + /* enable no excessive collison drop */ + ks8842_enable_bits(adapter, 32, 1 << 3, REG_SGCR2); + + /* Enable port 1 force flow control / back pressure / transmit / recv */ + ks8842_write16(adapter, 48, 0x1E07, REG_P1CR2); + + /* restart port auto-negotiation */ + ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4); + /* only advertise 10Mbps */ + ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4); + + /* Enable the transmitter */ + ks8842_enable_tx(adapter); + + /* Enable the receiver */ + ks8842_enable_rx(adapter); + + /* clear all interrupts */ + ks8842_write16(adapter, 18, 0xffff, REG_ISR); + + /* enable interrupts */ + ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); + + /* enable the switch */ + ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE); +} + +static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest) +{ + int i; + u16 mac; + + for (i = 0; i < ETH_ALEN; i++) + dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i); + + /* make sure the switch port uses the same MAC as the QMU */ + mac = ks8842_read16(adapter, 2, REG_MARL); + ks8842_write16(adapter, 39, mac, REG_MACAR1); + mac = ks8842_read16(adapter, 2, REG_MARM); + ks8842_write16(adapter, 39, mac, REG_MACAR2); + mac = ks8842_read16(adapter, 2, REG_MARH); + ks8842_write16(adapter, 39, mac, REG_MACAR3); +} + +static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter) +{ + return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff; +} + +static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + int len = skb->len; + u32 *ptr = (u32 *)skb->data; + u32 ctrl; + + dev_dbg(&adapter->pdev->dev, + "%s: len %u head %p data %p tail %p end %p\n", + __func__, skb->len, skb->head, skb->data, + skb_tail_pointer(skb), skb_end_pointer(skb)); + + /* check FIFO buffer space, we need space for CRC and command bits */ + if (ks8842_tx_fifo_space(adapter) < len + 8) + return NETDEV_TX_BUSY; + + /* the control word, enable IRQ, port 1 and the length */ + ctrl = 0x8000 | 0x100 | (len << 16); + ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO); + + netdev->stats.tx_bytes += len; + + /* copy buffer */ + while (len > 0) { + iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO); + len -= sizeof(u32); + ptr++; + } + + /* enqueue packet */ + ks8842_write16(adapter, 17, 1, REG_TXQCR); + + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} + +static void ks8842_rx_frame(struct net_device *netdev, + struct ks8842_adapter *adapter) +{ + u32 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO); + int len = (status >> 16) & 0x7ff; + + status &= 0xffff; + + dev_dbg(&adapter->pdev->dev, "%s - rx_data: status: %x\n", + __func__, status); + + /* check the status */ + if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { + struct sk_buff *skb = netdev_alloc_skb(netdev, len + 2); + + dev_dbg(&adapter->pdev->dev, "%s, got package, len: %d\n", + __func__, len); + if (skb) { + u32 *data; + + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += len; + if (status & RXSR_MULTICAST) + netdev->stats.multicast++; + + /* Align socket buffer in 4-byte boundary for + better performance. */ + skb_reserve(skb, 2); + data = (u32 *)skb_put(skb, len); + + ks8842_select_bank(adapter, 17); + while (len > 0) { + *data++ = ioread32(adapter->hw_addr + + REG_QMU_DATA_LO); + len -= sizeof(u32); + } + + skb->protocol = eth_type_trans(skb, netdev); + netif_rx(skb); + } else + netdev->stats.rx_dropped++; + } else { + dev_dbg(&adapter->pdev->dev, "RX error, status: %x\n", status); + netdev->stats.rx_errors++; + if (status & RXSR_TOO_LONG) + netdev->stats.rx_length_errors++; + if (status & RXSR_CRC_ERROR) + netdev->stats.rx_crc_errors++; + if (status & RXSR_RUNT) + netdev->stats.rx_frame_errors++; + } + + /* set high watermark to 3K */ + ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR); + + /* release the frame */ + ks8842_write16(adapter, 17, 0x01, REG_RXQCR); + + /* set high watermark to 2K */ + ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR); +} + +void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter) +{ + u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff; + dev_dbg(&adapter->pdev->dev, "%s Entry - rx_data: %d\n", + __func__, rx_data); + while (rx_data) { + ks8842_rx_frame(netdev, adapter); + rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff; + } +} + +void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter) +{ + u16 sr = ks8842_read16(adapter, 16, REG_TXSR); + dev_dbg(&adapter->pdev->dev, "%s - entry, sr: %x\n", __func__, sr); + netdev->stats.tx_packets++; + if (netif_queue_stopped(netdev)) + netif_wake_queue(netdev); +} + +void ks8842_handle_rx_overrun(struct net_device *netdev, + struct ks8842_adapter *adapter) +{ + dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__); + netdev->stats.rx_errors++; + netdev->stats.rx_fifo_errors++; +} + +void ks8842_tasklet(unsigned long arg) +{ + struct net_device *netdev = (struct net_device *)arg; + struct ks8842_adapter *adapter = netdev_priv(netdev); + u16 isr; + unsigned long flags; + u16 entry_bank; + + /* read current bank to be able to set it back */ + spin_lock_irqsave(&adapter->lock, flags); + entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK); + spin_unlock_irqrestore(&adapter->lock, flags); + + isr = ks8842_read16(adapter, 18, REG_ISR); + dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr); + + /* Ack */ + ks8842_write16(adapter, 18, isr, REG_ISR); + + if (!netif_running(netdev)) + return; + + if (isr & IRQ_LINK_CHANGE) + ks8842_update_link_status(netdev, adapter); + + if (isr & (IRQ_RX | IRQ_RX_ERROR)) + ks8842_handle_rx(netdev, adapter); + + if (isr & IRQ_TX) + ks8842_handle_tx(netdev, adapter); + + if (isr & IRQ_RX_OVERRUN) + ks8842_handle_rx_overrun(netdev, adapter); + + if (isr & IRQ_TX_STOPPED) { + ks8842_disable_tx(adapter); + ks8842_enable_tx(adapter); + } + + if (isr & IRQ_RX_STOPPED) { + ks8842_disable_rx(adapter); + ks8842_enable_rx(adapter); + } + + /* re-enable interrupts, put back the bank selection register */ + spin_lock_irqsave(&adapter->lock, flags); + ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); + iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); + spin_unlock_irqrestore(&adapter->lock, flags); +} + +static irqreturn_t ks8842_irq(int irq, void *devid) +{ + struct ks8842_adapter *adapter = devid; + u16 isr; + u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK); + irqreturn_t ret = IRQ_NONE; + + isr = ks8842_read16(adapter, 18, REG_ISR); + dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr); + + if (isr) { + /* disable IRQ */ + ks8842_write16(adapter, 18, 0x00, REG_IER); + + /* schedule tasklet */ + tasklet_schedule(&adapter->tasklet); + + ret = IRQ_HANDLED; + } + + iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); + + return ret; +} + + +/* Netdevice operations */ + +static int ks8842_open(struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + int err; + + dev_dbg(&adapter->pdev->dev, "%s - entry\n", __func__); + + /* reset the HW */ + ks8842_reset_hw(adapter); + + ks8842_update_link_status(netdev, adapter); + + err = request_irq(adapter->irq, ks8842_irq, IRQF_SHARED, DRV_NAME, + adapter); + if (err) { + printk(KERN_ERR "Failed to request IRQ: %d: %d\n", + adapter->irq, err); + return err; + } + + return 0; +} + +static int ks8842_close(struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + + dev_dbg(&adapter->pdev->dev, "%s - entry\n", __func__); + + /* free the irq */ + free_irq(adapter->irq, adapter); + + /* disable the switch */ + ks8842_write16(adapter, 32, 0x0, REG_SW_ID_AND_ENABLE); + + return 0; +} + +static int ks8842_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + int ret; + struct ks8842_adapter *adapter = netdev_priv(netdev); + + dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__); + + ret = ks8842_tx_frame(skb, netdev); + + if (ks8842_tx_fifo_space(adapter) < netdev->mtu + 8) + netif_stop_queue(netdev); + + return ret; +} + +static int ks8842_set_mac(struct net_device *netdev, void *p) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + struct sockaddr *addr = p; + char *mac = (u8 *)addr->sa_data; + int i; + + dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__); + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, mac, netdev->addr_len); + + spin_lock_irqsave(&adapter->lock, flags); + for (i = 0; i < ETH_ALEN; i++) { + ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i); + ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1], + REG_MACAR1 + i); + } + spin_unlock_irqrestore(&adapter->lock, flags); + return 0; +} + +static void ks8842_tx_timeout(struct net_device *netdev) +{ + struct ks8842_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + + dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__); + + spin_lock_irqsave(&adapter->lock, flags); + /* disable interrupts */ + ks8842_write16(adapter, 18, 0, REG_IER); + ks8842_write16(adapter, 18, 0xFFFF, REG_ISR); + spin_unlock_irqrestore(&adapter->lock, flags); + + ks8842_reset_hw(adapter); + + ks8842_update_link_status(netdev, adapter); +} + +static const struct net_device_ops ks8842_netdev_ops = { + .ndo_open = ks8842_open, + .ndo_stop = ks8842_close, + .ndo_start_xmit = ks8842_xmit_frame, + .ndo_set_mac_address = ks8842_set_mac, + .ndo_tx_timeout = ks8842_tx_timeout, + .ndo_validate_addr = eth_validate_addr +}; + +static struct ethtool_ops ks8842_ethtool_ops = { + .get_link = ethtool_op_get_link, +}; + +static int __devinit ks8842_probe(struct platform_device *pdev) +{ + int err = -ENOMEM; + struct resource *iomem; + struct net_device *netdev; + struct ks8842_adapter *adapter; + u16 id; + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME)) + goto err_mem_region; + + netdev = alloc_etherdev(sizeof(struct ks8842_adapter)); + if (!netdev) + goto err_alloc_etherdev; + + SET_NETDEV_DEV(netdev, &pdev->dev); + + adapter = netdev_priv(netdev); + adapter->hw_addr = ioremap(iomem->start, resource_size(iomem)); + if (!adapter->hw_addr) + goto err_ioremap; + + adapter->irq = platform_get_irq(pdev, 0); + if (adapter->irq < 0) { + err = adapter->irq; + goto err_get_irq; + } + + adapter->pdev = pdev; + + tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev); + spin_lock_init(&adapter->lock); + + netdev->netdev_ops = &ks8842_netdev_ops; + netdev->ethtool_ops = &ks8842_ethtool_ops; + + ks8842_read_mac_addr(adapter, netdev->dev_addr); + + id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE); + + strcpy(netdev->name, "eth%d"); + err = register_netdev(netdev); + if (err) + goto err_register; + + platform_set_drvdata(pdev, netdev); + + printk(KERN_INFO DRV_NAME + " Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n", + (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7); + + return 0; + +err_register: +err_get_irq: + iounmap(adapter->hw_addr); +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: + release_mem_region(iomem->start, resource_size(iomem)); +err_mem_region: + return err; +} + +static int __devexit ks8842_remove(struct platform_device *pdev) +{ + struct net_device *netdev = platform_get_drvdata(pdev); + struct ks8842_adapter *adapter = netdev_priv(netdev); + struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + unregister_netdev(netdev); + tasklet_kill(&adapter->tasklet); + iounmap(adapter->hw_addr); + free_netdev(netdev); + release_mem_region(iomem->start, resource_size(iomem)); + platform_set_drvdata(pdev, NULL); + return 0; +} + + +static struct platform_driver ks8842_platform_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ks8842_probe, + .remove = ks8842_remove, +}; + +static int __init ks8842_init(void) +{ + return platform_driver_register(&ks8842_platform_driver); +} + +static void __exit ks8842_exit(void) +{ + platform_driver_unregister(&ks8842_platform_driver); +} + +module_init(ks8842_init); +module_exit(ks8842_exit); + +MODULE_DESCRIPTION("Timberdale KS8842 ethernet driver"); +MODULE_AUTHOR("Mocean Laboratories "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:ks8842"); + diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index efbae4b8398e..a0c578585a50 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -161,12 +161,12 @@ lan_init_chip(struct parisc_device *dev) if (!dev->irq) { printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n", - __FILE__, dev->hpa.start); + __FILE__, (unsigned long)dev->hpa.start); return -ENODEV; } - printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start, - dev->irq); + printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", + (unsigned long)dev->hpa.start, dev->irq); netdevice = alloc_etherdev(sizeof(struct i596_private)); if (!netdevice) diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 7415f517491d..070fa4500871 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1036,6 +1036,19 @@ static void print_eth(unsigned char *add, char *str) printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n", add, add + 6, add, add[12], add[13], str); } +static const struct net_device_ops i596_netdev_ops = { + .ndo_open = i596_open, + .ndo_stop = i596_close, + .ndo_start_xmit = i596_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = i596_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = i596_poll_controller, +#endif +}; static int __devinit i82596_probe(struct net_device *dev) { @@ -1062,16 +1075,8 @@ static int __devinit i82596_probe(struct net_device *dev) return -ENOMEM; } - /* The 82596-specific entries in the device structure. */ - dev->open = i596_open; - dev->stop = i596_close; - dev->hard_start_xmit = i596_start_xmit; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = i596_tx_timeout; + dev->netdev_ops = &i596_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = i596_poll_controller; -#endif memset(dma, 0, sizeof(struct i596_dma)); lp->dma = dma; diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 789b6cb744b2..f28c23343009 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -370,7 +370,7 @@ static int __ei_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock(&ei_local->page_lock); enable_irq_lockdep_irqrestore(dev->irq, &flags); dev->stats.tx_errors++; - return 1; + return NETDEV_TX_BUSY; } /* diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h new file mode 100644 index 000000000000..1af66a1e6911 --- /dev/null +++ b/drivers/net/ll_temac.h @@ -0,0 +1,374 @@ + +#ifndef XILINX_LL_TEMAC_H +#define XILINX_LL_TEMAC_H + +#include +#include +#include +#include +#include + +/* packet size info */ +#define XTE_HDR_SIZE 14 /* size of Ethernet header */ +#define XTE_TRL_SIZE 4 /* size of Ethernet trailer (FCS) */ +#define XTE_JUMBO_MTU 9000 +#define XTE_MAX_JUMBO_FRAME_SIZE (XTE_JUMBO_MTU + XTE_HDR_SIZE + XTE_TRL_SIZE) + +/* Configuration options */ + +/* Accept all incoming packets. + * This option defaults to disabled (cleared) */ +#define XTE_OPTION_PROMISC (1 << 0) +/* Jumbo frame support for Tx & Rx. + * This option defaults to disabled (cleared) */ +#define XTE_OPTION_JUMBO (1 << 1) +/* VLAN Rx & Tx frame support. + * This option defaults to disabled (cleared) */ +#define XTE_OPTION_VLAN (1 << 2) +/* Enable recognition of flow control frames on Rx + * This option defaults to enabled (set) */ +#define XTE_OPTION_FLOW_CONTROL (1 << 4) +/* Strip FCS and PAD from incoming frames. + * Note: PAD from VLAN frames is not stripped. + * This option defaults to disabled (set) */ +#define XTE_OPTION_FCS_STRIP (1 << 5) +/* Generate FCS field and add PAD automatically for outgoing frames. + * This option defaults to enabled (set) */ +#define XTE_OPTION_FCS_INSERT (1 << 6) +/* Enable Length/Type error checking for incoming frames. When this option is +set, the MAC will filter frames that have a mismatched type/length field +and if XTE_OPTION_REPORT_RXERR is set, the user is notified when these +types of frames are encountered. When this option is cleared, the MAC will +allow these types of frames to be received. +This option defaults to enabled (set) */ +#define XTE_OPTION_LENTYPE_ERR (1 << 7) +/* Enable the transmitter. + * This option defaults to enabled (set) */ +#define XTE_OPTION_TXEN (1 << 11) +/* Enable the receiver +* This option defaults to enabled (set) */ +#define XTE_OPTION_RXEN (1 << 12) + +/* Default options set when device is initialized or reset */ +#define XTE_OPTION_DEFAULTS \ + (XTE_OPTION_TXEN | \ + XTE_OPTION_FLOW_CONTROL | \ + XTE_OPTION_RXEN) + +/* XPS_LL_TEMAC SDMA registers definition */ + +#define TX_NXTDESC_PTR 0x00 /* r */ +#define TX_CURBUF_ADDR 0x01 /* r */ +#define TX_CURBUF_LENGTH 0x02 /* r */ +#define TX_CURDESC_PTR 0x03 /* rw */ +#define TX_TAILDESC_PTR 0x04 /* rw */ +#define TX_CHNL_CTRL 0x05 /* rw */ +/* + 0:7 24:31 IRQTimeout + 8:15 16:23 IRQCount + 16:20 11:15 Reserved + 21 10 0 + 22 9 UseIntOnEnd + 23 8 LdIRQCnt + 24 7 IRQEn + 25:28 3:6 Reserved + 29 2 IrqErrEn + 30 1 IrqDlyEn + 31 0 IrqCoalEn +*/ +#define CHNL_CTRL_IRQ_IOE (1 << 9) +#define CHNL_CTRL_IRQ_EN (1 << 7) +#define CHNL_CTRL_IRQ_ERR_EN (1 << 2) +#define CHNL_CTRL_IRQ_DLY_EN (1 << 1) +#define CHNL_CTRL_IRQ_COAL_EN (1 << 0) +#define TX_IRQ_REG 0x06 /* rw */ +/* + 0:7 24:31 DltTmrValue + 8:15 16:23 ClscCntrValue + 16:17 14:15 Reserved + 18:21 10:13 ClscCnt + 22:23 8:9 DlyCnt + 24:28 3::7 Reserved + 29 2 ErrIrq + 30 1 DlyIrq + 31 0 CoalIrq + */ +#define TX_CHNL_STS 0x07 /* r */ +/* + 0:9 22:31 Reserved + 10 21 TailPErr + 11 20 CmpErr + 12 19 AddrErr + 13 18 NxtPErr + 14 17 CurPErr + 15 16 BsyWr + 16:23 8:15 Reserved + 24 7 Error + 25 6 IOE + 26 5 SOE + 27 4 Cmplt + 28 3 SOP + 29 2 EOP + 30 1 EngBusy + 31 0 Reserved +*/ + +#define RX_NXTDESC_PTR 0x08 /* r */ +#define RX_CURBUF_ADDR 0x09 /* r */ +#define RX_CURBUF_LENGTH 0x0a /* r */ +#define RX_CURDESC_PTR 0x0b /* rw */ +#define RX_TAILDESC_PTR 0x0c /* rw */ +#define RX_CHNL_CTRL 0x0d /* rw */ +/* + 0:7 24:31 IRQTimeout + 8:15 16:23 IRQCount + 16:20 11:15 Reserved + 21 10 0 + 22 9 UseIntOnEnd + 23 8 LdIRQCnt + 24 7 IRQEn + 25:28 3:6 Reserved + 29 2 IrqErrEn + 30 1 IrqDlyEn + 31 0 IrqCoalEn + */ +#define RX_IRQ_REG 0x0e /* rw */ +#define IRQ_COAL (1 << 0) +#define IRQ_DLY (1 << 1) +#define IRQ_ERR (1 << 2) +#define IRQ_DMAERR (1 << 7) /* this is not documented ??? */ +/* + 0:7 24:31 DltTmrValue + 8:15 16:23 ClscCntrValue + 16:17 14:15 Reserved + 18:21 10:13 ClscCnt + 22:23 8:9 DlyCnt + 24:28 3::7 Reserved +*/ +#define RX_CHNL_STS 0x0f /* r */ +#define CHNL_STS_ENGBUSY (1 << 1) +#define CHNL_STS_EOP (1 << 2) +#define CHNL_STS_SOP (1 << 3) +#define CHNL_STS_CMPLT (1 << 4) +#define CHNL_STS_SOE (1 << 5) +#define CHNL_STS_IOE (1 << 6) +#define CHNL_STS_ERR (1 << 7) + +#define CHNL_STS_BSYWR (1 << 16) +#define CHNL_STS_CURPERR (1 << 17) +#define CHNL_STS_NXTPERR (1 << 18) +#define CHNL_STS_ADDRERR (1 << 19) +#define CHNL_STS_CMPERR (1 << 20) +#define CHNL_STS_TAILERR (1 << 21) +/* + 0:9 22:31 Reserved + 10 21 TailPErr + 11 20 CmpErr + 12 19 AddrErr + 13 18 NxtPErr + 14 17 CurPErr + 15 16 BsyWr + 16:23 8:15 Reserved + 24 7 Error + 25 6 IOE + 26 5 SOE + 27 4 Cmplt + 28 3 SOP + 29 2 EOP + 30 1 EngBusy + 31 0 Reserved +*/ + +#define DMA_CONTROL_REG 0x10 /* rw */ +#define DMA_CONTROL_RST (1 << 0) +#define DMA_TAIL_ENABLE (1 << 2) + +/* XPS_LL_TEMAC direct registers definition */ + +#define XTE_RAF0_OFFSET 0x00 +#define RAF0_RST (1 << 0) +#define RAF0_MCSTREJ (1 << 1) +#define RAF0_BCSTREJ (1 << 2) +#define XTE_TPF0_OFFSET 0x04 +#define XTE_IFGP0_OFFSET 0x08 +#define XTE_ISR0_OFFSET 0x0c +#define ISR0_HARDACSCMPLT (1 << 0) +#define ISR0_AUTONEG (1 << 1) +#define ISR0_RXCMPLT (1 << 2) +#define ISR0_RXREJ (1 << 3) +#define ISR0_RXFIFOOVR (1 << 4) +#define ISR0_TXCMPLT (1 << 5) +#define ISR0_RXDCMLCK (1 << 6) + +#define XTE_IPR0_OFFSET 0x10 +#define XTE_IER0_OFFSET 0x14 + +#define XTE_MSW0_OFFSET 0x20 +#define XTE_LSW0_OFFSET 0x24 +#define XTE_CTL0_OFFSET 0x28 +#define XTE_RDY0_OFFSET 0x2c + +#define XTE_RSE_MIIM_RR_MASK 0x0002 +#define XTE_RSE_MIIM_WR_MASK 0x0004 +#define XTE_RSE_CFG_RR_MASK 0x0020 +#define XTE_RSE_CFG_WR_MASK 0x0040 +#define XTE_RDY0_HARD_ACS_RDY_MASK (0x10000) + +/* XPS_LL_TEMAC indirect registers offset definition */ + +#define XTE_RXC0_OFFSET 0x00000200 /* Rx configuration word 0 */ +#define XTE_RXC1_OFFSET 0x00000240 /* Rx configuration word 1 */ +#define XTE_RXC1_RXRST_MASK (1 << 31) /* Receiver reset */ +#define XTE_RXC1_RXJMBO_MASK (1 << 30) /* Jumbo frame enable */ +#define XTE_RXC1_RXFCS_MASK (1 << 29) /* FCS not stripped */ +#define XTE_RXC1_RXEN_MASK (1 << 28) /* Receiver enable */ +#define XTE_RXC1_RXVLAN_MASK (1 << 27) /* VLAN enable */ +#define XTE_RXC1_RXHD_MASK (1 << 26) /* Half duplex */ +#define XTE_RXC1_RXLT_MASK (1 << 25) /* Length/type check disable */ + +#define XTE_TXC_OFFSET 0x00000280 /* Tx configuration */ +#define XTE_TXC_TXRST_MASK (1 << 31) /* Transmitter reset */ +#define XTE_TXC_TXJMBO_MASK (1 << 30) /* Jumbo frame enable */ +#define XTE_TXC_TXFCS_MASK (1 << 29) /* Generate FCS */ +#define XTE_TXC_TXEN_MASK (1 << 28) /* Transmitter enable */ +#define XTE_TXC_TXVLAN_MASK (1 << 27) /* VLAN enable */ +#define XTE_TXC_TXHD_MASK (1 << 26) /* Half duplex */ + +#define XTE_FCC_OFFSET 0x000002C0 /* Flow control config */ +#define XTE_FCC_RXFLO_MASK (1 << 29) /* Rx flow control enable */ +#define XTE_FCC_TXFLO_MASK (1 << 30) /* Tx flow control enable */ + +#define XTE_EMCFG_OFFSET 0x00000300 /* EMAC configuration */ +#define XTE_EMCFG_LINKSPD_MASK 0xC0000000 /* Link speed */ +#define XTE_EMCFG_HOSTEN_MASK (1 << 26) /* Host interface enable */ +#define XTE_EMCFG_LINKSPD_10 0x00000000 /* 10 Mbit LINKSPD_MASK */ +#define XTE_EMCFG_LINKSPD_100 (1 << 30) /* 100 Mbit LINKSPD_MASK */ +#define XTE_EMCFG_LINKSPD_1000 (1 << 31) /* 1000 Mbit LINKSPD_MASK */ + +#define XTE_GMIC_OFFSET 0x00000320 /* RGMII/SGMII config */ +#define XTE_MC_OFFSET 0x00000340 /* MDIO configuration */ +#define XTE_UAW0_OFFSET 0x00000380 /* Unicast address word 0 */ +#define XTE_UAW1_OFFSET 0x00000384 /* Unicast address word 1 */ + +#define XTE_MAW0_OFFSET 0x00000388 /* Multicast addr word 0 */ +#define XTE_MAW1_OFFSET 0x0000038C /* Multicast addr word 1 */ +#define XTE_AFM_OFFSET 0x00000390 /* Promiscuous mode */ +#define XTE_AFM_EPPRM_MASK (1 << 31) /* Promiscuous mode enable */ + +/* Interrupt Request status */ +#define XTE_TIS_OFFSET 0x000003A0 +#define TIS_FRIS (1 << 0) +#define TIS_MRIS (1 << 1) +#define TIS_MWIS (1 << 2) +#define TIS_ARIS (1 << 3) +#define TIS_AWIS (1 << 4) +#define TIS_CRIS (1 << 5) +#define TIS_CWIS (1 << 6) + +#define XTE_TIE_OFFSET 0x000003A4 /* Interrupt enable */ + +/** MII Mamagement Control register (MGTCR) */ +#define XTE_MGTDR_OFFSET 0x000003B0 /* MII data */ +#define XTE_MIIMAI_OFFSET 0x000003B4 /* MII control */ + +#define CNTLREG_WRITE_ENABLE_MASK 0x8000 +#define CNTLREG_EMAC1SEL_MASK 0x0400 +#define CNTLREG_ADDRESSCODE_MASK 0x03ff + +/* CDMAC descriptor status bit definitions */ + +#define STS_CTRL_APP0_ERR (1 << 31) +#define STS_CTRL_APP0_IRQONEND (1 << 30) +/* undoccumented */ +#define STS_CTRL_APP0_STOPONEND (1 << 29) +#define STS_CTRL_APP0_CMPLT (1 << 28) +#define STS_CTRL_APP0_SOP (1 << 27) +#define STS_CTRL_APP0_EOP (1 << 26) +#define STS_CTRL_APP0_ENGBUSY (1 << 25) +/* undocumented */ +#define STS_CTRL_APP0_ENGRST (1 << 24) + +#define TX_CONTROL_CALC_CSUM_MASK 1 + +#define XTE_ALIGN 32 +#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN) + +#define MULTICAST_CAM_TABLE_NUM 4 + +/* TX/RX CURDESC_PTR points to first descriptor */ +/* TX/RX TAILDESC_PTR points to last descriptor in linked list */ + +/** + * struct cdmac_bd - LocalLink buffer descriptor format + * + * app0 bits: + * 0 Error + * 1 IrqOnEnd generate an interrupt at completion of DMA op + * 2 reserved + * 3 completed Current descriptor completed + * 4 SOP TX - marks first desc/ RX marks first desct + * 5 EOP TX marks last desc/RX marks last desc + * 6 EngBusy DMA is processing + * 7 reserved + * 8:31 application specific + */ +struct cdmac_bd { + u32 next; /* Physical address of next buffer descriptor */ + u32 phys; + u32 len; + u32 app0; + u32 app1; /* TX start << 16 | insert */ + u32 app2; /* TX csum */ + u32 app3; + u32 app4; /* skb for TX length for RX */ +}; + +struct temac_local { + struct net_device *ndev; + struct device *dev; + + /* Connection to PHY device */ + struct phy_device *phy_dev; /* Pointer to PHY device */ + struct device_node *phy_node; + + /* MDIO bus data */ + struct mii_bus *mii_bus; /* MII bus reference */ + int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ + + /* IO registers and IRQs */ + void __iomem *regs; + dcr_host_t sdma_dcrs; + int tx_irq; + int rx_irq; + int emac_num; + + struct sk_buff **rx_skb; + spinlock_t rx_lock; + struct mutex indirect_mutex; + u32 options; /* Current options word */ + int last_link; + + /* Buffer descriptors */ + struct cdmac_bd *tx_bd_v; + dma_addr_t tx_bd_p; + struct cdmac_bd *rx_bd_v; + dma_addr_t rx_bd_p; + int tx_bd_ci; + int tx_bd_next; + int tx_bd_tail; + int rx_bd_ci; +}; + +/* xilinx_temac.c */ +u32 temac_ior(struct temac_local *lp, int offset); +void temac_iow(struct temac_local *lp, int offset, u32 value); +int temac_indirect_busywait(struct temac_local *lp); +u32 temac_indirect_in32(struct temac_local *lp, int reg); +void temac_indirect_out32(struct temac_local *lp, int reg, u32 value); + + +/* xilinx_temac_mdio.c */ +int temac_mdio_setup(struct temac_local *lp, struct device_node *np); +void temac_mdio_teardown(struct temac_local *lp); + +#endif /* XILINX_LL_TEMAC_H */ diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c new file mode 100644 index 000000000000..96e7248876c1 --- /dev/null +++ b/drivers/net/ll_temac_main.c @@ -0,0 +1,969 @@ +/* + * Driver for Xilinx TEMAC Ethernet device + * + * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi + * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. + * Copyright (c) 2008-2009 Secret Lab Technologies Ltd. + * + * This is a driver for the Xilinx ll_temac ipcore which is often used + * in the Virtex and Spartan series of chips. + * + * Notes: + * - The ll_temac hardware uses indirect access for many of the TEMAC + * registers, include the MDIO bus. However, indirect access to MDIO + * registers take considerably more clock cycles than to TEMAC registers. + * MDIO accesses are long, so threads doing them should probably sleep + * rather than busywait. However, since only one indirect access can be + * in progress at any given time, that means that *all* indirect accesses + * could end up sleeping (to wait for an MDIO access to complete). + * Fortunately none of the indirect accesses are on the 'hot' path for tx + * or rx, so this should be okay. + * + * TODO: + * - Fix driver to work on more than just Virtex5. Right now the driver + * assumes that the locallink DMA registers are accessed via DCR + * instructions. + * - Factor out locallink DMA code into separate driver + * - Fix multicast assignment. + * - Fix support for hardware checksumming. + * - Testing. Lots and lots of testing. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* needed for sizeof(tcphdr) */ +#include /* needed for sizeof(udphdr) */ +#include +#include +#include +#include + +#include "ll_temac.h" + +#define TX_BD_NUM 64 +#define RX_BD_NUM 128 + +/* --------------------------------------------------------------------- + * Low level register access functions + */ + +u32 temac_ior(struct temac_local *lp, int offset) +{ + return in_be32((u32 *)(lp->regs + offset)); +} + +void temac_iow(struct temac_local *lp, int offset, u32 value) +{ + out_be32((u32 *) (lp->regs + offset), value); +} + +int temac_indirect_busywait(struct temac_local *lp) +{ + long end = jiffies + 2; + + while (!(temac_ior(lp, XTE_RDY0_OFFSET) & XTE_RDY0_HARD_ACS_RDY_MASK)) { + if (end - jiffies <= 0) { + WARN_ON(1); + return -ETIMEDOUT; + } + msleep(1); + } + return 0; +} + +/** + * temac_indirect_in32 + * + * lp->indirect_mutex must be held when calling this function + */ +u32 temac_indirect_in32(struct temac_local *lp, int reg) +{ + u32 val; + + if (temac_indirect_busywait(lp)) + return -ETIMEDOUT; + temac_iow(lp, XTE_CTL0_OFFSET, reg); + if (temac_indirect_busywait(lp)) + return -ETIMEDOUT; + val = temac_ior(lp, XTE_LSW0_OFFSET); + + return val; +} + +/** + * temac_indirect_out32 + * + * lp->indirect_mutex must be held when calling this function + */ +void temac_indirect_out32(struct temac_local *lp, int reg, u32 value) +{ + if (temac_indirect_busywait(lp)) + return; + temac_iow(lp, XTE_LSW0_OFFSET, value); + temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg); +} + +static u32 temac_dma_in32(struct temac_local *lp, int reg) +{ + return dcr_read(lp->sdma_dcrs, reg); +} + +static void temac_dma_out32(struct temac_local *lp, int reg, u32 value) +{ + dcr_write(lp->sdma_dcrs, reg, value); +} + +/** + * temac_dma_bd_init - Setup buffer descriptor rings + */ +static int temac_dma_bd_init(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct sk_buff *skb; + int i; + + lp->rx_skb = kzalloc(sizeof(struct sk_buff)*RX_BD_NUM, GFP_KERNEL); + /* allocate the tx and rx ring buffer descriptors. */ + /* returns a virtual addres and a physical address. */ + lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * TX_BD_NUM, + &lp->tx_bd_p, GFP_KERNEL); + lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * RX_BD_NUM, + &lp->rx_bd_p, GFP_KERNEL); + + memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM); + for (i = 0; i < TX_BD_NUM; i++) { + lp->tx_bd_v[i].next = lp->tx_bd_p + + sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM); + } + + memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM); + for (i = 0; i < RX_BD_NUM; i++) { + lp->rx_bd_v[i].next = lp->rx_bd_p + + sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM); + + skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + + XTE_ALIGN, GFP_ATOMIC); + if (skb == 0) { + dev_err(&ndev->dev, "alloc_skb error %d\n", i); + return -1; + } + lp->rx_skb[i] = skb; + skb_reserve(skb, BUFFER_ALIGN(skb->data)); + /* returns physical address of skb->data */ + lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, + skb->data, + XTE_MAX_JUMBO_FRAME_SIZE, + DMA_FROM_DEVICE); + lp->rx_bd_v[i].len = XTE_MAX_JUMBO_FRAME_SIZE; + lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND; + } + + temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 | + CHNL_CTRL_IRQ_EN | + CHNL_CTRL_IRQ_DLY_EN | + CHNL_CTRL_IRQ_COAL_EN); + /* 0x10220483 */ + /* 0x00100483 */ + temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 | + CHNL_CTRL_IRQ_EN | + CHNL_CTRL_IRQ_DLY_EN | + CHNL_CTRL_IRQ_COAL_EN | + CHNL_CTRL_IRQ_IOE); + /* 0xff010283 */ + + temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p); + temac_dma_out32(lp, RX_TAILDESC_PTR, + lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); + temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p); + + return 0; +} + +/* --------------------------------------------------------------------- + * net_device_ops + */ + +static int temac_set_mac_address(struct net_device *ndev, void *address) +{ + struct temac_local *lp = netdev_priv(ndev); + + if (address) + memcpy(ndev->dev_addr, address, ETH_ALEN); + + if (!is_valid_ether_addr(ndev->dev_addr)) + random_ether_addr(ndev->dev_addr); + + /* set up unicast MAC address filter set its mac address */ + mutex_lock(&lp->indirect_mutex); + temac_indirect_out32(lp, XTE_UAW0_OFFSET, + (ndev->dev_addr[0]) | + (ndev->dev_addr[1] << 8) | + (ndev->dev_addr[2] << 16) | + (ndev->dev_addr[3] << 24)); + /* There are reserved bits in EUAW1 + * so don't affect them Set MAC bits [47:32] in EUAW1 */ + temac_indirect_out32(lp, XTE_UAW1_OFFSET, + (ndev->dev_addr[4] & 0x000000ff) | + (ndev->dev_addr[5] << 8)); + mutex_unlock(&lp->indirect_mutex); + + return 0; +} + +static void temac_set_multicast_list(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + u32 multi_addr_msw, multi_addr_lsw, val; + int i; + + mutex_lock(&lp->indirect_mutex); + if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) + || ndev->mc_count > MULTICAST_CAM_TABLE_NUM) { + /* + * We must make the kernel realise we had to move + * into promisc mode or we start all out war on + * the cable. If it was a promisc request the + * flag is already set. If not we assert it. + */ + ndev->flags |= IFF_PROMISC; + temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); + dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); + } else if (ndev->mc_count) { + struct dev_mc_list *mclist = ndev->mc_list; + for (i = 0; mclist && i < ndev->mc_count; i++) { + + if (i >= MULTICAST_CAM_TABLE_NUM) + break; + multi_addr_msw = ((mclist->dmi_addr[3] << 24) | + (mclist->dmi_addr[2] << 16) | + (mclist->dmi_addr[1] << 8) | + (mclist->dmi_addr[0])); + temac_indirect_out32(lp, XTE_MAW0_OFFSET, + multi_addr_msw); + multi_addr_lsw = ((mclist->dmi_addr[5] << 8) | + (mclist->dmi_addr[4]) | (i << 16)); + temac_indirect_out32(lp, XTE_MAW1_OFFSET, + multi_addr_lsw); + mclist = mclist->next; + } + } else { + val = temac_indirect_in32(lp, XTE_AFM_OFFSET); + temac_indirect_out32(lp, XTE_AFM_OFFSET, + val & ~XTE_AFM_EPPRM_MASK); + temac_indirect_out32(lp, XTE_MAW0_OFFSET, 0); + temac_indirect_out32(lp, XTE_MAW1_OFFSET, 0); + dev_info(&ndev->dev, "Promiscuous mode disabled.\n"); + } + mutex_unlock(&lp->indirect_mutex); +} + +struct temac_option { + int flg; + u32 opt; + u32 reg; + u32 m_or; + u32 m_and; +} temac_options[] = { + /* Turn on jumbo packet support for both Rx and Tx */ + { + .opt = XTE_OPTION_JUMBO, + .reg = XTE_TXC_OFFSET, + .m_or = XTE_TXC_TXJMBO_MASK, + }, + { + .opt = XTE_OPTION_JUMBO, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXJMBO_MASK, + }, + /* Turn on VLAN packet support for both Rx and Tx */ + { + .opt = XTE_OPTION_VLAN, + .reg = XTE_TXC_OFFSET, + .m_or =XTE_TXC_TXVLAN_MASK, + }, + { + .opt = XTE_OPTION_VLAN, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXVLAN_MASK, + }, + /* Turn on FCS stripping on receive packets */ + { + .opt = XTE_OPTION_FCS_STRIP, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXFCS_MASK, + }, + /* Turn on FCS insertion on transmit packets */ + { + .opt = XTE_OPTION_FCS_INSERT, + .reg = XTE_TXC_OFFSET, + .m_or =XTE_TXC_TXFCS_MASK, + }, + /* Turn on length/type field checking on receive packets */ + { + .opt = XTE_OPTION_LENTYPE_ERR, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXLT_MASK, + }, + /* Turn on flow control */ + { + .opt = XTE_OPTION_FLOW_CONTROL, + .reg = XTE_FCC_OFFSET, + .m_or =XTE_FCC_RXFLO_MASK, + }, + /* Turn on flow control */ + { + .opt = XTE_OPTION_FLOW_CONTROL, + .reg = XTE_FCC_OFFSET, + .m_or =XTE_FCC_TXFLO_MASK, + }, + /* Turn on promiscuous frame filtering (all frames are received ) */ + { + .opt = XTE_OPTION_PROMISC, + .reg = XTE_AFM_OFFSET, + .m_or =XTE_AFM_EPPRM_MASK, + }, + /* Enable transmitter if not already enabled */ + { + .opt = XTE_OPTION_TXEN, + .reg = XTE_TXC_OFFSET, + .m_or =XTE_TXC_TXEN_MASK, + }, + /* Enable receiver? */ + { + .opt = XTE_OPTION_RXEN, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXEN_MASK, + }, + {} +}; + +/** + * temac_setoptions + */ +static u32 temac_setoptions(struct net_device *ndev, u32 options) +{ + struct temac_local *lp = netdev_priv(ndev); + struct temac_option *tp = &temac_options[0]; + int reg; + + mutex_lock(&lp->indirect_mutex); + while (tp->opt) { + reg = temac_indirect_in32(lp, tp->reg) & ~tp->m_or; + if (options & tp->opt) + reg |= tp->m_or; + temac_indirect_out32(lp, tp->reg, reg); + tp++; + } + lp->options |= options; + mutex_unlock(&lp->indirect_mutex); + + return (0); +} + +/* Initilize temac */ +static void temac_device_reset(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + u32 timeout; + u32 val; + + /* Perform a software reset */ + + /* 0x300 host enable bit ? */ + /* reset PHY through control register ?:1 */ + + dev_dbg(&ndev->dev, "%s()\n", __func__); + + mutex_lock(&lp->indirect_mutex); + /* Reset the receiver and wait for it to finish reset */ + temac_indirect_out32(lp, XTE_RXC1_OFFSET, XTE_RXC1_RXRST_MASK); + timeout = 1000; + while (temac_indirect_in32(lp, XTE_RXC1_OFFSET) & XTE_RXC1_RXRST_MASK) { + udelay(1); + if (--timeout == 0) { + dev_err(&ndev->dev, + "temac_device_reset RX reset timeout!!\n"); + break; + } + } + + /* Reset the transmitter and wait for it to finish reset */ + temac_indirect_out32(lp, XTE_TXC_OFFSET, XTE_TXC_TXRST_MASK); + timeout = 1000; + while (temac_indirect_in32(lp, XTE_TXC_OFFSET) & XTE_TXC_TXRST_MASK) { + udelay(1); + if (--timeout == 0) { + dev_err(&ndev->dev, + "temac_device_reset TX reset timeout!!\n"); + break; + } + } + + /* Disable the receiver */ + val = temac_indirect_in32(lp, XTE_RXC1_OFFSET); + temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK); + + /* Reset Local Link (DMA) */ + temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST); + timeout = 1000; + while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) { + udelay(1); + if (--timeout == 0) { + dev_err(&ndev->dev, + "temac_device_reset DMA reset timeout!!\n"); + break; + } + } + temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); + + temac_dma_bd_init(ndev); + + temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0); + temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0); + temac_indirect_out32(lp, XTE_TXC_OFFSET, 0); + temac_indirect_out32(lp, XTE_FCC_OFFSET, XTE_FCC_RXFLO_MASK); + + mutex_unlock(&lp->indirect_mutex); + + /* Sync default options with HW + * but leave receiver and transmitter disabled. */ + temac_setoptions(ndev, + lp->options & ~(XTE_OPTION_TXEN | XTE_OPTION_RXEN)); + + temac_set_mac_address(ndev, NULL); + + /* Set address filter table */ + temac_set_multicast_list(ndev); + if (temac_setoptions(ndev, lp->options)) + dev_err(&ndev->dev, "Error setting TEMAC options\n"); + + /* Init Driver variable */ + ndev->trans_start = 0; +} + +void temac_adjust_link(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct phy_device *phy = lp->phy_dev; + u32 mii_speed; + int link_state; + + /* hash together the state values to decide if something has changed */ + link_state = phy->speed | (phy->duplex << 1) | phy->link; + + mutex_lock(&lp->indirect_mutex); + if (lp->last_link != link_state) { + mii_speed = temac_indirect_in32(lp, XTE_EMCFG_OFFSET); + mii_speed &= ~XTE_EMCFG_LINKSPD_MASK; + + switch (phy->speed) { + case SPEED_1000: mii_speed |= XTE_EMCFG_LINKSPD_1000; break; + case SPEED_100: mii_speed |= XTE_EMCFG_LINKSPD_100; break; + case SPEED_10: mii_speed |= XTE_EMCFG_LINKSPD_10; break; + } + + /* Write new speed setting out to TEMAC */ + temac_indirect_out32(lp, XTE_EMCFG_OFFSET, mii_speed); + lp->last_link = link_state; + phy_print_status(phy); + } + mutex_unlock(&lp->indirect_mutex); +} + +static void temac_start_xmit_done(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct cdmac_bd *cur_p; + unsigned int stat = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; + stat = cur_p->app0; + + while (stat & STS_CTRL_APP0_CMPLT) { + dma_unmap_single(ndev->dev.parent, cur_p->phys, cur_p->len, + DMA_TO_DEVICE); + if (cur_p->app4) + dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); + cur_p->app0 = 0; + + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += cur_p->len; + + lp->tx_bd_ci++; + if (lp->tx_bd_ci >= TX_BD_NUM) + lp->tx_bd_ci = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; + stat = cur_p->app0; + } + + netif_wake_queue(ndev); +} + +static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct cdmac_bd *cur_p; + dma_addr_t start_p, tail_p; + int ii; + unsigned long num_frag; + skb_frag_t *frag; + + num_frag = skb_shinfo(skb)->nr_frags; + frag = &skb_shinfo(skb)->frags[0]; + start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + + if (cur_p->app0 & STS_CTRL_APP0_CMPLT) { + if (!netif_queue_stopped(ndev)) { + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; + } + return NETDEV_TX_BUSY; + } + + cur_p->app0 = 0; + if (skb->ip_summed == CHECKSUM_PARTIAL) { + const struct iphdr *ip = ip_hdr(skb); + int length = 0, start = 0, insert = 0; + + switch (ip->protocol) { + case IPPROTO_TCP: + start = sizeof(struct iphdr) + ETH_HLEN; + insert = sizeof(struct iphdr) + ETH_HLEN + 16; + length = ip->tot_len - sizeof(struct iphdr); + break; + case IPPROTO_UDP: + start = sizeof(struct iphdr) + ETH_HLEN; + insert = sizeof(struct iphdr) + ETH_HLEN + 6; + length = ip->tot_len - sizeof(struct iphdr); + break; + default: + break; + } + cur_p->app1 = ((start << 16) | insert); + cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr, + length, ip->protocol, 0); + skb->data[insert] = 0; + skb->data[insert + 1] = 0; + } + cur_p->app0 |= STS_CTRL_APP0_SOP; + cur_p->len = skb_headlen(skb); + cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len, + DMA_TO_DEVICE); + cur_p->app4 = (unsigned long)skb; + + for (ii = 0; ii < num_frag; ii++) { + lp->tx_bd_tail++; + if (lp->tx_bd_tail >= TX_BD_NUM) + lp->tx_bd_tail = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + cur_p->phys = dma_map_single(ndev->dev.parent, + (void *)page_address(frag->page) + + frag->page_offset, + frag->size, DMA_TO_DEVICE); + cur_p->len = frag->size; + cur_p->app0 = 0; + frag++; + } + cur_p->app0 |= STS_CTRL_APP0_EOP; + + tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; + lp->tx_bd_tail++; + if (lp->tx_bd_tail >= TX_BD_NUM) + lp->tx_bd_tail = 0; + + /* Kick off the transfer */ + temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ + + return 0; +} + + +static void ll_temac_recv(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct sk_buff *skb, *new_skb; + unsigned int bdstat; + struct cdmac_bd *cur_p; + dma_addr_t tail_p; + int length; + unsigned long skb_vaddr; + unsigned long flags; + + spin_lock_irqsave(&lp->rx_lock, flags); + + tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + + bdstat = cur_p->app0; + while ((bdstat & STS_CTRL_APP0_CMPLT)) { + + skb = lp->rx_skb[lp->rx_bd_ci]; + length = cur_p->app4; + + skb_vaddr = virt_to_bus(skb->data); + dma_unmap_single(ndev->dev.parent, skb_vaddr, length, + DMA_FROM_DEVICE); + + skb_put(skb, length); + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + netif_rx(skb); + + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += length; + + new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN, + GFP_ATOMIC); + if (new_skb == 0) { + dev_err(&ndev->dev, "no memory for new sk_buff\n"); + spin_unlock_irqrestore(&lp->rx_lock, flags); + return; + } + + skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data)); + + cur_p->app0 = STS_CTRL_APP0_IRQONEND; + cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data, + XTE_MAX_JUMBO_FRAME_SIZE, + DMA_FROM_DEVICE); + cur_p->len = XTE_MAX_JUMBO_FRAME_SIZE; + lp->rx_skb[lp->rx_bd_ci] = new_skb; + + lp->rx_bd_ci++; + if (lp->rx_bd_ci >= RX_BD_NUM) + lp->rx_bd_ci = 0; + + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + bdstat = cur_p->app0; + } + temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p); + + spin_unlock_irqrestore(&lp->rx_lock, flags); +} + +static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) +{ + struct net_device *ndev = _ndev; + struct temac_local *lp = netdev_priv(ndev); + unsigned int status; + + status = temac_dma_in32(lp, TX_IRQ_REG); + temac_dma_out32(lp, TX_IRQ_REG, status); + + if (status & (IRQ_COAL | IRQ_DLY)) + temac_start_xmit_done(lp->ndev); + if (status & 0x080) + dev_err(&ndev->dev, "DMA error 0x%x\n", status); + + return IRQ_HANDLED; +} + +static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev) +{ + struct net_device *ndev = _ndev; + struct temac_local *lp = netdev_priv(ndev); + unsigned int status; + + /* Read and clear the status registers */ + status = temac_dma_in32(lp, RX_IRQ_REG); + temac_dma_out32(lp, RX_IRQ_REG, status); + + if (status & (IRQ_COAL | IRQ_DLY)) + ll_temac_recv(lp->ndev); + + return IRQ_HANDLED; +} + +static int temac_open(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + int rc; + + dev_dbg(&ndev->dev, "temac_open()\n"); + + if (lp->phy_node) { + lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node, + temac_adjust_link, 0, 0); + if (!lp->phy_dev) { + dev_err(lp->dev, "of_phy_connect() failed\n"); + return -ENODEV; + } + + phy_start(lp->phy_dev); + } + + rc = request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->name, ndev); + if (rc) + goto err_tx_irq; + rc = request_irq(lp->rx_irq, ll_temac_rx_irq, 0, ndev->name, ndev); + if (rc) + goto err_rx_irq; + + temac_device_reset(ndev); + return 0; + + err_rx_irq: + free_irq(lp->tx_irq, ndev); + err_tx_irq: + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + dev_err(lp->dev, "request_irq() failed\n"); + return rc; +} + +static int temac_stop(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + + dev_dbg(&ndev->dev, "temac_close()\n"); + + free_irq(lp->tx_irq, ndev); + free_irq(lp->rx_irq, ndev); + + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +temac_poll_controller(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + + disable_irq(lp->tx_irq); + disable_irq(lp->rx_irq); + + ll_temac_rx_irq(lp->tx_irq, lp); + ll_temac_tx_irq(lp->rx_irq, lp); + + enable_irq(lp->tx_irq); + enable_irq(lp->rx_irq); +} +#endif + +static const struct net_device_ops temac_netdev_ops = { + .ndo_open = temac_open, + .ndo_stop = temac_stop, + .ndo_start_xmit = temac_start_xmit, + .ndo_set_mac_address = temac_set_mac_address, + //.ndo_set_multicast_list = temac_set_multicast_list, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = temac_poll_controller, +#endif +}; + +/* --------------------------------------------------------------------- + * SYSFS device attributes + */ +static ssize_t temac_show_llink_regs(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct temac_local *lp = netdev_priv(ndev); + int i, len = 0; + + for (i = 0; i < 0x11; i++) + len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i), + (i % 8) == 7 ? "\n" : " "); + len += sprintf(buf + len, "\n"); + + return len; +} + +static DEVICE_ATTR(llink_regs, 0440, temac_show_llink_regs, NULL); + +static struct attribute *temac_device_attrs[] = { + &dev_attr_llink_regs.attr, + NULL, +}; + +static const struct attribute_group temac_attr_group = { + .attrs = temac_device_attrs, +}; + +static int __init +temac_of_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *np; + struct temac_local *lp; + struct net_device *ndev; + const void *addr; + int size, rc = 0; + unsigned int dcrs; + + /* Init network device structure */ + ndev = alloc_etherdev(sizeof(*lp)); + if (!ndev) { + dev_err(&op->dev, "could not allocate device.\n"); + return -ENOMEM; + } + ether_setup(ndev); + dev_set_drvdata(&op->dev, ndev); + SET_NETDEV_DEV(ndev, &op->dev); + ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ + ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->netdev_ops = &temac_netdev_ops; +#if 0 + ndev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4. */ + ndev->features |= NETIF_F_HW_CSUM; /* Can checksum all the packets. */ + ndev->features |= NETIF_F_IPV6_CSUM; /* Can checksum IPV6 TCP/UDP */ + ndev->features |= NETIF_F_HIGHDMA; /* Can DMA to high memory. */ + ndev->features |= NETIF_F_HW_VLAN_TX; /* Transmit VLAN hw accel */ + ndev->features |= NETIF_F_HW_VLAN_RX; /* Receive VLAN hw acceleration */ + ndev->features |= NETIF_F_HW_VLAN_FILTER; /* Receive VLAN filtering */ + ndev->features |= NETIF_F_VLAN_CHALLENGED; /* cannot handle VLAN pkts */ + ndev->features |= NETIF_F_GSO; /* Enable software GSO. */ + ndev->features |= NETIF_F_MULTI_QUEUE; /* Has multiple TX/RX queues */ + ndev->features |= NETIF_F_LRO; /* large receive offload */ +#endif + + /* setup temac private info structure */ + lp = netdev_priv(ndev); + lp->ndev = ndev; + lp->dev = &op->dev; + lp->options = XTE_OPTION_DEFAULTS; + spin_lock_init(&lp->rx_lock); + mutex_init(&lp->indirect_mutex); + + /* map device registers */ + lp->regs = of_iomap(op->node, 0); + if (!lp->regs) { + dev_err(&op->dev, "could not map temac regs.\n"); + goto nodev; + } + + /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ + np = of_parse_phandle(op->node, "llink-connected", 0); + if (!np) { + dev_err(&op->dev, "could not find DMA node\n"); + goto nodev; + } + + dcrs = dcr_resource_start(np, 0); + if (dcrs == 0) { + dev_err(&op->dev, "could not get DMA register address\n"); + goto nodev;; + } + lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0)); + dev_dbg(&op->dev, "DCR base: %x\n", dcrs); + + lp->rx_irq = irq_of_parse_and_map(np, 0); + lp->tx_irq = irq_of_parse_and_map(np, 1); + if (!lp->rx_irq || !lp->tx_irq) { + dev_err(&op->dev, "could not determine irqs\n"); + rc = -ENOMEM; + goto nodev; + } + + of_node_put(np); /* Finished with the DMA node; drop the reference */ + + /* Retrieve the MAC address */ + addr = of_get_property(op->node, "local-mac-address", &size); + if ((!addr) || (size != 6)) { + dev_err(&op->dev, "could not find MAC address\n"); + rc = -ENODEV; + goto nodev; + } + temac_set_mac_address(ndev, (void *)addr); + + rc = temac_mdio_setup(lp, op->node); + if (rc) + dev_warn(&op->dev, "error registering MDIO bus\n"); + + lp->phy_node = of_parse_phandle(op->node, "phy-handle", 0); + if (lp->phy_node) + dev_dbg(lp->dev, "using PHY node %s (%p)\n", np->full_name, np); + + /* Add the device attributes */ + rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group); + if (rc) { + dev_err(lp->dev, "Error creating sysfs files\n"); + goto nodev; + } + + rc = register_netdev(lp->ndev); + if (rc) { + dev_err(lp->dev, "register_netdev() error (%i)\n", rc); + goto err_register_ndev; + } + + return 0; + + err_register_ndev: + sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); + nodev: + free_netdev(ndev); + ndev = NULL; + return rc; +} + +static int __devexit temac_of_remove(struct of_device *op) +{ + struct net_device *ndev = dev_get_drvdata(&op->dev); + struct temac_local *lp = netdev_priv(ndev); + + temac_mdio_teardown(lp); + unregister_netdev(ndev); + sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); + if (lp->phy_node) + of_node_put(lp->phy_node); + lp->phy_node = NULL; + dev_set_drvdata(&op->dev, NULL); + free_netdev(ndev); + return 0; +} + +static struct of_device_id temac_of_match[] __devinitdata = { + { .compatible = "xlnx,xps-ll-temac-1.01.b", }, + {}, +}; +MODULE_DEVICE_TABLE(of, temac_of_match); + +static struct of_platform_driver temac_of_driver = { + .match_table = temac_of_match, + .probe = temac_of_probe, + .remove = __devexit_p(temac_of_remove), + .driver = { + .owner = THIS_MODULE, + .name = "xilinx_temac", + }, +}; + +static int __init temac_init(void) +{ + return of_register_platform_driver(&temac_of_driver); +} +module_init(temac_init); + +static void __exit temac_exit(void) +{ + of_unregister_platform_driver(&temac_of_driver); +} +module_exit(temac_exit); + +MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver"); +MODULE_AUTHOR("Yoshio Kashiwagi"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c new file mode 100644 index 000000000000..da0e462308d5 --- /dev/null +++ b/drivers/net/ll_temac_mdio.c @@ -0,0 +1,120 @@ +/* + * MDIO bus driver for the Xilinx TEMAC device + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ll_temac.h" + +/* --------------------------------------------------------------------- + * MDIO Bus functions + */ +static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + struct temac_local *lp = bus->priv; + u32 rc; + + /* Write the PHY address to the MIIM Access Initiator register. + * When the transfer completes, the PHY register value will appear + * in the LSW0 register */ + mutex_lock(&lp->indirect_mutex); + temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg); + rc = temac_indirect_in32(lp, XTE_MIIMAI_OFFSET); + mutex_unlock(&lp->indirect_mutex); + + dev_dbg(lp->dev, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n", + phy_id, reg, rc); + + return rc; +} + +static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val) +{ + struct temac_local *lp = bus->priv; + + dev_dbg(lp->dev, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n", + phy_id, reg, val); + + /* First write the desired value into the write data register + * and then write the address into the access initiator register + */ + mutex_lock(&lp->indirect_mutex); + temac_indirect_out32(lp, XTE_MGTDR_OFFSET, val); + temac_indirect_out32(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) | reg); + mutex_unlock(&lp->indirect_mutex); + + return 0; +} + +int temac_mdio_setup(struct temac_local *lp, struct device_node *np) +{ + struct mii_bus *bus; + const u32 *bus_hz; + int clk_div; + int rc, size; + struct resource res; + + /* Calculate a reasonable divisor for the clock rate */ + clk_div = 0x3f; /* worst-case default setting */ + bus_hz = of_get_property(np, "clock-frequency", &size); + if (bus_hz && size >= sizeof(*bus_hz)) { + clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1; + if (clk_div < 1) + clk_div = 1; + if (clk_div > 0x3f) + clk_div = 0x3f; + } + + /* Enable the MDIO bus by asserting the enable bit and writing + * in the clock config */ + mutex_lock(&lp->indirect_mutex); + temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div); + mutex_unlock(&lp->indirect_mutex); + + bus = mdiobus_alloc(); + if (!bus) + return -ENOMEM; + + of_address_to_resource(np, 0, &res); + snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", + (unsigned long long)res.start); + bus->priv = lp; + bus->name = "Xilinx TEMAC MDIO"; + bus->read = temac_mdio_read; + bus->write = temac_mdio_write; + bus->parent = lp->dev; + bus->irq = lp->mdio_irqs; /* preallocated IRQ table */ + + lp->mii_bus = bus; + + rc = of_mdiobus_register(bus, np); + if (rc) + goto err_register; + + mutex_lock(&lp->indirect_mutex); + dev_dbg(lp->dev, "MDIO bus registered; MC:%x\n", + temac_indirect_in32(lp, XTE_MC_OFFSET)); + mutex_unlock(&lp->indirect_mutex); + return 0; + + err_register: + mdiobus_free(bus); + return rc; +} + +void temac_mdio_teardown(struct temac_local *lp) +{ + mdiobus_unregister(lp->mii_bus); + kfree(lp->mii_bus->irq); + mdiobus_free(lp->mii_bus); + lp->mii_bus = NULL; +} + diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b7d438a367f3..da472c687481 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -62,6 +62,7 @@ struct pcpu_lstats { unsigned long packets; unsigned long bytes; + unsigned long drops; }; /* @@ -71,18 +72,22 @@ struct pcpu_lstats { static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) { struct pcpu_lstats *pcpu_lstats, *lb_stats; + int len; skb_orphan(skb); - skb->protocol = eth_type_trans(skb,dev); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ pcpu_lstats = dev->ml_priv; lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id()); - lb_stats->bytes += skb->len; - lb_stats->packets++; - netif_rx(skb); + len = skb->len; + if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { + lb_stats->bytes += len; + lb_stats->packets++; + } else + lb_stats->drops++; return 0; } @@ -93,6 +98,7 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev) struct net_device_stats *stats = &dev->stats; unsigned long bytes = 0; unsigned long packets = 0; + unsigned long drops = 0; int i; pcpu_lstats = dev->ml_priv; @@ -102,11 +108,14 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev) lb_stats = per_cpu_ptr(pcpu_lstats, i); bytes += lb_stats->bytes; packets += lb_stats->packets; + drops += lb_stats->drops; } stats->rx_packets = packets; stats->tx_packets = packets; - stats->rx_bytes = bytes; - stats->tx_bytes = bytes; + stats->rx_dropped = drops; + stats->rx_errors = drops; + stats->rx_bytes = bytes; + stats->tx_bytes = bytes; return stats; } @@ -161,6 +170,7 @@ static void loopback_setup(struct net_device *dev) dev->tx_queue_len = 0; dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ dev->flags = IFF_LOOPBACK; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | NETIF_F_NO_CSUM diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 22e74a0e0361..f8fa0c3f0f64 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -620,19 +620,12 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd /* Good, done, now spit out some messages */ printk(KERN_INFO "%s: %s in slot %X (type %s)\n", - dev->name, ndev->board->name, ndev->board->slot, cardname[type]); - printk(KERN_INFO "MAC "); - { - int i; - for (i = 0; i < 6; i++) { - printk("%2.2x", dev->dev_addr[i]); - if (i < 5) - printk(":"); - } - } - printk(" IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", - dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4, - dev->mem_start, access_bitmode?32:16); + dev->name, ndev->board->name, ndev->board->slot, cardname[type]); + printk(KERN_INFO + "MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", + dev->dev_addr, dev->irq, + (unsigned int)(dev->mem_end - dev->mem_start) >> 10, + dev->mem_start, access_bitmode ? 32 : 16); return 0; } diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index 384e072de2e7..dab45339d3a8 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -73,8 +73,6 @@ static char *version = or override something. */ #include -#define PRINTK(x) printk x - /* Sources: @@ -402,7 +400,7 @@ net_send_packet(struct sk_buff *skb, struct net_device *dev) /* Gasp! It hasn't. But that shouldn't happen since we're waiting for TxOk, so return 1 and requeue this packet. */ local_irq_restore(flags); - return 1; + return NETDEV_TX_BUSY; } /* Write the contents of the packet */ diff --git a/drivers/net/macb.c b/drivers/net/macb.c index e82aee41d77e..5b5c25368d1e 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -599,6 +599,21 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void macb_poll_controller(struct net_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + macb_interrupt(dev->irq, dev); + local_irq_restore(flags); +} +#endif + static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct macb *bp = netdev_priv(dev); @@ -630,7 +645,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) "BUG! Tx Ring full when queue awake!\n"); dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n", bp->tx_head, bp->tx_tail); - return 1; + return NETDEV_TX_BUSY; } entry = bp->tx_head; @@ -1094,6 +1109,9 @@ static const struct net_device_ops macb_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = macb_poll_controller, +#endif }; static int __init macb_probe(struct platform_device *pdev) diff --git a/drivers/net/mace.c b/drivers/net/mace.c index feebbd92aff2..1427755c224d 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -94,6 +94,16 @@ static void __mace_set_address(struct net_device *dev, void *addr); */ static unsigned char *dummy_buf; +static const struct net_device_ops mace_netdev_ops = { + .ndo_open = mace_open, + .ndo_stop = mace_close, + .ndo_start_xmit = mace_xmit_start, + .ndo_set_multicast_list = mace_set_multicast, + .ndo_set_mac_address = mace_set_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match) { struct device_node *mace = macio_get_of_node(mdev); @@ -207,11 +217,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i } } - dev->open = mace_open; - dev->stop = mace_close; - dev->hard_start_xmit = mace_xmit_start; - dev->set_multicast_list = mace_set_multicast; - dev->set_mac_address = mace_set_address; + dev->netdev_ops = &mace_netdev_ops; /* * Most of what is below could be moved to mace_open() @@ -541,7 +547,7 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); mp->tx_fullup = 1; spin_unlock_irqrestore(&mp->lock, flags); - return 1; /* can't take it at the moment */ + return NETDEV_TX_BUSY; /* can't take it at the moment */ } spin_unlock_irqrestore(&mp->lock, flags); diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 274e99bb63ac..44f3c2896f20 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -180,6 +180,17 @@ static void mace_dma_off(struct net_device *dev) psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100); } +static const struct net_device_ops mace_netdev_ops = { + .ndo_open = mace_open, + .ndo_stop = mace_close, + .ndo_start_xmit = mace_xmit_start, + .ndo_tx_timeout = mace_tx_timeout, + .ndo_set_multicast_list = mace_set_multicast, + .ndo_set_mac_address = mace_set_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + /* * Not really much of a probe. The hardware table tells us if this * model of Macintrash has a MACE (AV macintoshes) @@ -240,13 +251,8 @@ static int __devinit mace_probe(struct platform_device *pdev) return -ENODEV; } - dev->open = mace_open; - dev->stop = mace_close; - dev->hard_start_xmit = mace_xmit_start; - dev->tx_timeout = mace_tx_timeout; + dev->netdev_ops = &mace_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; - dev->set_multicast_list = mace_set_multicast; - dev->set_mac_address = mace_set_address; printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n", dev->name, dev->dev_addr); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 214a8cf2b708..99eed9f37c84 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -232,7 +232,7 @@ static int macvlan_open(struct net_device *dev) if (macvlan_addr_busy(vlan->port, dev->dev_addr)) goto out; - err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN); + err = dev_unicast_add(lowerdev, dev->dev_addr); if (err < 0) goto out; if (dev->flags & IFF_ALLMULTI) { @@ -244,7 +244,7 @@ static int macvlan_open(struct net_device *dev) return 0; del_unicast: - dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(lowerdev, dev->dev_addr); out: return err; } @@ -258,7 +258,7 @@ static int macvlan_stop(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(lowerdev, -1); - dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(lowerdev, dev->dev_addr); macvlan_hash_del(vlan); return 0; @@ -282,10 +282,11 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p) if (macvlan_addr_busy(vlan->port, addr->sa_data)) return -EBUSY; - if ((err = dev_unicast_add(lowerdev, addr->sa_data, ETH_ALEN))) + err = dev_unicast_add(lowerdev, addr->sa_data); + if (err) return err; - dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(lowerdev, dev->dev_addr); macvlan_hash_change_addr(vlan, addr->sa_data); } @@ -358,6 +359,7 @@ static int macvlan_init(struct net_device *dev) (lowerdev->state & MACVLAN_STATE_MASK); dev->features = lowerdev->features & MACVLAN_FEATURES; dev->iflink = lowerdev->ifindex; + dev->hard_header_len = lowerdev->hard_header_len; macvlan_set_lockdep_class(dev); @@ -374,36 +376,20 @@ static void macvlan_ethtool_get_drvinfo(struct net_device *dev, static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) { const struct macvlan_dev *vlan = netdev_priv(dev); - struct net_device *lowerdev = vlan->lowerdev; - - if (lowerdev->ethtool_ops == NULL || - lowerdev->ethtool_ops->get_rx_csum == NULL) - return 0; - return lowerdev->ethtool_ops->get_rx_csum(lowerdev); + return dev_ethtool_get_rx_csum(vlan->lowerdev); } static int macvlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { const struct macvlan_dev *vlan = netdev_priv(dev); - struct net_device *lowerdev = vlan->lowerdev; - - if (!lowerdev->ethtool_ops || - !lowerdev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - - return lowerdev->ethtool_ops->get_settings(lowerdev, cmd); + return dev_ethtool_get_settings(vlan->lowerdev, cmd); } static u32 macvlan_ethtool_get_flags(struct net_device *dev) { const struct macvlan_dev *vlan = netdev_priv(dev); - struct net_device *lowerdev = vlan->lowerdev; - - if (!lowerdev->ethtool_ops || - !lowerdev->ethtool_ops->get_flags) - return 0; - return lowerdev->ethtool_ops->get_flags(lowerdev); + return dev_ethtool_get_flags(vlan->lowerdev); } static const struct ethtool_ops macvlan_ethtool_ops = { @@ -430,6 +416,7 @@ static void macvlan_setup(struct net_device *dev) { ether_setup(dev); + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; dev->netdev_ops = &macvlan_netdev_ops; dev->destructor = free_netdev; dev->header_ops = &macvlan_hard_header_ops, diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c new file mode 100644 index 000000000000..dc45e9856c35 --- /dev/null +++ b/drivers/net/mdio.c @@ -0,0 +1,431 @@ +/* + * mdio.c: Generic support for MDIO-compatible transceivers + * Copyright 2006-2009 Solarflare Communications 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, incorporated herein by reference. + */ + +#include +#include +#include +#include +#include +#include + +/** + * mdio45_probe - probe for an MDIO (clause 45) device + * @mdio: MDIO interface + * @prtad: Expected PHY address + * + * This sets @prtad and @mmds in the MDIO interface if successful. + * Returns 0 on success, negative on error. + */ +int mdio45_probe(struct mdio_if_info *mdio, int prtad) +{ + int mmd, stat2, devs1, devs2; + + /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY + * XS or DTE XS; give up if none is present. */ + for (mmd = 1; mmd <= 5; mmd++) { + /* Is this MMD present? */ + stat2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_STAT2); + if (stat2 < 0 || + (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) + continue; + + /* It should tell us about all the other MMDs */ + devs1 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS1); + devs2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS2); + if (devs1 < 0 || devs2 < 0) + continue; + + mdio->prtad = prtad; + mdio->mmds = devs1 | (devs2 << 16); + return 0; + } + + return -ENODEV; +} +EXPORT_SYMBOL(mdio45_probe); + +/** + * mdio_set_flag - set or clear flag in an MDIO register + * @mdio: MDIO interface + * @prtad: PHY address + * @devad: MMD address + * @addr: Register address + * @mask: Mask for flag (single bit set) + * @sense: New value of flag + * + * This debounces changes: it does not write the register if the flag + * already has the proper value. Returns 0 on success, negative on error. + */ +int mdio_set_flag(const struct mdio_if_info *mdio, + int prtad, int devad, u16 addr, int mask, + bool sense) +{ + int old_val = mdio->mdio_read(mdio->dev, prtad, devad, addr); + int new_val; + + if (old_val < 0) + return old_val; + if (sense) + new_val = old_val | mask; + else + new_val = old_val & ~mask; + if (old_val == new_val) + return 0; + return mdio->mdio_write(mdio->dev, prtad, devad, addr, new_val); +} +EXPORT_SYMBOL(mdio_set_flag); + +/** + * mdio_link_ok - is link status up/OK + * @mdio: MDIO interface + * @mmd_mask: Mask for MMDs to check + * + * Returns 1 if the PHY reports link status up/OK, 0 otherwise. + * @mmd_mask is normally @mdio->mmds, but if loopback is enabled + * the MMDs being bypassed should be excluded from the mask. + */ +int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmd_mask) +{ + int devad, reg; + + if (!mmd_mask) { + /* Use absence of XGMII faults in lieu of link state */ + reg = mdio->mdio_read(mdio->dev, mdio->prtad, + MDIO_MMD_PHYXS, MDIO_STAT2); + return reg >= 0 && !(reg & MDIO_STAT2_RXFAULT); + } + + for (devad = 0; mmd_mask; devad++) { + if (mmd_mask & (1 << devad)) { + mmd_mask &= ~(1 << devad); + + /* Read twice because link state is latched and a + * read moves the current state into the register */ + mdio->mdio_read(mdio->dev, mdio->prtad, + devad, MDIO_STAT1); + reg = mdio->mdio_read(mdio->dev, mdio->prtad, + devad, MDIO_STAT1); + if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) + return false; + } + } + + return true; +} +EXPORT_SYMBOL(mdio45_links_ok); + +/** + * mdio45_nway_restart - restart auto-negotiation for this interface + * @mdio: MDIO interface + * + * Returns 0 on success, negative on error. + */ +int mdio45_nway_restart(const struct mdio_if_info *mdio) +{ + if (!(mdio->mmds & MDIO_DEVS_AN)) + return -EOPNOTSUPP; + + mdio_set_flag(mdio, mdio->prtad, MDIO_MMD_AN, MDIO_CTRL1, + MDIO_AN_CTRL1_RESTART, true); + return 0; +} +EXPORT_SYMBOL(mdio45_nway_restart); + +static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr) +{ + u32 result = 0; + int reg; + + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, addr); + if (reg & ADVERTISE_10HALF) + result |= ADVERTISED_10baseT_Half; + if (reg & ADVERTISE_10FULL) + result |= ADVERTISED_10baseT_Full; + if (reg & ADVERTISE_100HALF) + result |= ADVERTISED_100baseT_Half; + if (reg & ADVERTISE_100FULL) + result |= ADVERTISED_100baseT_Full; + return result; +} + +/** + * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET + * @mdio: MDIO interface + * @ecmd: Ethtool request structure + * @npage_adv: Modes currently advertised on next pages + * @npage_lpa: Modes advertised by link partner on next pages + * + * Since the CSRs for auto-negotiation using next pages are not fully + * standardised, this function does not attempt to decode them. The + * caller must pass them in. + */ +void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, + struct ethtool_cmd *ecmd, + u32 npage_adv, u32 npage_lpa) +{ + int reg; + + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = mdio->prtad; + ecmd->mdio_support = + mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22); + + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_CTRL2); + switch (reg & MDIO_PMA_CTRL2_TYPE) { + case MDIO_PMA_CTRL2_10GBT: + case MDIO_PMA_CTRL2_1000BT: + case MDIO_PMA_CTRL2_100BTX: + case MDIO_PMA_CTRL2_10BT: + ecmd->port = PORT_TP; + ecmd->supported = SUPPORTED_TP; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_SPEED); + if (reg & MDIO_SPEED_10G) + ecmd->supported |= SUPPORTED_10000baseT_Full; + if (reg & MDIO_PMA_SPEED_1000) + ecmd->supported |= (SUPPORTED_1000baseT_Full | + SUPPORTED_1000baseT_Half); + if (reg & MDIO_PMA_SPEED_100) + ecmd->supported |= (SUPPORTED_100baseT_Full | + SUPPORTED_100baseT_Half); + if (reg & MDIO_PMA_SPEED_10) + ecmd->supported |= (SUPPORTED_10baseT_Full | + SUPPORTED_10baseT_Half); + ecmd->advertising = ADVERTISED_TP; + break; + + case MDIO_PMA_CTRL2_10GBCX4: + ecmd->port = PORT_OTHER; + ecmd->supported = 0; + ecmd->advertising = 0; + break; + + case MDIO_PMA_CTRL2_10GBKX4: + case MDIO_PMA_CTRL2_10GBKR: + case MDIO_PMA_CTRL2_1000BKX: + ecmd->port = PORT_OTHER; + ecmd->supported = SUPPORTED_Backplane; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_PMA_EXTABLE); + if (reg & MDIO_PMA_EXTABLE_10GBKX4) + ecmd->supported |= SUPPORTED_10000baseKX4_Full; + if (reg & MDIO_PMA_EXTABLE_10GBKR) + ecmd->supported |= SUPPORTED_10000baseKR_Full; + if (reg & MDIO_PMA_EXTABLE_1000BKX) + ecmd->supported |= SUPPORTED_1000baseKX_Full; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_PMA_10GBR_FECABLE); + if (reg & MDIO_PMA_10GBR_FECABLE_ABLE) + ecmd->supported |= SUPPORTED_10000baseR_FEC; + ecmd->advertising = ADVERTISED_Backplane; + break; + + /* All the other defined modes are flavours of optical */ + default: + ecmd->port = PORT_FIBRE; + ecmd->supported = SUPPORTED_FIBRE; + ecmd->advertising = ADVERTISED_FIBRE; + break; + } + + if (mdio->mmds & MDIO_DEVS_AN) { + ecmd->supported |= SUPPORTED_Autoneg; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_CTRL1); + if (reg & MDIO_AN_CTRL1_ENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->advertising |= + ADVERTISED_Autoneg | + mdio45_get_an(mdio, MDIO_AN_ADVERTISE) | + npage_adv; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + } + } else { + ecmd->autoneg = AUTONEG_DISABLE; + } + + if (ecmd->autoneg) { + u32 modes = 0; + int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad, + MDIO_MMD_AN, MDIO_STAT1); + + /* If AN is complete and successful, report best common + * mode, otherwise report best advertised mode. */ + if (an_stat & MDIO_AN_STAT1_COMPLETE) { + ecmd->lp_advertising = + mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa; + if (an_stat & MDIO_AN_STAT1_LPABLE) + ecmd->lp_advertising |= ADVERTISED_Autoneg; + modes = ecmd->advertising & ecmd->lp_advertising; + } + if ((modes & ~ADVERTISED_Autoneg) == 0) + modes = ecmd->advertising; + + if (modes & (ADVERTISED_10000baseT_Full | + ADVERTISED_10000baseKX4_Full | + ADVERTISED_10000baseKR_Full)) { + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + } else if (modes & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseKX_Full)) { + ecmd->speed = SPEED_1000; + ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half); + } else if (modes & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { + ecmd->speed = SPEED_100; + ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); + } else { + ecmd->speed = SPEED_10; + ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); + } + } else { + /* Report forced settings */ + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_CTRL1); + ecmd->speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) * + ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10)); + ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX || + ecmd->speed == SPEED_10000); + } + + /* 10GBASE-T MDI/MDI-X */ + if (ecmd->port == PORT_TP && ecmd->speed == SPEED_10000) { + switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_PMA_10GBT_SWAPPOL)) { + case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX: + ecmd->eth_tp_mdix = ETH_TP_MDI; + break; + case 0: + ecmd->eth_tp_mdix = ETH_TP_MDI_X; + break; + default: + /* It's complicated... */ + ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + break; + } + } +} +EXPORT_SYMBOL(mdio45_ethtool_gset_npage); + +/** + * mdio45_ethtool_spauseparam_an - set auto-negotiated pause parameters + * @mdio: MDIO interface + * @ecmd: Ethtool request structure + * + * This function assumes that the PHY has an auto-negotiation MMD. It + * will enable and disable advertising of flow control as appropriate. + */ +void mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio, + const struct ethtool_pauseparam *ecmd) +{ + int adv, old_adv; + + WARN_ON(!(mdio->mmds & MDIO_DEVS_AN)); + + old_adv = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_AN_ADVERTISE); + adv = old_adv & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + if (ecmd->autoneg) + adv |= mii_advertise_flowctrl( + (ecmd->rx_pause ? FLOW_CTRL_RX : 0) | + (ecmd->tx_pause ? FLOW_CTRL_TX : 0)); + if (adv != old_adv) { + mdio->mdio_write(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_AN_ADVERTISE, adv); + mdio45_nway_restart(mdio); + } +} +EXPORT_SYMBOL(mdio45_ethtool_spauseparam_an); + +/** + * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs + * @mdio: MDIO interface + * @mii_data: MII ioctl data structure + * @cmd: MII ioctl command + * + * Returns 0 on success, negative on error. + */ +int mdio_mii_ioctl(const struct mdio_if_info *mdio, + struct mii_ioctl_data *mii_data, int cmd) +{ + int prtad, devad; + u16 addr = mii_data->reg_num; + + /* Validate/convert cmd to one of SIOC{G,S}MIIREG */ + switch (cmd) { + case SIOCGMIIPHY: + if (mdio->prtad == MDIO_PRTAD_NONE) + return -EOPNOTSUPP; + mii_data->phy_id = mdio->prtad; + cmd = SIOCGMIIREG; + break; + case SIOCGMIIREG: + break; + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + break; + default: + return -EOPNOTSUPP; + } + + /* Validate/convert phy_id */ + if ((mdio->mode_support & MDIO_SUPPORTS_C45) && + mdio_phy_id_is_c45(mii_data->phy_id)) { + prtad = mdio_phy_id_prtad(mii_data->phy_id); + devad = mdio_phy_id_devad(mii_data->phy_id); + } else if ((mdio->mode_support & MDIO_SUPPORTS_C22) && + mii_data->phy_id < 0x20) { + prtad = mii_data->phy_id; + devad = MDIO_DEVAD_NONE; + addr &= 0x1f; + } else if ((mdio->mode_support & MDIO_EMULATE_C22) && + mdio->prtad != MDIO_PRTAD_NONE && + mii_data->phy_id == mdio->prtad) { + /* Remap commonly-used MII registers. */ + prtad = mdio->prtad; + switch (addr) { + case MII_BMCR: + case MII_BMSR: + case MII_PHYSID1: + case MII_PHYSID2: + devad = __ffs(mdio->mmds); + break; + case MII_ADVERTISE: + case MII_LPA: + if (!(mdio->mmds & MDIO_DEVS_AN)) + return -EINVAL; + devad = MDIO_MMD_AN; + if (addr == MII_ADVERTISE) + addr = MDIO_AN_ADVERTISE; + else + addr = MDIO_AN_LPA; + break; + default: + return -EINVAL; + } + } else { + return -EINVAL; + } + + if (cmd == SIOCGMIIREG) { + int rc = mdio->mdio_read(mdio->dev, prtad, devad, addr); + if (rc < 0) + return rc; + mii_data->val_out = rc; + return 0; + } else { + return mdio->mdio_write(mdio->dev, prtad, devad, addr, + mii_data->val_in); + } +} +EXPORT_SYMBOL(mdio_mii_ioctl); diff --git a/drivers/net/meth.c b/drivers/net/meth.c index dbd3436912b8..5d04d94f2a21 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -770,9 +770,17 @@ static int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } } -/* - * Return statistics to the caller - */ +static const struct net_device_ops meth_netdev_ops = { + .ndo_open = meth_open, + .ndo_stop = meth_release, + .ndo_start_xmit = meth_tx, + .ndo_do_ioctl = meth_ioctl, + .ndo_tx_timeout = meth_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + /* * The init function. */ @@ -786,16 +794,10 @@ static int __init meth_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - dev->open = meth_open; - dev->stop = meth_release; - dev->hard_start_xmit = meth_tx; - dev->do_ioctl = meth_ioctl; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = meth_tx_timeout; - dev->watchdog_timeo = timeout; -#endif - dev->irq = MACE_ETHERNET_IRQ; - dev->base_addr = (unsigned long)&mace->eth; + dev->netdev_ops = &meth_netdev_ops; + dev->watchdog_timeo = timeout; + dev->irq = MACE_ETHERNET_IRQ; + dev->base_addr = (unsigned long)&mace->eth; memcpy(dev->dev_addr, o2meth_eaddr, 6); priv = netdev_priv(dev); diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 92056051f269..d81a5d22a3a9 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -31,7 +31,27 @@ #include #include #include -#include +#include + +static u32 mii_get_an(struct mii_if_info *mii, u16 addr) +{ + u32 result = 0; + int advert; + + advert = mii->mdio_read(mii->dev, mii->phy_id, addr); + if (advert & LPA_LPACK) + result |= ADVERTISED_Autoneg; + if (advert & ADVERTISE_10HALF) + result |= ADVERTISED_10baseT_Half; + if (advert & ADVERTISE_10FULL) + result |= ADVERTISED_10baseT_Full; + if (advert & ADVERTISE_100HALF) + result |= ADVERTISED_100baseT_Half; + if (advert & ADVERTISE_100FULL) + result |= ADVERTISED_100baseT_Full; + + return result; +} /** * mii_ethtool_gset - get settings that are specified in @ecmd @@ -43,8 +63,8 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) { struct net_device *dev = mii->dev; - u32 advert, bmcr, lpa, nego; - u32 advert2 = 0, bmcr2 = 0, lpa2 = 0; + u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; + u32 nego; ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | @@ -62,50 +82,51 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) /* this isn't fully supported at higher layers */ ecmd->phy_address = mii->phy_id; + ecmd->mdio_support = MDIO_SUPPORTS_C22; ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); - if (mii->supports_gmii) - advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - - if (advert & ADVERTISE_10HALF) - ecmd->advertising |= ADVERTISED_10baseT_Half; - if (advert & ADVERTISE_10FULL) - ecmd->advertising |= ADVERTISED_10baseT_Full; - if (advert & ADVERTISE_100HALF) - ecmd->advertising |= ADVERTISED_100baseT_Half; - if (advert & ADVERTISE_100FULL) - ecmd->advertising |= ADVERTISED_100baseT_Full; - if (advert2 & ADVERTISE_1000HALF) - ecmd->advertising |= ADVERTISED_1000baseT_Half; - if (advert2 & ADVERTISE_1000FULL) - ecmd->advertising |= ADVERTISED_1000baseT_Full; bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); + bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); if (mii->supports_gmii) { - bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); + ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); + stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); } if (bmcr & BMCR_ANENABLE) { ecmd->advertising |= ADVERTISED_Autoneg; ecmd->autoneg = AUTONEG_ENABLE; - nego = mii_nway_result(advert & lpa); - if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) & - (lpa2 >> 2)) - ecmd->speed = SPEED_1000; - else if (nego == LPA_100FULL || nego == LPA_100HALF) - ecmd->speed = SPEED_100; - else - ecmd->speed = SPEED_10; - if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL || - nego == LPA_10FULL) { - ecmd->duplex = DUPLEX_FULL; - mii->full_duplex = 1; + ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE); + if (ctrl1000 & ADVERTISE_1000HALF) + ecmd->advertising |= ADVERTISED_1000baseT_Half; + if (ctrl1000 & ADVERTISE_1000FULL) + ecmd->advertising |= ADVERTISED_1000baseT_Full; + + if (bmsr & BMSR_ANEGCOMPLETE) { + ecmd->lp_advertising = mii_get_an(mii, MII_LPA); + if (stat1000 & LPA_1000HALF) + ecmd->lp_advertising |= + ADVERTISED_1000baseT_Half; + if (stat1000 & LPA_1000FULL) + ecmd->lp_advertising |= + ADVERTISED_1000baseT_Full; } else { - ecmd->duplex = DUPLEX_HALF; - mii->full_duplex = 0; + ecmd->lp_advertising = 0; + } + + nego = ecmd->advertising & ecmd->lp_advertising; + + if (nego & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { + ecmd->speed = SPEED_1000; + ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full); + } else if (nego & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { + ecmd->speed = SPEED_100; + ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full); + } else { + ecmd->speed = SPEED_10; + ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full); } } else { ecmd->autoneg = AUTONEG_DISABLE; @@ -116,6 +137,8 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } + mii->full_duplex = ecmd->duplex; + /* ignore maxtxpkt, maxrxpkt for now */ return 0; diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 664835b822fb..b3b9a147d09a 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -237,6 +237,16 @@ static void mipsnet_set_mclist(struct net_device *dev) { } +static const struct net_device_ops mipsnet_netdev_ops = { + .ndo_open = mipsnet_open, + .ndo_stop = mipsnet_close, + .ndo_start_xmit = mipsnet_xmit, + .ndo_set_multicast_list = mipsnet_set_mclist, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int __init mipsnet_probe(struct platform_device *dev) { struct net_device *netdev; @@ -250,10 +260,7 @@ static int __init mipsnet_probe(struct platform_device *dev) platform_set_drvdata(dev, netdev); - netdev->open = mipsnet_open; - netdev->stop = mipsnet_close; - netdev->hard_start_xmit = mipsnet_xmit; - netdev->set_multicast_list = mipsnet_set_mclist; + netdev->netdev_ops = &mipsnet_netdev_ops; /* * TODO: probe for these or load them from PARAM diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile index 21040a0d81fe..1fd068e1d930 100644 --- a/drivers/net/mlx4/Makefile +++ b/drivers/net/mlx4/Makefile @@ -5,5 +5,5 @@ mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ obj-$(CONFIG_MLX4_EN) += mlx4_en.o -mlx4_en-y := en_main.o en_tx.o en_rx.o en_params.o en_port.o en_cq.o \ +mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \ en_resources.o en_netdev.o diff --git a/drivers/net/mlx4/en_cq.c b/drivers/net/mlx4/en_cq.c index a276125b709b..21786ad4455e 100644 --- a/drivers/net/mlx4/en_cq.c +++ b/drivers/net/mlx4/en_cq.c @@ -89,6 +89,9 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) *cq->mcq.arm_db = 0; memset(cq->buf, 0, cq->buf_size); + if (!cq->is_tx) + cq->size = priv->rx_ring[cq->ring].actual_size; + err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx); if (err) diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_ethtool.c similarity index 86% rename from drivers/net/mlx4/en_params.c rename to drivers/net/mlx4/en_ethtool.c index c1bd040b9e05..091f99052c91 100644 --- a/drivers/net/mlx4/en_params.c +++ b/drivers/net/mlx4/en_ethtool.c @@ -38,64 +38,6 @@ #include "mlx4_en.h" #include "en_port.h" -#define MLX4_EN_PARM_INT(X, def_val, desc) \ - static unsigned int X = def_val;\ - module_param(X , uint, 0444); \ - MODULE_PARM_DESC(X, desc); - - -/* - * Device scope module parameters - */ - - -/* Use a XOR rathern than Toeplitz hash function for RSS */ -MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS"); - -/* RSS hash type mask - default to */ -MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask"); - -/* Number of LRO sessions per Rx ring (rounded up to a power of two) */ -MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS, - "Number of LRO sessions per ring or disabled (0)"); - -/* Priority pausing */ -MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." - " Per priority bit mask"); -MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]." - " Per priority bit mask"); - -int mlx4_en_get_profile(struct mlx4_en_dev *mdev) -{ - struct mlx4_en_profile *params = &mdev->profile; - int i; - - params->rss_xor = (rss_xor != 0); - params->rss_mask = rss_mask & 0x1f; - params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); - for (i = 1; i <= MLX4_MAX_PORTS; i++) { - params->prof[i].rx_pause = 1; - params->prof[i].rx_ppp = pfcrx; - params->prof[i].tx_pause = 1; - params->prof[i].tx_ppp = pfctx; - params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; - } - if (pfcrx || pfctx) { - params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; - params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; - } else { - params->prof[1].tx_ring_num = 1; - params->prof[2].tx_ring_num = 1; - } - - return 0; -} - - -/* - * Ethtool support - */ static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv) { @@ -326,8 +268,7 @@ static int mlx4_en_set_coalesce(struct net_device *dev, priv->rx_frames = (coal->rx_max_coalesced_frames == MLX4_EN_AUTO_CONF) ? - MLX4_EN_RX_COAL_TARGET / - priv->dev->mtu + 1 : + MLX4_EN_RX_COAL_TARGET : coal->rx_max_coalesced_frames; priv->rx_usecs = (coal->rx_coalesce_usecs == MLX4_EN_AUTO_CONF) ? @@ -371,7 +312,7 @@ static int mlx4_en_set_pauseparam(struct net_device *dev, priv->prof->rx_pause, priv->prof->rx_ppp); if (err) - mlx4_err(mdev, "Failed setting pause params to\n"); + en_err(priv, "Failed setting pause params\n"); return err; } @@ -421,13 +362,13 @@ static int mlx4_en_set_ringparam(struct net_device *dev, err = mlx4_en_alloc_resources(priv); if (err) { - mlx4_err(mdev, "Failed reallocating port resources\n"); + en_err(priv, "Failed reallocating port resources\n"); goto out; } if (port_up) { err = mlx4_en_start_port(dev); if (err) - mlx4_err(mdev, "Failed starting port\n"); + en_err(priv, "Failed starting port\n"); } out: diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index 510633fd57f6..9ed4a158f895 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -51,6 +51,55 @@ static const char mlx4_en_version[] = DRV_NAME ": Mellanox ConnectX HCA Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; +#define MLX4_EN_PARM_INT(X, def_val, desc) \ + static unsigned int X = def_val;\ + module_param(X , uint, 0444); \ + MODULE_PARM_DESC(X, desc); + + +/* + * Device scope module parameters + */ + + +/* Use a XOR rathern than Toeplitz hash function for RSS */ +MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS"); + +/* RSS hash type mask - default to */ +MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask"); + +/* Number of LRO sessions per Rx ring (rounded up to a power of two) */ +MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS, + "Number of LRO sessions per ring or disabled (0)"); + +/* Priority pausing */ +MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." + " Per priority bit mask"); +MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]." + " Per priority bit mask"); + +static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) +{ + struct mlx4_en_profile *params = &mdev->profile; + int i; + + params->rss_xor = (rss_xor != 0); + params->rss_mask = rss_mask & 0x1f; + params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); + for (i = 1; i <= MLX4_MAX_PORTS; i++) { + params->prof[i].rx_pause = 1; + params->prof[i].rx_ppp = pfcrx; + params->prof[i].tx_pause = 1; + params->prof[i].tx_ppp = pfctx; + params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; + params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; + params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS + + (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS; + } + + return 0; +} + static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, enum mlx4_dev_event event, int port) { @@ -194,28 +243,11 @@ static void *mlx4_en_add(struct mlx4_dev *dev) /* Create a netdev for each port */ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { mlx4_info(mdev, "Activating port:%d\n", i); - if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) { + if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) mdev->pndev[i] = NULL; - goto err_free_netdev; - } } return mdev; - -err_free_netdev: - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { - if (mdev->pndev[i]) - mlx4_en_destroy_netdev(mdev->pndev[i]); - } - - mutex_lock(&mdev->state_lock); - mdev->device_up = false; - mutex_unlock(&mdev->state_lock); - flush_workqueue(mdev->workqueue); - - /* Stop event queue before we drop down to release shared SW state */ - destroy_workqueue(mdev->workqueue); - err_mr: mlx4_mr_free(dev, &mdev->mr); err_uar: diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index e8eeef0c9c9a..e02bafdd3682 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -51,14 +51,14 @@ static void mlx4_en_vlan_rx_register(struct net_device *dev, struct vlan_group * struct mlx4_en_dev *mdev = priv->mdev; int err; - mlx4_dbg(HW, priv, "Registering VLAN group:%p\n", grp); + en_dbg(HW, priv, "Registering VLAN group:%p\n", grp); priv->vlgrp = grp; mutex_lock(&mdev->state_lock); if (mdev->device_up && priv->port_up) { err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, grp); if (err) - mlx4_err(mdev, "Failed configuring VLAN filter\n"); + en_err(priv, "Failed configuring VLAN filter\n"); } mutex_unlock(&mdev->state_lock); } @@ -72,15 +72,15 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) if (!priv->vlgrp) return; - mlx4_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n", - vid, vlan_group_get_device(priv->vlgrp, vid)); + en_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n", + vid, vlan_group_get_device(priv->vlgrp, vid)); /* Add VID to port VLAN filter */ mutex_lock(&mdev->state_lock); if (mdev->device_up && priv->port_up) { err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); if (err) - mlx4_err(mdev, "Failed configuring VLAN filter\n"); + en_err(priv, "Failed configuring VLAN filter\n"); } mutex_unlock(&mdev->state_lock); } @@ -94,9 +94,8 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) if (!priv->vlgrp) return; - mlx4_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp " - "entry:%p)\n", vid, priv->vlgrp, - vlan_group_get_device(priv->vlgrp, vid)); + en_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp entry:%p)\n", + vid, priv->vlgrp, vlan_group_get_device(priv->vlgrp, vid)); vlan_group_set_device(priv->vlgrp, vid, NULL); /* Remove VID from port VLAN filter */ @@ -104,7 +103,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) if (mdev->device_up && priv->port_up) { err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); if (err) - mlx4_err(mdev, "Failed configuring VLAN filter\n"); + en_err(priv, "Failed configuring VLAN filter\n"); } mutex_unlock(&mdev->state_lock); } @@ -150,9 +149,10 @@ static void mlx4_en_do_set_mac(struct work_struct *work) err = mlx4_register_mac(mdev->dev, priv->port, priv->mac, &priv->mac_index); if (err) - mlx4_err(mdev, "Failed changing HW MAC address\n"); + en_err(priv, "Failed changing HW MAC address\n"); } else - mlx4_dbg(HW, priv, "Port is down, exiting...\n"); + en_dbg(HW, priv, "Port is down while " + "registering mac, exiting...\n"); mutex_unlock(&mdev->state_lock); } @@ -174,7 +174,6 @@ static void mlx4_en_clear_list(struct net_device *dev) static void mlx4_en_cache_mclist(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; struct dev_mc_list *mclist; struct dev_mc_list *tmp; struct dev_mc_list *plist = NULL; @@ -182,7 +181,7 @@ static void mlx4_en_cache_mclist(struct net_device *dev) for (mclist = dev->mc_list; mclist; mclist = mclist->next) { tmp = kmalloc(sizeof(struct dev_mc_list), GFP_ATOMIC); if (!tmp) { - mlx4_err(mdev, "failed to allocate multicast list\n"); + en_err(priv, "failed to allocate multicast list\n"); mlx4_en_clear_list(dev); return; } @@ -219,13 +218,13 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) mutex_lock(&mdev->state_lock); if (!mdev->device_up) { - mlx4_dbg(HW, priv, "Card is not up, ignoring " - "multicast change.\n"); + en_dbg(HW, priv, "Card is not up, " + "ignoring multicast change.\n"); goto out; } if (!priv->port_up) { - mlx4_dbg(HW, priv, "Port is down, ignoring " - "multicast change.\n"); + en_dbg(HW, priv, "Port is down, " + "ignoring multicast change.\n"); goto out; } @@ -236,29 +235,27 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) if (dev->flags & IFF_PROMISC) { if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) { if (netif_msg_rx_status(priv)) - mlx4_warn(mdev, "Port:%d entering promiscuous mode\n", - priv->port); + en_warn(priv, "Entering promiscuous mode\n"); priv->flags |= MLX4_EN_FLAG_PROMISC; /* Enable promiscouos mode */ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 1); if (err) - mlx4_err(mdev, "Failed enabling " - "promiscous mode\n"); + en_err(priv, "Failed enabling " + "promiscous mode\n"); /* Disable port multicast filter (unconditionally) */ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 0, MLX4_MCAST_DISABLE); if (err) - mlx4_err(mdev, "Failed disabling " - "multicast filter\n"); + en_err(priv, "Failed disabling " + "multicast filter\n"); /* Disable port VLAN filter */ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL); if (err) - mlx4_err(mdev, "Failed disabling " - "VLAN filter\n"); + en_err(priv, "Failed disabling VLAN filter\n"); } goto out; } @@ -269,20 +266,19 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) if (priv->flags & MLX4_EN_FLAG_PROMISC) { if (netif_msg_rx_status(priv)) - mlx4_warn(mdev, "Port:%d leaving promiscuous mode\n", - priv->port); + en_warn(priv, "Leaving promiscuous mode\n"); priv->flags &= ~MLX4_EN_FLAG_PROMISC; /* Disable promiscouos mode */ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0); if (err) - mlx4_err(mdev, "Failed disabling promiscous mode\n"); + en_err(priv, "Failed disabling promiscous mode\n"); /* Enable port VLAN filter */ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); if (err) - mlx4_err(mdev, "Failed enabling VLAN filter\n"); + en_err(priv, "Failed enabling VLAN filter\n"); } /* Enable/disable the multicast filter according to IFF_ALLMULTI */ @@ -290,12 +286,12 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 0, MLX4_MCAST_DISABLE); if (err) - mlx4_err(mdev, "Failed disabling multicast filter\n"); + en_err(priv, "Failed disabling multicast filter\n"); } else { err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 0, MLX4_MCAST_DISABLE); if (err) - mlx4_err(mdev, "Failed disabling multicast filter\n"); + en_err(priv, "Failed disabling multicast filter\n"); /* Flush mcast filter and init it with broadcast address */ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST, @@ -314,7 +310,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 0, MLX4_MCAST_ENABLE); if (err) - mlx4_err(mdev, "Failed enabling multicast filter\n"); + en_err(priv, "Failed enabling multicast filter\n"); mlx4_en_clear_list(dev); } @@ -346,10 +342,10 @@ static void mlx4_en_tx_timeout(struct net_device *dev) struct mlx4_en_dev *mdev = priv->mdev; if (netif_msg_timer(priv)) - mlx4_warn(mdev, "Tx timeout called on port:%d\n", priv->port); + en_warn(priv, "Tx timeout called on port:%d\n", priv->port); priv->port_stats.tx_timeout++; - mlx4_dbg(DRV, priv, "Scheduling watchdog\n"); + en_dbg(DRV, priv, "Scheduling watchdog\n"); queue_work(mdev->workqueue, &priv->watchdog_task); } @@ -376,10 +372,10 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) * satisfy our coelsing target. * - moder_time is set to a fixed value. */ - priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->mtu + 1; + priv->rx_frames = MLX4_EN_RX_COAL_TARGET; priv->rx_usecs = MLX4_EN_RX_COAL_TIME; - mlx4_dbg(INTR, priv, "Default coalesing params for mtu:%d - " - "rx_frames:%d rx_usecs:%d\n", + en_dbg(INTR, priv, "Default coalesing params for mtu:%d - " + "rx_frames:%d rx_usecs:%d\n", priv->dev->mtu, priv->rx_frames, priv->rx_usecs); /* Setup cq moderation params */ @@ -412,7 +408,6 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) { unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies); - struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_cq *cq; unsigned long packets; unsigned long rate; @@ -472,11 +467,11 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) moder_time = priv->rx_usecs; } - mlx4_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n", - tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period); + en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n", + tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period); - mlx4_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu " - "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n", + en_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu " + "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n", priv->last_moder_time, moder_time, period, packets, avg_pkt_size, rate); @@ -487,8 +482,7 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) cq->moder_time = moder_time; err = mlx4_en_set_cq_moder(priv, cq); if (err) { - mlx4_err(mdev, "Failed modifying moderation for cq:%d " - "on port:%d\n", i, priv->port); + en_err(priv, "Failed modifying moderation for cq:%d\n", i); break; } } @@ -511,8 +505,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work) err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0); if (err) - mlx4_dbg(HW, priv, "Could not update stats for " - "port:%d\n", priv->port); + en_dbg(HW, priv, "Could not update stats \n"); mutex_lock(&mdev->state_lock); if (mdev->device_up) { @@ -536,12 +529,10 @@ static void mlx4_en_linkstate(struct work_struct *work) * report to system log */ if (priv->last_link_state != linkstate) { if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) { - if (netif_msg_link(priv)) - mlx4_info(mdev, "Port %d - link down\n", priv->port); + en_dbg(LINK, priv, "Link Down\n"); netif_carrier_off(priv->dev); } else { - if (netif_msg_link(priv)) - mlx4_info(mdev, "Port %d - link up\n", priv->port); + en_dbg(LINK, priv, "Link Up\n"); netif_carrier_on(priv->dev); } } @@ -556,58 +547,53 @@ int mlx4_en_start_port(struct net_device *dev) struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_cq *cq; struct mlx4_en_tx_ring *tx_ring; - struct mlx4_en_rx_ring *rx_ring; int rx_index = 0; int tx_index = 0; - u16 stride; int err = 0; int i; int j; if (priv->port_up) { - mlx4_dbg(DRV, priv, "start port called while port already up\n"); + en_dbg(DRV, priv, "start port called while port already up\n"); return 0; } /* Calculate Rx buf size */ dev->mtu = min(dev->mtu, priv->max_mtu); mlx4_en_calc_rx_buf(dev); - mlx4_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size); - stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + - DS_SIZE * priv->num_frags); + en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size); + /* Configure rx cq's and rings */ + err = mlx4_en_activate_rx_rings(priv); + if (err) { + en_err(priv, "Failed to activate RX rings\n"); + return err; + } for (i = 0; i < priv->rx_ring_num; i++) { cq = &priv->rx_cq[i]; - rx_ring = &priv->rx_ring[i]; err = mlx4_en_activate_cq(priv, cq); if (err) { - mlx4_err(mdev, "Failed activating Rx CQ\n"); + en_err(priv, "Failed activating Rx CQ\n"); goto cq_err; } for (j = 0; j < cq->size; j++) cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK; err = mlx4_en_set_cq_moder(priv, cq); if (err) { - mlx4_err(mdev, "Failed setting cq moderation parameters"); + en_err(priv, "Failed setting cq moderation parameters"); mlx4_en_deactivate_cq(priv, cq); goto cq_err; } mlx4_en_arm_cq(priv, cq); - + priv->rx_ring[i].cqn = cq->mcq.cqn; ++rx_index; } - err = mlx4_en_activate_rx_rings(priv); - if (err) { - mlx4_err(mdev, "Failed to activate RX rings\n"); - goto cq_err; - } - err = mlx4_en_config_rss_steer(priv); if (err) { - mlx4_err(mdev, "Failed configuring rss steering\n"); - goto rx_err; + en_err(priv, "Failed configuring rss steering\n"); + goto cq_err; } /* Configure tx cq's and rings */ @@ -616,16 +602,16 @@ int mlx4_en_start_port(struct net_device *dev) cq = &priv->tx_cq[i]; err = mlx4_en_activate_cq(priv, cq); if (err) { - mlx4_err(mdev, "Failed allocating Tx CQ\n"); + en_err(priv, "Failed allocating Tx CQ\n"); goto tx_err; } err = mlx4_en_set_cq_moder(priv, cq); if (err) { - mlx4_err(mdev, "Failed setting cq moderation parameters"); + en_err(priv, "Failed setting cq moderation parameters"); mlx4_en_deactivate_cq(priv, cq); goto tx_err; } - mlx4_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i); + en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i); cq->buf->wqe_index = cpu_to_be16(0xffff); /* Configure ring */ @@ -633,7 +619,7 @@ int mlx4_en_start_port(struct net_device *dev) err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn, priv->rx_ring[0].srq.srqn); if (err) { - mlx4_err(mdev, "Failed allocating Tx ring\n"); + en_err(priv, "Failed allocating Tx ring\n"); mlx4_en_deactivate_cq(priv, cq); goto tx_err; } @@ -651,30 +637,30 @@ int mlx4_en_start_port(struct net_device *dev) priv->prof->rx_pause, priv->prof->rx_ppp); if (err) { - mlx4_err(mdev, "Failed setting port general configurations" - " for port %d, with error %d\n", priv->port, err); + en_err(priv, "Failed setting port general configurations " + "for port %d, with error %d\n", priv->port, err); goto tx_err; } /* Set default qp number */ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0); if (err) { - mlx4_err(mdev, "Failed setting default qp numbers\n"); + en_err(priv, "Failed setting default qp numbers\n"); goto tx_err; } /* Set port mac number */ - mlx4_dbg(DRV, priv, "Setting mac for port %d\n", priv->port); + en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port); err = mlx4_register_mac(mdev->dev, priv->port, priv->mac, &priv->mac_index); if (err) { - mlx4_err(mdev, "Failed setting port mac\n"); + en_err(priv, "Failed setting port mac\n"); goto tx_err; } /* Init port */ - mlx4_dbg(HW, priv, "Initializing port\n"); + en_dbg(HW, priv, "Initializing port\n"); err = mlx4_INIT_PORT(mdev->dev, priv->port); if (err) { - mlx4_err(mdev, "Failed Initializing port\n"); + en_err(priv, "Failed Initializing port\n"); goto mac_err; } @@ -694,12 +680,11 @@ int mlx4_en_start_port(struct net_device *dev) } mlx4_en_release_rss_steer(priv); -rx_err: - for (i = 0; i < priv->rx_ring_num; i++) - mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); cq_err: while (rx_index--) mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); + for (i = 0; i < priv->rx_ring_num; i++) + mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); return err; /* need to close devices */ } @@ -712,8 +697,7 @@ void mlx4_en_stop_port(struct net_device *dev) int i; if (!priv->port_up) { - mlx4_dbg(DRV, priv, "stop port (%d) called while port already down\n", - priv->port); + en_dbg(DRV, priv, "stop port called while port already down\n"); return; } netif_stop_queue(dev); @@ -758,13 +742,13 @@ static void mlx4_en_restart(struct work_struct *work) struct mlx4_en_dev *mdev = priv->mdev; struct net_device *dev = priv->dev; - mlx4_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port); + en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port); mutex_lock(&mdev->state_lock); if (priv->port_up) { mlx4_en_stop_port(dev); if (mlx4_en_start_port(dev)) - mlx4_err(mdev, "Failed restarting port %d\n", priv->port); + en_err(priv, "Failed restarting port %d\n", priv->port); } mutex_unlock(&mdev->state_lock); } @@ -780,14 +764,14 @@ static int mlx4_en_open(struct net_device *dev) mutex_lock(&mdev->state_lock); if (!mdev->device_up) { - mlx4_err(mdev, "Cannot open - device down/disabled\n"); + en_err(priv, "Cannot open - device down/disabled\n"); err = -EBUSY; goto out; } /* Reset HW statistics and performance counters */ if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1)) - mlx4_dbg(HW, priv, "Failed dumping statistics\n"); + en_dbg(HW, priv, "Failed dumping statistics\n"); memset(&priv->stats, 0, sizeof(priv->stats)); memset(&priv->pstats, 0, sizeof(priv->pstats)); @@ -804,7 +788,7 @@ static int mlx4_en_open(struct net_device *dev) mlx4_en_set_default_moderation(priv); err = mlx4_en_start_port(dev); if (err) - mlx4_err(mdev, "Failed starting port:%d\n", priv->port); + en_err(priv, "Failed starting port:%d\n", priv->port); out: mutex_unlock(&mdev->state_lock); @@ -817,8 +801,7 @@ static int mlx4_en_close(struct net_device *dev) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; - if (netif_msg_ifdown(priv)) - mlx4_info(mdev, "Close called for port:%d\n", priv->port); + en_dbg(IFDOWN, priv, "Close port called\n"); mutex_lock(&mdev->state_lock); @@ -850,7 +833,6 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv) int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) { - struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_port_profile *prof = priv->prof; int i; @@ -879,7 +861,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) return 0; err: - mlx4_err(mdev, "Failed to allocate NIC resources\n"); + en_err(priv, "Failed to allocate NIC resources\n"); return -ENOMEM; } @@ -889,7 +871,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; - mlx4_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port); + en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port); /* Unregister device - this will close the port if it was up */ if (priv->registered) @@ -918,11 +900,11 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) struct mlx4_en_dev *mdev = priv->mdev; int err = 0; - mlx4_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n", + en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n", dev->mtu, new_mtu); if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) { - mlx4_err(mdev, "Bad MTU size:%d.\n", new_mtu); + en_err(priv, "Bad MTU size:%d.\n", new_mtu); return -EPERM; } dev->mtu = new_mtu; @@ -932,13 +914,13 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) if (!mdev->device_up) { /* NIC is probably restarting - let watchdog task reset * the port */ - mlx4_dbg(DRV, priv, "Change MTU called with card down!?\n"); + en_dbg(DRV, priv, "Change MTU called with card down!?\n"); } else { mlx4_en_stop_port(dev); mlx4_en_set_default_moderation(priv); err = mlx4_en_start_port(dev); if (err) { - mlx4_err(mdev, "Failed restarting port:%d\n", + en_err(priv, "Failed restarting port:%d\n", priv->port); queue_work(mdev->workqueue, &priv->watchdog_task); } @@ -952,6 +934,7 @@ static const struct net_device_ops mlx4_netdev_ops = { .ndo_open = mlx4_en_open, .ndo_stop = mlx4_en_close, .ndo_start_xmit = mlx4_en_xmit, + .ndo_select_queue = mlx4_en_select_queue, .ndo_get_stats = mlx4_en_get_stats, .ndo_set_multicast_list = mlx4_en_set_multicast, .ndo_set_mac_address = mlx4_en_set_mac, @@ -974,7 +957,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, int i; int err; - dev = alloc_etherdev(sizeof(struct mlx4_en_priv)); + dev = alloc_etherdev_mq(sizeof(struct mlx4_en_priv), prof->tx_ring_num); if (dev == NULL) { mlx4_err(mdev, "Net device allocation failed\n"); return -ENOMEM; @@ -1012,7 +995,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port]; priv->mac = mdev->dev->caps.def_mac[priv->port]; if (ILLEGAL_MAC(priv->mac)) { - mlx4_err(mdev, "Port: %d, invalid mac burned: 0x%llx, quiting\n", + en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n", priv->port, priv->mac); err = -EINVAL; goto out; @@ -1031,19 +1014,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, err = mlx4_alloc_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE); if (err) { - mlx4_err(mdev, "Failed to allocate page for rx qps\n"); + en_err(priv, "Failed to allocate page for rx qps\n"); goto out; } priv->allocated = 1; - /* Populate Tx priority mappings */ - mlx4_en_set_prio_map(priv, priv->tx_prio_map, prof->tx_ring_num); - /* * Initialize netdev entry points */ dev->netdev_ops = &mlx4_netdev_ops; dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT; + dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS; SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops); @@ -1057,7 +1038,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, * Set driver features */ dev->features |= NETIF_F_SG; + dev->vlan_features |= NETIF_F_SG; dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | @@ -1067,6 +1050,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, if (mdev->LSO_support) { dev->features |= NETIF_F_TSO; dev->features |= NETIF_F_TSO6; + dev->vlan_features |= NETIF_F_TSO; + dev->vlan_features |= NETIF_F_TSO6; } mdev->pndev[port] = dev; @@ -1074,9 +1059,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, netif_carrier_off(dev); err = register_netdev(dev); if (err) { - mlx4_err(mdev, "Netdev registration failed\n"); + en_err(priv, "Netdev registration failed for port %d\n", port); goto out; } + + en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num); + en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num); + priv->registered = 1; queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); return 0; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 9ee873e872b3..5a14899c1e25 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -114,8 +114,8 @@ static int mlx4_en_init_allocator(struct mlx4_en_priv *priv, goto out; page_alloc->offset = priv->frag_info[i].frag_align; - mlx4_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n", - i, page_alloc->page); + en_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n", + i, page_alloc->page); } return 0; @@ -136,8 +136,8 @@ static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv, for (i = 0; i < priv->num_frags; i++) { page_alloc = &ring->page_alloc[i]; - mlx4_dbg(DRV, priv, "Freeing allocator:%d count:%d\n", - i, page_count(page_alloc->page)); + en_dbg(DRV, priv, "Freeing allocator:%d count:%d\n", + i, page_count(page_alloc->page)); put_page(page_alloc->page); page_alloc->page = NULL; @@ -202,12 +202,34 @@ static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring) *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff); } -static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) +static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv, + struct mlx4_en_rx_ring *ring, + int index) { struct mlx4_en_dev *mdev = priv->mdev; + struct skb_frag_struct *skb_frags; + struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride); + dma_addr_t dma; + int nr; + + skb_frags = ring->rx_info + (index << priv->log_rx_info); + for (nr = 0; nr < priv->num_frags; nr++) { + en_dbg(DRV, priv, "Freeing fragment:%d\n", nr); + dma = be64_to_cpu(rx_desc->data[nr].addr); + + en_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma); + pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, + PCI_DMA_FROMDEVICE); + put_page(skb_frags[nr].page); + } +} + +static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) +{ struct mlx4_en_rx_ring *ring; int ring_ind; int buf_ind; + int new_size; for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) { for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { @@ -216,22 +238,34 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) if (mlx4_en_prepare_rx_desc(priv, ring, ring->actual_size)) { if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) { - mlx4_err(mdev, "Failed to allocate " - "enough rx buffers\n"); + en_err(priv, "Failed to allocate " + "enough rx buffers\n"); return -ENOMEM; } else { - if (netif_msg_rx_err(priv)) - mlx4_warn(mdev, - "Only %d buffers allocated\n", - ring->actual_size); - goto out; + new_size = rounddown_pow_of_two(ring->actual_size); + en_warn(priv, "Only %d buffers allocated " + "reducing ring size to %d", + ring->actual_size, new_size); + goto reduce_rings; } } ring->actual_size++; ring->prod++; } } -out: + return 0; + +reduce_rings: + for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { + ring = &priv->rx_ring[ring_ind]; + while (ring->actual_size > new_size) { + ring->actual_size--; + ring->prod--; + mlx4_en_free_rx_desc(priv, ring, ring->actual_size); + } + ring->size_mask = ring->actual_size - 1; + } + return 0; } @@ -247,15 +281,14 @@ static int mlx4_en_fill_rx_buf(struct net_device *dev, ring->size_mask); if (err) { if (netif_msg_rx_err(priv)) - mlx4_warn(priv->mdev, - "Failed preparing rx descriptor\n"); + en_warn(priv, "Failed preparing rx descriptor\n"); priv->port_stats.rx_alloc_failed++; break; } ++num; ++ring->prod; } - if ((u32) (ring->prod - ring->cons) == ring->size) + if ((u32) (ring->prod - ring->cons) == ring->actual_size) ring->full = 1; return num; @@ -264,33 +297,17 @@ static int mlx4_en_fill_rx_buf(struct net_device *dev, static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring) { - struct mlx4_en_dev *mdev = priv->mdev; - struct skb_frag_struct *skb_frags; - struct mlx4_en_rx_desc *rx_desc; - dma_addr_t dma; int index; - int nr; - mlx4_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n", - ring->cons, ring->prod); + en_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n", + ring->cons, ring->prod); /* Unmap and free Rx buffers */ - BUG_ON((u32) (ring->prod - ring->cons) > ring->size); + BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size); while (ring->cons != ring->prod) { index = ring->cons & ring->size_mask; - rx_desc = ring->buf + (index << ring->log_stride); - skb_frags = ring->rx_info + (index << priv->log_rx_info); - mlx4_dbg(DRV, priv, "Processing descriptor:%d\n", index); - - for (nr = 0; nr < priv->num_frags; nr++) { - mlx4_dbg(DRV, priv, "Freeing fragment:%d\n", nr); - dma = be64_to_cpu(rx_desc->data[nr].addr); - - mlx4_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma); - pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, - PCI_DMA_FROMDEVICE); - put_page(skb_frags[nr].page); - } + en_dbg(DRV, priv, "Processing descriptor:%d\n", index); + mlx4_en_free_rx_desc(priv, ring, index); ++ring->cons; } } @@ -354,10 +371,10 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, sizeof(struct skb_frag_struct)); ring->rx_info = vmalloc(tmp); if (!ring->rx_info) { - mlx4_err(mdev, "Failed allocating rx_info ring\n"); + en_err(priv, "Failed allocating rx_info ring\n"); return -ENOMEM; } - mlx4_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n", + en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n", ring->rx_info, tmp); err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, @@ -367,7 +384,7 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, err = mlx4_en_map_buffer(&ring->wqres.buf); if (err) { - mlx4_err(mdev, "Failed to map RX buffer\n"); + en_err(priv, "Failed to map RX buffer\n"); goto err_hwq; } ring->buf = ring->wqres.buf.direct.buf; @@ -385,7 +402,7 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, sizeof(struct net_lro_desc), GFP_KERNEL); if (!ring->lro.lro_arr) { - mlx4_err(mdev, "Failed to allocate lro array\n"); + en_err(priv, "Failed to allocate lro array\n"); goto err_map; } ring->lro.get_frag_header = mlx4_en_get_frag_header; @@ -436,7 +453,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) /* Initialize page allocators */ err = mlx4_en_init_allocator(priv, ring); if (err) { - mlx4_err(mdev, "Failed initializing ring allocator\n"); + en_err(priv, "Failed initializing ring allocator\n"); ring_ind--; goto err_allocator; } @@ -454,7 +471,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) mlx4_en_update_rx_prod_db(ring); /* Configure SRQ representing the ring */ - ring->srq.max = ring->size; + ring->srq.max = ring->actual_size; ring->srq.max_gs = max_gs; ring->srq.wqe_shift = ilog2(ring->stride); @@ -467,7 +484,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) err = mlx4_srq_alloc(mdev->dev, mdev->priv_pdn, &ring->wqres.mtt, ring->wqres.db.dma, &ring->srq); if (err){ - mlx4_err(mdev, "Failed to allocate srq\n"); + en_err(priv, "Failed to allocate srq\n"); ring_ind--; goto err_srq; } @@ -582,7 +599,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN); if (!skb) { - mlx4_dbg(RX_ERR, priv, "Failed allocating skb\n"); + en_dbg(RX_ERR, priv, "Failed allocating skb\n"); return NULL; } skb->dev = priv->dev; @@ -661,7 +678,6 @@ static void mlx4_en_copy_desc(struct mlx4_en_priv *priv, int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_cqe *cqe; struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; struct skb_frag_struct *skb_frags; @@ -698,14 +714,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud /* Drop packet on bad receive or bad checksum */ if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_CQE_OPCODE_ERROR)) { - mlx4_err(mdev, "CQE completed in error - vendor " + en_err(priv, "CQE completed in error - vendor " "syndrom:%d syndrom:%d\n", ((struct mlx4_err_cqe *) cqe)->vendor_err_syndrome, ((struct mlx4_err_cqe *) cqe)->syndrome); goto next; } if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) { - mlx4_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n"); + en_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n"); goto next; } @@ -855,7 +871,7 @@ static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 u16 res = MLX4_EN_ALLOC_SIZE % stride; u16 offset = MLX4_EN_ALLOC_SIZE - stride - res + align; - mlx4_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d " + en_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d " "res:%d offset:%d\n", stride, align, res, offset); return offset; } @@ -900,10 +916,10 @@ void mlx4_en_calc_rx_buf(struct net_device *dev) priv->rx_skb_size = eff_mtu; priv->log_rx_info = ROUNDUP_LOG2(i * sizeof(struct skb_frag_struct)); - mlx4_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d " + en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d " "num_frags:%d):\n", eff_mtu, priv->num_frags); for (i = 0; i < priv->num_frags; i++) { - mlx4_dbg(DRV, priv, " frag:%d - size:%d prefix:%d align:%d " + en_dbg(DRV, priv, " frag:%d - size:%d prefix:%d align:%d " "stride:%d last_offset:%d\n", i, priv->frag_info[i].frag_size, priv->frag_info[i].frag_prefix_size, @@ -923,12 +939,12 @@ void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv, int i; rss_map->size = roundup_pow_of_two(num_entries); - mlx4_dbg(DRV, priv, "Setting default RSS map of %d entires\n", - rss_map->size); + 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; - mlx4_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]); + en_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]); } } @@ -943,13 +959,13 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, context = kmalloc(sizeof *context , GFP_KERNEL); if (!context) { - mlx4_err(mdev, "Failed to allocate qp context\n"); + en_err(priv, "Failed to allocate qp context\n"); return -ENOMEM; } err = mlx4_qp_alloc(mdev->dev, qpn, qp); if (err) { - mlx4_err(mdev, "Failed to allocate qp #%d\n", qpn); + en_err(priv, "Failed to allocate qp #%x\n", qpn); goto out; } qp->event = mlx4_en_sqp_event; @@ -981,12 +997,11 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) int err = 0; int good_qps = 0; - mlx4_dbg(DRV, priv, "Configuring rss steering for port %u\n", priv->port); + 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); if (err) { - mlx4_err(mdev, "Failed reserving %d qps for port %u\n", - rss_map->size, priv->port); + en_err(priv, "Failed reserving %d qps\n", rss_map->size); return err; } @@ -1006,13 +1021,13 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) /* Configure RSS indirection qp */ err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn); if (err) { - mlx4_err(mdev, "Failed to reserve range for RSS " - "indirection qp\n"); + en_err(priv, "Failed to reserve range for RSS " + "indirection qp\n"); goto rss_err; } err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp); if (err) { - mlx4_err(mdev, "Failed to allocate RSS indirection QP\n"); + en_err(priv, "Failed to allocate RSS indirection QP\n"); goto reserve_err; } rss_map->indir_qp.event = mlx4_en_sqp_event; diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index e5c98a98ad37..5dc7466ad035 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -68,15 +68,15 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, tmp = size * sizeof(struct mlx4_en_tx_info); ring->tx_info = vmalloc(tmp); if (!ring->tx_info) { - mlx4_err(mdev, "Failed allocating tx_info ring\n"); + en_err(priv, "Failed allocating tx_info ring\n"); return -ENOMEM; } - mlx4_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n", + en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n", ring->tx_info, tmp); ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL); if (!ring->bounce_buf) { - mlx4_err(mdev, "Failed allocating bounce buffer\n"); + en_err(priv, "Failed allocating bounce buffer\n"); err = -ENOMEM; goto err_tx; } @@ -85,31 +85,31 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size, 2 * PAGE_SIZE); if (err) { - mlx4_err(mdev, "Failed allocating hwq resources\n"); + en_err(priv, "Failed allocating hwq resources\n"); goto err_bounce; } err = mlx4_en_map_buffer(&ring->wqres.buf); if (err) { - mlx4_err(mdev, "Failed to map TX buffer\n"); + en_err(priv, "Failed to map TX buffer\n"); goto err_hwq_res; } ring->buf = ring->wqres.buf.direct.buf; - mlx4_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d " - "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size, - ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map); + en_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d " + "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size, + ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map); err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn); if (err) { - mlx4_err(mdev, "Failed reserving qp for tx ring.\n"); + en_err(priv, "Failed reserving qp for tx ring.\n"); goto err_map; } err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp); if (err) { - mlx4_err(mdev, "Failed allocating qp %d\n", ring->qpn); + en_err(priv, "Failed allocating qp %d\n", ring->qpn); goto err_reserve; } ring->qp.event = mlx4_en_sqp_event; @@ -135,7 +135,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring) { struct mlx4_en_dev *mdev = priv->mdev; - mlx4_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn); + en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn); mlx4_qp_remove(mdev->dev, &ring->qp); mlx4_qp_free(mdev->dev, &ring->qp); @@ -274,12 +274,12 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring) /* Skip last polled descriptor */ ring->cons += ring->last_nr_txbb; - mlx4_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n", + en_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n", ring->cons, ring->prod); if ((u32) (ring->prod - ring->cons) > ring->size) { if (netif_msg_tx_err(priv)) - mlx4_warn(priv->mdev, "Tx consumer passed producer!\n"); + en_warn(priv, "Tx consumer passed producer!\n"); return 0; } @@ -292,39 +292,11 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring) } if (cnt) - mlx4_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt); + en_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt); return cnt; } -void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num) -{ - int block = 8 / ring_num; - int extra = 8 - (block * ring_num); - int num = 0; - u16 ring = 1; - int prio; - - if (ring_num == 1) { - for (prio = 0; prio < 8; prio++) - prio_map[prio] = 0; - return; - } - - for (prio = 0; prio < 8; prio++) { - if (extra && (num == block + 1)) { - ring++; - num = 0; - extra--; - } else if (!extra && (num == block)) { - ring++; - num = 0; - } - prio_map[prio] = ring; - mlx4_dbg(DRV, priv, " prio:%d --> ring:%d\n", prio, ring); - num++; - } -} static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) { @@ -386,18 +358,8 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) if (unlikely(ring->blocked)) { if ((u32) (ring->prod - ring->cons) <= ring->size - HEADROOM - MAX_DESC_TXBBS) { - - /* TODO: support multiqueue netdevs. Currently, we block - * when *any* ring is full. Note that: - * - 2 Tx rings can unblock at the same time and call - * netif_wake_queue(), which is OK since this - * operation is idempotent. - * - We might wake the queue just after another ring - * stopped it. This is no big deal because the next - * transmission on that ring would stop the queue. - */ ring->blocked = 0; - netif_wake_queue(dev); + netif_tx_wake_queue(netdev_get_tx_queue(dev, cq->ring)); priv->port_stats.wake_queue++; } } @@ -539,7 +501,6 @@ static int get_real_size(struct sk_buff *skb, struct net_device *dev, int *lso_header_size) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; int real_size; if (skb_is_gso(skb)) { @@ -553,14 +514,14 @@ static int get_real_size(struct sk_buff *skb, struct net_device *dev, real_size += DS_SIZE; else { if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "Non-linear headers\n"); + en_warn(priv, "Non-linear headers\n"); dev_kfree_skb_any(skb); return 0; } } if (unlikely(*lso_header_size > MAX_LSO_HDR_SIZE)) { if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "LSO header size too big\n"); + en_warn(priv, "LSO header size too big\n"); dev_kfree_skb_any(skb); return 0; } @@ -617,21 +578,20 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f; } -static int get_vlan_info(struct mlx4_en_priv *priv, struct sk_buff *skb, - u16 *vlan_tag) +u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb) { - int tx_ind; + struct mlx4_en_priv *priv = netdev_priv(dev); + u16 vlan_tag = 0; - /* Obtain VLAN information if present */ - if (priv->vlgrp && vlan_tx_tag_present(skb)) { - *vlan_tag = vlan_tx_tag_get(skb); - /* Set the Tx ring to use according to vlan priority */ - tx_ind = priv->tx_prio_map[*vlan_tag >> 13]; - } else { - *vlan_tag = 0; - tx_ind = 0; + /* If we support per priority flow control and the packet contains + * a vlan tag, send the packet to the TX ring assigned to that priority + */ + if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) { + vlan_tag = vlan_tx_tag_get(skb); + return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13); } - return tx_ind; + + return skb_tx_hash(dev, skb); } int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) @@ -651,7 +611,7 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) dma_addr_t dma; u32 index; __be32 op_own; - u16 vlan_tag; + u16 vlan_tag = 0; int i; int lso_header_size; void *fragptr; @@ -669,20 +629,21 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) nr_txbb = desc_size / TXBB_SIZE; if (unlikely(nr_txbb > MAX_DESC_TXBBS)) { if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "Oversized header or SG list\n"); + en_warn(priv, "Oversized header or SG list\n"); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } - tx_ind = get_vlan_info(priv, skb, &vlan_tag); + tx_ind = skb->queue_mapping; ring = &priv->tx_ring[tx_ind]; + if (priv->vlgrp && vlan_tx_tag_present(skb)) + vlan_tag = vlan_tx_tag_get(skb); /* Check available TXBBs And 2K spare for prefetch */ if (unlikely(((int)(ring->prod - ring->cons)) > ring->size - HEADROOM - MAX_DESC_TXBBS)) { - /* every full Tx ring stops queue. - * TODO: implement multi-queue support (per-queue stop) */ - netif_stop_queue(dev); + /* every full Tx ring stops queue */ + netif_tx_stop_queue(netdev_get_tx_queue(dev, tx_ind)); ring->blocked = 1; priv->port_stats.queue_stopped++; @@ -695,7 +656,7 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) /* Now that we know what Tx ring to use */ if (unlikely(!priv->port_up)) { if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "xmit: port down!\n"); + en_warn(priv, "xmit: port down!\n"); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -819,7 +780,6 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) /* Ring doorbell! */ wmb(); writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL); - dev->trans_start = jiffies; /* Poll CQ here */ mlx4_en_xmit_poll(priv, tx_ind); diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index ce064e324200..b9ceddde46c0 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -625,8 +625,10 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE, (dev->flags & MLX4_FLAG_MSI_X) ? i : 0, &priv->eq_table.eq[i]); - if (err) + if (err) { + --i; goto err_out_unmap; + } } err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE, diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index ef840abbcd39..d43a9e4c2aea 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -49,26 +49,42 @@ #include "en_port.h" #define DRV_NAME "mlx4_en" -#define DRV_VERSION "1.4.0" -#define DRV_RELDATE "Sep 2008" +#define DRV_VERSION "1.4.1.1" +#define DRV_RELDATE "June 2009" #define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN) -#define mlx4_dbg(mlevel, priv, format, arg...) \ - if (NETIF_MSG_##mlevel & priv->msg_enable) \ - printk(KERN_DEBUG "%s %s: " format , DRV_NAME ,\ - (dev_name(&priv->mdev->pdev->dev)) , ## arg) +#define en_print(level, priv, format, arg...) \ + { \ + if ((priv)->registered) \ + printk(level "%s: %s: " format, DRV_NAME, \ + (priv->dev)->name, ## arg); \ + else \ + printk(level "%s: %s: Port %d: " format, \ + DRV_NAME, dev_name(&priv->mdev->pdev->dev), \ + (priv)->port, ## arg); \ + } + +#define en_dbg(mlevel, priv, format, arg...) \ + { \ + if (NETIF_MSG_##mlevel & priv->msg_enable) \ + en_print(KERN_DEBUG, priv, format, ## arg) \ + } +#define en_warn(priv, format, arg...) \ + en_print(KERN_WARNING, priv, format, ## arg) +#define en_err(priv, format, arg...) \ + en_print(KERN_ERR, priv, format, ## arg) #define mlx4_err(mdev, format, arg...) \ printk(KERN_ERR "%s %s: " format , DRV_NAME ,\ - (dev_name(&mdev->pdev->dev)) , ## arg) + dev_name(&mdev->pdev->dev) , ## arg) #define mlx4_info(mdev, format, arg...) \ printk(KERN_INFO "%s %s: " format , DRV_NAME ,\ - (dev_name(&mdev->pdev->dev)) , ## arg) + dev_name(&mdev->pdev->dev) , ## arg) #define mlx4_warn(mdev, format, arg...) \ printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\ - (dev_name(&mdev->pdev->dev)) , ## arg) + dev_name(&mdev->pdev->dev) , ## arg) /* * Device constants @@ -123,12 +139,14 @@ enum { #define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES) #define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE) -#define MLX4_EN_TX_RING_NUM 9 -#define MLX4_EN_DEF_TX_RING_SIZE 1024 +#define MLX4_EN_SMALL_PKT_SIZE 64 +#define MLX4_EN_NUM_TX_RINGS 8 +#define MLX4_EN_NUM_PPP_RINGS 8 +#define MLX4_EN_DEF_TX_RING_SIZE 512 #define MLX4_EN_DEF_RX_RING_SIZE 1024 -/* Target number of bytes to coalesce with interrupt moderation */ -#define MLX4_EN_RX_COAL_TARGET 0x20000 +/* Target number of packets to coalesce with interrupt moderation */ +#define MLX4_EN_RX_COAL_TARGET 44 #define MLX4_EN_RX_COAL_TIME 0x10 #define MLX4_EN_TX_COAL_PKTS 5 @@ -462,7 +480,6 @@ struct mlx4_en_priv { int base_qpn; struct mlx4_en_rss_map rss_map; - u16 tx_prio_map[8]; u32 flags; #define MLX4_EN_FLAG_PROMISC 0x1 u32 tx_ring_num; @@ -500,8 +517,6 @@ void mlx4_en_stop_port(struct net_device *dev); void mlx4_en_free_resources(struct mlx4_en_priv *priv); int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); -int mlx4_en_get_profile(struct mlx4_en_dev *mdev); - int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, int entries, int ring, enum cq_type mode); void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); @@ -512,6 +527,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); void mlx4_en_poll_tx_cq(unsigned long data); void mlx4_en_tx_irq(struct mlx4_cq *mcq); +u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb); int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring, @@ -546,7 +562,6 @@ 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); -void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num); 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/mlx4/mr.c b/drivers/net/mlx4/mr.c index 3b8973d19933..5887e4764d22 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -402,7 +402,8 @@ static int mlx4_write_mtt_chunk(struct mlx4_dev *dev, struct mlx4_mtt *mtt, for (i = 0; i < npages; ++i) mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT); - dma_sync_single(&dev->pdev->dev, dma_handle, npages * sizeof (u64), DMA_TO_DEVICE); + dma_sync_single_for_cpu(&dev->pdev->dev, dma_handle, + npages * sizeof (u64), DMA_TO_DEVICE); return 0; } @@ -549,8 +550,8 @@ int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list for (i = 0; i < npages; ++i) fmr->mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT); - dma_sync_single(&dev->pdev->dev, fmr->dma_handle, - npages * sizeof(u64), DMA_TO_DEVICE); + dma_sync_single_for_cpu(&dev->pdev->dev, fmr->dma_handle, + npages * sizeof(u64), DMA_TO_DEVICE); fmr->mpt->key = cpu_to_be32(key); fmr->mpt->lkey = cpu_to_be32(key); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 6bb5af35eda6..b4e18a58cb1b 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -55,6 +55,7 @@ #include #include #include +#include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.4"; @@ -88,7 +89,24 @@ static char mv643xx_eth_driver_version[] = "1.4"; #define MAC_ADDR_LOW 0x0014 #define MAC_ADDR_HIGH 0x0018 #define SDMA_CONFIG 0x001c +#define TX_BURST_SIZE_16_64BIT 0x01000000 +#define TX_BURST_SIZE_4_64BIT 0x00800000 +#define BLM_TX_NO_SWAP 0x00000020 +#define BLM_RX_NO_SWAP 0x00000010 +#define RX_BURST_SIZE_16_64BIT 0x00000008 +#define RX_BURST_SIZE_4_64BIT 0x00000004 #define PORT_SERIAL_CONTROL 0x003c +#define SET_MII_SPEED_TO_100 0x01000000 +#define SET_GMII_SPEED_TO_1000 0x00800000 +#define SET_FULL_DUPLEX_MODE 0x00200000 +#define MAX_RX_PACKET_9700BYTE 0x000a0000 +#define DISABLE_AUTO_NEG_SPEED_GMII 0x00002000 +#define DO_NOT_FORCE_LINK_FAIL 0x00000400 +#define SERIAL_PORT_CONTROL_RESERVED 0x00000200 +#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL 0x00000008 +#define DISABLE_AUTO_NEG_FOR_DUPLEX 0x00000004 +#define FORCE_LINK_PASS 0x00000002 +#define SERIAL_PORT_ENABLE 0x00000001 #define PORT_STATUS 0x0044 #define TX_FIFO_EMPTY 0x00000400 #define TX_IN_PROGRESS 0x00000080 @@ -106,7 +124,9 @@ static char mv643xx_eth_driver_version[] = "1.4"; #define TX_BW_BURST 0x005c #define INT_CAUSE 0x0060 #define INT_TX_END 0x07f80000 +#define INT_TX_END_0 0x00080000 #define INT_RX 0x000003fc +#define INT_RX_0 0x00000004 #define INT_EXT 0x00000002 #define INT_CAUSE_EXT 0x0064 #define INT_EXT_LINK_PHY 0x00110000 @@ -135,15 +155,8 @@ static char mv643xx_eth_driver_version[] = "1.4"; /* - * SDMA configuration register. + * SDMA configuration register default value. */ -#define RX_BURST_SIZE_4_64BIT (2 << 1) -#define RX_BURST_SIZE_16_64BIT (4 << 1) -#define BLM_RX_NO_SWAP (1 << 4) -#define BLM_TX_NO_SWAP (1 << 5) -#define TX_BURST_SIZE_4_64BIT (2 << 22) -#define TX_BURST_SIZE_16_64BIT (4 << 22) - #if defined(__BIG_ENDIAN) #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ (RX_BURST_SIZE_4_64BIT | \ @@ -160,22 +173,11 @@ static char mv643xx_eth_driver_version[] = "1.4"; /* - * Port serial control register. + * Misc definitions. */ -#define SET_MII_SPEED_TO_100 (1 << 24) -#define SET_GMII_SPEED_TO_1000 (1 << 23) -#define SET_FULL_DUPLEX_MODE (1 << 21) -#define MAX_RX_PACKET_9700BYTE (5 << 17) -#define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13) -#define DO_NOT_FORCE_LINK_FAIL (1 << 10) -#define SERIAL_PORT_CONTROL_RESERVED (1 << 9) -#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1 << 3) -#define DISABLE_AUTO_NEG_FOR_DUPLEX (1 << 2) -#define FORCE_LINK_PASS (1 << 1) -#define SERIAL_PORT_ENABLE (1 << 0) - -#define DEFAULT_RX_QUEUE_SIZE 128 -#define DEFAULT_TX_QUEUE_SIZE 256 +#define DEFAULT_RX_QUEUE_SIZE 128 +#define DEFAULT_TX_QUEUE_SIZE 256 +#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) /* @@ -393,6 +395,7 @@ struct mv643xx_eth_private { struct work_struct tx_timeout_task; struct napi_struct napi; + u32 int_mask; u8 oom; u8 work_link; u8 work_tx; @@ -651,23 +654,20 @@ static int rxq_refill(struct rx_queue *rxq, int budget) refilled = 0; while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { struct sk_buff *skb; - int unaligned; int rx; struct rx_desc *rx_desc; skb = __skb_dequeue(&mp->rx_recycle); if (skb == NULL) - skb = dev_alloc_skb(mp->skb_size + - dma_get_cache_alignment() - 1); + skb = dev_alloc_skb(mp->skb_size); if (skb == NULL) { mp->oom = 1; goto oom; } - unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1); - if (unaligned) - skb_reserve(skb, dma_get_cache_alignment() - unaligned); + if (SKB_DMA_REALIGN) + skb_reserve(skb, SKB_DMA_REALIGN); refilled++; rxq->rx_desc_count++; @@ -969,8 +969,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) if (skb != NULL) { if (skb_queue_len(&mp->rx_recycle) < mp->rx_ring_size && - skb_recycle_check(skb, mp->skb_size + - dma_get_cache_alignment() - 1)) + skb_recycle_check(skb, mp->skb_size)) __skb_queue_head(&mp->rx_recycle, skb); else dev_kfree_skb(skb); @@ -1723,20 +1722,20 @@ static void uc_addr_set(struct mv643xx_eth_private *mp, unsigned char *addr) static u32 uc_addr_filter_mask(struct net_device *dev) { - struct dev_addr_list *uc_ptr; + struct netdev_hw_addr *ha; u32 nibbles; if (dev->flags & IFF_PROMISC) return 0; nibbles = 1 << (dev->dev_addr[5] & 0x0f); - for (uc_ptr = dev->uc_list; uc_ptr != NULL; uc_ptr = uc_ptr->next) { - if (memcmp(dev->dev_addr, uc_ptr->da_addr, 5)) + list_for_each_entry(ha, &dev->uc_list, list) { + if (memcmp(dev->dev_addr, ha->addr, 5)) return 0; - if ((dev->dev_addr[5] ^ uc_ptr->da_addr[5]) & 0xf0) + if ((dev->dev_addr[5] ^ ha->addr[5]) & 0xf0) return 0; - nibbles |= 1 << (uc_ptr->da_addr[5] & 0x0f); + nibbles |= 1 << (ha->addr[5] & 0x0f); } return nibbles; @@ -1810,7 +1809,6 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev) if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { int port_num; u32 accept; - int i; oom: port_num = mp->port_num; @@ -2067,15 +2065,16 @@ static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp) u32 int_cause; u32 int_cause_ext; - int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT); + int_cause = rdlp(mp, INT_CAUSE) & mp->int_mask; if (int_cause == 0) return 0; int_cause_ext = 0; - if (int_cause & INT_EXT) + if (int_cause & INT_EXT) { + int_cause &= ~INT_EXT; int_cause_ext = rdlp(mp, INT_CAUSE_EXT); + } - int_cause &= INT_TX_END | INT_RX; if (int_cause) { wrlp(mp, INT_CAUSE, ~int_cause); mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & @@ -2182,6 +2181,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) if (mp->work_link) { mp->work_link = 0; handle_link_event(mp); + work_done++; continue; } @@ -2220,7 +2220,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) if (mp->oom) mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); napi_complete(napi); - wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); + wrlp(mp, INT_MASK, mp->int_mask); } return work_done; @@ -2341,6 +2341,14 @@ static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) * size field are ignored by the hardware. */ mp->skb_size = (skb_size + 7) & ~7; + + /* + * If NET_SKB_PAD is smaller than a cache line, + * netdev_alloc_skb() will cause skb->data to be misaligned + * to a cache line boundary. If this is the case, include + * some extra space to allow re-aligning the data area. + */ + mp->skb_size += SKB_DMA_REALIGN; } static int mv643xx_eth_open(struct net_device *dev) @@ -2366,6 +2374,8 @@ static int mv643xx_eth_open(struct net_device *dev) skb_queue_head_init(&mp->rx_recycle); + mp->int_mask = INT_EXT; + for (i = 0; i < mp->rxq_count; i++) { err = rxq_init(mp, i); if (err) { @@ -2375,6 +2385,7 @@ static int mv643xx_eth_open(struct net_device *dev) } rxq_refill(mp->rxq + i, INT_MAX); + mp->int_mask |= INT_RX_0 << i; } if (mp->oom) { @@ -2389,12 +2400,13 @@ static int mv643xx_eth_open(struct net_device *dev) txq_deinit(mp->txq + i); goto out_free; } + mp->int_mask |= INT_TX_END_0 << i; } port_start(mp); wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); - wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); + wrlp(mp, INT_MASK, mp->int_mask); return 0; @@ -2538,7 +2550,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev) mv643xx_eth_irq(dev->irq, dev); - wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); + wrlp(mp, INT_MASK, mp->int_mask); } #endif diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c index 435e5a847c43..93c709d63e2f 100644 --- a/drivers/net/mvme147.c +++ b/drivers/net/mvme147.c @@ -57,6 +57,17 @@ typedef void (*writerap_t)(void *, unsigned short); typedef void (*writerdp_t)(void *, unsigned short); typedef unsigned short (*readrdp_t)(void *); +static const struct net_device_ops lance_netdev_ops = { + .ndo_open = m147lance_open, + .ndo_stop = m147lance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = lance_set_multicast, + .ndo_tx_timeout = lance_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + /* Initialise the one and only on-board 7990 */ struct net_device * __init mvme147lance_probe(int unit) { @@ -81,11 +92,7 @@ struct net_device * __init mvme147lance_probe(int unit) /* Fill the dev fields */ dev->base_addr = (unsigned long)MVME147_LANCE_BASE; - dev->open = &m147lance_open; - dev->stop = &m147lance_close; - dev->hard_start_xmit = &lance_start_xmit; - dev->set_multicast_list = &lance_set_multicast; - dev->tx_timeout = &lance_tx_timeout; + dev->netdev_ops = &lance_netdev_ops; dev->dma = 0; addr=(u_long *)ETHERNET_ADDRESS; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index f2c4a665e93f..1f6e36ea669e 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.4.4-1.401" +#define MYRI10GE_VERSION_STR "1.5.0-1.418" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -255,6 +255,7 @@ struct myri10ge_priv { u32 read_write_dma; u32 link_changes; u32 msg_enable; + unsigned int board_number; }; static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat"; @@ -266,6 +267,13 @@ static char *myri10ge_fw_name = NULL; module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); +#define MYRI10GE_MAX_BOARDS 8 +static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] = + {[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL }; +module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL, + 0444); +MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board"); + static int myri10ge_ecrc_enable = 1; module_param(myri10ge_ecrc_enable, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E"); @@ -319,10 +327,6 @@ static int myri10ge_debug = -1; /* defaults above */ module_param(myri10ge_debug, int, 0); MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); -static int myri10ge_lro = 1; -module_param(myri10ge_lro, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload"); - static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS; module_param(myri10ge_lro_max_pkts, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_lro_max_pkts, @@ -361,6 +365,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) __raw_writel((__force __u32) val, (__force void __iomem *)p); } +static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); + static int myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, struct myri10ge_cmd *data, int atomic) @@ -1290,7 +1296,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, remainder -= MYRI10GE_ALLOC_SIZE; } - if (mgp->csum_flag && myri10ge_lro) { + if (dev->features & NETIF_F_LRO) { rx_frags[0].page_offset += MXGEFW_PAD; rx_frags[0].size -= MXGEFW_PAD; len -= MXGEFW_PAD; @@ -1412,6 +1418,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) { struct myri10ge_rx_done *rx_done = &ss->rx_done; struct myri10ge_priv *mgp = ss->mgp; + struct net_device *netdev = mgp->dev; unsigned long rx_bytes = 0; unsigned long rx_packets = 0; unsigned long rx_ok; @@ -1445,7 +1452,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ss->stats.rx_packets += rx_packets; ss->stats.rx_bytes += rx_bytes; - if (myri10ge_lro) + if (netdev->features & NETIF_F_LRO) lro_flush_all(&rx_done->lro_mgr); /* restock receive rings if needed */ @@ -1686,7 +1693,7 @@ myri10ge_get_ringparam(struct net_device *netdev, ring->rx_mini_max_pending = mgp->ss[0].rx_small.mask + 1; ring->rx_max_pending = mgp->ss[0].rx_big.mask + 1; ring->rx_jumbo_max_pending = 0; - ring->tx_max_pending = mgp->ss[0].rx_small.mask + 1; + ring->tx_max_pending = mgp->ss[0].tx.mask + 1; ring->rx_mini_pending = ring->rx_mini_max_pending; ring->rx_pending = ring->rx_max_pending; ring->rx_jumbo_pending = ring->rx_jumbo_max_pending; @@ -1706,12 +1713,17 @@ static u32 myri10ge_get_rx_csum(struct net_device *netdev) static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) { struct myri10ge_priv *mgp = netdev_priv(netdev); + int err = 0; if (csum_enabled) mgp->csum_flag = MXGEFW_FLAGS_CKSUM; - else + else { + u32 flags = ethtool_op_get_flags(netdev); + err = ethtool_op_set_flags(netdev, (flags & ~ETH_FLAG_LRO)); mgp->csum_flag = 0; - return 0; + + } + return err; } static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled) @@ -1803,6 +1815,8 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, int slice; int i; + /* force stats update */ + (void)myri10ge_get_stats(netdev); for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) data[i] = ((unsigned long *)&mgp->stats)[i]; @@ -1892,7 +1906,9 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { .get_sset_count = myri10ge_get_sset_count, .get_ethtool_stats = myri10ge_get_ethtool_stats, .set_msglevel = myri10ge_set_msglevel, - .get_msglevel = myri10ge_get_msglevel + .get_msglevel = myri10ge_get_msglevel, + .get_flags = ethtool_op_get_flags, + .set_flags = ethtool_op_set_flags }; static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) @@ -2671,7 +2687,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) /* we are out of transmit resources */ tx->stop_queue++; netif_tx_stop_queue(netdev_queue); - return 1; + return NETDEV_TX_BUSY; } /* Setup checksum offloading, if needed */ @@ -2876,7 +2892,6 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) tx->stop_queue++; netif_tx_stop_queue(netdev_queue); } - dev->trans_start = jiffies; return 0; abort_linearize: @@ -2969,6 +2984,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) struct net_device_stats *stats = &mgp->stats; int i; + spin_lock(&mgp->stats_lock); memset(stats, 0, sizeof(*stats)); for (i = 0; i < mgp->num_slices; i++) { slice_stats = &mgp->ss[i].stats; @@ -2979,6 +2995,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) stats->rx_dropped += slice_stats->rx_dropped; stats->tx_dropped += slice_stats->tx_dropped; } + spin_unlock(&mgp->stats_lock); return stats; } @@ -3253,6 +3270,8 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) static void myri10ge_select_firmware(struct myri10ge_priv *mgp) { + int overridden = 0; + if (myri10ge_force_firmware == 0) { int link_width, exp_cap; u16 lnk; @@ -3286,10 +3305,18 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) } } if (myri10ge_fw_name != NULL) { - dev_info(&mgp->pdev->dev, "overriding firmware to %s\n", - myri10ge_fw_name); + overridden = 1; mgp->fw_name = myri10ge_fw_name; } + if (mgp->board_number < MYRI10GE_MAX_BOARDS && + myri10ge_fw_names[mgp->board_number] != NULL && + strlen(myri10ge_fw_names[mgp->board_number])) { + mgp->fw_name = myri10ge_fw_names[mgp->board_number]; + overridden = 1; + } + if (overridden) + dev_info(&mgp->pdev->dev, "overriding firmware to %s\n", + mgp->fw_name); } #ifdef CONFIG_PM @@ -3754,6 +3781,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int status = -ENXIO; int dac_enabled; unsigned hdr_offset, ss_offset; + static int board_number; netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES); if (netdev == NULL) { @@ -3770,6 +3798,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp->pause = myri10ge_flow_control; mgp->intr_coal_delay = myri10ge_intr_coal_delay; mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT); + mgp->board_number = board_number; init_waitqueue_head(&mgp->down_wq); if (pci_enable_device(pdev)) { @@ -3884,6 +3913,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (dac_enabled) netdev->features |= NETIF_F_HIGHDMA; + netdev->features |= NETIF_F_LRO; + + netdev->vlan_features |= mgp->features; + if (mgp->fw_ver_tiny < 37) + netdev->vlan_features &= ~NETIF_F_TSO6; + if (mgp->fw_ver_tiny < 32) + netdev->vlan_features &= ~NETIF_F_TSO; /* make sure we can get an irq, and that MSI can be * setup (if available). Also ensure netdev->irq @@ -3902,6 +3938,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, (unsigned long)mgp); + spin_lock_init(&mgp->stats_lock); SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); status = register_netdev(netdev); @@ -3919,6 +3956,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->irq, mgp->tx_boundary, mgp->fw_name, (mgp->wc_enabled ? "Enabled" : "Disabled")); + board_number++; return 0; abort_with_state: @@ -4008,6 +4046,8 @@ static struct pci_device_id myri10ge_pci_tbl[] = { {0}, }; +MODULE_DEVICE_TABLE(pci, myri10ge_pci_tbl); + static struct pci_driver myri10ge_driver = { .name = "myri10ge", .probe = myri10ge_probe, diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 9a802adba9a3..5f0758bda6b3 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -640,7 +640,7 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!TX_BUFFS_AVAIL(head, tail)) { DTX(("no buffs available, returning 1\n")); - return 1; + return NETDEV_TX_BUSY; } spin_lock_irqsave(&mp->irq_lock, flags); diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 7d83896b8c26..3fcebb70151c 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -374,7 +374,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, dev->ethtool_ops = &ne2k_pci_ethtool_ops; NS8390_init(dev, 0); - memcpy(dev->dev_addr, SA_prom, 6); + memcpy(dev->dev_addr, SA_prom, dev->addr_len); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); i = register_netdev(dev); diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index 6a843f7350ab..a00bbfb9aed0 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c @@ -104,7 +104,7 @@ static int __init ne3210_eisa_probe (struct device *device) } SET_NETDEV_DEV(dev, device); - device->driver_data = dev; + dev_set_drvdata(device, dev); ioaddr = edev->base_addr; if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) { @@ -225,7 +225,7 @@ static int __init ne3210_eisa_probe (struct device *device) static int __devexit ne3210_eisa_remove (struct device *device) { - struct net_device *dev = device->driver_data; + struct net_device *dev = dev_get_drvdata(device); unsigned long ioaddr = to_eisa_device (device)->base_addr; unregister_netdev (dev); diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index 1861d5bbd96b..946366dcc992 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -301,6 +301,17 @@ netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value) while (readl(NETX_MIIMU) & MIIMU_SNRDY); } +static const struct net_device_ops netx_eth_netdev_ops = { + .ndo_open = netx_eth_open, + .ndo_stop = netx_eth_close, + .ndo_start_xmit = netx_eth_hard_start_xmit, + .ndo_tx_timeout = netx_eth_timeout, + .ndo_set_multicast_list = netx_eth_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int netx_eth_enable(struct net_device *ndev) { struct netx_eth_priv *priv = netdev_priv(ndev); @@ -309,12 +320,8 @@ static int netx_eth_enable(struct net_device *ndev) ether_setup(ndev); - ndev->open = netx_eth_open; - ndev->stop = netx_eth_close; - ndev->hard_start_xmit = netx_eth_hard_start_xmit; - ndev->tx_timeout = netx_eth_timeout; + ndev->netdev_ops = &netx_eth_netdev_ops; ndev->watchdog_timeo = msecs_to_jiffies(5000); - ndev->set_multicast_list = netx_eth_set_multicast_list; priv->msg_enable = NETIF_MSG_LINK; priv->mii.phy_id_mask = 0x1f; diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index c40815169f35..ab11c2b3f0fe 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -34,10 +34,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -46,21 +42,16 @@ #include #include #include +#include #include #include -#include #include -#include -#include #include -#include #include #include -#include -#include #include "netxen_nic_hw.h" @@ -84,10 +75,10 @@ (sizeof(struct netxen_rx_buffer) * rds_ring->num_desc) #define STATUS_DESC_RINGSIZE(sds_ring) \ (sizeof(struct status_desc) * (sds_ring)->num_desc) -#define TX_BUFF_RINGSIZE(adapter) \ - (sizeof(struct netxen_cmd_buffer) * adapter->num_txd) -#define TX_DESC_RINGSIZE(adapter) \ - (sizeof(struct cmd_desc_type0) * adapter->num_txd) +#define TX_BUFF_RINGSIZE(tx_ring) \ + (sizeof(struct netxen_cmd_buffer) * tx_ring->num_desc) +#define TX_DESC_RINGSIZE(tx_ring) \ + (sizeof(struct cmd_desc_type0) * tx_ring->num_desc) #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) @@ -118,6 +109,7 @@ #define NX_P3_A2 0x30 #define NX_P3_B0 0x40 #define NX_P3_B1 0x41 +#define NX_P3_B2 0x42 #define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1) #define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0) @@ -203,18 +195,10 @@ #define MAX_RCV_DESCRIPTORS_10G 4096 #define MAX_JUMBO_RCV_DESCRIPTORS 1024 #define MAX_LRO_RCV_DESCRIPTORS 8 -#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS -#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS -#define MAX_RCV_DESC MAX_RCV_DESCRIPTORS -#define MAX_RCVSTATUS_DESC MAX_RCV_DESCRIPTORS -#define MAX_EPG_DESCRIPTORS (MAX_CMD_DESCRIPTORS * 8) -#define NUM_RCV_DESC (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \ - MAX_LRO_RCV_DESCRIPTORS) -#define MIN_TX_COUNT 4096 -#define MIN_RX_COUNT 4096 #define NETXEN_CTX_SIGNATURE 0xdee0 +#define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 +#define NETXEN_CTX_RESET 0xbad0 #define NETXEN_RCV_PRODUCER(ringid) (ringid) -#define MAX_FRAME_SIZE 0x10000 /* 64K MAX size for LSO */ #define PHAN_PEG_RCV_INITIALIZED 0xff01 #define PHAN_PEG_RCV_START_INITIALIZE 0xff00 @@ -253,12 +237,19 @@ typedef u32 netxen_ctx_msg; #define netxen_set_msg_opcode(config_word, val) \ ((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28) -struct netxen_rcv_context { - __le64 rcv_ring_addr; - __le32 rcv_ring_size; +struct netxen_rcv_ring { + __le64 addr; + __le32 size; __le32 rsrvd; }; +struct netxen_sts_ring { + __le64 addr; + __le32 size; + __le16 msi_index; + __le16 rsvd; +} ; + struct netxen_ring_ctx { /* one command ring */ @@ -268,13 +259,18 @@ struct netxen_ring_ctx { __le32 rsrvd; /* three receive rings */ - struct netxen_rcv_context rcv_ctx[3]; + struct netxen_rcv_ring rcv_rings[NUM_RCV_DESC_RINGS]; - /* one status ring */ __le64 sts_ring_addr; __le32 sts_ring_size; __le32 ctx_id; + + __le64 rsrvd_2[3]; + __le32 sts_ring_count; + __le32 rsrvd_3; + struct netxen_sts_ring sts_rings[NUM_STS_DESC_RINGS]; + } __attribute__ ((aligned(64))); /* @@ -373,6 +369,7 @@ struct rcv_desc { /* opcode field in status_desc */ #define NETXEN_NIC_RXPKT_DESC 0x04 #define NETXEN_OLD_RXPKT_DESC 0x3f +#define NETXEN_NIC_RESPONSE_DESC 0x05 /* for status field in status_desc */ #define STATUS_NEED_CKSUM (1) @@ -382,13 +379,11 @@ struct rcv_desc { #define STATUS_OWNER_HOST (0x1ULL << 56) #define STATUS_OWNER_PHANTOM (0x2ULL << 56) -/* Note: sizeof(status_desc) should always be a mutliple of 2 */ - -#define netxen_get_sts_desc_lro_cnt(status_desc) \ - ((status_desc)->lro & 0x7F) -#define netxen_get_sts_desc_lro_last_frag(status_desc) \ - (((status_desc)->lro & 0x80) >> 7) - +/* Status descriptor: + 0-3 port, 4-7 status, 8-11 type, 12-27 total_length + 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset + 53-55 desc_cnt, 56-57 owner, 58-63 opcode + */ #define netxen_get_sts_port(sts_data) \ ((sts_data) & 0x0F) #define netxen_get_sts_status(sts_data) \ @@ -403,41 +398,15 @@ struct rcv_desc { (((sts_data) >> 44) & 0x0F) #define netxen_get_sts_pkt_offset(sts_data) \ (((sts_data) >> 48) & 0x1F) +#define netxen_get_sts_desc_cnt(sts_data) \ + (((sts_data) >> 53) & 0x7) #define netxen_get_sts_opcode(sts_data) \ (((sts_data) >> 58) & 0x03F) struct status_desc { - /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length - 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset - 53-55 desc_cnt, 56-57 owner, 58-63 opcode - */ - __le64 status_desc_data; - union { - struct { - __le32 hash_value; - u8 hash_type; - u8 msg_type; - u8 unused; - union { - /* Bit pattern: 0-6 lro_count indicates frag - * sequence, 7 last_frag indicates last frag - */ - u8 lro; - - /* chained buffers */ - u8 nr_frags; - }; - }; - struct { - __le16 frag_handles[4]; - }; - }; + __le64 status_desc_data[2]; } __attribute__ ((aligned(16))); -enum { - NETXEN_RCV_PEG_0 = 0, - NETXEN_RCV_PEG_1 -}; /* The version of the main data structure */ #define NETXEN_BDINFO_VERSION 1 @@ -447,85 +416,35 @@ enum { /* Max number of Gig ports on a Phantom board */ #define NETXEN_MAX_PORTS 4 -typedef enum { - NETXEN_BRDTYPE_P1_BD = 0x0000, - NETXEN_BRDTYPE_P1_SB = 0x0001, - NETXEN_BRDTYPE_P1_SMAX = 0x0002, - NETXEN_BRDTYPE_P1_SOCK = 0x0003, +#define NETXEN_BRDTYPE_P1_BD 0x0000 +#define NETXEN_BRDTYPE_P1_SB 0x0001 +#define NETXEN_BRDTYPE_P1_SMAX 0x0002 +#define NETXEN_BRDTYPE_P1_SOCK 0x0003 - NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008, - NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009, - NETXEN_BRDTYPE_P2_SB35_4G = 0x000a, - NETXEN_BRDTYPE_P2_SB31_10G = 0x000b, - NETXEN_BRDTYPE_P2_SB31_2G = 0x000c, +#define NETXEN_BRDTYPE_P2_SOCK_31 0x0008 +#define NETXEN_BRDTYPE_P2_SOCK_35 0x0009 +#define NETXEN_BRDTYPE_P2_SB35_4G 0x000a +#define NETXEN_BRDTYPE_P2_SB31_10G 0x000b +#define NETXEN_BRDTYPE_P2_SB31_2G 0x000c - NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d, - NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e, - NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f, +#define NETXEN_BRDTYPE_P2_SB31_10G_IMEZ 0x000d +#define NETXEN_BRDTYPE_P2_SB31_10G_HMEZ 0x000e +#define NETXEN_BRDTYPE_P2_SB31_10G_CX4 0x000f - NETXEN_BRDTYPE_P3_REF_QG = 0x0021, - NETXEN_BRDTYPE_P3_HMEZ = 0x0022, - NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023, - NETXEN_BRDTYPE_P3_4_GB = 0x0024, - NETXEN_BRDTYPE_P3_IMEZ = 0x0025, - NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026, - NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027, - NETXEN_BRDTYPE_P3_XG_LOM = 0x0028, - NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029, - NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a, - NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b, - NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031, - NETXEN_BRDTYPE_P3_10G_XFP = 0x0032, - NETXEN_BRDTYPE_P3_10G_TP = 0x0080 - -} netxen_brdtype_t; - -typedef enum { - NETXEN_BRDMFG_INVENTEC = 1 -} netxen_brdmfg; - -typedef enum { - MEM_ORG_128Mbx4 = 0x0, /* DDR1 only */ - MEM_ORG_128Mbx8 = 0x1, /* DDR1 only */ - MEM_ORG_128Mbx16 = 0x2, /* DDR1 only */ - MEM_ORG_256Mbx4 = 0x3, - MEM_ORG_256Mbx8 = 0x4, - MEM_ORG_256Mbx16 = 0x5, - MEM_ORG_512Mbx4 = 0x6, - MEM_ORG_512Mbx8 = 0x7, - MEM_ORG_512Mbx16 = 0x8, - MEM_ORG_1Gbx4 = 0x9, - MEM_ORG_1Gbx8 = 0xa, - MEM_ORG_1Gbx16 = 0xb, - MEM_ORG_2Gbx4 = 0xc, - MEM_ORG_2Gbx8 = 0xd, - MEM_ORG_2Gbx16 = 0xe, - MEM_ORG_128Mbx32 = 0x10002, /* GDDR only */ - MEM_ORG_256Mbx32 = 0x10005 /* GDDR only */ -} netxen_mn_mem_org_t; - -typedef enum { - MEM_ORG_512Kx36 = 0x0, - MEM_ORG_1Mx36 = 0x1, - MEM_ORG_2Mx36 = 0x2 -} netxen_sn_mem_org_t; - -typedef enum { - MEM_DEPTH_4MB = 0x1, - MEM_DEPTH_8MB = 0x2, - MEM_DEPTH_16MB = 0x3, - MEM_DEPTH_32MB = 0x4, - MEM_DEPTH_64MB = 0x5, - MEM_DEPTH_128MB = 0x6, - MEM_DEPTH_256MB = 0x7, - MEM_DEPTH_512MB = 0x8, - MEM_DEPTH_1GB = 0x9, - MEM_DEPTH_2GB = 0xa, - MEM_DEPTH_4GB = 0xb, - MEM_DEPTH_8GB = 0xc, - MEM_DEPTH_16GB = 0xd, - MEM_DEPTH_32GB = 0xe -} netxen_mem_depth_t; +#define NETXEN_BRDTYPE_P3_REF_QG 0x0021 +#define NETXEN_BRDTYPE_P3_HMEZ 0x0022 +#define NETXEN_BRDTYPE_P3_10G_CX4_LP 0x0023 +#define NETXEN_BRDTYPE_P3_4_GB 0x0024 +#define NETXEN_BRDTYPE_P3_IMEZ 0x0025 +#define NETXEN_BRDTYPE_P3_10G_SFP_PLUS 0x0026 +#define NETXEN_BRDTYPE_P3_10000_BASE_T 0x0027 +#define NETXEN_BRDTYPE_P3_XG_LOM 0x0028 +#define NETXEN_BRDTYPE_P3_4_GB_MM 0x0029 +#define NETXEN_BRDTYPE_P3_10G_SFP_CT 0x002a +#define NETXEN_BRDTYPE_P3_10G_SFP_QT 0x002b +#define NETXEN_BRDTYPE_P3_10G_CX4 0x0031 +#define NETXEN_BRDTYPE_P3_10G_XFP 0x0032 +#define NETXEN_BRDTYPE_P3_10G_TP 0x0080 struct netxen_board_info { u32 header_version; @@ -676,17 +595,15 @@ struct netxen_new_user_info { #define PRIMARY_IMAGE_BAD 0xffffffff /* Flash memory map */ -typedef enum { - NETXEN_CRBINIT_START = 0, /* Crbinit section */ - NETXEN_BRDCFG_START = 0x4000, /* board config */ - NETXEN_INITCODE_START = 0x6000, /* pegtune code */ - NETXEN_BOOTLD_START = 0x10000, /* bootld */ - NETXEN_IMAGE_START = 0x43000, /* compressed image */ - NETXEN_SECONDARY_START = 0x200000, /* backup images */ - NETXEN_PXE_START = 0x3E0000, /* user defined region */ - NETXEN_USER_START = 0x3E8000, /* User defined region for new boards */ - NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */ -} netxen_flash_map_t; +#define NETXEN_CRBINIT_START 0 /* crbinit section */ +#define NETXEN_BRDCFG_START 0x4000 /* board config */ +#define NETXEN_INITCODE_START 0x6000 /* pegtune code */ +#define NETXEN_BOOTLD_START 0x10000 /* bootld */ +#define NETXEN_IMAGE_START 0x43000 /* compressed image */ +#define NETXEN_SECONDARY_START 0x200000 /* backup images */ +#define NETXEN_PXE_START 0x3E0000 /* PXE boot rom */ +#define NETXEN_USER_START 0x3E8000 /* Firmare info */ +#define NETXEN_FIXED_START 0x3F0000 /* backup of crbinit */ #define NX_FW_VERSION_OFFSET (NETXEN_USER_START+0x408) #define NX_FW_SIZE_OFFSET (NETXEN_USER_START+0x40c) @@ -708,21 +625,8 @@ typedef enum { #define NETXEN_FLASH_SECONDARY_SIZE (NETXEN_USER_START-NETXEN_SECONDARY_START) #define NETXEN_NUM_PRIMARY_SECTORS (0x20) #define NETXEN_NUM_CONFIG_SECTORS (1) -#define PFX "NetXen: " extern char netxen_nic_driver_name[]; -/* Note: Make sure to not call this before adapter->port is valid */ -#if !defined(NETXEN_DEBUG) -#define DPRINTK(klevel, fmt, args...) do { \ - } while (0) -#else -#define DPRINTK(klevel, fmt, args...) do { \ - printk(KERN_##klevel PFX "%s: %s: " fmt, __func__,\ - (adapter != NULL && adapter->netdev != NULL) ? \ - adapter->netdev->name : NULL, \ - ## args); } while(0) -#endif - /* Number of status descriptors to handle per interrupt */ #define MAX_STATUS_HANDLE (64) @@ -732,7 +636,7 @@ extern char netxen_nic_driver_name[]; */ struct netxen_skb_frag { u64 dma; - ulong length; + u64 length; }; #define _netxen_set_bits(config_word, start, bits, val) {\ @@ -793,34 +697,24 @@ struct netxen_hardware_context { u8 cut_through; u8 revision_id; + u8 pci_func; + u8 linkup; u16 port_type; - int board_type; - u32 linkup; - /* Address of cmd ring in Phantom */ - struct cmd_desc_type0 *cmd_desc_head; - dma_addr_t cmd_desc_phys_addr; - struct netxen_adapter *adapter; - int pci_func; + u16 board_type; }; #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ #define ETHERNET_FCS_SIZE 4 struct netxen_adapter_stats { - u64 rcvdbadskb; u64 xmitcalled; - u64 xmitedframes; u64 xmitfinished; - u64 badskblen; - u64 nocmddescriptor; - u64 polled; u64 rxdropped; u64 txdropped; u64 csummed; u64 no_rcv; u64 rxbytes; u64 txbytes; - u64 ints; }; /* @@ -852,14 +746,25 @@ struct nx_host_sds_ring { struct napi_struct napi; struct list_head free_list[NUM_RCV_DESC_RINGS]; - u16 clean_tx; - u16 post_rxd; int irq; dma_addr_t phys_addr; char name[IFNAMSIZ+4]; }; +struct nx_host_tx_ring { + u32 producer; + __le32 *hw_consumer; + u32 sw_consumer; + u32 crb_cmd_producer; + u32 crb_cmd_consumer; + u32 num_desc; + + struct netxen_cmd_buffer *cmd_buf_arr; + struct cmd_desc_type0 *desc_head; + dma_addr_t phys_addr; +}; + /* * Receive context. There is one such structure per instance of the * receive processing. Any state information that is relevant to @@ -871,8 +776,11 @@ struct netxen_recv_context { u16 context_id; u16 virt_port; - struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS]; - struct nx_host_sds_ring sds_rings[NUM_STS_DESC_RINGS]; + struct nx_host_rds_ring *rds_rings; + struct nx_host_sds_ring *sds_rings; + + struct netxen_ring_ctx *hwctx; + dma_addr_t phys_addr; }; /* New HW context creation */ @@ -1111,8 +1019,8 @@ typedef struct { #define NETXEN_MAC_DEL 2 typedef struct nx_mac_list_s { - struct nx_mac_list_s *next; - uint8_t mac_addr[MAX_ADDR_LEN]; + struct list_head list; + uint8_t mac_addr[ETH_ALEN+2]; } nx_mac_list_t; /* @@ -1154,31 +1062,118 @@ typedef struct { #define NX_MAC_EVENT 0x1 -enum { - NX_NIC_H2C_OPCODE_START = 0, - NX_NIC_H2C_OPCODE_CONFIG_RSS, - NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL, - NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE, - NX_NIC_H2C_OPCODE_CONFIG_LED, - NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS, - NX_NIC_H2C_OPCODE_CONFIG_L2_MAC, - NX_NIC_H2C_OPCODE_LRO_REQUEST, - NX_NIC_H2C_OPCODE_GET_SNMP_STATS, - NX_NIC_H2C_OPCODE_PROXY_START_REQUEST, - NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST, - NX_NIC_H2C_OPCODE_PROXY_SET_MTU, - NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE, - NX_H2P_OPCODE_GET_FINGER_PRINT_REQUEST, - NX_H2P_OPCODE_INSTALL_LICENSE_REQUEST, - NX_H2P_OPCODE_GET_LICENSE_CAPABILITY_REQUEST, - NX_NIC_H2C_OPCODE_GET_NET_STATS, - NX_NIC_H2C_OPCODE_LAST -}; +/* + * Driver --> Firmware + */ +#define NX_NIC_H2C_OPCODE_START 0 +#define NX_NIC_H2C_OPCODE_CONFIG_RSS 1 +#define NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL 2 +#define NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE 3 +#define NX_NIC_H2C_OPCODE_CONFIG_LED 4 +#define NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS 5 +#define NX_NIC_H2C_OPCODE_CONFIG_L2_MAC 6 +#define NX_NIC_H2C_OPCODE_LRO_REQUEST 7 +#define NX_NIC_H2C_OPCODE_GET_SNMP_STATS 8 +#define NX_NIC_H2C_OPCODE_PROXY_START_REQUEST 9 +#define NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST 10 +#define NX_NIC_H2C_OPCODE_PROXY_SET_MTU 11 +#define NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE 12 +#define NX_NIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST 13 +#define NX_NIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST 14 +#define NX_NIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST 15 +#define NX_NIC_H2C_OPCODE_GET_NET_STATS 16 +#define NX_NIC_H2C_OPCODE_PROXY_UPDATE_P2V 17 +#define NX_NIC_H2C_OPCODE_CONFIG_IPADDR 18 +#define NX_NIC_H2C_OPCODE_CONFIG_LOOPBACK 19 +#define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE 20 +#define NX_NIC_H2C_OPCODE_GET_LINKEVENT 21 +#define NX_NIC_C2C_OPCODE 22 +#define NX_NIC_H2C_OPCODE_LAST 23 + +/* + * Firmware --> Driver + */ + +#define NX_NIC_C2H_OPCODE_START 128 +#define NX_NIC_C2H_OPCODE_CONFIG_RSS_RESPONSE 129 +#define NX_NIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE 130 +#define NX_NIC_C2H_OPCODE_CONFIG_MAC_RESPONSE 131 +#define NX_NIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE 132 +#define NX_NIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE 133 +#define NX_NIC_C2H_OPCODE_LRO_DELETE_RESPONSE 134 +#define NX_NIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE 135 +#define NX_NIC_C2H_OPCODE_GET_SNMP_STATS 136 +#define NX_NIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY 137 +#define NX_NIC_C2H_OPCODE_INSTALL_LICENSE_REPLY 138 +#define NX_NIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139 +#define NX_NIC_C2H_OPCODE_GET_NET_STATS_RESPONSE 140 +#define NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 +#define NX_NIC_C2H_OPCODE_LAST 142 #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ +#define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) +#define NX_FW_CAPABILITY_SWITCHING (1 << 6) + +/* module types */ +#define LINKEVENT_MODULE_NOT_PRESENT 1 +#define LINKEVENT_MODULE_OPTICAL_UNKNOWN 2 +#define LINKEVENT_MODULE_OPTICAL_SRLR 3 +#define LINKEVENT_MODULE_OPTICAL_LRM 4 +#define LINKEVENT_MODULE_OPTICAL_SFP_1G 5 +#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE 6 +#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN 7 +#define LINKEVENT_MODULE_TWINAX 8 + +#define LINKSPEED_10GBPS 10000 +#define LINKSPEED_1GBPS 1000 +#define LINKSPEED_100MBPS 100 +#define LINKSPEED_10MBPS 10 + +#define LINKSPEED_ENCODED_10MBPS 0 +#define LINKSPEED_ENCODED_100MBPS 1 +#define LINKSPEED_ENCODED_1GBPS 2 + +#define LINKEVENT_AUTONEG_DISABLED 0 +#define LINKEVENT_AUTONEG_ENABLED 1 + +#define LINKEVENT_HALF_DUPLEX 0 +#define LINKEVENT_FULL_DUPLEX 1 + +#define LINKEVENT_LINKSPEED_MBPS 0 +#define LINKEVENT_LINKSPEED_ENCODED 1 + +/* firmware response header: + * 63:58 - message type + * 57:56 - owner + * 55:53 - desc count + * 52:48 - reserved + * 47:40 - completion id + * 39:32 - opcode + * 31:16 - error code + * 15:00 - reserved + */ +#define netxen_get_nic_msgtype(msg_hdr) \ + ((msg_hdr >> 58) & 0x3F) +#define netxen_get_nic_msg_compid(msg_hdr) \ + ((msg_hdr >> 40) & 0xFF) +#define netxen_get_nic_msg_opcode(msg_hdr) \ + ((msg_hdr >> 32) & 0xFF) +#define netxen_get_nic_msg_errcode(msg_hdr) \ + ((msg_hdr >> 16) & 0xFFFF) + +typedef struct { + union { + struct { + u64 hdr; + u64 body[7]; + }; + u64 words[8]; + }; +} nx_fw_msg_t; + typedef struct { __le64 qhdr; __le64 req_hdr; @@ -1218,99 +1213,96 @@ struct netxen_adapter { struct net_device *netdev; struct pci_dev *pdev; - int pci_using_dac; - struct net_device_stats net_stats; - int mtu; - int portnum; - u8 physical_port; - u16 tx_context_id; - - uint8_t mc_enabled; - uint8_t max_mc_count; - nx_mac_list_t *mac_list; - - struct netxen_legacy_intr_set legacy_intr; - - struct work_struct watchdog_task; - struct timer_list watchdog_timer; - struct work_struct tx_timeout_task; + struct list_head mac_list; u32 curr_window; u32 crb_win; rwlock_t adapter_lock; - u32 cmd_producer; - __le32 *cmd_consumer; - u32 last_cmd_consumer; - u32 crb_addr_cmd_producer; - u32 crb_addr_cmd_consumer; spinlock_t tx_clean_lock; - u32 num_txd; - u32 num_rxd; - u32 num_jumbo_rxd; - u32 num_lro_rxd; + u16 num_txd; + u16 num_rxd; + u16 num_jumbo_rxd; + u16 num_lro_rxd; - int max_rds_rings; - int max_sds_rings; + u8 max_rds_rings; + u8 max_sds_rings; + u8 driver_mismatch; + u8 msix_supported; + u8 rx_csum; + u8 pci_using_dac; + u8 portnum; + u8 physical_port; - u32 flags; - u32 irq; - int driver_mismatch; - u32 temp; + u8 mc_enabled; + u8 max_mc_count; + u8 rss_supported; + u8 resv2; + u32 resv3; - u32 fw_major; - u32 fw_version; - - int msix_supported; - struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; - - struct netxen_adapter_stats stats; + u8 has_link_events; + u8 resv1; + u16 tx_context_id; + u16 mtu; + u16 is_up; u16 link_speed; u16 link_duplex; - u16 state; u16 link_autoneg; - int rx_csum; + u16 module_type; - struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */ + u32 capabilities; + u32 flags; + u32 irq; + u32 temp; + + u32 msi_tgt_status; + u32 resv4; + + struct netxen_adapter_stats stats; - /* - * Receive instances. These can be either one per port, - * or one per peg, etc. - */ struct netxen_recv_context recv_ctx; + struct nx_host_tx_ring *tx_ring; - int is_up; - struct netxen_dummy_dma dummy_dma; - nx_nic_intr_coalesce_t coal; - - /* Context interface shared between card and host */ - struct netxen_ring_ctx *ctx_desc; - dma_addr_t ctx_desc_phys_addr; - int intr_scheme; - int msi_mode; int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); - int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t); + int (*macaddr_set) (struct netxen_adapter *, u8 *); int (*set_mtu) (struct netxen_adapter *, int); int (*set_promisc) (struct netxen_adapter *, u32); + void (*set_multi) (struct net_device *); int (*phy_read) (struct netxen_adapter *, long reg, u32 *); int (*phy_write) (struct netxen_adapter *, long reg, u32 val); int (*init_port) (struct netxen_adapter *, int); int (*stop_port) (struct netxen_adapter *); - int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int); - int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int); + u32 (*hw_read_wx)(struct netxen_adapter *, ulong); + int (*hw_write_wx)(struct netxen_adapter *, ulong, u32); int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int); int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int); int (*pci_write_immediate)(struct netxen_adapter *, u64, u32); u32 (*pci_read_immediate)(struct netxen_adapter *, u64); - void (*pci_write_normalize)(struct netxen_adapter *, u64, u32); - u32 (*pci_read_normalize)(struct netxen_adapter *, u64); unsigned long (*pci_set_window)(struct netxen_adapter *, unsigned long long); -}; /* netxen_adapter structure */ + + struct netxen_legacy_intr_set legacy_intr; + + struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; + + struct netxen_dummy_dma dummy_dma; + + struct work_struct watchdog_task; + struct timer_list watchdog_timer; + struct work_struct tx_timeout_task; + + struct net_device_stats net_stats; + + nx_nic_intr_coalesce_t coal; + + u32 fw_major; + u32 fw_version; + const struct firmware *fw; +}; /* * NetXen dma watchdog control structure @@ -1330,46 +1322,6 @@ struct netxen_adapter { #define netxen_get_dma_watchdog_disabled(config_word) \ (((config_word) >> 1) & 0x1) -/* Max number of xmit producer threads that can run simultaneously */ -#define MAX_XMIT_PRODUCERS 16 - -#define PCI_OFFSET_FIRST_RANGE(adapter, off) \ - ((adapter)->ahw.pci_base0 + (off)) -#define PCI_OFFSET_SECOND_RANGE(adapter, off) \ - ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START) -#define PCI_OFFSET_THIRD_RANGE(adapter, off) \ - ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START) - -static inline void __iomem *pci_base_offset(struct netxen_adapter *adapter, - unsigned long off) -{ - if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) { - return (adapter->ahw.pci_base0 + off); - } else if ((off < SECOND_PAGE_GROUP_END) && - (off >= SECOND_PAGE_GROUP_START)) { - return (adapter->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START); - } else if ((off < THIRD_PAGE_GROUP_END) && - (off >= THIRD_PAGE_GROUP_START)) { - return (adapter->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START); - } - return NULL; -} - -static inline void __iomem *pci_base(struct netxen_adapter *adapter, - unsigned long off) -{ - if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) { - return adapter->ahw.pci_base0; - } else if ((off < SECOND_PAGE_GROUP_END) && - (off >= SECOND_PAGE_GROUP_START)) { - return adapter->ahw.pci_base1; - } else if ((off < THIRD_PAGE_GROUP_END) && - (off >= THIRD_PAGE_GROUP_START)) { - return adapter->ahw.pci_base2; - } - return NULL; -} - 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); @@ -1382,21 +1334,22 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, /* Functions available from netxen_nic_hw.c */ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu); int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu); -void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val); -int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off); -void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value); -void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value); -void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value); -void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value); + +int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr); +int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr); + +#define NXRD32(adapter, off) \ + (adapter->hw_read_wx(adapter, off)) +#define NXWR32(adapter, off, val) \ + (adapter->hw_write_wx(adapter, off, val)) int netxen_nic_get_board_info(struct netxen_adapter *adapter); void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); int netxen_nic_wol_supported(struct netxen_adapter *adapter); -int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len); +u32 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off); int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len); + ulong off, u32 data); int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, u64 off, void *data, int size); int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, @@ -1412,16 +1365,13 @@ unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw); -int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len); +u32 netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off); int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len); + ulong off, u32 data); int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, u64 off, void *data, int size); int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, u64 off, void *data, int size); -void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, - unsigned long off, int data); int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, u64 off, u32 data); u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off); @@ -1435,8 +1385,9 @@ unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); -int netxen_receive_peg_ready(struct netxen_adapter *adapter); int netxen_load_firmware(struct netxen_adapter *adapter); +void netxen_request_firmware(struct netxen_adapter *adapter); +void netxen_release_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); @@ -1475,6 +1426,8 @@ 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_linkevent_request(struct netxen_adapter *adapter, int enable); +void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); @@ -1483,7 +1436,7 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p); struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, - uint32_t crb_producer); + struct nx_host_tx_ring *tx_ring, uint32_t crb_producer); /* * NetXen Board information @@ -1491,7 +1444,7 @@ void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, #define NETXEN_MAX_SHORT_NAME 32 struct netxen_brdinfo { - netxen_brdtype_t brdtype; /* type of board */ + int brdtype; /* type of board */ long ports; /* max no of physical ports */ char short_name[NETXEN_MAX_SHORT_NAME]; }; @@ -1541,17 +1494,15 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter) u32 ctrl; /* check if already inactive */ - if (adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) - printk(KERN_ERR "failed to read dma watchdog status\n"); + 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); - netxen_crb_writelit_adapter(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); return 0; } @@ -1561,9 +1512,8 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) { u32 ctrl; - if (adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) - printk(KERN_ERR "failed to read dma watchdog status\n"); + ctrl = adapter->hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); return (netxen_get_dma_watchdog_enabled(ctrl) == 0); } @@ -1573,9 +1523,8 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) { u32 ctrl; - if (adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) - printk(KERN_ERR "failed to read dma watchdog status\n"); + ctrl = adapter->hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); if (netxen_get_dma_watchdog_enabled(ctrl)) return 1; @@ -1583,8 +1532,7 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) /* send the wakeup request */ netxen_set_dma_watchdog_enable_req(ctrl); - netxen_crb_writelit_adapter(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); return 0; } diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 9234473bc08a..4754f5cffad0 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -41,8 +41,7 @@ netxen_api_lock(struct netxen_adapter *adapter) for (;;) { /* Acquire PCIE HW semaphore5 */ - netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_LOCK)); if (done == 1) break; @@ -56,7 +55,7 @@ netxen_api_lock(struct netxen_adapter *adapter) } #if 0 - netxen_nic_write_w1(adapter, + NXWR32(adapter, NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER); #endif return 0; @@ -65,11 +64,8 @@ netxen_api_lock(struct netxen_adapter *adapter) static int netxen_api_unlock(struct netxen_adapter *adapter) { - u32 val; - /* Release PCIE HW semaphore5 */ - netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val); + NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK)); return 0; } @@ -86,7 +82,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter) if (++timeout > NX_OS_CRB_RETRY_COUNT) return NX_CDRP_RSP_TIMEOUT; - netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp); + rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET); } while (!NX_CDRP_IS_RSP(rsp)); return rsp; @@ -106,16 +102,15 @@ netxen_issue_cmd(struct netxen_adapter *adapter, if (netxen_api_lock(adapter)) return NX_RCODE_TIMEOUT; - netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature); + NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); - netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1); + NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1); - netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2); + NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2); - netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3); + NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3); - netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET, - NX_CDRP_FORM_CMD(cmd)); + NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd)); rsp = netxen_poll_rsp(adapter); @@ -125,7 +120,7 @@ netxen_issue_cmd(struct netxen_adapter *adapter, rcode = NX_RCODE_TIMEOUT; } else if (rsp == NX_CDRP_RSP_FAIL) { - netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode); + rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET); printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); @@ -328,6 +323,8 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) int err = 0; u64 offset, phys_addr; dma_addr_t rq_phys_addr, rsp_phys_addr; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); rq_addr = pci_alloc_consistent(adapter->pdev, @@ -362,15 +359,13 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr); - offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx); + offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx); prq->cmd_cons_dma_addr = cpu_to_le64(offset); prq_cds = &prq->cds_ring; - prq_cds->host_phys_addr = - cpu_to_le64(adapter->ahw.cmd_desc_phys_addr); - - prq_cds->ring_size = cpu_to_le32(adapter->num_txd); + prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr); + prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); phys_addr = rq_phys_addr; err = netxen_issue_cmd(adapter, @@ -383,8 +378,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) if (err == NX_RCODE_SUCCESS) { temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); - adapter->crb_addr_cmd_producer = - NETXEN_NIC_REG(temp - 0x200); + tx_ring->crb_cmd_producer = NETXEN_NIC_REG(temp - 0x200); #if 0 adapter->tx_state = le32_to_cpu(prsp->host_ctx_state); @@ -448,7 +442,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x120) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x138), + { + NETXEN_NIC_REG(0x138), + NETXEN_NIC_REG_2(0x000), + NETXEN_NIC_REG_2(0x004), + NETXEN_NIC_REG_2(0x008), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_0, + NETXEN_NIC_REG_2(0x044), + NETXEN_NIC_REG_2(0x048), + NETXEN_NIC_REG_2(0x04c), + }, }, /* Instance 1 */ { @@ -461,7 +467,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x164) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x17c), + { + NETXEN_NIC_REG(0x17c), + NETXEN_NIC_REG_2(0x020), + NETXEN_NIC_REG_2(0x024), + NETXEN_NIC_REG_2(0x028), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_1, + NETXEN_NIC_REG_2(0x064), + NETXEN_NIC_REG_2(0x068), + NETXEN_NIC_REG_2(0x06c), + }, }, /* Instance 2 */ { @@ -474,7 +492,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x208) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x220), + { + NETXEN_NIC_REG(0x220), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_2, + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, }, /* Instance 3 */ { @@ -487,7 +517,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x24c) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x264), + { + NETXEN_NIC_REG(0x264), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_3, + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, }, }; @@ -497,84 +539,91 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring; int ring; - int func_id = adapter->portnum; - - adapter->ctx_desc->cmd_ring_addr = - cpu_to_le64(adapter->ahw.cmd_desc_phys_addr); - adapter->ctx_desc->cmd_ring_size = - cpu_to_le32(adapter->num_txd); + int port = adapter->portnum; + struct netxen_ring_ctx *hwctx; + u32 signature; + tx_ring = adapter->tx_ring; recv_ctx = &adapter->recv_ctx; + hwctx = recv_ctx->hwctx; + + hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); + hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); + for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr = + hwctx->rcv_rings[ring].addr = cpu_to_le64(rds_ring->phys_addr); - adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = + hwctx->rcv_rings[ring].size = cpu_to_le32(rds_ring->num_desc); } - sds_ring = &recv_ctx->sds_rings[0]; - adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); - adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc); - adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id), - lower32(adapter->ctx_desc_phys_addr)); - adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id), - upper32(adapter->ctx_desc_phys_addr)); - adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id), - NETXEN_CTX_SIGNATURE | func_id); + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + if (ring == 0) { + hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); + hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc); + } + hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr); + hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc); + hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring); + } + hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings); + + signature = (adapter->max_sds_rings > 1) ? + NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE; + + NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port), + lower32(recv_ctx->phys_addr)); + NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port), + upper32(recv_ctx->phys_addr)); + NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), + signature | port); return 0; } -static uint32_t sw_int_mask[4] = { - CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1, - CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3 -}; - int netxen_alloc_hw_resources(struct netxen_adapter *adapter) { - struct netxen_hardware_context *hw = &adapter->ahw; - u32 state = 0; void *addr; int err = 0; int ring; struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring; struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; + int port = adapter->portnum; - err = netxen_receive_peg_ready(adapter); - if (err) { - printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n", - state); - return err; - } + recv_ctx = &adapter->recv_ctx; + tx_ring = adapter->tx_ring; addr = pci_alloc_consistent(pdev, sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), - &adapter->ctx_desc_phys_addr); - + &recv_ctx->phys_addr); if (addr == NULL) { dev_err(&pdev->dev, "failed to allocate hw context\n"); return -ENOMEM; } + memset(addr, 0, sizeof(struct netxen_ring_ctx)); - adapter->ctx_desc = (struct netxen_ring_ctx *)addr; - adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum); - adapter->ctx_desc->cmd_consumer_offset = - cpu_to_le64(adapter->ctx_desc_phys_addr + + recv_ctx->hwctx = (struct netxen_ring_ctx *)addr; + recv_ctx->hwctx->ctx_id = cpu_to_le32(port); + recv_ctx->hwctx->cmd_consumer_offset = + cpu_to_le64(recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx)); - adapter->cmd_consumer = + tx_ring->hw_consumer = (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); /* cmd desc ring */ - addr = pci_alloc_consistent(pdev, - TX_DESC_RINGSIZE(adapter), - &hw->cmd_desc_phys_addr); + addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), + &tx_ring->phys_addr); if (addr == NULL) { dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", @@ -582,9 +631,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) return -ENOMEM; } - hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; - - recv_ctx = &adapter->recv_ctx; + tx_ring->desc_head = (struct cmd_desc_type0 *)addr; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; @@ -602,8 +649,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (adapter->fw_major < 4) rds_ring->crb_rcv_producer = - recv_crb_registers[adapter->portnum]. - crb_rcv_producer[ring]; + recv_crb_registers[port].crb_rcv_producer[ring]; } for (ring = 0; ring < adapter->max_sds_rings; ring++) { @@ -620,13 +666,16 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) goto err_out_free; } sds_ring->desc_head = (struct status_desc *)addr; + + sds_ring->crb_sts_consumer = + recv_crb_registers[port].crb_sts_consumer[ring]; + + sds_ring->crb_intr_mask = + recv_crb_registers[port].sw_int_mask[ring]; } if (adapter->fw_major >= 4) { - adapter->intr_scheme = INTR_SCHEME_PERPORT; - adapter->msi_mode = MSI_MODE_MULTIFUNC; - err = nx_fw_cmd_create_rx_ctx(adapter); if (err) goto err_out_free; @@ -634,23 +683,11 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (err) goto err_out_free; } else { - sds_ring = &recv_ctx->sds_rings[0]; - sds_ring->crb_sts_consumer = - recv_crb_registers[adapter->portnum].crb_sts_consumer; - - adapter->intr_scheme = adapter->pci_read_normalize(adapter, - CRB_NIC_CAPABILITIES_FW); - adapter->msi_mode = adapter->pci_read_normalize(adapter, - CRB_NIC_MSI_MODE_FW); - recv_ctx->sds_rings[0].crb_intr_mask = - sw_int_mask[adapter->portnum]; - err = netxen_init_old_ctx(adapter); if (err) { netxen_free_hw_resources(adapter); return err; } - } return 0; @@ -665,32 +702,40 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring; int ring; + int port = adapter->portnum; + if (adapter->fw_major >= 4) { nx_fw_cmd_destroy_tx_ctx(adapter); nx_fw_cmd_destroy_rx_ctx(adapter); - } - - if (adapter->ctx_desc != NULL) { - pci_free_consistent(adapter->pdev, - sizeof(struct netxen_ring_ctx) + - sizeof(uint32_t), - adapter->ctx_desc, - adapter->ctx_desc_phys_addr); - adapter->ctx_desc = NULL; - } - - if (adapter->ahw.cmd_desc_head != NULL) { - pci_free_consistent(adapter->pdev, - sizeof(struct cmd_desc_type0) * - adapter->num_txd, - adapter->ahw.cmd_desc_head, - adapter->ahw.cmd_desc_phys_addr); - adapter->ahw.cmd_desc_head = NULL; + } else { + netxen_api_lock(adapter); + NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), + NETXEN_CTX_RESET | port); + netxen_api_unlock(adapter); } recv_ctx = &adapter->recv_ctx; + + if (recv_ctx->hwctx != NULL) { + pci_free_consistent(adapter->pdev, + sizeof(struct netxen_ring_ctx) + + sizeof(uint32_t), + recv_ctx->hwctx, + recv_ctx->phys_addr); + recv_ctx->hwctx = NULL; + } + + tx_ring = adapter->tx_ring; + if (tx_ring->desc_head != NULL) { + pci_free_consistent(adapter->pdev, + TX_DESC_RINGSIZE(tx_ring), + tx_ring->desc_head, tx_ring->phys_addr); + tx_ring->desc_head = NULL; + } + for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index a677ff895184..e16ea46c24b8 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -53,13 +52,9 @@ struct netxen_nic_stats { #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { - {"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)}, {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)}, - {"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)}, {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)}, - {"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)}, - {"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)}, - {"polled", NETXEN_NIC_STAT(stats.polled)}, + {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)}, {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, {"csummed", NETXEN_NIC_STAT(stats.csummed)}, {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)}, @@ -97,12 +92,9 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) strncpy(drvinfo->driver, netxen_nic_driver_name, 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); write_lock_irqsave(&adapter->adapter_lock, flags); - fw_major = adapter->pci_read_normalize(adapter, - NETXEN_FW_VERSION_MAJOR); - fw_minor = adapter->pci_read_normalize(adapter, - NETXEN_FW_VERSION_MINOR); - fw_build = adapter->pci_read_normalize(adapter, - NETXEN_FW_VERSION_SUB); + fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); + fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); + fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); write_unlock_irqrestore(&adapter->adapter_lock, flags); sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); @@ -115,6 +107,7 @@ static int netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_adapter *adapter = netdev_priv(dev); + int check_sfp_module = 0; /* read which mode */ if (adapter->ahw.port_type == NETXEN_NIC_GBE) { @@ -139,7 +132,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { u32 val; - adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &val, 4); + val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR); if (val == NETXEN_PORT_MODE_802_3_AP) { ecmd->supported = SUPPORTED_1000baseT_Full; ecmd->advertising = ADVERTISED_1000baseT_Full; @@ -148,13 +141,19 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->advertising = ADVERTISED_10000baseT_Full; } + if (netif_running(dev) && adapter->has_link_events) { + ecmd->speed = adapter->link_speed; + ecmd->autoneg = adapter->link_autoneg; + ecmd->duplex = adapter->link_duplex; + goto skip; + } + ecmd->port = PORT_TP; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { u16 pcifn = adapter->ahw.pci_func; - adapter->hw_read_wx(adapter, - P3_LINK_SPEED_REG(pcifn), &val, 4); + val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn)); ecmd->speed = P3_LINK_SPEED_MHZ * P3_LINK_SPEED_VAL(pcifn, val); } else @@ -165,10 +164,11 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else return -EIO; +skip: ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; - switch ((netxen_brdtype_t)adapter->ahw.board_type) { + switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: case NETXEN_BRDTYPE_P2_SB31_2G: case NETXEN_BRDTYPE_P3_REF_QG: @@ -195,7 +195,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) case NETXEN_BRDTYPE_P3_HMEZ: ecmd->supported |= SUPPORTED_MII; ecmd->advertising |= ADVERTISED_MII; - ecmd->port = PORT_FIBRE; + ecmd->port = PORT_MII; ecmd->autoneg = AUTONEG_DISABLE; break; case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: @@ -203,6 +203,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) case NETXEN_BRDTYPE_P3_10G_SFP_QT: ecmd->advertising |= ADVERTISED_TP; ecmd->supported |= SUPPORTED_TP; + check_sfp_module = netif_running(dev) && + adapter->has_link_events; case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_XFP: ecmd->supported |= SUPPORTED_FIBRE; @@ -217,6 +219,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP); ecmd->port = PORT_FIBRE; + check_sfp_module = netif_running(dev) && + adapter->has_link_events; } else { ecmd->autoneg = AUTONEG_ENABLE; ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); @@ -227,10 +231,28 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) break; default: printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", - (netxen_brdtype_t)adapter->ahw.board_type); + adapter->ahw.board_type); return -EIO; } + if (check_sfp_module) { + switch (adapter->module_type) { + case LINKEVENT_MODULE_OPTICAL_UNKNOWN: + case LINKEVENT_MODULE_OPTICAL_SRLR: + case LINKEVENT_MODULE_OPTICAL_LRM: + case LINKEVENT_MODULE_OPTICAL_SFP_1G: + ecmd->port = PORT_FIBRE; + break; + case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: + case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: + case LINKEVENT_MODULE_TWINAX: + ecmd->port = PORT_TP; + break; + default: + ecmd->port = -1; + } + } + return 0; } @@ -398,12 +420,11 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) | (adapter->pdev)->device; /* which mode */ - adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, ®s_buff[0], 4); + regs_buff[0] = NXRD32(adapter, NETXEN_NIU_MODE); mode = regs_buff[0]; /* Common registers to all the modes */ - adapter->hw_read_wx(adapter, - NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, ®s_buff[2], 4); + regs_buff[2] = NXRD32(adapter, NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER); /* GB/XGB Mode */ mode = (mode / 2) - 1; window = 0; @@ -414,9 +435,8 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) window = adapter->physical_port * NETXEN_NIC_PORT_WINDOW; - adapter->hw_read_wx(adapter, - niu_registers[mode].reg[i - 3] + window, - ®s_buff[i], 4); + regs_buff[i] = NXRD32(adapter, + niu_registers[mode].reg[i - 3] + window); } } @@ -440,7 +460,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) return !val; } } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); + val = NXRD32(adapter, CRB_XG_STATE); return (val == XG_LINK_UP) ? 0 : 1; } return -EIO; @@ -504,10 +524,9 @@ netxen_nic_get_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ - netxen_nic_read_w0(adapter,NETXEN_NIU_GB_MAC_CONFIG_0(port), - &val); + val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port)); pause->rx_pause = netxen_gb_get_rx_flowctl(val); - netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val); + val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { case 0: pause->tx_pause = !(netxen_gb_get_gb0_mask(val)); @@ -527,7 +546,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; - netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val); + val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) pause->tx_pause = !(netxen_xg_get_xg0_mask(val)); else @@ -550,18 +569,17 @@ netxen_nic_set_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ - netxen_nic_read_w0(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), &val); + val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port)); if (pause->rx_pause) netxen_gb_rx_flowctl(val); else netxen_gb_unset_rx_flowctl(val); - netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), val); /* set autoneg */ - netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val); + val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { case 0: if (pause->tx_pause) @@ -589,11 +607,11 @@ netxen_nic_set_pauseparam(struct net_device *dev, netxen_gb_set_gb3_mask(val); break; } - netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); + NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return -EIO; - netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val); + val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) { if (pause->tx_pause) netxen_xg_unset_xg0_mask(val); @@ -605,7 +623,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, else netxen_xg_set_xg1_mask(val); } - netxen_nic_write_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, val); + NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val); } else { printk(KERN_ERR "%s: Unknown board type: %x\n", netxen_nic_driver_name, @@ -619,14 +637,14 @@ static int netxen_nic_reg_test(struct net_device *dev) struct netxen_adapter *adapter = netdev_priv(dev); u32 data_read, data_written; - netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read); + data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0)); if ((data_read & 0xffff) != PHAN_VENDOR_ID) return 1; data_written = (u32)0xa5a5a5a5; - netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written); - data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST); + NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written); + data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST); if (data_written != data_read) return 1; @@ -743,11 +761,11 @@ netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) return; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); if (wol_cfg & (1UL << adapter->portnum)) wol->supported |= WAKE_MAGIC; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); if (wol_cfg & (1UL << adapter->portnum)) wol->wolopts |= WAKE_MAGIC; } @@ -764,16 +782,16 @@ netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EOPNOTSUPP; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); if (!(wol_cfg & (1 << adapter->portnum))) return -EOPNOTSUPP; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); if (wol->wolopts & WAKE_MAGIC) wol_cfg |= 1UL << adapter->portnum; else wol_cfg &= ~(1UL << adapter->portnum); - netxen_nic_reg_write(adapter, NETXEN_WOL_CONFIG, wol_cfg); + NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg); return 0; } diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 016c62129c76..7f0ddbfa7b28 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -31,16 +31,8 @@ #ifndef __NETXEN_NIC_HDR_H_ #define __NETXEN_NIC_HDR_H_ -#include #include -#include -#include -#include -#include -#include #include -#include -#include /* for memset */ /* * The basic unit of access when reading/writing control registers. diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 5026811c04ce..42ffb825ebf1 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -32,7 +32,6 @@ #include "netxen_nic_hw.h" #include "netxen_nic_phan_reg.h" -#include #include #define MASK(n) ((1ULL<<(n))-1) @@ -48,8 +47,49 @@ #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) #define CRB_INDIRECT_2M (0x1e0000UL) +#ifndef readq +static inline u64 readq(void __iomem *addr) +{ + return readl(addr) | (((u64) readl(addr + 4)) << 32LL); +} +#endif + +#ifndef writeq +static inline void writeq(u64 val, void __iomem *addr) +{ + writel(((u32) (val)), (addr)); + writel(((u32) (val >> 32)), (addr + 4)); +} +#endif + +#define ADDR_IN_RANGE(addr, low, high) \ + (((addr) < (high)) && ((addr) >= (low))) + +#define PCI_OFFSET_FIRST_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base0 + (off)) +#define PCI_OFFSET_SECOND_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START) +#define PCI_OFFSET_THIRD_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START) + +static void __iomem *pci_base_offset(struct netxen_adapter *adapter, + unsigned long off) +{ + if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END)) + return PCI_OFFSET_FIRST_RANGE(adapter, off); + + if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END)) + return PCI_OFFSET_SECOND_RANGE(adapter, off); + + if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END)) + return PCI_OFFSET_THIRD_RANGE(adapter, off); + + return NULL; +} + #define CRB_WIN_LOCK_TIMEOUT 100000000 -static crb_128M_2M_block_map_t crb_128M_2M_map[64] = { +static crb_128M_2M_block_map_t +crb_128M_2M_map[64] __cacheline_aligned_in_smp = { {{{0, 0, 0, 0} } }, /* 0: PCI */ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ {1, 0x0110000, 0x0120000, 0x130000}, @@ -279,39 +319,8 @@ static unsigned crb_hub_agt[64] = /* PCI Windowing for DDR regions. */ -#define ADDR_IN_RANGE(addr, low, high) \ - (((addr) <= (high)) && ((addr) >= (low))) - #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ -#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL -#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL -#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL -#define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL - -#define NETXEN_NIC_WINDOW_MARGIN 0x100000 - -int netxen_nic_set_mac(struct net_device *netdev, void *p) -{ - struct netxen_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (netif_running(netdev)) - return -EBUSY; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - - /* For P3, MAC addr is not set in NIU */ - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - if (adapter->macaddr_set) - adapter->macaddr_set(adapter, addr->sa_data); - - return 0; -} - #define NETXEN_UNICAST_ADDR(port, index) \ (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8)) #define NETXEN_MCAST_ADDR(port, index) \ @@ -331,22 +340,20 @@ netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter) if (adapter->mc_enabled) return 0; - adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG); val |= (1UL << (28+port)); - adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); /* add broadcast addr to filter */ val = 0xffffff; - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); - netxen_crb_writelit_adapter(adapter, - NETXEN_UNICAST_ADDR(port, 0)+4, val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val); /* add station addr to filter */ val = MAC_HI(addr); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val); val = MAC_LO(addr); - netxen_crb_writelit_adapter(adapter, - NETXEN_UNICAST_ADDR(port, 1)+4, val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val); adapter->mc_enabled = 1; return 0; @@ -362,18 +369,17 @@ netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter) if (!adapter->mc_enabled) return 0; - adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG); val &= ~(1UL << (28+port)); - adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); val = MAC_HI(addr); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val); val = MAC_LO(addr); - netxen_crb_writelit_adapter(adapter, - NETXEN_UNICAST_ADDR(port, 0)+4, val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0); adapter->mc_enabled = 0; return 0; @@ -389,10 +395,8 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, lo = MAC_LO(addr); hi = MAC_HI(addr); - netxen_crb_writelit_adapter(adapter, - NETXEN_MCAST_ADDR(port, index), hi); - netxen_crb_writelit_adapter(adapter, - NETXEN_MCAST_ADDR(port, index)+4, lo); + NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi); + NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo); return 0; } @@ -445,100 +449,58 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) netxen_nic_set_mcast_addr(adapter, index, null_addr); } -static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, - u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list) -{ - nx_mac_list_t *cur, *prev; - - /* if in del_list, move it to adapter->mac_list */ - for (cur = *del_list, prev = NULL; cur;) { - if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { - if (prev == NULL) - *del_list = cur->next; - else - prev->next = cur->next; - cur->next = adapter->mac_list; - adapter->mac_list = cur; - return 0; - } - prev = cur; - cur = cur->next; - } - - /* make sure to add each mac address only once */ - for (cur = adapter->mac_list; cur; cur = cur->next) { - if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) - return 0; - } - /* not in del_list, create new entry and add to add_list */ - cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL); - if (cur == NULL) { - printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may" - "not work properly from now.\n", __func__); - return -1; - } - - memcpy(cur->mac_addr, addr, ETH_ALEN); - cur->next = *add_list; - *add_list = cur; - return 0; -} - static int netxen_send_cmd_descs(struct netxen_adapter *adapter, - struct cmd_desc_type0 *cmd_desc_arr, int nr_elements) + struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) { - uint32_t i, producer; + u32 i, producer, consumer; struct netxen_cmd_buffer *pbuf; struct cmd_desc_type0 *cmd_desc; - - if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) { - printk(KERN_WARNING "%s: Too many command descriptors in a " - "request\n", __func__); - return -EINVAL; - } + struct nx_host_tx_ring *tx_ring; i = 0; + tx_ring = adapter->tx_ring; netif_tx_lock_bh(adapter->netdev); - producer = adapter->cmd_producer; + producer = tx_ring->producer; + consumer = tx_ring->sw_consumer; + + if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) { + netif_tx_unlock_bh(adapter->netdev); + return -EBUSY; + } + do { cmd_desc = &cmd_desc_arr[i]; - pbuf = &adapter->cmd_buf_arr[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; pbuf->frag_count = 0; - /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ - memcpy(&adapter->ahw.cmd_desc_head[producer], + memcpy(&tx_ring->desc_head[producer], &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); - producer = get_next_index(producer, - adapter->num_txd); + producer = get_next_index(producer, tx_ring->num_desc); i++; - } while (i != nr_elements); + } while (i != nr_desc); - adapter->cmd_producer = producer; + tx_ring->producer = producer; - /* write producer index to start the xmit */ - - netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); + netxen_nic_update_cmd_producer(adapter, tx_ring, producer); netif_tx_unlock_bh(adapter->netdev); return 0; } -static int nx_p3_sre_macaddr_change(struct net_device *dev, - u8 *addr, unsigned op) +static int +nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op) { - struct netxen_adapter *adapter = netdev_priv(dev); nx_nic_req_t req; nx_mac_req_t *mac_req; u64 word; - int rv; memset(&req, 0, sizeof(nx_nic_req_t)); req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); @@ -550,28 +512,51 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev, mac_req->op = op; memcpy(mac_req->mac_addr, addr, 6); - rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); - if (rv != 0) { - printk(KERN_ERR "ERROR. Could not send mac update\n"); - return rv; + return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); +} + +static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, + u8 *addr, struct list_head *del_list) +{ + struct list_head *head; + nx_mac_list_t *cur; + + /* look up if already exists */ + list_for_each(head, del_list) { + cur = list_entry(head, nx_mac_list_t, list); + + if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { + list_move_tail(head, &adapter->mac_list); + return 0; + } } - return 0; + cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC); + if (cur == NULL) { + printk(KERN_ERR "%s: failed to add mac address filter\n", + adapter->netdev->name); + return -ENOMEM; + } + memcpy(cur->mac_addr, addr, ETH_ALEN); + list_add_tail(&cur->list, &adapter->mac_list); + return nx_p3_sre_macaddr_change(adapter, + cur->mac_addr, NETXEN_MAC_ADD); } void netxen_p3_nic_set_multi(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - nx_mac_list_t *cur, *next, *del_list, *add_list = NULL; struct dev_mc_list *mc_ptr; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; + LIST_HEAD(del_list); + struct list_head *head; + nx_mac_list_t *cur; - del_list = adapter->mac_list; - adapter->mac_list = NULL; + list_splice_tail_init(&adapter->mac_list, &del_list); - nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list); - nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list); + nx_p3_nic_add_mac(adapter, netdev->dev_addr, &del_list); + nx_p3_nic_add_mac(adapter, bcast_addr, &del_list); if (netdev->flags & IFF_PROMISC) { mode = VPORT_MISS_MODE_ACCEPT_ALL; @@ -587,25 +572,20 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) if (netdev->mc_count > 0) { for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { - nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, - &add_list, &del_list); + nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); } } send_fw_cmd: adapter->set_promisc(adapter, mode); - for (cur = del_list; cur;) { - nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL); - next = cur->next; + head = &del_list; + while (!list_empty(head)) { + cur = list_entry(head->next, nx_mac_list_t, list); + + nx_p3_sre_macaddr_change(adapter, + cur->mac_addr, NETXEN_MAC_DEL); + list_del(&cur->list); kfree(cur); - cur = next; - } - for (cur = add_list; cur;) { - nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD); - next = cur->next; - cur->next = adapter->mac_list; - adapter->mac_list = cur; - cur = next; } } @@ -630,17 +610,25 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) void netxen_p3_free_mac_list(struct netxen_adapter *adapter) { - nx_mac_list_t *cur, *next; + nx_mac_list_t *cur; + struct list_head *head = &adapter->mac_list; - cur = adapter->mac_list; - - while (cur) { - next = cur->next; + while (!list_empty(head)) { + cur = list_entry(head->next, nx_mac_list_t, list); + nx_p3_sre_macaddr_change(adapter, + cur->mac_addr, NETXEN_MAC_DEL); + list_del(&cur->list); kfree(cur); - cur = next; } } +int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) +{ + /* assuming caller has already copied new addr to netdev */ + netxen_p3_nic_set_multi(adapter->netdev); + return 0; +} + #define NETXEN_CONFIG_INTR_COALESCE 3 /* @@ -717,6 +705,28 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable) return rv; } +int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) +{ + 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_GET_LINKEVENT | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + req.words[0] = cpu_to_le64(enable | (enable << 8)); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not configure link notification\n", + adapter->netdev->name); + } + + return rv; +} + /* * netxen_nic_change_mtu - Change the Maximum Transfer Unit * @returns 0 on success, negative on failure @@ -812,8 +822,8 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); - adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4); - adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4); + mac_lo = NXRD32(adapter, crbaddr); + mac_hi = NXRD32(adapter, crbaddr+4); if (pci_func & 1) *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); @@ -831,8 +841,7 @@ static int crb_win_lock(struct netxen_adapter *adapter) while (!done) { /* acquire semaphore3 from PCI HW block */ - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_LOCK)); if (done == 1) break; if (timeout >= CRB_WIN_LOCK_TIMEOUT) @@ -840,8 +849,7 @@ static int crb_win_lock(struct netxen_adapter *adapter) timeout++; udelay(1); } - netxen_crb_writelit_adapter(adapter, - NETXEN_CRB_WIN_LOCK_ID, adapter->portnum); + NXWR32(adapter, NETXEN_CRB_WIN_LOCK_ID, adapter->portnum); return 0; } @@ -849,8 +857,7 @@ static void crb_win_unlock(struct netxen_adapter *adapter) { int val; - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4); + val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK)); } /* @@ -907,17 +914,15 @@ netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw) * In: 'off' is offset from base in 128M pci map */ static int -netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, - ulong *off, int len) +netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) { - unsigned long end = *off + len; crb_128M_2M_sub_block_map_t *m; if (*off >= NETXEN_CRB_MAX) return -1; - if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) { + if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) { *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE + (ulong)adapter->ahw.pci_base0; return 0; @@ -927,14 +932,13 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, return -1; *off -= NETXEN_PCI_CRBSPACE; - end = *off + len; /* * Try direct map */ m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; - if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) { + if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { *off = *off + m->start_2M - m->start_128M + (ulong)adapter->ahw.pci_base0; return 0; @@ -972,214 +976,11 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) (ulong)adapter->ahw.pci_base0; } -static int -netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, - const struct firmware *fw) -{ - u64 *ptr64; - u32 i, flashaddr, size; - struct pci_dev *pdev = adapter->pdev; - - if (fw) - dev_info(&pdev->dev, "loading firmware from file %s\n", fwname); - else - dev_info(&pdev->dev, "loading firmware from flash\n"); - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_CAS_RST, 1); - - if (fw) { - __le64 data; - - size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; - - ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; - flashaddr = NETXEN_BOOTLD_START; - - for (i = 0; i < size; i++) { - data = cpu_to_le64(ptr64[i]); - adapter->pci_mem_write(adapter, flashaddr, &data, 8); - flashaddr += 8; - } - - size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; - size = (__force u32)cpu_to_le32(size) / 8; - - ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; - flashaddr = NETXEN_IMAGE_START; - - for (i = 0; i < size; i++) { - data = cpu_to_le64(ptr64[i]); - - if (adapter->pci_mem_write(adapter, - flashaddr, &data, 8)) - return -EIO; - - flashaddr += 8; - } - } else { - u32 data; - - size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; - flashaddr = NETXEN_BOOTLD_START; - - for (i = 0; i < size; i++) { - if (netxen_rom_fast_read(adapter, - flashaddr, (int *)&data) != 0) - return -EIO; - - if (adapter->pci_mem_write(adapter, - flashaddr, &data, 4)) - return -EIO; - - flashaddr += 4; - } - } - msleep(1); - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); - else { - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_CAS_RST, 0); - } - - return 0; -} - -static int -netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, - const struct firmware *fw) -{ - __le32 val; - u32 major, minor, build, ver, min_ver, bios; - struct pci_dev *pdev = adapter->pdev; - - if (fw->size < NX_FW_MIN_SIZE) - return -EINVAL; - - val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); - if ((__force u32)val != NETXEN_BDINFO_MAGIC) - return -EINVAL; - - val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - min_ver = NETXEN_VERSION_CODE(4, 0, 216); - else - min_ver = NETXEN_VERSION_CODE(3, 4, 216); - - ver = NETXEN_VERSION_CODE(major, minor, build); - - if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { - dev_err(&pdev->dev, - "%s: firmware version %d.%d.%d unsupported\n", - fwname, major, minor, build); - return -EINVAL; - } - - val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); - netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); - if ((__force u32)val != bios) { - dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", - fwname); - return -EINVAL; - } - - /* check if flashed firmware is newer */ - if (netxen_rom_fast_read(adapter, - NX_FW_VERSION_OFFSET, (int *)&val)) - return -EIO; - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; - if (NETXEN_VERSION_CODE(major, minor, build) > ver) - return -EINVAL; - - netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc), - NETXEN_BDINFO_MAGIC); - return 0; -} - -static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; - -int netxen_load_firmware(struct netxen_adapter *adapter) -{ - u32 capability, flashed_ver; - const struct firmware *fw; - int 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, - NX_FW_VERSION_OFFSET, (int *)&flashed_ver); - if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { - adapter->hw_read_wx(adapter, - NX_PEG_TUNE_CAPABILITY, &capability, 4); - if (capability & NX_PEG_TUNE_MN_PRESENT) { - fw_type = NX_P3_MN_ROMIMAGE; - goto request_fw; - } - } - -request_fw: - rc = request_firmware(&fw, fw_name[fw_type], &pdev->dev); - if (rc != 0) { - if (fw_type == NX_P3_CT_ROMIMAGE) { - msleep(1); - goto request_mn; - } - - fw = NULL; - goto load_fw; - } - - rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw); - if (rc != 0) { - release_firmware(fw); - - if (fw_type == NX_P3_CT_ROMIMAGE) { - msleep(1); - goto request_mn; - } - - fw = NULL; - } - -load_fw: - rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw); - - if (fw) - release_firmware(fw); - return rc; -} - int -netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) { void __iomem *addr; - BUG_ON(len != 4); - if (ADDR_IN_WINDOW1(off)) { addr = NETXEN_CRB_NORMALIZE(adapter, off); } else { /* Window 0 */ @@ -1192,7 +993,7 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, return 1; } - writel(*(u32 *) data, addr); + writel(data, addr); if (!ADDR_IN_WINDOW1(off)) netxen_nic_pci_change_crbwindow_128M(adapter, 1); @@ -1200,13 +1001,11 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, return 0; } -int -netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +u32 +netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) { void __iomem *addr; - - BUG_ON(len != 4); + u32 data; if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ addr = NETXEN_CRB_NORMALIZE(adapter, off); @@ -1220,24 +1019,21 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, return 1; } - *(u32 *)data = readl(addr); + data = readl(addr); if (!ADDR_IN_WINDOW1(off)) netxen_nic_pci_change_crbwindow_128M(adapter, 1); - return 0; + return data; } int -netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) { unsigned long flags = 0; int rv; - BUG_ON(len != 4); - - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); if (rv == -1) { printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", @@ -1250,26 +1046,24 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, write_lock_irqsave(&adapter->adapter_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); - writel(*(uint32_t *)data, (void __iomem *)off); + writel(data, (void __iomem *)off); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->adapter_lock, flags); } else - writel(*(uint32_t *)data, (void __iomem *)off); + writel(data, (void __iomem *)off); return 0; } -int -netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +u32 +netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) { unsigned long flags = 0; int rv; + u32 data; - BUG_ON(len != 4); - - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); if (rv == -1) { printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", @@ -1282,47 +1076,13 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, write_lock_irqsave(&adapter->adapter_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); - *(uint32_t *)data = readl((void __iomem *)off); + data = readl((void __iomem *)off); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->adapter_lock, flags); } else - *(uint32_t *)data = readl((void __iomem *)off); + data = readl((void __iomem *)off); - return 0; -} - -void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) -{ - adapter->hw_write_wx(adapter, off, &val, 4); -} - -int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) -{ - int val; - adapter->hw_read_wx(adapter, off, &val, 4); - return val; -} - -/* Change the window to 0, write and change back to window 1. */ -void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) -{ - adapter->hw_write_wx(adapter, index, &value, 4); -} - -/* Change the window to 0, read and change back to window 1. */ -void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value) -{ - adapter->hw_read_wx(adapter, index, value, 4); -} - -void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value) -{ - adapter->hw_write_wx(adapter, index, &value, 4); -} - -void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value) -{ - adapter->hw_read_wx(adapter, index, value, 4); + return data; } /* @@ -1425,17 +1185,6 @@ u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off) return readl((void __iomem *)(pci_base_offset(adapter, off))); } -void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter, - u64 off, u32 data) -{ - writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); -} - -u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off) -{ - return readl(NETXEN_CRB_NORMALIZE(adapter, off)); -} - unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, unsigned long long addr) @@ -1447,12 +1196,10 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, /* DDR network side */ window = MN_WIN(addr); adapter->ahw.ddr_mn_window = window; - adapter->hw_write_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &window, 4); - adapter->hw_read_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &win_read, 4); + NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, + window); + win_read = NXRD32(adapter, + adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); if ((win_read << 17) != window) { printk(KERN_INFO "Written MNwin (0x%x) != " "Read MNwin (0x%x)\n", window, win_read); @@ -1467,12 +1214,10 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, window = OCM_WIN(addr); adapter->ahw.ddr_mn_window = window; - adapter->hw_write_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &window, 4); - adapter->hw_read_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &win_read, 4); + NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, + window); + win_read = NXRD32(adapter, + adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); if ((win_read >> 7) != window) { printk(KERN_INFO "%s: Written OCMwin (0x%x) != " "Read OCMwin (0x%x)\n", @@ -1485,12 +1230,10 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, /* QDR network side */ window = MS_WIN(addr); adapter->ahw.qdr_sn_window = window; - adapter->hw_write_wx(adapter, - adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, - &window, 4); - adapter->hw_read_wx(adapter, - adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, - &win_read, 4); + NXWR32(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, + window); + win_read = NXRD32(adapter, + adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE); if (win_read != window) { printk(KERN_INFO "%s: Written MSwin (0x%x) != " "Read MSwin (0x%x)\n", @@ -1936,27 +1679,20 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { temp = off8 + (i << 3); - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); temp = 0; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); temp = word[i] & 0xffffffff; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); temp = (word[i] >> 32) & 0xffffffff; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_CTRL, &temp, 4); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp); temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_CTRL, &temp, 4); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp); for (j = 0; j < MAX_CTL_CHECK; j++) { - adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -2013,21 +1749,16 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { temp = off8 + (i << 3); - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); temp = 0; - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); temp = MIU_TA_CTL_ENABLE; - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp); temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp); for (j = 0; j < MAX_CTL_CHECK; j++) { - adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -2042,8 +1773,8 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, start = off0[i] >> 2; end = (off0[i] + sz[i] - 1) >> 2; for (k = start; k <= end; k++) { - adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4); + temp = NXRD32(adapter, + mem_crb + MIU_TEST_AGT_RDDATA(k)); word[i] |= ((uint64_t)temp << (32 * k)); } } @@ -2086,29 +1817,14 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, u64 off, u32 data) { - adapter->hw_write_wx(adapter, off, &data, 4); + NXWR32(adapter, off, data); return 0; } u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off) { - u32 temp; - adapter->hw_read_wx(adapter, off, &temp, 4); - return temp; -} - -void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter, - u64 off, u32 data) -{ - adapter->hw_write_wx(adapter, off, &data, 4); -} - -u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off) -{ - u32 temp; - adapter->hw_read_wx(adapter, off, &temp, 4); - return temp; + return NXRD32(adapter, off); } int netxen_nic_get_board_info(struct netxen_adapter *adapter) @@ -2142,13 +1858,12 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) adapter->ahw.board_type = board_type; if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { - u32 gpio = netxen_nic_reg_read(adapter, - NETXEN_ROMUSB_GLB_PAD_GPIO_I); + u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I); if ((gpio & 0x8000) == 0) board_type = NETXEN_BRDTYPE_P3_10G_TP; } - switch ((netxen_brdtype_t)board_type) { + switch (board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: adapter->ahw.port_type = NETXEN_NIC_GBE; break; @@ -2195,8 +1910,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu) { new_mtu += MTU_FUDGE_FACTOR; - netxen_nic_write_w0(adapter, - NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port), + NXWR32(adapter, NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port), new_mtu); return 0; } @@ -2205,21 +1919,12 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu) { new_mtu += MTU_FUDGE_FACTOR; if (adapter->physical_port == 0) - netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, - new_mtu); + NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); else - netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, - new_mtu); + NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu); return 0; } -void -netxen_crb_writelit_adapter(struct netxen_adapter *adapter, - unsigned long off, int data) -{ - adapter->hw_write_wx(adapter, off, &data, 4); -} - void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) { __u32 status; @@ -2234,8 +1939,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) } if (adapter->ahw.port_type == NETXEN_NIC_GBE) { - adapter->hw_read_wx(adapter, - NETXEN_PORT_MODE_ADDR, &port_mode, 4); + port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { adapter->link_speed = SPEED_1000; adapter->link_duplex = DUPLEX_FULL; @@ -2312,9 +2016,9 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) addr += sizeof(u32); } - adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4); - adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4); - adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4); + 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); @@ -2337,8 +2041,7 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) fw_major, fw_minor, fw_build); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - adapter->hw_read_wx(adapter, - NETXEN_MIU_MN_CONTROL, &i, 4); + i = NXRD32(adapter, NETXEN_MIU_MN_CONTROL); adapter->ahw.cut_through = (i & 0x4) ? 1 : 0; dev_info(&pdev->dev, "firmware running in %s mode\n", adapter->ahw.cut_through ? "cut-through" : "legacy"); @@ -2353,9 +2056,9 @@ netxen_nic_wol_supported(struct netxen_adapter *adapter) if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 0; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); if (wol_cfg & (1UL << adapter->portnum)) { - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); if (wol_cfg & (1 << adapter->portnum)) return 1; } diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index 04b47a7993cd..d4e833339781 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -36,35 +36,13 @@ /* Hardware memory size of 128 meg */ #define NETXEN_MEMADDR_MAX (128 * 1024 * 1024) -#ifndef readq -static inline u64 readq(void __iomem * addr) -{ - return readl(addr) | (((u64) readl(addr + 4)) << 32LL); -} -#endif - -#ifndef writeq -static inline void writeq(u64 val, void __iomem * addr) -{ - writel(((u32) (val)), (addr)); - writel(((u32) (val >> 32)), (addr + 4)); -} -#endif - struct netxen_adapter; #define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20) -struct netxen_port; void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); -typedef u8 netxen_ethernet_macaddr_t[6]; - /* Nibble or Byte mode for phy interface (GbE mode only) */ -typedef enum { - NETXEN_NIU_10_100_MB = 0, - NETXEN_NIU_1000_MB -} netxen_niu_gbe_ifmode_t; #define _netxen_crb_get_bit(var, bit) ((var >> bit) & 0x1) @@ -222,30 +200,28 @@ typedef enum { /* * PHY-Specific MII control/status registers. */ -typedef enum { - NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0, - NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3, - NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4, - NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5, - NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6, - NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7, - NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8, - NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9, - NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10, - NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20, - NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21, - NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24, - NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27 -} netxen_niu_phy_register_t; +#define NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL 0 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS 1 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 2 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 3 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG 4 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART 5 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE 6 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT 7 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE 8 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL 9 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS 10 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS 15 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL 16 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS 17 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE 18 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS 19 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE 20 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT 21 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL 24 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE 25 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET 26 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE 27 /* * PHY-Specific Status Register (reg 17). @@ -417,14 +393,6 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, u32 mode); -/* set the MAC address for a given MAC */ -int netxen_niu_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr); - -/* XG version */ -int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr); - /* Generic enable for GbE ports. Will detect the speed of the link. */ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 0759c35f16ac..6f77ad58e3b3 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -108,42 +108,6 @@ static void crb_addr_transform_setup(void) crb_addr_transform(I2C0); } -int netxen_init_firmware(struct netxen_adapter *adapter) -{ - u32 state = 0, loops = 0, err = 0; - - /* Window 1 call */ - state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE); - - if (state == PHAN_INITIALIZE_ACK) - return 0; - - while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) { - msleep(1); - /* Window 1 call */ - state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE); - - loops++; - } - if (loops >= 2000) { - printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n", - state); - err = -EIO; - return err; - } - /* Window 1 call */ - adapter->pci_write_normalize(adapter, - CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); - adapter->pci_write_normalize(adapter, - CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); - adapter->pci_write_normalize(adapter, - CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); - adapter->pci_write_normalize(adapter, - CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); - - return err; -} - void netxen_release_rx_buffers(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; @@ -173,9 +137,10 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) struct netxen_cmd_buffer *cmd_buf; struct netxen_skb_frag *buffrag; int i, j; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; - cmd_buf = adapter->cmd_buf_arr; - for (i = 0; i < adapter->num_txd; i++) { + cmd_buf = tx_ring->cmd_buf_arr; + for (i = 0; i < tx_ring->num_desc; i++) { buffrag = cmd_buf->frag_array; if (buffrag->dma) { pci_unmap_single(adapter->pdev, buffrag->dma, @@ -203,20 +168,27 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_tx_ring *tx_ring; int ring; recv_ctx = &adapter->recv_ctx; + + if (recv_ctx->rds_rings == NULL) + goto skip_rds; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - if (rds_ring->rx_buf_arr) { - vfree(rds_ring->rx_buf_arr); - rds_ring->rx_buf_arr = NULL; - } + vfree(rds_ring->rx_buf_arr); + rds_ring->rx_buf_arr = NULL; } + kfree(recv_ctx->rds_rings); - if (adapter->cmd_buf_arr) - vfree(adapter->cmd_buf_arr); - return; +skip_rds: + if (adapter->tx_ring == NULL) + return; + + tx_ring = adapter->tx_ring; + vfree(tx_ring->cmd_buf_arr); } int netxen_alloc_sw_resources(struct netxen_adapter *adapter) @@ -224,23 +196,45 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring; struct netxen_rx_buffer *rx_buf; - int ring, i, num_rx_bufs; + int ring, i, size; struct netxen_cmd_buffer *cmd_buf_arr; struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; - cmd_buf_arr = - (struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(adapter)); - if (cmd_buf_arr == NULL) { - printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n", + size = sizeof(struct nx_host_tx_ring); + tx_ring = kzalloc(size, GFP_KERNEL); + if (tx_ring == NULL) { + dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n", netdev->name); return -ENOMEM; } - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(adapter)); - adapter->cmd_buf_arr = cmd_buf_arr; + adapter->tx_ring = tx_ring; + + tx_ring->num_desc = adapter->num_txd; + + cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); + if (cmd_buf_arr == NULL) { + dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", + netdev->name); + return -ENOMEM; + } + memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); + tx_ring->cmd_buf_arr = cmd_buf_arr; recv_ctx = &adapter->recv_ctx; + + size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring); + rds_ring = kzalloc(size, GFP_KERNEL); + if (rds_ring == NULL) { + dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n", + netdev->name); + return -ENOMEM; + } + recv_ctx->rds_rings = rds_ring; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; switch (ring) { @@ -292,9 +286,8 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) * Now go through all of them, set reference handles * and put them in the queues. */ - num_rx_bufs = rds_ring->num_desc; rx_buf = rds_ring->rx_buf_arr; - for (i = 0; i < num_rx_bufs; i++) { + for (i = 0; i < rds_ring->num_desc; i++) { list_add_tail(&rx_buf->list, &rds_ring->free_list); rx_buf->ref_handle = i; @@ -307,8 +300,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; sds_ring->irq = adapter->msix_entries[ring].vector; - sds_ring->clean_tx = (ring == 0); - sds_ring->post_rxd = (ring == 0); sds_ring->adapter = adapter; sds_ring->num_desc = adapter->num_rxd; @@ -325,13 +316,15 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) { + adapter->macaddr_set = netxen_p2_nic_set_mac_addr; + adapter->set_multi = netxen_p2_nic_set_multi; + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: adapter->enable_phy_interrupts = netxen_niu_gbe_enable_phy_interrupts; adapter->disable_phy_interrupts = netxen_niu_gbe_disable_phy_interrupts; - adapter->macaddr_set = netxen_niu_macaddr_set; adapter->set_mtu = netxen_nic_set_mtu_gb; adapter->set_promisc = netxen_niu_set_promiscuous_mode; adapter->phy_read = netxen_niu_gbe_phy_read; @@ -345,7 +338,6 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) netxen_niu_xgbe_enable_phy_interrupts; adapter->disable_phy_interrupts = netxen_niu_xgbe_disable_phy_interrupts; - adapter->macaddr_set = netxen_niu_xg_macaddr_set; adapter->set_mtu = netxen_nic_set_mtu_xgb; adapter->init_port = netxen_niu_xg_init_port; adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode; @@ -359,6 +351,8 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { adapter->set_mtu = nx_fw_cmd_set_mtu; adapter->set_promisc = netxen_p3_nic_set_promisc; + adapter->macaddr_set = netxen_p3_nic_set_mac_addr; + adapter->set_multi = netxen_p3_nic_set_multi; } } @@ -400,8 +394,7 @@ static int rom_lock(struct netxen_adapter *adapter) while (!done) { /* acquire semaphore2 from PCI HW block */ - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK), - &done); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK)); if (done == 1) break; if (timeout >= rom_lock_timeout) @@ -418,7 +411,7 @@ static int rom_lock(struct netxen_adapter *adapter) cpu_relax(); /*This a nop instr on i386 */ } } - netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER); + NXWR32(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER); return 0; } @@ -430,7 +423,7 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) cond_resched(); while (done == 0) { - done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS); + done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS); done &= 2; timeout++; if (timeout >= rom_max_timeout) { @@ -443,30 +436,28 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) static void netxen_rom_unlock(struct netxen_adapter *adapter) { - u32 val; - /* release semaphore2 */ - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val); + NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK)); } static int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); + NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); + NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); + NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { printk("Error waiting for rom done\n"); return -EIO; } /* reset abyte_cnt and dummy_byte_cnt */ - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); udelay(10); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); - *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); + *valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA); return 0; } @@ -530,8 +521,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* resetall */ rom_lock(adapter); - netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, - 0xffffffff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); netxen_rom_unlock(adapter); if (verbose) { @@ -655,7 +645,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } } - adapter->hw_write_wx(adapter, off, &buf[i].data, 4); + NXWR32(adapter, off, buf[i].data); msleep(init_delay); } @@ -665,36 +655,230 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* unreset_net_cache */ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, &val, 4); - netxen_crb_writelit_adapter(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f)); + val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f)); } /* p2dn replyCount */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e); + NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e); /* disable_peg_cache 0 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8); + NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8); /* disable_peg_cache 1 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8); + NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8); /* peg_clr_all */ /* peg_clr 0 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0); /* peg_clr 1 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0); /* peg_clr 2 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0); /* peg_clr 3 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0); return 0; } +int +netxen_load_firmware(struct netxen_adapter *adapter) +{ + u64 *ptr64; + u32 i, flashaddr, size; + const struct firmware *fw = adapter->fw; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); + + if (fw) { + __le64 data; + + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; + + ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; + flashaddr = NETXEN_BOOTLD_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + adapter->pci_mem_write(adapter, flashaddr, &data, 8); + flashaddr += 8; + } + + size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; + size = (__force u32)cpu_to_le32(size) / 8; + + ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; + flashaddr = NETXEN_IMAGE_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + + if (adapter->pci_mem_write(adapter, + flashaddr, &data, 8)) + return -EIO; + + flashaddr += 8; + } + } else { + u32 data; + + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; + flashaddr = NETXEN_BOOTLD_START; + + for (i = 0; i < size; i++) { + if (netxen_rom_fast_read(adapter, + flashaddr, (int *)&data) != 0) + return -EIO; + + if (adapter->pci_mem_write(adapter, + flashaddr, &data, 4)) + return -EIO; + + flashaddr += 4; + } + } + msleep(1); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); + else { + NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); + } + + return 0; +} + +static int +netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) +{ + __le32 val; + u32 major, minor, build, ver, min_ver, bios; + struct pci_dev *pdev = adapter->pdev; + const struct firmware *fw = adapter->fw; + + if (fw->size < NX_FW_MIN_SIZE) + return -EINVAL; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); + if ((__force u32)val != NETXEN_BDINFO_MAGIC) + return -EINVAL; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); + major = (__force u32)val & 0xff; + minor = ((__force u32)val >> 8) & 0xff; + build = (__force u32)val >> 16; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + min_ver = NETXEN_VERSION_CODE(4, 0, 216); + else + min_ver = NETXEN_VERSION_CODE(3, 4, 216); + + ver = NETXEN_VERSION_CODE(major, minor, build); + + if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { + dev_err(&pdev->dev, + "%s: firmware version %d.%d.%d unsupported\n", + fwname, major, minor, build); + return -EINVAL; + } + + val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); + netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); + if ((__force u32)val != bios) { + dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", + fwname); + return -EINVAL; + } + + /* check if flashed firmware is newer */ + if (netxen_rom_fast_read(adapter, + NX_FW_VERSION_OFFSET, (int *)&val)) + return -EIO; + major = (__force u32)val & 0xff; + minor = ((__force u32)val >> 8) & 0xff; + build = (__force u32)val >> 16; + if (NETXEN_VERSION_CODE(major, minor, build) > ver) + return -EINVAL; + + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + return 0; +} + +static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; + +void netxen_request_firmware(struct netxen_adapter *adapter) +{ + u32 capability, flashed_ver; + int 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, + NX_FW_VERSION_OFFSET, (int *)&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; + } + } + +request_fw: + rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); + if (rc != 0) { + if (fw_type == NX_P3_CT_ROMIMAGE) { + msleep(1); + goto request_mn; + } + + adapter->fw = NULL; + goto done; + } + + rc = netxen_validate_firmware(adapter, fw_name[fw_type]); + if (rc != 0) { + release_firmware(adapter->fw); + + if (fw_type == NX_P3_CT_ROMIMAGE) { + msleep(1); + goto request_mn; + } + + adapter->fw = NULL; + goto done; + } + +done: + if (adapter->fw) + dev_info(&pdev->dev, "loading firmware from file %s\n", + fw_name[fw_type]); + else + dev_info(&pdev->dev, "loading firmware from flash\n"); +} + + +void +netxen_release_firmware(struct netxen_adapter *adapter) +{ + if (adapter->fw) + release_firmware(adapter->fw); +} + int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) { uint64_t addr; @@ -715,12 +899,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) hi = (addr >> 32) & 0xffffffff; lo = addr & 0xffffffff; - adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); - adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); + 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; - adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4); + NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp); } return 0; @@ -762,8 +946,7 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) if (!pegtune_val) { do { - val = adapter->pci_read_normalize(adapter, - CRB_CMDPEG_STATE); + val = NXRD32(adapter, CRB_CMDPEG_STATE); if (val == PHAN_INITIALIZE_COMPLETE || val == PHAN_INITIALIZE_ACK) @@ -774,7 +957,7 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) } while (--retries); if (!retries) { - pegtune_val = adapter->pci_read_normalize(adapter, + pegtune_val = NXRD32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE); printk(KERN_WARNING "netxen_phantom_init: init failed, " "pegtune_val=%x\n", pegtune_val); @@ -785,13 +968,14 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) return 0; } -int netxen_receive_peg_ready(struct netxen_adapter *adapter) +static int +netxen_receive_peg_ready(struct netxen_adapter *adapter) { u32 val = 0; int retries = 2000; do { - val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE); + val = NXRD32(adapter, CRB_RCVPEG_STATE); if (val == PHAN_PEG_RCV_INITIALIZED) return 0; @@ -809,6 +993,93 @@ int netxen_receive_peg_ready(struct netxen_adapter *adapter) return 0; } +int netxen_init_firmware(struct netxen_adapter *adapter) +{ + int err; + + err = netxen_receive_peg_ready(adapter); + if (err) + return err; + + NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); + NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); + 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; +} + +static void +netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) +{ + u32 cable_OUI; + u16 cable_len; + u16 link_speed; + u8 link_status, module, duplex, autoneg; + struct net_device *netdev = adapter->netdev; + + adapter->has_link_events = 1; + + cable_OUI = msg->body[1] & 0xffffffff; + cable_len = (msg->body[1] >> 32) & 0xffff; + link_speed = (msg->body[1] >> 48) & 0xffff; + + link_status = msg->body[2] & 0xff; + duplex = (msg->body[2] >> 16) & 0xff; + autoneg = (msg->body[2] >> 24) & 0xff; + + module = (msg->body[2] >> 8) & 0xff; + if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) { + printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n", + netdev->name, cable_OUI, cable_len); + } else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) { + printk(KERN_INFO "%s: unsupported cable length %d\n", + netdev->name, cable_len); + } + + netxen_advert_link_change(adapter, link_status); + + /* update link parameters */ + if (duplex == LINKEVENT_FULL_DUPLEX) + adapter->link_duplex = DUPLEX_FULL; + else + adapter->link_duplex = DUPLEX_HALF; + adapter->module_type = module; + adapter->link_autoneg = autoneg; + adapter->link_speed = link_speed; +} + +static void +netxen_handle_fw_message(int desc_cnt, int index, + struct nx_host_sds_ring *sds_ring) +{ + nx_fw_msg_t msg; + struct status_desc *desc; + int i = 0, opcode; + + while (desc_cnt > 0 && i < 8) { + desc = &sds_ring->desc_head[index]; + msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); + msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); + + index = get_next_index(index, sds_ring->num_desc); + desc_cnt--; + } + + opcode = netxen_get_nic_msg_opcode(msg.body[0]); + switch (opcode) { + case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: + netxen_handle_linkevent(sds_ring->adapter, &msg); + break; + default: + break; + } +} + static int netxen_alloc_rx_skb(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring, @@ -874,7 +1145,8 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, static struct netxen_rx_buffer * netxen_process_rcv(struct netxen_adapter *adapter, - int ring, int index, int length, int cksum, int pkt_offset) + int ring, int index, int length, int cksum, int pkt_offset, + struct nx_host_sds_ring *sds_ring) { struct net_device *netdev = adapter->netdev; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; @@ -902,7 +1174,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, skb->protocol = eth_type_trans(skb, netdev); - netif_receive_skb(skb); + napi_gro_receive(&sds_ring->napi, skb); adapter->stats.no_rcv++; adapter->stats.rxbytes += length; @@ -927,35 +1199,53 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) int count = 0; u64 sts_data; - int opcode, ring, index, length, cksum, pkt_offset; + int opcode, ring, index, length, cksum, pkt_offset, desc_cnt; while (count < max) { desc = &sds_ring->desc_head[consumer]; - sts_data = le64_to_cpu(desc->status_desc_data); + sts_data = le64_to_cpu(desc->status_desc_data[0]); if (!(sts_data & 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) - continue; + goto skip; opcode = netxen_get_sts_opcode(sts_data); + switch (opcode) { + case NETXEN_NIC_RXPKT_DESC: + case NETXEN_OLD_RXPKT_DESC: + break; + case NETXEN_NIC_RESPONSE_DESC: + netxen_handle_fw_message(desc_cnt, consumer, sds_ring); + default: + goto skip; + } + + 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); + length, cksum, pkt_offset, sds_ring); if (rxbuf) list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); - desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); - - consumer = get_next_index(consumer, sds_ring->num_desc); +skip: + for (; desc_cnt > 0; desc_cnt--) { + desc = &sds_ring->desc_head[consumer]; + desc->status_desc_data[0] = + cpu_to_le64(STATUS_OWNER_PHANTOM); + consumer = get_next_index(consumer, sds_ring->num_desc); + } count++; } @@ -980,8 +1270,7 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) if (count) { sds_ring->consumer = consumer; - adapter->pci_write_normalize(adapter, - sds_ring->crb_sts_consumer, consumer); + NXWR32(adapter, sds_ring->crb_sts_consumer, consumer); } return count; @@ -990,23 +1279,24 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) /* Process Command status ring */ int netxen_process_cmd_ring(struct netxen_adapter *adapter) { - u32 last_consumer, consumer; + u32 sw_consumer, hw_consumer; int count = 0, i; struct netxen_cmd_buffer *buffer; struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; struct netxen_skb_frag *frag; int done = 0; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; if (!spin_trylock(&adapter->tx_clean_lock)) return 1; - last_consumer = adapter->last_cmd_consumer; - barrier(); /* cmd_consumer can change underneath */ - consumer = le32_to_cpu(*(adapter->cmd_consumer)); + sw_consumer = tx_ring->sw_consumer; + barrier(); /* hw_consumer can change underneath */ + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); - while (last_consumer != consumer) { - buffer = &adapter->cmd_buf_arr[last_consumer]; + while (sw_consumer != hw_consumer) { + buffer = &tx_ring->cmd_buf_arr[sw_consumer]; if (buffer->skb) { frag = &buffer->frag_array[0]; pci_unmap_single(pdev, frag->dma, frag->length, @@ -1024,16 +1314,16 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) buffer->skb = NULL; } - last_consumer = get_next_index(last_consumer, - adapter->num_txd); + sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); if (++count >= MAX_STATUS_HANDLE) break; } - if (count) { - adapter->last_cmd_consumer = last_consumer; + tx_ring->sw_consumer = sw_consumer; + + if (count && netif_running(netdev)) { smp_mb(); - if (netif_queue_stopped(netdev) && netif_running(netdev)) { + if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { netif_tx_lock(netdev); netif_wake_queue(netdev); smp_mb(); @@ -1053,9 +1343,9 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) * There is still a possible race condition and the host could miss an * interrupt. The card has to take care of this. */ - barrier(); /* cmd_consumer can change underneath */ - consumer = le32_to_cpu(*(adapter->cmd_consumer)); - done = (last_consumer == consumer); + barrier(); /* hw_consumer can change underneath */ + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); + done = (sw_consumer == hw_consumer); spin_unlock(&adapter->tx_clean_lock); return (done); @@ -1099,8 +1389,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, if (count) { rds_ring->producer = producer; - adapter->pci_write_normalize(adapter, - rds_ring->crb_rcv_producer, + NXWR32(adapter, rds_ring->crb_rcv_producer, (producer-1) & (rds_ring->num_desc-1)); if (adapter->fw_major < 4) { @@ -1160,10 +1449,8 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, if (count) { rds_ring->producer = producer; - adapter->pci_write_normalize(adapter, - rds_ring->crb_rcv_producer, + NXWR32(adapter, rds_ring->crb_rcv_producer, (producer - 1) & (rds_ring->num_desc - 1)); - wmb(); } spin_unlock(&rds_ring->lock); } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index aef77289bd34..98737ef72936 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -29,7 +29,7 @@ */ #include -#include +#include #include "netxen_nic_hw.h" #include "netxen_nic.h" @@ -107,10 +107,9 @@ static uint32_t crb_cmd_producer[4] = { void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, - uint32_t crb_producer) + struct nx_host_tx_ring *tx_ring, u32 producer) { - adapter->pci_write_normalize(adapter, - adapter->crb_addr_cmd_producer, crb_producer); + NXWR32(adapter, tx_ring->crb_cmd_producer, producer); } static uint32_t crb_cmd_consumer[4] = { @@ -120,10 +119,9 @@ static uint32_t crb_cmd_consumer[4] = { static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, - u32 crb_consumer) + struct nx_host_tx_ring *tx_ring, u32 consumer) { - adapter->pci_write_normalize(adapter, - adapter->crb_addr_cmd_consumer, crb_consumer); + NXWR32(adapter, tx_ring->crb_cmd_consumer, consumer); } static uint32_t msi_tgt_status[8] = { @@ -139,37 +137,54 @@ static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0); + NXWR32(adapter, sds_ring->crb_intr_mask, 0); } static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1); + NXWR32(adapter, sds_ring->crb_intr_mask, 0x1); if (!NETXEN_IS_MSI_FAMILY(adapter)) adapter->pci_write_immediate(adapter, adapter->legacy_intr.tgt_mask_reg, 0xfbff); } +static int +netxen_alloc_sds_rings(struct netxen_recv_context *recv_ctx, int count) +{ + int size = sizeof(struct nx_host_sds_ring) * count; + + recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL); + + return (recv_ctx->sds_rings == NULL); +} + static void +netxen_free_sds_rings(struct netxen_recv_context *recv_ctx) +{ + if (recv_ctx->sds_rings != NULL) + kfree(recv_ctx->sds_rings); +} + +static int netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) { int ring; struct nx_host_sds_ring *sds_ring; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) - adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2; - else - adapter->max_sds_rings = 1; + if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) + return 1; for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; netif_napi_add(netdev, &sds_ring->napi, netxen_nic_poll, NETXEN_NETDEV_WEIGHT); } + + return 0; } static void @@ -195,8 +210,9 @@ netxen_napi_disable(struct netxen_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; - netxen_nic_disable_int(sds_ring); napi_disable(&sds_ring->napi); + netxen_nic_disable_int(sds_ring); + synchronize_irq(sds_ring->irq); } } @@ -240,7 +256,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) change = 0; - shift = netxen_nic_reg_read(adapter, CRB_DMA_SHIFT); + shift = NXRD32(adapter, CRB_DMA_SHIFT); if (shift >= 32) return 0; @@ -268,10 +284,21 @@ static void netxen_check_options(struct netxen_adapter *adapter) else if (adapter->ahw.port_type == NETXEN_NIC_GBE) adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + adapter->msix_supported = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { adapter->msix_supported = !!use_msi_x; - else - adapter->msix_supported = 0; + adapter->rss_supported = !!use_msi_x; + } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) { + switch (adapter->ahw.board_type) { + case NETXEN_BRDTYPE_P2_SB31_10G: + case NETXEN_BRDTYPE_P2_SB31_10G_CX4: + adapter->msix_supported = !!use_msi_x; + adapter->rss_supported = !!use_msi_x; + break; + default: + break; + } + } adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST; adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; @@ -287,43 +314,34 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) if (first_boot == 0x55555555) { /* This is the first boot after power up */ - adapter->pci_write_normalize(adapter, - NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 0; /* PCI bus master workaround */ - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(0x4), &first_boot, 4); + first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4)); if (!(first_boot & 0x4)) { first_boot |= 0x4; - adapter->hw_write_wx(adapter, - NETXEN_PCIE_REG(0x4), &first_boot, 4); - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(0x4), &first_boot, 4); + NXWR32(adapter, NETXEN_PCIE_REG(0x4), first_boot); + first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4)); } /* This is the first boot after power up */ - adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4); + first_boot = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET); if (first_boot != 0x80000f) { /* clear the register for future unloads/loads */ - adapter->pci_write_normalize(adapter, - NETXEN_CAM_RAM(0x1fc), 0); + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), 0); return -EIO; } /* Start P2 boot loader */ - val = adapter->pci_read_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE); - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); + val = NXRD32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE); + NXWR32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); timeout = 0; do { msleep(1); - val = adapter->pci_read_normalize(adapter, - NETXEN_CAM_RAM(0x1fc)); + val = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); if (++timeout > 5000) return -EIO; @@ -342,24 +360,19 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) (val == NETXEN_BRDTYPE_P3_XG_LOM)) { if (port_mode == NETXEN_PORT_MODE_802_3_AP) { data = NETXEN_PORT_MODE_802_3_AP; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_XG) { data = NETXEN_PORT_MODE_XG; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) { data = NETXEN_PORT_MODE_AUTO_NEG_1G; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) { data = NETXEN_PORT_MODE_AUTO_NEG_XG; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else { data = NETXEN_PORT_MODE_AUTO_NEG; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) && @@ -368,8 +381,7 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) { wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG; } - adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE, - &wol_port_mode, 4); + NXWR32(adapter, NETXEN_WOL_PORT_MODE, wol_port_mode); } } @@ -389,11 +401,11 @@ static void netxen_set_msix_bit(struct pci_dev *pdev, int enable) } } -static void netxen_init_msix_entries(struct netxen_adapter *adapter) +static void netxen_init_msix_entries(struct netxen_adapter *adapter, int count) { int i; - for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++) + for (i = 0; i < count; i++) adapter->msix_entries[i].entry = i; } @@ -424,20 +436,38 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) if (!is_valid_ether_addr(netdev->perm_addr)) dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr); - else - adapter->macaddr_set(adapter, netdev->dev_addr); return 0; } +int netxen_nic_set_mac(struct net_device *netdev, void *p) +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + if (netif_running(netdev)) { + netif_device_detach(netdev); + netxen_napi_disable(adapter); + } + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + adapter->macaddr_set(adapter, addr->sa_data); + + if (netif_running(netdev)) { + netif_device_attach(netdev); + netxen_napi_enable(adapter); + } + return 0; +} + static void netxen_set_multicast_list(struct net_device *dev) { struct netxen_adapter *adapter = netdev_priv(dev); - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - netxen_p3_nic_set_multi(dev); - else - netxen_p2_nic_set_multi(dev); + adapter->set_multi(dev); } static const struct net_device_ops netxen_netdev_ops = { @@ -460,10 +490,17 @@ netxen_setup_intr(struct netxen_adapter *adapter) { struct netxen_legacy_intr_set *legacy_intrp; struct pci_dev *pdev = adapter->pdev; + int err, num_msix; + + if (adapter->rss_supported) { + num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? + MSIX_ENTRIES_PER_ADAPTER : 2; + } else + num_msix = 1; + + adapter->max_sds_rings = 1; adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); - adapter->intr_scheme = -1; - adapter->msi_mode = -1; if (adapter->ahw.revision_id >= NX_P3_B0) legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; @@ -478,24 +515,36 @@ netxen_setup_intr(struct netxen_adapter *adapter) if (adapter->msix_supported) { - netxen_init_msix_entries(adapter); - if (pci_enable_msix(pdev, adapter->msix_entries, - MSIX_ENTRIES_PER_ADAPTER)) - goto request_msi; + netxen_init_msix_entries(adapter, num_msix); + err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); + if (err == 0) { + adapter->flags |= NETXEN_NIC_MSIX_ENABLED; + netxen_set_msix_bit(pdev, 1); - adapter->flags |= NETXEN_NIC_MSIX_ENABLED; - netxen_set_msix_bit(pdev, 1); - dev_info(&pdev->dev, "using msi-x interrupts\n"); + if (adapter->rss_supported) + adapter->max_sds_rings = num_msix; - } else { -request_msi: - if (use_msi && !pci_enable_msi(pdev)) { - adapter->flags |= NETXEN_NIC_MSI_ENABLED; - dev_info(&pdev->dev, "using msi interrupts\n"); - } else - dev_info(&pdev->dev, "using legacy interrupts\n"); - adapter->msix_entries[0].vector = pdev->irq; + dev_info(&pdev->dev, "using msi-x interrupts\n"); + return; + } + + if (err > 0) + pci_disable_msix(pdev); + + /* fall through for msi */ } + + if (use_msi && !pci_enable_msi(pdev)) { + adapter->flags |= NETXEN_NIC_MSI_ENABLED; + adapter->msi_tgt_status = + msi_tgt_status[adapter->ahw.pci_func]; + dev_info(&pdev->dev, "using msi interrupts\n"); + adapter->msix_entries[0].vector = pdev->irq; + return; + } + + dev_info(&pdev->dev, "using legacy interrupts\n"); + adapter->msix_entries[0].vector = pdev->irq; } static void @@ -552,8 +601,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) adapter->hw_read_wx = netxen_nic_hw_read_wx_128M; adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M; adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M; - adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M; - adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M; adapter->pci_set_window = netxen_nic_pci_set_window_128M; adapter->pci_mem_read = netxen_nic_pci_mem_read_128M; adapter->pci_mem_write = netxen_nic_pci_mem_write_128M; @@ -575,9 +622,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M; adapter->pci_write_immediate = netxen_nic_pci_write_immediate_2M; - adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M; - adapter->pci_write_normalize = - netxen_nic_pci_write_normalize_2M; adapter->pci_set_window = netxen_nic_pci_set_window_2M; adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; @@ -643,25 +687,22 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) } static int -netxen_start_firmware(struct netxen_adapter *adapter) +netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) { int val, err, first_boot; struct pci_dev *pdev = adapter->pdev; int first_driver = 0; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - if (adapter->ahw.pci_func == 0) - first_driver = 1; - } else { - if (adapter->portnum == 0) - first_driver = 1; - } + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + first_driver = (adapter->portnum == 0); + else + first_driver = (adapter->ahw.pci_func == 0); if (!first_driver) return 0; - first_boot = adapter->pci_read_normalize(adapter, - NETXEN_CAM_RAM(0x1fc)); + first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); err = netxen_check_hw_init(adapter, first_boot); if (err) { @@ -669,14 +710,16 @@ netxen_start_firmware(struct netxen_adapter *adapter) return err; } + if (request_fw) + netxen_request_firmware(adapter); + if (first_boot != 0x55555555) { - adapter->pci_write_normalize(adapter, - CRB_CMDPEG_STATE, 0); + NXWR32(adapter, CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); msleep(1); } - netxen_nic_reg_write(adapter, CRB_DMA_SHIFT, 0x55555555); + NXWR32(adapter, CRB_DMA_SHIFT, 0x55555555); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_set_port_mode(adapter); @@ -688,8 +731,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) val = 0x7654; if (adapter->ahw.port_type == NETXEN_NIC_XGBE) val |= 0x0f000000; - netxen_crb_writelit_adapter(adapter, - NETXEN_MAC_ADDR_CNTL_REG, val); + NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); } @@ -703,7 +745,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) val = (_NETXEN_NIC_LINUX_MAJOR << 16) | ((_NETXEN_NIC_LINUX_MINOR << 8)) | (_NETXEN_NIC_LINUX_SUBVERSION); - adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, val); + NXWR32(adapter, CRB_DRIVER_VERSION, val); /* Handshake with the card before we register the devices. */ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); @@ -726,15 +768,6 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || - (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { - printk(KERN_ERR "%s: Firmware interrupt scheme is " - "incompatible with driver\n", - netdev->name); - adapter->driver_mismatch = 1; - return -EINVAL; - } - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) handler = netxen_msix_intr; else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) @@ -747,7 +780,7 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; - sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring); + sprintf(sds_ring->name, "%s[%d]", netdev->name, ring); err = request_irq(sds_ring->irq, handler, flags, sds_ring->name, sds_ring); if (err) @@ -782,22 +815,26 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) netxen_nic_driver_name, adapter->portnum); return err; } - adapter->macaddr_set(adapter, netdev->dev_addr); + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + adapter->macaddr_set(adapter, netdev->dev_addr); - netxen_nic_set_link_parameters(adapter); - - netxen_set_multicast_list(netdev); - if (adapter->set_mtu) - adapter->set_mtu(adapter, netdev->mtu); + adapter->set_multi(netdev); + adapter->set_mtu(adapter, netdev->mtu); adapter->ahw.linkup = 0; - mod_timer(&adapter->watchdog_timer, jiffies); netxen_napi_enable(adapter); if (adapter->max_sds_rings > 1) netxen_config_rss(adapter, 1); + if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) + netxen_linkevent_request(adapter, 1); + else + netxen_nic_set_link_parameters(adapter); + + mod_timer(&adapter->watchdog_timer, jiffies); + return 0; } @@ -806,11 +843,15 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) { netif_carrier_off(netdev); netif_stop_queue(netdev); - netxen_napi_disable(adapter); if (adapter->stop_port) adapter->stop_port(adapter); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_p3_free_mac_list(adapter); + + netxen_napi_disable(adapter); + netxen_release_tx_buffers(adapter); FLUSH_SCHEDULED_WORK(); @@ -825,6 +866,7 @@ netxen_nic_attach(struct netxen_adapter *adapter) struct pci_dev *pdev = adapter->pdev; int err, ring; struct nx_host_rds_ring *rds_ring; + struct nx_host_tx_ring *tx_ring; err = netxen_init_firmware(adapter); if (err != 0) { @@ -854,13 +896,12 @@ netxen_nic_attach(struct netxen_adapter *adapter) } if (adapter->fw_major < 4) { - adapter->crb_addr_cmd_producer = - crb_cmd_producer[adapter->portnum]; - adapter->crb_addr_cmd_consumer = - crb_cmd_consumer[adapter->portnum]; + 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]; - netxen_nic_update_cmd_producer(adapter, 0); - netxen_nic_update_cmd_consumer(adapter, 0); + netxen_nic_update_cmd_producer(adapter, tx_ring, 0); + netxen_nic_update_cmd_consumer(adapter, tx_ring, 0); } for (ring = 0; ring < adapter->max_rds_rings; ring++) { @@ -889,10 +930,9 @@ netxen_nic_attach(struct netxen_adapter *adapter) static void netxen_nic_detach(struct netxen_adapter *adapter) { - netxen_nic_free_irq(adapter); - netxen_release_rx_buffers(adapter); netxen_free_hw_resources(adapter); + netxen_nic_free_irq(adapter); netxen_free_sw_resources(adapter); adapter->is_up = 0; @@ -957,6 +997,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rwlock_init(&adapter->adapter_lock); spin_lock_init(&adapter->tx_clean_lock); + INIT_LIST_HEAD(&adapter->mac_list); err = netxen_setup_pci_map(adapter); if (err) @@ -979,6 +1020,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 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)) { @@ -1011,7 +1053,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - err = netxen_start_firmware(adapter); + err = netxen_start_firmware(adapter, 1); if (err) goto err_out_iounmap; @@ -1024,8 +1066,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ adapter->physical_port = adapter->portnum; if (adapter->fw_major < 4) { - i = adapter->pci_read_normalize(adapter, - CRB_V2P(adapter->portnum)); + i = NXRD32(adapter, CRB_V2P(adapter->portnum)); if (i != 0x55555555) adapter->physical_port = i; } @@ -1036,10 +1077,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->irq = adapter->msix_entries[0].vector; - netxen_napi_add(adapter, netdev); - - err = netxen_receive_peg_ready(adapter); - if (err) + if (netxen_napi_add(adapter, netdev)) goto err_out_disable_msi; init_timer(&adapter->watchdog_timer); @@ -1113,18 +1151,18 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { netxen_nic_detach(adapter); - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - netxen_p3_free_mac_list(adapter); } if (adapter->portnum == 0) netxen_free_adapter_offload(adapter); netxen_teardown_intr(adapter); + netxen_free_sds_rings(&adapter->recv_ctx); netxen_cleanup_pci_map(adapter); + netxen_release_firmware(adapter); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -1176,7 +1214,7 @@ netxen_nic_resume(struct pci_dev *pdev) adapter->curr_window = 255; - err = netxen_start_firmware(adapter); + err = netxen_start_firmware(adapter, 0); if (err) { dev_err(&pdev->dev, "failed to start firmware\n"); return err; @@ -1315,7 +1353,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct netxen_hardware_context *hw = &adapter->ahw; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; unsigned int first_seg_len = skb->len - skb->data_len; struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; @@ -1326,28 +1364,26 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) u32 producer, consumer; int frag_count, no_of_desc; - u32 num_txd = adapter->num_txd; + u32 num_txd = tx_ring->num_desc; bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; - /* There 4 fragments per descriptor */ + /* 4 fragments per cmd des */ no_of_desc = (frag_count + 3) >> 2; - producer = adapter->cmd_producer; + producer = tx_ring->producer; smp_mb(); - consumer = adapter->last_cmd_consumer; - if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) { + consumer = tx_ring->sw_consumer; + if ((no_of_desc+2) >= find_diff_among(producer, consumer, num_txd)) { netif_stop_queue(netdev); smp_mb(); return NETDEV_TX_BUSY; } - /* Copy the descriptors into the hardware */ - hwdesc = &hw->cmd_desc_head[producer]; + hwdesc = &tx_ring->desc_head[producer]; netxen_clear_cmddesc((u64 *)hwdesc); - /* Take skb->data itself */ - pbuf = &adapter->cmd_buf_arr[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; is_tso = netxen_tso_check(netdev, hwdesc, skb); @@ -1376,9 +1412,9 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if ((i & 0x3) == 0) { k = 0; producer = get_next_index(producer, num_txd); - hwdesc = &hw->cmd_desc_head[producer]; + hwdesc = &tx_ring->desc_head[producer]; netxen_clear_cmddesc((u64 *)hwdesc); - pbuf = &adapter->cmd_buf_arr[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; } frag = &skb_shinfo(skb)->frags[i - 1]; @@ -1430,8 +1466,8 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) more_hdr = 0; } /* copy the MAC/IP/TCP headers to the cmd descriptor list */ - hwdesc = &hw->cmd_desc_head[producer]; - pbuf = &adapter->cmd_buf_arr[producer]; + hwdesc = &tx_ring->desc_head[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; /* copy the first 64 bytes */ @@ -1440,8 +1476,8 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) producer = get_next_index(producer, num_txd); if (more_hdr) { - hwdesc = &hw->cmd_desc_head[producer]; - pbuf = &adapter->cmd_buf_arr[producer]; + 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 @@ -1454,13 +1490,12 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } - adapter->cmd_producer = producer; + tx_ring->producer = producer; adapter->stats.txbytes += skb->len; - netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); + netxen_nic_update_cmd_producer(adapter, tx_ring, producer); adapter->stats.xmitcalled++; - netdev->trans_start = jiffies; return NETDEV_TX_OK; @@ -1476,7 +1511,7 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) uint32_t temp, temp_state, temp_val; int rv = 0; - temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE); + temp = NXRD32(adapter, CRB_TEMP_STATE); temp_state = nx_get_temp_state(temp); temp_val = nx_get_temp_val(temp); @@ -1510,26 +1545,9 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) return rv; } -static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) +void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) { struct net_device *netdev = adapter->netdev; - u32 val, port, linkup; - - port = adapter->physical_port; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3); - val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); - linkup = (val == XG_LINK_UP_P3); - } else { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); - if (adapter->ahw.port_type == NETXEN_NIC_GBE) - linkup = (val >> port) & 1; - else { - val = (val >> port*8) & 0xff; - linkup = (val == XG_LINK_UP); - } - } if (adapter->ahw.linkup && !linkup) { printk(KERN_INFO "%s: %s NIC Link is down\n", @@ -1540,7 +1558,9 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_stop_queue(netdev); } - netxen_nic_set_link_parameters(adapter); + if (!adapter->has_link_events) + netxen_nic_set_link_parameters(adapter); + } else if (!adapter->ahw.linkup && linkup) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); @@ -1550,10 +1570,34 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_wake_queue(netdev); } - netxen_nic_set_link_parameters(adapter); + if (!adapter->has_link_events) + netxen_nic_set_link_parameters(adapter); } } +static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) +{ + u32 val, port, linkup; + + port = adapter->physical_port; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + val = NXRD32(adapter, CRB_XG_STATE_P3); + val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); + linkup = (val == XG_LINK_UP_P3); + } else { + val = NXRD32(adapter, CRB_XG_STATE); + if (adapter->ahw.port_type == NETXEN_NIC_GBE) + linkup = (val >> port) & 1; + else { + val = (val >> port*8) & 0xff; + linkup = (val == XG_LINK_UP); + } + } + + netxen_advert_link_change(adapter, linkup); +} + static void netxen_watchdog(unsigned long v) { struct netxen_adapter *adapter = (struct netxen_adapter *)v; @@ -1569,7 +1613,8 @@ void netxen_watchdog_task(struct work_struct *work) if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) return; - netxen_nic_handle_phy_intr(adapter); + if (!adapter->has_link_events) + netxen_nic_handle_phy_intr(adapter); if (netif_running(adapter->netdev)) mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); @@ -1598,10 +1643,6 @@ static void netxen_tx_timeout_task(struct work_struct *work) netif_wake_queue(adapter->netdev); } -/* - * netxen_nic_get_stats - Get System Network Statistics - * @netdev: network interface device structure - */ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); @@ -1609,22 +1650,11 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) memset(stats, 0, sizeof(*stats)); - /* total packets received */ stats->rx_packets = adapter->stats.no_rcv; - /* total packets transmitted */ - stats->tx_packets = adapter->stats.xmitedframes + - adapter->stats.xmitfinished; - /* total bytes received */ + stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes; - /* total bytes transmitted */ stats->tx_bytes = adapter->stats.txbytes; - /* bad packets received */ - stats->rx_errors = adapter->stats.rcvdbadskb; - /* packet transmit problems */ - stats->tx_errors = adapter->stats.nocmddescriptor; - /* no space in linux buffers */ stats->rx_dropped = adapter->stats.rxdropped; - /* no space available in linux */ stats->tx_dropped = adapter->stats.txdropped; return stats; @@ -1651,15 +1681,14 @@ static irqreturn_t netxen_intr(int irq, void *data) } else { unsigned long our_int = 0; - our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR); + our_int = NXRD32(adapter, CRB_INT_VECTOR); /* not our interrupt */ if (!test_and_clear_bit((7 + adapter->portnum), &our_int)) return IRQ_NONE; /* claim interrupt */ - adapter->pci_write_normalize(adapter, - CRB_INT_VECTOR, (our_int & 0xffffffff)); + NXWR32(adapter, CRB_INT_VECTOR, (our_int & 0xffffffff)); } /* clear interrupt */ @@ -1685,7 +1714,7 @@ static irqreturn_t netxen_msi_intr(int irq, void *data) /* clear interrupt */ adapter->pci_write_immediate(adapter, - msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); + adapter->msi_tgt_status, 0xffffffff); napi_schedule(&sds_ring->napi); return IRQ_HANDLED; diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index d85203203d4d..5941c79be723 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -43,8 +43,7 @@ static int phy_lock(struct netxen_adapter *adapter) int done = 0, timeout = 0; while (!done) { - done = netxen_nic_reg_read(adapter, - NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); if (done == 1) break; if (timeout >= phy_lock_timeout) { @@ -59,8 +58,7 @@ static int phy_lock(struct netxen_adapter *adapter) } } - netxen_crb_writelit_adapter(adapter, - NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER); + NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER); return 0; } @@ -105,9 +103,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, * so it cannot be in reset */ - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) - return -EIO; + mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); if (netxen_gb_get_soft_reset(mac_cfg0)) { __u32 temp; temp = 0; @@ -115,9 +111,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, netxen_gb_rx_reset_pb(temp); netxen_gb_tx_reset_mac(temp); netxen_gb_rx_reset_mac(temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &temp, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) return -EIO; restore = 1; } @@ -125,43 +119,32 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), - &address, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) return -EIO; command = 0; /* turn off any prior activity */ - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), - &command, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; /* send read command */ netxen_gb_mii_mgmt_set_read_cycle(command); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), - &command, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; status = 0; do { - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_INDICATE(0), - &status, 4)) - return -EIO; + status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); timeout++; } while ((netxen_get_gb_mii_mgmt_busy(status) || netxen_get_gb_mii_mgmt_notvalid(status)) && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); if (timeout < NETXEN_NIU_PHY_WAITMAX) { - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_STATUS(0), - readval, 4)) - return -EIO; + *readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0)); result = 0; } else result = -1; if (restore) - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) return -EIO; phy_unlock(adapter); return result; @@ -197,9 +180,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, * cannot be in reset */ - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) - return -EIO; + mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); if (netxen_gb_get_soft_reset(mac_cfg0)) { __u32 temp; temp = 0; @@ -208,35 +189,27 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, netxen_gb_tx_reset_mac(temp); netxen_gb_rx_reset_mac(temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &temp, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) return -EIO; restore = 1; } command = 0; /* turn off any prior activity */ - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), - &command, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), - &address, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) return -EIO; - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), - &val, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val)) return -EIO; status = 0; do { - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_INDICATE(0), - &status, 4)) - return -EIO; + status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); timeout++; } while ((netxen_get_gb_mii_mgmt_busy(status)) && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); @@ -248,9 +221,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, /* restore the state of port 0 MAC in case we tampered with it */ if (restore) - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) return -EIO; return result; @@ -258,7 +229,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f); + NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x3f); return 0; } @@ -281,7 +252,7 @@ int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter) int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f); + NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x7f); return 0; } @@ -315,36 +286,27 @@ static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter) static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, int port, long enable) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x80000000); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x0000f0025); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), - 0xf1ff); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); - netxen_crb_writelit_adapter(adapter, - (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); + NXWR32(adapter, NETXEN_NIU_MODE, 0x2); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf1ff); + NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); + NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); + NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); + NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); if (enable) { /* * Do NOT enable flow control until a suitable solution for * shutting down pause frames is found. */ - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x5); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); } if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n"); + printk(KERN_ERR "ERROR enabling PHY interrupts\n"); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); } /* @@ -353,36 +315,27 @@ static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port, long enable) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x80000000); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x0000f0025); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), - 0xf2ff); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); - netxen_crb_writelit_adapter(adapter, - (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); + NXWR32(adapter, NETXEN_NIU_MODE, 0x2); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf2ff); + NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); + NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); + NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); + NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); if (enable) { /* * Do NOT enable flow control until a suitable solution for * shutting down pause frames is found. */ - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x5); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); } if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n"); + printk(KERN_ERR "ERROR enabling PHY interrupts\n"); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); } int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) @@ -416,25 +369,20 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) * plugged in. */ - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0 - (port), + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), NETXEN_GB_MAC_SOFT_RESET); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0 - (port), - NETXEN_GB_MAC_RESET_PROT_BLK - | NETXEN_GB_MAC_ENABLE_TX_RX - | - NETXEN_GB_MAC_PAUSED_FRMS); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + NETXEN_GB_MAC_RESET_PROT_BLK | + NETXEN_GB_MAC_ENABLE_TX_RX | + NETXEN_GB_MAC_PAUSED_FRMS); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR PFX + printk(KERN_ERR "ERROR enabling PHY interrupts\n"); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); result = -1; } @@ -447,91 +395,13 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) { if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); } return 0; } -/* - * Return the current station MAC address. - * Note that the passed-in value must already be in network byte order. - */ -static int netxen_niu_macaddr_get(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t * addr) -{ - u32 stationhigh; - u32 stationlow; - int phy = adapter->physical_port; - u8 val[8]; - - if (addr == NULL) - return -EINVAL; - if ((phy < 0) || (phy > 3)) - return -EINVAL; - - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), - &stationhigh, 4)) - return -EIO; - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), - &stationlow, 4)) - return -EIO; - ((__le32 *)val)[1] = cpu_to_le32(stationhigh); - ((__le32 *)val)[0] = cpu_to_le32(stationlow); - - memcpy(addr, val + 2, 6); - - return 0; -} - -/* - * Set the station MAC address. - * Note that the passed-in value must already be in network byte order. - */ -int netxen_niu_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr) -{ - u8 temp[4]; - u32 val; - int phy = adapter->physical_port; - unsigned char mac_addr[6]; - int i; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - for (i = 0; i < 10; i++) { - temp[0] = temp[1] = 0; - memcpy(temp + 2, addr, 2); - val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4)) - return -EIO; - - memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32)); - val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4)) - return -2; - - netxen_niu_macaddr_get(adapter, - (netxen_ethernet_macaddr_t *) mac_addr); - if (memcmp(mac_addr, addr, 6) == 0) - break; - } - - if (i == 10) { - printk(KERN_ERR "%s: cannot set Mac addr for %s\n", - netxen_nic_driver_name, adapter->netdev->name); - printk(KERN_ERR "MAC address set: %pM.\n", addr); - printk(KERN_ERR "MAC address get: %pM.\n", mac_addr); - } - return 0; -} - /* Disable a GbE interface */ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) { @@ -545,8 +415,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) return -EINVAL; mac_cfg0 = 0; netxen_gb_soft_reset(mac_cfg0); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - &mac_cfg0, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0)) return -EIO; return 0; } @@ -564,8 +433,8 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) return -EINVAL; mac_cfg = 0; - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4)) + if (NXWR32(adapter, + NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) return -EIO; return 0; } @@ -581,9 +450,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return -EINVAL; /* save previous contents */ - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, - ®, 4)) - return -EIO; + reg = NXRD32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR); if (mode == NETXEN_NIU_PROMISC_MODE) { switch (port) { case 0: @@ -619,67 +486,11 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return -EIO; } } - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, - ®, 4)) + if (NXWR32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg)) return -EIO; return 0; } -/* - * Set the MAC address for an XG port - * Note that the passed-in value must already be in network byte order. - */ -int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr) -{ - int phy = adapter->physical_port; - u8 temp[4]; - u32 val; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS)) - return -EIO; - - temp[0] = temp[1] = 0; - switch (phy) { - case 0: - memcpy(temp + 2, addr, 2); - val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, - &val, 4)) - return -EIO; - - memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); - val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, - &val, 4)) - return -EIO; - break; - - case 1: - memcpy(temp + 2, addr, 2); - val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1, - &val, 4)) - return -EIO; - - memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); - val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI, - &val, 4)) - return -EIO; - break; - - default: - printk(KERN_ERR "Unknown port %d\n", phy); - break; - } - - return 0; -} - int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, u32 mode) { @@ -689,9 +500,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, if (port > NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), ®, 4)) - return -EIO; + reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); if (mode == NETXEN_NIU_PROMISC_MODE) reg = (reg | 0x2000UL); else @@ -702,8 +511,40 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, else reg = (reg & ~0x1000UL); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); + + return 0; +} + +int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) +{ + u32 mac_hi, mac_lo; + u32 reg_hi, reg_lo; + + u8 phy = adapter->physical_port; + u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ? + NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS; + + if (phy >= phy_count) + return -EINVAL; + + mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24); + mac_hi = addr[2] | ((u32)addr[3] << 8) | + ((u32)addr[4] << 16) | ((u32)addr[5] << 24); + + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { + reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy); + reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy); + } else { + reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy); + reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy); + } + + /* write twice to flush */ + if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) + return -EIO; + if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) + return -EIO; return 0; } diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 50183335e43a..b73a62ca74f8 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -36,23 +36,25 @@ */ #define NIC_CRB_BASE NETXEN_CAM_RAM(0x200) #define NETXEN_NIC_REG(X) (NIC_CRB_BASE+(X)) +#define NIC_CRB_BASE_2 NETXEN_CAM_RAM(0x700) +#define NETXEN_NIC_REG_2(X) (NIC_CRB_BASE_2+(X)) #define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00) #define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) #define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) #define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) -#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) /* C0 EPG BUG */ +#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) #define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14) #define NX_CDRP_CRB_OFFSET NETXEN_NIC_REG(0x18) #define NX_ARG1_CRB_OFFSET NETXEN_NIC_REG(0x1c) #define NX_ARG2_CRB_OFFSET NETXEN_NIC_REG(0x20) #define NX_ARG3_CRB_OFFSET NETXEN_NIC_REG(0x24) #define NX_SIGN_CRB_OFFSET NETXEN_NIC_REG(0x28) -#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) /* 4 regs for perf */ +#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) #define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24) #define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28) #define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x2c) -#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x30) /* phantom init status */ +#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x30) #define CRB_MMAP_ADDR_3 NETXEN_NIC_REG(0x34) #define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x38) #define CRB_HOST_DUMMY_BUF_ADDR_HI NETXEN_NIC_REG(0x3c) @@ -65,7 +67,7 @@ #define CRB_MMAP_SIZE_1 NETXEN_NIC_REG(0x58) #define CRB_MMAP_SIZE_2 NETXEN_NIC_REG(0x5c) #define CRB_MMAP_SIZE_3 NETXEN_NIC_REG(0x60) -#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x64) /* interrupt coalescing */ +#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x64) #define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x68) #define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x6c) #define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x70) @@ -83,13 +85,13 @@ #define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xa0) #define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xa4) #define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xa8) -#define CRB_TX_STATE NETXEN_NIC_REG(0xac) /* Debug -performance */ +#define CRB_TX_STATE NETXEN_NIC_REG(0xac) #define CRB_TX_COUNT NETXEN_NIC_REG(0xb0) #define CRB_RX_STATE NETXEN_NIC_REG(0xb4) #define CRB_RX_PERF_DEBUG_1 NETXEN_NIC_REG(0xb8) -#define CRB_RX_LRO_CONTROL NETXEN_NIC_REG(0xbc) /* LRO On/OFF */ +#define CRB_RX_LRO_CONTROL NETXEN_NIC_REG(0xbc) #define CRB_RX_LRO_START_NUM NETXEN_NIC_REG(0xc0) -#define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) /* Multiport Mode */ +#define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) #define CRB_CMD_RING_SIZE NETXEN_NIC_REG(0xc8) #define CRB_DMA_SHIFT NETXEN_NIC_REG(0xcc) #define CRB_INT_VECTOR NETXEN_NIC_REG(0xd4) @@ -109,8 +111,6 @@ #define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0) #define CRB_CMD_PRODUCER_OFFSET_2 NETXEN_NIC_REG(0x1b8) #define CRB_CMD_CONSUMER_OFFSET_2 NETXEN_NIC_REG(0x1bc) - -// 1c0 to 1cc used for signature reg #define CRB_CMD_PRODUCER_OFFSET_3 NETXEN_NIC_REG(0x1d0) #define CRB_CMD_CONSUMER_OFFSET_3 NETXEN_NIC_REG(0x1d4) #define CRB_TEMP_STATE NETXEN_NIC_REG(0x1b4) @@ -120,13 +120,13 @@ #define CRB_V2P_2 NETXEN_NIC_REG(0x298) #define CRB_V2P_3 NETXEN_NIC_REG(0x29c) #define CRB_V2P(port) (CRB_V2P_0+((port)*4)) -#define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) -/* sw int status/mask registers */ +#define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) #define CRB_SW_INT_MASK_0 NETXEN_NIC_REG(0x1d8) #define CRB_SW_INT_MASK_1 NETXEN_NIC_REG(0x1e0) #define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) #define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) +#define CRB_FW_CAPABILITIES_1 NETXEN_CAM_RAM(0x128) #define CRB_MAC_BLOCK_START NETXEN_CAM_RAM(0x1c0) /* @@ -136,7 +136,7 @@ #define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) -#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) +#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) #define INTR_SCHEME_PERPORT 0x1 #define MSI_MODE_MULTIFUNC 0x1 @@ -162,7 +162,8 @@ struct netxen_recv_crb { u32 crb_rcv_producer[NUM_RCV_DESC_RINGS]; - u32 crb_sts_consumer; + u32 crb_sts_consumer[NUM_STS_DESC_RINGS]; + u32 sw_int_mask[NUM_STS_DESC_RINGS]; }; /* diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index 6474f02bf783..1f10ed603e20 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -1165,7 +1165,7 @@ static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev) if (test_and_set_bit(0, (void*)&p->lock)) { printk(KERN_ERR "%s: Queue was locked.\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } { diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 2b1745328cf7..fa61a12c5e15 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -1317,7 +1318,7 @@ static int bcm8704_reset(struct niu *np) err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR, MII_BMCR); - if (err < 0) + if (err < 0 || err == 0xffff) return err; err |= BMCR_RESET; err = mdio_write(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR, @@ -2042,7 +2043,7 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p) err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, BCM8704_PMD_RCV_SIGDET); - if (err < 0) + if (err < 0 || err == 0xffff) goto out; if (!(err & PMD_RCV_SIGDET_GLOBAL)) { err = 0; @@ -2083,8 +2084,6 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p) out: *link_up_p = link_up; - if (np->flags & NIU_FLAGS_HOTPLUG_PHY) - err = 0; return err; } @@ -2220,10 +2219,17 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p) if (phy_present != phy_present_prev) { /* state change */ if (phy_present) { + /* A NEM was just plugged in */ np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT; if (np->phy_ops->xcvr_init) err = np->phy_ops->xcvr_init(np); if (err) { + err = mdio_read(np, np->phy_addr, + BCM8704_PHYXS_DEV_ADDR, MII_BMCR); + if (err == 0xffff) { + /* No mdio, back-to-back XAUI */ + goto out; + } /* debounce */ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; } @@ -2234,13 +2240,21 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p) np->dev->name); } } - if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) +out: + if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) { err = link_status_10g_bcm8706(np, link_up_p); + if (err == 0xffff) { + /* No mdio, back-to-back XAUI: it is C10NEM */ + *link_up_p = 1; + np->link_config.active_speed = SPEED_10000; + np->link_config.active_duplex = DUPLEX_FULL; + } + } } spin_unlock_irqrestore(&np->lock, flags); - return err; + return 0; } static int niu_link_status(struct niu *np, int *link_up_p) @@ -2312,6 +2326,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = { .link_status = link_status_10g_hotplug, }; +static const struct niu_phy_ops phy_ops_niu_10g_hotplug = { + .serdes_init = serdes_init_niu_10g_fiber, + .xcvr_init = xcvr_init_10g_bcm8706, + .link_status = link_status_10g_hotplug, +}; + static const struct niu_phy_ops phy_ops_10g_copper = { .serdes_init = serdes_init_10g, .link_status = link_status_10g, /* XXX */ @@ -2358,6 +2378,11 @@ static const struct niu_phy_template phy_template_10g_fiber_hotplug = { .phy_addr_base = 8, }; +static const struct niu_phy_template phy_template_niu_10g_hotplug = { + .ops = &phy_ops_niu_10g_hotplug, + .phy_addr_base = 8, +}; + static const struct niu_phy_template phy_template_10g_copper = { .ops = &phy_ops_10g_copper, .phy_addr_base = 10, @@ -2542,8 +2567,16 @@ static int niu_determine_phy_disposition(struct niu *np) case NIU_FLAGS_10G | NIU_FLAGS_FIBER: /* 10G Fiber */ default: - tp = &phy_template_niu_10g_fiber; - phy_addr_off += np->port; + if (np->flags & NIU_FLAGS_HOTPLUG_PHY) { + tp = &phy_template_niu_10g_hotplug; + if (np->port == 0) + phy_addr_off = 8; + if (np->port == 1) + phy_addr_off = 12; + } else { + tp = &phy_template_niu_10g_fiber; + phy_addr_off += np->port; + } break; } } else { @@ -2630,11 +2663,11 @@ static int niu_init_link(struct niu *np) msleep(200); } err = niu_serdes_init(np); - if (err) + if (err && !(np->flags & NIU_FLAGS_HOTPLUG_PHY)) return err; msleep(200); err = niu_xcvr_init(np); - if (!err) + if (!err || (np->flags & NIU_FLAGS_HOTPLUG_PHY)) niu_link_status(np, &ignore); return 0; } @@ -6330,6 +6363,7 @@ static void niu_set_rx_mode(struct net_device *dev) struct niu *np = netdev_priv(dev); int i, alt_cnt, err; struct dev_addr_list *addr; + struct netdev_hw_addr *ha; unsigned long flags; u16 hash[16] = { 0, }; @@ -6351,9 +6385,8 @@ static void niu_set_rx_mode(struct net_device *dev) if (alt_cnt) { int index = 0; - for (addr = dev->uc_list; addr; addr = addr->next) { - err = niu_set_alt_mac(np, index, - addr->da_addr); + list_for_each_entry(ha, &dev->uc_list, list) { + err = niu_set_alt_mac(np, index, ha->addr); if (err) printk(KERN_WARNING PFX "%s: Error %d " "adding alt mac %d\n", @@ -6745,8 +6778,6 @@ static int niu_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_tx_wake_queue(txq); } - dev->trans_start = jiffies; - out: return NETDEV_TX_OK; @@ -9346,6 +9377,11 @@ static int __devinit niu_get_of_props(struct niu *np) if (model) strcpy(np->vpd.model, model); + if (of_find_property(dp, "hot-swappable-phy", &prop_len)) { + np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER | + NIU_FLAGS_HOTPLUG_PHY); + } + return 0; #else return -EINVAL; diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index d531614a90b5..1576ac07216e 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1097,7 +1097,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (unlikely(dev->CFG_cache & CFG_LNKSTS)) { netif_stop_queue(ndev); if (unlikely(dev->CFG_cache & CFG_LNKSTS)) - return 1; + return NETDEV_TX_BUSY; netif_start_queue(ndev); } @@ -1115,7 +1115,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) netif_start_queue(ndev); goto again; } - return 1; + return NETDEV_TX_BUSY; } if (free_idx == dev->tx_intr_idx) { @@ -1204,9 +1204,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (stopped && (dev->tx_done_idx != tx_done_idx) && start_tx_okay(dev)) netif_start_queue(ndev); - /* set the transmit start time to catch transmit timeouts */ - ndev->trans_start = jiffies; - return 0; + return NETDEV_TX_OK; } static void ns83820_update_stats(struct ns83820 *dev) @@ -1626,7 +1624,7 @@ static void ns83820_tx_watch(unsigned long data) ); #endif - if (time_after(jiffies, ndev->trans_start + 1*HZ) && + if (time_after(jiffies, dev_trans_start(ndev) + 1*HZ) && dev->tx_done_idx != dev->tx_free_idx) { printk(KERN_DEBUG "%s: ns83820_tx_watch: %u %u %d\n", ndev->name, diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 5eeb5a87b738..c254a7f5b9f5 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1086,34 +1087,17 @@ static int pasemi_mac_phy_init(struct net_device *dev) struct pasemi_mac *mac = netdev_priv(dev); struct device_node *dn, *phy_dn; struct phy_device *phydev; - unsigned int phy_id; - const phandle *ph; - const unsigned int *prop; - struct resource r; - int ret; dn = pci_device_to_OF_node(mac->pdev); - ph = of_get_property(dn, "phy-handle", NULL); - if (!ph) - return -ENODEV; - phy_dn = of_find_node_by_phandle(*ph); - - prop = of_get_property(phy_dn, "reg", NULL); - ret = of_address_to_resource(phy_dn->parent, 0, &r); - if (ret) - goto err; - - phy_id = *prop; - snprintf(mac->phy_id, sizeof(mac->phy_id), "%x:%02x", - (int)r.start, phy_id); - + phy_dn = of_parse_phandle(dn, "phy-handle", 0); of_node_put(phy_dn); mac->link = 0; mac->speed = 0; mac->duplex = -1; - phydev = phy_connect(dev, mac->phy_id, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII); + phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, + PHY_INTERFACE_MODE_SGMII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); @@ -1123,10 +1107,6 @@ static int pasemi_mac_phy_init(struct net_device *dev) mac->phydev = phydev; return 0; - -err: - of_node_put(phy_dn); - return -ENODEV; } @@ -1735,12 +1715,25 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) return ret; } +static const struct net_device_ops pasemi_netdev_ops = { + .ndo_open = pasemi_mac_open, + .ndo_stop = pasemi_mac_close, + .ndo_start_xmit = pasemi_mac_start_tx, + .ndo_set_multicast_list = pasemi_mac_set_rx_mode, + .ndo_set_mac_address = pasemi_mac_set_mac_addr, + .ndo_change_mtu = pasemi_mac_change_mtu, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = pasemi_mac_netpoll, +#endif +}; + static int __devinit pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct pasemi_mac *mac; - int err; + int err, ret; err = pci_enable_device(pdev); if (err) @@ -1798,12 +1791,13 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr)); - mac->dma_if = mac_to_intf(mac); - if (mac->dma_if < 0) { + ret = mac_to_intf(mac); + if (ret < 0) { dev_err(&mac->pdev->dev, "Can't map DMA interface\n"); err = -ENODEV; goto out; } + mac->dma_if = ret; switch (pdev->device) { case 0xa005: @@ -1817,19 +1811,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out; } - dev->open = pasemi_mac_open; - dev->stop = pasemi_mac_close; - dev->hard_start_xmit = pasemi_mac_start_tx; - dev->set_multicast_list = pasemi_mac_set_rx_mode; - dev->set_mac_address = pasemi_mac_set_mac_addr; + dev->netdev_ops = &pasemi_netdev_ops; dev->mtu = PE_DEF_MTU; /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = pasemi_mac_netpoll; -#endif - dev->change_mtu = pasemi_mac_change_mtu; dev->ethtool_ops = &pasemi_mac_ethtool_ops; if (err) diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h index 1a115ec60b53..e2f4efa8ad46 100644 --- a/drivers/net/pasemi_mac.h +++ b/drivers/net/pasemi_mac.h @@ -100,7 +100,6 @@ struct pasemi_mac { int duplex; unsigned int msg_enable; - char phy_id[BUS_ID_SIZE]; }; /* Software status descriptor (ring_info) */ diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index c95fd72c3bb9..8c1f6988f398 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -728,6 +728,17 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev, return rc; } +static const struct net_device_ops netdrv_netdev_ops = { + .ndo_open = netdrv_open, + .ndo_stop = netdrv_close, + .ndo_start_xmit = netdrv_start_xmit, + .ndo_set_multicast_list = netdrv_set_rx_mode, + .ndo_do_ioctl = netdrv_ioctl, + .ndo_tx_timeout = netdrv_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; static int __devinit netdrv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -769,13 +780,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, ((u16 *) (dev->dev_addr))[i] = le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - /* The Rtl8139-specific entries in the device structure. */ - dev->open = netdrv_open; - dev->hard_start_xmit = netdrv_start_xmit; - dev->stop = netdrv_close; - dev->set_multicast_list = netdrv_set_rx_mode; - dev->do_ioctl = netdrv_ioctl; - dev->tx_timeout = netdrv_tx_timeout; + dev->netdev_ops = &netdrv_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->irq = pdev->irq; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 8f3872b8985d..f35c609ba020 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -1195,7 +1195,7 @@ static int el3_close(struct net_device *dev) static struct pcmcia_device_id tc574_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, tc574_ids); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index cdf661a6092c..ec7cf5ac4f05 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -967,8 +967,8 @@ static struct pcmcia_device_id tc589_ids[] = { PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis"), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, tc589_ids); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 15b8fe61695b..0e38d80fd255 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1130,7 +1130,7 @@ static int axnet_start_xmit(struct sk_buff *skb, struct net_device *dev) outb_p(ENISR_ALL, e8390_base + EN0_IMR); spin_unlock_irqrestore(&ei_local->page_lock, flags); dev->stats.tx_errors++; - return 1; + return NETDEV_TX_BUSY; } /* diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 81e6660a433a..479d5b494371 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -877,7 +877,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev) if (length > ETH_FRAME_LEN) { printk(KERN_NOTICE "%s: Attempting to send a large packet" " (%d bytes).\n", dev->name, length); - return 1; + return NETDEV_TX_BUSY; } DEBUG(4, "%s: Transmitting a packet of length %lu.\n", diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 48dbb35747d8..37e05d3ab893 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1388,7 +1388,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_aborted_errors++; printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } smc->saved_skb = skb; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index a3685c0d22fc..ef37d22c7e1d 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1399,7 +1399,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n", dev->name, freespace, okay ? " (okay)":" (not enough)"); if (!okay) { /* not enough space */ - return 1; /* upper layer may decide to requeue this packet */ + return NETDEV_TX_BUSY; /* upper layer may decide to requeue this packet */ } /* send the packet */ PutWord(XIRCREG_EDP, (u_short)pktlen); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 80124fac65fa..1c35e1d637a0 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1227,7 +1227,6 @@ static void pcnet32_rx_entry(struct net_device *dev, dev->stats.rx_dropped++; return; } - skb->dev = dev; if (!rx_in_place) { skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len); /* Make room */ @@ -1406,7 +1405,7 @@ static int pcnet32_poll(struct napi_struct *napi, int budget) /* Set interrupt enable. */ lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); - mmiowb(); + spin_unlock_irqrestore(&lp->lock, flags); } return work_done; @@ -2598,7 +2597,7 @@ pcnet32_interrupt(int irq, void *dev_id) val = lp->a.read_csr(ioaddr, CSR3); val |= 0x5f00; lp->a.write_csr(ioaddr, CSR3, val); - mmiowb(); + __napi_schedule(&lp->napi); break; } diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 7a3ec9d39a9a..dd6f54d1b495 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -243,6 +243,7 @@ static int m88e1111_config_init(struct phy_device *phydev) temp &= ~(MII_M1111_HWCFG_MODE_MASK); temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; + temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); if (err < 0) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index b754020cbe75..bd4e8d72dc08 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -113,7 +113,6 @@ int mdiobus_register(struct mii_bus *bus) bus->reset(bus); for (i = 0; i < PHY_MAX_ADDR; i++) { - bus->phy_map[i] = NULL; if ((bus->phy_mask & (1 << i)) == 0) { struct phy_device *phydev; @@ -150,6 +149,7 @@ void mdiobus_unregister(struct mii_bus *bus) for (i = 0; i < PHY_MAX_ADDR; i++) { if (bus->phy_map[i]) device_unregister(&bus->phy_map[i]->dev); + bus->phy_map[i] = NULL; } } EXPORT_SYMBOL(mdiobus_unregister); @@ -188,35 +188,12 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) if (IS_ERR(phydev) || phydev == NULL) return phydev; - /* There's a PHY at this address - * We need to set: - * 1) IRQ - * 2) bus_id - * 3) parent - * 4) bus - * 5) mii_bus - * And, we need to register it */ - - phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; - - phydev->dev.parent = bus->parent; - phydev->dev.bus = &mdio_bus_type; - dev_set_name(&phydev->dev, PHY_ID_FMT, bus->id, addr); - - phydev->bus = bus; - - /* Run all of the fixups for this PHY */ - phy_scan_fixups(phydev); - - err = device_register(&phydev->dev); + err = phy_device_register(phydev); if (err) { - printk(KERN_ERR "phy %d failed to register\n", addr); phy_device_free(phydev); - phydev = NULL; + return NULL; } - bus->phy_map[addr] = phydev; - return phydev; } EXPORT_SYMBOL(mdiobus_scan); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0a06e4fd37d9..a2ece89622d6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -39,20 +39,21 @@ MODULE_DESCRIPTION("PHY library"); MODULE_AUTHOR("Andy Fleming"); MODULE_LICENSE("GPL"); -static struct phy_driver genphy_driver; -extern int mdio_bus_init(void); -extern void mdio_bus_exit(void); - void phy_device_free(struct phy_device *phydev) { kfree(phydev); } +EXPORT_SYMBOL(phy_device_free); static void phy_device_release(struct device *dev) { phy_device_free(to_phy_device(dev)); } +static struct phy_driver genphy_driver; +extern int mdio_bus_init(void); +extern void mdio_bus_exit(void); + static LIST_HEAD(phy_fixup_list); static DEFINE_MUTEX(phy_fixup_lock); @@ -166,6 +167,10 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) dev->addr = addr; dev->phy_id = phy_id; dev->bus = bus; + dev->dev.parent = bus->parent; + dev->dev.bus = &mdio_bus_type; + dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; + dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr); dev->state = PHY_DOWN; @@ -235,6 +240,38 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) return dev; } +EXPORT_SYMBOL(get_phy_device); + +/** + * phy_device_register - Register the phy device on the MDIO bus + * @phy_device: phy_device structure to be added to the MDIO bus + */ +int phy_device_register(struct phy_device *phydev) +{ + int err; + + /* Don't register a phy if one is already registered at this + * address */ + if (phydev->bus->phy_map[phydev->addr]) + return -EINVAL; + phydev->bus->phy_map[phydev->addr] = phydev; + + /* Run all of the fixups for this PHY */ + phy_scan_fixups(phydev); + + err = device_register(&phydev->dev); + if (err) { + pr_err("phy %d failed to register\n", phydev->addr); + goto out; + } + + return 0; + + out: + phydev->bus->phy_map[phydev->addr] = NULL; + return err; +} +EXPORT_SYMBOL(phy_device_register); /** * phy_prepare_link - prepares the PHY layer to monitor link status @@ -254,6 +291,33 @@ void phy_prepare_link(struct phy_device *phydev, phydev->adjust_link = handler; } +/** + * phy_connect_direct - connect an ethernet device to a specific phy_device + * @dev: the network device to connect + * @phydev: the pointer to the phy device + * @handler: callback function for state change notifications + * @flags: PHY device's dev_flags + * @interface: PHY device's interface + */ +int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, + void (*handler)(struct net_device *), u32 flags, + phy_interface_t interface) +{ + int rc; + + rc = phy_attach_direct(dev, phydev, flags, interface); + if (rc) + return rc; + + phy_prepare_link(phydev, handler); + phy_start_machine(phydev, NULL); + if (phydev->irq > 0) + phy_start_interrupts(phydev); + + return 0; +} +EXPORT_SYMBOL(phy_connect_direct); + /** * phy_connect - connect an ethernet device to a PHY device * @dev: the network device to connect @@ -275,18 +339,21 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, phy_interface_t interface) { struct phy_device *phydev; + struct device *d; + int rc; - phydev = phy_attach(dev, bus_id, flags, interface); + /* Search the list of PHY devices on the mdio bus for the + * PHY with the requested name */ + d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); + if (!d) { + pr_err("PHY %s not found\n", bus_id); + return ERR_PTR(-ENODEV); + } + phydev = to_phy_device(d); - if (IS_ERR(phydev)) - return phydev; - - phy_prepare_link(phydev, handler); - - phy_start_machine(phydev, NULL); - - if (phydev->irq > 0) - phy_start_interrupts(phydev); + rc = phy_connect_direct(dev, phydev, handler, flags, interface); + if (rc) + return ERR_PTR(rc); return phydev; } @@ -310,9 +377,9 @@ void phy_disconnect(struct phy_device *phydev) EXPORT_SYMBOL(phy_disconnect); /** - * phy_attach - attach a network device to a particular PHY device + * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach - * @bus_id: PHY device to attach + * @phydev: Pointer to phy_device to attach * @flags: PHY device's dev_flags * @interface: PHY device's interface * @@ -323,22 +390,10 @@ EXPORT_SYMBOL(phy_disconnect); * the attaching device, and given a callback for link status * change. The phy_device is returned to the attaching driver. */ -struct phy_device *phy_attach(struct net_device *dev, - const char *bus_id, u32 flags, phy_interface_t interface) +int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface) { - struct bus_type *bus = &mdio_bus_type; - struct phy_device *phydev; - struct device *d; - - /* Search the list of PHY devices on the mdio bus for the - * PHY with the requested name */ - d = bus_find_device_by_name(bus, NULL, bus_id); - if (d) { - phydev = to_phy_device(d); - } else { - printk(KERN_ERR "%s not found\n", bus_id); - return ERR_PTR(-ENODEV); - } + struct device *d = &phydev->dev; /* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver. */ @@ -351,13 +406,12 @@ struct phy_device *phy_attach(struct net_device *dev, err = device_bind_driver(d); if (err) - return ERR_PTR(err); + return err; } if (phydev->attached_dev) { - printk(KERN_ERR "%s: %s already attached\n", - dev->name, bus_id); - return ERR_PTR(-EBUSY); + dev_err(&dev->dev, "PHY already attached\n"); + return -EBUSY; } phydev->attached_dev = dev; @@ -375,14 +429,49 @@ struct phy_device *phy_attach(struct net_device *dev, err = phy_scan_fixups(phydev); if (err < 0) - return ERR_PTR(err); + return err; err = phydev->drv->config_init(phydev); if (err < 0) - return ERR_PTR(err); + return err; } + return 0; +} +EXPORT_SYMBOL(phy_attach_direct); + +/** + * phy_attach - attach a network device to a particular PHY device + * @dev: network device to attach + * @bus_id: Bus ID of PHY device to attach + * @flags: PHY device's dev_flags + * @interface: PHY device's interface + * + * Description: Same as phy_attach_direct() except that a PHY bus_id + * string is passed instead of a pointer to a struct phy_device. + */ +struct phy_device *phy_attach(struct net_device *dev, + const char *bus_id, u32 flags, phy_interface_t interface) +{ + struct bus_type *bus = &mdio_bus_type; + struct phy_device *phydev; + struct device *d; + int rc; + + /* Search the list of PHY devices on the mdio bus for the + * PHY with the requested name */ + d = bus_find_device_by_name(bus, NULL, bus_id); + if (!d) { + pr_err("PHY %s not found\n", bus_id); + return ERR_PTR(-ENODEV); + } + phydev = to_phy_device(d); + + rc = phy_attach_direct(dev, phydev, flags, interface); + if (rc) + return ERR_PTR(rc); + return phydev; } EXPORT_SYMBOL(phy_attach); diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 0be0f0b164f3..7a62f781fef2 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -955,12 +955,12 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev) struct plip_local *snd = &nl->snd_data; if (netif_queue_stopped(dev)) - return 1; + return NETDEV_TX_BUSY; /* We may need to grab the bus */ if (!nl->port_owner) { if (parport_claim(nl->pardev)) - return 1; + return NETDEV_TX_BUSY; nl->port_owner = 1; } @@ -969,7 +969,7 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev) if (skb->len > dev->mtu + dev->hard_header_len) { printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len); netif_start_queue (dev); - return 1; + return NETDEV_TX_BUSY; } if (net_debug > 2) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 8ee91421db12..639d11bc444e 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1054,6 +1054,7 @@ static void ppp_setup(struct net_device *dev) dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } /* diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 5b07dd8e5c04..e7935d09c896 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -433,8 +433,7 @@ static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct s * to the inner packet either */ secpath_reset(skb); - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); nf_reset(skb); po = pppox_sk(session_sock); @@ -976,7 +975,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh /* Calculate UDP checksum if configured to do so */ if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT) skb->ip_summed = CHECKSUM_NONE; - else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) { + else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) { skb->ip_summed = CHECKSUM_COMPLETE; csum = skb_checksum(skb, 0, udp_len, 0); uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr, @@ -1172,14 +1171,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) nf_reset(skb); /* Get routing info from the tunnel socket */ - dst_release(skb->dst); - skb->dst = dst_clone(__sk_dst_get(sk_tun)); + skb_dst_drop(skb); + skb_dst_set(skb, dst_clone(__sk_dst_get(sk_tun))); pppol2tp_skb_set_owner_w(skb, sk_tun); /* Calculate UDP checksum if configured to do so */ if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT) skb->ip_summed = CHECKSUM_NONE; - else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) { + else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) { skb->ip_summed = CHECKSUM_COMPLETE; csum = skb_checksum(skb, 0, udp_len, 0); uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr, @@ -1238,8 +1237,7 @@ static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel) struct pppol2tp_session *session; struct sock *sk; - if (tunnel == NULL) - BUG(); + BUG_ON(tunnel == NULL); PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, "%s: closing all sessions...\n", tunnel->name); diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index cadc32c94c1e..8a823ecc99a9 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2617,7 +2617,6 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) &port_regs->CommonRegs.reqQProducerIndex, qdev->req_producer_index); - ndev->trans_start = jiffies; if (netif_msg_tx_queued(qdev)) printk(KERN_DEBUG PFX "%s: tx queued, slot %d, len %d\n", ndev->name, qdev->req_producer_index, skb->len); diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index fcb159e4df54..156e02e8905d 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -27,6 +27,8 @@ "%s: " fmt, __func__, ##args); \ } while (0) +#define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ + #define QLGE_VENDOR_ID 0x1077 #define QLGE_DEVICE_ID_8012 0x8012 #define QLGE_DEVICE_ID_8000 0x8000 @@ -39,7 +41,18 @@ #define NUM_SMALL_BUFFERS 512 #define NUM_LARGE_BUFFERS 512 +#define DB_PAGE_SIZE 4096 +/* Calculate the number of (4k) pages required to + * contain a buffer queue of the given length. + */ +#define MAX_DB_PAGES_PER_BQ(x) \ + (((x * sizeof(u64)) / DB_PAGE_SIZE) + \ + (((x * sizeof(u64)) % DB_PAGE_SIZE) ? 1 : 0)) + +#define RX_RING_SHADOW_SPACE (sizeof(u64) + \ + MAX_DB_PAGES_PER_BQ(NUM_SMALL_BUFFERS) * sizeof(u64) + \ + MAX_DB_PAGES_PER_BQ(NUM_LARGE_BUFFERS) * sizeof(u64)) #define SMALL_BUFFER_SIZE 256 #define LARGE_BUFFER_SIZE PAGE_SIZE #define MAX_SPLIT_SIZE 1023 @@ -50,7 +63,7 @@ #define MAX_INTER_FRAME_WAIT 10 /* 10 usec max interframe-wait for coalescing */ #define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2) #define UDELAY_COUNT 3 -#define UDELAY_DELAY 10 +#define UDELAY_DELAY 100 #define TX_DESC_PER_IOCB 8 @@ -63,7 +76,16 @@ #define TX_DESC_PER_OAL 0 #endif -#define DB_PAGE_SIZE 4096 +/* MPI test register definitions. This register + * is used for determining alternate NIC function's + * PCI->func number. + */ +enum { + MPI_TEST_FUNC_PORT_CFG = 0x1002, + MPI_TEST_NIC1_FUNC_SHIFT = 1, + MPI_TEST_NIC2_FUNC_SHIFT = 5, + MPI_TEST_NIC_FUNC_MASK = 0x00000007, +}; /* * Processor Address Register (PROC_ADDR) bit definitions. @@ -1430,7 +1452,10 @@ struct ql_adapter { /* Hardware information */ u32 chip_rev_id; + u32 fw_rev_id; u32 func; /* PCI function for this adapter */ + u32 alt_func; /* PCI function for alternate adapter */ + u32 port; /* Port number this adapter */ spinlock_t adapter_lock; spinlock_t hw_lock; @@ -1580,6 +1605,8 @@ void ql_mpi_idc_work(struct work_struct *work); void ql_mpi_port_cfg_work(struct work_struct *work); int ql_mb_get_fw_state(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev); +int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); +int ql_mb_about_fw(struct ql_adapter *qdev); #if 1 #define QL_ALL_DUMP diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 913b2a5fafc9..37c99fe79770 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -293,7 +293,10 @@ static void ql_get_drvinfo(struct net_device *ndev, struct ql_adapter *qdev = netdev_priv(ndev); strncpy(drvinfo->driver, qlge_driver_name, 32); strncpy(drvinfo->version, qlge_driver_version, 32); - strncpy(drvinfo->fw_version, "N/A", 32); + snprintf(drvinfo->fw_version, 32, "v%d.%d.%d", + (qdev->fw_rev_id & 0x00ff0000) >> 16, + (qdev->fw_rev_id & 0x0000ff00) >> 8, + (qdev->fw_rev_id & 0x000000ff)); strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32); drvinfo->n_stats = 0; drvinfo->testinfo_len = 0; @@ -401,6 +404,7 @@ const struct ethtool_ops qlge_ethtool_ops = { .get_rx_csum = ql_get_rx_csum, .set_rx_csum = ql_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 1fd5ecb24425..90d1f76c0e8b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -675,11 +675,12 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) int status; __le32 *p = (__le32 *)&qdev->flash; u32 offset; + u8 mac_addr[6]; /* Get flash offset for function and adjust * for dword access. */ - if (!qdev->func) + if (!qdev->port) offset = FUNC0_FLASH_OFFSET / sizeof(u32); else offset = FUNC1_FLASH_OFFSET / sizeof(u32); @@ -705,14 +706,26 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) goto exit; } - if (!is_valid_ether_addr(qdev->flash.flash_params_8000.mac_addr)) { + /* Extract either manufacturer or BOFM modified + * MAC address. + */ + if (qdev->flash.flash_params_8000.data_type1 == 2) + memcpy(mac_addr, + qdev->flash.flash_params_8000.mac_addr1, + qdev->ndev->addr_len); + else + memcpy(mac_addr, + qdev->flash.flash_params_8000.mac_addr, + qdev->ndev->addr_len); + + if (!is_valid_ether_addr(mac_addr)) { QPRINTK(qdev, IFUP, ERR, "Invalid MAC address.\n"); status = -EINVAL; goto exit; } memcpy(qdev->ndev->dev_addr, - qdev->flash.flash_params_8000.mac_addr, + mac_addr, qdev->ndev->addr_len); exit: @@ -731,7 +744,7 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) /* Second function's parameters follow the first * function's. */ - if (qdev->func) + if (qdev->port) offset = size; if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) @@ -837,6 +850,13 @@ int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data) static int ql_8000_port_initialize(struct ql_adapter *qdev) { int status; + /* + * Get MPI firmware version for driver banner + * and ethool info. + */ + status = ql_mb_about_fw(qdev); + if (status) + goto exit; status = ql_mb_get_fw_state(qdev); if (status) goto exit; @@ -1518,6 +1538,22 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, return; } + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", + ib_mac_rsp->flags2); + dev_kfree_skb_any(skb); + return; + } + + /* The max framesize filter on this chip is set higher than + * MTU since FCoE uses 2k frames. + */ + if (skb->len > ndev->mtu + ETH_HLEN) { + dev_kfree_skb_any(skb); + return; + } + prefetch(skb->data); skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { @@ -1540,7 +1576,6 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, * csum or frame errors. */ if (qdev->rx_csum && - !(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) && !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { @@ -2108,7 +2143,6 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) wmb(); ql_write_db_reg(tx_ring->prod_idx, tx_ring->prod_idx_db_reg); - ndev->trans_start = jiffies; QPRINTK(qdev, TX_QUEUED, DEBUG, "tx queued, slot %d, len %d\n", tx_ring->prod_idx, skb->len); @@ -2203,7 +2237,7 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, &tx_ring->wq_base_dma); if ((tx_ring->wq_base == NULL) - || tx_ring->wq_base_dma & (tx_ring->wq_size - 1)) { + || tx_ring->wq_base_dma & WQ_ADDR_ALIGN) { QPRINTK(qdev, IFUP, ERR, "tx_ring alloc failed.\n"); return -ENOMEM; } @@ -2518,14 +2552,16 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) { struct cqicb *cqicb = &rx_ring->cqicb; void *shadow_reg = qdev->rx_ring_shadow_reg_area + - (rx_ring->cq_id * sizeof(u64) * 4); + (rx_ring->cq_id * RX_RING_SHADOW_SPACE); u64 shadow_reg_dma = qdev->rx_ring_shadow_reg_dma + - (rx_ring->cq_id * sizeof(u64) * 4); + (rx_ring->cq_id * RX_RING_SHADOW_SPACE); void __iomem *doorbell_area = qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id)); int err = 0; u16 bq_len; u64 tmp; + __le64 *base_indirect_ptr; + int page_entries; /* Set up the shadow registers for this ring. */ rx_ring->prod_idx_sh_reg = shadow_reg; @@ -2534,8 +2570,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) shadow_reg_dma += sizeof(u64); rx_ring->lbq_base_indirect = shadow_reg; rx_ring->lbq_base_indirect_dma = shadow_reg_dma; - shadow_reg += sizeof(u64); - shadow_reg_dma += sizeof(u64); + shadow_reg += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len)); + shadow_reg_dma += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len)); rx_ring->sbq_base_indirect = shadow_reg; rx_ring->sbq_base_indirect_dma = shadow_reg_dma; @@ -2572,7 +2608,14 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) if (rx_ring->lbq_len) { cqicb->flags |= FLAGS_LL; /* Load lbq values */ tmp = (u64)rx_ring->lbq_base_dma;; - *((__le64 *) rx_ring->lbq_base_indirect) = cpu_to_le64(tmp); + base_indirect_ptr = (__le64 *) rx_ring->lbq_base_indirect; + page_entries = 0; + do { + *base_indirect_ptr = cpu_to_le64(tmp); + tmp += DB_PAGE_SIZE; + base_indirect_ptr++; + page_entries++; + } while (page_entries < MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len)); cqicb->lbq_addr = cpu_to_le64(rx_ring->lbq_base_indirect_dma); bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 : @@ -2589,7 +2632,14 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) if (rx_ring->sbq_len) { cqicb->flags |= FLAGS_LS; /* Load sbq values */ tmp = (u64)rx_ring->sbq_base_dma;; - *((__le64 *) rx_ring->sbq_base_indirect) = cpu_to_le64(tmp); + base_indirect_ptr = (__le64 *) rx_ring->sbq_base_indirect; + page_entries = 0; + do { + *base_indirect_ptr = cpu_to_le64(tmp); + tmp += DB_PAGE_SIZE; + base_indirect_ptr++; + page_entries++; + } while (page_entries < MAX_DB_PAGES_PER_BQ(rx_ring->sbq_len)); cqicb->sbq_addr = cpu_to_le64(rx_ring->sbq_base_indirect_dma); cqicb->sbq_buf_size = @@ -3186,9 +3236,10 @@ static void ql_display_dev_info(struct net_device *ndev) struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); QPRINTK(qdev, PROBE, INFO, - "Function #%d, NIC Roll %d, NIC Rev = %d, " + "Function #%d, Port %d, NIC Roll %d, NIC Rev = %d, " "XG Roll = %d, XG Rev = %d.\n", qdev->func, + qdev->port, qdev->chip_rev_id & 0x0000000f, qdev->chip_rev_id >> 4 & 0x0000000f, qdev->chip_rev_id >> 8 & 0x0000000f, @@ -3264,7 +3315,6 @@ static int ql_adapter_up(struct ql_adapter *qdev) err = ql_adapter_initialize(qdev); if (err) { QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n"); - spin_unlock(&qdev->hw_lock); goto err_init; } set_bit(QL_ADAPTER_UP, &qdev->flags); @@ -3361,7 +3411,6 @@ static int ql_configure_rings(struct ql_adapter *qdev) * completion handler rx_rings. */ qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1; - netif_set_gso_max_size(qdev->ndev, 65536); for (i = 0; i < qdev->tx_ring_count; i++) { tx_ring = &qdev->tx_ring[i]; @@ -3644,12 +3693,53 @@ static struct nic_operations qla8000_nic_ops = { .port_initialize = ql_8000_port_initialize, }; - -static void ql_get_board_info(struct ql_adapter *qdev) +/* Find the pcie function number for the other NIC + * on this chip. Since both NIC functions share a + * common firmware we have the lowest enabled function + * do any common work. Examples would be resetting + * after a fatal firmware error, or doing a firmware + * coredump. + */ +static int ql_get_alt_pcie_func(struct ql_adapter *qdev) { + int status = 0; + u32 temp; + u32 nic_func1, nic_func2; + + status = ql_read_mpi_reg(qdev, MPI_TEST_FUNC_PORT_CFG, + &temp); + if (status) + return status; + + nic_func1 = ((temp >> MPI_TEST_NIC1_FUNC_SHIFT) & + MPI_TEST_NIC_FUNC_MASK); + nic_func2 = ((temp >> MPI_TEST_NIC2_FUNC_SHIFT) & + MPI_TEST_NIC_FUNC_MASK); + + if (qdev->func == nic_func1) + qdev->alt_func = nic_func2; + else if (qdev->func == nic_func2) + qdev->alt_func = nic_func1; + else + status = -EIO; + + return status; +} + +static int ql_get_board_info(struct ql_adapter *qdev) +{ + int status; qdev->func = (ql_read32(qdev, STS) & STS_FUNC_ID_MASK) >> STS_FUNC_ID_SHIFT; - if (qdev->func) { + if (qdev->func > 3) + return -EIO; + + status = ql_get_alt_pcie_func(qdev); + if (status) + return status; + + qdev->port = (qdev->func < qdev->alt_func) ? 0 : 1; + if (qdev->port) { qdev->xg_sem_mask = SEM_XGMAC1_MASK; qdev->port_link_up = STS_PL1; qdev->port_init = STS_PI1; @@ -3668,6 +3758,7 @@ static void ql_get_board_info(struct ql_adapter *qdev) qdev->nic_ops = &qla8012_nic_ops; else if (qdev->device_id == QLGE_DEVICE_ID_8000) qdev->nic_ops = &qla8000_nic_ops; + return status; } static void ql_release_all(struct pci_dev *pdev) @@ -3762,7 +3853,12 @@ static int __devinit ql_init_device(struct pci_dev *pdev, qdev->ndev = ndev; qdev->pdev = pdev; - ql_get_board_info(qdev); + err = ql_get_board_info(qdev); + if (err) { + dev_err(&pdev->dev, "Register access failed.\n"); + err = -EIO; + goto err_out; + } qdev->msg_enable = netif_msg_init(debug, default_msg); spin_lock_init(&qdev->hw_lock); spin_lock_init(&qdev->stats_lock); diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index ac9493f6c1a1..71afbf8b9c50 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -90,14 +90,14 @@ static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) */ static int ql_wait_mbx_cmd_cmplt(struct ql_adapter *qdev) { - int count = 50; /* TODO: arbitrary for now. */ + int count = 100; u32 value; do { value = ql_read32(qdev, STS); if (value & STS_PI) return 0; - udelay(UDELAY_DELAY); /* 10us */ + mdelay(UDELAY_DELAY); /* 100ms */ } while (--count); return -ETIMEDOUT; } @@ -453,6 +453,13 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) } end: ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); + /* Restore the original mailbox count to + * what the caller asked for. This can get + * changed when a mailbox command is waiting + * for a response and an AEN arrives and + * is handled. + * */ + mbcp->out_count = orig_count; return status; } @@ -540,6 +547,40 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) return status; } + +/* Get MPI firmware version. This will be used for + * driver banner and for ethtool info. + * Returns zero on success. + */ +int ql_mb_about_fw(struct ql_adapter *qdev) +{ + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + int status = 0; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 1; + mbcp->out_count = 3; + + mbcp->mbox_in[0] = MB_CMD_ABOUT_FW; + + status = ql_mailbox_command(qdev, mbcp); + if (status) + return status; + + if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { + QPRINTK(qdev, DRV, ERR, + "Failed about firmware command\n"); + status = -EIO; + } + + /* Store the firmware version */ + qdev->fw_rev_id = mbcp->mbox_out[1]; + + return status; +} + /* Get functional state for MPI firmware. * Returns zero on success. */ @@ -754,7 +795,6 @@ void ql_mpi_port_cfg_work(struct work_struct *work) { struct ql_adapter *qdev = container_of(work, struct ql_adapter, mpi_port_cfg_work.work); - struct net_device *ndev = qdev->ndev; int status; status = ql_mb_get_port_cfg(qdev); @@ -764,9 +804,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work) goto err; } - if (ndev->mtu <= 2500) - goto end; - else if (qdev->link_config & CFG_JUMBO_FRAME_SIZE && + if (qdev->link_config & CFG_JUMBO_FRAME_SIZE && qdev->max_frame_size == CFG_DEFAULT_MAX_FRAME_SIZE) goto end; @@ -831,13 +869,19 @@ void ql_mpi_work(struct work_struct *work) container_of(work, struct ql_adapter, mpi_work.work); struct mbox_params mbc; struct mbox_params *mbcp = &mbc; + int err = 0; mutex_lock(&qdev->mpi_mutex); while (ql_read32(qdev, STS) & STS_PI) { memset(mbcp, 0, sizeof(struct mbox_params)); mbcp->out_count = 1; - ql_mpi_handler(qdev, mbcp); + /* Don't continue if an async event + * did not complete properly. + */ + err = ql_mpi_handler(qdev, mbcp); + if (err) + break; } mutex_unlock(&qdev->mpi_mutex); diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 6f97b47d74a6..ed63d23a6452 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include #define DRV_NAME "r6040" -#define DRV_VERSION "0.22" -#define DRV_RELDATE "25Mar2009" +#define DRV_VERSION "0.23" +#define DRV_RELDATE "05May2009" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ @@ -401,6 +401,9 @@ static void r6040_init_mac_regs(struct net_device *dev) * we may got called by r6040_tx_timeout which has left * some unsent tx buffers */ iowrite16(0x01, ioaddr + MTPR); + + /* Check media */ + mii_check_media(&lp->mii_if, 1, 1); } static void r6040_tx_timeout(struct net_device *dev) @@ -528,6 +531,8 @@ static int r6040_phy_mode_chk(struct net_device *dev) phy_dat = 0x0000; } + mii_check_media(&lp->mii_if, 0, 1); + return phy_dat; }; @@ -742,6 +747,14 @@ static int r6040_up(struct net_device *dev) struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; int ret; + u16 val; + + /* Check presence of a second PHY */ + val = r6040_phy_read(ioaddr, lp->phy_addr, 2); + if (val == 0xFFFF) { + printk(KERN_ERR DRV_NAME " no second PHY attached\n"); + return -EIO; + } /* Initialise and alloc RX/TX buffers */ r6040_init_txbufs(dev); @@ -802,7 +815,6 @@ static void r6040_timer(unsigned long data) lp->phy_mode = phy_mode; lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode; iowrite16(lp->mcr0, ioaddr); - printk(KERN_INFO "Link Change %x \n", ioread16(ioaddr)); } /* Timer active again */ diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 3b19e0ce290f..35196faa084e 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -93,6 +93,7 @@ static const int multicast_filter_limit = 32; #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) enum mac_version { + RTL_GIGA_MAC_NONE = 0x00, RTL_GIGA_MAC_VER_01 = 0x01, // 8169 RTL_GIGA_MAC_VER_02 = 0x02, // 8169S RTL_GIGA_MAC_VER_03 = 0x03, // 8110S @@ -478,7 +479,6 @@ struct rtl8169_private { u16 intr_event; u16 napi_event; u16 intr_mask; - int phy_auto_nego_reg; int phy_1000_ctrl_reg; #ifdef CONFIG_R8169_VLAN struct vlan_group *vlgrp; @@ -843,76 +843,81 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); + int giga_ctrl, bmcr; if (autoneg == AUTONEG_ENABLE) { + int auto_nego; + + auto_nego = mdio_read(ioaddr, MII_ADVERTISE); auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) + auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + + giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); + giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); + + /* The 8100e/8101e/8102e do Fast Ethernet only. */ + if ((tp->mac_version != RTL_GIGA_MAC_VER_07) && + (tp->mac_version != RTL_GIGA_MAC_VER_08) && + (tp->mac_version != RTL_GIGA_MAC_VER_09) && + (tp->mac_version != RTL_GIGA_MAC_VER_10) && + (tp->mac_version != RTL_GIGA_MAC_VER_13) && + (tp->mac_version != RTL_GIGA_MAC_VER_14) && + (tp->mac_version != RTL_GIGA_MAC_VER_15) && + (tp->mac_version != RTL_GIGA_MAC_VER_16)) { giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || - (tp->mac_version == RTL_GIGA_MAC_VER_08) || - (tp->mac_version == RTL_GIGA_MAC_VER_09) || - (tp->mac_version == RTL_GIGA_MAC_VER_10) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) && - netif_msg_link(tp)) { + } else if (netif_msg_link(tp)) { printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", dev->name); } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + bmcr = BMCR_ANENABLE | BMCR_ANRESTART; + + if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || + (tp->mac_version == RTL_GIGA_MAC_VER_12) || + (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { + /* + * Wake up the PHY. + * Vendor specific (0x1f) and reserved (0x0e) MII + * registers. + */ + mdio_write(ioaddr, 0x1f, 0x0000); + mdio_write(ioaddr, 0x0e, 0x0000); + } + + mdio_write(ioaddr, MII_ADVERTISE, auto_nego); + mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); + } else { + giga_ctrl = 0; + + if (speed == SPEED_10) + bmcr = 0; + else if (speed == SPEED_100) + bmcr = BMCR_SPEED100; + else + return -EINVAL; + + if (duplex == DUPLEX_FULL) + bmcr |= BMCR_FULLDPLX; - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII registers. - */ mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); } - tp->phy_auto_nego_reg = auto_nego; tp->phy_1000_ctrl_reg = giga_ctrl; - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); + mdio_write(ioaddr, MII_BMCR, bmcr); + + if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || + (tp->mac_version == RTL_GIGA_MAC_VER_03)) { + if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { + mdio_write(ioaddr, 0x17, 0x2138); + mdio_write(ioaddr, 0x0e, 0x0260); + } else { + mdio_write(ioaddr, 0x17, 0x2108); + mdio_write(ioaddr, 0x0e, 0x0000); + } + } + return 0; } @@ -1295,7 +1300,8 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ + /* Catch-all */ + { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } }, *p = mac_info; u32 reg; @@ -1303,12 +1309,6 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, while ((reg & p->mask) != p->val) p++; tp->mac_version = p->mac_version; - - if (p->mask == 0x00000000) { - struct pci_dev *pdev = tp->pci_dev; - - dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg); - } } static void rtl8169_print_mac_version(struct rtl8169_private *tp) @@ -1884,6 +1884,7 @@ static const struct rtl_cfg_info { u16 intr_event; u16 napi_event; unsigned features; + u8 default_ver; } rtl_cfg_infos [] = { [RTL_CFG_0] = { .hw_start = rtl_hw_start_8169, @@ -1892,7 +1893,8 @@ static const struct rtl_cfg_info { .intr_event = SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII + .features = RTL_FEATURE_GMII, + .default_ver = RTL_GIGA_MAC_VER_01, }, [RTL_CFG_1] = { .hw_start = rtl_hw_start_8168, @@ -1901,7 +1903,8 @@ static const struct rtl_cfg_info { .intr_event = SYSErr | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI + .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, + .default_ver = RTL_GIGA_MAC_VER_11, }, [RTL_CFG_2] = { .hw_start = rtl_hw_start_8101, @@ -1910,7 +1913,8 @@ static const struct rtl_cfg_info { .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_MSI + .features = RTL_FEATURE_MSI, + .default_ver = RTL_GIGA_MAC_VER_13, } }; @@ -2091,6 +2095,15 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Identify chip attached to board */ rtl8169_get_mac_version(tp, ioaddr); + /* Use appropriate default if unknown */ + if (tp->mac_version == RTL_GIGA_MAC_NONE) { + if (netif_msg_probe(tp)) { + dev_notice(&pdev->dev, + "unknown MAC, using family default\n"); + } + tp->mac_version = cfg->default_ver; + } + rtl8169_print_mac_version(tp); for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) { @@ -2098,13 +2111,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) break; } if (i == ARRAY_SIZE(rtl_chip_info)) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - if (netif_msg_probe(tp)) { - dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); - } - i = 0; + dev_err(&pdev->dev, + "driver bug, MAC version not found in rtl_chip_info\n"); + goto err_out_msi_5; } tp->chipset = i; @@ -3269,8 +3278,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); txd->opts1 = cpu_to_le32(status); - dev->trans_start = jiffies; - tp->cur_tx += frags + 1; smp_wmb(); @@ -3371,7 +3378,7 @@ static void rtl8169_tx_interrupt(struct net_device *dev, rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); if (status & LastFrag) { - dev_kfree_skb_irq(tx_skb->skb); + dev_kfree_skb(tx_skb->skb); tx_skb->skb = NULL; } dirty_tx++; @@ -3802,16 +3809,13 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) return &dev->stats; } -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) +static void rtl8169_net_suspend(struct net_device *dev) { - struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; if (!netif_running(dev)) - goto out_pci_suspend; + return; netif_device_detach(dev); netif_stop_queue(dev); @@ -3823,24 +3827,25 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); +} -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); +#ifdef CONFIG_PM + +static int rtl8169_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct net_device *dev = pci_get_drvdata(pdev); + + rtl8169_net_suspend(dev); return 0; } -static int rtl8169_resume(struct pci_dev *pdev) +static int rtl8169_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - if (!netif_running(dev)) goto out; @@ -3851,23 +3856,42 @@ static int rtl8169_resume(struct pci_dev *pdev) return 0; } +static struct dev_pm_ops rtl8169_pm_ops = { + .suspend = rtl8169_suspend, + .resume = rtl8169_resume, + .freeze = rtl8169_suspend, + .thaw = rtl8169_resume, + .poweroff = rtl8169_suspend, + .restore = rtl8169_resume, +}; + +#define RTL8169_PM_OPS (&rtl8169_pm_ops) + +#else /* !CONFIG_PM */ + +#define RTL8169_PM_OPS NULL + +#endif /* !CONFIG_PM */ + static void rtl_shutdown(struct pci_dev *pdev) { - rtl8169_suspend(pdev, PMSG_SUSPEND); -} + struct net_device *dev = pci_get_drvdata(pdev); -#endif /* CONFIG_PM */ + rtl8169_net_suspend(dev); + + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, true); + pci_set_power_state(pdev, PCI_D3hot); + } +} static struct pci_driver rtl8169_pci_driver = { .name = MODULENAME, .id_table = rtl8169_pci_tbl, .probe = rtl8169_init_one, .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, .shutdown = rtl_shutdown, -#endif + .driver.pm = RTL8169_PM_OPS, }; static int __init rtl8169_init_module(void) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index ec59e29807a6..8702e7acdee6 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -428,6 +428,15 @@ static const struct ethtool_ops rionet_ethtool_ops = { .get_link = ethtool_op_get_link, }; +static const struct net_device_ops rionet_netdev_ops = { + .ndo_open = rionet_open, + .ndo_stop = rionet_close, + .ndo_start_xmit = rionet_start_xmit, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int rionet_setup_netdev(struct rio_mport *mport) { int rc = 0; @@ -466,10 +475,7 @@ static int rionet_setup_netdev(struct rio_mport *mport) ndev->dev_addr[4] = device_id >> 8; ndev->dev_addr[5] = device_id & 0xff; - /* Fill in the driver function table */ - ndev->open = &rionet_open; - ndev->hard_start_xmit = &rionet_start_xmit; - ndev->stop = &rionet_close; + ndev->netdev_ops = &rionet_netdev_ops; ndev->mtu = RIO_MAX_MSG_SIZE - 14; ndev->features = NETIF_F_LLTX; SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops); diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index d890829a9acc..81dbcbb910f4 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -1425,7 +1425,7 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!(new_skb = dev_alloc_skb(len + 8))) { dev_kfree_skb(skb); netif_wake_queue(dev); - return -EBUSY; + return NETDEV_TX_OK; } skb_reserve(new_skb, 8); skb_put(new_skb, len); diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index f8274f8941ea..416669fd68c6 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -271,11 +271,6 @@ struct XENA_dev_config { u64 mdio_control; #define MDIO_MMD_INDX_ADDR(val) vBIT(val, 0, 16) #define MDIO_MMD_DEV_ADDR(val) vBIT(val, 19, 5) -#define MDIO_MMD_PMA_DEV_ADDR 0x1 -#define MDIO_MMD_PMD_DEV_ADDR 0x1 -#define MDIO_MMD_WIS_DEV_ADDR 0x2 -#define MDIO_MMD_PCS_DEV_ADDR 0x3 -#define MDIO_MMD_PHYXS_DEV_ADDR 0x4 #define MDIO_MMS_PRT_ADDR(val) vBIT(val, 27, 5) #define MDIO_CTRL_START_TRANS(val) vBIT(val, 56, 4) #define MDIO_OP(val) vBIT(val, 60, 2) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 1a4979f27fb5..458daa06ed41 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -1763,7 +1764,7 @@ static int init_nic(struct s2io_nic *nic) * by then we return error. */ time = 0; - while (TRUE) { + while (true) { val64 = readq(&bar0->rti_command_mem); if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) break; @@ -2136,7 +2137,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) herc = (sp->device_type == XFRAME_II_DEVICE); - if (flag == FALSE) { + if (flag == false) { if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE)) ret = 1; @@ -3328,9 +3329,9 @@ static void s2io_updt_xpak_counter(struct net_device *dev) struct stat_block *stat_info = sp->mac_control.stats_info; /* Check the communication with the MDIO slave */ - addr = 0x0000; + addr = MDIO_CTRL1; val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); if((val64 == 0xFFFF) || (val64 == 0x0000)) { DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - " @@ -3338,24 +3339,24 @@ static void s2io_updt_xpak_counter(struct net_device *dev) return; } - /* Check for the expecte value of 2040 at PMA address 0x0000 */ - if(val64 != 0x2040) + /* Check for the expected value of control reg 1 */ + if(val64 != MDIO_CTRL1_SPEED10G) { DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - "); - DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n", - (unsigned long long)val64); + DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x%x\n", + (unsigned long long)val64, MDIO_CTRL1_SPEED10G); return; } /* Loading the DOM register to MDIO register */ addr = 0xA100; - s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev); - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + s2io_mdio_write(MDIO_MMD_PMAPMD, addr, val16, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); /* Reading the Alarm flags */ addr = 0xA070; val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); flag = CHECKBIT(val64, 0x7); type = 1; @@ -3387,7 +3388,7 @@ static void s2io_updt_xpak_counter(struct net_device *dev) /* Reading the Warning flags */ addr = 0xA074; val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); if(CHECKBIT(val64, 0x7)) stat_info->xpak_stat.warn_transceiver_temp_high++; @@ -3586,7 +3587,7 @@ static void s2io_reset(struct s2io_nic * sp) writeq(val64, &bar0->pcc_err_reg); } - sp->device_enabled_once = FALSE; + sp->device_enabled_once = false; } /** @@ -4298,7 +4299,6 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) s2io_stop_tx_queue(sp, fifo->fifo_no); } mac_control->stats_info->sw_stat.mem_allocated += skb->truesize; - dev->trans_start = jiffies; spin_unlock_irqrestore(&fifo->tx_lock, flags); if (sp->config.intr_type == MSI_X) @@ -5572,10 +5572,10 @@ static void s2io_ethtool_getpause_data(struct net_device *dev, val64 = readq(&bar0->rmac_pause_cfg); if (val64 & RMAC_PAUSE_GEN_ENABLE) - ep->tx_pause = TRUE; + ep->tx_pause = true; if (val64 & RMAC_PAUSE_RX_ENABLE) - ep->rx_pause = TRUE; - ep->autoneg = FALSE; + ep->rx_pause = true; + ep->autoneg = false; } /** @@ -6806,7 +6806,7 @@ static void s2io_set_link(struct work_struct *work) val64 |= ADAPTER_LED_ON; writeq(val64, &bar0->adapter_control); } - nic->device_enabled_once = TRUE; + nic->device_enabled_once = true; } else { DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name); DBG_PRINT(ERR_DBG, "device is not Quiescent\n"); @@ -7754,7 +7754,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) struct s2io_nic *sp; struct net_device *dev; int i, j, ret; - int dma_flag = FALSE; + int dma_flag = false; u32 mac_up, mac_down; u64 val64 = 0, tmp64 = 0; struct XENA_dev_config __iomem *bar0 = NULL; @@ -7777,7 +7777,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n"); - dma_flag = TRUE; + dma_flag = true; if (pci_set_consistent_dma_mask (pdev, DMA_BIT_MASK(64))) { DBG_PRINT(ERR_DBG, @@ -7818,7 +7818,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) sp->dev = dev; sp->pdev = pdev; sp->high_dma_flag = dma_flag; - sp->device_enabled_once = FALSE; + sp->device_enabled_once = false; if (rx_ring_mode == 1) sp->rxd_mode = RXD_MODE_1; if (rx_ring_mode == 2) @@ -7964,7 +7964,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - if (sp->high_dma_flag == TRUE) + if (sp->high_dma_flag == true) dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_TSO; dev->features |= NETIF_F_TSO6; diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 55cb943f23f8..d5c5be6c07b9 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -18,15 +18,6 @@ #define vBIT(val, loc, sz) (((u64)val) << (64-loc-sz)) #define INV(d) ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff) -#ifndef BOOL -#define BOOL int -#endif - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - #undef SUCCESS #define SUCCESS 0 #define FAILURE -1 diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index ce7551e17ba7..d8c9cf1b901d 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2084,7 +2084,7 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); spin_unlock_irqrestore(&sc->sbm_lock, flags); - return 1; + return NETDEV_TX_BUSY; } dev->trans_start = jiffies; @@ -2271,6 +2271,21 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) return 0; } +static const struct net_device_ops sbmac_netdev_ops = { + .ndo_open = sbmac_open, + .ndo_stop = sbmac_close, + .ndo_start_xmit = sbmac_start_tx, + .ndo_set_multicast_list = sbmac_set_rx_mode, + .ndo_tx_timeout = sbmac_tx_timeout, + .ndo_do_ioctl = sbmac_mii_ioctl, + .ndo_change_mtu = sb1250_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = sbmac_netpoll, +#endif +}; + /********************************************************************** * SBMAC_INIT(dev) * @@ -2285,7 +2300,7 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) static int sbmac_init(struct platform_device *pldev, long long base) { - struct net_device *dev = pldev->dev.driver_data; + struct net_device *dev = dev_get_drvdata(&pldev->dev); int idx = pldev->id; struct sbmac_softc *sc = netdev_priv(dev); unsigned char *eaddr; @@ -2327,21 +2342,11 @@ static int sbmac_init(struct platform_device *pldev, long long base) spin_lock_init(&(sc->sbm_lock)); - dev->open = sbmac_open; - dev->hard_start_xmit = sbmac_start_tx; - dev->stop = sbmac_close; - dev->set_multicast_list = sbmac_set_rx_mode; - dev->do_ioctl = sbmac_mii_ioctl; - dev->tx_timeout = sbmac_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; + dev->netdev_ops = &sbmac_netdev_ops; + dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, &sc->napi, sbmac_poll, 16); - dev->change_mtu = sb1250_change_mtu; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = sbmac_netpoll; -#endif - dev->irq = UNIT_INT(idx); /* This is needed for PASS2 for Rx H/W checksum feature */ @@ -2726,7 +2731,7 @@ static int __init sbmac_probe(struct platform_device *pldev) goto out_unmap; } - pldev->dev.driver_data = dev; + dev_set_drvdata(&pldev->dev, dev); SET_NETDEV_DEV(dev, &pldev->dev); sc = netdev_priv(dev); @@ -2751,7 +2756,7 @@ static int __init sbmac_probe(struct platform_device *pldev) static int __exit sbmac_remove(struct platform_device *pldev) { - struct net_device *dev = pldev->dev.driver_data; + struct net_device *dev = dev_get_drvdata(&pldev->dev); struct sbmac_softc *sc = netdev_priv(dev); unregister_netdev(dev); diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index 12a82966b577..260aafaac235 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig @@ -1,7 +1,7 @@ config SFC tristate "Solarflare Solarstorm SFC4000 support" depends on PCI && INET - select MII + select MDIO select CRC32 select I2C select I2C_ALGOBIT diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c index 5182ac5a1034..4a4c74c891b7 100644 --- a/drivers/net/sfc/boards.c +++ b/drivers/net/sfc/boards.c @@ -172,7 +172,6 @@ static const u8 sfe4002_lm87_regs[] = { static struct i2c_board_info sfe4002_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfe4002_lm87_channel, - .irq = -1, }; /****************************************************************************/ @@ -247,7 +246,6 @@ static const u8 sfn4112f_lm87_regs[] = { static struct i2c_board_info sfn4112f_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfn4112f_lm87_channel, - .irq = -1, }; #define SFN4112F_ACT_LED 0 diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 7269a426051c..343e8da1fa30 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -49,16 +49,6 @@ static struct workqueue_struct *reset_workqueue; * *************************************************************************/ -/* - * Enable large receive offload (LRO) aka soft segment reassembly (SSR) - * - * This sets the default for new devices. It can be controlled later - * using ethtool. - */ -static int lro = true; -module_param(lro, int, 0644); -MODULE_PARM_DESC(lro, "Large receive offload acceleration"); - /* * Use separate channels for TX and RX events * @@ -894,9 +884,9 @@ static int efx_wanted_rx_queues(void) int count; int cpu; - if (!alloc_cpumask_var(&core_mask, GFP_KERNEL)) { + if (unlikely(!alloc_cpumask_var(&core_mask, GFP_KERNEL))) { printk(KERN_WARNING - "efx.c: allocation failure, irq balancing hobbled\n"); + "sfc: RSS disabled due to allocation failure\n"); return 1; } @@ -1300,10 +1290,16 @@ static void efx_monitor(struct work_struct *data) static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) { struct efx_nic *efx = netdev_priv(net_dev); + struct mii_ioctl_data *data = if_mii(ifr); EFX_ASSERT_RESET_SERIALISED(efx); - return generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL); + /* Convert phy_id from older PRTAD/DEVAD format */ + if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && + (data->phy_id & 0xfc00) == 0x0400) + data->phy_id ^= MDIO_PHY_ID_C45 | 0x0400; + + return mdio_mii_ioctl(&efx->mdio, data, cmd); } /************************************************************************** @@ -1945,7 +1941,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, mutex_init(&efx->mac_lock); efx->mac_op = &efx_dummy_mac_operations; efx->phy_op = &efx_dummy_phy_operations; - efx->mii.dev = net_dev; + efx->mdio.dev = net_dev; INIT_WORK(&efx->phy_work, efx_phy_work); INIT_WORK(&efx->mac_work, efx_mac_work); atomic_set(&efx->netif_stop_count, 1); @@ -2161,9 +2157,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, if (!net_dev) return -ENOMEM; net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_TSO); - if (lro) - net_dev->features |= NETIF_F_GRO; + NETIF_F_HIGHDMA | NETIF_F_TSO | + NETIF_F_GRO); /* Mask for features that also apply to VLAN devices */ net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_TSO); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 64309f4e8b19..997ea2a3d53f 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "net_driver.h" #include "workarounds.h" @@ -345,8 +346,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, unsigned int n = 0, i; enum efx_loopback_mode mode; - efx_fill_test(n++, strings, data, &tests->mii, - "core", 0, "mii", NULL); + efx_fill_test(n++, strings, data, &tests->mdio, + "core", 0, "mdio", NULL); efx_fill_test(n++, strings, data, &tests->nvram, "core", 0, "nvram", NULL); efx_fill_test(n++, strings, data, &tests->interrupt, @@ -529,14 +530,7 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, - __ffs(BMCR_ANRESTART), true); - return 0; - } - - return -EOPNOTSUPP; + return mdio45_nway_restart(&efx->mdio); } static u32 efx_ethtool_get_link(struct net_device *net_dev) @@ -689,7 +683,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, return -EINVAL; } - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) && + if (!(efx->phy_op->mmds & MDIO_DEVS_AN) && (wanted_fc & EFX_FC_AUTO)) { EFX_LOG(efx, "PHY does not support flow control " "autonegotiation\n"); @@ -717,7 +711,8 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, mutex_lock(&efx->mac_lock); efx->wanted_fc = wanted_fc; - mdio_clause45_set_pause(efx); + if (efx->phy_op->mmds & MDIO_DEVS_AN) + mdio45_ethtool_spauseparam_an(&efx->mdio, pause); __efx_reconfigure_port(efx); mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 466a8abb0053..c049364aec46 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -2063,26 +2063,6 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) ************************************************************************** */ -/* Use the top bit of the MII PHY id to indicate the PHY type - * (1G/10G), with the remaining bits as the actual PHY id. - * - * This allows us to avoid leaking information from the mii_if_info - * structure into other data structures. - */ -#define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR) -#define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1) -#define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1) -#define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1) -#define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1)) - - -/* Packing the clause 45 port and device fields into a single value */ -#define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN) -#define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH -#define MD_DEV_ADR_COMP_LBN 0 -#define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH - - /* Wait for GMII access to complete */ static int falcon_gmii_wait(struct efx_nic *efx) { @@ -2108,49 +2088,29 @@ static int falcon_gmii_wait(struct efx_nic *efx) return -ETIMEDOUT; } -/* Writes a GMII register of a PHY connected to Falcon using MDIO. */ -static void falcon_mdio_write(struct net_device *net_dev, int phy_id, - int addr, int value) +/* Write an MDIO register of a PHY connected to Falcon. */ +static int falcon_mdio_write(struct net_device *net_dev, + int prtad, int devad, u16 addr, u16 value) { struct efx_nic *efx = netdev_priv(net_dev); - unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK; efx_oword_t reg; + int rc; - /* The 'generic' prt/dev packing in mdio_10g.h is conveniently - * chosen so that the only current user, Falcon, can take the - * packed value and use them directly. - * Fail to build if this assumption is broken. - */ - BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G); - BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH); - BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN); - BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN); - - if (phy_id2 == PHY_ADDR_INVALID) - return; - - /* See falcon_mdio_read for an explanation. */ - if (!(phy_id & FALCON_PHY_ID_10G)) { - int mmd = ffs(efx->phy_op->mmds) - 1; - EFX_TRACE(efx, "Fixing erroneous clause22 write\n"); - phy_id2 = mdio_clause45_pack(phy_id2, mmd) - & FALCON_PHY_ID_ID_MASK; - } - - EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id, - addr, value); + EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n", + prtad, devad, addr, value); spin_lock_bh(&efx->phy_lock); - /* Check MII not currently being accessed */ - if (falcon_gmii_wait(efx) != 0) + /* Check MDIO not currently being accessed */ + rc = falcon_gmii_wait(efx); + if (rc) goto out; /* Write the address/ID register */ EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); falcon_write(efx, ®, MD_PHY_ADR_REG_KER); - EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2); + EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad); falcon_write(efx, ®, MD_ID_REG_KER); /* Write data */ @@ -2163,7 +2123,8 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, falcon_write(efx, ®, MD_CS_REG_KER); /* Wait for data to be written */ - if (falcon_gmii_wait(efx) != 0) { + rc = falcon_gmii_wait(efx); + if (rc) { /* Abort the write operation */ EFX_POPULATE_OWORD_2(reg, MD_WRC, 0, @@ -2174,45 +2135,28 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, out: spin_unlock_bh(&efx->phy_lock); + return rc; } -/* Reads a GMII register from a PHY connected to Falcon. If no value - * could be read, -1 will be returned. */ -static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) +/* Read an MDIO register of a PHY connected to Falcon. */ +static int falcon_mdio_read(struct net_device *net_dev, + int prtad, int devad, u16 addr) { struct efx_nic *efx = netdev_priv(net_dev); - unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK; efx_oword_t reg; - int value = -1; - - if (phy_addr == PHY_ADDR_INVALID) - return -1; - - /* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G) - * but the generic Linux code does not make any distinction or have - * any state for this. - * We spot the case where someone tried to talk 22 to a 45 PHY and - * redirect the request to the lowest numbered MMD as a clause45 - * request. This is enough to allow simple queries like id and link - * state to succeed. TODO: We may need to do more in future. - */ - if (!(phy_id & FALCON_PHY_ID_10G)) { - int mmd = ffs(efx->phy_op->mmds) - 1; - EFX_TRACE(efx, "Fixing erroneous clause22 read\n"); - phy_addr = mdio_clause45_pack(phy_addr, mmd) - & FALCON_PHY_ID_ID_MASK; - } + int rc; spin_lock_bh(&efx->phy_lock); - /* Check MII not currently being accessed */ - if (falcon_gmii_wait(efx) != 0) + /* Check MDIO not currently being accessed */ + rc = falcon_gmii_wait(efx); + if (rc) goto out; EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); falcon_write(efx, ®, MD_PHY_ADR_REG_KER); - EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr); + EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad); falcon_write(efx, ®, MD_ID_REG_KER); /* Request data to be read */ @@ -2220,12 +2164,12 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) falcon_write(efx, ®, MD_CS_REG_KER); /* Wait for data to become available */ - value = falcon_gmii_wait(efx); - if (value == 0) { + rc = falcon_gmii_wait(efx); + if (rc == 0) { falcon_read(efx, ®, MD_RXD_REG_KER); - value = EFX_OWORD_FIELD(reg, MD_RXD); - EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n", - phy_id, addr, value); + rc = EFX_OWORD_FIELD(reg, MD_RXD); + EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n", + prtad, devad, addr, rc); } else { /* Abort the read operation */ EFX_POPULATE_OWORD_2(reg, @@ -2233,22 +2177,13 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) MD_GC, 1); falcon_write(efx, ®, MD_CS_REG_KER); - EFX_LOG(efx, "read from GMII 0x%x register %02x, got " - "error %d\n", phy_id, addr, value); + EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n", + prtad, devad, addr, rc); } out: spin_unlock_bh(&efx->phy_lock); - - return value; -} - -static void falcon_init_mdio(struct mii_if_info *gmii) -{ - gmii->mdio_read = falcon_mdio_read; - gmii->mdio_write = falcon_mdio_write; - gmii->phy_id_mask = FALCON_PHY_ID_MASK; - gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1); + return rc; } static int falcon_probe_phy(struct efx_nic *efx) @@ -2342,9 +2277,11 @@ int falcon_probe_port(struct efx_nic *efx) if (rc) return rc; - /* Set up GMII structure for PHY */ - efx->mii.supports_gmii = true; - falcon_init_mdio(&efx->mii); + /* Set up MDIO structure for PHY */ + efx->mdio.mmds = efx->phy_op->mmds; + efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + efx->mdio.mdio_read = falcon_mdio_read; + efx->mdio.mdio_write = falcon_mdio_write; /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ if (falcon_rev(efx) >= FALCON_REV_B0) @@ -2761,7 +2698,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) if (rc == -EINVAL) { EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n"); efx->phy_type = PHY_TYPE_NONE; - efx->mii.phy_id = PHY_ADDR_INVALID; + efx->mdio.prtad = MDIO_PRTAD_NONE; board_rev = 0; rc = 0; } else if (rc) { @@ -2771,7 +2708,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; efx->phy_type = v2->port0_phy_type; - efx->mii.phy_id = v2->port0_phy_addr; + efx->mdio.prtad = v2->port0_phy_addr; board_rev = le16_to_cpu(v2->board_revision); if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { @@ -2793,7 +2730,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) /* Read the MAC addresses */ memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); - EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); + EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad); efx_set_board_info(efx, board_rev); diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index bda8d5bb72e4..375e2a5961ec 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h @@ -456,9 +456,6 @@ #define MD_PRT_ADR_WIDTH 5 #define MD_DEV_ADR_LBN 6 #define MD_DEV_ADR_WIDTH 5 -/* Used for writing both at once */ -#define MD_PRT_DEV_ADR_LBN 6 -#define MD_PRT_DEV_ADR_WIDTH 10 /* PHY management status & mask register (DWORD read only) */ #define MD_STAT_REG_KER 0xc50 diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 5a03713685ac..2b3269c03263 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -133,7 +133,7 @@ bool falcon_xaui_link_ok(struct efx_nic *efx) /* If the link is up, then check the phy side of the xaui link */ if (efx->link_up && link_ok) if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) - link_ok = mdio_clause45_phyxgxs_lane_sync(efx); + link_ok = efx_mdio_phyxgxs_lane_sync(efx); return link_ok; } diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 9f5ec3eb3418..6c33459f9ea9 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -17,7 +17,7 @@ #include "boards.h" #include "workarounds.h" -unsigned mdio_id_oui(u32 id) +unsigned efx_mdio_id_oui(u32 id) { unsigned oui = 0; int i; @@ -32,52 +32,45 @@ unsigned mdio_id_oui(u32 id) return oui; } -int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, +int efx_mdio_reset_mmd(struct efx_nic *port, int mmd, int spins, int spintime) { u32 ctrl; - int phy_id = port->mii.phy_id; /* Catch callers passing values in the wrong units (or just silly) */ EFX_BUG_ON_PARANOID(spins * spintime >= 5000); - mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1, - (1 << MDIO_MMDREG_CTRL1_RESET_LBN)); + efx_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET); /* Wait for the reset bit to clear. */ do { msleep(spintime); - ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1); + ctrl = efx_mdio_read(port, mmd, MDIO_CTRL1); spins--; - } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))); + } while (spins && (ctrl & MDIO_CTRL1_RESET)); return spins ? spins : -ETIMEDOUT; } -static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, - int fault_fatal) +static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal) { int status; - int phy_id = efx->mii.phy_id; if (LOOPBACK_INTERNAL(efx)) return 0; if (mmd != MDIO_MMD_AN) { /* Read MMD STATUS2 to check it is responding. */ - status = mdio_clause45_read(efx, phy_id, mmd, - MDIO_MMDREG_STAT2); - if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & - ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != - MDIO_MMDREG_STAT2_PRESENT_VAL) { + status = efx_mdio_read(efx, mmd, MDIO_STAT2); + if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) { EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); return -EIO; } } /* Read MMD STATUS 1 to check for fault. */ - status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1); - if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) { + status = efx_mdio_read(efx, mmd, MDIO_STAT1); + if (status & MDIO_STAT1_FAULT) { if (fault_fatal) { EFX_ERR(efx, "PHY MMD %d reporting fatal" " fault: status %x\n", mmd, status); @@ -94,8 +87,7 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, #define MDIO45_RESET_TIME 1000 /* ms */ #define MDIO45_RESET_ITERS 100 -int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, - unsigned int mmd_mask) +int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask) { const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; int tries = MDIO45_RESET_ITERS; @@ -109,16 +101,13 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, in_reset = 0; while (mask) { if (mask & 1) { - stat = mdio_clause45_read(efx, - efx->mii.phy_id, - mmd, - MDIO_MMDREG_CTRL1); + stat = efx_mdio_read(efx, mmd, MDIO_CTRL1); if (stat < 0) { EFX_ERR(efx, "failed to read status of" " MMD %d\n", mmd); return -EIO; } - if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)) + if (stat & MDIO_CTRL1_RESET) in_reset |= (1 << mmd); } mask = mask >> 1; @@ -137,28 +126,26 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, return rc; } -int mdio_clause45_check_mmds(struct efx_nic *efx, - unsigned int mmd_mask, unsigned int fatal_mask) +int efx_mdio_check_mmds(struct efx_nic *efx, + unsigned int mmd_mask, unsigned int fatal_mask) { - int mmd = 0, probe_mmd, devs0, devs1; + int mmd = 0, probe_mmd, devs1, devs2; u32 devices; /* Historically we have probed the PHYXS to find out what devices are * present,but that doesn't work so well if the PHYXS isn't expected * to exist, if so just find the first item in the list supplied. */ - probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS : + probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS : __ffs(mmd_mask); /* Check all the expected MMDs are present */ - devs0 = mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS0); - devs1 = mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS1); - if (devs0 < 0 || devs1 < 0) { + devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1); + devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2); + if (devs1 < 0 || devs2 < 0) { EFX_ERR(efx, "failed to read devices present\n"); return -EIO; } - devices = devs0 | (devs1 << 16); + devices = devs1 | (devs2 << 16); if ((devices & mmd_mask) != mmd_mask) { EFX_ERR(efx, "required MMDs not present: got %x, " "wanted %x\n", devices, mmd_mask); @@ -170,7 +157,7 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, while (mmd_mask) { if (mmd_mask & 1) { int fault_fatal = fatal_mask & 1; - if (mdio_clause45_check_mmd(efx, mmd, fault_fatal)) + if (efx_mdio_check_mmd(efx, mmd, fault_fatal)) return -EIO; } mmd_mask = mmd_mask >> 1; @@ -181,13 +168,8 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, return 0; } -bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) +bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask) { - int phy_id = efx->mii.phy_id; - u32 reg; - bool ok = true; - int mmd = 0; - /* If the port is in loopback, then we should only consider a subset * of mmd's */ if (LOOPBACK_INTERNAL(efx)) @@ -197,241 +179,75 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) else if (efx_phy_mode_disabled(efx->phy_mode)) return false; else if (efx->loopback_mode == LOOPBACK_PHYXS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_DEVS_PHYXS | + MDIO_DEVS_PCS | + MDIO_DEVS_PMAPMD | + MDIO_DEVS_AN); else if (efx->loopback_mode == LOOPBACK_PCS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_DEVS_PCS | + MDIO_DEVS_PMAPMD | + MDIO_DEVS_AN); else if (efx->loopback_mode == LOOPBACK_PMAPMD) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_DEVS_PMAPMD | + MDIO_DEVS_AN); - if (!mmd_mask) { - /* Use presence of XGMII faults in leui of link state */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_PHYXS_STATUS2); - return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN)); - } - - while (mmd_mask) { - if (mmd_mask & 1) { - /* Double reads because link state is latched, and a - * read moves the current state into the register */ - reg = mdio_clause45_read(efx, phy_id, - mmd, MDIO_MMDREG_STAT1); - reg = mdio_clause45_read(efx, phy_id, - mmd, MDIO_MMDREG_STAT1); - ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN)); - } - mmd_mask = (mmd_mask >> 1); - mmd++; - } - return ok; + return mdio45_links_ok(&efx->mdio, mmd_mask); } -void mdio_clause45_transmit_disable(struct efx_nic *efx) +void efx_mdio_transmit_disable(struct efx_nic *efx) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN, - efx->phy_mode & PHY_MODE_TX_DISABLED); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, + MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL, + efx->phy_mode & PHY_MODE_TX_DISABLED); } -void mdio_clause45_phy_reconfigure(struct efx_nic *efx) +void efx_mdio_phy_reconfigure(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PMAPMD); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PCS); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_NETWORK); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, + MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK, + efx->loopback_mode == LOOPBACK_PMAPMD); + efx_mdio_set_flag(efx, MDIO_MMD_PCS, + MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK, + efx->loopback_mode == LOOPBACK_PCS); + efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, + MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK, + efx->loopback_mode == LOOPBACK_NETWORK); } -static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx, - int lpower, int mmd) +static void efx_mdio_set_mmd_lpower(struct efx_nic *efx, + int lpower, int mmd) { - int phy = efx->mii.phy_id; - int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1); + int stat = efx_mdio_read(efx, mmd, MDIO_STAT1); EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n", mmd, lpower); - if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) { - mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1, - MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower); + if (stat & MDIO_STAT1_LPOWERABLE) { + efx_mdio_set_flag(efx, mmd, MDIO_CTRL1, + MDIO_CTRL1_LPOWER, lpower); } } -void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, - int low_power, unsigned int mmd_mask) +void efx_mdio_set_mmds_lpower(struct efx_nic *efx, + int low_power, unsigned int mmd_mask) { int mmd = 0; - mmd_mask &= ~MDIO_MMDREG_DEVS_AN; + mmd_mask &= ~MDIO_DEVS_AN; while (mmd_mask) { if (mmd_mask & 1) - mdio_clause45_set_mmd_lpower(efx, low_power, mmd); + efx_mdio_set_mmd_lpower(efx, low_power, mmd); mmd_mask = (mmd_mask >> 1); mmd++; } } -static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) -{ - int phy_id = efx->mii.phy_id; - u32 result = 0; - int reg; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr); - if (reg & ADVERTISE_10HALF) - result |= ADVERTISED_10baseT_Half; - if (reg & ADVERTISE_10FULL) - result |= ADVERTISED_10baseT_Full; - if (reg & ADVERTISE_100HALF) - result |= ADVERTISED_100baseT_Half; - if (reg & ADVERTISE_100FULL) - result |= ADVERTISED_100baseT_Full; - return result; -} - /** - * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd) -{ - mdio_clause45_get_settings_ext(efx, ecmd, 0, 0); -} - -/** - * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * @xnp: Advertised Extended Next Page state - * @xnp_lpa: Link Partner's advertised XNP state - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings_ext(struct efx_nic *efx, - struct ethtool_cmd *ecmd, - u32 npage_adv, u32 npage_lpa) -{ - int phy_id = efx->mii.phy_id; - int reg; - - ecmd->transceiver = XCVR_INTERNAL; - ecmd->phy_address = phy_id; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL2); - switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) { - case MDIO_PMAPMD_CTRL2_10G_BT: - case MDIO_PMAPMD_CTRL2_1G_BT: - case MDIO_PMAPMD_CTRL2_100_BT: - case MDIO_PMAPMD_CTRL2_10_BT: - ecmd->port = PORT_TP; - ecmd->supported = SUPPORTED_TP; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_SPEED); - if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN)) - ecmd->supported |= SUPPORTED_10000baseT_Full; - if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN)) - ecmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_1000baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN)) - ecmd->supported |= (SUPPORTED_100baseT_Full | - SUPPORTED_100baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN)) - ecmd->supported |= (SUPPORTED_10baseT_Full | - SUPPORTED_10baseT_Half); - ecmd->advertising = ADVERTISED_TP; - break; - - /* We represent CX4 as fibre in the absence of anything better */ - case MDIO_PMAPMD_CTRL2_10G_CX4: - /* All the other defined modes are flavours of optical */ - default: - ecmd->port = PORT_FIBRE; - ecmd->supported = SUPPORTED_FIBRE; - ecmd->advertising = ADVERTISED_FIBRE; - break; - } - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - ecmd->supported |= SUPPORTED_Autoneg; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - ecmd->autoneg = AUTONEG_ENABLE; - ecmd->advertising |= - ADVERTISED_Autoneg | - mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) | - npage_adv; - } else - ecmd->autoneg = AUTONEG_DISABLE; - } else - ecmd->autoneg = AUTONEG_DISABLE; - - if (ecmd->autoneg) { - /* If AN is complete, report best common mode, - * otherwise report best advertised mode. */ - u32 modes = 0; - if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_STAT1) & - (1 << MDIO_AN_STATUS_AN_DONE_LBN)) - modes = (ecmd->advertising & - (mdio_clause45_get_an(efx, MDIO_AN_LPA) | - npage_lpa)); - if (modes == 0) - modes = ecmd->advertising; - - if (modes & ADVERTISED_10000baseT_Full) { - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - } else if (modes & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { - ecmd->speed = SPEED_1000; - ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); - } else if (modes & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { - ecmd->speed = SPEED_100; - ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); - } else { - ecmd->speed = SPEED_10; - ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); - } - } else { - /* Report forced settings */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) * - ((reg & BMCR_SPEED100) ? 100 : 10)); - ecmd->duplex = (reg & BMCR_FULLDPLX || - ecmd->speed == SPEED_10000); - } -} - -/** - * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO. + * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO. * @efx: Efx NIC * @ecmd: New settings */ -int mdio_clause45_set_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd) +int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; struct ethtool_cmd prev; u32 required; int reg; @@ -488,95 +304,48 @@ int mdio_clause45_set_settings(struct efx_nic *efx, else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) reg |= ADVERTISE_NPAGE; - reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); + reg |= mii_advertise_flowctrl(efx->wanted_fc); + efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); /* Set up the (extended) next page if necessary */ if (efx->phy_op->set_npage_adv) efx->phy_op->set_npage_adv(efx, ecmd->advertising); /* Enable and restart AN */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - reg |= BMCR_ANENABLE; + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); + reg |= MDIO_AN_CTRL1_ENABLE; if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) - reg |= BMCR_ANRESTART; + reg |= MDIO_AN_CTRL1_RESTART; if (xnp) - reg |= 1 << MDIO_AN_CTRL_XNP_LBN; + reg |= MDIO_AN_CTRL1_XNP; else - reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); + reg &= ~MDIO_AN_CTRL1_XNP; + efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); } else { /* Disable AN */ - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, - __ffs(BMCR_ANENABLE), false); + efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_CTRL1, + MDIO_AN_CTRL1_ENABLE, false); /* Set the basic control bits */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | - 0x003c); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1); + reg &= ~(MDIO_CTRL1_SPEEDSEL | MDIO_CTRL1_FULLDPLX); if (ecmd->speed == SPEED_100) - reg |= BMCR_SPEED100; + reg |= MDIO_PMA_CTRL1_SPEED100; if (ecmd->duplex) - reg |= BMCR_FULLDPLX; - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, reg); + reg |= MDIO_CTRL1_FULLDPLX; + efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, reg); } return 0; } -void mdio_clause45_set_pause(struct efx_nic *efx) +enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - int reg; - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - /* Set pause capability advertising */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE); - reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); - - /* Restart auto-negotiation */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - reg |= BMCR_ANRESTART; - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); - } - } -} - -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; int lpa; - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN))) + if (!(efx->phy_op->mmds & MDIO_DEVS_AN)) return efx->wanted_fc; - lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA); + lpa = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA); return efx_fc_resolve(efx->wanted_fc, lpa); } - -void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense) -{ - int old_val = mdio_clause45_read(efx, prt, dev, addr); - int new_val; - - if (sense) - new_val = old_val | (1 << bit); - else - new_val = old_val & ~(1 << bit); - if (old_val != new_val) - mdio_clause45_write(efx, prt, dev, addr, new_val); -} diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index 7014d2279c20..6b14421a7444 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -10,247 +10,53 @@ #ifndef EFX_MDIO_10G_H #define EFX_MDIO_10G_H +#include + /* - * Definitions needed for doing 10G MDIO as specified in clause 45 - * MDIO, which do not appear in Linux yet. Also some helper functions. + * Helper functions for doing 10G MDIO as specified in IEEE 802.3 clause 45. */ #include "efx.h" #include "boards.h" -/* Numbering of the MDIO Manageable Devices (MMDs) */ -/* Physical Medium Attachment/ Physical Medium Dependent sublayer */ -#define MDIO_MMD_PMAPMD (1) -/* WAN Interface Sublayer */ -#define MDIO_MMD_WIS (2) -/* Physical Coding Sublayer */ -#define MDIO_MMD_PCS (3) -/* PHY Extender Sublayer */ -#define MDIO_MMD_PHYXS (4) -/* Extender Sublayer */ -#define MDIO_MMD_DTEXS (5) -/* Transmission convergence */ -#define MDIO_MMD_TC (6) -/* Auto negotiation */ -#define MDIO_MMD_AN (7) -/* Clause 22 extension */ -#define MDIO_MMD_C22EXT 29 +static inline unsigned efx_mdio_id_rev(u32 id) { return id & 0xf; } +static inline unsigned efx_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; } +extern unsigned efx_mdio_id_oui(u32 id); -/* Generic register locations */ -#define MDIO_MMDREG_CTRL1 (0) -#define MDIO_MMDREG_STAT1 (1) -#define MDIO_MMDREG_IDHI (2) -#define MDIO_MMDREG_IDLOW (3) -#define MDIO_MMDREG_SPEED (4) -#define MDIO_MMDREG_DEVS0 (5) -#define MDIO_MMDREG_DEVS1 (6) -#define MDIO_MMDREG_CTRL2 (7) -#define MDIO_MMDREG_STAT2 (8) -#define MDIO_MMDREG_TXDIS (9) - -/* Bits in MMDREG_CTRL1 */ -/* Reset */ -#define MDIO_MMDREG_CTRL1_RESET_LBN (15) -#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1) -/* Loopback */ -/* Loopback bit for WIS, PCS, PHYSX and DTEXS */ -#define MDIO_MMDREG_CTRL1_LBACK_LBN (14) -#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1) -/* Low power */ -#define MDIO_MMDREG_CTRL1_LPOWER_LBN (11) -#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH (1) - -/* Bits in MMDREG_STAT1 */ -#define MDIO_MMDREG_STAT1_FAULT_LBN (7) -#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1) -/* Link state */ -#define MDIO_MMDREG_STAT1_LINK_LBN (2) -#define MDIO_MMDREG_STAT1_LINK_WIDTH (1) -/* Low power ability */ -#define MDIO_MMDREG_STAT1_LPABLE_LBN (1) -#define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1) - -/* Bits in combined ID regs */ -static inline unsigned mdio_id_rev(u32 id) { return id & 0xf; } -static inline unsigned mdio_id_model(u32 id) { return (id >> 4) & 0x3f; } -extern unsigned mdio_id_oui(u32 id); - -/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out - * so the 'bit present' bit number of an MMD is the number of - * that MMD */ -#define DEV_PRESENT_BIT(_b) (1 << _b) - -#define MDIO_MMDREG_DEVS_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS) -#define MDIO_MMDREG_DEVS_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS) -#define MDIO_MMDREG_DEVS_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD) -#define MDIO_MMDREG_DEVS_AN DEV_PRESENT_BIT(MDIO_MMD_AN) -#define MDIO_MMDREG_DEVS_C22EXT DEV_PRESENT_BIT(MDIO_MMD_C22EXT) - -/* Bits in MMDREG_SPEED */ -#define MDIO_MMDREG_SPEED_10G_LBN 0 -#define MDIO_MMDREG_SPEED_10G_WIDTH 1 -#define MDIO_MMDREG_SPEED_1000M_LBN 4 -#define MDIO_MMDREG_SPEED_1000M_WIDTH 1 -#define MDIO_MMDREG_SPEED_100M_LBN 5 -#define MDIO_MMDREG_SPEED_100M_WIDTH 1 -#define MDIO_MMDREG_SPEED_10M_LBN 6 -#define MDIO_MMDREG_SPEED_10M_WIDTH 1 - -/* Bits in MMDREG_STAT2 */ -#define MDIO_MMDREG_STAT2_PRESENT_VAL (2) -#define MDIO_MMDREG_STAT2_PRESENT_LBN (14) -#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2) - -/* Bits in MMDREG_TXDIS */ -#define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0) -#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1) - -/* MMD-specific bits, ordered by MMD, then register */ -#define MDIO_PMAPMD_CTRL1_LBACK_LBN (0) -#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1) - -/* PMA type (4 bits) */ -#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0) -#define MDIO_PMAPMD_CTRL2_10G_EW (0x1) -#define MDIO_PMAPMD_CTRL2_10G_LW (0x2) -#define MDIO_PMAPMD_CTRL2_10G_SW (0x3) -#define MDIO_PMAPMD_CTRL2_10G_LX4 (0x4) -#define MDIO_PMAPMD_CTRL2_10G_ER (0x5) -#define MDIO_PMAPMD_CTRL2_10G_LR (0x6) -#define MDIO_PMAPMD_CTRL2_10G_SR (0x7) -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_10G_BT (0x9) -/* Reserved */ -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_1G_BT (0xc) -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_100_BT (0xe) -#define MDIO_PMAPMD_CTRL2_10_BT (0xf) -#define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf) - -/* PMA 10GBT registers */ -#define MDIO_PMAPMD_10GBT_TXPWR (131) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1) - -/* PHY XGXS Status 2 */ -#define MDIO_PHYXS_STATUS2 (8) -#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10 - -/* PHY XGXS lane state */ -#define MDIO_PHYXS_LANE_STATE (0x18) -#define MDIO_PHYXS_LANE_ALIGNED_LBN (12) - -/* AN registers */ -#define MDIO_AN_CTRL_XNP_LBN 13 -#define MDIO_AN_STATUS (1) -#define MDIO_AN_STATUS_XNP_LBN (7) -#define MDIO_AN_STATUS_PAGE_LBN (6) -#define MDIO_AN_STATUS_AN_DONE_LBN (5) -#define MDIO_AN_STATUS_LP_AN_CAP_LBN (0) - -#define MDIO_AN_ADVERTISE 16 -#define MDIO_AN_ADVERTISE_XNP_LBN 12 -#define MDIO_AN_LPA 19 -#define MDIO_AN_XNP 22 -#define MDIO_AN_LPA_XNP 25 - -#define MDIO_AN_10GBT_CTRL 32 -#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12 -#define MDIO_AN_10GBT_STATUS (33) -#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ -#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ -#define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */ -#define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */ -#define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */ -#define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */ -#define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9) /* LP Training Reset Request */ - - -/* Packing of the prt and dev arguments of clause 45 style MDIO into a - * single int so they can be passed into the mdio_read/write functions - * that currently exist. Note that as Falcon is the only current user, - * the packed form is chosen to match what Falcon needs to write into - * a register. This is checked at compile-time so do not change it. If - * your target chip needs things layed out differently you will need - * to unpack the arguments in your chip-specific mdio functions. - */ - /* These are defined by the standard. */ -#define MDIO45_PRT_ID_WIDTH (5) -#define MDIO45_DEV_ID_WIDTH (5) - -/* The prt ID is just packed in immediately to the left of the dev ID */ -#define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH) - -#define MDIO45_PRT_ID_MASK ((1 << MDIO45_PRT_DEV_WIDTH) - 1) -/* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */ -#define MDIO45_XPRT_ID_WIDTH (MDIO45_PRT_DEV_WIDTH + 1) -#define MDIO45_XPRT_ID_MASK ((1 << MDIO45_XPRT_ID_WIDTH) - 1) -#define MDIO45_XPRT_ID_IS10G (1 << (MDIO45_XPRT_ID_WIDTH - 1)) - - -#define MDIO45_PRT_ID_COMP_LBN MDIO45_DEV_ID_WIDTH -#define MDIO45_PRT_ID_COMP_WIDTH MDIO45_PRT_ID_WIDTH -#define MDIO45_DEV_ID_COMP_LBN 0 -#define MDIO45_DEV_ID_COMP_WIDTH MDIO45_DEV_ID_WIDTH - -/* Compose port and device into a phy_id */ -static inline int mdio_clause45_pack(u8 prt, u8 dev) +static inline int efx_mdio_read(struct efx_nic *efx, int devad, int addr) { - efx_dword_t phy_id; - EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt, - MDIO45_DEV_ID_COMP, dev); - return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id); + return efx->mdio.mdio_read(efx->net_dev, efx->mdio.prtad, devad, addr); } -static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev) +static inline void +efx_mdio_write(struct efx_nic *efx, int devad, int addr, int value) { - efx_dword_t phy_id; - EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val); - *prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP); - *dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP); + efx->mdio.mdio_write(efx->net_dev, efx->mdio.prtad, devad, addr, value); } -static inline int mdio_clause45_read(struct efx_nic *efx, - u8 prt, u8 dev, u16 addr) +static inline u32 efx_mdio_read_id(struct efx_nic *efx, int mmd) { - return efx->mii.mdio_read(efx->net_dev, - mdio_clause45_pack(prt, dev), addr); -} - -static inline void mdio_clause45_write(struct efx_nic *efx, - u8 prt, u8 dev, u16 addr, int value) -{ - efx->mii.mdio_write(efx->net_dev, - mdio_clause45_pack(prt, dev), addr, value); -} - - -static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd) -{ - int phy_id = efx->mii.phy_id; - u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW); - u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI); + u16 id_low = efx_mdio_read(efx, mmd, MDIO_DEVID2); + u16 id_hi = efx_mdio_read(efx, mmd, MDIO_DEVID1); return (id_hi << 16) | (id_low); } -static inline bool mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx) +static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx) { int i, lane_status; bool sync; for (i = 0; i < 2; ++i) - lane_status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PHYXS, - MDIO_PHYXS_LANE_STATE); + lane_status = efx_mdio_read(efx, MDIO_MMD_PHYXS, + MDIO_PHYXS_LNSTAT); - sync = !!(lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)); + sync = !!(lane_status & MDIO_PHYXS_LNSTAT_ALIGN); if (!sync) EFX_LOG(efx, "XGXS lane status: %x\n", lane_status); return sync; } -extern const char *mdio_clause45_mmd_name(int mmd); +extern const char *efx_mdio_mmd_name(int mmd); /* * Reset a specific MMD and wait for reset to clear. @@ -258,54 +64,44 @@ extern const char *mdio_clause45_mmd_name(int mmd); * * This function will sleep */ -extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd, - int spins, int spintime); +extern int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd, + int spins, int spintime); -/* As mdio_clause45_check_mmd but for multiple MMDs */ -int mdio_clause45_check_mmds(struct efx_nic *efx, - unsigned int mmd_mask, unsigned int fatal_mask); +/* As efx_mdio_check_mmd but for multiple MMDs */ +int efx_mdio_check_mmds(struct efx_nic *efx, + unsigned int mmd_mask, unsigned int fatal_mask); /* Check the link status of specified mmds in bit mask */ -extern bool mdio_clause45_links_ok(struct efx_nic *efx, - unsigned int mmd_mask); +extern bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask); /* Generic transmit disable support though PMAPMD */ -extern void mdio_clause45_transmit_disable(struct efx_nic *efx); +extern void efx_mdio_transmit_disable(struct efx_nic *efx); /* Generic part of reconfigure: set/clear loopback bits */ -extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx); +extern void efx_mdio_phy_reconfigure(struct efx_nic *efx); /* Set the power state of the specified MMDs */ -extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, - int low_power, unsigned int mmd_mask); - -/* Read (some of) the PHY settings over MDIO */ -extern void mdio_clause45_get_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd); - -/* Read (some of) the PHY settings over MDIO */ -extern void -mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd, - u32 xnp, u32 xnp_lpa); +extern void efx_mdio_set_mmds_lpower(struct efx_nic *efx, + int low_power, unsigned int mmd_mask); /* Set (some of) the PHY settings over MDIO */ -extern int mdio_clause45_set_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd); - -/* Set pause parameters to be advertised through AN (if available) */ -extern void mdio_clause45_set_pause(struct efx_nic *efx); +extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); /* Get pause parameters from AN if available (otherwise return * requested pause parameters) */ -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx); +enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx); /* Wait for specified MMDs to exit reset within a timeout */ -extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, - unsigned int mmd_mask); +extern int efx_mdio_wait_reset_mmds(struct efx_nic *efx, + unsigned int mmd_mask); /* Set or clear flag, debouncing */ -extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense); +static inline void +efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr, + int mask, bool state) +{ + mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state); +} #endif /* EFX_MDIO_10G_H */ diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index e169e5dcd1e6..5eabede9ac18 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -458,8 +458,6 @@ enum phy_type { PHY_TYPE_MAX /* Insert any new items before this */ }; -#define PHY_ADDR_INVALID 0xff - #define EFX_IS10G(efx) ((efx)->link_speed == 10000) enum nic_state { @@ -497,8 +495,8 @@ struct efx_nic; /* Pseudo bit-mask flow control field */ enum efx_fc_type { - EFX_FC_RX = 1, - EFX_FC_TX = 2, + EFX_FC_RX = FLOW_CTRL_RX, + EFX_FC_TX = FLOW_CTRL_TX, EFX_FC_AUTO = 4, }; @@ -508,33 +506,15 @@ enum efx_mac_type { EFX_XMAC = 2, }; -static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc) -{ - unsigned int adv = 0; - if (wanted_fc & EFX_FC_RX) - adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - if (wanted_fc & EFX_FC_TX) - adv ^= ADVERTISE_PAUSE_ASYM; - return adv; -} - static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc, unsigned int lpa) { - unsigned int adv = efx_fc_advertise(wanted_fc); + BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX)); if (!(wanted_fc & EFX_FC_AUTO)) return wanted_fc; - if (adv & lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX | EFX_FC_TX; - if (adv & lpa & ADVERTISE_PAUSE_ASYM) { - if (adv & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX; - if (lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_TX; - } - return 0; + return mii_resolve_flowctrl_fdx(mii_advertise_flowctrl(wanted_fc), lpa); } /** @@ -758,7 +738,7 @@ union efx_multicast_hash { * @phy_lock: PHY access lock * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) - * @mii: PHY interface + * @mdio: PHY MDIO interface * @phy_mode: PHY operating mode. Serialised by @mac_lock. * @mac_up: MAC link state * @link_up: Link status @@ -845,7 +825,7 @@ struct efx_nic { struct work_struct phy_work; struct efx_phy_operations *phy_op; void *phy_data; - struct mii_if_info mii; + struct mdio_if_info mdio; enum efx_phy_mode phy_mode; bool mac_up; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 66d7fe3db3e6..01f9432c31ef 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -450,17 +450,27 @@ static void efx_rx_packet_lro(struct efx_channel *channel, /* Pass the skb/page into the LRO engine */ if (rx_buf->page) { - struct napi_gro_fraginfo info; + struct sk_buff *skb = napi_get_frags(napi); - info.frags[0].page = rx_buf->page; - info.frags[0].page_offset = efx_rx_buf_offset(rx_buf); - info.frags[0].size = rx_buf->len; - info.nr_frags = 1; - info.ip_summed = CHECKSUM_UNNECESSARY; - info.len = rx_buf->len; + if (!skb) { + put_page(rx_buf->page); + goto out; + } - napi_gro_frags(napi, &info); + skb_shinfo(skb)->frags[0].page = rx_buf->page; + skb_shinfo(skb)->frags[0].page_offset = + efx_rx_buf_offset(rx_buf); + skb_shinfo(skb)->frags[0].size = rx_buf->len; + skb_shinfo(skb)->nr_frags = 1; + skb->len = rx_buf->len; + skb->data_len = rx_buf->len; + skb->truesize += rx_buf->len; + skb->ip_summed = CHECKSUM_UNNECESSARY; + + napi_gro_frags(napi); + +out: EFX_BUG_ON_PARANOID(rx_buf->skb); rx_buf->page = NULL; } else { diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 0a598084c513..b67ccca3fc1a 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -80,39 +80,38 @@ struct efx_loopback_state { * **************************************************************************/ -static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests) +static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) { int rc = 0; + int devad = __ffs(efx->mdio.mmds); u16 physid1, physid2; - struct mii_if_info *mii = &efx->mii; - struct net_device *net_dev = efx->net_dev; if (efx->phy_type == PHY_TYPE_NONE) return 0; mutex_lock(&efx->mac_lock); - tests->mii = -1; + tests->mdio = -1; - physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1); - physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2); + physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1); + physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2); if ((physid1 == 0x0000) || (physid1 == 0xffff) || (physid2 == 0x0000) || (physid2 == 0xffff)) { - EFX_ERR(efx, "no MII PHY present with ID %d\n", - mii->phy_id); + EFX_ERR(efx, "no MDIO PHY present with ID %d\n", + efx->mdio.prtad); rc = -EINVAL; goto out; } if (EFX_IS10G(efx)) { - rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); + rc = efx_mdio_check_mmds(efx, efx->phy_op->mmds, 0); if (rc) goto out; } out: mutex_unlock(&efx->mac_lock); - tests->mii = rc ? -1 : 1; + tests->mdio = rc ? -1 : 1; return rc; } @@ -439,6 +438,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) kfree_skb(skb); return -EPIPE; } + efx->net_dev->trans_start = jiffies; } return 0; @@ -673,7 +673,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* Online (i.e. non-disruptive) testing * This checks interrupt generation, event delivery and PHY presence. */ - rc = efx_test_mii(efx, tests); + rc = efx_test_mdio(efx, tests); if (rc && !rc_test) rc_test = rc; diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index 39451cf938cf..f6feee04c96b 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h @@ -32,7 +32,7 @@ struct efx_loopback_self_tests { */ struct efx_self_tests { /* online tests */ - int mii; + int mdio; int nvram; int interrupt; int eventq_dma[EFX_MAX_CHANNELS]; diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 4eac5da81e5a..cee00ad49b57 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -296,7 +296,6 @@ static int sfe4001_check_hw(struct efx_nic *efx) static struct i2c_board_info sfe4001_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, }; /* This board uses an I2C expander to provider power to the PHY, which needs to @@ -389,12 +388,10 @@ static void sfn4111t_fini(struct efx_nic *efx) static struct i2c_board_info sfn4111t_a0_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, }; static struct i2c_board_info sfn4111t_r5_hwmon_info = { I2C_BOARD_INFO("max6646", 0x4d), - .irq = -1, }; int sfn4111t_init(struct efx_nic *efx) diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index e61dc4d4741c..f4d509015f75 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -23,10 +23,10 @@ * clause 22 extension MMD, but since it doesn't have all the generic * MMD registers it is pointless to include it here. */ -#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PHYXS | \ - MDIO_MMDREG_DEVS_AN) +#define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \ + MDIO_DEVS_PCS | \ + MDIO_DEVS_PHYXS | \ + MDIO_DEVS_AN) #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ (1 << LOOPBACK_PCS) | \ @@ -44,18 +44,6 @@ */ #define MAX_BAD_LP_TRIES (5) -/* LASI Control */ -#define PMA_PMD_LASI_CTRL 36866 -#define PMA_PMD_LASI_STATUS 36869 -#define PMA_PMD_LS_ALARM_LBN 0 -#define PMA_PMD_LS_ALARM_WIDTH 1 -#define PMA_PMD_TX_ALARM_LBN 1 -#define PMA_PMD_TX_ALARM_WIDTH 1 -#define PMA_PMD_RX_ALARM_LBN 2 -#define PMA_PMD_RX_ALARM_WIDTH 1 -#define PMA_PMD_AN_ALARM_LBN 3 -#define PMA_PMD_AN_ALARM_WIDTH 1 - /* Extended control register */ #define PMA_PMD_XCONTROL_REG 49152 #define PMA_PMD_EXT_GMII_EN_LBN 1 @@ -75,6 +63,7 @@ /* extended status register */ #define PMA_PMD_XSTATUS_REG 49153 +#define PMA_PMD_XSTAT_MDIX_LBN 14 #define PMA_PMD_XSTAT_FLP_LBN (12) /* LED control register */ @@ -153,10 +142,6 @@ #define LOOPBACK_NEAR_LBN (8) #define LOOPBACK_NEAR_WIDTH (1) -#define PCS_10GBASET_STAT1 32 -#define PCS_10GBASET_BLKLK_LBN 0 -#define PCS_10GBASET_BLKLK_WIDTH 1 - /* Boot status register */ #define PCS_BOOT_STATUS_REG 53248 #define PCS_BOOT_FATAL_ERROR_LBN 0 @@ -206,10 +191,8 @@ static ssize_t show_phy_short_reach(struct device *dev, struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); int reg; - reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR); - return sprintf(buf, "%d\n", - !!(reg & (1 << MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN))); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR); + return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT)); } static ssize_t set_phy_short_reach(struct device *dev, @@ -219,10 +202,9 @@ static ssize_t set_phy_short_reach(struct device *dev, struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); rtnl_lock(); - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR, - MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN, - count != 0 && *buf != '0'); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, + MDIO_PMA_10GBT_TXPWR_SHORT, + count != 0 && *buf != '0'); efx_reconfigure_port(efx); rtnl_unlock(); @@ -238,9 +220,8 @@ int sft9001_wait_boot(struct efx_nic *efx) int boot_stat; for (;;) { - boot_stat = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PCS, - PCS_BOOT_STATUS_REG); + boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS, + PCS_BOOT_STATUS_REG); if (boot_stat >= 0) { EFX_LOG(efx, "PHY boot status = %#x\n", boot_stat); switch (boot_stat & @@ -286,38 +267,32 @@ int sft9001_wait_boot(struct efx_nic *efx) static int tenxpress_init(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; int reg; if (efx->phy_type == PHY_TYPE_SFX7101) { /* Enable 312.5 MHz clock */ - mdio_clause45_write(efx, phy_id, - MDIO_MMD_PCS, PCS_TEST_SELECT_REG, - 1 << CLK312_EN_LBN); + efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, + 1 << CLK312_EN_LBN); } else { /* Enable 312.5 MHz clock and GMII */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | (1 << PMA_PMD_EXT_CLK_OUT_LBN) | (1 << PMA_PMD_EXT_CLK312_LBN) | (1 << PMA_PMD_EXT_ROBUST_LBN)); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, GPHY_ISOLATE_LBN, - false); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); + efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, + GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN, + false); } /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ if (efx->phy_type == PHY_TYPE_SFX7101) { - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_CTRL_REG, - PMA_PMA_LED_ACTIVITY_LBN, - true); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, PMA_PMD_LED_DEFAULT); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, + 1 << PMA_PMA_LED_ACTIVITY_LBN, true); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, + PMA_PMD_LED_DEFAULT); } return 0; @@ -337,22 +312,19 @@ static int tenxpress_phy_init(struct efx_nic *efx) if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { if (efx->phy_type == PHY_TYPE_SFT9001A) { int reg; - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_XCONTROL_REG); reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + PMA_PMD_XCONTROL_REG, reg); mdelay(200); } - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); + rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) goto fail; - rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); + rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); if (rc < 0) goto fail; } @@ -360,7 +332,6 @@ static int tenxpress_phy_init(struct efx_nic *efx) rc = tenxpress_init(efx); if (rc < 0) goto fail; - mdio_clause45_set_pause(efx); if (efx->phy_type == PHY_TYPE_SFT9001B) { rc = device_create_file(&efx->pci_dev->dev, @@ -395,17 +366,14 @@ static int tenxpress_special_reset(struct efx_nic *efx) efx_stats_disable(efx); /* Initiate reset */ - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); mdelay(200); /* Wait for the blocks to come out of reset */ - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); + rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) goto out; @@ -424,7 +392,6 @@ static int tenxpress_special_reset(struct efx_nic *efx) static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) { struct tenxpress_phy_data *pd = efx->phy_data; - int phy_id = efx->mii.phy_id; bool bad_lp; int reg; @@ -432,11 +399,10 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) bad_lp = false; } else { /* Check that AN has started but not completed. */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_STATUS); - if (!(reg & (1 << MDIO_AN_STATUS_LP_AN_CAP_LBN))) + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1); + if (!(reg & MDIO_AN_STAT1_LPABLE)) return; /* LP status is unknown */ - bad_lp = !(reg & (1 << MDIO_AN_STATUS_AN_DONE_LBN)); + bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE); if (bad_lp) pd->bad_lp_tries++; } @@ -448,8 +414,8 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) /* Use the RX (red) LED as an error indicator once we've seen AN * failure several times in a row, and also log a message. */ if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_LED_OVERR_REG); reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN); if (!bad_lp) { reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN; @@ -460,23 +426,22 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) " supports 10GBASE-T ONLY, so no link can" " be established\n"); } - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + PMA_PMD_LED_OVERR_REG, reg); pd->bad_lp_tries = bad_lp; } } static bool sfx7101_link_ok(struct efx_nic *efx) { - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PHYXS); + return efx_mdio_links_ok(efx, + MDIO_DEVS_PMAPMD | + MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS); } static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; u32 reg; if (efx_phy_mode_disabled(efx->phy_mode)) @@ -484,50 +449,43 @@ static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) else if (efx->loopback_mode == LOOPBACK_GPHY) return true; else if (efx->loopback_mode) - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PHYXS); + return efx_mdio_links_ok(efx, + MDIO_DEVS_PMAPMD | + MDIO_DEVS_PHYXS); /* We must use the same definition of link state as LASI, * otherwise we can miss a link state transition */ if (ecmd->speed == 10000) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_10GBASET_STAT1); - return reg & (1 << PCS_10GBASET_BLKLK_LBN); + reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1); + return reg & MDIO_PCS_10GBRT_STAT1_BLKLK; } else { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_STATUS_REG); + reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG); return reg & (1 << C22EXT_STATUS_LINK_LBN); } } static void tenxpress_ext_loopback(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - PHYXS_TEST1, LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_PHYXS); + efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1, + 1 << LOOPBACK_NEAR_LBN, + efx->loopback_mode == LOOPBACK_PHYXS); if (efx->phy_type != PHY_TYPE_SFX7101) - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, - GPHY_LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_GPHY); + efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG, + 1 << GPHY_LOOPBACK_NEAR_LBN, + efx->loopback_mode == LOOPBACK_GPHY); } static void tenxpress_low_power(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - if (efx->phy_type == PHY_TYPE_SFX7101) - mdio_clause45_set_mmds_lpower( + efx_mdio_set_mmds_lpower( efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), TENXPRESS_REQUIRED_DEVS); else - mdio_clause45_set_flag( - efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, PMA_PMD_EXT_LPOWER_LBN, + efx_mdio_set_flag( + efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, + 1 << PMA_PMD_EXT_LPOWER_LBN, !!(efx->phy_mode & PHY_MODE_LOW_POWER)); } @@ -568,8 +526,8 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) WARN_ON(rc); } - mdio_clause45_transmit_disable(efx); - mdio_clause45_phy_reconfigure(efx); + efx_mdio_transmit_disable(efx); + efx_mdio_phy_reconfigure(efx); tenxpress_ext_loopback(efx); phy_data->loopback_mode = efx->loopback_mode; @@ -585,7 +543,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) efx->link_fd = ecmd.duplex == DUPLEX_FULL; efx->link_up = sft9001_link_ok(efx, &ecmd); } - efx->link_fc = mdio_clause45_get_pause(efx); + efx->link_fc = efx_mdio_get_pause(efx); } /* Poll PHY for interrupt */ @@ -599,7 +557,7 @@ static void tenxpress_phy_poll(struct efx_nic *efx) if (link_ok != efx->link_up) { change = true; } else { - unsigned int link_fc = mdio_clause45_get_pause(efx); + unsigned int link_fc = efx_mdio_get_pause(efx); if (link_fc != efx->link_fc) change = true; } @@ -609,10 +567,9 @@ static void tenxpress_phy_poll(struct efx_nic *efx) if (link_ok != efx->link_up) change = true; } else { - u32 status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_LASI_STATUS); - if (status & (1 << PMA_PMD_LS_ALARM_LBN)) + int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + MDIO_PMA_LASI_STAT); + if (status & MDIO_PMA_LASI_LSALARM) change = true; } @@ -634,8 +591,7 @@ static void tenxpress_phy_fini(struct efx_nic *efx) if (efx->phy_type == PHY_TYPE_SFX7101) { /* Power down the LNPGA */ reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); /* Waiting here ensures that the board fini, which can turn * off the power to the PHY, won't get run until the LNPGA @@ -661,8 +617,7 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink) else reg = PMA_PMD_LED_DEFAULT; - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg); } static const char *const sfx7101_test_names[] = { @@ -698,7 +653,6 @@ static const char *const sft9001_test_names[] = { static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) { struct ethtool_cmd ecmd; - int phy_id = efx->mii.phy_id; int rc = 0, rc2, i, ctrl_reg, res_reg; if (flags & ETH_TEST_FL_OFFLINE) @@ -717,11 +671,10 @@ static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) * must reset the PHY to resume normal service. */ ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN); } - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_CTRL_REG, ctrl_reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG, + ctrl_reg); i = 0; - while (mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_CTRL_REG) & + while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) & (1 << CDIAG_CTRL_IN_PROG_LBN)) { if (++i == 50) { rc = -ETIMEDOUT; @@ -729,15 +682,13 @@ static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) } msleep(100); } - res_reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_RES_REG); + res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG); for (i = 0; i < 4; i++) { int pair_res = (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH)) & ((1 << CDIAG_RES_WIDTH) - 1); - int len_reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_LEN_REG + i); + int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_CDIAG_LEN_REG + i); if (pair_res == CDIAG_RES_OK) results[1 + i] = 1; else if (pair_res == CDIAG_RES_INVALID) @@ -769,36 +720,39 @@ static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) static void tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; u32 adv = 0, lpa = 0; int reg; if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL); + reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL); if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN)) adv |= ADVERTISED_1000baseT_Full; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_STATUS); + reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS); if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN)) lpa |= ADVERTISED_1000baseT_Half; if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) lpa |= ADVERTISED_1000baseT_Full; } - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL); - if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN)) + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); + if (reg & MDIO_AN_10GBT_CTRL_ADV10G) adv |= ADVERTISED_10000baseT_Full; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_STATUS); - if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); + if (reg & MDIO_AN_10GBT_STAT_LP10G) lpa |= ADVERTISED_10000baseT_Full; - mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa); + mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa); - if (efx->phy_type != PHY_TYPE_SFX7101) + if (efx->phy_type != PHY_TYPE_SFX7101) { ecmd->supported |= (SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full); + if (ecmd->speed != SPEED_10000) { + ecmd->eth_tp_mdix = + (efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_XSTATUS_REG) & + (1 << PMA_PMD_XSTAT_MDIX_LBN)) + ? ETH_TP_MDI_X : ETH_TP_MDI; + } + } /* In loopback, the PHY automatically brings up the correct interface, * but doesn't advertise the correct speed. So override it */ @@ -813,29 +767,24 @@ static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) if (!ecmd->autoneg) return -EINVAL; - return mdio_clause45_set_settings(efx, ecmd); + return efx_mdio_set_settings(efx, ecmd); } static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); + efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G, + advertising & ADVERTISED_10000baseT_Full); } static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) { - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL, - C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, - advertising & ADVERTISED_1000baseT_Full); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); + efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL, + 1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, + advertising & ADVERTISED_1000baseT_Full); + efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G, + advertising & ADVERTISED_10000baseT_Full); } struct efx_phy_operations falcon_sfx7101_phy_ops = { diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index d6681edb7014..14a14788566c 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -360,13 +360,6 @@ inline int efx_xmit(struct efx_nic *efx, /* Map fragments for DMA and add to TX queue */ rc = efx_enqueue_skb(tx_queue, skb); - if (unlikely(rc != NETDEV_TX_OK)) - goto out; - - /* Update last TX timer */ - efx->net_dev->trans_start = jiffies; - - out: return rc; } diff --git a/drivers/net/sfc/xenpack.h b/drivers/net/sfc/xenpack.h deleted file mode 100644 index b0d1f225b70a..000000000000 --- a/drivers/net/sfc/xenpack.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006 Solarflare Communications 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, incorporated herein by reference. - */ - -#ifndef EFX_XENPACK_H -#define EFX_XENPACK_H - -/* Exported functions from Xenpack standard PHY control */ - -#include "mdio_10g.h" - -/****************************************************************************/ -/* XENPACK MDIO register extensions */ -#define MDIO_XP_LASI_RX_CTRL (0x9000) -#define MDIO_XP_LASI_TX_CTRL (0x9001) -#define MDIO_XP_LASI_CTRL (0x9002) -#define MDIO_XP_LASI_RX_STAT (0x9003) -#define MDIO_XP_LASI_TX_STAT (0x9004) -#define MDIO_XP_LASI_STAT (0x9005) - -/* Control/Status bits */ -#define XP_LASI_LS_ALARM (1 << 0) -#define XP_LASI_TX_ALARM (1 << 1) -#define XP_LASI_RX_ALARM (1 << 2) -/* These two are Quake vendor extensions to the standard XENPACK defines */ -#define XP_LASI_LS_INTB (1 << 3) -#define XP_LASI_TEST (1 << 7) - -/* Enable LASI interrupts for PHY */ -static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx) -{ - int reg; - int phy_id = efx->mii.phy_id; - /* Read to clear LASI status register */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_STAT); - - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM); -} - -/* Read the LASI interrupt status to clear the interrupt. */ -static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx) -{ - /* Read to clear link status alarm */ - return mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT); -} - -/* Turn off LASI interrupts */ -static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx) -{ - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_CTRL, 0); -} - -#endif /* EFX_XENPACK_H */ diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index bb1ef77d5f56..bb2e6afd0829 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -15,13 +15,12 @@ #include #include "efx.h" #include "mdio_10g.h" -#include "xenpack.h" #include "phy.h" #include "falcon.h" -#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PHYXS) +#define XFP_REQUIRED_DEVS (MDIO_DEVS_PCS | \ + MDIO_DEVS_PMAPMD | \ + MDIO_DEVS_PHYXS) #define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \ (1 << LOOPBACK_PMAPMD) | \ @@ -49,8 +48,7 @@ void xfp_set_led(struct efx_nic *p, int led, int mode) { int addr = MDIO_QUAKE_LED0_REG + led; - mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr, - mode); + efx_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode); } struct xfp_phy_data { @@ -63,14 +61,12 @@ struct xfp_phy_data { static int qt2025c_wait_reset(struct efx_nic *efx) { unsigned long timeout = jiffies + 10 * HZ; - int phy_id = efx->mii.phy_id; int reg, old_counter = 0; /* Wait for firmware heartbeat to start */ for (;;) { int counter; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_FW_HEARTBEAT_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG); if (reg < 0) return reg; counter = ((reg >> PCS_FW_HEARTB_LBN) & @@ -86,8 +82,7 @@ static int qt2025c_wait_reset(struct efx_nic *efx) /* Wait for firmware status to look good */ for (;;) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_UC8051_STATUS_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG); if (reg < 0) return reg; if ((reg & @@ -109,9 +104,9 @@ static int xfp_reset_phy(struct efx_nic *efx) { int rc; - rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS, - XFP_MAX_RESET_TIME / XFP_RESET_WAIT, - XFP_RESET_WAIT); + rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS, + XFP_MAX_RESET_TIME / XFP_RESET_WAIT, + XFP_RESET_WAIT); if (rc < 0) goto fail; @@ -126,8 +121,7 @@ static int xfp_reset_phy(struct efx_nic *efx) /* Check that all the MMDs we expect are present and responding. We * expect faults on some if the link is down, but not on the PHY XS */ - rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS, - MDIO_MMDREG_DEVS_PHYXS); + rc = efx_mdio_check_mmds(efx, XFP_REQUIRED_DEVS, MDIO_DEVS_PHYXS); if (rc < 0) goto fail; @@ -143,7 +137,7 @@ static int xfp_reset_phy(struct efx_nic *efx) static int xfp_phy_init(struct efx_nic *efx) { struct xfp_phy_data *phy_data; - u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); + u32 devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS); int rc; phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); @@ -152,8 +146,8 @@ static int xfp_phy_init(struct efx_nic *efx) efx->phy_data = phy_data; EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", - devid, mdio_id_oui(devid), mdio_id_model(devid), - mdio_id_rev(devid)); + devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid), + efx_mdio_id_rev(devid)); phy_data->phy_mode = efx->phy_mode; @@ -174,12 +168,13 @@ static int xfp_phy_init(struct efx_nic *efx) static void xfp_phy_clear_interrupt(struct efx_nic *efx) { - xenpack_clear_lasi_irqs(efx); + /* Read to clear link status alarm */ + efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT); } static int xfp_link_ok(struct efx_nic *efx) { - return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS); + return efx_mdio_links_ok(efx, XFP_REQUIRED_DEVS); } static void xfp_phy_poll(struct efx_nic *efx) @@ -200,9 +195,9 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) * or optical transceivers, varying somewhat between * firmware versions. Only 'static mode' appears to * cover everything. */ - mdio_clause45_set_flag( - efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_FTX_CTRL2_REG, PMA_PMD_FTX_STATIC_LBN, + mdio_set_flag( + &efx->mdio, efx->mdio.prtad, MDIO_MMD_PMAPMD, + PMA_PMD_FTX_CTRL2_REG, 1 << PMA_PMD_FTX_STATIC_LBN, efx->phy_mode & PHY_MODE_TX_DISABLED || efx->phy_mode & PHY_MODE_LOW_POWER || efx->loopback_mode == LOOPBACK_PCS || @@ -213,10 +208,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) (phy_data->phy_mode & PHY_MODE_TX_DISABLED)) xfp_reset_phy(efx); - mdio_clause45_transmit_disable(efx); + efx_mdio_transmit_disable(efx); } - mdio_clause45_phy_reconfigure(efx); + efx_mdio_phy_reconfigure(efx); phy_data->phy_mode = efx->phy_mode; efx->link_up = xfp_link_ok(efx); @@ -225,6 +220,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) efx->link_fc = efx->wanted_fc; } +static void xfp_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +{ + mdio45_ethtool_gset(&efx->mdio, ecmd); +} static void xfp_phy_fini(struct efx_nic *efx) { @@ -243,8 +242,8 @@ struct efx_phy_operations falcon_xfp_phy_ops = { .poll = xfp_phy_poll, .fini = xfp_phy_fini, .clear_interrupt = xfp_phy_clear_interrupt, - .get_settings = mdio_clause45_get_settings, - .set_settings = mdio_clause45_set_settings, + .get_settings = xfp_phy_get_settings, + .set_settings = efx_mdio_set_settings, .mmds = XFP_REQUIRED_DEVS, .loopbacks = XFP_LOOPBACKS, }; diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 97d68560067d..5fb88ca6dd7f 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -709,6 +709,17 @@ static inline void setup_rx_ring(struct net_device *dev, dma_sync_desc_dev(dev, &buf[i]); } +static const struct net_device_ops sgiseeq_netdev_ops = { + .ndo_open = sgiseeq_open, + .ndo_stop = sgiseeq_close, + .ndo_start_xmit = sgiseeq_start_xmit, + .ndo_tx_timeout = timeout, + .ndo_set_multicast_list = sgiseeq_set_multicast, + .ndo_set_mac_address = sgiseeq_set_mac_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init sgiseeq_probe(struct platform_device *pdev) { struct sgiseeq_platform_data *pd = pdev->dev.platform_data; @@ -775,13 +786,8 @@ static int __init sgiseeq_probe(struct platform_device *pdev) SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT | SEEQ_CTRL_ENCARR; - dev->open = sgiseeq_open; - dev->stop = sgiseeq_close; - dev->hard_start_xmit = sgiseeq_start_xmit; - dev->tx_timeout = timeout; + dev->netdev_ops = &sgiseeq_netdev_ops; dev->watchdog_timeo = (200 * HZ) / 1000; - dev->set_multicast_list = sgiseeq_set_multicast; - dev->set_mac_address = sgiseeq_set_mac_address; dev->irq = irq; if (register_netdev(dev)) { diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 3ab28bb00c12..341882f959f3 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -2,7 +2,7 @@ * SuperH Ethernet device driver * * Copyright (C) 2006-2008 Nobuhiro Iwamatsu - * Copyright (C) 2008 Renesas Solutions Corp. + * Copyright (C) 2008-2009 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -33,6 +33,226 @@ #include "sh_eth.h" +/* There is CPU dependent code */ +#if defined(CONFIG_CPU_SUBTYPE_SH7724) +#define SH_ETH_RESET_DEFAULT 1 +static void sh_eth_set_duplex(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + + if (mdp->duplex) /* Full */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); + else /* Half */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); +} + +static void sh_eth_set_rate(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + + switch (mdp->speed) { + case 10: /* 10BASE */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR); + break; + case 100:/* 100BASE */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR); + break; + default: + break; + } +} + +/* SH7724 */ +static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + .set_duplex = sh_eth_set_duplex, + .set_rate = sh_eth_set_rate, + + .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD, + .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP, + .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f, + + .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, + .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE | + EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI, + .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE, + + .apr = 1, + .mpr = 1, + .tpauser = 1, + .hw_swap = 1, +}; + +#elif defined(CONFIG_CPU_SUBTYPE_SH7763) +#define SH_ETH_HAS_TSU 1 +static void sh_eth_chip_reset(struct net_device *ndev) +{ + /* reset device */ + ctrl_outl(ARSTR_ARSTR, ARSTR); + mdelay(1); +} + +static void sh_eth_reset(struct net_device *ndev) +{ + u32 ioaddr = ndev->base_addr; + int cnt = 100; + + ctrl_outl(EDSR_ENALL, ioaddr + EDSR); + ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); + while (cnt > 0) { + if (!(ctrl_inl(ioaddr + EDMR) & 0x3)) + break; + mdelay(1); + cnt--; + } + if (cnt < 0) + printk(KERN_ERR "Device reset fail\n"); + + /* Table Init */ + ctrl_outl(0x0, ioaddr + TDLAR); + ctrl_outl(0x0, ioaddr + TDFAR); + ctrl_outl(0x0, ioaddr + TDFXR); + ctrl_outl(0x0, ioaddr + TDFFR); + ctrl_outl(0x0, ioaddr + RDLAR); + ctrl_outl(0x0, ioaddr + RDFAR); + ctrl_outl(0x0, ioaddr + RDFXR); + ctrl_outl(0x0, ioaddr + RDFFR); +} + +static void sh_eth_set_duplex(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + + if (mdp->duplex) /* Full */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR); + else /* Half */ + ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR); +} + +static void sh_eth_set_rate(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 ioaddr = ndev->base_addr; + + switch (mdp->speed) { + case 10: /* 10BASE */ + ctrl_outl(GECMR_10, ioaddr + GECMR); + break; + case 100:/* 100BASE */ + ctrl_outl(GECMR_100, ioaddr + GECMR); + break; + case 1000: /* 1000BASE */ + ctrl_outl(GECMR_1000, ioaddr + GECMR); + break; + default: + break; + } +} + +/* sh7763 */ +static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + .chip_reset = sh_eth_chip_reset, + .set_duplex = sh_eth_set_duplex, + .set_rate = sh_eth_set_rate, + + .ecsr_value = ECSR_ICD | ECSR_MPD, + .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP, + .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, + + .tx_check = EESR_TC1 | EESR_FTC, + .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ + EESR_ECI, + .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ + EESR_TFE, + + .apr = 1, + .mpr = 1, + .tpauser = 1, + .bculr = 1, + .hw_swap = 1, + .rpadir = 1, + .no_trimd = 1, + .no_ade = 1, +}; + +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +#define SH_ETH_RESET_DEFAULT 1 +static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, + + .apr = 1, + .mpr = 1, + .tpauser = 1, + .hw_swap = 1, +}; +#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) +#define SH_ETH_RESET_DEFAULT 1 +#define SH_ETH_HAS_TSU 1 +static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, +}; +#endif + +static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd) +{ + if (!cd->ecsr_value) + cd->ecsr_value = DEFAULT_ECSR_INIT; + + if (!cd->ecsipr_value) + cd->ecsipr_value = DEFAULT_ECSIPR_INIT; + + if (!cd->fcftr_value) + cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \ + DEFAULT_FIFO_F_D_RFD; + + if (!cd->fdr_value) + cd->fdr_value = DEFAULT_FDR_INIT; + + if (!cd->rmcr_value) + cd->rmcr_value = DEFAULT_RMCR_VALUE; + + if (!cd->tx_check) + cd->tx_check = DEFAULT_TX_CHECK; + + if (!cd->eesr_err_check) + cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK; + + if (!cd->tx_error_check) + cd->tx_error_check = DEFAULT_TX_ERROR_CHECK; +} + +#if defined(SH_ETH_RESET_DEFAULT) +/* Chip Reset */ +static void sh_eth_reset(struct net_device *ndev) +{ + u32 ioaddr = ndev->base_addr; + + ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); + mdelay(3); + ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR); +} +#endif + +#if defined(CONFIG_CPU_SH4) +static void sh_eth_set_receive_align(struct sk_buff *skb) +{ + int reserve; + + reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1)); + if (reserve) + skb_reserve(skb, reserve); +} +#else +static void sh_eth_set_receive_align(struct sk_buff *skb) +{ + skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN); +} +#endif + + /* CPU <-> EDMAC endian convert */ static inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x) { @@ -165,41 +385,6 @@ static struct mdiobb_ops bb_ops = { .get_mdio_data = sh_get_mdio, }; -/* Chip Reset */ -static void sh_eth_reset(struct net_device *ndev) -{ - u32 ioaddr = ndev->base_addr; - -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - int cnt = 100; - - ctrl_outl(EDSR_ENALL, ioaddr + EDSR); - ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); - while (cnt > 0) { - if (!(ctrl_inl(ioaddr + EDMR) & 0x3)) - break; - mdelay(1); - cnt--; - } - if (cnt < 0) - printk(KERN_ERR "Device reset fail\n"); - - /* Table Init */ - ctrl_outl(0x0, ioaddr + TDLAR); - ctrl_outl(0x0, ioaddr + TDFAR); - ctrl_outl(0x0, ioaddr + TDFXR); - ctrl_outl(0x0, ioaddr + TDFFR); - ctrl_outl(0x0, ioaddr + RDLAR); - ctrl_outl(0x0, ioaddr + RDFAR); - ctrl_outl(0x0, ioaddr + RDFXR); - ctrl_outl(0x0, ioaddr + RDFFR); -#else - ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR); - mdelay(3); - ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR); -#endif -} - /* free skb and descriptor buffer */ static void sh_eth_ring_free(struct net_device *ndev) { @@ -228,7 +413,7 @@ static void sh_eth_ring_free(struct net_device *ndev) /* format skb and descriptor buffer */ static void sh_eth_ring_format(struct net_device *ndev) { - u32 ioaddr = ndev->base_addr, reserve = 0; + u32 ioaddr = ndev->base_addr; struct sh_eth_private *mdp = netdev_priv(ndev); int i; struct sk_buff *skb; @@ -250,37 +435,27 @@ static void sh_eth_ring_format(struct net_device *ndev) mdp->rx_skbuff[i] = skb; if (skb == NULL) break; + dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz, + DMA_FROM_DEVICE); skb->dev = ndev; /* Mark as being used by this device. */ -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - reserve = SH7763_SKB_ALIGN - - ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1)); - if (reserve) - skb_reserve(skb, reserve); -#else - skb_reserve(skb, RX_OFFSET); -#endif + sh_eth_set_receive_align(skb); + /* RX descriptor */ rxdesc = &mdp->rx_ring[i]; - rxdesc->addr = (u32)skb->data & ~0x3UL; + rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4)); rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP); /* The size of the buffer is 16 byte boundary. */ - rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F; + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); /* Rx descriptor address set */ if (i == 0) { - ctrl_outl((u32)rxdesc, ioaddr + RDLAR); + ctrl_outl(mdp->rx_desc_dma, ioaddr + RDLAR); #if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl((u32)rxdesc, ioaddr + RDFAR); + ctrl_outl(mdp->rx_desc_dma, ioaddr + RDFAR); #endif } } - /* Rx descriptor address set */ -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl((u32)rxdesc, ioaddr + RDFXR); - ctrl_outl(0x1, ioaddr + RDFFR); -#endif - mdp->dirty_rx = (u32) (i - RX_RING_SIZE); /* Mark the last entry as wrapping the ring. */ @@ -296,19 +471,13 @@ static void sh_eth_ring_format(struct net_device *ndev) txdesc->buffer_length = 0; if (i == 0) { /* Tx descriptor address set */ - ctrl_outl((u32)txdesc, ioaddr + TDLAR); + ctrl_outl(mdp->tx_desc_dma, ioaddr + TDLAR); #if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl((u32)txdesc, ioaddr + TDFAR); + ctrl_outl(mdp->tx_desc_dma, ioaddr + TDFAR); #endif } } - /* Tx descriptor address set */ -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl((u32)txdesc, ioaddr + TDFXR); - ctrl_outl(0x1, ioaddr + TDFFR); -#endif - txdesc->status |= cpu_to_edmac(mdp, TD_TDLE); } @@ -331,7 +500,7 @@ static int sh_eth_ring_init(struct net_device *ndev) mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE, GFP_KERNEL); if (!mdp->rx_skbuff) { - printk(KERN_ERR "%s: Cannot allocate Rx skb\n", ndev->name); + dev_err(&ndev->dev, "Cannot allocate Rx skb\n"); ret = -ENOMEM; return ret; } @@ -339,7 +508,7 @@ static int sh_eth_ring_init(struct net_device *ndev) mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE, GFP_KERNEL); if (!mdp->tx_skbuff) { - printk(KERN_ERR "%s: Cannot allocate Tx skb\n", ndev->name); + dev_err(&ndev->dev, "Cannot allocate Tx skb\n"); ret = -ENOMEM; goto skb_ring_free; } @@ -350,8 +519,8 @@ static int sh_eth_ring_init(struct net_device *ndev) GFP_KERNEL); if (!mdp->rx_ring) { - printk(KERN_ERR "%s: Cannot allocate Rx Ring (size %d bytes)\n", - ndev->name, rx_ringsize); + dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n", + rx_ringsize); ret = -ENOMEM; goto desc_ring_free; } @@ -363,8 +532,8 @@ static int sh_eth_ring_init(struct net_device *ndev) mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, GFP_KERNEL); if (!mdp->tx_ring) { - printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n", - ndev->name, tx_ringsize); + dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n", + tx_ringsize); ret = -ENOMEM; goto desc_ring_free; } @@ -394,44 +563,43 @@ static int sh_eth_dev_init(struct net_device *ndev) /* Descriptor format */ sh_eth_ring_format(ndev); - ctrl_outl(RPADIR_INIT, ioaddr + RPADIR); + if (mdp->cd->rpadir) + ctrl_outl(mdp->cd->rpadir_value, ioaddr + RPADIR); /* all sh_eth int mask */ ctrl_outl(0, ioaddr + EESIPR); -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl(EDMR_EL, ioaddr + EDMR); -#else - ctrl_outl(0, ioaddr + EDMR); /* Endian change */ +#if defined(__LITTLE_ENDIAN__) + if (mdp->cd->hw_swap) + ctrl_outl(EDMR_EL, ioaddr + EDMR); + else #endif + ctrl_outl(0, ioaddr + EDMR); /* FIFO size set */ - ctrl_outl((FIFO_SIZE_T | FIFO_SIZE_R), ioaddr + FDR); + ctrl_outl(mdp->cd->fdr_value, ioaddr + FDR); ctrl_outl(0, ioaddr + TFTR); /* Frame recv control */ - ctrl_outl(0, ioaddr + RMCR); + ctrl_outl(mdp->cd->rmcr_value, ioaddr + RMCR); rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5; tx_int_var = mdp->tx_int_var = DESC_I_TINT2; ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER); -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - /* Burst sycle set */ - ctrl_outl(0x800, ioaddr + BCULR); -#endif + if (mdp->cd->bculr) + ctrl_outl(0x800, ioaddr + BCULR); /* Burst sycle set */ - ctrl_outl((FIFO_F_D_RFF | FIFO_F_D_RFD), ioaddr + FCFTR); + ctrl_outl(mdp->cd->fcftr_value, ioaddr + FCFTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl(0, ioaddr + TRIMD); -#endif + if (!mdp->cd->no_trimd) + ctrl_outl(0, ioaddr + TRIMD); /* Recv frame limit set register */ ctrl_outl(RFLR_VALUE, ioaddr + RFLR); ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR); - ctrl_outl((DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff), ioaddr + EESIPR); + ctrl_outl(mdp->cd->eesipr_value, ioaddr + EESIPR); /* PAUSE Prohibition */ val = (ctrl_inl(ioaddr + ECMR) & ECMR_DM) | @@ -439,24 +607,25 @@ static int sh_eth_dev_init(struct net_device *ndev) ctrl_outl(val, ioaddr + ECMR); + if (mdp->cd->set_rate) + mdp->cd->set_rate(ndev); + /* E-MAC Status Register clear */ - ctrl_outl(ECSR_INIT, ioaddr + ECSR); + ctrl_outl(mdp->cd->ecsr_value, ioaddr + ECSR); /* E-MAC Interrupt Enable register */ - ctrl_outl(ECSIPR_INIT, ioaddr + ECSIPR); + ctrl_outl(mdp->cd->ecsipr_value, ioaddr + ECSIPR); /* Set MAC address */ update_mac_address(ndev); /* mask reset */ -#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7763) - ctrl_outl(APR_AP, ioaddr + APR); - ctrl_outl(MPR_MP, ioaddr + MPR); - ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER); -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7710) - ctrl_outl(BCFR_UNLIMITED, ioaddr + BCFR); -#endif + if (mdp->cd->apr) + ctrl_outl(APR_AP, ioaddr + APR); + if (mdp->cd->mpr) + ctrl_outl(MPR_MP, ioaddr + MPR); + if (mdp->cd->tpauser) + ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER); /* Setting the Rx mode will start the Rx process. */ ctrl_outl(EDRRR_R, ioaddr + EDRRR); @@ -505,7 +674,7 @@ static int sh_eth_rx(struct net_device *ndev) int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx; struct sk_buff *skb; u16 pkt_len = 0; - u32 desc_status, reserve = 0; + u32 desc_status; rxdesc = &mdp->rx_ring[entry]; while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) { @@ -534,7 +703,10 @@ static int sh_eth_rx(struct net_device *ndev) if (desc_status & RD_RFS10) mdp->stats.rx_over_errors++; } else { - swaps((char *)(rxdesc->addr & ~0x3), pkt_len + 2); + if (!mdp->cd->hw_swap) + sh_eth_soft_swap( + phys_to_virt(ALIGN(rxdesc->addr, 4)), + pkt_len + 2); skb = mdp->rx_skbuff[entry]; mdp->rx_skbuff[entry] = NULL; skb_put(skb, pkt_len); @@ -545,6 +717,7 @@ static int sh_eth_rx(struct net_device *ndev) } rxdesc->status |= cpu_to_edmac(mdp, RD_RACT); entry = (++mdp->cur_rx) % RX_RING_SIZE; + rxdesc = &mdp->rx_ring[entry]; } /* Refill the Rx ring buffers. */ @@ -552,24 +725,20 @@ static int sh_eth_rx(struct net_device *ndev) entry = mdp->dirty_rx % RX_RING_SIZE; rxdesc = &mdp->rx_ring[entry]; /* The size of the buffer is 16 byte boundary. */ - rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F; + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); if (mdp->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb(mdp->rx_buf_sz); mdp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ + dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz, + DMA_FROM_DEVICE); skb->dev = ndev; -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - reserve = SH7763_SKB_ALIGN - - ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1)); - if (reserve) - skb_reserve(skb, reserve); -#else - skb_reserve(skb, RX_OFFSET); -#endif + sh_eth_set_receive_align(skb); + skb->ip_summed = CHECKSUM_NONE; - rxdesc->addr = (u32)skb->data & ~0x3UL; + rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4)); } if (entry >= RX_RING_SIZE - 1) rxdesc->status |= @@ -593,6 +762,8 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) struct sh_eth_private *mdp = netdev_priv(ndev); u32 ioaddr = ndev->base_addr; u32 felic_stat; + u32 link_stat; + u32 mask; if (intr_status & EESR_ECI) { felic_stat = ctrl_inl(ioaddr + ECSR); @@ -601,7 +772,14 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) mdp->stats.tx_carrier_errors++; if (felic_stat & ECSR_LCHNG) { /* Link Changed */ - u32 link_stat = (ctrl_inl(ioaddr + PSR)); + if (mdp->cd->no_psr) { + if (mdp->link == PHY_DOWN) + link_stat = 0; + else + link_stat = PHY_ST_LINK; + } else { + link_stat = (ctrl_inl(ioaddr + PSR)); + } if (!(link_stat & PHY_ST_LINK)) { /* Link Down : disable tx and rx */ ctrl_outl(ctrl_inl(ioaddr + ECMR) & @@ -633,17 +811,15 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) if (intr_status & EESR_RFRMER) { /* Receive Frame Overflow int */ mdp->stats.rx_frame_errors++; - printk(KERN_ERR "Receive Frame Overflow\n"); + dev_err(&ndev->dev, "Receive Frame Overflow\n"); } } -#if !defined(CONFIG_CPU_SUBTYPE_SH7763) - if (intr_status & EESR_ADE) { - if (intr_status & EESR_TDE) { - if (intr_status & EESR_TFE) - mdp->stats.tx_fifo_errors++; - } + + if (!mdp->cd->no_ade) { + if (intr_status & EESR_ADE && intr_status & EESR_TDE && + intr_status & EESR_TFE) + mdp->stats.tx_fifo_errors++; } -#endif if (intr_status & EESR_RDE) { /* Receive Descriptor Empty int */ @@ -651,24 +827,24 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) if (ctrl_inl(ioaddr + EDRRR) ^ EDRRR_R) ctrl_outl(EDRRR_R, ioaddr + EDRRR); - printk(KERN_ERR "Receive Descriptor Empty\n"); + dev_err(&ndev->dev, "Receive Descriptor Empty\n"); } if (intr_status & EESR_RFE) { /* Receive FIFO Overflow int */ mdp->stats.rx_fifo_errors++; - printk(KERN_ERR "Receive FIFO Overflow\n"); + dev_err(&ndev->dev, "Receive FIFO Overflow\n"); } - if (intr_status & (EESR_TWB | EESR_TABT | -#if !defined(CONFIG_CPU_SUBTYPE_SH7763) - EESR_ADE | -#endif - EESR_TDE | EESR_TFE)) { + + mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE; + if (mdp->cd->no_ade) + mask &= ~EESR_ADE; + if (intr_status & mask) { /* Tx error */ u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR); /* dmesg */ - printk(KERN_ERR "%s:TX error. status=%8.8x cur_tx=%8.8x ", - ndev->name, intr_status, mdp->cur_tx); - printk(KERN_ERR "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n", + dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ", + intr_status, mdp->cur_tx); + dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n", mdp->dirty_tx, (u32) ndev->state, edtrr); /* dirty buffer free */ sh_eth_txfree(ndev); @@ -687,6 +863,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) { struct net_device *ndev = netdev; struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_cpu_data *cd = mdp->cd; irqreturn_t ret = IRQ_NONE; u32 ioaddr, boguscnt = RX_RING_SIZE; u32 intr_status = 0; @@ -699,7 +876,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) /* Clear interrupt */ if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | - TX_CHECK | EESR_ERR_CHECK)) { + cd->tx_check | cd->eesr_err_check)) { ctrl_outl(intr_status, ioaddr + EESR); ret = IRQ_HANDLED; } else @@ -716,12 +893,12 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) } /* Tx Check */ - if (intr_status & TX_CHECK) { + if (intr_status & cd->tx_check) { sh_eth_txfree(ndev); netif_wake_queue(ndev); } - if (intr_status & EESR_ERR_CHECK) + if (intr_status & cd->eesr_err_check) sh_eth_error(ndev, intr_status); if (--boguscnt < 0) { @@ -756,32 +933,15 @@ static void sh_eth_adjust_link(struct net_device *ndev) if (phydev->duplex != mdp->duplex) { new_state = 1; mdp->duplex = phydev->duplex; -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - if (mdp->duplex) { /* FULL */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, - ioaddr + ECMR); - } else { /* Half */ - ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, - ioaddr + ECMR); - } -#endif + if (mdp->cd->set_duplex) + mdp->cd->set_duplex(ndev); } if (phydev->speed != mdp->speed) { new_state = 1; mdp->speed = phydev->speed; -#if defined(CONFIG_CPU_SUBTYPE_SH7763) - switch (mdp->speed) { - case 10: /* 10BASE */ - ctrl_outl(GECMR_10, ioaddr + GECMR); break; - case 100:/* 100BASE */ - ctrl_outl(GECMR_100, ioaddr + GECMR); break; - case 1000: /* 1000BASE */ - ctrl_outl(GECMR_1000, ioaddr + GECMR); break; - default: - break; - } -#endif + if (mdp->cd->set_rate) + mdp->cd->set_rate(ndev); } if (mdp->link == PHY_DOWN) { ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF) @@ -804,7 +964,7 @@ static void sh_eth_adjust_link(struct net_device *ndev) static int sh_eth_phy_init(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); - char phy_id[BUS_ID_SIZE]; + char phy_id[MII_BUS_ID_SIZE + 3]; struct phy_device *phydev = NULL; snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, @@ -821,8 +981,9 @@ static int sh_eth_phy_init(struct net_device *ndev) dev_err(&ndev->dev, "phy_connect failed\n"); return PTR_ERR(phydev); } + dev_info(&ndev->dev, "attached phy %i to driver %s\n", - phydev->addr, phydev->drv->name); + phydev->addr, phydev->drv->name); mdp->phydev = phydev; @@ -860,7 +1021,7 @@ static int sh_eth_open(struct net_device *ndev) #endif ndev->name, ndev); if (ret) { - printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME); + dev_err(&ndev->dev, "Can not assign IRQ number\n"); return ret; } @@ -947,7 +1108,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (!sh_eth_txfree(ndev)) { netif_stop_queue(ndev); spin_unlock_irqrestore(&mdp->lock, flags); - return 1; + return NETDEV_TX_BUSY; } } spin_unlock_irqrestore(&mdp->lock, flags); @@ -955,9 +1116,11 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) entry = mdp->cur_tx % TX_RING_SIZE; mdp->tx_skbuff[entry] = skb; txdesc = &mdp->tx_ring[entry]; - txdesc->addr = (u32)(skb->data); + txdesc->addr = virt_to_phys(skb->data); /* soft swap. */ - swaps((char *)(txdesc->addr & ~0x3), skb->len + 2); + if (!mdp->cd->hw_swap) + sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)), + skb->len + 2); /* write back */ __flush_purge_region(skb->data, skb->len); if (skb->len < ETHERSMALL) @@ -1059,7 +1222,7 @@ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, return phy_mii_ioctl(phydev, if_mii(rq), cmd); } - +#if defined(SH_ETH_HAS_TSU) /* Multicast reception directions set */ static void sh_eth_set_multicast_list(struct net_device *ndev) { @@ -1104,6 +1267,7 @@ static void sh_eth_tsu_init(u32 ioaddr) ctrl_outl(0, ioaddr + TSU_POST3); /* Disable CAM entry [16-23] */ ctrl_outl(0, ioaddr + TSU_POST4); /* Disable CAM entry [24-31] */ } +#endif /* SH_ETH_HAS_TSU */ /* MDIO bus release function */ static int sh_mdio_release(struct net_device *ndev) @@ -1193,7 +1357,9 @@ static const struct net_device_ops sh_eth_netdev_ops = { .ndo_stop = sh_eth_close, .ndo_start_xmit = sh_eth_start_xmit, .ndo_get_stats = sh_eth_get_stats, +#if defined(SH_ETH_HAS_TSU) .ndo_set_multicast_list = sh_eth_set_multicast_list, +#endif .ndo_tx_timeout = sh_eth_tx_timeout, .ndo_do_ioctl = sh_eth_do_ioctl, .ndo_validate_addr = eth_validate_addr, @@ -1219,7 +1385,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) ndev = alloc_etherdev(sizeof(struct sh_eth_private)); if (!ndev) { - printk(KERN_ERR "%s: could not allocate device.\n", CARDNAME); + dev_err(&pdev->dev, "Could not allocate device.\n"); ret = -ENOMEM; goto out; } @@ -1252,6 +1418,10 @@ static int sh_eth_drv_probe(struct platform_device *pdev) /* EDMAC endian */ mdp->edmac_endian = pd->edmac_endian; + /* set cpu data */ + mdp->cd = &sh_eth_my_cpu_data; + sh_eth_set_default_cpu_data(mdp->cd); + /* set function */ ndev->netdev_ops = &sh_eth_netdev_ops; ndev->watchdog_timeo = TX_TIMEOUT; @@ -1264,13 +1434,10 @@ static int sh_eth_drv_probe(struct platform_device *pdev) /* First device only init */ if (!devno) { -#if defined(ARSTR) - /* reset device */ - ctrl_outl(ARSTR_ARSTR, ARSTR); - mdelay(1); -#endif + if (mdp->cd->chip_reset) + mdp->cd->chip_reset(ndev); -#if defined(SH_TSU_ADDR) +#if defined(SH_ETH_HAS_TSU) /* TSU init (Init only)*/ sh_eth_tsu_init(SH_TSU_ADDR); #endif @@ -1287,8 +1454,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev) goto out_unregister; /* pritnt device infomation */ - printk(KERN_INFO "%s: %s at 0x%x, ", - ndev->name, CARDNAME, (u32) ndev->base_addr); + pr_info("Base address at 0x%x, ", + (u32)ndev->base_addr); for (i = 0; i < 5; i++) printk("%02X:", ndev->dev_addr[i]); diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 1537e13e623d..9afe5b4c855d 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -2,7 +2,7 @@ * SuperH Ethernet device driver * * Copyright (C) 2006-2008 Nobuhiro Iwamatsu - * Copyright (C) 2008 Renesas Solutions Corp. + * Copyright (C) 2008-2009 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -39,12 +39,12 @@ #define ETHERSMALL 60 #define PKT_BUF_SZ 1538 -#ifdef CONFIG_CPU_SUBTYPE_SH7763 +#if defined(CONFIG_CPU_SUBTYPE_SH7763) +/* This CPU register maps is very difference by other SH4 CPU */ -#define SH7763_SKB_ALIGN 32 /* Chip Base Address */ # define SH_TSU_ADDR 0xFEE01800 -# define ARSTR SH_TSU_ADDR +# define ARSTR SH_TSU_ADDR /* Chip Registers */ /* E-DMAC */ @@ -143,8 +143,60 @@ # define FWNLCR1 0xB0 # define FWALCR1 0x40 -#else /* CONFIG_CPU_SUBTYPE_SH7763 */ -# define RX_OFFSET 2 /* skb offset */ +#elif defined(CONFIG_CPU_SH4) /* #if defined(CONFIG_CPU_SUBTYPE_SH7763) */ +/* EtherC */ +#define ECMR 0x100 +#define RFLR 0x108 +#define ECSR 0x110 +#define ECSIPR 0x118 +#define PIR 0x120 +#define PSR 0x128 +#define RDMLR 0x140 +#define IPGR 0x150 +#define APR 0x154 +#define MPR 0x158 +#define TPAUSER 0x164 +#define RFCF 0x160 +#define TPAUSECR 0x168 +#define BCFRR 0x16c +#define MAHR 0x1c0 +#define MALR 0x1c8 +#define TROCR 0x1d0 +#define CDCR 0x1d4 +#define LCCR 0x1d8 +#define CNDCR 0x1dc +#define CEFCR 0x1e4 +#define FRECR 0x1e8 +#define TSFRCR 0x1ec +#define TLFRCR 0x1f0 +#define RFCR 0x1f4 +#define MAFCR 0x1f8 +#define RTRATE 0x1fc + +/* E-DMAC */ +#define EDMR 0x000 +#define EDTRR 0x008 +#define EDRRR 0x010 +#define TDLAR 0x018 +#define RDLAR 0x020 +#define EESR 0x028 +#define EESIPR 0x030 +#define TRSCER 0x038 +#define RMFCR 0x040 +#define TFTR 0x048 +#define FDR 0x050 +#define RMCR 0x058 +#define TFUCR 0x064 +#define RFOCR 0x068 +#define FCFTR 0x070 +#define RPADIR 0x078 +#define TRIMD 0x07c +#define RBWAR 0x0c8 +#define RDFAR 0x0cc +#define TBRAR 0x0d4 +#define TDFAR 0x0d8 +#else /* #elif defined(CONFIG_CPU_SH4) */ +/* This section is SH3 or SH2 */ #ifndef CONFIG_CPU_SUBTYPE_SH7619 /* Chip base address */ # define SH_TSU_ADDR 0xA7000804 @@ -243,6 +295,30 @@ #endif /* CONFIG_CPU_SUBTYPE_SH7763 */ +/* There are avoid compile error... */ +#if !defined(BCULR) +#define BCULR 0x0fc +#endif +#if !defined(TRIMD) +#define TRIMD 0x0fc +#endif +#if !defined(APR) +#define APR 0x0fc +#endif +#if !defined(MPR) +#define MPR 0x0fc +#endif +#if !defined(TPAUSER) +#define TPAUSER 0x0fc +#endif + +/* Driver's parameters */ +#if defined(CONFIG_CPU_SH4) +#define SH4_SKB_RX_ALIGN 32 +#else +#define SH2_SH3_SKB_RX_ALIGN 2 +#endif + /* * Register's bits */ @@ -261,11 +337,10 @@ enum GECMR_BIT { /* EDMR */ enum DMAC_M_BIT { + EDMR_EL = 0x40, /* Litte endian */ EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, #ifdef CONFIG_CPU_SUBTYPE_SH7763 - EDMR_SRST = 0x03, - EMDR_DESC_R = 0x30, /* Descriptor reserve size */ - EDMR_EL = 0x40, /* Litte endian */ + EDMR_SRST = 0x03, #else /* CONFIG_CPU_SUBTYPE_SH7763 */ EDMR_SRST = 0x01, #endif @@ -307,47 +382,43 @@ enum PHY_STATUS_BIT { PHY_ST_LINK = 0x01, }; /* EESR */ enum EESR_BIT { -#ifndef CONFIG_CPU_SUBTYPE_SH7763 - EESR_TWB = 0x40000000, -#else - EESR_TWB = 0xC0000000, - EESR_TC1 = 0x20000000, - EESR_TUC = 0x10000000, - EESR_ROC = 0x80000000, -#endif - EESR_TABT = 0x04000000, - EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000, -#ifndef CONFIG_CPU_SUBTYPE_SH7763 - EESR_ADE = 0x00800000, -#endif - EESR_ECI = 0x00400000, - EESR_FTC = 0x00200000, EESR_TDE = 0x00100000, - EESR_TFE = 0x00080000, EESR_FRC = 0x00040000, - EESR_RDE = 0x00020000, EESR_RFE = 0x00010000, -#ifndef CONFIG_CPU_SUBTYPE_SH7763 - EESR_CND = 0x00000800, -#endif - EESR_DLC = 0x00000400, - EESR_CD = 0x00000200, EESR_RTO = 0x00000100, - EESR_RMAF = 0x00000080, EESR_CEEF = 0x00000040, - EESR_CELF = 0x00000020, EESR_RRF = 0x00000010, - EESR_RTLF = 0x00000008, EESR_RTSF = 0x00000004, - EESR_PRE = 0x00000002, EESR_CERF = 0x00000001, + EESR_TWB1 = 0x80000000, + EESR_TWB = 0x40000000, /* same as TWB0 */ + EESR_TC1 = 0x20000000, + EESR_TUC = 0x10000000, + EESR_ROC = 0x08000000, + EESR_TABT = 0x04000000, + EESR_RABT = 0x02000000, + EESR_RFRMER = 0x01000000, /* same as RFCOF */ + EESR_ADE = 0x00800000, + EESR_ECI = 0x00400000, + EESR_FTC = 0x00200000, /* same as TC or TC0 */ + EESR_TDE = 0x00100000, + EESR_TFE = 0x00080000, /* same as TFUF */ + EESR_FRC = 0x00040000, /* same as FR */ + EESR_RDE = 0x00020000, + EESR_RFE = 0x00010000, + EESR_CND = 0x00000800, + EESR_DLC = 0x00000400, + EESR_CD = 0x00000200, + EESR_RTO = 0x00000100, + EESR_RMAF = 0x00000080, + EESR_CEEF = 0x00000040, + EESR_CELF = 0x00000020, + EESR_RRF = 0x00000010, + EESR_RTLF = 0x00000008, + EESR_RTSF = 0x00000004, + EESR_PRE = 0x00000002, + EESR_CERF = 0x00000001, }; - -#ifdef CONFIG_CPU_SUBTYPE_SH7763 -# define TX_CHECK (EESR_TC1 | EESR_FTC) -# define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \ - | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI) -# define TX_ERROR_CEHCK (EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE) - -#else -# define TX_CHECK (EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO) -# define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \ - | EESR_RFRMER | EESR_ADE | EESR_TFE | EESR_TDE | EESR_ECI) -# define TX_ERROR_CEHCK (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE) -#endif +#define DEFAULT_TX_CHECK (EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | \ + EESR_RTO) +#define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | \ + EESR_RDE | EESR_RFRMER | EESR_ADE | \ + EESR_TFE | EESR_TDE | EESR_ECI) +#define DEFAULT_TX_ERROR_CHECK (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | \ + EESR_TFE) /* EESIPR */ enum DMAC_IM_BIT { @@ -386,12 +457,8 @@ enum FCFTR_BIT { FCFTR_RFF0 = 0x00010000, FCFTR_RFD2 = 0x00000004, FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001, }; -#define FIFO_F_D_RFF (FCFTR_RFF2|FCFTR_RFF1|FCFTR_RFF0) -#ifndef CONFIG_CPU_SUBTYPE_SH7619 -#define FIFO_F_D_RFD (FCFTR_RFD2|FCFTR_RFD1|FCFTR_RFD0) -#else -#define FIFO_F_D_RFD (FCFTR_RFD0) -#endif +#define DEFAULT_FIFO_F_D_RFF (FCFTR_RFF2 | FCFTR_RFF1 | FCFTR_RFF0) +#define DEFAULT_FIFO_F_D_RFD (FCFTR_RFD2 | FCFTR_RFD1 | FCFTR_RFD0) /* Transfer descriptor bit */ enum TD_STS_BIT { @@ -404,60 +471,38 @@ enum TD_STS_BIT { #define TD_TFP (TD_TFP1|TD_TFP0) /* RMCR */ -enum RECV_RST_BIT { RMCR_RST = 0x01, }; +#define DEFAULT_RMCR_VALUE 0x00000000 + /* ECMR */ enum FELIC_MODE_BIT { -#ifdef CONFIG_CPU_SUBTYPE_SH7763 ECMR_TRCCM = 0x04000000, ECMR_RCSC = 0x00800000, ECMR_DPAD = 0x00200000, ECMR_RZPF = 0x00100000, -#endif ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000, ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000, ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, - ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, ECMR_DM = 0x00000002, - ECMR_PRM = 0x00000001, + ECMR_RTM = 0x00000010, ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, + ECMR_DM = 0x00000002, ECMR_PRM = 0x00000001, }; -#ifdef CONFIG_CPU_SUBTYPE_SH7763 -#define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF |\ - ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT) -#elif CONFIG_CPU_SUBTYPE_SH7619 -#define ECMR_CHG_DM (ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF) -#else -#define ECMR_CHG_DM (ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT) -#endif - /* ECSR */ enum ECSR_STATUS_BIT { -#ifndef CONFIG_CPU_SUBTYPE_SH7763 ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10, -#endif ECSR_LCHNG = 0x04, ECSR_MPD = 0x02, ECSR_ICD = 0x01, }; -#ifdef CONFIG_CPU_SUBTYPE_SH7763 -# define ECSR_INIT (ECSR_ICD | ECSIPR_MPDIP) -#else -# define ECSR_INIT (ECSR_BRCRX | ECSR_PSRTO | \ - ECSR_LCHNG | ECSR_ICD | ECSIPR_MPDIP) -#endif +#define DEFAULT_ECSR_INIT (ECSR_BRCRX | ECSR_PSRTO | ECSR_LCHNG | \ + ECSR_ICD | ECSIPR_MPDIP) /* ECSIPR */ enum ECSIPR_STATUS_MASK_BIT { -#ifndef CONFIG_CPU_SUBTYPE_SH7763 ECSIPR_BRCRXIP = 0x20, ECSIPR_PSRTOIP = 0x10, -#endif ECSIPR_LCHNGIP = 0x04, ECSIPR_MPDIP = 0x02, ECSIPR_ICDIP = 0x01, }; -#ifdef CONFIG_CPU_SUBTYPE_SH7763 -# define ECSIPR_INIT (ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP) -#else -# define ECSIPR_INIT (ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | \ - ECSIPR_ICDIP | ECSIPR_MPDIP) -#endif +#define DEFAULT_ECSIPR_INIT (ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | \ + ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP) /* APR */ enum APR_BIT { @@ -483,23 +528,12 @@ enum RPADIR_BIT { RPADIR_PADR = 0x0003f, }; -#if defined(CONFIG_CPU_SUBTYPE_SH7763) -# define RPADIR_INIT (0x00) -#else -# define RPADIR_INIT (RPADIR_PADS1) -#endif - /* RFLR */ #define RFLR_VALUE 0x1000 /* FDR */ -enum FIFO_SIZE_BIT { -#ifndef CONFIG_CPU_SUBTYPE_SH7619 - FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007, -#else - FIFO_SIZE_T = 0x00000100, FIFO_SIZE_R = 0x00000001, -#endif -}; +#define DEFAULT_FDR_INIT 0x00000707 + enum phy_offsets { PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3, PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6, @@ -633,7 +667,43 @@ struct sh_eth_rxdesc { u32 pad0; /* padding data */ } __attribute__((aligned(2), packed)); +/* This structure is used by each CPU dependency handling. */ +struct sh_eth_cpu_data { + /* optional functions */ + void (*chip_reset)(struct net_device *ndev); + void (*set_duplex)(struct net_device *ndev); + void (*set_rate)(struct net_device *ndev); + + /* mandatory initialize value */ + unsigned long eesipr_value; + + /* optional initialize value */ + unsigned long ecsr_value; + unsigned long ecsipr_value; + unsigned long fdr_value; + unsigned long fcftr_value; + unsigned long rpadir_value; + unsigned long rmcr_value; + + /* interrupt checking mask */ + unsigned long tx_check; + unsigned long eesr_err_check; + unsigned long tx_error_check; + + /* hardware features */ + unsigned no_psr:1; /* EtherC DO NOT have PSR */ + unsigned apr:1; /* EtherC have APR */ + unsigned mpr:1; /* EtherC have MPR */ + unsigned tpauser:1; /* EtherC have TPAUSER */ + unsigned bculr:1; /* EtherC have BCULR */ + unsigned hw_swap:1; /* E-DMAC have DE bit in EDMR */ + unsigned rpadir:1; /* E-DMAC have RPADIR */ + unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */ + unsigned no_ade:1; /* E-DMAC DO NOT have ADE bit in EESR */ +}; + struct sh_eth_private { + struct sh_eth_cpu_data *cd; dma_addr_t rx_desc_dma; dma_addr_t tx_desc_dma; struct sh_eth_rxdesc *rx_ring; @@ -661,11 +731,7 @@ struct sh_eth_private { struct net_device_stats tsu_stats; /* TSU forward status */ }; -#ifdef CONFIG_CPU_SUBTYPE_SH7763 -/* SH7763 has endian control register */ -#define swaps(x, y) -#else -static void swaps(char *src, int len) +static inline void sh_eth_soft_swap(char *src, int len) { #ifdef __LITTLE_ENDIAN__ u32 *p = (u32 *)src; @@ -676,5 +742,5 @@ static void swaps(char *src, int len) *p = swab32(*p); #endif } -#endif /* CONFIG_CPU_SUBTYPE_SH7763 */ -#endif + +#endif /* #ifndef __SH_ETH_H__ */ diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 55ccd51d247e..e2247669a495 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -47,7 +47,7 @@ #define PHY_ID_ANY 0x1f #define MII_REG_ANY 0x1f -#define DRV_VERSION "1.2" +#define DRV_VERSION "1.3" #define DRV_NAME "sis190" #define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION #define PFX DRV_NAME ": " @@ -317,6 +317,7 @@ static struct mii_chip_info { unsigned int type; u32 feature; } mii_chip_table[] = { + { "Atheros PHY", { 0x004d, 0xd010 }, LAN, 0 }, { "Atheros PHY AR8012", { 0x004d, 0xd020 }, LAN, 0 }, { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 }, { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 }, @@ -347,7 +348,7 @@ static struct { u32 msg_enable; } debug = { -1 }; -MODULE_DESCRIPTION("SiS sis190 Gigabit Ethernet driver"); +MODULE_DESCRIPTION("SiS sis190/191 Gigabit Ethernet driver"); module_param(rx_copybreak, int, 0); MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); module_param_named(debug, debug.msg_enable, int, 0); @@ -539,8 +540,8 @@ static bool sis190_try_rx_copy(struct sis190_private *tp, if (!skb) goto out; - pci_dma_sync_single_for_device(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(tp->pci_dev, addr, tp->rx_buf_sz, + PCI_DMA_FROMDEVICE); skb_reserve(skb, 2); skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size); *sk_buff = skb; @@ -942,9 +943,9 @@ static void sis190_phy_task(struct work_struct *work) u32 ctl; const char *msg; } reg31[] = { - { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000, + { LPA_1000FULL, 0x07000c00 | 0x00001000, "1000 Mbps Full Duplex" }, - { LPA_1000XHALF | LPA_SLCT, 0x07000c00, + { LPA_1000HALF, 0x07000c00, "1000 Mbps Half Duplex" }, { LPA_100FULL, 0x04000800 | 0x00001000, "100 Mbps Full Duplex" }, @@ -955,22 +956,35 @@ static void sis190_phy_task(struct work_struct *work) { LPA_10HALF, 0x04000400, "10 Mbps Half Duplex" }, { 0, 0x04000400, "unknown" } - }, *p; - u16 adv; + }, *p = NULL; + u16 adv, autoexp, gigadv, gigrec; val = mdio_read(ioaddr, phy_id, 0x1f); net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val); val = mdio_read(ioaddr, phy_id, MII_LPA); adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE); - net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n", - dev->name, val, adv); + autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION); + net_link(tp, KERN_INFO "%s: mii lpa=%04x adv=%04x exp=%04x.\n", + dev->name, val, adv, autoexp); - val &= adv; + if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) { + /* check for gigabit speed */ + gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000); + gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000); + val = (gigadv & (gigrec >> 2)); + if (val & ADVERTISE_1000FULL) + p = reg31; + else if (val & ADVERTISE_1000HALF) + p = reg31 + 1; + } + if (!p) { + val &= adv; - for (p = reg31; p->val; p++) { - if ((val & p->val) == p->val) - break; + for (p = reg31; p->val; p++) { + if ((val & p->val) == p->val) + break; + } } p->ctl |= SIS_R32(StationControl) & ~0x0f001c00; @@ -1204,8 +1218,6 @@ static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev) SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb); - dev->trans_start = jiffies; - dirty_tx = tp->dirty_tx; if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) { netif_stop_queue(dev); @@ -1315,12 +1327,15 @@ static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp, ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ? LAN : HOME) : p->type; tp->features |= p->feature; - } else + net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n", + pci_name(tp->pci_dev), p->name, phy_id); + } else { phy->type = UNKNOWN; - - net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n", - pci_name(tp->pci_dev), - (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id); + net_probe(tp, KERN_INFO + "%s: unknown PHY 0x%x:0x%x transceiver at address %d\n", + pci_name(tp->pci_dev), + phy->id[0], (phy->id[1] & 0xfff0), phy_id); + } } static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp) diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 2d4617b3e208..a9a897bb42d5 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1584,7 +1584,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) /* Don't transmit data before the complete of auto-negotiation */ if(!sis_priv->autong_complete){ netif_stop_queue(net_dev); - return 1; + return NETDEV_TX_BUSY; } spin_lock_irqsave(&sis_priv->lock, flags); diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index e14aec0a7333..088fe26484e7 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -159,12 +159,6 @@ MODULE_AUTHOR("Mirko Lindner "); static int num_boards; /* total number of adapters configured */ -#ifdef DRIVERDEBUG -#define PRINTK(s, args...) printk(s, ## args) -#else -#define PRINTK(s, args...) -#endif // DRIVERDEBUG - static const struct net_device_ops skfp_netdev_ops = { .ndo_open = skfp_open, .ndo_stop = skfp_close, @@ -213,7 +207,7 @@ static int skfp_init_one(struct pci_dev *pdev, void __iomem *mem; int err; - PRINTK(KERN_INFO "entering skfp_init_one\n"); + pr_debug(KERN_INFO "entering skfp_init_one\n"); if (num_boards == 0) printk("%s\n", boot_msg); @@ -389,7 +383,7 @@ static int skfp_driver_init(struct net_device *dev) skfddi_priv *bp = &smc->os; int err = -EIO; - PRINTK(KERN_INFO "entering skfp_driver_init\n"); + pr_debug(KERN_INFO "entering skfp_driver_init\n"); // set the io address in private structures bp->base_addr = dev->base_addr; @@ -409,7 +403,7 @@ static int skfp_driver_init(struct net_device *dev) // Determine the required size of the 'shared' memory area. bp->SharedMemSize = mac_drv_check_space(); - PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize); + pr_debug(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize); if (bp->SharedMemSize > 0) { bp->SharedMemSize += 16; // for descriptor alignment @@ -433,13 +427,13 @@ static int skfp_driver_init(struct net_device *dev) card_stop(smc); // Reset adapter. - PRINTK(KERN_INFO "mac_drv_init()..\n"); + pr_debug(KERN_INFO "mac_drv_init()..\n"); if (mac_drv_init(smc) != 0) { - PRINTK(KERN_INFO "mac_drv_init() failed.\n"); + pr_debug(KERN_INFO "mac_drv_init() failed.\n"); goto fail; } read_address(smc, NULL); - PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n", + pr_debug(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n", smc->hw.fddi_canon_addr.a[0], smc->hw.fddi_canon_addr.a[1], smc->hw.fddi_canon_addr.a[2], @@ -495,7 +489,7 @@ static int skfp_open(struct net_device *dev) struct s_smc *smc = netdev_priv(dev); int err; - PRINTK(KERN_INFO "entering skfp_open\n"); + pr_debug(KERN_INFO "entering skfp_open\n"); /* Register IRQ - support shared interrupts by passing device ptr */ err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED, dev->name, dev); @@ -868,12 +862,12 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) /* Enable promiscuous mode, if necessary */ if (dev->flags & IFF_PROMISC) { mac_drv_rx_mode(smc, RX_ENABLE_PROMISC); - PRINTK(KERN_INFO "PROMISCUOUS MODE ENABLED\n"); + pr_debug(KERN_INFO "PROMISCUOUS MODE ENABLED\n"); } /* Else, update multicast address table */ else { mac_drv_rx_mode(smc, RX_DISABLE_PROMISC); - PRINTK(KERN_INFO "PROMISCUOUS MODE DISABLED\n"); + pr_debug(KERN_INFO "PROMISCUOUS MODE DISABLED\n"); // Reset all MC addresses mac_clear_multicast(smc); @@ -881,7 +875,7 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI); - PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n"); + pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n"); } else if (dev->mc_count > 0) { if (dev->mc_count <= FPMAX_MULTICAST) { /* use exact filtering */ @@ -894,12 +888,12 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) (struct fddi_addr *)dmi->dmi_addr, 1); - PRINTK(KERN_INFO "ENABLE MC ADDRESS:"); - PRINTK(" %02x %02x %02x ", + pr_debug(KERN_INFO "ENABLE MC ADDRESS:"); + pr_debug(" %02x %02x %02x ", dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2]); - PRINTK("%02x %02x %02x\n", + pr_debug("%02x %02x %02x\n", dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); @@ -909,11 +903,11 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) } else { // more MC addresses than HW supports mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI); - PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n"); + pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n"); } } else { // no MC addresses - PRINTK(KERN_INFO "DISABLE ALL MC ADDRESSES\n"); + pr_debug(KERN_INFO "DISABLE ALL MC ADDRESSES\n"); } /* Update adapter filters */ @@ -1067,7 +1061,7 @@ static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev) struct s_smc *smc = netdev_priv(dev); skfddi_priv *bp = &smc->os; - PRINTK(KERN_INFO "skfp_send_pkt\n"); + pr_debug(KERN_INFO "skfp_send_pkt\n"); /* * Verify that incoming transmit request is OK @@ -1088,7 +1082,7 @@ static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev) if (bp->QueueSkb == 0) { // return with tbusy set: queue full netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; } bp->QueueSkb--; skb_queue_tail(&bp->SendSkbQueue, skb); @@ -1137,13 +1131,13 @@ static void send_queued_packets(struct s_smc *smc) int frame_status; // HWM tx frame status. - PRINTK(KERN_INFO "send queued packets\n"); + pr_debug(KERN_INFO "send queued packets\n"); for (;;) { // send first buffer from queue skb = skb_dequeue(&bp->SendSkbQueue); if (!skb) { - PRINTK(KERN_INFO "queue empty\n"); + pr_debug(KERN_INFO "queue empty\n"); return; } // queue empty ! @@ -1174,11 +1168,11 @@ static void send_queued_packets(struct s_smc *smc) if ((frame_status & RING_DOWN) != 0) { // Ring is down. - PRINTK("Tx attempt while ring down.\n"); + pr_debug("Tx attempt while ring down.\n"); } else if ((frame_status & OUT_OF_TXD) != 0) { - PRINTK("%s: out of TXDs.\n", bp->dev->name); + pr_debug("%s: out of TXDs.\n", bp->dev->name); } else { - PRINTK("%s: out of transmit resources", + pr_debug("%s: out of transmit resources", bp->dev->name); } @@ -1255,7 +1249,7 @@ static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr) static void ResetAdapter(struct s_smc *smc) { - PRINTK(KERN_INFO "[fddi: ResetAdapter]\n"); + pr_debug(KERN_INFO "[fddi: ResetAdapter]\n"); // Stop the adapter. @@ -1301,7 +1295,7 @@ void llc_restart_tx(struct s_smc *smc) { skfddi_priv *bp = &smc->os; - PRINTK(KERN_INFO "[llc_restart_tx]\n"); + pr_debug(KERN_INFO "[llc_restart_tx]\n"); // Try to send queued packets spin_unlock(&bp->DriverLock); @@ -1331,7 +1325,7 @@ void *mac_drv_get_space(struct s_smc *smc, unsigned int size) { void *virt; - PRINTK(KERN_INFO "mac_drv_get_space (%d bytes), ", size); + pr_debug(KERN_INFO "mac_drv_get_space (%d bytes), ", size); virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap); if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) { @@ -1340,9 +1334,9 @@ void *mac_drv_get_space(struct s_smc *smc, unsigned int size) } smc->os.SharedMemHeap += size; // Move heap pointer. - PRINTK(KERN_INFO "mac_drv_get_space end\n"); - PRINTK(KERN_INFO "virt addr: %lx\n", (ulong) virt); - PRINTK(KERN_INFO "bus addr: %lx\n", (ulong) + pr_debug(KERN_INFO "mac_drv_get_space end\n"); + pr_debug(KERN_INFO "virt addr: %lx\n", (ulong) virt); + pr_debug(KERN_INFO "bus addr: %lx\n", (ulong) (smc->os.SharedMemDMA + ((char *) virt - (char *)smc->os.SharedMemAddr))); return (virt); @@ -1372,7 +1366,7 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size) char *virt; - PRINTK(KERN_INFO "mac_drv_get_desc_mem\n"); + pr_debug(KERN_INFO "mac_drv_get_desc_mem\n"); // Descriptor memory must be aligned on 16-byte boundary. @@ -1381,8 +1375,8 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size) size = (u_int) (16 - (((unsigned long) virt) & 15UL)); size = size % 16; - PRINTK("Allocate %u bytes alignment gap ", size); - PRINTK("for descriptor memory.\n"); + pr_debug("Allocate %u bytes alignment gap ", size); + pr_debug("for descriptor memory.\n"); if (!mac_drv_get_space(smc, size)) { printk("fddi: Unable to align descriptor memory.\n"); @@ -1516,11 +1510,11 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd) { struct sk_buff *skb; - PRINTK(KERN_INFO "entering mac_drv_tx_complete\n"); + pr_debug(KERN_INFO "entering mac_drv_tx_complete\n"); // Check if this TxD points to a skb if (!(skb = txd->txd_os.skb)) { - PRINTK("TXD with no skb assigned.\n"); + pr_debug("TXD with no skb assigned.\n"); return; } txd->txd_os.skb = NULL; @@ -1536,7 +1530,7 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd) // free the skb dev_kfree_skb_irq(skb); - PRINTK(KERN_INFO "leaving mac_drv_tx_complete\n"); + pr_debug(KERN_INFO "leaving mac_drv_tx_complete\n"); } // mac_drv_tx_complete @@ -1603,7 +1597,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, unsigned short ri; u_int RifLength; - PRINTK(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len); + pr_debug(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len); if (frag_count != 1) { // This is not allowed to happen. printk("fddi: Multi-fragment receive!\n"); @@ -1612,7 +1606,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, } skb = rxd->rxd_os.skb; if (!skb) { - PRINTK(KERN_INFO "No skb in rxd\n"); + pr_debug(KERN_INFO "No skb in rxd\n"); smc->os.MacStat.gen.rx_errors++; goto RequeueRxd; } @@ -1642,7 +1636,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, else { int n; // goos: RIF removal has still to be tested - PRINTK(KERN_INFO "RIF found\n"); + pr_debug(KERN_INFO "RIF found\n"); // Get RIF length from Routing Control (RC) field. cp = virt + FDDI_MAC_HDR_LEN; // Point behind MAC header. @@ -1687,7 +1681,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, return; RequeueRxd: - PRINTK(KERN_INFO "Rx: re-queue RXD.\n"); + pr_debug(KERN_INFO "Rx: re-queue RXD.\n"); mac_drv_requeue_rxd(smc, rxd, frag_count); smc->os.MacStat.gen.rx_errors++; // Count receive packets // not indicated. @@ -1736,7 +1730,7 @@ void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, skb = src_rxd->rxd_os.skb; if (skb == NULL) { // this should not happen - PRINTK("Requeue with no skb in rxd!\n"); + pr_debug("Requeue with no skb in rxd!\n"); skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb @@ -1751,7 +1745,7 @@ void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, rxd->rxd_os.dma_addr = b_addr; } else { // no skb available, use local buffer - PRINTK("Queueing invalid buffer!\n"); + pr_debug("Queueing invalid buffer!\n"); rxd->rxd_os.skb = NULL; v_addr = smc->os.LocalRxBuffer; b_addr = smc->os.LocalRxBufferDMA; @@ -1798,7 +1792,7 @@ void mac_drv_fill_rxd(struct s_smc *smc) struct sk_buff *skb; volatile struct s_smt_fp_rxd *rxd; - PRINTK(KERN_INFO "entering mac_drv_fill_rxd\n"); + pr_debug(KERN_INFO "entering mac_drv_fill_rxd\n"); // Walk through the list of free receive buffers, passing receive // buffers to the HWM as long as RXDs are available. @@ -1806,7 +1800,7 @@ void mac_drv_fill_rxd(struct s_smc *smc) MaxFrameSize = smc->os.MaxFrameSize; // Check if there is any RXD left. while (HWM_GET_RX_FREE(smc) > 0) { - PRINTK(KERN_INFO ".\n"); + pr_debug(KERN_INFO ".\n"); rxd = HWM_GET_CURR_RXD(smc); skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); @@ -1826,7 +1820,7 @@ void mac_drv_fill_rxd(struct s_smc *smc) // keep the receiver running in hope of better times. // Multiple descriptors may point to this local buffer, // so data in it must be considered invalid. - PRINTK("Queueing invalid buffer!\n"); + pr_debug("Queueing invalid buffer!\n"); v_addr = smc->os.LocalRxBuffer; b_addr = smc->os.LocalRxBufferDMA; } @@ -1837,7 +1831,7 @@ void mac_drv_fill_rxd(struct s_smc *smc) hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, FIRST_FRAG | LAST_FRAG); } - PRINTK(KERN_INFO "leaving mac_drv_fill_rxd\n"); + pr_debug(KERN_INFO "leaving mac_drv_fill_rxd\n"); } // mac_drv_fill_rxd @@ -1863,7 +1857,7 @@ void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, struct sk_buff *skb; - PRINTK("entering mac_drv_clear_rxd\n"); + pr_debug("entering mac_drv_clear_rxd\n"); if (frag_count != 1) // This is not allowed to happen. @@ -1919,19 +1913,19 @@ int mac_drv_rx_init(struct s_smc *smc, int len, int fc, { struct sk_buff *skb; - PRINTK("entering mac_drv_rx_init(len=%d)\n", len); + pr_debug("entering mac_drv_rx_init(len=%d)\n", len); // "Received" a SMT or NSA frame of the local SMT. if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) { - PRINTK("fddi: Discard invalid local SMT frame\n"); - PRINTK(" len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n", + pr_debug("fddi: Discard invalid local SMT frame\n"); + pr_debug(" len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n", len, la_len, (unsigned long) look_ahead); return (0); } skb = alloc_skb(len + 3, GFP_ATOMIC); if (!skb) { - PRINTK("fddi: Local SMT: skb memory exhausted.\n"); + pr_debug("fddi: Local SMT: skb memory exhausted.\n"); return (0); } skb_reserve(skb, 3); @@ -1981,40 +1975,40 @@ void smt_timer_poll(struct s_smc *smc) ************************/ void ring_status_indication(struct s_smc *smc, u_long status) { - PRINTK("ring_status_indication( "); + pr_debug("ring_status_indication( "); if (status & RS_RES15) - PRINTK("RS_RES15 "); + pr_debug("RS_RES15 "); if (status & RS_HARDERROR) - PRINTK("RS_HARDERROR "); + pr_debug("RS_HARDERROR "); if (status & RS_SOFTERROR) - PRINTK("RS_SOFTERROR "); + pr_debug("RS_SOFTERROR "); if (status & RS_BEACON) - PRINTK("RS_BEACON "); + pr_debug("RS_BEACON "); if (status & RS_PATHTEST) - PRINTK("RS_PATHTEST "); + pr_debug("RS_PATHTEST "); if (status & RS_SELFTEST) - PRINTK("RS_SELFTEST "); + pr_debug("RS_SELFTEST "); if (status & RS_RES9) - PRINTK("RS_RES9 "); + pr_debug("RS_RES9 "); if (status & RS_DISCONNECT) - PRINTK("RS_DISCONNECT "); + pr_debug("RS_DISCONNECT "); if (status & RS_RES7) - PRINTK("RS_RES7 "); + pr_debug("RS_RES7 "); if (status & RS_DUPADDR) - PRINTK("RS_DUPADDR "); + pr_debug("RS_DUPADDR "); if (status & RS_NORINGOP) - PRINTK("RS_NORINGOP "); + pr_debug("RS_NORINGOP "); if (status & RS_VERSION) - PRINTK("RS_VERSION "); + pr_debug("RS_VERSION "); if (status & RS_STUCKBYPASSS) - PRINTK("RS_STUCKBYPASSS "); + pr_debug("RS_STUCKBYPASSS "); if (status & RS_EVENT) - PRINTK("RS_EVENT "); + pr_debug("RS_EVENT "); if (status & RS_RINGOPCHANGE) - PRINTK("RS_RINGOPCHANGE "); + pr_debug("RS_RINGOPCHANGE "); if (status & RS_RES0) - PRINTK("RS_RES0 "); - PRINTK("]\n"); + pr_debug("RS_RES0 "); + pr_debug("]\n"); } // ring_status_indication @@ -2057,17 +2051,17 @@ void smt_stat_counter(struct s_smc *smc, int stat) { // BOOLEAN RingIsUp ; - PRINTK(KERN_INFO "smt_stat_counter\n"); + pr_debug(KERN_INFO "smt_stat_counter\n"); switch (stat) { case 0: - PRINTK(KERN_INFO "Ring operational change.\n"); + pr_debug(KERN_INFO "Ring operational change.\n"); break; case 1: - PRINTK(KERN_INFO "Receive fifo overflow.\n"); + pr_debug(KERN_INFO "Receive fifo overflow.\n"); smc->os.MacStat.gen.rx_errors++; break; default: - PRINTK(KERN_INFO "Unknown status (%d).\n", stat); + pr_debug(KERN_INFO "Unknown status (%d).\n", stat); break; } } // smt_stat_counter @@ -2123,10 +2117,10 @@ void cfm_state_change(struct s_smc *smc, int c_state) s = "SC11_C_WRAP_S"; break; default: - PRINTK(KERN_INFO "cfm_state_change: unknown %d\n", c_state); + pr_debug(KERN_INFO "cfm_state_change: unknown %d\n", c_state); return; } - PRINTK(KERN_INFO "cfm_state_change: %s\n", s); + pr_debug(KERN_INFO "cfm_state_change: %s\n", s); #endif // DRIVERDEBUG } // cfm_state_change @@ -2181,7 +2175,7 @@ void ecm_state_change(struct s_smc *smc, int e_state) s = "unknown"; break; } - PRINTK(KERN_INFO "ecm_state_change: %s\n", s); + pr_debug(KERN_INFO "ecm_state_change: %s\n", s); #endif //DRIVERDEBUG } // ecm_state_change @@ -2236,7 +2230,7 @@ void rmt_state_change(struct s_smc *smc, int r_state) s = "unknown"; break; } - PRINTK(KERN_INFO "[rmt_state_change: %s]\n", s); + pr_debug(KERN_INFO "[rmt_state_change: %s]\n", s); #endif // DRIVERDEBUG } // rmt_state_change @@ -2256,7 +2250,7 @@ void rmt_state_change(struct s_smc *smc, int r_state) ************************/ void drv_reset_indication(struct s_smc *smc) { - PRINTK(KERN_INFO "entering drv_reset_indication\n"); + pr_debug(KERN_INFO "entering drv_reset_indication\n"); smc->os.ResetRequested = TRUE; // Set flag. diff --git a/drivers/net/skge.c b/drivers/net/skge.c index c11cdd08ec57..60d502eef4fc 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2837,8 +2837,6 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - dev->trans_start = jiffies; - return NETDEV_TX_OK; } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a2ff9cb1e7ac..6b5946fe8ae2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1690,7 +1690,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); - dev->trans_start = jiffies; return NETDEV_TX_OK; mapping_unwind: diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 8d36d40649ef..c791ef76c1d6 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -370,7 +370,7 @@ static int __init ultramca_probe(struct device *gen_dev) outb(reg4, ioaddr + 4); - gen_dev->driver_data = dev; + dev_set_drvdata(gen_dev, dev); /* The 8390 isn't at the base address, so fake the offset */ @@ -531,7 +531,7 @@ static int ultramca_close_card(struct net_device *dev) static int ultramca_remove(struct device *gen_dev) { struct mca_device *mca_dev = to_mca_device(gen_dev); - struct net_device *dev = (struct net_device *)gen_dev->driver_data; + struct net_device *dev = dev_get_drvdata(gen_dev); if (dev) { /* NB: ultra_close_card() does free_irq */ diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 293610334a77..bc4976ac8712 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1774,6 +1774,20 @@ static int __devinit smc911x_findirq(struct net_device *dev) return probe_irq_off(cookie); } +static const struct net_device_ops smc911x_netdev_ops = { + .ndo_open = smc911x_open, + .ndo_stop = smc911x_close, + .ndo_start_xmit = smc911x_hard_start_xmit, + .ndo_tx_timeout = smc911x_timeout, + .ndo_set_multicast_list = smc911x_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = smc911x_poll_controller, +#endif +}; + /* * Function: smc911x_probe(unsigned long ioaddr) * @@ -1940,16 +1954,9 @@ static int __devinit smc911x_probe(struct net_device *dev) /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); - dev->open = smc911x_open; - dev->stop = smc911x_close; - dev->hard_start_xmit = smc911x_hard_start_xmit; - dev->tx_timeout = smc911x_timeout; + dev->netdev_ops = &smc911x_netdev_ops; dev->watchdog_timeo = msecs_to_jiffies(watchdog); - dev->set_multicast_list = smc911x_set_multicast_list; dev->ethtool_ops = &smc911x_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = smc911x_poll_controller; -#endif INIT_WORK(&lp->phy_configure, smc911x_phy_configure); lp->mii.phy_id_mask = 0x1f; diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 9a7973a54116..e02471b2f2b5 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -503,7 +503,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de /* THIS SHOULD NEVER HAPPEN. */ dev->stats.tx_aborted_errors++; printk(CARDNAME": Bad Craziness - sent packet while busy.\n" ); - return 1; + return NETDEV_TX_BUSY; } lp->saved_skb = skb; diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index eb7db032a780..b60639bd181b 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include "smsc911x.h" @@ -175,6 +176,12 @@ static inline void smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, unsigned int wordcount) { + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { + while (wordcount--) + smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++)); + return; + } + if (pdata->config.flags & SMSC911X_USE_32BIT) { writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount); return; @@ -194,6 +201,12 @@ static inline void smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, unsigned int wordcount) { + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { + while (wordcount--) + *buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO)); + return; + } + if (pdata->config.flags & SMSC911X_USE_32BIT) { readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount); return; @@ -1963,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = -ENODEV; goto out_0; } - res_size = res->end - res->start; + res_size = res->end - res->start + 1; irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { @@ -2096,12 +2109,58 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) return retval; } +#ifdef CONFIG_PM +/* 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) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct smsc911x_data *pdata = netdev_priv(dev); + + /* enable wake on LAN, energy detection and the external PME + * signal. */ + smsc911x_reg_write(pdata, PMT_CTRL, + PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ | + PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_); + + return 0; +} + +static int smsc911x_resume(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct smsc911x_data *pdata = netdev_priv(dev); + unsigned int to = 100; + + /* Note 3.11 from the datasheet: + * "When the LAN9220 is in a power saving state, a write of any + * data to the BYTE_TEST register will wake-up the device." + */ + smsc911x_reg_write(pdata, BYTE_TEST, 0); + + /* poll the READY bit in PMT_CTRL. Any other access to the device is + * forbidden while this bit isn't set. Try for 100ms and return -EIO + * if it failed. */ + while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) + udelay(1000); + + return (to == 0) ? -EIO : 0; +} + +#else +#define smsc911x_suspend NULL +#define smsc911x_resume NULL +#endif + static struct platform_driver smsc911x_driver = { .probe = smsc911x_drv_probe, - .remove = smsc911x_drv_remove, + .remove = __devexit_p(smsc911x_drv_remove), .driver = { .name = SMSC_CHIPNAME, }, + .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 211e805c1223..e4255d829380 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -223,7 +223,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) if (!laddr) { printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name); dev_kfree_skb(skb); - return 1; + return NETDEV_TX_BUSY } sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index fcb943fca4f1..838cce8b8fff 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1236,7 +1236,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) */ if ((np->cur_tx - np->dirty_tx) + skb_num_frags(skb) * 2 > TX_RING_SIZE) { netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; } #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE) diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index a39c0b9ba8b6..7bb27426dbd6 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -1023,7 +1023,7 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev) #if(NUM_XMIT_BUFFS > 1) if(test_and_set_bit(0,(void *) &p->lock)) { printk("%s: Queue was locked\n",dev->name); - return 1; + return NETDEV_TX_BUSY; } else #endif diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index e5beb299cbd0..534dfe3eef6f 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -294,6 +294,16 @@ struct net_device * __init sun3lance_probe(int unit) return ERR_PTR(err); } +static const struct net_device_ops lance_netdev_ops = { + .ndo_open = lance_open, + .ndo_stop = lance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_set_mac_address = NULL, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init lance_probe( struct net_device *dev) { unsigned long ioaddr; @@ -397,12 +407,7 @@ static int __init lance_probe( struct net_device *dev) if (did_version++ == 0) printk( version ); - /* The LANCE-specific entries in the device structure. */ - dev->open = &lance_open; - dev->hard_start_xmit = &lance_start_xmit; - dev->stop = &lance_close; - dev->set_multicast_list = &set_multicast_list; - dev->set_mac_address = NULL; + dev->netdev_ops = &lance_netdev_ops; // KLUDGE -- REMOVE ME set_bit(__LINK_STATE_PRESENT, &dev->state); @@ -521,7 +526,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) if (netif_queue_stopped(dev)) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 20) - return( 1 ); + return NETDEV_TX_BUSY; DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", dev->name, DREG )); @@ -572,7 +577,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) { printk( "%s: tx queue lock!.\n", dev->name); /* don't clear dev->tbusy flag. */ - return 1; + return NETDEV_TX_BUSY; } AREG = CSR0; diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index c399b1955c1e..545f81b34ad7 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -369,7 +369,6 @@ struct netdev_private { struct sk_buff* tx_skbuff[TX_RING_SIZE]; dma_addr_t tx_ring_dma; dma_addr_t rx_ring_dma; - struct net_device_stats stats; struct timer_list timer; /* Media monitoring timer. */ /* Frequently used values: keep some adjacent for cache effect. */ spinlock_t lock; @@ -975,7 +974,7 @@ static void tx_timeout(struct net_device *dev) dev->if_port = 0; dev->trans_start = jiffies; - np->stats.tx_errors++; + dev->stats.tx_errors++; if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { netif_wake_queue(dev); } @@ -1123,7 +1122,7 @@ reset_tx (struct net_device *dev) else dev_kfree_skb (skb); np->tx_skbuff[i] = NULL; - np->stats.tx_dropped++; + dev->stats.tx_dropped++; } } np->cur_tx = np->dirty_tx = 0; @@ -1181,15 +1180,15 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) if (netif_msg_tx_err(np)) printk("%s: Transmit error status %4.4x.\n", dev->name, tx_status); - np->stats.tx_errors++; + dev->stats.tx_errors++; if (tx_status & 0x10) - np->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; if (tx_status & 0x08) - np->stats.collisions++; + dev->stats.collisions++; if (tx_status & 0x04) - np->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; if (tx_status & 0x02) - np->stats.tx_window_errors++; + dev->stats.tx_window_errors++; /* ** This reset has been verified on @@ -1313,11 +1312,15 @@ static void rx_poll(unsigned long data) if (netif_msg_rx_err(np)) printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", frame_status); - np->stats.rx_errors++; - if (frame_status & 0x00100000) np->stats.rx_length_errors++; - if (frame_status & 0x00010000) np->stats.rx_fifo_errors++; - if (frame_status & 0x00060000) np->stats.rx_frame_errors++; - if (frame_status & 0x00080000) np->stats.rx_crc_errors++; + dev->stats.rx_errors++; + if (frame_status & 0x00100000) + dev->stats.rx_length_errors++; + if (frame_status & 0x00010000) + dev->stats.rx_fifo_errors++; + if (frame_status & 0x00060000) + dev->stats.rx_frame_errors++; + if (frame_status & 0x00080000) + dev->stats.rx_crc_errors++; if (frame_status & 0x00100000) { printk(KERN_WARNING "%s: Oversized Ethernet frame," " status %8.8x.\n", @@ -1485,22 +1488,22 @@ static struct net_device_stats *get_stats(struct net_device *dev) the vulnerability window is very small and statistics are non-critical. */ /* The chip only need report frame silently dropped. */ - np->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); - np->stats.tx_packets += ioread16(ioaddr + TxFramesOK); - np->stats.rx_packets += ioread16(ioaddr + RxFramesOK); - np->stats.collisions += ioread8(ioaddr + StatsLateColl); - np->stats.collisions += ioread8(ioaddr + StatsMultiColl); - np->stats.collisions += ioread8(ioaddr + StatsOneColl); - np->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); + dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); + dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK); + dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK); + dev->stats.collisions += ioread8(ioaddr + StatsLateColl); + dev->stats.collisions += ioread8(ioaddr + StatsMultiColl); + dev->stats.collisions += ioread8(ioaddr + StatsOneColl); + dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); ioread8(ioaddr + StatsTxDefer); for (i = StatsTxDefer; i <= StatsMcastRx; i++) ioread8(ioaddr + i); - np->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); - np->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; - np->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); - np->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16; + dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); + dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; + dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); + dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16; - return &np->stats; + return &dev->stats; } static void set_rx_mode(struct net_device *dev) diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 4e9bd380a5c2..4ef729198e10 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2275,7 +2275,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&hp->happy_lock); printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } entry = hp->tx_new; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 0ce2db6ce2bf..d737f6b8f876 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -688,14 +688,11 @@ static void tc_handle_link_change(struct net_device *dev) if (status_change && netif_msg_link(lp)) { phy_print_status(phydev); -#ifdef DEBUG - printk(KERN_DEBUG - "%s: MII BMCR %04x BMSR %04x LPA %04x\n", - dev->name, - phy_read(phydev, MII_BMCR), - phy_read(phydev, MII_BMSR), - phy_read(phydev, MII_LPA)); -#endif + pr_debug("%s: MII BMCR %04x BMSR %04x LPA %04x\n", + dev->name, + phy_read(phydev, MII_BMCR), + phy_read(phydev, MII_BMSR), + phy_read(phydev, MII_LPA)); } } diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 7f4a9683ba1e..3c2679cd196b 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -948,8 +948,7 @@ static void print_rxfd(struct rxf_desc *rxfd); static void bdx_rxdb_destroy(struct rxdb *db) { - if (db) - vfree(db); + vfree(db); } static struct rxdb *bdx_rxdb_create(int nelem) @@ -1482,10 +1481,8 @@ static void bdx_tx_db_close(struct txdb *d) { BDX_ASSERT(d == NULL); - if (d->start) { - vfree(d->start); - d->start = NULL; - } + vfree(d->start); + d->start = NULL; } /************************************************************************* @@ -1718,8 +1715,9 @@ static int bdx_tx_transmit(struct sk_buff *skb, struct net_device *ndev) WRITE_REG(priv, f->m.reg_WPTR, f->m.wptr & TXF_WPTR_WR_PTR); #endif - ndev->trans_start = jiffies; - +#ifdef BDX_LLTX + ndev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ +#endif priv->net_stats.tx_packets++; priv->net_stats.tx_bytes += skb->len; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 201be425643a..46a3f86125be 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.98" -#define DRV_MODULE_RELDATE "February 25, 2009" +#define DRV_MODULE_VERSION "3.99" +#define DRV_MODULE_RELDATE "April 20, 2009" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1950,7 +1950,8 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); - } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) { /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */ u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | @@ -2455,8 +2456,6 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } - __tg3_set_mac_addr(tp, 0); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u32 val; @@ -4656,6 +4655,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) * so we must read it before checking for more work. */ tp->last_tag = sblk->status_tag; + tp->last_irq_tag = tp->last_tag; rmb(); } else sblk->status &= ~SD_STATUS_UPDATED; @@ -4811,7 +4811,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if (unlikely(sblk->status_tag == tp->last_tag)) { + if (unlikely(sblk->status_tag == tp->last_irq_tag)) { if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { handled = 0; @@ -4831,18 +4831,22 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * excessive spurious interrupts can be worse in some cases. */ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + + /* + * In a shared interrupt configuration, sometimes other devices' + * interrupts will scream. We record the current status tag here + * so that the above check can report that the screaming interrupts + * are unhandled. Eventually they will be silenced. + */ + tp->last_irq_tag = sblk->status_tag; + if (tg3_irq_sync(tp)) goto out; - if (napi_schedule_prep(&tp->napi)) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - /* Update last_tag to mark that this status has been - * seen. Because interrupt may be shared, we may be - * racing with tg3_poll(), so only update last_tag - * if tg3_poll() is not scheduled. - */ - tp->last_tag = sblk->status_tag; - __napi_schedule(&tp->napi); - } + + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + + napi_schedule(&tp->napi); + out: return IRQ_RETVAL(handled); } @@ -5017,7 +5021,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, /* New SKB is guaranteed to be linear. */ entry = *start; ret = skb_dma_map(&tp->pdev->dev, new_skb, DMA_TO_DEVICE); - new_addr = skb_shinfo(new_skb)->dma_maps[0]; + new_addr = skb_shinfo(new_skb)->dma_head; /* Make sure new skb does not cross any 4G boundaries. * Drop the packet if it does. @@ -5151,7 +5155,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) sp = skb_shinfo(skb); - mapping = sp->dma_maps[0]; + mapping = sp->dma_head; tp->tx_buffers[entry].skb = skb; @@ -5169,7 +5173,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; len = frag->size; - mapping = sp->dma_maps[i + 1]; + mapping = sp->dma_maps[i]; tp->tx_buffers[entry].skb = NULL; tg3_set_txd(tp, entry, mapping, len, @@ -5190,9 +5194,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } out_unlock: - mmiowb(); - - dev->trans_start = jiffies; + mmiowb(); return NETDEV_TX_OK; } @@ -5329,7 +5331,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) sp = skb_shinfo(skb); - mapping = sp->dma_maps[0]; + mapping = sp->dma_head; tp->tx_buffers[entry].skb = skb; @@ -5354,7 +5356,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; len = frag->size; - mapping = sp->dma_maps[i + 1]; + mapping = sp->dma_maps[i]; tp->tx_buffers[entry].skb = NULL; @@ -5403,9 +5405,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) } out_unlock: - mmiowb(); - - dev->trans_start = jiffies; + mmiowb(); return NETDEV_TX_OK; } @@ -6156,6 +6156,7 @@ static int tg3_chip_reset(struct tg3 *tp) tp->hw_status->status_tag = 0; } tp->last_tag = 0; + tp->last_irq_tag = 0; smp_mb(); synchronize_irq(tp->pdev->irq); @@ -6350,6 +6351,8 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) tg3_abort_hw(tp, silent); err = tg3_chip_reset(tp); + __tg3_set_mac_addr(tp, 0); + tg3_write_sig_legacy(tp, kind); tg3_write_sig_post_reset(tp, kind); @@ -6711,6 +6714,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_CPMU_HST_ACC, val); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { + val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK; + val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN | + PCIE_PWR_MGMT_L1_THRESH_4MS; + tw32(PCIE_PWR_MGMT_THRESH, val); + } + /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. But do not set this on PCI Express @@ -7138,7 +7148,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(100); tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); - tp->last_tag = 0; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); @@ -8539,6 +8548,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u32 i, offset, len, b_offset, b_count; __be32 val; + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + return -EINVAL; + if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -8604,7 +8616,8 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if (tp->link_config.phy_is_low_power) return -EAGAIN; - if (eeprom->magic != TG3_EEPROM_MAGIC) + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + eeprom->magic != TG3_EEPROM_MAGIC) return -EINVAL; offset = eeprom->offset; @@ -9201,6 +9214,9 @@ static int tg3_test_nvram(struct tg3 *tp) __be32 *buf; int i, j, k, err = 0, size; + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + return 0; + if (tg3_nvram_read(tp, 0, &magic) != 0) return -EIO; @@ -10183,7 +10199,8 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) { u32 val; - if (tg3_nvram_read(tp, 0, &val) != 0) + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + tg3_nvram_read(tp, 0, &val) != 0) return; /* Selfboot format */ @@ -10565,6 +10582,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) } break; default: + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; return; } @@ -11365,7 +11383,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp) unsigned int i; u32 magic; - if (tg3_nvram_read(tp, 0x0, &magic)) + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + tg3_nvram_read(tp, 0x0, &magic)) goto out_not_found; if (magic == TG3_EEPROM_MAGIC) { @@ -11457,6 +11476,15 @@ static void __devinit tg3_read_partno(struct tg3 *tp) out_not_found: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) strcpy(tp->board_part_number, "BCM95906"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780) + strcpy(tp->board_part_number, "BCM57780"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760) + strcpy(tp->board_part_number, "BCM57760"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790) + strcpy(tp->board_part_number, "BCM57790"); else strcpy(tp->board_part_number, "none"); } @@ -11667,6 +11695,14 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) { u32 val; + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) { + tp->fw_ver[0] = 's'; + tp->fw_ver[1] = 'b'; + tp->fw_ver[2] = '\0'; + + return; + } + if (tg3_nvram_read(tp, 0, &val)) return; @@ -11952,7 +11988,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_57780_A1) tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG; } } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { @@ -12144,7 +12181,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; - if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) { /* Turn off the debug UART. */ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) @@ -12454,7 +12492,8 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) } if (!addr_ok) { /* Next, try NVRAM. */ - if (!tg3_nvram_read_be32(tp, mac_offset + 0, &hi) && + if (!(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) && + !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) && !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) { memcpy(&dev->dev_addr[0], ((char *)&hi) + 2, 2); memcpy(&dev->dev_addr[2], (char *)&lo, sizeof(lo)); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index cb4c62abdd21..b3347c41a1a3 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -95,6 +95,8 @@ #define CHIPREV_ID_5752_A1 0x6001 #define CHIPREV_ID_5714_A2 0x9002 #define CHIPREV_ID_5906_A1 0xc001 +#define CHIPREV_ID_57780_A0 0x57780000 +#define CHIPREV_ID_57780_A1 0x57780001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -1697,6 +1699,8 @@ #define PCIE_PWR_MGMT_THRESH 0x00007d28 #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 +#define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00 +#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000 /* OTP bit definitions */ @@ -2501,6 +2505,7 @@ struct tg3 { struct tg3_hw_status *hw_status; dma_addr_t status_mapping; u32 last_tag; + u32 last_irq_tag; u32 msg_enable; @@ -2635,6 +2640,7 @@ struct tg3 { #define TG3_FLG3_CLKREQ_BUG 0x00000800 #define TG3_FLG3_PHY_ENABLE_APD 0x00001000 #define TG3_FLG3_5755_PLUS 0x00002000 +#define TG3_FLG3_NO_NVRAM 0x00004000 struct timer_list timer; u16 timer_counter; diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index aa6964922d5e..384cb5e28397 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1111,7 +1111,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) dev->name, priv->txHead, priv->txTail ); netif_stop_queue(dev); priv->txBusyCount++; - return 1; + return NETDEV_TX_BUSY; } tail_list->forward = 0; diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 0337b9d673f4..b40b6de2d086 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -1243,7 +1243,7 @@ static int xl_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } else { spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ; - return 1; + return NETDEV_TX_BUSY; } } diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 46a2cc92d979..b3715efdce56 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -1187,7 +1187,7 @@ static int streamer_xmit(struct sk_buff *skb, struct net_device *dev) } else { netif_stop_queue(dev); spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags); - return 1; + return NETDEV_TX_BUSY; } } diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 2d819fc85589..451b54136ede 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1055,7 +1055,7 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } else { spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); - return 1; + return NETDEV_TX_BUSY; } } diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index a91d9c55d78e..54ad4ed03374 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -4601,7 +4601,7 @@ static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); if(tp->QueueSkb == 0) - return (1); /* Return with tbusy set: queue full */ + return NETDEV_TX_BUSY; /* Return with tbusy set: queue full */ tp->QueueSkb--; skb_queue_tail(&tp->SendSkbQueue, skb); diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index b11bb72dc7ab..a2eab72b507a 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -633,7 +633,7 @@ static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device if (tms380tr_debug > 0) printk(KERN_DEBUG "%s: No free TPL\n", dev->name); spin_unlock_irqrestore(&tp->lock, flags); - return 1; + return NETDEV_TX_BUSY; } dmabuf = 0; diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index d913405bc393..1cc8cf4425d1 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -27,6 +27,18 @@ config DE2104X To compile this driver as a module, choose M here. The module will be called de2104x. +config DE2104X_DSL + int "Descriptor Skip Length in 32 bit longwords" + depends on DE2104X + range 0 31 + default 0 + help + Setting this value allows to align ring buffer descriptors into their + own cache lines. Value of 4 corresponds to the typical 32 byte line + (the descriptor is 16 bytes). This is necessary on systems that lack + cache coherence, an example is PowerMac 5500. Otherwise 0 is safe. + Default is 0, and range is 0 to 31. + config TULIP tristate "DECchip Tulip (dc2114x) PCI support" depends on PCI diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index d4c5ecc51f77..81f054dbb88d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -82,6 +82,13 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) +/* Descriptor skip length in 32 bit longwords. */ +#ifndef CONFIG_DE2104X_DSL +#define DSL 0 +#else +#define DSL CONFIG_DE2104X_DSL +#endif + #define DE_RX_RING_SIZE 64 #define DE_TX_RING_SIZE 64 #define DE_RING_BYTES \ @@ -153,6 +160,7 @@ enum { CmdReset = (1 << 0), CacheAlign16 = 0x00008000, BurstLen4 = 0x00000400, + DescSkipLen = (DSL << 2), /* Rx/TxPoll bits */ NormalTxPoll = (1 << 0), @@ -246,7 +254,7 @@ static const u32 de_intr_mask = * Set the programmable burst length to 4 longwords for all: * DMA errors result without these values. Cache align 16 long. */ -static const u32 de_bus_mode = CacheAlign16 | BurstLen4; +static const u32 de_bus_mode = CacheAlign16 | BurstLen4 | DescSkipLen; struct de_srom_media_block { u8 opts; @@ -266,6 +274,9 @@ struct de_desc { __le32 opts2; __le32 addr1; __le32 addr2; +#if DSL + __le32 skip[DSL]; +#endif }; struct media_info { @@ -601,7 +612,7 @@ static int de_start_xmit (struct sk_buff *skb, struct net_device *dev) if (tx_free == 0) { netif_stop_queue(dev); spin_unlock_irq(&de->lock); - return 1; + return NETDEV_TX_BUSY; } tx_free--; diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index f9491bd787d1..eb72d2e9ab3d 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1099,7 +1099,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) struct pci_dev *pdev = NULL; int i, status=0; - gendev->driver_data = dev; + dev_set_drvdata(gendev, dev); /* Ensure we're not sleeping */ if (lp->bus == EISA) { @@ -1461,12 +1461,12 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; - int status = 0; + int status = NETDEV_TX_OK; u_long flags = 0; netif_stop_queue(dev); if (!lp->tx_enable) { /* Cannot send for now */ - return -1; + return NETDEV_TX_LOCKED; } /* @@ -1480,7 +1480,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) /* Test if cache is already locked - requeue skb if so */ if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt) - return -1; + return NETDEV_TX_LOCKED; /* Transmit descriptor ring full or stale skb */ if (netif_queue_stopped(dev) || (u_long) lp->tx_skb[lp->tx_new] > 1) { @@ -2094,7 +2094,7 @@ static int __devexit de4x5_eisa_remove (struct device *device) struct net_device *dev; u_long iobase; - dev = device->driver_data; + dev = dev_get_drvdata(device); iobase = dev->base_addr; unregister_netdev (dev); @@ -2338,7 +2338,7 @@ static void __devexit de4x5_pci_remove (struct pci_dev *pdev) struct net_device *dev; u_long iobase; - dev = pdev->dev.driver_data; + dev = dev_get_drvdata(&pdev->dev); iobase = dev->base_addr; unregister_netdev (dev); diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index f2e669974c78..8e78f003f08f 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -686,7 +686,7 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev) spin_unlock_irqrestore(&db->lock, flags); printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_queue_cnt); - return 1; + return NETDEV_TX_BUSY; } /* Disable NIC interrupt */ diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 8761a5a5bd79..9277ce8febe4 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -591,7 +591,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev) if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) { spin_unlock_irqrestore(&db->lock, flags); printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt); - return 1; + return NETDEV_TX_BUSY; } /* Disable NIC interrupt */ diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 264e61404f34..842b1a2c40d4 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1601,8 +1601,7 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state) /* no more hardware accesses behind this line. */ - BUG_ON(np->csr6); - if (ioread32(ioaddr + IntrEnable)) BUG(); + BUG_ON(np->csr6 || ioread32(ioaddr + IntrEnable)); /* pci_power_off(pdev, -1); */ diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 735bf41c654a..811d3517fce0 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -540,31 +540,38 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, /* Get packet from user space buffer */ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, - struct iovec *iv, size_t count, + const struct iovec *iv, size_t count, int noblock) { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; size_t len = count, align = 0; struct virtio_net_hdr gso = { 0 }; + int offset = 0; if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) > count) return -EINVAL; - if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) + if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) return -EFAULT; + offset += sizeof(pi); } if (tun->flags & TUN_VNET_HDR) { if ((len -= sizeof(gso)) > count) return -EINVAL; - if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso))) + if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) return -EFAULT; + if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + gso.csum_start + gso.csum_offset + 2 > gso.hdr_len) + gso.hdr_len = gso.csum_start + gso.csum_offset + 2; + if (gso.hdr_len > len) return -EINVAL; + offset += sizeof(gso); } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { @@ -581,7 +588,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, return PTR_ERR(skb); } - if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) { + if (skb_copy_datagram_from_iovec(skb, 0, iv, offset, len)) { tun->dev->stats.rx_dropped++; kfree_skb(skb); return -EFAULT; @@ -673,7 +680,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); - result = tun_get_user(tun, (struct iovec *)iv, iov_length(iv, count), + result = tun_get_user(tun, iv, iov_length(iv, count), file->f_flags & O_NONBLOCK); tun_put(tun); @@ -683,7 +690,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, /* Put packet to the user space buffer */ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, struct sk_buff *skb, - struct iovec *iv, int len) + const struct iovec *iv, int len) { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; @@ -697,7 +704,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, pi.flags |= TUN_PKT_STRIP; } - if (memcpy_toiovec(iv, (void *) &pi, sizeof(pi))) + if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi))) return -EFAULT; total += sizeof(pi); } @@ -730,14 +737,15 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, gso.csum_offset = skb->csum_offset; } /* else everything is zero */ - if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso)))) + if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, + sizeof(gso)))) return -EFAULT; total += sizeof(gso); } len = min_t(int, skb->len, len); - skb_copy_datagram_iovec(skb, 0, iv, len); + skb_copy_datagram_const_iovec(skb, 0, iv, total, len); total += len; tun->dev->stats.tx_packets++; @@ -792,7 +800,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, } netif_wake_queue(tun->dev); - ret = tun_put_user(tun, skb, (struct iovec *) iv, len); + ret = tun_put_user(tun, skb, iv, len); kfree_skb(skb); break; } @@ -840,12 +848,12 @@ static void tun_sock_write_space(struct sock *sk) if (!sock_writeable(sk)) return; - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible_sync(sk->sk_sleep); - if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) return; + if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + wake_up_interruptible_sync(sk->sk_sleep); + tun = container_of(sk, struct tun_sock, sk)->tun; kill_fasync(&tun->fasync, SIGIO, POLL_OUT); } @@ -861,6 +869,52 @@ static struct proto tun_proto = { .obj_size = sizeof(struct tun_sock), }; +static int tun_flags(struct tun_struct *tun) +{ + int flags = 0; + + if (tun->flags & TUN_TUN_DEV) + flags |= IFF_TUN; + else + flags |= IFF_TAP; + + if (tun->flags & TUN_NO_PI) + flags |= IFF_NO_PI; + + if (tun->flags & TUN_ONE_QUEUE) + flags |= IFF_ONE_QUEUE; + + if (tun->flags & TUN_VNET_HDR) + flags |= IFF_VNET_HDR; + + return flags; +} + +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "0x%x\n", tun_flags(tun)); +} + +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "%d\n", tun->owner); +} + +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "%d\n", tun->group); +} + +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); + static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) { struct sock *sk; @@ -870,6 +924,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) dev = __dev_get_by_name(net, ifr->ifr_name); if (dev) { + if (ifr->ifr_flags & IFF_TUN_EXCL) + return -EBUSY; if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) tun = netdev_priv(dev); else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) @@ -944,6 +1000,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (err < 0) goto err_free_sk; + if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || + device_create_file(&tun->dev->dev, &dev_attr_owner) || + device_create_file(&tun->dev->dev, &dev_attr_group)) + printk(KERN_ERR "Failed to create tun sysfs files\n"); + sk->sk_destruct = tun_sock_destruct; err = tun_attach(tun, file); @@ -996,21 +1057,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) strcpy(ifr->ifr_name, tun->dev->name); - ifr->ifr_flags = 0; - - if (ifr->ifr_flags & TUN_TUN_DEV) - ifr->ifr_flags |= IFF_TUN; - else - ifr->ifr_flags |= IFF_TAP; - - if (tun->flags & TUN_NO_PI) - ifr->ifr_flags |= IFF_NO_PI; - - if (tun->flags & TUN_ONE_QUEUE) - ifr->ifr_flags |= IFF_ONE_QUEUE; - - if (tun->flags & TUN_VNET_HDR) - ifr->ifr_flags |= IFF_VNET_HDR; + ifr->ifr_flags = tun_flags(tun); tun_put(tun); return 0; @@ -1275,21 +1322,22 @@ static int tun_chr_open(struct inode *inode, struct file * file) static int tun_chr_close(struct inode *inode, struct file *file) { struct tun_file *tfile = file->private_data; - struct tun_struct *tun = __tun_get(tfile); + struct tun_struct *tun; + rtnl_lock(); + tun = __tun_get(tfile); if (tun) { DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); - rtnl_lock(); __tun_detach(tun); /* If desireable, unregister the netdevice. */ if (!(tun->flags & TUN_PERSIST)) unregister_netdevice(tun->dev); - rtnl_unlock(); } + rtnl_unlock(); tun = tfile->tun; if (tun) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 9dd16c9b1a10..e2f2e91cfdd2 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved. + * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved. * * Author: Shlomi Gridish * Li Yang @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,8 @@ static DEFINE_SPINLOCK(ugeth_lock); +static void uec_configure_serdes(struct net_device *dev); + static struct { u32 msg_enable; } debug = { -1 }; @@ -1409,6 +1412,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UCC_GETH_UPSMR_TBIM; } + if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)) + upsmr |= UCC_GETH_UPSMR_SGMM; + out_be32(&uf_regs->upsmr, upsmr); /* Disable autonegotiation in tbi mode, because by default it @@ -1543,14 +1549,19 @@ static int init_phy(struct net_device *dev) priv->oldspeed = 0; priv->oldduplex = -1; - phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0, - priv->phy_interface); + if (!ug_info->phy_node) + return 0; - if (IS_ERR(phydev)) { + phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0, + priv->phy_interface); + if (!phydev) { printk("%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); + return -ENODEV; } + if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII) + uec_configure_serdes(dev); + phydev->supported &= (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | @@ -1566,7 +1577,41 @@ static int init_phy(struct net_device *dev) return 0; } +/* Initialize TBI PHY interface for communicating with the + * SERDES lynx PHY on the chip. We communicate with this PHY + * through the MDIO bus on each controller, treating it as a + * "normal" PHY at the address found in the UTBIPA register. We assume + * that the UTBIPA register is valid. Either the MDIO bus code will set + * it to a value that doesn't conflict with other PHYs on the bus, or the + * value doesn't matter, as there are no other PHYs on the bus. + */ +static void uec_configure_serdes(struct net_device *dev) +{ + struct ucc_geth_private *ugeth = netdev_priv(dev); + if (!ugeth->tbiphy) { + printk(KERN_WARNING "SGMII mode requires that the device " + "tree specify a tbi-handle\n"); + return; + } + + /* + * If the link is already up, we must already be ok, and don't need to + * configure and reset the TBI<->SerDes link. Maybe U-Boot configured + * everything for us? Resetting it takes the link down and requires + * several seconds for it to come back. + */ + if (phy_read(ugeth->tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) + return; + + /* Single clk mode, mii mode off(for serdes communication) */ + phy_write(ugeth->tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS); + + phy_write(ugeth->tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT); + + phy_write(ugeth->tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS); + +} static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) { @@ -3225,7 +3270,7 @@ 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_irq(ugeth-> + dev_kfree_skb(ugeth-> tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]); ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; ugeth->skb_dirtytx[txQ] = @@ -3259,9 +3304,15 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget) 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); + if (howmany < budget) { napi_complete(napi); - setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS); + setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS); } return howmany; @@ -3275,8 +3326,6 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) struct ucc_geth_info *ug_info; register u32 ucce; register u32 uccm; - register u32 tx_mask; - u8 i; ugeth_vdbg("%s: IN", __func__); @@ -3290,27 +3339,14 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) out_be32(uccf->p_ucce, ucce); /* check for receive events that require processing */ - if (ucce & UCCE_RX_EVENTS) { + if (ucce & (UCCE_RX_EVENTS | UCCE_TX_EVENTS)) { if (napi_schedule_prep(&ugeth->napi)) { - uccm &= ~UCCE_RX_EVENTS; + uccm &= ~(UCCE_RX_EVENTS | UCCE_TX_EVENTS); out_be32(uccf->p_uccm, uccm); __napi_schedule(&ugeth->napi); } } - /* Tx event processing */ - if (ucce & UCCE_TX_EVENTS) { - spin_lock(&ugeth->lock); - tx_mask = UCC_GETH_UCCE_TXB0; - for (i = 0; i < ug_info->numQueuesTx; i++) { - if (ucce & tx_mask) - ucc_geth_tx(dev, i); - ucce &= ~tx_mask; - tx_mask <<= 1; - } - spin_unlock(&ugeth->lock); - } - /* Errors and other events */ if (ucce & UCCE_OTHER) { if (ucce & UCC_GETH_UCCE_BSY) @@ -3339,6 +3375,37 @@ static void ucc_netpoll(struct net_device *dev) } #endif /* CONFIG_NET_POLL_CONTROLLER */ +static int ucc_geth_set_mac_addr(struct net_device *dev, void *p) +{ + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + /* + * If device is not running, we will set mac addr register + * when opening the device. + */ + if (!netif_running(dev)) + return 0; + + spin_lock_irq(&ugeth->lock); + init_mac_station_addr_regs(dev->dev_addr[0], + dev->dev_addr[1], + dev->dev_addr[2], + dev->dev_addr[3], + dev->dev_addr[4], + dev->dev_addr[5], + &ugeth->ug_regs->macstnaddr1, + &ugeth->ug_regs->macstnaddr2); + spin_unlock_irq(&ugeth->lock); + + return 0; +} + /* Called when something needs to use the ethernet device */ /* Returns 0 for success. */ static int ucc_geth_open(struct net_device *dev) @@ -3506,6 +3573,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_RGMII_RXID; if (strcasecmp(phy_connection_type, "rtbi") == 0) return PHY_INTERFACE_MODE_RTBI; + if (strcasecmp(phy_connection_type, "sgmii") == 0) + return PHY_INTERFACE_MODE_SGMII; return PHY_INTERFACE_MODE_MII; } @@ -3515,7 +3584,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = { .ndo_stop = ucc_geth_close, .ndo_start_xmit = ucc_geth_start_xmit, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = ucc_geth_set_mac_addr, .ndo_change_mtu = eth_change_mtu, .ndo_set_multicast_list = ucc_geth_set_multi, .ndo_tx_timeout = ucc_geth_timeout, @@ -3528,14 +3597,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma { struct device *device = &ofdev->dev; struct device_node *np = ofdev->node; - struct device_node *mdio; struct net_device *dev = NULL; struct ucc_geth_private *ugeth = NULL; struct ucc_geth_info *ug_info; struct resource res; struct device_node *phy; int err, ucc_num, max_speed = 0; - const phandle *ph; const u32 *fixed_link; const unsigned int *prop; const char *sprop; @@ -3552,6 +3619,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, + PHY_INTERFACE_MODE_SGMII, }; ugeth_vdbg("%s: IN", __func__); @@ -3635,40 +3703,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); fixed_link = of_get_property(np, "fixed-link", NULL); if (fixed_link) { - snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), - PHY_ID_FMT, "0", fixed_link[0]); phy = NULL; } else { - char bus_name[MII_BUS_ID_SIZE]; - - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); - + phy = of_parse_phandle(np, "phy-handle", 0); if (phy == NULL) return -ENODEV; - - /* set the PHY address */ - prop = of_get_property(phy, "reg", NULL); - if (prop == NULL) - return -1; - - /* Set the bus id */ - mdio = of_get_parent(phy); - - if (mdio == NULL) - return -ENODEV; - - err = of_address_to_resource(mdio, 0, &res); - - if (err) { - of_node_put(mdio); - return err; - } - fsl_pq_mdio_bus_name(bus_name, mdio); - of_node_put(mdio); - snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), - "%s:%02x", bus_name, *prop); } + ug_info->phy_node = phy; /* get the phy interface type, or default to MII */ prop = of_get_property(np, "phy-connection-type", NULL); @@ -3694,6 +3735,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_TBI: case PHY_INTERFACE_MODE_RTBI: + case PHY_INTERFACE_MODE_SGMII: max_speed = SPEED_1000; break; default: @@ -3751,7 +3793,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma dev->netdev_ops = &ucc_geth_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); - netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT); + netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64); dev->mtu = 1500; ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); @@ -3776,6 +3818,37 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ugeth->ndev = dev; ugeth->node = np; + /* Find the TBI PHY. If it's not there, we don't support SGMII */ + ph = of_get_property(np, "tbi-handle", NULL); + if (ph) { + struct device_node *tbi = of_find_node_by_phandle(*ph); + struct of_device *ofdev; + struct mii_bus *bus; + const unsigned int *id; + + if (!tbi) + return 0; + + mdio = of_get_parent(tbi); + if (!mdio) + return 0; + + ofdev = of_find_device_by_node(mdio); + + of_node_put(mdio); + + id = of_get_property(tbi, "reg", NULL); + if (!id) + return 0; + of_node_put(tbi); + + bus = dev_get_drvdata(&ofdev->dev); + if (!bus) + return 0; + + ugeth->tbiphy = bus->phy_map[*id]; + } + return 0; } diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 46bb1d233597..5beba4c14532 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -1,5 +1,5 @@ /* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. + * Copyright (C) Freescale Semicondutor, Inc. 2006-2009. All rights reserved. * * Author: Shlomi Gridish * @@ -193,6 +193,31 @@ struct ucc_geth { #define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */ #define ENET_TBI_MII_TBICON 0x11 /* TBI control */ +/* TBI MDIO register bit fields*/ +#define TBISR_LSTATUS 0x0004 +#define TBICON_CLK_SELECT 0x0020 +#define TBIANA_ASYMMETRIC_PAUSE 0x0100 +#define TBIANA_SYMMETRIC_PAUSE 0x0080 +#define TBIANA_HALF_DUPLEX 0x0040 +#define TBIANA_FULL_DUPLEX 0x0020 +#define TBICR_PHY_RESET 0x8000 +#define TBICR_ANEG_ENABLE 0x1000 +#define TBICR_RESTART_ANEG 0x0200 +#define TBICR_FULL_DUPLEX 0x0100 +#define TBICR_SPEED1_SET 0x0040 + +#define TBIANA_SETTINGS ( \ + TBIANA_ASYMMETRIC_PAUSE \ + | TBIANA_SYMMETRIC_PAUSE \ + | TBIANA_FULL_DUPLEX \ + ) +#define TBICR_SETTINGS ( \ + TBICR_PHY_RESET \ + | TBICR_ANEG_ENABLE \ + | TBICR_FULL_DUPLEX \ + | TBICR_SPEED1_SET \ + ) + /* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ #define MACCFG1_FLOW_RX 0x00000020 /* Flow Control Rx */ @@ -852,7 +877,6 @@ struct ucc_geth_hardware_statistics { /* Driver definitions */ #define TX_BD_RING_LEN 0x10 #define RX_BD_RING_LEN 0x10 -#define UCC_GETH_DEV_WEIGHT TX_BD_RING_LEN #define TX_RING_MOD_MASK(size) (size-1) #define RX_RING_MOD_MASK(size) (size-1) @@ -1100,7 +1124,7 @@ struct ucc_geth_info { u32 eventRegMask; u16 pausePeriod; u16 extensionField; - char phy_bus_id[BUS_ID_SIZE]; + struct device_node *phy_node; u8 weightfactor[NUM_TX_QUEUES]; u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; @@ -1189,6 +1213,7 @@ struct ucc_geth_private { struct ugeth_mii_info *mii_info; struct phy_device *phydev; + struct phy_device *tbiphy; phy_interface_t phy_interface; int max_speed; uint32_t msg_enable; diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index dfc6cf765fbd..3717569828bf 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -359,4 +359,12 @@ config USB_HSO To compile this driver as a module, choose M here: the module will be called hso. +config USB_NET_INT51X1 + tristate "Intellon PLC based usb adapter" + depends on USB_USBNET + help + Choose this option if you're using a 14Mb USB-based PLC + (Powerline Communications) solution with an Intellon + INT51x1/INT5200 chip, like the "devolo dLan duo". + endmenu diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index c8aef62cf2b7..b870b0b1cbe0 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o +obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 55e8ecc3a9e5..01fd528306ec 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -389,36 +388,6 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) } } -static u8 nibble(unsigned char c) -{ - if (likely(isdigit(c))) - return c - '0'; - c = toupper(c); - if (likely(isxdigit(c))) - return 10 + c - 'A'; - return 0; -} - -static inline int -get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e) -{ - int tmp, i; - unsigned char buf [13]; - - tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf); - if (tmp != 12) { - dev_dbg(&dev->udev->dev, - "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp); - if (tmp >= 0) - tmp = -EINVAL; - return tmp; - } - for (i = tmp = 0; i < 6; i++, tmp += 2) - dev->net->dev_addr [i] = - (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); - return 0; -} - static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) { int status; @@ -428,7 +397,7 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) if (status < 0) return status; - status = get_ethernet_addr(dev, info->ether); + status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress); if (status < 0) { usb_set_intfdata(info->data, NULL); usb_driver_release_interface(driver_of(intf), info->data); diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 6fc4f82b0beb..7ae82446b93a 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -497,10 +497,10 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) int len; /* format: - b0: rx status - b1: packet length (incl crc) low - b2: packet length (incl crc) high - b3..n-4: packet data + b1: rx status + b2: packet length (incl crc) low + b3: packet length (incl crc) high + b4..n-4: packet data bn-3..bn: ethernet crc */ @@ -533,8 +533,8 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, int len; /* format: - b0: packet length low - b1: packet length high + b1: packet length low + b2: packet length high b3..n: packet data */ diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index f84b78d94c40..f8c6d7ea7264 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -482,7 +482,7 @@ static ssize_t hso_sysfs_show_porttype(struct device *dev, struct device_attribute *attr, char *buf) { - struct hso_device *hso_dev = dev->driver_data; + struct hso_device *hso_dev = dev_get_drvdata(dev); char *port_name; if (!hso_dev) @@ -816,7 +816,7 @@ static int hso_net_start_xmit(struct sk_buff *skb, struct net_device *net) } dev_kfree_skb(skb); /* we're done */ - return result; + return NETDEV_TX_OK; } static void hso_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) @@ -899,15 +899,14 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, continue; } /* Allocate an sk_buff */ - odev->skb_rx_buf = dev_alloc_skb(frame_len); + odev->skb_rx_buf = netdev_alloc_skb(odev->net, + frame_len); if (!odev->skb_rx_buf) { /* We got no receive buffer. */ D1("could not allocate memory"); odev->rx_parse_state = WAIT_SYNC; return; } - /* Here's where it came from */ - odev->skb_rx_buf->dev = odev->net; /* Copy what we got so far. make room for iphdr * after tail. */ @@ -2313,7 +2312,7 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, serial->parent->dev = tty_register_device(tty_drv, minor, &serial->parent->interface->dev); dev = serial->parent->dev; - dev->driver_data = serial->parent; + dev_set_drvdata(dev, serial->parent); i = device_create_file(dev, &dev_attr_hsotype); /* fill in specific data for later use */ @@ -2481,10 +2480,10 @@ static int add_net_device(struct hso_device *hso_dev) return 0; } -static int hso_radio_toggle(void *data, enum rfkill_state state) +static int hso_rfkill_set_block(void *data, bool blocked) { struct hso_device *hso_dev = data; - int enabled = (state == RFKILL_STATE_ON); + int enabled = !blocked; int rv; mutex_lock(&hso_dev->mutex); @@ -2498,6 +2497,10 @@ static int hso_radio_toggle(void *data, enum rfkill_state state) return rv; } +static const struct rfkill_ops hso_rfkill_ops = { + .set_block = hso_rfkill_set_block, +}; + /* Creates and sets up everything for rfkill */ static void hso_create_rfkill(struct hso_device *hso_dev, struct usb_interface *interface) @@ -2506,29 +2509,25 @@ static void hso_create_rfkill(struct hso_device *hso_dev, struct device *dev = &hso_net->net->dev; char *rfkn; - hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, - RFKILL_TYPE_WWAN); - if (!hso_net->rfkill) { - dev_err(dev, "%s - Out of memory\n", __func__); - return; - } rfkn = kzalloc(20, GFP_KERNEL); - if (!rfkn) { - rfkill_free(hso_net->rfkill); - hso_net->rfkill = NULL; + if (!rfkn) dev_err(dev, "%s - Out of memory\n", __func__); - return; - } + snprintf(rfkn, 20, "hso-%d", interface->altsetting->desc.bInterfaceNumber); - hso_net->rfkill->name = rfkn; - hso_net->rfkill->state = RFKILL_STATE_ON; - hso_net->rfkill->data = hso_dev; - hso_net->rfkill->toggle_radio = hso_radio_toggle; - if (rfkill_register(hso_net->rfkill) < 0) { + + hso_net->rfkill = rfkill_alloc(rfkn, + &interface_to_usbdev(interface)->dev, + RFKILL_TYPE_WWAN, + &hso_rfkill_ops, hso_dev); + if (!hso_net->rfkill) { + dev_err(dev, "%s - Out of memory\n", __func__); + kfree(rfkn); + return; + } + if (rfkill_register(hso_net->rfkill) < 0) { + rfkill_destroy(hso_net->rfkill); kfree(rfkn); - hso_net->rfkill->name = NULL; - rfkill_free(hso_net->rfkill); hso_net->rfkill = NULL; dev_err(dev, "%s - Failed to register rfkill\n", __func__); return; @@ -3165,8 +3164,10 @@ static void hso_free_interface(struct usb_interface *interface) hso_stop_net_device(network_table[i]); cancel_work_sync(&network_table[i]->async_put_intf); cancel_work_sync(&network_table[i]->async_get_intf); - if (rfk) + if (rfk) { rfkill_unregister(rfk); + rfkill_destroy(rfk); + } hso_free_net_device(network_table[i]); } } diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c new file mode 100644 index 000000000000..55cf7081de10 --- /dev/null +++ b/drivers/net/usb/int51x1.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2009 Peter Holik + * + * Intellon usb PLC (Powerline Communications) usb net driver + * + * http://www.tandel.be/downloads/INT51X1_Datasheet.pdf + * + * Based on the work of Jan 'RedBully' Seiffert + */ + +/* + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define INT51X1_VENDOR_ID 0x09e1 +#define INT51X1_PRODUCT_ID 0x5121 + +#define INT51X1_HEADER_SIZE 2 /* 2 byte header */ + +#define PACKET_TYPE_PROMISCUOUS (1 << 0) +#define PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ +#define PACKET_TYPE_DIRECTED (1 << 2) +#define PACKET_TYPE_BROADCAST (1 << 3) +#define PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ + +#define SET_ETHERNET_PACKET_FILTER 0x43 + +static int int51x1_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + int len; + + if (!(pskb_may_pull(skb, INT51X1_HEADER_SIZE))) { + deverr(dev, "unexpected tiny rx frame"); + return 0; + } + + len = le16_to_cpu(*(__le16 *)&skb->data[skb->len - 2]); + + skb_trim(skb, len); + + return 1; +} + +static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev, + struct sk_buff *skb, gfp_t flags) +{ + int pack_len = skb->len; + int pack_with_header_len = pack_len + INT51X1_HEADER_SIZE; + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + int need_tail = 0; + __le16 *len; + + /* if packet and our header is smaler than 64 pad to 64 (+ ZLP) */ + if ((pack_with_header_len) < dev->maxpacket) + need_tail = dev->maxpacket - pack_with_header_len + 1; + /* + * usbnet would send a ZLP if packetlength mod urbsize == 0 for us, + * but we need to know ourself, because this would add to the length + * we send down to the device... + */ + else if (!(pack_with_header_len % dev->maxpacket)) + need_tail = 1; + + if (!skb_cloned(skb) && + (headroom + tailroom >= need_tail + INT51X1_HEADER_SIZE)) { + if (headroom < INT51X1_HEADER_SIZE || tailroom < need_tail) { + skb->data = memmove(skb->head + INT51X1_HEADER_SIZE, + skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + } + } else { + struct sk_buff *skb2; + + skb2 = skb_copy_expand(skb, + INT51X1_HEADER_SIZE, + need_tail, + flags); + dev_kfree_skb_any(skb); + if (!skb2) + return NULL; + skb = skb2; + } + + pack_len += need_tail; + pack_len &= 0x07ff; + + len = (__le16 *) __skb_push(skb, INT51X1_HEADER_SIZE); + *len = cpu_to_le16(pack_len); + + if(need_tail) + memset(__skb_put(skb, need_tail), 0, need_tail); + + return skb; +} + +static void int51x1_async_cmd_callback(struct urb *urb) +{ + struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; + int status = urb->status; + + if (status < 0) + dev_warn(&urb->dev->dev, "async callback failed with %d\n", status); + + kfree(req); + usb_free_urb(urb); +} + +static void int51x1_set_multicast(struct net_device *netdev) +{ + struct usb_ctrlrequest *req; + int status; + struct urb *urb; + struct usbnet *dev = netdev_priv(netdev); + u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST; + + if (netdev->flags & IFF_PROMISC) { + /* do not expect to see traffic of other PLCs */ + filter |= PACKET_TYPE_PROMISCUOUS; + devinfo(dev, "promiscuous mode enabled"); + } else if (netdev->mc_count || + (netdev->flags & IFF_ALLMULTI)) { + filter |= PACKET_TYPE_ALL_MULTICAST; + devdbg(dev, "receive all multicast enabled"); + } else { + /* ~PROMISCUOUS, ~MULTICAST */ + devdbg(dev, "receive own packets only"); + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + devwarn(dev, "Error allocating URB"); + return; + } + + req = kmalloc(sizeof(*req), GFP_ATOMIC); + if (!req) { + devwarn(dev, "Error allocating control msg"); + goto out; + } + + req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + req->bRequest = SET_ETHERNET_PACKET_FILTER; + req->wValue = cpu_to_le16(filter); + req->wIndex = 0; + req->wLength = 0; + + usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), + (void *)req, NULL, 0, + int51x1_async_cmd_callback, + (void *)req); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + devwarn(dev, "Error submitting control msg, sts=%d", status); + goto out1; + } + return; +out1: + kfree(req); +out: + usb_free_urb(urb); +} + +static const struct net_device_ops int51x1_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = int51x1_set_multicast, +}; + +static int int51x1_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status = usbnet_get_ethernet_addr(dev, 3); + + if (status) + return status; + + dev->net->hard_header_len += INT51X1_HEADER_SIZE; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + dev->net->netdev_ops = &int51x1_netdev_ops; + + return usbnet_get_endpoints(dev, intf); +} + +static const struct driver_info int51x1_info = { + .description = "Intellon usb powerline adapter", + .bind = int51x1_bind, + .rx_fixup = int51x1_rx_fixup, + .tx_fixup = int51x1_tx_fixup, + .in = 1, + .out = 2, + .flags = FLAG_ETHER, +}; + +static const struct usb_device_id products[] = { + { + USB_DEVICE(INT51X1_VENDOR_ID, INT51X1_PRODUCT_ID), + .driver_info = (unsigned long) &int51x1_info, + }, + {}, +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver int51x1_driver = { + .name = "int51x1", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + +static int __init int51x1_init(void) +{ + return usb_register(&int51x1_driver); +} +module_init(int51x1_init); + +static void __exit int51x1_exit(void) +{ + usb_deregister(&int51x1_driver); +} +module_exit(int51x1_exit); + +MODULE_AUTHOR("Peter Holik"); +MODULE_DESCRIPTION("Intellon usb powerline adapter"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 3d0d0b0b37c5..e01314789718 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -31,7 +31,6 @@ ****************************************************************/ /* TODO: - * Fix in_interrupt() problem * Develop test procedures for USB net interfaces * Run test procedures * Fix bugs from previous two steps @@ -606,14 +605,30 @@ static void kaweth_usb_receive(struct urb *urb) struct sk_buff *skb; - if(unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) - /* we are killed - set a flag and wake the disconnect handler */ - { + if (unlikely(status == -EPIPE)) { + kaweth->stats.rx_errors++; kaweth->end = 1; wake_up(&kaweth->term_wait); + dbg("Status was -EPIPE."); return; } - + if (unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) { + /* we are killed - set a flag and wake the disconnect handler */ + kaweth->end = 1; + wake_up(&kaweth->term_wait); + dbg("Status was -ECONNRESET or -ESHUTDOWN."); + return; + } + if (unlikely(status == -EPROTO || status == -ETIME || + status == -EILSEQ)) { + kaweth->stats.rx_errors++; + dbg("Status was -EPROTO, -ETIME, or -EILSEQ."); + return; + } + if (unlikely(status == -EOVERFLOW)) { + kaweth->stats.rx_errors++; + dbg("Status was -EOVERFLOW."); + } spin_lock(&kaweth->device_lock); if (IS_BLOCKED(kaweth->status)) { spin_unlock(&kaweth->device_lock); @@ -883,13 +898,16 @@ static void kaweth_set_rx_mode(struct net_device *net) ****************************************************************/ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) { + int result; __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap; + kaweth->packet_filter_bitmap = 0; if (packet_filter_bitmap == 0) return; - { - int result; + if (in_interrupt()) + return; + result = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_PACKET_FILTER, @@ -906,7 +924,6 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) else { dbg("Set Rx mode to %d", packet_filter_bitmap); } - } } /**************************************************************** diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index f9fb454ffa8b..fcc6fa0905d1 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -221,7 +221,8 @@ static void ctrl_callback(struct urb *urb) case -ENOENT: break; default: - dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status); + if (printk_ratelimit()) + dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status); } dev = urb->context; clear_bit(RX_REG_SET, &dev->flags); @@ -442,10 +443,12 @@ static void read_bulk_callback(struct urb *urb) case -ENOENT: return; /* the urb is in unlink state */ case -ETIME: - dev_warn(&urb->dev->dev, "may be reset is needed?..\n"); + if (printk_ratelimit()) + dev_warn(&urb->dev->dev, "may be reset is needed?..\n"); goto goon; default: - dev_warn(&urb->dev->dev, "Rx status %d\n", status); + if (printk_ratelimit()) + dev_warn(&urb->dev->dev, "Rx status %d\n", status); goto goon; } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 5a7283372b53..89a91f8c22de 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1134,7 +1134,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (skb->len == size) { if (pdata->use_rx_csum) smsc95xx_rx_csum_offload(skb); - + skb_trim(skb, skb->len - 4); /* remove fcs */ skb->truesize = size + sizeof(struct sk_buff); return 1; @@ -1152,7 +1152,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (pdata->use_rx_csum) smsc95xx_rx_csum_offload(ax_skb); - + skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ ax_skb->truesize = size + sizeof(struct sk_buff); usbnet_skb_return(dev, ax_skb); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 47f68cfa7e21..22c0585a0319 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,36 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_get_endpoints); +static u8 nibble(unsigned char c) +{ + if (likely(isdigit(c))) + return c - '0'; + c = toupper(c); + if (likely(isxdigit(c))) + return 10 + c - 'A'; + return 0; +} + +int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress) +{ + int tmp, i; + unsigned char buf [13]; + + tmp = usb_string(dev->udev, iMACAddress, buf, sizeof buf); + if (tmp != 12) { + dev_dbg(&dev->udev->dev, + "bad MAC string %d fetch, %d\n", iMACAddress, tmp); + if (tmp >= 0) + tmp = -EINVAL; + return tmp; + } + for (i = tmp = 0; i < 6; i++, tmp += 2) + dev->net->dev_addr [i] = + (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); + return 0; +} +EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr); + static void intr_complete (struct urb *urb); static int init_status (struct usbnet *dev, struct usb_interface *intf) @@ -1185,12 +1216,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) #endif net->netdev_ops = &usbnet_netdev_ops; -#ifdef CONFIG_COMPAT_NET_DEV_OPS - net->hard_start_xmit = usbnet_start_xmit; - net->open = usbnet_open; - net->stop = usbnet_stop; - net->tx_timeout = usbnet_tx_timeout; -#endif net->watchdog_timeo = TX_TIMEOUT_JIFFIES; net->ethtool_ops = &usbnet_ethtool_ops; diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 8e56fcf0a0e3..87197dd9c788 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -176,8 +176,6 @@ static int veth_xmit(struct sk_buff *skb, struct net_device *dev) if (dev->features & NETIF_F_NO_CSUM) skb->ip_summed = rcv_priv->ip_summed; - dst_release(skb->dst); - skb->dst = NULL; skb->mark = 0; secpath_reset(skb); nf_reset(skb); diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 45daba726b66..d3489a3c4c03 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -388,7 +388,6 @@ struct rhine_private { long pioaddr; struct net_device *dev; struct napi_struct napi; - struct net_device_stats stats; spinlock_t lock; /* Frequently used values: keep some adjacent for cache effect. */ @@ -1209,7 +1208,7 @@ static void rhine_tx_timeout(struct net_device *dev) enable_irq(rp->pdev->irq); dev->trans_start = jiffies; - rp->stats.tx_errors++; + dev->stats.tx_errors++; netif_wake_queue(dev); } @@ -1237,7 +1236,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) /* packet too long, drop it */ dev_kfree_skb(skb); rp->tx_skbuff[entry] = NULL; - rp->stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; } @@ -1378,29 +1377,33 @@ static void rhine_tx(struct net_device *dev) printk(KERN_DEBUG "%s: Transmit error, " "Tx status %8.8x.\n", dev->name, txstatus); - rp->stats.tx_errors++; - if (txstatus & 0x0400) rp->stats.tx_carrier_errors++; - if (txstatus & 0x0200) rp->stats.tx_window_errors++; - if (txstatus & 0x0100) rp->stats.tx_aborted_errors++; - if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++; + dev->stats.tx_errors++; + if (txstatus & 0x0400) + dev->stats.tx_carrier_errors++; + if (txstatus & 0x0200) + dev->stats.tx_window_errors++; + if (txstatus & 0x0100) + dev->stats.tx_aborted_errors++; + if (txstatus & 0x0080) + dev->stats.tx_heartbeat_errors++; if (((rp->quirks & rqRhineI) && txstatus & 0x0002) || (txstatus & 0x0800) || (txstatus & 0x1000)) { - rp->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); break; /* Keep the skb - we try again */ } /* Transmitter restarted in 'abnormal' handler. */ } else { if (rp->quirks & rqRhineI) - rp->stats.collisions += (txstatus >> 3) & 0x0F; + dev->stats.collisions += (txstatus >> 3) & 0x0F; else - rp->stats.collisions += txstatus & 0x0F; + dev->stats.collisions += txstatus & 0x0F; if (debug > 6) printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n", (txstatus >> 3) & 0xF, txstatus & 0xF); - rp->stats.tx_bytes += rp->tx_skbuff[entry]->len; - rp->stats.tx_packets++; + dev->stats.tx_bytes += rp->tx_skbuff[entry]->len; + dev->stats.tx_packets++; } /* Free the original skb. */ if (rp->tx_skbuff_dma[entry]) { @@ -1455,21 +1458,24 @@ static int rhine_rx(struct net_device *dev, int limit) printk(KERN_WARNING "%s: Oversized Ethernet " "frame %p vs %p.\n", dev->name, rp->rx_head_desc, &rp->rx_ring[entry]); - rp->stats.rx_length_errors++; + dev->stats.rx_length_errors++; } else if (desc_status & RxErr) { /* There was a error. */ if (debug > 2) printk(KERN_DEBUG "rhine_rx() Rx " "error was %8.8x.\n", desc_status); - rp->stats.rx_errors++; - if (desc_status & 0x0030) rp->stats.rx_length_errors++; - if (desc_status & 0x0048) rp->stats.rx_fifo_errors++; - if (desc_status & 0x0004) rp->stats.rx_frame_errors++; + dev->stats.rx_errors++; + if (desc_status & 0x0030) + dev->stats.rx_length_errors++; + if (desc_status & 0x0048) + dev->stats.rx_fifo_errors++; + if (desc_status & 0x0004) + dev->stats.rx_frame_errors++; if (desc_status & 0x0002) { /* this can also be updated outside the interrupt handler */ spin_lock(&rp->lock); - rp->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; spin_unlock(&rp->lock); } } @@ -1513,8 +1519,8 @@ static int rhine_rx(struct net_device *dev, int limit) } skb->protocol = eth_type_trans(skb, dev); netif_receive_skb(skb); - rp->stats.rx_bytes += pkt_len; - rp->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + dev->stats.rx_packets++; } entry = (++rp->cur_rx) % RX_RING_SIZE; rp->rx_head_desc = &rp->rx_ring[entry]; @@ -1599,8 +1605,8 @@ static void rhine_error(struct net_device *dev, int intr_status) if (intr_status & IntrLinkChange) rhine_check_media(dev, 0); if (intr_status & IntrStatsMax) { - rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); - rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); + dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); + dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); clear_tally_counters(ioaddr); } if (intr_status & IntrTxAborted) { @@ -1654,12 +1660,12 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev) unsigned long flags; spin_lock_irqsave(&rp->lock, flags); - rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); - rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); + dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); + dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); clear_tally_counters(ioaddr); spin_unlock_irqrestore(&rp->lock, flags); - return &rp->stats; + return &dev->stats; } static void rhine_set_rx_mode(struct net_device *dev) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 754a4b182c1d..e2a7725e567e 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1385,7 +1385,7 @@ static void velocity_free_td_ring(struct velocity_info *vptr) static int velocity_rx_srv(struct velocity_info *vptr, int status) { - struct net_device_stats *stats = &vptr->stats; + struct net_device_stats *stats = &vptr->dev->stats; int rd_curr = vptr->rx.curr; int works = 0; @@ -1519,7 +1519,7 @@ static inline void velocity_iph_realign(struct velocity_info *vptr, static int velocity_receive_frame(struct velocity_info *vptr, int idx) { void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int); - struct net_device_stats *stats = &vptr->stats; + struct net_device_stats *stats = &vptr->dev->stats; struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]); struct rx_desc *rd = &(vptr->rx.ring[idx]); int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff; @@ -1532,7 +1532,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) } if (rd->rdesc0.RSR & RSR_MAR) - vptr->stats.multicast++; + stats->multicast++; skb = rd_info->skb; @@ -1634,7 +1634,7 @@ static int velocity_tx_srv(struct velocity_info *vptr, u32 status) int idx; int works = 0; struct velocity_td_info *tdinfo; - struct net_device_stats *stats = &vptr->stats; + 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; @@ -2324,22 +2324,22 @@ static struct net_device_stats *velocity_get_stats(struct net_device *dev) /* If the hardware is down, don't touch MII */ if(!netif_running(dev)) - return &vptr->stats; + return &dev->stats; spin_lock_irq(&vptr->lock); velocity_update_hw_mibs(vptr); spin_unlock_irq(&vptr->lock); - vptr->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts]; - vptr->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts]; - vptr->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors]; + 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 */ - vptr->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions]; + 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 */ - vptr->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE]; + 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 */ @@ -2347,7 +2347,7 @@ static struct net_device_stats *velocity_get_stats(struct net_device *dev) /* detailed tx_errors */ // unsigned long tx_fifo_errors; - return &vptr->stats; + return &dev->stats; } diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index ea43e1832afb..4cd3f6c97379 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -1503,7 +1503,6 @@ struct velocity_info { struct pci_dev *pdev; struct net_device *dev; - struct net_device_stats stats; struct vlan_group *vlgrp; u8 ip_addr[4]; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7fa620ddeb21..52198f6797a4 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -283,10 +283,11 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi) for (;;) { struct virtio_net_hdr *hdr; - skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN); + skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN); if (unlikely(!skb)) break; + skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, MAX_PACKET_LEN); hdr = skb_vnet_hdr(skb); @@ -470,7 +471,7 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) } if (skb_is_gso(skb)) { - hdr->hdr_len = skb_transport_header(skb) - skb->data; + hdr->hdr_len = skb_headlen(skb); hdr->gso_size = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; @@ -622,12 +623,9 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, unsigned int tmp; int i; - if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { - BUG(); /* Caller should know better */ - return false; - } - - BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX); + /* Caller should know better */ + BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) || + (out + in > VIRTNET_SEND_COMMAND_SG_MAX)); out++; /* Add header */ in++; /* Add return status */ @@ -642,8 +640,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, sg_set_buf(&sg[i + 1], sg_virt(s), s->length); sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); - if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0) - BUG(); + BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi)); vi->cvq->vq_ops->kick(vi->cvq); @@ -684,6 +681,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) u8 promisc, allmulti; struct virtio_net_ctrl_mac *mac_data; struct dev_addr_list *addr; + struct netdev_hw_addr *ha; void *buf; int i; @@ -722,9 +720,9 @@ static void virtnet_set_rx_mode(struct net_device *dev) /* Store the unicast list and count in the front of the buffer */ mac_data->entries = dev->uc_count; - addr = dev->uc_list; - for (i = 0; i < dev->uc_count; i++, addr = addr->next) - memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); + i = 0; + list_for_each_entry(ha, &dev->uc_list, list) + memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); sg_set_buf(&sg[0], mac_data, sizeof(mac_data->entries) + (dev->uc_count * ETH_ALEN)); diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index 6b41c884a337..26cde573af43 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c @@ -1884,17 +1884,13 @@ void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool) mempool->memblock_size, dma_object); } - if (mempool->items_arr) - vfree(mempool->items_arr); + vfree(mempool->items_arr); - if (mempool->memblocks_dma_arr) - vfree(mempool->memblocks_dma_arr); + vfree(mempool->memblocks_dma_arr); - if (mempool->memblocks_priv_arr) - vfree(mempool->memblocks_priv_arr); + vfree(mempool->memblocks_priv_arr); - if (mempool->memblocks_arr) - vfree(mempool->memblocks_arr); + vfree(mempool->memblocks_arr); vfree(mempool); } diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index b7f08f3e524b..6c838b3e063a 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -677,7 +677,7 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr, return VXGE_HW_OK; } -/* select a vpath to trasmit the packet */ +/* select a vpath to transmit the packet */ static u32 vxge_get_vpath_no(struct vxgedev *vdev, struct sk_buff *skb, int *do_lock) { @@ -992,7 +992,9 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev) VXGE_HW_FIFO_TXD_TX_CKO_UDP_EN); vxge_hw_fifo_txdl_post(fifo_hw, dtr); - dev->trans_start = jiffies; +#ifdef NETIF_F_LLTX + dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ +#endif spin_unlock_irqrestore(&fifo->tx_lock, flags); VXGE_COMPLETE_VPATH_TX(fifo); diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index c2eeac4125f3..370f55cbbad7 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c @@ -1923,7 +1923,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( if (vpath == NULL) { alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN, alarm_event); - goto out; + goto out2; } hldev = vpath->hldev; @@ -2161,7 +2161,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( } out: hldev->stats.sw_dev_err_stats.vpath_alarms++; - +out2: if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) || (alarm_event == VXGE_HW_EVENT_UNKNOWN)) return VXGE_HW_OK; diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index 35dea3bea95d..f525f9fe74db 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -615,7 +615,7 @@ static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb, case WAN_DISCONNECTED: if (cycx_x25_chan_connect(dev)) { netif_stop_queue(dev); - return -EBUSY; + return NETDEV_TX_BUSY; } /* fall thru */ case WAN_CONNECTED: @@ -624,7 +624,7 @@ static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb, netif_stop_queue(dev); if (cycx_x25_chan_send(dev, skb)) - return -EBUSY; + return NETDEV_TX_BUSY; break; default: @@ -656,7 +656,7 @@ static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb, if (cycx_x25_chan_send(dev, skb)) { /* prepare for future retransmissions */ skb_push(skb, 1); - return -EBUSY; + return NETDEV_TX_BUSY; } } diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index e8d155c3e59f..2fa275a58f9d 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -205,15 +205,15 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev) { case DLCI_RET_OK: dev->stats.tx_packets++; - ret = 0; + ret = NETDEV_TX_OK; break; case DLCI_RET_ERR: dev->stats.tx_errors++; - ret = 0; + ret = NETDEV_TX_OK; break; case DLCI_RET_DROP: dev->stats.tx_dropped++; - ret = 1; + ret = NETDEV_TX_BUSY; break; } /* Alan Cox recommends always returning 0, and always freeing the packet */ diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 800530101093..bfa0161a02d3 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1054,6 +1054,7 @@ static void pvc_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT; dev->hard_header_len = 10; dev->addr_len = 2; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } static const struct net_device_ops pvc_ops = { diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index a6dc317083d3..bb719b6114cb 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -732,8 +732,8 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget) dma_unmap_single(&dev->dev, desc->data, RX_SIZE, DMA_FROM_DEVICE); #else - dma_sync_single(&dev->dev, desc->data, - RX_SIZE, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(&dev->dev, desc->data, + RX_SIZE, DMA_FROM_DEVICE); memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n], ALIGN(desc->pkt_len, 4) / 4); #endif diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index c23fde0c0344..79dabc557bd3 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -225,6 +225,7 @@ static char rcsid[] = #include #include #include +#include #include #include #include @@ -3246,6 +3247,16 @@ static inline void show_version(void) rcsvers, rcsdate, __DATE__, __TIME__); } /* show_version */ +static const struct net_device_ops cpc_netdev_ops = { + .ndo_open = cpc_open, + .ndo_stop = cpc_close, + .ndo_tx_timeout = cpc_tx_timeout, + .ndo_set_mac_address = NULL, + .ndo_change_mtu = cpc_change_mtu, + .ndo_do_ioctl = cpc_ioctl, + .ndo_validate_addr = eth_validate_addr, +}; + static void cpc_init_card(pc300_t * card) { int i, devcount = 0; @@ -3357,18 +3368,11 @@ static void cpc_init_card(pc300_t * card) dev->mem_start = card->hw.ramphys; dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1; dev->irq = card->hw.irq; - dev->init = NULL; dev->tx_queue_len = PC300_TX_QUEUE_LEN; dev->mtu = PC300_DEF_MTU; - dev->open = cpc_open; - dev->stop = cpc_close; - dev->tx_timeout = cpc_tx_timeout; + dev->netdev_ops = &cpc_netdev_ops; dev->watchdog_timeo = PC300_TX_TIMEOUT; - dev->set_multicast_list = NULL; - dev->set_mac_address = NULL; - dev->change_mtu = cpc_change_mtu; - dev->do_ioctl = cpc_ioctl; if (register_hdlc_device(dev) == 0) { printk("%s: Cyclades-PC300/", dev->name); diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index f4211fe0f445..3fb9dbc88a1a 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -469,7 +469,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev ) } } - return 1; + return NETDEV_TX_BUSY; } #else /* CONFIG_SBNI_MULTILINE */ diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 8130b79a8a99..e4ad7b6b52eb 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -283,7 +283,7 @@ static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) #endif netif_stop_queue(dev); spin_unlock_irq(&port->lock); - return 1; /* request packet to be queued */ + return NETDEV_TX_BUSY; /* request packet to be queued */ } #ifdef DEBUG_PKT diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index b3cadb626fe0..07308686dbcf 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -292,8 +292,6 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, d_fnstart(3, dev, "(i2400m %p ss %p [%u])\n", i2400m, ss, i2400m_state); - if (unlikely(i2400m->ready == 0)) /* act if up */ - goto out; if (i2400m->state != i2400m_state) { i2400m->state = i2400m_state; wake_up_all(&i2400m->state_wq); @@ -341,7 +339,6 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, i2400m->bus_reset(i2400m, I2400M_RT_WARM); break; }; -out: d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n", i2400m, ss, i2400m_state); } @@ -372,8 +369,6 @@ void i2400m_report_tlv_media_status(struct i2400m *i2400m, d_fnstart(3, dev, "(i2400m %p ms %p [%u])\n", i2400m, ms, status); - if (unlikely(i2400m->ready == 0)) /* act if up */ - goto out; switch (status) { case I2400M_MEDIA_STATUS_LINK_UP: netif_carrier_on(net_dev); @@ -393,14 +388,59 @@ void i2400m_report_tlv_media_status(struct i2400m *i2400m, dev_err(dev, "HW BUG? unknown media status %u\n", status); }; -out: d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n", i2400m, ms, status); } /* - * Parse a 'state report' and extract carrier on/off information + * Process a TLV from a 'state report' + * + * @i2400m: device descriptor + * @tlv: pointer to the TLV header; it has been already validated for + * consistent size. + * @tag: for error messages + * + * Act on the TLVs from a 'state report'. + */ +static +void i2400m_report_state_parse_tlv(struct i2400m *i2400m, + const struct i2400m_tlv_hdr *tlv, + const char *tag) +{ + struct device *dev = i2400m_dev(i2400m); + const struct i2400m_tlv_media_status *ms; + const struct i2400m_tlv_system_state *ss; + const struct i2400m_tlv_rf_switches_status *rfss; + + if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE, sizeof(*ss))) { + ss = container_of(tlv, typeof(*ss), hdr); + d_printf(2, dev, "%s: system state TLV " + "found (0x%04x), state 0x%08x\n", + tag, I2400M_TLV_SYSTEM_STATE, + le32_to_cpu(ss->state)); + i2400m_report_tlv_system_state(i2400m, ss); + } + if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS, sizeof(*rfss))) { + rfss = container_of(tlv, typeof(*rfss), hdr); + d_printf(2, dev, "%s: RF status TLV " + "found (0x%04x), sw 0x%02x hw 0x%02x\n", + tag, I2400M_TLV_RF_STATUS, + le32_to_cpu(rfss->sw_rf_switch), + le32_to_cpu(rfss->hw_rf_switch)); + i2400m_report_tlv_rf_switches_status(i2400m, rfss); + } + if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS, sizeof(*ms))) { + ms = container_of(tlv, typeof(*ms), hdr); + d_printf(2, dev, "%s: Media Status TLV: %u\n", + tag, le32_to_cpu(ms->media_status)); + i2400m_report_tlv_media_status(i2400m, ms); + } +} + + +/* + * Parse a 'state report' and extract information * * @i2400m: device descriptor * @l3l4_hdr: pointer to message; it has been already validated for @@ -409,13 +449,7 @@ void i2400m_report_tlv_media_status(struct i2400m *i2400m, * declaration is assumed to be congruent with @size (as in * sizeof(*l3l4_hdr) + l3l4_hdr->length == size) * - * Extract from the report state the system state TLV and infer from - * there if we have a carrier or not. Update our local state and tell - * netdev. - * - * When setting the carrier, it's fine to set OFF twice (for example), - * as netif_carrier_off() will not generate two OFF events (just on - * the transitions). + * Walk over the TLVs in a report state and act on them. */ static void i2400m_report_state_hook(struct i2400m *i2400m, @@ -424,9 +458,6 @@ void i2400m_report_state_hook(struct i2400m *i2400m, { struct device *dev = i2400m_dev(i2400m); const struct i2400m_tlv_hdr *tlv; - const struct i2400m_tlv_system_state *ss; - const struct i2400m_tlv_rf_switches_status *rfss; - const struct i2400m_tlv_media_status *ms; size_t tlv_size = le16_to_cpu(l3l4_hdr->length); d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n", @@ -434,34 +465,8 @@ void i2400m_report_state_hook(struct i2400m *i2400m, tlv = NULL; while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl, - tlv_size, tlv))) { - if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE, - sizeof(*ss))) { - ss = container_of(tlv, typeof(*ss), hdr); - d_printf(2, dev, "%s: system state TLV " - "found (0x%04x), state 0x%08x\n", - tag, I2400M_TLV_SYSTEM_STATE, - le32_to_cpu(ss->state)); - i2400m_report_tlv_system_state(i2400m, ss); - } - if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS, - sizeof(*rfss))) { - rfss = container_of(tlv, typeof(*rfss), hdr); - d_printf(2, dev, "%s: RF status TLV " - "found (0x%04x), sw 0x%02x hw 0x%02x\n", - tag, I2400M_TLV_RF_STATUS, - le32_to_cpu(rfss->sw_rf_switch), - le32_to_cpu(rfss->hw_rf_switch)); - i2400m_report_tlv_rf_switches_status(i2400m, rfss); - } - if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS, - sizeof(*ms))) { - ms = container_of(tlv, typeof(*ms), hdr); - d_printf(2, dev, "%s: Media Status TLV: %u\n", - tag, le32_to_cpu(ms->media_status)); - i2400m_report_tlv_media_status(i2400m, ms); - } - } + tlv_size, tlv))) + i2400m_report_state_parse_tlv(i2400m, tlv, tag); d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n", i2400m, l3l4_hdr, size, tag); } @@ -500,8 +505,15 @@ void i2400m_report_hook(struct i2400m *i2400m, * it. */ case I2400M_MT_REPORT_POWERSAVE_READY: /* zzzzz */ if (l3l4_hdr->status == cpu_to_le16(I2400M_MS_DONE_OK)) { - d_printf(1, dev, "ready for powersave, requesting\n"); - i2400m_cmd_enter_powersave(i2400m); + if (i2400m_power_save_disabled) + d_printf(1, dev, "ready for powersave, " + "not requesting (disabled by module " + "parameter)\n"); + else { + d_printf(1, dev, "ready for powersave, " + "requesting\n"); + i2400m_cmd_enter_powersave(i2400m); + } } break; }; @@ -683,8 +695,9 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n", i2400m, buf, buf_len); + rmb(); /* Make sure we see what i2400m_dev_reset_handle() */ if (i2400m->boot_mode) - return ERR_PTR(-ENODEV); + return ERR_PTR(-EL3RST); msg_l3l4_hdr = buf; /* Check msg & payload consistency */ @@ -721,6 +734,8 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, ack_timeout = HZ; }; + if (unlikely(i2400m->trace_msg_from_user)) + wimax_msg(&i2400m->wimax_dev, "echo", buf, buf_len, GFP_KERNEL); /* The RX path in rx.c will put any response for this message * in i2400m->ack_skb and wake us up. If we cancel the wait, * we need to change the value of i2400m->ack_skb to something @@ -755,6 +770,9 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len); /* Check the ack and deliver it if it is ok */ + if (unlikely(i2400m->trace_msg_from_user)) + wimax_msg(&i2400m->wimax_dev, "echo", + ack_l3l4_hdr, ack_len, GFP_KERNEL); result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len); if (result < 0) { dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n", @@ -1379,16 +1397,16 @@ int i2400m_dev_initialize(struct i2400m *i2400m) * * @i2400m: device descriptor * - * Gracefully stops the device, moving it to the lowest power - * consumption state possible. + * Release resources acquired during the running of the device; in + * theory, should also tell the device to go to sleep, switch off the + * radio, all that, but at this point, in most cases (driver + * disconnection, reset handling) we can't even talk to the device. */ void i2400m_dev_shutdown(struct i2400m *i2400m) { - int result = -ENODEV; struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - result = i2400m->bus_reset(i2400m, I2400M_RT_WARM); - d_fnend(3, dev, "(i2400m %p) = void [%d]\n", i2400m, result); + d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); return; } diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 07a54bad237b..304f0443ca4b 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -62,6 +62,7 @@ * unregister_netdev() */ #include "i2400m.h" +#include #include #include #include @@ -81,6 +82,14 @@ module_param_named(rx_reorder_disabled, i2400m_rx_reorder_disabled, int, 0644); MODULE_PARM_DESC(rx_reorder_disabled, "If true, RX reordering will be disabled."); +int i2400m_power_save_disabled; /* 0 (power saving enabled) by default */ +module_param_named(power_save_disabled, i2400m_power_save_disabled, int, 0644); +MODULE_PARM_DESC(power_save_disabled, + "If true, the driver will not tell the device to enter " + "power saving mode when it reports it is ready for it. " + "False by default (so the device is told to do power " + "saving)."); + /** * i2400m_queue_work - schedule work on a i2400m's queue * @@ -171,7 +180,6 @@ int i2400m_schedule_work(struct i2400m *i2400m, int result; struct i2400m_work *iw; - BUG_ON(i2400m->work_queue == NULL); result = -ENOMEM; iw = kzalloc(sizeof(*iw), gfp_flags); if (iw == NULL) @@ -234,9 +242,6 @@ int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev, result = PTR_ERR(ack_skb); if (IS_ERR(ack_skb)) goto error_msg_to_dev; - if (unlikely(i2400m->trace_msg_from_user)) - wimax_msg(&i2400m->wimax_dev, "trace", - msg_buf, msg_len, GFP_KERNEL); result = wimax_msg_send(&i2400m->wimax_dev, ack_skb); error_msg_to_dev: d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu " @@ -379,6 +384,11 @@ int i2400m_check_mac_addr(struct i2400m *i2400m) * Uploads firmware and brings up all the resources needed to be able * to communicate with the device. * + * The workqueue has to be setup early, at least before RX handling + * (it's only real user for now) so it can process reports as they + * arrive. We also want to destroy it if we retry, to make sure it is + * flushed...easier like this. + * * TX needs to be setup before the bus-specific code (otherwise on * shutdown, the bus-tx code could try to access it). */ @@ -389,7 +399,7 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) struct wimax_dev *wimax_dev = &i2400m->wimax_dev; struct net_device *net_dev = wimax_dev->net_dev; struct device *dev = i2400m_dev(i2400m); - int times = 3; + int times = i2400m->bus_bm_retries; d_fnstart(3, dev, "(i2400m %p)\n", i2400m); retry: @@ -404,15 +414,15 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) result = i2400m_rx_setup(i2400m); if (result < 0) goto error_rx_setup; - result = i2400m->bus_dev_start(i2400m); - if (result < 0) - goto error_bus_dev_start; i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name); if (i2400m->work_queue == NULL) { result = -ENOMEM; dev_err(dev, "cannot create workqueue\n"); goto error_create_workqueue; } + result = i2400m->bus_dev_start(i2400m); + if (result < 0) + goto error_bus_dev_start; result = i2400m_firmware_check(i2400m); /* fw versions ok? */ if (result < 0) goto error_fw_check; @@ -434,17 +444,17 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) error_dev_initialize: error_check_mac_addr: error_fw_check: - destroy_workqueue(i2400m->work_queue); -error_create_workqueue: i2400m->bus_dev_stop(i2400m); error_bus_dev_start: + destroy_workqueue(i2400m->work_queue); +error_create_workqueue: i2400m_rx_release(i2400m); error_rx_setup: i2400m_tx_release(i2400m); error_tx_setup: error_bootstrap: - if (result == -ERESTARTSYS && times-- > 0) { - flags = I2400M_BRI_SOFT; + if (result == -EL3RST && times-- > 0) { + flags = I2400M_BRI_SOFT|I2400M_BRI_MAC_REINIT; goto retry; } d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", @@ -473,7 +483,9 @@ int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags) * * Returns: 0 if ok, < 0 errno code on error. * - * Releases all the resources allocated to communicate with the device. + * Releases all the resources allocated to communicate with the + * device. Note we cannot destroy the workqueue earlier as until RX is + * fully destroyed, it could still try to schedule jobs. */ static void __i2400m_dev_stop(struct i2400m *i2400m) @@ -485,8 +497,8 @@ void __i2400m_dev_stop(struct i2400m *i2400m) wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING); i2400m_dev_shutdown(i2400m); i2400m->ready = 0; - destroy_workqueue(i2400m->work_queue); i2400m->bus_dev_stop(i2400m); + destroy_workqueue(i2400m->work_queue); i2400m_rx_release(i2400m); i2400m_tx_release(i2400m); wimax_state_change(wimax_dev, WIMAX_ST_DOWN); @@ -548,7 +560,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) * i2400m_dev_stop() [we are shutting down anyway, so * ignore it] or we are resetting somewhere else. */ dev_err(dev, "device rebooted\n"); - i2400m_msg_to_dev_cancel_wait(i2400m, -ERESTARTSYS); + i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST); complete(&i2400m->msg_completion); goto out; } @@ -598,6 +610,8 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) */ int i2400m_dev_reset_handle(struct i2400m *i2400m) { + i2400m->boot_mode = 1; + wmb(); /* Make sure i2400m_msg_to_dev() sees boot_mode */ return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, GFP_ATOMIC); } @@ -650,6 +664,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) result = i2400m_read_mac_addr(i2400m); if (result < 0) goto error_read_mac_addr; + random_ether_addr(i2400m->src_mac_addr); result = register_netdev(net_dev); /* Okey dokey, bring it up */ if (result < 0) { diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 675c6ce810c0..e81750e54452 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -397,7 +397,7 @@ static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk, unsigned int direct, unsigned int do_csum) { int ret; - size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_PAD); + size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_ALIGN); struct device *dev = i2400m_dev(i2400m); struct { struct i2400m_bootrom_header cmd; @@ -532,14 +532,14 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, cmd = (void *) bcf + offset; if (i2400m->sboot == 0) { struct i2400m_bootrom_header jump_ack; - d_printf(3, dev, "unsecure boot, jumping to 0x%08x\n", + d_printf(1, dev, "unsecure boot, jumping to 0x%08x\n", le32_to_cpu(cmd->target_addr)); i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP); cmd->data_size = 0; ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), &jump_ack, sizeof(jump_ack), 0); } else { - d_printf(3, dev, "secure boot, jumping to 0x%08x\n", + d_printf(1, dev, "secure boot, jumping to 0x%08x\n", le32_to_cpu(cmd->target_addr)); cmd_buf = i2400m->bm_cmd_buf; memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd)); @@ -696,8 +696,7 @@ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) return result; error_timeout: - dev_err(dev, "Timed out waiting for reboot ack, resetting\n"); - i2400m->bus_reset(i2400m, I2400M_RT_BUS); + dev_err(dev, "Timed out waiting for reboot ack\n"); result = -ETIMEDOUT; goto exit_timeout; } @@ -770,40 +769,21 @@ int i2400m_read_mac_addr(struct i2400m *i2400m) static int i2400m_dnload_init_nonsigned(struct i2400m *i2400m) { -#define POKE(a, d) { \ - .address = cpu_to_le32(a), \ - .data = cpu_to_le32(d) \ -} - static const struct { - __le32 address; - __le32 data; - } i2400m_pokes[] = { - POKE(0x081A58, 0xA7810230), - POKE(0x080040, 0x00000000), - POKE(0x080048, 0x00000082), - POKE(0x08004C, 0x0000081F), - POKE(0x080054, 0x00000085), - POKE(0x080058, 0x00000180), - POKE(0x08005C, 0x00000018), - POKE(0x080060, 0x00000010), - POKE(0x080574, 0x00000001), - POKE(0x080550, 0x00000005), - POKE(0xAE0000, 0x00000000), - }; -#undef POKE - unsigned i; - int ret; + unsigned i = 0; + int ret = 0; struct device *dev = i2400m_dev(i2400m); - - dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n"); - d_fnstart(5, dev, "(i2400m %p)\n", i2400m); - for (i = 0; i < ARRAY_SIZE(i2400m_pokes); i++) { - ret = i2400m_download_chunk(i2400m, &i2400m_pokes[i].data, - sizeof(i2400m_pokes[i].data), - i2400m_pokes[i].address, 1, 1); - if (ret < 0) - break; + if (i2400m->bus_bm_pokes_table) { + while (i2400m->bus_bm_pokes_table[i].address) { + ret = i2400m_download_chunk( + i2400m, + &i2400m->bus_bm_pokes_table[i].data, + sizeof(i2400m->bus_bm_pokes_table[i].data), + i2400m->bus_bm_pokes_table[i].address, 1, 1); + if (ret < 0) + break; + i++; + } } d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); return ret; @@ -980,11 +960,12 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, { int ret = 0; struct device *dev = i2400m_dev(i2400m); - int count = I2400M_BOOT_RETRIES; + int count = i2400m->bus_bm_retries; d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n", i2400m, bcf, bcf_size); i2400m->boot_mode = 1; + wmb(); /* Make sure other readers see it */ hw_reboot: if (count-- == 0) { ret = -ERESTARTSYS; @@ -1033,6 +1014,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, d_printf(2, dev, "fw %s successfully uploaded\n", i2400m->fw_name); i2400m->boot_mode = 0; + wmb(); /* Make sure i2400m_msg_to_dev() sees boot_mode */ error_dnload_finalize: error_dnload_bcf: error_dnload_init: diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h index 08c2fb739234..9c4e3189f7b5 100644 --- a/drivers/net/wimax/i2400m/i2400m-sdio.h +++ b/drivers/net/wimax/i2400m/i2400m-sdio.h @@ -78,6 +78,8 @@ enum { /* The number of ticks to wait for the device to signal that * it is ready */ I2400MS_INIT_SLEEP_INTERVAL = 10, + /* How long to wait for the device to settle after reset */ + I2400MS_SETTLE_TIME = 40, }; @@ -105,6 +107,10 @@ struct i2400ms { char tx_wq_name[32]; struct dentry *debugfs_dentry; + + wait_queue_head_t bm_wfa_wq; + int bm_wait_result; + size_t bm_ack_size; }; @@ -129,4 +135,7 @@ extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *, extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *, struct i2400m_bootrom_header *, size_t); +extern void i2400ms_bus_bm_release(struct i2400m *); +extern int i2400ms_bus_bm_setup(struct i2400m *); + #endif /* #ifndef __I2400M_SDIO_H__ */ diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 3ae2df38b59a..1fe5da4cf0a0 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -150,11 +150,33 @@ enum { /* Firmware uploading */ I2400M_BOOT_RETRIES = 3, + I3200_BOOT_RETRIES = 3, /* Size of the Boot Mode Command buffer */ I2400M_BM_CMD_BUF_SIZE = 16 * 1024, I2400M_BM_ACK_BUF_SIZE = 256, }; +/** + * struct i2400m_poke_table - Hardware poke table for the Intel 2400m + * + * This structure will be used to create a device specific poke table + * to put the device in a consistant state at boot time. + * + * @address: The device address to poke + * + * @data: The data value to poke to the device address + * + */ +struct i2400m_poke_table{ + __le32 address; + __le32 data; +}; + +#define I2400M_FW_POKE(a, d) { \ + .address = cpu_to_le32(a), \ + .data = cpu_to_le32(d) \ +} + /** * i2400m_reset_type - methods to reset a device @@ -224,6 +246,17 @@ struct i2400m_roq; * process, so it cannot rely on common infrastructure being laid * out. * + * @bus_bm_retries: [fill] How many times shall a firmware upload / + * device initialization be retried? Different models of the same + * device might need different values, hence it is set by the + * bus-specific driver. Note this value is used in two places, + * i2400m_fw_dnload() and __i2400m_dev_start(); they won't become + * multiplicative (__i2400m_dev_start() calling N times + * i2400m_fw_dnload() and this trying N times to download the + * firmware), as if __i2400m_dev_start() only retries if the + * firmware crashed while initializing the device (not in a + * general case). + * * @bus_bm_cmd_send: [fill] Function called to send a boot-mode * command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This * is synchronous and has to return 0 if ok or < 0 errno code in @@ -252,6 +285,12 @@ struct i2400m_roq; * address provided in boot mode is kind of broken and needs to * be re-read later on. * + * @bus_bm_pokes_table: [fill/optional] A table of device addresses + * and values that will be poked at device init time to move the + * device to the correct state for the type of boot/firmware being + * used. This table MUST be terminated with (0x000000, + * 0x00000000) or bad things will happen. + * * * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX * stack. Due to the way a net_device is allocated, we need to @@ -323,6 +362,10 @@ struct i2400m_roq; * delivered. Then the driver can release them to the host. See * drivers/net/i2400m/rx.c for details. * + * @src_mac_addr: MAC address used to make ethernet packets be coming + * from. This is generated at i2400m_setup() time and used during + * the life cycle of the instance. See i2400m_fake_eth_header(). + * * @init_mutex: Mutex used for serializing the device bringup * sequence; this way if the device reboots in the middle, we * don't try to do a bringup again while we are tearing down the @@ -395,6 +438,8 @@ struct i2400m { size_t bus_tx_block_size; size_t bus_pl_size_max; + unsigned bus_bm_retries; + int (*bus_dev_start)(struct i2400m *); void (*bus_dev_stop)(struct i2400m *); void (*bus_tx_kick)(struct i2400m *); @@ -406,6 +451,7 @@ struct i2400m { struct i2400m_bootrom_header *, size_t); const char **bus_fw_names; unsigned bus_bm_mac_addr_impaired:1; + const struct i2400m_poke_table *bus_bm_pokes_table; spinlock_t tx_lock; /* protect TX state */ void *tx_buf; @@ -421,6 +467,7 @@ struct i2400m { unsigned rx_pl_num, rx_pl_max, rx_pl_min, rx_num, rx_size_acc, rx_size_min, rx_size_max; struct i2400m_roq *rx_roq; /* not under rx_lock! */ + u8 src_mac_addr[ETH_HLEN]; struct mutex msg_mutex; /* serialize command execution */ struct completion msg_completion; @@ -704,6 +751,7 @@ static const __le32 i2400m_SBOOT_BARKER[4] = { cpu_to_le32(I2400M_SBOOT_BARKER) }; +extern int i2400m_power_save_disabled; /* * Utility functions diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 6b1fe7a81f25..9653f478b382 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -404,10 +404,12 @@ static void i2400m_rx_fake_eth_header(struct net_device *net_dev, void *_eth_hdr, __be16 protocol) { + struct i2400m *i2400m = net_dev_to_i2400m(net_dev); struct ethhdr *eth_hdr = _eth_hdr; memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest)); - memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest)); + memcpy(eth_hdr->h_source, i2400m->src_mac_addr, + sizeof(eth_hdr->h_source)); eth_hdr->h_proto = protocol; } diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c index 487ec58cea46..43927b5d7ad6 100644 --- a/drivers/net/wimax/i2400m/op-rfkill.c +++ b/drivers/net/wimax/i2400m/op-rfkill.c @@ -54,8 +54,10 @@ int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state) /* state == WIMAX_RF_ON */ return i2400m->state != I2400M_SS_RF_OFF && i2400m->state != I2400M_SS_RF_SHUTDOWN; - else + else { BUG(); + return -EINVAL; /* shut gcc warnings on certain arches */ + } } diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index f9fc38902322..07c32e68909f 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c @@ -177,7 +177,8 @@ void i2400m_report_hook_work(struct work_struct *ws) struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); struct i2400m_report_hook_args *args = (void *) iw->pl; - i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size); + if (iw->i2400m->ready) + i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size); kfree_skb(args->skb_rx); i2400m_put(iw->i2400m); kfree(iw); @@ -309,6 +310,9 @@ void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx, skb_get(skb_rx); i2400m_queue_work(i2400m, i2400m_report_hook_work, GFP_KERNEL, &args, sizeof(args)); + if (unlikely(i2400m->trace_msg_from_user)) + wimax_msg(&i2400m->wimax_dev, "echo", + l3l4_hdr, size, GFP_KERNEL); result = wimax_msg(&i2400m->wimax_dev, NULL, l3l4_hdr, size, GFP_KERNEL); if (result < 0) @@ -1144,7 +1148,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) num_pls = le16_to_cpu(msg_hdr->num_pls); pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ num_pls * sizeof(msg_hdr->pld[0]); - pl_itr = ALIGN(pl_itr, I2400M_PL_PAD); + pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN); if (pl_itr > skb->len) { /* got all the payload descriptors? */ dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " "%u payload descriptors (%zu each, total %zu)\n", @@ -1162,7 +1166,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) single_last = num_pls == 1 || i == num_pls - 1; i2400m_rx_payload(i2400m, skb, single_last, &msg_hdr->pld[i], skb->data + pl_itr); - pl_itr += ALIGN(pl_size, I2400M_PL_PAD); + pl_itr += ALIGN(pl_size, I2400M_PL_ALIGN); cond_resched(); /* Don't monopolize */ } kfree_skb(skb); diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c index 3487205d8f50..7d6ec0f475f8 100644 --- a/drivers/net/wimax/i2400m/sdio-fw.c +++ b/drivers/net/wimax/i2400m/sdio-fw.c @@ -46,17 +46,24 @@ * Inaky Perez-Gonzalez * - SDIO rehash for changes in the bus-driver model * + * Dirk Brandewie + * - Make it IRQ based, not polling + * * THE PROCEDURE * * See fw.c for the generic description of this procedure. * * This file implements only the SDIO specifics. It boils down to how * to send a command and waiting for an acknowledgement from the - * device. We do polled reads. + * device. + * + * All this code is sequential -- all i2400ms_bus_bm_*() functions are + * executed in the same thread, except i2400ms_bm_irq() [on its own by + * the SDIO driver]. This makes it possible to avoid locking. * * COMMAND EXECUTION * - * THe generic firmware upload code will call i2400m_bus_bm_cmd_send() + * The generic firmware upload code will call i2400m_bus_bm_cmd_send() * to send commands. * * The SDIO devices expects things in 256 byte blocks, so it will pad @@ -64,12 +71,15 @@ * * ACK RECEPTION * - * This works in polling mode -- the fw loader says when to wait for - * data and for that it calls i2400ms_bus_bm_wait_for_ack(). + * This works in IRQ mode -- the fw loader says when to wait for data + * and for that it calls i2400ms_bus_bm_wait_for_ack(). * - * This will poll the device for data until it is received. We need to - * receive at least as much bytes as where asked for (although it'll - * always be a multiple of 256 bytes). + * This checks if there is any data available (RX size > 0); if not, + * waits for the IRQ handler to notify about it. Once there is data, + * it is read and passed to the caller. Doing it this way we don't + * need much coordination/locking, and it makes it much more difficult + * for an interrupt to be lost and the wait_for_ack() function getting + * stuck even when data is pending. */ #include #include "i2400m-sdio.h" @@ -78,6 +88,7 @@ #define D_SUBMODULE fw #include "sdio-debug-levels.h" + /* * Send a boot-mode command to the SDIO function * @@ -139,7 +150,7 @@ ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, /* - * Read an ack from the device's boot-mode (polling) + * Read an ack from the device's boot-mode * * @i2400m: * @_ack: pointer to where to store the read data @@ -150,75 +161,49 @@ ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, * The ACK for a BM command is always at least sizeof(*ack) bytes, so * check for that. We don't need to check for device reboots * - * NOTE: We do an artificial timeout of 1 sec over the SDIO timeout; - * this way we have control over it...there is no way that I know - * of setting an SDIO transaction timeout. */ ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, struct i2400m_bootrom_header *ack, size_t ack_size) { - int result; - ssize_t rx_size; - u64 timeout; + ssize_t result; struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; + int size; BUG_ON(sizeof(*ack) > ack_size); d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n", i2400m, ack, ack_size); - timeout = get_jiffies_64() + 2 * HZ; - sdio_claim_host(func); - while (1) { - if (time_after64(get_jiffies_64(), timeout)) { - rx_size = -ETIMEDOUT; - dev_err(dev, "timeout waiting for ack data\n"); - goto error_timedout; - } + spin_lock(&i2400m->rx_lock); + i2400ms->bm_ack_size = -EINPROGRESS; + spin_unlock(&i2400m->rx_lock); - /* Find the RX size, check if it fits or not -- it if - * doesn't fit, fail, as we have no way to dispose of - * the extra data. */ - rx_size = __i2400ms_rx_get_size(i2400ms); - if (rx_size < 0) - goto error_rx_get_size; - result = -ENOSPC; /* Check it fits */ - if (rx_size < sizeof(*ack)) { - rx_size = -EIO; - dev_err(dev, "HW BUG? received is too small (%zu vs " - "%zu needed)\n", sizeof(*ack), rx_size); - goto error_too_small; - } - if (rx_size > I2400M_BM_ACK_BUF_SIZE) { - dev_err(dev, "SW BUG? BM_ACK_BUF is too small (%u vs " - "%zu needed)\n", I2400M_BM_ACK_BUF_SIZE, - rx_size); - goto error_too_small; - } - - /* Read it */ - result = sdio_memcpy_fromio(func, i2400m->bm_ack_buf, - I2400MS_DATA_ADDR, rx_size); - if (result == -ETIMEDOUT || result == -ETIME) - continue; - if (result < 0) { - dev_err(dev, "BM SDIO receive (%zu B) failed: %d\n", - rx_size, result); - goto error_read; - } else - break; + result = wait_event_timeout(i2400ms->bm_wfa_wq, + i2400ms->bm_ack_size != -EINPROGRESS, + 2 * HZ); + if (result == 0) { + result = -ETIMEDOUT; + dev_err(dev, "BM: error waiting for an ack\n"); + goto error_timeout; } - rx_size = min((ssize_t)ack_size, rx_size); - memcpy(ack, i2400m->bm_ack_buf, rx_size); -error_read: -error_too_small: -error_rx_get_size: -error_timedout: - sdio_release_host(func); - d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %ld\n", - i2400m, ack, ack_size, (long) rx_size); - return rx_size; + + spin_lock(&i2400m->rx_lock); + result = i2400ms->bm_ack_size; + BUG_ON(result == -EINPROGRESS); + if (result < 0) /* so we exit when rx_release() is called */ + dev_err(dev, "BM: %s failed: %zd\n", __func__, result); + else { + size = min(ack_size, i2400ms->bm_ack_size); + memcpy(ack, i2400m->bm_ack_buf, size); + } + i2400ms->bm_ack_size = -EINPROGRESS; + spin_unlock(&i2400m->rx_lock); + +error_timeout: + d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n", + i2400m, ack, ack_size, result); + return result; } diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c index a3008b904f7d..321beadf6e47 100644 --- a/drivers/net/wimax/i2400m/sdio-rx.c +++ b/drivers/net/wimax/i2400m/sdio-rx.c @@ -69,6 +69,13 @@ #define D_SUBMODULE rx #include "sdio-debug-levels.h" +static const __le32 i2400m_ACK_BARKER[4] = { + __constant_cpu_to_le32(I2400M_ACK_BARKER), + __constant_cpu_to_le32(I2400M_ACK_BARKER), + __constant_cpu_to_le32(I2400M_ACK_BARKER), + __constant_cpu_to_le32(I2400M_ACK_BARKER) +}; + /* * Read and return the amount of bytes available for RX @@ -131,25 +138,35 @@ void i2400ms_rx(struct i2400ms *i2400ms) ret = rx_size; goto error_get_size; } + ret = -ENOMEM; skb = alloc_skb(rx_size, GFP_ATOMIC); if (NULL == skb) { dev_err(dev, "RX: unable to alloc skb\n"); goto error_alloc_skb; } - ret = sdio_memcpy_fromio(func, skb->data, I2400MS_DATA_ADDR, rx_size); if (ret < 0) { dev_err(dev, "RX: SDIO data read failed: %d\n", ret); goto error_memcpy_fromio; } - /* Check if device has reset */ - if (!memcmp(skb->data, i2400m_NBOOT_BARKER, - sizeof(i2400m_NBOOT_BARKER)) - || !memcmp(skb->data, i2400m_SBOOT_BARKER, - sizeof(i2400m_SBOOT_BARKER))) { + + rmb(); /* make sure we get boot_mode from dev_reset_handle */ + if (i2400m->boot_mode == 1) { + spin_lock(&i2400m->rx_lock); + i2400ms->bm_ack_size = rx_size; + spin_unlock(&i2400m->rx_lock); + memcpy(i2400m->bm_ack_buf, skb->data, rx_size); + wake_up(&i2400ms->bm_wfa_wq); + dev_err(dev, "RX: SDIO boot mode message\n"); + kfree_skb(skb); + } else if (unlikely(!memcmp(skb->data, i2400m_NBOOT_BARKER, + sizeof(i2400m_NBOOT_BARKER)) + || !memcmp(skb->data, i2400m_SBOOT_BARKER, + sizeof(i2400m_SBOOT_BARKER)))) { ret = i2400m_dev_reset_handle(i2400m); + dev_err(dev, "RX: SDIO reboot barker\n"); kfree_skb(skb); } else { skb_put(skb, rx_size); @@ -179,7 +196,6 @@ void i2400ms_irq(struct sdio_func *func) { int ret; struct i2400ms *i2400ms = sdio_get_drvdata(func); - struct i2400m *i2400m = &i2400ms->i2400m; struct device *dev = &func->dev; int val; @@ -194,10 +210,7 @@ void i2400ms_irq(struct sdio_func *func) goto error_no_irq; } sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); - if (WARN_ON(i2400m->boot_mode != 0)) - dev_err(dev, "RX: SW BUG? boot mode and IRQ is up?\n"); - else - i2400ms_rx(i2400ms); + i2400ms_rx(i2400ms); error_no_irq: d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); return; @@ -214,8 +227,15 @@ int i2400ms_rx_setup(struct i2400ms *i2400ms) int result; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; + struct i2400m *i2400m = &i2400ms->i2400m; d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); + + init_waitqueue_head(&i2400ms->bm_wfa_wq); + spin_lock(&i2400m->rx_lock); + i2400ms->bm_wait_result = -EINPROGRESS; + spin_unlock(&i2400m->rx_lock); + sdio_claim_host(func); result = sdio_claim_irq(func, i2400ms_irq); if (result < 0) { @@ -245,8 +265,13 @@ void i2400ms_rx_release(struct i2400ms *i2400ms) int result; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; + struct i2400m *i2400m = &i2400ms->i2400m; d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); + spin_lock(&i2400m->rx_lock); + i2400ms->bm_ack_size = -EINTR; + spin_unlock(&i2400m->rx_lock); + wake_up_all(&i2400ms->bm_wfa_wq); sdio_claim_host(func); sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result); sdio_release_irq(func); diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 5ac5e76701cd..2538825d1c66 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c @@ -78,6 +78,14 @@ static const char *i2400ms_bus_fw_names[] = { }; +static const struct i2400m_poke_table i2400ms_pokes[] = { + I2400M_FW_POKE(0x6BE260, 0x00000088), + I2400M_FW_POKE(0x080550, 0x00000005), + I2400M_FW_POKE(0xAE0000, 0x00000000), + I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad + * things will happen */ +}; + /* * Enable the SDIO function * @@ -148,19 +156,14 @@ int i2400ms_bus_dev_start(struct i2400m *i2400m) d_fnstart(3, dev, "(i2400m %p)\n", i2400m); msleep(200); - result = i2400ms_rx_setup(i2400ms); - if (result < 0) - goto error_rx_setup; result = i2400ms_tx_setup(i2400ms); if (result < 0) goto error_tx_setup; d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); return result; - i2400ms_tx_release(i2400ms); error_tx_setup: - i2400ms_rx_release(i2400ms); -error_rx_setup: + i2400ms_tx_release(i2400ms); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); return result; } @@ -174,7 +177,6 @@ void i2400ms_bus_dev_stop(struct i2400m *i2400m) struct device *dev = &func->dev; d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - i2400ms_rx_release(i2400ms); i2400ms_tx_release(i2400ms); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); } @@ -255,7 +257,7 @@ int __i2400ms_send_barker(struct i2400ms *i2400ms, static int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) { - int result; + int result = 0; struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); struct device *dev = i2400m_dev(i2400m); @@ -280,8 +282,25 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) sizeof(i2400m_COLD_BOOT_BARKER)); else if (rt == I2400M_RT_BUS) { do_bus_reset: - dev_err(dev, "FIXME: SDIO bus reset not implemented\n"); - result = rt == I2400M_RT_WARM ? -ENODEV : -ENOSYS; + /* call netif_tx_disable() before sending IOE disable, + * so that all the tx from network layer are stopped + * while IOE is being reset. Make sure it is called + * only after register_netdev() was issued. + */ + if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED) + netif_tx_disable(i2400m->wimax_dev.net_dev); + + i2400ms_rx_release(i2400ms); + sdio_claim_host(i2400ms->func); + sdio_disable_func(i2400ms->func); + sdio_release_host(i2400ms->func); + + /* Wait for the device to settle */ + msleep(40); + + result = i2400ms_enable_function(i2400ms->func); + if (result >= 0) + i2400ms_rx_setup(i2400ms); } else BUG(); if (result < 0 && rt != I2400M_RT_BUS) { @@ -404,10 +423,22 @@ int i2400ms_probe(struct sdio_func *func, i2400m->bus_dev_stop = i2400ms_bus_dev_stop; i2400m->bus_tx_kick = i2400ms_bus_tx_kick; i2400m->bus_reset = i2400ms_bus_reset; + /* The iwmc3200-wimax sometimes requires the driver to try + * hard when we paint it into a corner. */ + i2400m->bus_bm_retries = I3200_BOOT_RETRIES; i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; i2400m->bus_fw_names = i2400ms_bus_fw_names; i2400m->bus_bm_mac_addr_impaired = 1; + i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; + + sdio_claim_host(func); + result = sdio_set_block_size(func, I2400MS_BLK_SIZE); + sdio_release_host(func); + if (result < 0) { + dev_err(dev, "Failed to set block size: %d\n", result); + goto error_set_blk_size; + } result = i2400ms_enable_function(i2400ms->func); if (result < 0) { @@ -415,13 +446,9 @@ int i2400ms_probe(struct sdio_func *func, goto error_func_enable; } - sdio_claim_host(func); - result = sdio_set_block_size(func, I2400MS_BLK_SIZE); - if (result < 0) { - dev_err(dev, "Failed to set block size: %d\n", result); - goto error_set_blk_size; - } - sdio_release_host(func); + result = i2400ms_rx_setup(i2400ms); + if (result < 0) + goto error_rx_setup; result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); if (result < 0) { @@ -440,12 +467,14 @@ int i2400ms_probe(struct sdio_func *func, error_debugfs_add: i2400m_release(i2400m); error_setup: - sdio_set_drvdata(func, NULL); + i2400ms_rx_release(i2400ms); +error_rx_setup: sdio_claim_host(func); -error_set_blk_size: sdio_disable_func(func); sdio_release_host(func); error_func_enable: +error_set_blk_size: + sdio_set_drvdata(func, NULL); free_netdev(net_dev); error_alloc_netdev: return result; @@ -462,6 +491,7 @@ void i2400ms_remove(struct sdio_func *func) d_fnstart(3, dev, "SDIO func %p\n", func); debugfs_remove_recursive(i2400ms->debugfs_dentry); + i2400ms_rx_release(i2400ms); i2400m_release(i2400m); sdio_set_drvdata(func, NULL); sdio_claim_host(func); diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c index 613a88ffd651..fa16ccf8e26a 100644 --- a/drivers/net/wimax/i2400m/tx.c +++ b/drivers/net/wimax/i2400m/tx.c @@ -277,6 +277,48 @@ enum { #define TAIL_FULL ((void *)~(unsigned long)NULL) +/* + * Calculate how much tail room is available + * + * Note the trick here. This path is ONLY caleed for Case A (see + * i2400m_tx_fifo_push() below), where we have: + * + * Case A + * N ___________ + * | tail room | + * | | + * |<- IN ->| + * | | + * | data | + * | | + * |<- OUT ->| + * | | + * | head room | + * 0 ----------- + * + * When calculating the tail_room, tx_in might get to be zero if + * i2400m->tx_in is right at the end of the buffer (really full + * buffer) if there is no head room. In this case, tail_room would be + * I2400M_TX_BUF_SIZE, although it is actually zero. Hence the final + * mod (%) operation. However, when doing this kind of optimization, + * i2400m->tx_in being zero would fail, so we treat is an a special + * case. + */ +static inline +size_t __i2400m_tx_tail_room(struct i2400m *i2400m) +{ + size_t tail_room; + size_t tx_in; + + if (unlikely(i2400m->tx_in) == 0) + return I2400M_TX_BUF_SIZE; + tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE; + tail_room = I2400M_TX_BUF_SIZE - tx_in; + tail_room %= I2400M_TX_BUF_SIZE; + return tail_room; +} + + /* * Allocate @size bytes in the TX fifo, return a pointer to it * @@ -338,7 +380,7 @@ void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding) return NULL; } /* Is there space at the tail? */ - tail_room = I2400M_TX_BUF_SIZE - i2400m->tx_in % I2400M_TX_BUF_SIZE; + tail_room = __i2400m_tx_tail_room(i2400m); if (tail_room < needed_size) { if (i2400m->tx_out % I2400M_TX_BUF_SIZE < i2400m->tx_in % I2400M_TX_BUF_SIZE) { @@ -367,17 +409,29 @@ void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding) * (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the * header). * + * Tail room can get to be zero if a message was opened when there was + * space only for a header. _tx_close() will mark it as to-skip (as it + * will have no payloads) and there will be no more space to flush, so + * nothing has to be done here. This is probably cheaper than ensuring + * in _tx_new() that there is some space for payloads...as we could + * always possibly hit the same problem if the payload wouldn't fit. + * * Note: * * Assumes i2400m->tx_lock is taken, and we use that as a barrier + * + * This path is only taken for Case A FIFO situations [see + * i2400m_tx_fifo_push()] */ static void i2400m_tx_skip_tail(struct i2400m *i2400m) { struct device *dev = i2400m_dev(i2400m); size_t tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE; - size_t tail_room = I2400M_TX_BUF_SIZE - tx_in; + size_t tail_room = __i2400m_tx_tail_room(i2400m); struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in; + if (unlikely(tail_room == 0)) + return; BUG_ON(tail_room < sizeof(*msg)); msg->size = tail_room | I2400M_TX_SKIP; d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n", @@ -474,10 +528,18 @@ void i2400m_tx_close(struct i2400m *i2400m) struct i2400m_msg_hdr *tx_msg_moved; size_t aligned_size, padding, hdr_size; void *pad_buf; + unsigned num_pls; if (tx_msg->size & I2400M_TX_SKIP) /* a skipper? nothing to do */ goto out; - + num_pls = le16_to_cpu(tx_msg->num_pls); + /* We can get this situation when a new message was started + * and there was no space to add payloads before hitting the + tail (and taking padding into consideration). */ + if (num_pls == 0) { + tx_msg->size |= I2400M_TX_SKIP; + goto out; + } /* Relocate the message header * * Find the current header size, align it to 16 and if we need @@ -491,7 +553,7 @@ void i2400m_tx_close(struct i2400m *i2400m) */ hdr_size = sizeof(*tx_msg) + le16_to_cpu(tx_msg->num_pls) * sizeof(tx_msg->pld[0]); - hdr_size = ALIGN(hdr_size, I2400M_PL_PAD); + hdr_size = ALIGN(hdr_size, I2400M_PL_ALIGN); tx_msg->offset = I2400M_TX_PLD_SIZE - hdr_size; tx_msg_moved = (void *) tx_msg + tx_msg->offset; memmove(tx_msg_moved, tx_msg, hdr_size); @@ -574,7 +636,7 @@ int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len, d_fnstart(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u)\n", i2400m, buf, buf_len, pl_type); - padded_len = ALIGN(buf_len, I2400M_PL_PAD); + padded_len = ALIGN(buf_len, I2400M_PL_ALIGN); d_printf(5, dev, "padded_len %zd buf_len %zd\n", padded_len, buf_len); /* If there is no current TX message, create one; if the * current one is out of payload slots or we have a singleton, @@ -591,6 +653,8 @@ int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len, i2400m_tx_close(i2400m); i2400m_tx_new(i2400m); } + if (i2400m->tx_msg == NULL) + goto error_tx_new; if (i2400m->tx_msg->size + padded_len > I2400M_TX_BUF_SIZE / 2) { d_printf(2, dev, "TX: message too big, going new\n"); i2400m_tx_close(i2400m); @@ -773,7 +837,6 @@ void i2400m_tx_msg_sent(struct i2400m *i2400m) n = i2400m->tx_out / I2400M_TX_BUF_SIZE; i2400m->tx_out %= I2400M_TX_BUF_SIZE; i2400m->tx_in -= n * I2400M_TX_BUF_SIZE; - netif_start_queue(i2400m->wimax_dev.net_dev); spin_unlock_irqrestore(&i2400m->tx_lock, flags); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); } diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 17851321b7fd..cfdaf69da9d1 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -254,8 +254,10 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) dev_err(dev, "USB reset failed (%d), giving up!\n", result); } - } else + } else { + result = -EINVAL; /* shut gcc up in certain arches */ BUG(); + } if (result < 0 && result != -EINVAL /* device is gone */ && rt != I2400M_RT_BUS) { @@ -399,6 +401,7 @@ int i2400mu_probe(struct usb_interface *iface, i2400m->bus_dev_stop = i2400mu_bus_dev_stop; i2400m->bus_tx_kick = i2400mu_bus_tx_kick; i2400m->bus_reset = i2400mu_bus_reset; + i2400m->bus_bm_retries = I2400M_BOOT_RETRIES; i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send; i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack; i2400m->bus_fw_names = i2400mu_bus_fw_names; diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 3359497012aa..5bc00db21b24 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -146,14 +146,14 @@ config LIBERTAS_CS A driver for Marvell Libertas 8385 CompactFlash devices. config LIBERTAS_SDIO - tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards" + tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" depends on LIBERTAS && MMC ---help--- - A driver for Marvell Libertas 8385 and 8686 SDIO devices. + A driver for Marvell Libertas 8385/8686/8688 SDIO devices. config LIBERTAS_SPI tristate "Marvell Libertas 8686 SPI 802.11b/g cards" - depends on LIBERTAS && SPI && GENERIC_GPIO + depends on LIBERTAS && SPI ---help--- A driver for Marvell Libertas 8686 SPI devices. @@ -333,6 +333,7 @@ config USB_ZD1201 config USB_NET_RNDIS_WLAN tristate "Wireless RNDIS USB support" depends on USB && WLAN_80211 && EXPERIMENTAL + depends on CFG80211 select USB_USBNET select USB_NET_CDCETHER select USB_NET_RNDIS_HOST @@ -434,6 +435,13 @@ config RTL8187 Thanks to Realtek for their support! +# If possible, automatically enable LEDs for RTL8187. + +config RTL8187_LEDS + bool + depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) + default y + config ADM8211 tristate "ADMtek ADM8211 support" depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL @@ -484,9 +492,7 @@ config MWL8K will be called mwl8k. If unsure, say N. source "drivers/net/wireless/p54/Kconfig" -source "drivers/net/wireless/ath5k/Kconfig" -source "drivers/net/wireless/ath9k/Kconfig" -source "drivers/net/wireless/ar9170/Kconfig" +source "drivers/net/wireless/ath/Kconfig" source "drivers/net/wireless/ipw2x00/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" @@ -495,5 +501,7 @@ source "drivers/net/wireless/b43legacy/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" source "drivers/net/wireless/orinoco/Kconfig" +source "drivers/net/wireless/wl12xx/Kconfig" +source "drivers/net/wireless/iwmc3200wifi/Kconfig" endmenu diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 50e7fba7f0ea..7a4647e78fd3 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -55,8 +55,10 @@ obj-$(CONFIG_RT2X00) += rt2x00/ obj-$(CONFIG_P54_COMMON) += p54/ -obj-$(CONFIG_ATH5K) += ath5k/ -obj-$(CONFIG_ATH9K) += ath9k/ -obj-$(CONFIG_AR9170_USB) += ar9170/ +obj-$(CONFIG_ATH_COMMON) += ath/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o + +obj-$(CONFIG_WL12XX) += wl12xx/ + +obj-$(CONFIG_IWM) += iwmc3200wifi/ diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index f71821795018..2b9e379994a1 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1311,18 +1311,20 @@ static int adm8211_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int adm8211_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) +static void adm8211_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changes) { struct adm8211_priv *priv = dev->priv; + if (!(changes & BSS_CHANGED_BSSID)) + return; + if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) { adm8211_set_bssid(dev, conf->bssid); memcpy(priv->bssid, conf->bssid, ETH_ALEN); } - - return 0; } static void adm8211_configure_filter(struct ieee80211_hw *dev, @@ -1753,7 +1755,7 @@ static const struct ieee80211_ops adm8211_ops = { .add_interface = adm8211_add_interface, .remove_interface = adm8211_remove_interface, .config = adm8211_config, - .config_interface = adm8211_config_interface, + .bss_info_changed = adm8211_bss_info_changed, .configure_filter = adm8211_configure_filter, .get_stats = adm8211_get_stats, .get_tx_stats = adm8211_get_tx_stats, diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 9eabf4d1f2e7..c70604f0329e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1935,7 +1935,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { netif_stop_queue (dev); if (npacks > MAXTXQ) { dev->stats.tx_fifo_errors++; - return 1; + return NETDEV_TX_BUSY; } skb_queue_tail (&ai->txq, skb); return 0; @@ -2139,7 +2139,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { if (i == MAX_FIDS / 2) { dev->stats.tx_fifo_errors++; - return 1; + return NETDEV_TX_BUSY; } } /* check min length*/ @@ -2193,7 +2193,8 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { if (test_bit(FLAG_MPI, &priv->flags)) { /* Not implemented yet for MPI350 */ netif_stop_queue(dev); - return -ENETDOWN; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } if ( skb == NULL ) { @@ -2210,7 +2211,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { if (i == MAX_FIDS) { dev->stats.tx_fifo_errors++; - return 1; + return NETDEV_TX_BUSY; } } /* check min length*/ diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c index a54a67c425c8..d84caf198a23 100644 --- a/drivers/net/wireless/arlan-main.c +++ b/drivers/net/wireless/arlan-main.c @@ -1199,7 +1199,7 @@ static int arlan_tx(struct sk_buff *skb, struct net_device *dev) arlan_process_interrupt(dev); netif_stop_queue (dev); ARLAN_DEBUG_EXIT("arlan_tx"); - return 1; + return NETDEV_TX_BUSY; } diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 8d93ca4651b9..4efbdbe6d6bf 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1965,13 +1965,18 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed) return 0; } -static int at76_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) +static void at76_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed) { struct at76_priv *priv = hw->priv; at76_dbg(DBG_MAC80211, "%s():", __func__); + + if (!(changed & BSS_CHANGED_BSSID)) + return; + at76_dbg_dump(DBG_MAC80211, conf->bssid, ETH_ALEN, "bssid:"); mutex_lock(&priv->mtx); @@ -1983,8 +1988,6 @@ static int at76_config_interface(struct ieee80211_hw *hw, at76_join(priv); mutex_unlock(&priv->mtx); - - return 0; } /* must be atomic */ @@ -2076,7 +2079,7 @@ static const struct ieee80211_ops at76_ops = { .add_interface = at76_add_interface, .remove_interface = at76_remove_interface, .config = at76_config, - .config_interface = at76_config_interface, + .bss_info_changed = at76_bss_info_changed, .configure_filter = at76_configure_filter, .start = at76_mac80211_start, .stop = at76_mac80211_stop, @@ -2250,6 +2253,7 @@ static int at76_init_new_device(struct at76_priv *priv, /* mac80211 initialisation */ priv->hw->wiphy->max_scan_ssids = 1; + priv->hw->wiphy->max_scan_ie_len = 0; priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band; priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | @@ -2311,8 +2315,7 @@ static void at76_delete_device(struct at76_priv *priv) del_timer_sync(&ledtrig_tx_timer); - if (priv->rx_skb) - kfree_skb(priv->rx_skb); + kfree_skb(priv->rx_skb); usb_put_dev(priv->udev); diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig new file mode 100644 index 000000000000..d26e7b485315 --- /dev/null +++ b/drivers/net/wireless/ath/Kconfig @@ -0,0 +1,8 @@ +config ATH_COMMON + tristate "Atheros Wireless Cards" + depends on ATH5K || ATH9K || AR9170_USB + +source "drivers/net/wireless/ath/ath5k/Kconfig" +source "drivers/net/wireless/ath/ath9k/Kconfig" +source "drivers/net/wireless/ath/ar9170/Kconfig" + diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile new file mode 100644 index 000000000000..4bb0132ada37 --- /dev/null +++ b/drivers/net/wireless/ath/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_ATH5K) += ath5k/ +obj-$(CONFIG_ATH9K) += ath9k/ +obj-$(CONFIG_AR9170_USB) += ar9170/ + +obj-$(CONFIG_ATH_COMMON) += ath.o +ath-objs := main.o regd.o diff --git a/drivers/net/wireless/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig similarity index 96% rename from drivers/net/wireless/ar9170/Kconfig rename to drivers/net/wireless/ath/ar9170/Kconfig index de4281fda129..b99e3263ee6d 100644 --- a/drivers/net/wireless/ar9170/Kconfig +++ b/drivers/net/wireless/ath/ar9170/Kconfig @@ -2,6 +2,7 @@ config AR9170_USB tristate "Atheros AR9170 802.11n USB support" depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER + select ATH_COMMON help This is a driver for the Atheros "otus" 802.11n USB devices. diff --git a/drivers/net/wireless/ar9170/Makefile b/drivers/net/wireless/ath/ar9170/Makefile similarity index 100% rename from drivers/net/wireless/ar9170/Makefile rename to drivers/net/wireless/ath/ar9170/Makefile diff --git a/drivers/net/wireless/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h similarity index 75% rename from drivers/net/wireless/ar9170/ar9170.h rename to drivers/net/wireless/ath/ar9170/ar9170.h index f4fb2e94aea0..bb97981fb248 100644 --- a/drivers/net/wireless/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -40,7 +40,7 @@ #include #include -#include +#include #include #ifdef CONFIG_AR9170_LEDS #include @@ -48,6 +48,8 @@ #include "eeprom.h" #include "hw.h" +#include "../regd.h" + #define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) enum ar9170_bw { @@ -58,6 +60,21 @@ enum ar9170_bw { __AR9170_NUM_BW, }; +static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) +{ + switch (type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + return AR9170_BW_20; + case NL80211_CHAN_HT40MINUS: + return AR9170_BW_40_BELOW; + case NL80211_CHAN_HT40PLUS: + return AR9170_BW_40_ABOVE; + default: + BUG(); + } +} + enum ar9170_rf_init_mode { AR9170_RFI_NONE, AR9170_RFI_WARM, @@ -74,6 +91,7 @@ struct ar9170_led { struct led_classdev l; char name[32]; unsigned int toggled; + bool last_state; bool registered; }; @@ -84,20 +102,31 @@ enum ar9170_device_state { AR9170_STOPPED, AR9170_IDLE, AR9170_STARTED, - AR9170_ASSOCIATED, }; +struct ar9170_rxstream_mpdu_merge { + struct ar9170_rx_head plcp; + bool has_plcp; +}; + +#define AR9170_QUEUE_TIMEOUT 64 +#define AR9170_TX_TIMEOUT 8 +#define AR9170_JANITOR_DELAY 128 +#define AR9170_TX_INVALID_RATE 0xffffffff + struct ar9170 { struct ieee80211_hw *hw; struct mutex mutex; enum ar9170_device_state state; + unsigned long bad_hw_nagger; int (*open)(struct ar9170 *); void (*stop)(struct ar9170 *); - int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int); + int (*tx)(struct ar9170 *, struct sk_buff *); int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , void *, u32 , void *); void (*callback_cmd)(struct ar9170 *, u32 , void *); + int (*flush)(struct ar9170 *); /* interface mode settings */ struct ieee80211_vif *vif; @@ -117,7 +146,8 @@ struct ar9170 { struct work_struct filter_config_work; u64 cur_mc_hash, want_mc_hash; u32 cur_filter, want_filter; - unsigned int filter_changed; + unsigned long filter_changed; + unsigned int filter_state; bool sniffer_enabled; /* PHY */ @@ -151,21 +181,35 @@ struct ar9170 { /* EEPROM */ struct ar9170_eeprom eeprom; + struct ath_regulatory regulatory; - /* global tx status for unregistered Stations. */ - struct sk_buff_head global_tx_status; - struct sk_buff_head global_tx_status_waste; - struct delayed_work tx_status_janitor; + /* tx queues - as seen by hw - */ + struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; + struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; + struct delayed_work tx_janitor; + + /* rxstream mpdu merge */ + struct ar9170_rxstream_mpdu_merge rx_mpdu; + struct sk_buff *rx_failover; + int rx_failover_missing; }; struct ar9170_sta_info { - struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; }; -#define IS_STARTED(a) (a->state >= AR9170_STARTED) -#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE) +#define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) +#define AR9170_TX_FLAG_NO_ACK BIT(1) +#define AR9170_TX_FLAG_BLOCK_ACK BIT(2) -#define AR9170_FILTER_CHANGED_PROMISC BIT(0) +struct ar9170_tx_info { + unsigned long timeout; + unsigned int flags; +}; + +#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) +#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) + +#define AR9170_FILTER_CHANGED_MODE BIT(0) #define AR9170_FILTER_CHANGED_MULTICAST BIT(1) #define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2) @@ -174,8 +218,9 @@ void *ar9170_alloc(size_t priv_size); int ar9170_register(struct ar9170 *ar, struct device *pdev); void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); void ar9170_unregister(struct ar9170 *ar); -void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, - bool update_statistics, u16 tx_status); +void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); +void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); +int ar9170_nag_limiter(struct ar9170 *ar); /* MAC */ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -185,6 +230,9 @@ int ar9170_update_multicast(struct ar9170 *ar); int ar9170_update_frame_filter(struct ar9170 *ar); int ar9170_set_operating_mode(struct ar9170 *ar); int ar9170_set_beacon_timers(struct ar9170 *ar); +int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); +int ar9170_set_slot_time(struct ar9170 *ar); +int ar9170_set_basic_rates(struct ar9170 *ar); int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); int ar9170_update_beacon(struct ar9170 *ar); void ar9170_new_beacon(struct work_struct *work); diff --git a/drivers/net/wireless/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c similarity index 100% rename from drivers/net/wireless/ar9170/cmd.c rename to drivers/net/wireless/ath/ar9170/cmd.c diff --git a/drivers/net/wireless/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h similarity index 100% rename from drivers/net/wireless/ar9170/cmd.h rename to drivers/net/wireless/ath/ar9170/cmd.h diff --git a/drivers/net/wireless/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h similarity index 100% rename from drivers/net/wireless/ar9170/eeprom.h rename to drivers/net/wireless/ath/ar9170/eeprom.h diff --git a/drivers/net/wireless/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h similarity index 96% rename from drivers/net/wireless/ar9170/hw.h rename to drivers/net/wireless/ath/ar9170/hw.h index 53e250a4278f..6cbfb2f83391 100644 --- a/drivers/net/wireless/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -207,6 +207,9 @@ enum ar9170_cmd { #define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) #define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) +#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C) +#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0) + #define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) #define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) @@ -312,7 +315,7 @@ struct ar9170_rx_head { u8 plcp[12]; } __packed; -struct ar9170_rx_tail { +struct ar9170_rx_phystatus { union { struct { u8 rssi_ant0, rssi_ant1, rssi_ant2, @@ -324,6 +327,9 @@ struct ar9170_rx_tail { u8 evm_stream0[6], evm_stream1[6]; u8 phy_err; +} __packed; + +struct ar9170_rx_macstatus { u8 SAidx, DAidx; u8 error; u8 status; @@ -339,7 +345,7 @@ struct ar9170_rx_tail { #define AR9170_RX_ENC_SOFTWARE 0x8 -static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) +static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) { return (t->SAidx & 0xc0) >> 4 | (t->DAidx & 0xc0) >> 6; @@ -357,10 +363,9 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) #define AR9170_RX_STATUS_MPDU_MASK 0x30 #define AR9170_RX_STATUS_MPDU_SINGLE 0x00 -#define AR9170_RX_STATUS_MPDU_FIRST 0x10 -#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20 -#define AR9170_RX_STATUS_MPDU_LAST 0x30 - +#define AR9170_RX_STATUS_MPDU_FIRST 0x20 +#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 +#define AR9170_RX_STATUS_MPDU_LAST 0x10 #define AR9170_RX_ERROR_RXTO 0x01 #define AR9170_RX_ERROR_OVERRUN 0x02 @@ -369,9 +374,9 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) #define AR9170_RX_ERROR_WRONG_RA 0x10 #define AR9170_RX_ERROR_PLCP 0x20 #define AR9170_RX_ERROR_MMIC 0x40 +#define AR9170_RX_ERROR_FATAL 0x80 struct ar9170_cmd_tx_status { - __le16 unkn; u8 dst[ETH_ALEN]; __le32 rate; __le16 status; @@ -389,6 +394,7 @@ struct ar9170_cmd_ba_failed_count { struct ar9170_cmd_response { u8 flag; u8 type; + __le16 padding; union { struct ar9170_cmd_tx_status tx_status; @@ -414,4 +420,7 @@ enum ar9170_txq { __AR9170_NUM_TXQ, }; +#define AR9170_TXQ_DEPTH 32 +#define AR9170_TX_MAX_PENDING 128 + #endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c similarity index 94% rename from drivers/net/wireless/ar9170/led.c rename to drivers/net/wireless/ath/ar9170/led.c index 341cead7f606..63fda6cd2101 100644 --- a/drivers/net/wireless/ar9170/led.c +++ b/drivers/net/wireless/ath/ar9170/led.c @@ -74,7 +74,7 @@ static void ar9170_update_leds(struct work_struct *work) mutex_lock(&ar->mutex); for (i = 0; i < AR9170_NUM_LEDS; i++) - if (ar->leds[i].toggled) { + if (ar->leds[i].registered && ar->leds[i].toggled) { led_val |= 1 << i; tmp = 70 + 200 / (ar->leds[i].toggled); @@ -101,9 +101,15 @@ static void ar9170_led_brightness_set(struct led_classdev *led, struct ar9170_led *arl = container_of(led, struct ar9170_led, l); struct ar9170 *ar = arl->ar; - arl->toggled++; + if (unlikely(!arl->registered)) + return ; - if (likely(IS_ACCEPTING_CMD(ar) && brightness)) + if (arl->last_state != !!brightness) { + arl->toggled++; + arl->last_state = !!brightness; + } + + if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10); } @@ -136,13 +142,14 @@ void ar9170_unregister_leds(struct ar9170 *ar) { int i; - cancel_delayed_work_sync(&ar->led_work); - for (i = 0; i < AR9170_NUM_LEDS; i++) if (ar->leds[i].registered) { led_classdev_unregister(&ar->leds[i].l); ar->leds[i].registered = false; + ar->leds[i].toggled = 0; } + + cancel_delayed_work_sync(&ar->led_work); } int ar9170_register_leds(struct ar9170 *ar) diff --git a/drivers/net/wireless/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c similarity index 86% rename from drivers/net/wireless/ar9170/mac.c rename to drivers/net/wireless/ath/ar9170/mac.c index c8fa3073169f..d9f1f46de183 100644 --- a/drivers/net/wireless/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -38,6 +38,55 @@ #include "ar9170.h" #include "cmd.h" +int ar9170_set_dyn_sifs_ack(struct ar9170 *ar) +{ + u32 val; + + if (conf_is_ht40(&ar->hw->conf)) + val = 0x010a; + else { + if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) + val = 0x105; + else + val = 0x104; + } + + return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); +} + +int ar9170_set_slot_time(struct ar9170 *ar) +{ + u32 slottime = 20; + + if (!ar->vif) + return 0; + + if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || + ar->vif->bss_conf.use_short_slot) + slottime = 9; + + return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10); +} + +int ar9170_set_basic_rates(struct ar9170 *ar) +{ + u8 cck, ofdm; + + if (!ar->vif) + return 0; + + ofdm = ar->vif->bss_conf.basic_rates >> 4; + + /* FIXME: is still necessary? */ + if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) + cck = 0; + else + cck = ar->vif->bss_conf.basic_rates & 0xf; + + return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE, + ofdm << 8 | cck); +} + int ar9170_set_qos(struct ar9170 *ar) { ar9170_regwrite_begin(ar); @@ -72,6 +121,24 @@ int ar9170_set_qos(struct ar9170 *ar) return ar9170_regwrite_result(); } +static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) +{ + u32 val; + + /* don't allow AMPDU density > 8us */ + if (mpdudensity > 6) + return -EINVAL; + + /* Watch out! Otus uses slightly different density values. */ + val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + int ar9170_init_mac(struct ar9170 *ar) { ar9170_regwrite_begin(ar); @@ -265,9 +332,9 @@ int ar9170_set_operating_mode(struct ar9170 *ar) case NL80211_IFTYPE_ADHOC: pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; break; -/* case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP: pm_mode |= AR9170_MAC_REG_POWERMGT_AP; - break;*/ + break; case NL80211_IFTYPE_WDS: pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; break; @@ -296,6 +363,11 @@ int ar9170_set_operating_mode(struct ar9170 *ar) if (err) return err; + /* set AMPDU density to 8us. */ + err = ar9170_set_ampdu_density(ar, 6); + if (err) + return err; + ar9170_regwrite_begin(ar); ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); @@ -316,9 +388,9 @@ int ar9170_set_beacon_timers(struct ar9170 *ar) u32 v = 0; u32 pretbtt = 0; - v |= ar->hw->conf.beacon_int; - if (ar->vif) { + v |= ar->vif->bss_conf.beacon_int; + switch (ar->vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: @@ -326,7 +398,7 @@ int ar9170_set_beacon_timers(struct ar9170 *ar) break; case NL80211_IFTYPE_AP: v |= BIT(24); - pretbtt = (ar->hw->conf.beacon_int - 6) << 16; + pretbtt = (ar->vif->bss_conf.beacon_int - 6) << 16; break; default: break; @@ -375,10 +447,10 @@ int ar9170_update_beacon(struct ar9170 *ar) /* XXX: use skb->cb info */ if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << (3+16)) + 0x0400); + ((skb->len + 4) << (3 + 16)) + 0x0400); else ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << (3+16)) + 0x0400); + ((skb->len + 4) << 16) + 0x001b); ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c similarity index 55% rename from drivers/net/wireless/ar9170/main.c rename to drivers/net/wireless/ath/ar9170/main.c index 5996ff9f7f47..9d38cf60a0db 100644 --- a/drivers/net/wireless/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -142,73 +142,153 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { }; #undef CHAN +#define AR9170_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ + IEEE80211_HT_CAP_SGI_40 | \ + 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, }, \ + }, \ +} + static struct ieee80211_supported_band ar9170_band_2GHz = { .channels = ar9170_2ghz_chantable, .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), .bitrates = ar9170_g_ratetable, .n_bitrates = ar9170_g_ratetable_size, + .ht_cap = AR9170_HT_CAP, }; -#ifdef AR9170_QUEUE_DEBUG -/* - * In case some wants works with AR9170's crazy tx_status queueing techniques. - * He might need this rather useful probing function. - * - * NOTE: caller must hold the queue's spinlock! - */ - -static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *)txc->frame_data; - - printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] " - "mac_control:%04x, phy_control:%08x]\n", - wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control), - le32_to_cpu(txc->phy_control)); -} - -static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar, - struct sk_buff_head *queue) -{ - struct sk_buff *skb; - int i = 0; - - printk(KERN_DEBUG "---[ cut here ]---\n"); - printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n", - wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); - - skb_queue_walk(queue, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *)txc->frame_data; - - printk(KERN_DEBUG "index:%d => \n", i); - ar9170_print_txheader(ar, skb); - } - printk(KERN_DEBUG "---[ end ]---\n"); -} -#endif /* AR9170_QUEUE_DEBUG */ - static struct ieee80211_supported_band ar9170_band_5GHz = { .channels = ar9170_5ghz_chantable, .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), .bitrates = ar9170_a_ratetable, .n_bitrates = ar9170_a_ratetable_size, + .ht_cap = AR9170_HT_CAP, }; -void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, - bool valid_status, u16 tx_status) +static void ar9170_tx(struct ar9170 *ar); + +#ifdef AR9170_QUEUE_DEBUG +static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(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 " + "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, + le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), + jiffies_to_msecs(arinfo->timeout - jiffies)); +} + +static void __ar9170_dump_txqueue(struct ar9170 *ar, + struct sk_buff_head *queue) +{ + struct sk_buff *skb; + int i = 0; + + printk(KERN_DEBUG "---[ cut here ]---\n"); + printk(KERN_DEBUG "%s: %d entries in queue.\n", + wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); + + skb_queue_walk(queue, skb) { + printk(KERN_DEBUG "index:%d => \n", i++); + ar9170_print_txheader(ar, skb); + } + if (i != skb_queue_len(queue)) + printk(KERN_DEBUG "WARNING: queue frame counter " + "mismatch %d != %d\n", skb_queue_len(queue), i); + printk(KERN_DEBUG "---[ end ]---\n"); +} + +static void ar9170_dump_txqueue(struct ar9170 *ar, + struct sk_buff_head *queue) +{ + unsigned long flags; + + spin_lock_irqsave(&queue->lock, flags); + __ar9170_dump_txqueue(ar, queue); + spin_unlock_irqrestore(&queue->lock, flags); +} + +static void __ar9170_dump_txstats(struct ar9170 *ar) +{ + int i; + + printk(KERN_DEBUG "%s: QoS queue stats\n", + 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])); +} + +static void ar9170_dump_txstats(struct ar9170 *ar) { - struct ieee80211_tx_info *txinfo; - unsigned int retries = 0, queue = skb_get_queue_mapping(skb); unsigned long flags; spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[queue].len--; - if (ieee80211_queue_stopped(ar->hw, queue)) - ieee80211_wake_queue(ar->hw, queue); + __ar9170_dump_txstats(ar); spin_unlock_irqrestore(&ar->tx_stats_lock, flags); +} +#endif /* AR9170_QUEUE_DEBUG */ + +/* caller must guarantee exclusive access for _bin_ queue. */ +static void ar9170_recycle_expired(struct ar9170 *ar, + struct sk_buff_head *queue, + struct sk_buff_head *bin) +{ + struct sk_buff *skb, *old = NULL; + unsigned long flags; + + spin_lock_irqsave(&queue->lock, flags); + while ((skb = skb_peek(queue))) { + struct ieee80211_tx_info *txinfo; + struct ar9170_tx_info *arinfo; + + txinfo = IEEE80211_SKB_CB(skb); + arinfo = (void *) txinfo->rate_driver_data; + + if (time_is_before_jiffies(arinfo->timeout)) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " + "recycle \n", wiphy_name(ar->hw->wiphy), + jiffies, arinfo->timeout); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + __skb_unlink(skb, queue); + __skb_queue_tail(bin, skb); + } else { + break; + } + + if (unlikely(old == skb)) { + /* bail out - queue is shot. */ + + WARN_ON(1); + break; + } + old = skb; + } + spin_unlock_irqrestore(&queue->lock, flags); +} + +static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, + u16 tx_status) +{ + struct ieee80211_tx_info *txinfo; + unsigned int retries = 0; txinfo = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(txinfo); @@ -230,45 +310,61 @@ void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, break; } - if (valid_status) - txinfo->status.rates[0].count = retries + 1; - + txinfo->status.rates[0].count = retries + 1; skb_pull(skb, sizeof(struct ar9170_tx_control)); ieee80211_tx_status_irqsafe(ar->hw, skb); } -static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar, - const u8 *mac, - const u32 queue, - struct sk_buff_head *q) +void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data; + unsigned int queue = skb_get_queue_mapping(skb); unsigned long flags; - struct sk_buff *skb; - spin_lock_irqsave(&q->lock, flags); - skb_queue_walk(q, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - u32 txc_queue = (le32_to_cpu(txc->phy_control) & - AR9170_TX_PHY_QOS_MASK) >> - AR9170_TX_PHY_QOS_SHIFT; + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[queue].len--; - if ((queue != txc_queue) || - (compare_ether_addr(ieee80211_get_DA(hdr), mac))) - continue; - - __skb_unlink(skb, q); - spin_unlock_irqrestore(&q->lock, flags); - return skb; + if (skb_queue_empty(&ar->tx_pending[queue])) { +#ifdef AR9170_QUEUE_STOP_DEBUG + printk(KERN_DEBUG "%s: wake queue %d\n", + wiphy_name(ar->hw->wiphy), queue); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ + ieee80211_wake_queue(ar->hw, queue); + } + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { + dev_kfree_skb_any(skb); + } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); + + skb_queue_tail(&ar->tx_status[queue], skb); + } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) { + ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); + } else { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: unsupported frame flags!\n", + wiphy_name(ar->hw->wiphy)); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + dev_kfree_skb_any(skb); + } + + if (!ar->tx_stats[queue].len && + !skb_queue_empty(&ar->tx_pending[queue])) { + ar9170_tx(ar); } - spin_unlock_irqrestore(&q->lock, flags); - return NULL; } -static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, - const u32 queue) +static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, + const u8 *mac, + struct sk_buff_head *queue, + const u32 rate) { - struct ieee80211_sta *sta; + unsigned long flags; struct sk_buff *skb; /* @@ -279,85 +375,94 @@ static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, * the firmware provided (-> destination MAC, and phy_control) - * and hope that we picked the right one... */ - rcu_read_lock(); - sta = ieee80211_find_sta(ar->hw, mac); - if (likely(sta)) { - struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv; - skb = skb_dequeue(&sta_priv->tx_status[queue]); - rcu_read_unlock(); - if (likely(skb)) - return skb; - } else - rcu_read_unlock(); + spin_lock_irqsave(&queue->lock, flags); + skb_queue_walk(queue, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + u32 r; - /* scan the waste queue for candidates */ - skb = ar9170_find_skb_in_queue(ar, mac, queue, - &ar->global_tx_status_waste); - if (!skb) { - /* so it still _must_ be in the global list. */ - skb = ar9170_find_skb_in_queue(ar, mac, queue, - &ar->global_tx_status); + if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n", + wiphy_name(ar->hw->wiphy), mac, + ieee80211_get_DA(hdr)); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + continue; + } + + r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >> + AR9170_TX_PHY_MCS_SHIFT; + + if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n", + wiphy_name(ar->hw->wiphy), rate, r); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + continue; + } + + __skb_unlink(skb, queue); + spin_unlock_irqrestore(&queue->lock, flags); + return skb; } #ifdef AR9170_QUEUE_DEBUG - if (unlikely((!skb) && net_ratelimit())) { - printk(KERN_ERR "%s: ESS:[%pM] does not have any " - "outstanding frames in this queue (%d).\n", - wiphy_name(ar->hw->wiphy), mac, queue); - } + printk(KERN_ERR "%s: ESS:[%pM] does not have any " + "outstanding frames in queue.\n", + wiphy_name(ar->hw->wiphy), mac); + __ar9170_dump_txqueue(ar, queue); #endif /* AR9170_QUEUE_DEBUG */ - return skb; + spin_unlock_irqrestore(&queue->lock, flags); + + return NULL; } /* - * This worker tries to keep the global tx_status queue empty. - * So we can guarantee that incoming tx_status reports for - * unregistered stations are always synced with the actual - * frame - which we think - belongs to. + * This worker tries to keeps an maintain tx_status queues. + * So we can guarantee that incoming tx_status reports are + * actually for a pending frame. */ -static void ar9170_tx_status_janitor(struct work_struct *work) +static void ar9170_tx_janitor(struct work_struct *work) { struct ar9170 *ar = container_of(work, struct ar9170, - tx_status_janitor.work); - struct sk_buff *skb; + tx_janitor.work); + struct sk_buff_head waste; + unsigned int i; + bool resched = false; if (unlikely(!IS_STARTED(ar))) return ; - mutex_lock(&ar->mutex); - /* recycle the garbage back to mac80211... one by one. */ - while ((skb = skb_dequeue(&ar->global_tx_status_waste))) { + skb_queue_head_init(&waste); + + for (i = 0; i < __AR9170_NUM_TXQ; i++) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: dispose queued frame =>\n", - wiphy_name(ar->hw->wiphy)); - ar9170_print_txheader(ar, skb); + printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n", + wiphy_name(ar->hw->wiphy), i); + ar9170_dump_txqueue(ar, &ar->tx_pending[i]); + ar9170_dump_txqueue(ar, &ar->tx_status[i]); #endif /* AR9170_QUEUE_DEBUG */ - ar9170_handle_tx_status(ar, skb, false, - AR9170_TX_STATUS_FAILED); + + ar9170_recycle_expired(ar, &ar->tx_status[i], &waste); + ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste); + skb_queue_purge(&waste); + + if (!skb_queue_empty(&ar->tx_status[i]) || + !skb_queue_empty(&ar->tx_pending[i])) + resched = true; } - while ((skb = skb_dequeue(&ar->global_tx_status))) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: moving frame into waste queue =>\n", - wiphy_name(ar->hw->wiphy)); - - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - skb_queue_tail(&ar->global_tx_status_waste, skb); - } - - /* recall the janitor in 100ms - if there's garbage in the can. */ - if (skb_queue_len(&ar->global_tx_status_waste) > 0) - queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, - msecs_to_jiffies(100)); - - mutex_unlock(&ar->mutex); + if (resched) + queue_delayed_work(ar->hw->workqueue, + &ar->tx_janitor, + msecs_to_jiffies(AR9170_JANITOR_DELAY)); } -static void ar9170_handle_command_response(struct ar9170 *ar, - void *buf, u32 len) +void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) { struct ar9170_cmd_response *cmd = (void *) buf; @@ -381,15 +486,21 @@ static void ar9170_handle_command_response(struct ar9170 *ar, */ struct sk_buff *skb; - u32 queue = (le32_to_cpu(cmd->tx_status.rate) & - AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT; + u32 phy = le32_to_cpu(cmd->tx_status.rate); + u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> + AR9170_TX_PHY_QOS_SHIFT; +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n", + wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q); +#endif /* AR9170_QUEUE_DEBUG */ - skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue); + skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, + &ar->tx_status[q], + AR9170_TX_INVALID_RATE); if (unlikely(!skb)) return ; - ar9170_handle_tx_status(ar, skb, true, - le16_to_cpu(cmd->tx_status.status)); + ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status)); break; } @@ -429,6 +540,38 @@ static void ar9170_handle_command_response(struct ar9170 *ar, /* retransmission issue / SIFS/EIFS collision ?! */ break; + /* firmware debug */ + case 0xca: + printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4); + break; + case 0xcb: + len -= 4; + + switch (len) { + case 1: + printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n", + *((char *)buf + 4)); + break; + case 2: + printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n", + le16_to_cpup((__le16 *)((char *)buf + 4))); + break; + case 4: + printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n", + le32_to_cpup((__le32 *)((char *)buf + 4))); + break; + case 8: + printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n", + (unsigned long)le64_to_cpup( + (__le64 *)((char *)buf + 4))); + break; + } + break; + case 0xcc: + print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE, + (char *)buf + 4, len - 4); + break; + default: printk(KERN_INFO "received unhandled event %x\n", cmd->type); print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); @@ -436,214 +579,430 @@ static void ar9170_handle_command_response(struct ar9170 *ar, } } -/* - * If the frame alignment is right (or the kernel has - * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there - * is only a single MPDU in the USB frame, then we can - * submit to mac80211 the SKB directly. However, since - * there may be multiple packets in one SKB in stream - * mode, and we need to observe the proper ordering, - * this is non-trivial. - */ -static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) { - struct sk_buff *skb; - struct ar9170_rx_head *head = (void *)buf; - struct ar9170_rx_tail *tail; - struct ieee80211_rx_status status; - int mpdu_len, i; - u8 error, antennas = 0, decrypt; - __le16 fc; - int reserved; + memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); + ar->rx_mpdu.has_plcp = false; +} - if (unlikely(!IS_STARTED(ar))) - return ; +int ar9170_nag_limiter(struct ar9170 *ar) +{ + bool print_message; + + /* + * we expect all sorts of errors in promiscuous mode. + * don't bother with it, it's OK! + */ + if (ar->sniffer_enabled) + return false; + + /* + * only go for frequent errors! The hardware tends to + * do some stupid thing once in a while under load, in + * noisy environments or just for fun! + */ + if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) + print_message = true; + else + print_message = false; + + /* reset threshold for "once in a while" */ + ar->bad_hw_nagger = jiffies + HZ / 4; + return print_message; +} + +static int ar9170_rx_mac_status(struct ar9170 *ar, + struct ar9170_rx_head *head, + struct ar9170_rx_macstatus *mac, + struct ieee80211_rx_status *status) +{ + u8 error, decrypt; - /* Received MPDU */ - mpdu_len = len; - mpdu_len -= sizeof(struct ar9170_rx_head); - mpdu_len -= sizeof(struct ar9170_rx_tail); BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); - BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24); - - if (mpdu_len <= FCS_LEN) - return; - - tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len); - - for (i = 0; i < 3; i++) - if (tail->rssi[i] != 0x80) - antennas |= BIT(i); - - /* post-process RSSI */ - for (i = 0; i < 7; i++) - if (tail->rssi[i] & 0x80) - tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f; - - memset(&status, 0, sizeof(status)); - - status.band = ar->channel->band; - status.freq = ar->channel->center_freq; - status.signal = ar->noise[0] + tail->rssi_combined; - status.noise = ar->noise[0]; - status.antenna = antennas; - - switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) { - case AR9170_RX_STATUS_MODULATION_CCK: - if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE) - status.flag |= RX_FLAG_SHORTPRE; - switch (head->plcp[0]) { - case 0x0a: - status.rate_idx = 0; - break; - case 0x14: - status.rate_idx = 1; - break; - case 0x37: - status.rate_idx = 2; - break; - case 0x6e: - status.rate_idx = 3; - break; - default: - if ((!ar->sniffer_enabled) && (net_ratelimit())) - printk(KERN_ERR "%s: invalid plcp cck rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); - return; - } - break; - case AR9170_RX_STATUS_MODULATION_OFDM: - switch (head->plcp[0] & 0xF) { - case 0xB: - status.rate_idx = 0; - break; - case 0xF: - status.rate_idx = 1; - break; - case 0xA: - status.rate_idx = 2; - break; - case 0xE: - status.rate_idx = 3; - break; - case 0x9: - status.rate_idx = 4; - break; - case 0xD: - status.rate_idx = 5; - break; - case 0x8: - status.rate_idx = 6; - break; - case 0xC: - status.rate_idx = 7; - break; - default: - if ((!ar->sniffer_enabled) && (net_ratelimit())) - printk(KERN_ERR "%s: invalid plcp ofdm rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); - return; - } - if (status.band == IEEE80211_BAND_2GHZ) - status.rate_idx += 4; - break; - case AR9170_RX_STATUS_MODULATION_HT: - case AR9170_RX_STATUS_MODULATION_DUPOFDM: - /* XXX */ - - if (net_ratelimit()) - printk(KERN_ERR "%s: invalid modulation\n", - wiphy_name(ar->hw->wiphy)); - return; - } - - error = tail->error; + BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); + error = mac->error; if (error & AR9170_RX_ERROR_MMIC) { - status.flag |= RX_FLAG_MMIC_ERROR; + status->flag |= RX_FLAG_MMIC_ERROR; error &= ~AR9170_RX_ERROR_MMIC; } if (error & AR9170_RX_ERROR_PLCP) { - status.flag |= RX_FLAG_FAILED_PLCP_CRC; + status->flag |= RX_FLAG_FAILED_PLCP_CRC; error &= ~AR9170_RX_ERROR_PLCP; + + if (!(ar->filter_state & FIF_PLCPFAIL)) + return -EINVAL; } if (error & AR9170_RX_ERROR_FCS) { - status.flag |= RX_FLAG_FAILED_FCS_CRC; + status->flag |= RX_FLAG_FAILED_FCS_CRC; error &= ~AR9170_RX_ERROR_FCS; + + if (!(ar->filter_state & FIF_FCSFAIL)) + return -EINVAL; } - decrypt = ar9170_get_decrypt_type(tail); + decrypt = ar9170_get_decrypt_type(mac); if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && decrypt != AR9170_ENC_ALG_NONE) - status.flag |= RX_FLAG_DECRYPTED; + status->flag |= RX_FLAG_DECRYPTED; /* ignore wrong RA errors */ error &= ~AR9170_RX_ERROR_WRONG_RA; if (error & AR9170_RX_ERROR_DECRYPT) { error &= ~AR9170_RX_ERROR_DECRYPT; - /* * Rx decryption is done in place, * the original data is lost anyway. */ - return ; + + return -EINVAL; } /* drop any other error frames */ - if ((error) && (net_ratelimit())) { - printk(KERN_DEBUG "%s: errors: %#x\n", - wiphy_name(ar->hw->wiphy), error); - return; + if (unlikely(error)) { + /* TODO: update netdevice's RX dropped/errors statistics */ + + if (ar9170_nag_limiter(ar)) + printk(KERN_DEBUG "%s: received frame with " + "suspicious error code (%#x).\n", + wiphy_name(ar->hw->wiphy), error); + + return -EINVAL; } - buf += sizeof(struct ar9170_rx_head); - fc = *(__le16 *)buf; + status->band = ar->channel->band; + status->freq = ar->channel->center_freq; - if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc)) - reserved = 32 + 2; - else - reserved = 32; + switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { + case AR9170_RX_STATUS_MODULATION_CCK: + if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) + status->flag |= RX_FLAG_SHORTPRE; + switch (head->plcp[0]) { + case 0x0a: + status->rate_idx = 0; + break; + case 0x14: + status->rate_idx = 1; + break; + case 0x37: + status->rate_idx = 2; + break; + case 0x6e: + status->rate_idx = 3; + break; + default: + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: invalid plcp cck rate " + "(%x).\n", wiphy_name(ar->hw->wiphy), + head->plcp[0]); + return -EINVAL; + } + break; - skb = dev_alloc_skb(mpdu_len + reserved); - if (!skb) - return; + case AR9170_RX_STATUS_MODULATION_OFDM: + switch (head->plcp[0] & 0xf) { + case 0xb: + status->rate_idx = 0; + break; + case 0xf: + status->rate_idx = 1; + break; + case 0xa: + status->rate_idx = 2; + break; + case 0xe: + status->rate_idx = 3; + break; + case 0x9: + status->rate_idx = 4; + break; + case 0xd: + status->rate_idx = 5; + break; + case 0x8: + status->rate_idx = 6; + break; + case 0xc: + status->rate_idx = 7; + break; + default: + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: invalid plcp ofdm rate " + "(%x).\n", wiphy_name(ar->hw->wiphy), + head->plcp[0]); + return -EINVAL; + } + if (status->band == IEEE80211_BAND_2GHZ) + status->rate_idx += 4; + break; - skb_reserve(skb, reserved); - memcpy(skb_put(skb, mpdu_len), buf, mpdu_len); - ieee80211_rx_irqsafe(ar->hw, skb, &status); + case AR9170_RX_STATUS_MODULATION_HT: + if (head->plcp[3] & 0x80) + status->flag |= RX_FLAG_40MHZ; + if (head->plcp[6] & 0x80) + status->flag |= RX_FLAG_SHORT_GI; + + status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); + status->flag |= RX_FLAG_HT; + break; + + case AR9170_RX_STATUS_MODULATION_DUPOFDM: + /* XXX */ + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: invalid modulation\n", + wiphy_name(ar->hw->wiphy)); + return -EINVAL; + } + + return 0; +} + +static void ar9170_rx_phy_status(struct ar9170 *ar, + struct ar9170_rx_phystatus *phy, + struct ieee80211_rx_status *status) +{ + int i; + + BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); + + for (i = 0; i < 3; i++) + if (phy->rssi[i] != 0x80) + status->antenna |= BIT(i); + + /* post-process RSSI */ + for (i = 0; i < 7; i++) + if (phy->rssi[i] & 0x80) + phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; + + /* TODO: we could do something with phy_errors */ + status->signal = ar->noise[0] + phy->rssi_combined; + status->noise = ar->noise[0]; +} + +static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) +{ + struct sk_buff *skb; + int reserved = 0; + struct ieee80211_hdr *hdr = (void *) buf; + + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + reserved += NET_IP_ALIGN; + + if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) + reserved += NET_IP_ALIGN; + } + + if (ieee80211_has_a4(hdr->frame_control)) + reserved += NET_IP_ALIGN; + + reserved = 32 + (reserved & NET_IP_ALIGN); + + skb = dev_alloc_skb(len + reserved); + if (likely(skb)) { + skb_reserve(skb, reserved); + memcpy(skb_put(skb, len), buf, len); + } + + return skb; +} + +/* + * If the frame alignment is right (or the kernel has + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there + * is only a single MPDU in the USB frame, then we could + * submit to mac80211 the SKB directly. However, since + * there may be multiple packets in one SKB in stream + * mode, and we need to observe the proper ordering, + * this is non-trivial. + */ + +static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +{ + struct ar9170_rx_head *head; + struct ar9170_rx_macstatus *mac; + struct ar9170_rx_phystatus *phy = NULL; + struct ieee80211_rx_status status; + struct sk_buff *skb; + int mpdu_len; + + if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) + return ; + + /* Received MPDU */ + mpdu_len = len - sizeof(*mac); + + mac = (void *)(buf + mpdu_len); + if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { + /* this frame is too damaged and can't be used - drop it */ + + return ; + } + + switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { + case AR9170_RX_STATUS_MPDU_FIRST: + /* first mpdu packet has the plcp header */ + if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { + head = (void *) buf; + memcpy(&ar->rx_mpdu.plcp, (void *) buf, + sizeof(struct ar9170_rx_head)); + + mpdu_len -= sizeof(struct ar9170_rx_head); + buf += sizeof(struct ar9170_rx_head); + ar->rx_mpdu.has_plcp = true; + } else { + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: plcp info is clipped.\n", + wiphy_name(ar->hw->wiphy)); + return ; + } + break; + + case AR9170_RX_STATUS_MPDU_LAST: + /* last mpdu has a extra tail with phy status information */ + + if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { + mpdu_len -= sizeof(struct ar9170_rx_phystatus); + phy = (void *)(buf + mpdu_len); + } else { + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: frame tail is clipped.\n", + wiphy_name(ar->hw->wiphy)); + return ; + } + + case AR9170_RX_STATUS_MPDU_MIDDLE: + /* middle mpdus are just data */ + if (unlikely(!ar->rx_mpdu.has_plcp)) { + if (!ar9170_nag_limiter(ar)) + return ; + + printk(KERN_ERR "%s: rx stream did not start " + "with a first_mpdu frame tag.\n", + wiphy_name(ar->hw->wiphy)); + + return ; + } + + head = &ar->rx_mpdu.plcp; + break; + + case AR9170_RX_STATUS_MPDU_SINGLE: + /* single mpdu - has plcp (head) and phy status (tail) */ + head = (void *) buf; + + mpdu_len -= sizeof(struct ar9170_rx_head); + mpdu_len -= sizeof(struct ar9170_rx_phystatus); + + buf += sizeof(struct ar9170_rx_head); + phy = (void *)(buf + mpdu_len); + break; + + default: + BUG_ON(1); + break; + } + + if (unlikely(mpdu_len < FCS_LEN)) + return ; + + memset(&status, 0, sizeof(status)); + if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) + return ; + + if (phy) + 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); } void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) { - unsigned int i, tlen, resplen; + unsigned int i, tlen, resplen, wlen = 0, clen = 0; u8 *tbuf, *respbuf; tbuf = skb->data; tlen = skb->len; while (tlen >= 4) { - int clen = tbuf[1] << 8 | tbuf[0]; - int wlen = (clen + 3) & ~3; + clen = tbuf[1] << 8 | tbuf[0]; + wlen = ALIGN(clen, 4); - /* - * parse stream (if any) - */ + /* check if this is stream has a valid tag.*/ if (tbuf[2] != 0 || tbuf[3] != 0x4e) { - printk(KERN_ERR "%s: missing tag!\n", - wiphy_name(ar->hw->wiphy)); + /* + * TODO: handle the highly unlikely event that the + * corrupted stream has the TAG at the right position. + */ + + /* check if the frame can be repaired. */ + if (!ar->rx_failover_missing) { + /* this is no "short read". */ + if (ar9170_nag_limiter(ar)) { + printk(KERN_ERR "%s: missing tag!\n", + wiphy_name(ar->hw->wiphy)); + goto err_telluser; + } else + goto err_silent; + } + + if (ar->rx_failover_missing > tlen) { + if (ar9170_nag_limiter(ar)) { + printk(KERN_ERR "%s: possible multi " + "stream corruption!\n", + wiphy_name(ar->hw->wiphy)); + goto err_telluser; + } else + goto err_silent; + } + + memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { + /* + * nested ar9170_rx call! + * termination is guranteed, even when the + * combined frame also have a element with + * a bad tag. + */ + + ar->rx_failover_missing = 0; + ar9170_rx(ar, ar->rx_failover); + + skb_reset_tail_pointer(ar->rx_failover); + skb_trim(ar->rx_failover, 0); + } + return ; } + + /* check if stream is clipped */ if (wlen > tlen - 4) { - printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n", - wiphy_name(ar->hw->wiphy), clen, wlen, tlen); - print_hex_dump(KERN_DEBUG, "data: ", - DUMP_PREFIX_OFFSET, - 16, 1, tbuf, tlen, true); + if (ar->rx_failover_missing) { + /* TODO: handle double stream corruption. */ + if (ar9170_nag_limiter(ar)) { + printk(KERN_ERR "%s: double rx stream " + "corruption!\n", + wiphy_name(ar->hw->wiphy)); + goto err_telluser; + } else + goto err_silent; + } + + /* + * save incomplete data set. + * the firmware will resend the missing bits when + * the rx - descriptor comes round again. + */ + + memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); + ar->rx_failover_missing = clen - tlen; return ; } resplen = clen; @@ -668,12 +1027,44 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (i == 12) ar9170_handle_command_response(ar, respbuf, resplen); else - ar9170_handle_mpdu(ar, respbuf, resplen); + ar9170_handle_mpdu(ar, respbuf, clen); } - if (tlen) - printk(KERN_ERR "%s: buffer remains!\n", - wiphy_name(ar->hw->wiphy)); + if (tlen) { + if (net_ratelimit()) + printk(KERN_ERR "%s: %d bytes of unprocessed " + "data left in rx stream!\n", + wiphy_name(ar->hw->wiphy), tlen); + + goto err_telluser; + } + + return ; + +err_telluser: + printk(KERN_ERR "%s: damaged RX stream data [want:%d, " + "data:%d, rx:%d, pending:%d ]\n", + wiphy_name(ar->hw->wiphy), clen, wlen, tlen, + ar->rx_failover_missing); + + if (ar->rx_failover_missing) + print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, + ar->rx_failover->data, + ar->rx_failover->len); + + print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, + skb->data, skb->len); + + printk(KERN_ERR "%s: please check your hardware and cables, if " + "you see this message frequently.\n", + wiphy_name(ar->hw->wiphy)); + +err_silent: + if (ar->rx_failover_missing) { + skb_reset_tail_pointer(ar->rx_failover); + skb_trim(ar->rx_failover, 0); + ar->rx_failover_missing = 0; + } } #define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ @@ -691,10 +1082,12 @@ static int ar9170_op_start(struct ieee80211_hw *hw) mutex_lock(&ar->mutex); + ar->filter_changed = 0; + /* reinitialize queues statistics */ memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); - for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++) - ar->tx_stats[i].limit = 8; + for (i = 0; i < __AR9170_NUM_TXQ; i++) + ar->tx_stats[i].limit = AR9170_TXQ_DEPTH; /* reset QoS defaults */ AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ @@ -703,6 +1096,8 @@ 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 */ + ar->bad_hw_nagger = jiffies; + err = ar->open(ar); if (err) goto out; @@ -738,17 +1133,17 @@ static int ar9170_op_start(struct ieee80211_hw *hw) static void ar9170_op_stop(struct ieee80211_hw *hw) { struct ar9170 *ar = hw->priv; + unsigned int i; if (IS_STARTED(ar)) ar->state = AR9170_IDLE; - mutex_lock(&ar->mutex); + flush_workqueue(ar->hw->workqueue); - cancel_delayed_work_sync(&ar->tx_status_janitor); + cancel_delayed_work_sync(&ar->tx_janitor); cancel_work_sync(&ar->filter_config_work); cancel_work_sync(&ar->beacon_work); - skb_queue_purge(&ar->global_tx_status_waste); - skb_queue_purge(&ar->global_tx_status); + mutex_lock(&ar->mutex); if (IS_ACCEPTING_CMD(ar)) { ar9170_set_leds_state(ar, 0); @@ -758,51 +1153,32 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) ar->stop(ar); } + for (i = 0; i < __AR9170_NUM_TXQ; i++) { + skb_queue_purge(&ar->tx_pending[i]); + skb_queue_purge(&ar->tx_status[i]); + } mutex_unlock(&ar->mutex); } -int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) { - struct ar9170 *ar = hw->priv; struct ieee80211_hdr *hdr; struct ar9170_tx_control *txc; struct ieee80211_tx_info *info; - struct ieee80211_rate *rate = NULL; struct ieee80211_tx_rate *txrate; + struct ar9170_tx_info *arinfo; unsigned int queue = skb_get_queue_mapping(skb); - unsigned long flags = 0; - struct ar9170_sta_info *sta_info = NULL; - u32 power, chains; u16 keytype = 0; u16 len, icv = 0; - int err; - bool tx_status; - if (unlikely(!IS_STARTED(ar))) - goto err_free; + BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); hdr = (void *)skb->data; info = IEEE80211_SKB_CB(skb); len = skb->len; - spin_lock_irqsave(&ar->tx_stats_lock, flags); - if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) { - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - return NETDEV_TX_OK; - } - - ar->tx_stats[queue].len++; - ar->tx_stats[queue].count++; - if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len) - ieee80211_stop_queue(hw, queue); - - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - txc = (void *)skb_push(skb, sizeof(*txc)); - tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) || - ((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0)); - if (info->control.hw_key) { icv = info->control.hw_key->icv_len; @@ -818,7 +1194,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) break; default: WARN_ON(1); - goto err_dequeue; + goto err_out; } } @@ -835,16 +1211,65 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_NO_ACK) txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - txrate = &info->control.rates[0]; - if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + arinfo = (void *)info->rate_driver_data; + arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + if (unlikely(!info->control.sta)) + goto err_out; + + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); + arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; + goto out; + } + + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); + /* + * WARNING: + * Putting the QoS queue bits into an unexplored territory is + * certainly not elegant. + * + * In my defense: This idea provides a reasonable way to + * smuggle valuable information to the tx_status callback. + * Also, the idea behind this bit-abuse came straight from + * the original driver code. + */ + + txc->phy_control |= + cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); + arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; + } else { + arinfo->flags = AR9170_TX_FLAG_NO_ACK; + } + +out: + return 0; + +err_out: + skb_pull(skb, sizeof(*txc)); + return -EINVAL; +} + +static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc; + struct ieee80211_tx_info *info; + struct ieee80211_rate *rate = NULL; + struct ieee80211_tx_rate *txrate; + u32 power, chains; + + txc = (void *) skb->data; + info = IEEE80211_SKB_CB(skb); + txrate = &info->control.rates[0]; + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); @@ -864,9 +1289,12 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) u32 r = txrate->idx; u8 *txpower; + /* heavy clip control */ + txc->phy_control |= cpu_to_le32((r & 0x7) << 7); + r <<= AR9170_TX_PHY_MCS_SHIFT; - if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK)) - goto err_dequeue; + BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK); + txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); @@ -928,53 +1356,154 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) chains = AR9170_TX_PHY_TXCHAIN_1; } txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); +} - if (tx_status) { - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); - /* - * WARNING: - * Putting the QoS queue bits into an unexplored territory is - * certainly not elegant. - * - * In my defense: This idea provides a reasonable way to - * smuggle valuable information to the tx_status callback. - * Also, the idea behind this bit-abuse came straight from - * the original driver code. - */ +static void ar9170_tx(struct ar9170 *ar) +{ + struct sk_buff *skb; + unsigned long flags; + struct ieee80211_tx_info *info; + struct ar9170_tx_info *arinfo; + unsigned int i, frames, frames_failed, remaining_space; + int err; + bool schedule_garbagecollector = false; - txc->phy_control |= - cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); + BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); - if (info->control.sta) { - sta_info = (void *) info->control.sta->drv_priv; - skb_queue_tail(&sta_info->tx_status[queue], skb); - } else { - skb_queue_tail(&ar->global_tx_status, skb); + if (unlikely(!IS_STARTED(ar))) + return ; - queue_delayed_work(ar->hw->workqueue, - &ar->tx_status_janitor, - msecs_to_jiffies(100)); + remaining_space = AR9170_TX_MAX_PENDING; + + for (i = 0; i < __AR9170_NUM_TXQ; i++) { + spin_lock_irqsave(&ar->tx_stats_lock, flags); + if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: queue %d full\n", + wiphy_name(ar->hw->wiphy), i); + + __ar9170_dump_txstats(ar); + printk(KERN_DEBUG "stuck frames: ===> \n"); + ar9170_dump_txqueue(ar, &ar->tx_pending[i]); + ar9170_dump_txqueue(ar, &ar->tx_status[i]); +#endif /* AR9170_QUEUE_DEBUG */ + ieee80211_stop_queue(ar->hw, i); + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + continue; + } + + frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, + skb_queue_len(&ar->tx_pending[i])); + + if (remaining_space < frames) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: tx quota reached queue:%d, " + "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; + } + + ar->tx_stats[i].len += frames; + ar->tx_stats[i].count += frames; + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + if (!frames) + continue; + + frames_failed = 0; + while (frames) { + skb = skb_dequeue(&ar->tx_pending[i]); + if (unlikely(!skb)) { + frames_failed += frames; + frames = 0; + break; + } + + info = IEEE80211_SKB_CB(skb); + arinfo = (void *) info->rate_driver_data; + + /* TODO: cancel stuck frames */ + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); + +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: send frame q:%d =>\n", + wiphy_name(ar->hw->wiphy), i); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + + err = ar->tx(ar, skb); + if (unlikely(err)) { + frames_failed++; + dev_kfree_skb_any(skb); + } else { + remaining_space--; + schedule_garbagecollector = true; + } + + frames--; + } + +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n", + wiphy_name(ar->hw->wiphy), i); + + printk(KERN_DEBUG "%s: unprocessed pending frames left:\n", + wiphy_name(ar->hw->wiphy)); + ar9170_dump_txqueue(ar, &ar->tx_pending[i]); +#endif /* AR9170_QUEUE_DEBUG */ + + if (unlikely(frames_failed)) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: frames failed =>\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; + ieee80211_wake_queue(ar->hw, i); + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); } } - err = ar->tx(ar, skb, tx_status, 0); - if (unlikely(tx_status && err)) { - if (info->control.sta) - skb_unlink(skb, &sta_info->tx_status[queue]); - else - skb_unlink(skb, &ar->global_tx_status); + if (schedule_garbagecollector) + queue_delayed_work(ar->hw->workqueue, + &ar->tx_janitor, + msecs_to_jiffies(AR9170_JANITOR_DELAY)); +} + +int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ar9170 *ar = hw->priv; + struct ieee80211_tx_info *info; + + if (unlikely(!IS_STARTED(ar))) + goto err_free; + + if (unlikely(ar9170_tx_prepare(ar, skb))) + goto err_free; + + 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; + } else { + unsigned int queue = skb_get_queue_mapping(skb); + + ar9170_tx_prepare_phy(ar, skb); + skb_queue_tail(&ar->tx_pending[queue], skb); } + ar9170_tx(ar); return NETDEV_TX_OK; -err_dequeue: - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[queue].len--; - ar->tx_stats[queue].count--; - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - err_free: - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -1037,11 +1566,6 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&ar->mutex); - if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { - /* TODO */ - err = 0; - } - if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /* TODO */ err = 0; @@ -1068,48 +1592,28 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) goto out; } - if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) { + if (changed & BSS_CHANGED_BEACON_INT) { err = ar9170_set_beacon_timers(ar); if (err) goto out; } if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - err = ar9170_set_channel(ar, hw->conf.channel, - AR9170_RFI_NONE, AR9170_BW_20); - if (err) - goto out; + /* adjust slot time for 5 GHz */ - if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) - err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, - 9 << 10); - } - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static int ar9170_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (conf->changed & IEEE80211_IFCC_BSSID) { - memcpy(ar->bssid, conf->bssid, ETH_ALEN); - err = ar9170_set_operating_mode(ar); - } - - if (conf->changed & IEEE80211_IFCC_BEACON) { - err = ar9170_update_beacon(ar); - + err = ar9170_set_slot_time(ar); + if (err) + goto out; + + err = ar9170_set_dyn_sifs_ack(ar); + if (err) + goto out; + + err = ar9170_set_channel(ar, hw->conf.channel, + AR9170_RFI_NONE, + nl80211_to_ar9170(hw->conf.channel_type)); if (err) goto out; - err = ar9170_set_beacon_timers(ar); } out: @@ -1123,24 +1627,30 @@ static void ar9170_set_filters(struct work_struct *work) filter_config_work); int err; - mutex_lock(&ar->mutex); if (unlikely(!IS_STARTED(ar))) - goto unlock; + return ; - if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) { + mutex_lock(&ar->mutex); + if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE, + &ar->filter_changed)) { err = ar9170_set_operating_mode(ar); if (err) goto unlock; } - if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) { + if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST, + &ar->filter_changed)) { err = ar9170_update_multicast(ar); if (err) goto unlock; } - if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER) + if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, + &ar->filter_changed)) { err = ar9170_update_frame_filter(ar); + if (err) + goto unlock; + } unlock: mutex_unlock(&ar->mutex); @@ -1155,8 +1665,8 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, /* mask supported flags */ *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | - FIF_PROMISC_IN_BSS; - + FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; + ar->filter_state = *new_flags; /* * We can support more by setting the sniffer bit and * then checking the error flags, later. @@ -1170,7 +1680,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, int i; /* always get broadcast frames */ - mchash = 1ULL << (0xff>>2); + mchash = 1ULL << (0xff >> 2); for (i = 0; i < mc_count; i++) { if (WARN_ON(!mclist)) @@ -1180,7 +1690,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, } ar->want_mc_hash = mchash; } - ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST; + set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed); } if (changed_flags & FIF_CONTROL) { @@ -1196,12 +1706,14 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, else ar->want_filter = ar->cur_filter & ~filter; - ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER; + set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, + &ar->filter_changed); } if (changed_flags & FIF_PROMISC_IN_BSS) { ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; - ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC; + set_bit(AR9170_FILTER_CHANGED_MODE, + &ar->filter_changed); } if (likely(IS_STARTED(ar))) @@ -1218,48 +1730,54 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&ar->mutex); - ar9170_regwrite_begin(ar); + if (changed & BSS_CHANGED_BSSID) { + memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN); + err = ar9170_set_operating_mode(ar); + if (err) + goto out; + } + + if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) { + err = ar9170_update_beacon(ar); + if (err) + goto out; + + err = ar9170_set_beacon_timers(ar); + if (err) + goto out; + } if (changed & BSS_CHANGED_ASSOC) { - ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state; - #ifndef CONFIG_AR9170_LEDS /* enable assoc LED. */ err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); #endif /* CONFIG_AR9170_LEDS */ } + if (changed & BSS_CHANGED_BEACON_INT) { + err = ar9170_set_beacon_timers(ar); + if (err) + goto out; + } + if (changed & BSS_CHANGED_HT) { /* TODO */ err = 0; } if (changed & BSS_CHANGED_ERP_SLOT) { - u32 slottime = 20; - - if (bss_conf->use_short_slot) - slottime = 9; - - ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10); + err = ar9170_set_slot_time(ar); + if (err) + goto out; } if (changed & BSS_CHANGED_BASIC_RATES) { - u32 cck, ofdm; - - if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) { - ofdm = bss_conf->basic_rates; - cck = 0; - } else { - /* four cck rates */ - cck = bss_conf->basic_rates & 0xf; - ofdm = bss_conf->basic_rates >> 4; - } - ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, - ofdm << 8 | cck); + err = ar9170_set_basic_rates(ar); + if (err) + goto out; } - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); +out: mutex_unlock(&ar->mutex); } @@ -1298,7 +1816,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (key->alg) { case ALG_WEP: - if (key->keylen == LEN_WEP40) + if (key->keylen == WLAN_KEY_LEN_WEP40) ktype = AR9170_ENC_ALG_WEP64; else ktype = AR9170_ENC_ALG_WEP128; @@ -1411,43 +1929,6 @@ 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 *info = (void *) sta->drv_priv; - struct sk_buff *skb; - unsigned int i; - - switch (cmd) { - case STA_NOTIFY_ADD: - for (i = 0; i < ar->hw->queues; i++) - skb_queue_head_init(&info->tx_status[i]); - break; - - case STA_NOTIFY_REMOVE: - - /* - * transfer all outstanding frames that need a tx_status - * reports to the global tx_status queue - */ - - for (i = 0; i < ar->hw->queues; i++) { - while ((skb = skb_dequeue(&info->tx_status[i]))) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: queueing frame in " - "global tx_status queue =>\n", - wiphy_name(ar->hw->wiphy)); - - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - skb_queue_tail(&ar->global_tx_status, skb); - } - } - queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, - msecs_to_jiffies(100)); - break; - - default: - break; - } } static int ar9170_get_stats(struct ieee80211_hw *hw, @@ -1486,7 +1967,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, int ret; mutex_lock(&ar->mutex); - if ((param) && !(queue > ar->hw->queues)) { + if ((param) && !(queue > __AR9170_NUM_TXQ)) { memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], param, sizeof(*param)); @@ -1498,6 +1979,24 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, return ret; } +static int ar9170_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) +{ + switch (action) { + 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; + default: + return -EOPNOTSUPP; + } +} + static const struct ieee80211_ops ar9170_ops = { .start = ar9170_op_start, .stop = ar9170_op_stop, @@ -1505,7 +2004,6 @@ static const struct ieee80211_ops ar9170_ops = { .add_interface = ar9170_op_add_interface, .remove_interface = ar9170_op_remove_interface, .config = ar9170_op_config, - .config_interface = ar9170_op_config_interface, .configure_filter = ar9170_op_configure_filter, .conf_tx = ar9170_conf_tx, .bss_info_changed = ar9170_op_bss_info_changed, @@ -1514,29 +2012,45 @@ static const struct ieee80211_ops ar9170_ops = { .sta_notify = ar9170_sta_notify, .get_stats = ar9170_get_stats, .get_tx_stats = ar9170_get_tx_stats, + .ampdu_action = ar9170_ampdu_action, }; void *ar9170_alloc(size_t priv_size) { struct ieee80211_hw *hw; struct ar9170 *ar; + struct sk_buff *skb; int i; + /* + * this buffer is used for rx stream reconstruction. + * Under heavy load this device (or the transport layer?) + * tends to split the streams into seperate rx descriptors. + */ + + skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); + if (!skb) + goto err_nomem; + hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); if (!hw) - return ERR_PTR(-ENOMEM); + goto err_nomem; ar = hw->priv; ar->hw = hw; + ar->rx_failover = skb; mutex_init(&ar->mutex); spin_lock_init(&ar->cmdlock); spin_lock_init(&ar->tx_stats_lock); - skb_queue_head_init(&ar->global_tx_status); - skb_queue_head_init(&ar->global_tx_status_waste); + for (i = 0; i < __AR9170_NUM_TXQ; i++) { + skb_queue_head_init(&ar->tx_status[i]); + skb_queue_head_init(&ar->tx_pending[i]); + } + ar9170_rx_reset_rx_mpdu(ar); INIT_WORK(&ar->filter_config_work, ar9170_set_filters); INIT_WORK(&ar->beacon_work, ar9170_new_beacon); - INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor); + INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); /* all hw supports 2.4 GHz, so set channel to 1 by default */ ar->channel = &ar9170_2ghz_chantable[0]; @@ -1561,6 +2075,10 @@ void *ar9170_alloc(size_t priv_size) ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ return ar; + +err_nomem: + kfree_skb(skb); + return ERR_PTR(-ENOMEM); } static int ar9170_read_eeprom(struct ar9170 *ar) @@ -1619,12 +2137,24 @@ static int ar9170_read_eeprom(struct ar9170 *ar) else ar->hw->channel_change_time = 80 * 1000; + ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); + ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); + /* second part of wiphy init */ SET_IEEE80211_PERM_ADDR(ar->hw, addr); return bands ? 0 : -EINVAL; } +static int ar9170_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ar9170 *ar = hw->priv; + + return ath_reg_notifier_apply(wiphy, request, &ar->regulatory); +} + int ar9170_register(struct ar9170 *ar, struct device *pdev) { int err; @@ -1634,10 +2164,18 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) if (err) goto err_out; + err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, + ar9170_reg_notifier); + if (err) + goto err_out; + err = ieee80211_register_hw(ar->hw); if (err) goto err_out; + if (!ath_is_world_regd(&ar->regulatory)) + regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); + err = ar9170_init_leds(ar); if (err) goto err_unreg; @@ -1666,6 +2204,7 @@ void ar9170_unregister(struct ar9170 *ar) ar9170_unregister_leds(ar); #endif /* CONFIG_AR9170_LEDS */ + kfree_skb(ar->rx_failover); ieee80211_unregister_hw(ar->hw); mutex_destroy(&ar->mutex); } diff --git a/drivers/net/wireless/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c similarity index 99% rename from drivers/net/wireless/ar9170/phy.c rename to drivers/net/wireless/ath/ar9170/phy.c index 6ce20754b8e7..df86f70cd817 100644 --- a/drivers/net/wireless/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -401,7 +401,7 @@ int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) int i, err; u32 val; bool is_2ghz = band == IEEE80211_BAND_2GHZ; - bool is_40mhz = false; /* XXX: for now */ + bool is_40mhz = conf_is_ht40(&ar->hw->conf); ar9170_regwrite_begin(ar); @@ -1200,7 +1200,7 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, return -ENOSYS; } - if (0 /* 2 streams capable */) + if (ar->eeprom.tx_mask != 1) tmp |= 0x100; err = ar9170_write_reg(ar, 0x1c5804, tmp); @@ -1214,7 +1214,7 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, freqpar = ar9170_get_hw_dyn_params(channel, bw); vals[0] = cpu_to_le32(channel->center_freq * 1000); - vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1); + vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf)); vals[2] = cpu_to_le32(offs << 2 | 1); vals[3] = cpu_to_le32(freqpar->coeff_exp); vals[4] = cpu_to_le32(freqpar->coeff_man); diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c similarity index 83% rename from drivers/net/wireless/ar9170/usb.c rename to drivers/net/wireless/ath/ar9170/usb.c index fddda477095c..754b1f8d8da9 100644 --- a/drivers/net/wireless/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -51,9 +51,14 @@ MODULE_AUTHOR("Johannes Berg "); MODULE_AUTHOR("Christian Lamparter "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); +MODULE_FIRMWARE("ar9170.fw"); MODULE_FIRMWARE("ar9170-1.fw"); MODULE_FIRMWARE("ar9170-2.fw"); +enum ar9170_requirements { + AR9170_REQ_FW1_ONLY = 1, +}; + static struct usb_device_id ar9170_usb_ids[] = { /* Atheros 9170 */ { USB_DEVICE(0x0cf3, 0x9170) }, @@ -81,25 +86,74 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x2019, 0x5304) }, /* IO-Data WNGDNUS2 */ { USB_DEVICE(0x04bb, 0x093f) }, + /* AVM FRITZ!WLAN USB Stick N */ + { USB_DEVICE(0x057C, 0x8401) }, + /* AVM FRITZ!WLAN USB Stick N 2.4 */ + { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, /* terminate */ {} }; MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); -static void ar9170_usb_tx_urb_complete_free(struct urb *urb) +static void ar9170_usb_submit_urb(struct ar9170_usb *aru) +{ + struct urb *urb; + unsigned long flags; + int err; + + if (unlikely(!IS_STARTED(&aru->common))) + return ; + + spin_lock_irqsave(&aru->tx_urb_lock, flags); + if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { + spin_unlock_irqrestore(&aru->tx_urb_lock, flags); + return ; + } + aru->tx_submitted_urbs++; + + urb = usb_get_from_anchor(&aru->tx_pending); + if (!urb) { + aru->tx_submitted_urbs--; + spin_unlock_irqrestore(&aru->tx_urb_lock, flags); + + return ; + } + spin_unlock_irqrestore(&aru->tx_urb_lock, flags); + + aru->tx_pending_urbs--; + usb_anchor_urb(urb, &aru->tx_submitted); + + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err)) { + if (ar9170_nag_limiter(&aru->common)) + dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", + err); + + usb_unanchor_urb(urb); + aru->tx_submitted_urbs--; + ar9170_tx_callback(&aru->common, urb->context); + } + + usb_free_urb(urb); +} + +static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) { struct sk_buff *skb = urb->context; struct ar9170_usb *aru = (struct ar9170_usb *) usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - if (!aru) { + if (unlikely(!aru)) { dev_kfree_skb_irq(skb); return ; } - ar9170_handle_tx_status(&aru->common, skb, false, - AR9170_TX_STATUS_COMPLETE); + aru->tx_submitted_urbs--; + + ar9170_tx_callback(&aru->common, skb); + + ar9170_usb_submit_urb(aru); } static void ar9170_usb_tx_urb_complete(struct urb *urb) @@ -126,8 +180,8 @@ static void ar9170_usb_irq_completed(struct urb *urb) goto resubmit; } - print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET, - urb->transfer_buffer, urb->actual_length); + ar9170_handle_command_response(&aru->common, urb->transfer_buffer, + urb->actual_length); resubmit: usb_anchor_urb(urb, &aru->rx_submitted); @@ -177,16 +231,15 @@ static void ar9170_usb_rx_completed(struct urb *urb) usb_anchor_urb(urb, &aru->rx_submitted); err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) { + if (unlikely(err)) { usb_unanchor_urb(urb); - dev_kfree_skb_irq(skb); + goto free; } return ; free: dev_kfree_skb_irq(skb); - return; } static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, @@ -282,21 +335,47 @@ static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) return err; } -static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) +static int ar9170_usb_flush(struct ar9170 *ar) { - int ret; + struct ar9170_usb *aru = (void *) ar; + struct urb *urb; + int ret, err = 0; - aru->common.state = AR9170_UNKNOWN_STATE; + if (IS_STARTED(ar)) + aru->common.state = AR9170_IDLE; - usb_unlink_anchored_urbs(&aru->tx_submitted); + usb_wait_anchor_empty_timeout(&aru->tx_pending, + msecs_to_jiffies(800)); + while ((urb = usb_get_from_anchor(&aru->tx_pending))) { + ar9170_tx_callback(&aru->common, (void *) urb->context); + usb_free_urb(urb); + } - /* give the LED OFF command and the deauth frame a chance to air. */ + /* lets wait a while until the tx - queues are dried out */ ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, msecs_to_jiffies(100)); if (ret == 0) - dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); - usb_poison_anchored_urbs(&aru->tx_submitted); + err = -ETIMEDOUT; + usb_kill_anchored_urbs(&aru->tx_submitted); + + if (IS_ACCEPTING_CMD(ar)) + aru->common.state = AR9170_STARTED; + + return err; +} + +static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) +{ + int err; + + aru->common.state = AR9170_UNKNOWN_STATE; + + err = ar9170_usb_flush(&aru->common); + if (err) + dev_err(&aru->udev->dev, "stuck tx urbs!\n"); + + usb_poison_anchored_urbs(&aru->tx_submitted); usb_poison_anchored_urbs(&aru->rx_submitted); } @@ -337,7 +416,7 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, usb_anchor_urb(urb, &aru->tx_submitted); err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) { + if (unlikely(err)) { usb_unanchor_urb(urb); usb_free_urb(urb); goto err_unbuf; @@ -350,7 +429,7 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, goto err_unbuf; } - if (outlen >= 0 && aru->readlen != outlen) { + if (aru->readlen != outlen) { err = -EMSGSIZE; goto err_unbuf; } @@ -380,12 +459,10 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, return err; } -static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, - bool txstatus_needed, unsigned int extra_len) +static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) { struct ar9170_usb *aru = (struct ar9170_usb *) ar; struct urb *urb; - int err; if (unlikely(!IS_STARTED(ar))) { /* Seriously, what were you drink... err... thinking!? */ @@ -398,18 +475,17 @@ static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, usb_fill_bulk_urb(urb, aru->udev, usb_sndbulkpipe(aru->udev, AR9170_EP_TX), - skb->data, skb->len + extra_len, (txstatus_needed ? - ar9170_usb_tx_urb_complete : - ar9170_usb_tx_urb_complete_free), skb); + skb->data, skb->len, + ar9170_usb_tx_urb_complete_frame, skb); urb->transfer_flags |= URB_ZERO_PACKET; - usb_anchor_urb(urb, &aru->tx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) - usb_unanchor_urb(urb); + usb_anchor_urb(urb, &aru->tx_pending); + aru->tx_pending_urbs++; usb_free_urb(urb); - return err; + + ar9170_usb_submit_urb(aru); + return 0; } static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) @@ -418,7 +494,7 @@ static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) unsigned long flags; u32 in, out; - if (!buffer) + if (unlikely(!buffer)) return ; in = le32_to_cpup((__le32 *)buffer); @@ -504,17 +580,29 @@ static int ar9170_usb_request_firmware(struct ar9170_usb *aru) { int err = 0; + err = request_firmware(&aru->firmware, "ar9170.fw", + &aru->udev->dev); + if (!err) { + aru->init_values = NULL; + return 0; + } + + if (aru->req_one_stage_fw) { + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found and is required for this device\n"); + return -EINVAL; + } + + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found, trying old firmware...\n"); + err = request_firmware(&aru->init_values, "ar9170-1.fw", &aru->udev->dev); - if (err) { - dev_err(&aru->udev->dev, "file with init values not found.\n"); - return err; - } err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); if (err) { release_firmware(aru->init_values); - dev_err(&aru->udev->dev, "firmware file not found.\n"); + dev_err(&aru->udev->dev, "file with init values not found.\n"); return err; } @@ -548,6 +636,9 @@ static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) { int err; + if (!aru->init_values) + goto upload_fw_start; + /* First, upload initial values to device RAM */ err = ar9170_usb_upload(aru, aru->init_values->data, aru->init_values->size, 0x102800, false); @@ -557,6 +648,8 @@ static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) return err; } +upload_fw_start: + /* Then, upload the firmware itself and start it */ return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, 0x200000, true); @@ -592,10 +685,8 @@ static void ar9170_usb_stop(struct ar9170 *ar) if (IS_ACCEPTING_CMD(ar)) aru->common.state = AR9170_STOPPED; - /* lets wait a while until the tx - queues are dried out */ - ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, - msecs_to_jiffies(1000)); - if (ret == 0) + ret = ar9170_usb_flush(ar); + if (ret) dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); usb_poison_anchored_urbs(&aru->tx_submitted); @@ -656,6 +747,15 @@ static int ar9170_usb_init_device(struct ar9170_usb *aru) return err; } +static bool ar9170_requires_one_stage(const struct usb_device_id *id) +{ + if (!id->driver_info) + return false; + if (id->driver_info == AR9170_REQ_FW1_ONLY) + return true; + return false; +} + static int ar9170_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -676,19 +776,30 @@ static int ar9170_usb_probe(struct usb_interface *intf, aru->intf = intf; ar = &aru->common; + aru->req_one_stage_fw = ar9170_requires_one_stage(id); + usb_set_intfdata(intf, aru); SET_IEEE80211_DEV(ar->hw, &udev->dev); init_usb_anchor(&aru->rx_submitted); + init_usb_anchor(&aru->tx_pending); init_usb_anchor(&aru->tx_submitted); init_completion(&aru->cmd_wait); + spin_lock_init(&aru->tx_urb_lock); + + aru->tx_pending_urbs = 0; + aru->tx_submitted_urbs = 0; aru->common.stop = ar9170_usb_stop; + aru->common.flush = ar9170_usb_flush; aru->common.open = ar9170_usb_open; aru->common.tx = ar9170_usb_tx; aru->common.exec_cmd = ar9170_usb_exec_cmd; aru->common.callback_cmd = ar9170_usb_callback_cmd; +#ifdef CONFIG_PM + udev->reset_resume = 1; +#endif /* CONFIG_PM */ err = ar9170_usb_reset(aru); if (err) goto err_freehw; @@ -773,11 +884,6 @@ static int ar9170_resume(struct usb_interface *intf) usb_unpoison_anchored_urbs(&aru->rx_submitted); usb_unpoison_anchored_urbs(&aru->tx_submitted); - /* - * FIXME: firmware upload will fail on resume. - * but this is better than a hang! - */ - err = ar9170_usb_init_device(aru); if (err) goto err_unrx; @@ -805,6 +911,7 @@ static struct usb_driver ar9170_driver = { #ifdef CONFIG_PM .suspend = ar9170_suspend, .resume = ar9170_resume, + .reset_resume = ar9170_resume, #endif /* CONFIG_PM */ }; diff --git a/drivers/net/wireless/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h similarity index 92% rename from drivers/net/wireless/ar9170/usb.h rename to drivers/net/wireless/ath/ar9170/usb.h index f5852924cd64..d098f4d5d2f2 100644 --- a/drivers/net/wireless/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include "eeprom.h" @@ -51,6 +51,7 @@ #include "ar9170.h" #define AR9170_NUM_RX_URBS 16 +#define AR9170_NUM_TX_URBS 8 struct firmware; @@ -60,9 +61,15 @@ struct ar9170_usb { struct usb_interface *intf; struct usb_anchor rx_submitted; + struct usb_anchor tx_pending; struct usb_anchor tx_submitted; - spinlock_t cmdlock; + bool req_one_stage_fw; + + spinlock_t tx_urb_lock; + unsigned int tx_submitted_urbs; + unsigned int tx_pending_urbs; + struct completion cmd_wait; int readlen; u8 *readbuf; diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig similarity index 98% rename from drivers/net/wireless/ath5k/Kconfig rename to drivers/net/wireless/ath/ath5k/Kconfig index 75383a5df992..509b6f94f73b 100644 --- a/drivers/net/wireless/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,6 +1,7 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + select ATH_COMMON select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile similarity index 93% rename from drivers/net/wireless/ath5k/Makefile rename to drivers/net/wireless/ath/ath5k/Makefile index 84a74c5248e5..090dc6d268a3 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile @@ -11,5 +11,6 @@ ath5k-y += reset.o ath5k-y += attach.o ath5k-y += base.o ath5k-y += led.o +ath5k-y += rfkill.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h similarity index 97% rename from drivers/net/wireless/ath5k/ath5k.h rename to drivers/net/wireless/ath/ath5k/ath5k.h index 0b616e72fe05..6358233bac99 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -27,6 +27,8 @@ #include #include +#include "../regd.h" + /* RX/TX descriptor hw structs * TODO: Driver part should only see sw structs */ #include "desc.h" @@ -207,7 +209,6 @@ #define AR5K_TUNE_MAX_TXPOWER 63 #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false -#define AR5K_TUNE_ANT_DIVERSITY true #define AR5K_TUNE_HWTXTRIES 4 #define AR5K_INIT_CARR_SENSE_EN 1 @@ -418,6 +419,17 @@ enum ath5k_driver_mode { AR5K_MODE_MAX = 5 }; +enum ath5k_ant_mode { + AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ + AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ + AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ + AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ + AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ + AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ + AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ + AR5K_ANTMODE_MAX, +}; + /****************\ TX DEFINITIONS @@ -1039,8 +1051,6 @@ struct ath5k_hw { bool ah_5ghz; bool ah_2ghz; -#define ah_regdomain ah_capabilities.cap_regdomain.reg_current -#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw #define ah_modes ah_capabilities.cap_mode #define ah_ee_version ah_capabilities.cap_eeprom.ee_version @@ -1051,8 +1061,11 @@ struct ath5k_hw { bool ah_software_retry; u32 ah_limit_tx_retries; - u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; - bool ah_ant_diversity; + /* Antenna Control */ + u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; + u8 ah_ant_mode; + u8 ah_tx_ant; + u8 ah_def_ant; u8 ah_sta_id[ETH_ALEN]; @@ -1065,6 +1078,7 @@ struct ath5k_hw { u32 ah_gpio[AR5K_MAX_GPIO]; int ah_gpio_npins; + struct ath_regulatory ah_regulatory; struct ath5k_capabilities ah_capabilities; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; @@ -1099,11 +1113,12 @@ struct ath5k_hw { /* Values in 0.25dB units */ s16 txp_min_pwr; s16 txp_max_pwr; + /* Values in 0.5dB units */ s16 txp_offset; s16 txp_ofdm; - /* Values in dB units */ - s16 txp_cck_ofdm_pwr_delta; s16 txp_cck_ofdm_gainf_delta; + /* Value in dB units */ + s16 txp_cck_ofdm_pwr_delta; } ah_txpower; struct { @@ -1241,6 +1256,10 @@ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); +/* rfkill Functions */ +extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah); +extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); + /* Misc functions */ int ath5k_hw_set_capabilities(struct ath5k_hw *ah); extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); @@ -1263,14 +1282,21 @@ 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); +/* Spur mitigation */ +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel); +void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, + struct ieee80211_channel *channel); /* Misc PHY functions */ extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); -extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); +/* Antenna control */ +extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); +extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); +extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); /* TX power setup */ extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); -extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); +extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); /* * Functions used internaly diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c similarity index 99% rename from drivers/net/wireless/ath5k/attach.c rename to drivers/net/wireless/ath/ath5k/attach.c index 70d376c63aac..c41ef58393e7 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -133,7 +133,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_cw_min = AR5K_TUNE_CWMIN; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_software_retry = false; - ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; /* * Set the mac version based on the pci id diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c similarity index 93% rename from drivers/net/wireless/ath5k/base.c rename to drivers/net/wireless/ath/ath5k/base.c index 32df27a9c7a2..55f7de09d134 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -61,9 +61,13 @@ static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static int modparam_all_channels; +module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); +MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); + /******************\ * Internal defines * @@ -223,9 +227,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); -static int ath5k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, @@ -241,8 +242,8 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw, static u64 ath5k_get_tsf(struct ieee80211_hw *hw); static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); static void ath5k_reset_tsf(struct ieee80211_hw *hw); -static int ath5k_beacon_update(struct ath5k_softc *sc, - struct sk_buff *skb); +static int ath5k_beacon_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); static void ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -255,7 +256,6 @@ static const struct ieee80211_ops ath5k_hw_ops = { .add_interface = ath5k_add_interface, .remove_interface = ath5k_remove_interface, .config = ath5k_config, - .config_interface = ath5k_config_interface, .configure_filter = ath5k_configure_filter, .set_key = ath5k_set_key, .get_stats = ath5k_get_stats, @@ -516,6 +516,7 @@ ath5k_pci_probe(struct pci_dev *pdev, IEEE80211_HW_NOISE_DBM; hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); @@ -705,6 +706,15 @@ ath5k_pci_resume(struct pci_dev *pdev) * Driver Initialization * \***********************/ +static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath5k_softc *sc = hw->priv; + struct ath_regulatory *reg = &sc->ah->ah_regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + static int ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) { @@ -793,12 +803,23 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) memset(sc->bssidmask, 0xff, ETH_ALEN); ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); + ah->ah_regulatory.current_rd = + ah->ah_capabilities.cap_eeprom.ee_regdomain; + ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); + if (ret) { + ATH5K_ERR(sc, "can't initialize regulatory system\n"); + goto err_queues; + } + ret = ieee80211_register_hw(hw); if (ret) { ATH5K_ERR(sc, "can't register ieee80211 hw\n"); goto err_queues; } + if (!ath_is_world_regd(&sc->ah->ah_regulatory)) + regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); + ath5k_init_leds(sc); return 0; @@ -862,6 +883,20 @@ ath5k_ieee2mhz(short chan) return 2212 + chan * 20; } +/* + * Returns true for the channel numbers used without all_channels modparam. + */ +static bool ath5k_is_standard_channel(short chan) +{ + return ((chan <= 14) || + /* UNII 1,2 */ + ((chan & 3) == 0 && chan >= 36 && chan <= 64) || + /* midband */ + ((chan & 3) == 0 && chan >= 100 && chan <= 140) || + /* UNII-3 */ + ((chan & 3) == 1 && chan >= 149 && chan <= 165)); +} + static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, @@ -899,6 +934,9 @@ ath5k_copy_channels(struct ath5k_hw *ah, if (!ath5k_channel_ok(ah, freq, chfreq)) continue; + if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) + continue; + /* Write channel info and increment counter */ channels[count].center_freq = freq; channels[count].band = (chfreq == CHANNEL_2GHZ) ? @@ -1238,7 +1276,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, (sc->power_level * 2), hw_rate, - info->control.rates[0].count, keyidx, 0, flags, + info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, cts_rate, duration); if (ret) goto err_unmap; @@ -1574,9 +1612,8 @@ ath5k_rx_start(struct ath5k_softc *sc) ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", sc->cachelsz, sc->rxbufsize); - sc->rxlink = NULL; - spin_lock_bh(&sc->rxbuflock); + sc->rxlink = NULL; list_for_each_entry(bf, &sc->rxbuf, list) { ret = ath5k_rxbuf_setup(sc, bf); if (ret != 0) { @@ -1585,9 +1622,9 @@ ath5k_rx_start(struct ath5k_softc *sc) } } bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); + ath5k_hw_set_rxdp(ah, bf->daddr); spin_unlock_bh(&sc->rxbuflock); - ath5k_hw_set_rxdp(ah, bf->daddr); ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ ath5k_mode_setup(sc); /* set filters, etc. */ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ @@ -1699,35 +1736,6 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, } } -static void ath5k_tasklet_beacon(unsigned long data) -{ - struct ath5k_softc *sc = (struct ath5k_softc *) data; - - /* - * Software beacon alert--time to send a beacon. - * - * In IBSS mode we use this interrupt just to - * keep track of the next TBTT (target beacon - * transmission time) in order to detect wether - * automatic TSF updates happened. - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* XXX: only if VEOL suppported */ - u64 tsf = ath5k_hw_get_tsf64(sc->ah); - sc->nexttbtt += sc->bintval; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "SWBA nexttbtt: %x hw_tu: %x " - "TSF: %llx\n", - sc->nexttbtt, - TSF_TO_TU(tsf), - (unsigned long long) tsf); - } else { - spin_lock(&sc->block); - ath5k_beacon_send(sc); - spin_unlock(&sc->block); - } -} - static void ath5k_tasklet_rx(unsigned long data) { @@ -1736,7 +1744,7 @@ ath5k_tasklet_rx(unsigned long data) struct sk_buff *skb, *next_skb; dma_addr_t next_skb_addr; struct ath5k_softc *sc = (void *)data; - struct ath5k_buf *bf, *bf_last; + struct ath5k_buf *bf; struct ath5k_desc *ds; int ret; int hdrlen; @@ -1747,7 +1755,6 @@ ath5k_tasklet_rx(unsigned long data) ATH5K_WARN(sc, "empty rx buf pool\n"); goto unlock; } - bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); do { rxs.flag = 0; @@ -1756,24 +1763,9 @@ ath5k_tasklet_rx(unsigned long data) skb = bf->skb; ds = bf->desc; - /* - * last buffer must not be freed to ensure proper hardware - * function. When the hardware finishes also a packet next to - * it, we are sure, it doesn't use it anymore and we can go on. - */ - if (bf_last == bf) - bf->flags |= 1; - if (bf->flags) { - struct ath5k_buf *bf_next = list_entry(bf->list.next, - struct ath5k_buf, list); - ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, - &rs); - if (ret) - break; - bf->flags &= ~1; - /* skip the overwritten one (even status is martian) */ - goto next; - } + /* bail if HW is still using self-linked descriptor */ + if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr) + break; ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); if (unlikely(ret == -EINPROGRESS)) @@ -2014,7 +2006,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath5k_hw *ah = sc->ah; struct ath5k_desc *ds; - int ret, antenna = 0; + int ret = 0; + u8 antenna; u32 flags; bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, @@ -2028,23 +2021,35 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) } ds = bf->desc; + antenna = ah->ah_tx_ant; flags = AR5K_TXDESC_NOACK; if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { ds->ds_link = bf->daddr; /* self-linked */ flags |= AR5K_TXDESC_VEOL; - /* - * Let hardware handle antenna switching if txantenna is not set - */ - } else { + } else ds->ds_link = 0; - /* - * Switch antenna every 4 beacons if txantenna is not set - * XXX assumes two antennas - */ - if (antenna == 0) - antenna = sc->bsent & 4 ? 2 : 1; - } + + /* + * If we use multiple antennas on AP and use + * the Sectored AP scenario, switch antenna every + * 4 beacons to make sure everybody hears our AP. + * When a client tries to associate, hw will keep + * track of the tx antenna to be used for this client + * automaticaly, based on ACKed packets. + * + * Note: AP still listens and transmits RTS on the + * default antenna which is supposed to be an omni. + * + * Note2: On sectored scenarios it's possible to have + * multiple antennas (1omni -the default- and 14 sectors) + * so if we choose to actually support this mode we need + * to allow user to set how many antennas we have and tweak + * the code below to send beacons on all of them. + */ + if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) + antenna = sc->bsent & 4 ? 2 : 1; + /* FIXME: If we are in g mode and rate is a CCK rate * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta @@ -2065,6 +2070,13 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) 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 @@ -2097,7 +2109,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) sc->bmisscount++; ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "missed %u consecutive beacons\n", sc->bmisscount); - if (sc->bmisscount > 3) { /* NB: 3 is a guess */ + if (sc->bmisscount > 10) { /* NB: 10 is a guess */ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "stuck beacon time (%u missed)\n", sc->bmisscount); @@ -2118,10 +2130,14 @@ ath5k_beacon_send(struct ath5k_softc *sc) * are still pending on the queue. */ if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { - ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); + ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } + /* refresh the beacon for AP mode */ + if (sc->opmode == NL80211_IFTYPE_AP) + ath5k_beacon_update(sc->hw, sc->vif); + ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); ath5k_hw_start_tx_dma(ah, sc->bhalq); ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", @@ -2278,6 +2294,35 @@ ath5k_beacon_config(struct ath5k_softc *sc) ath5k_hw_set_imr(ah, sc->imask); } +static void ath5k_tasklet_beacon(unsigned long data) +{ + struct ath5k_softc *sc = (struct ath5k_softc *) data; + + /* + * Software beacon alert--time to send a beacon. + * + * In IBSS mode we use this interrupt just to + * keep track of the next TBTT (target beacon + * transmission time) in order to detect wether + * automatic TSF updates happened. + */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) { + /* XXX: only if VEOL suppported */ + u64 tsf = ath5k_hw_get_tsf64(sc->ah); + sc->nexttbtt += sc->bintval; + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "SWBA nexttbtt: %x hw_tu: %x " + "TSF: %llx\n", + sc->nexttbtt, + TSF_TO_TU(tsf), + (unsigned long long) tsf); + } else { + spin_lock(&sc->block); + ath5k_beacon_send(sc); + spin_unlock(&sc->block); + } +} + /********************\ * Interrupt handling * @@ -2315,6 +2360,8 @@ ath5k_init(struct ath5k_softc *sc) if (ret) goto done; + ath5k_rfkill_hw_start(ah); + /* * Reset the key cache since some parts do not reset the * contents on initial power up or resume from suspend. @@ -2423,6 +2470,8 @@ ath5k_stop_hw(struct ath5k_softc *sc) tasklet_kill(&sc->restq); tasklet_kill(&sc->beacontq); + ath5k_rfkill_hw_stop(sc->ah); + return ret; } @@ -2452,7 +2501,7 @@ ath5k_intr(int irq, void *dev_id) tasklet_schedule(&sc->restq); } else { if (status & AR5K_INT_SWBA) { - tasklet_schedule(&sc->beacontq); + tasklet_hi_schedule(&sc->beacontq); } if (status & AR5K_INT_RXEOL) { /* @@ -2481,8 +2530,11 @@ ath5k_intr(int irq, void *dev_id) */ ath5k_hw_update_mib_counters(ah, &sc->ll_stats); } + if (status & AR5K_INT_GPIO) + tasklet_schedule(&sc->rf_kill.toggleq); + } - } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); + } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); if (unlikely(!counter)) ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); @@ -2719,6 +2771,7 @@ 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); @@ -2729,54 +2782,44 @@ ath5k_remove_interface(struct ieee80211_hw *hw, */ static int ath5k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath5k_softc *sc = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - int ret; - - mutex_lock(&sc->lock); - - sc->bintval = conf->beacon_int; - sc->power_level = conf->power_level; - - ret = ath5k_chan_set(sc, conf->channel); - - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) { struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; + struct ieee80211_conf *conf = &hw->conf; int ret = 0; mutex_lock(&sc->lock); - if (sc->vif != vif) { - ret = -EIO; + + ret = ath5k_chan_set(sc, conf->channel); + if (ret < 0) goto unlock; + + if ((changed & IEEE80211_CONF_CHANGE_POWER) && + (sc->power_level != conf->power_level)) { + sc->power_level = conf->power_level; + + /* Half dB steps */ + ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); } - if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { - /* Cache for later use during resets */ - memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); - /* XXX: assoc id is set to 0 for now, mac80211 doesn't have - * a clean way of letting us retrieve this yet. */ - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - mmiowb(); - } - if (conf->changed & IEEE80211_IFCC_BEACON && - (vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_AP)) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) { - ret = -ENOMEM; - goto unlock; - } - ath5k_beacon_update(sc, beacon); - } + + /* TODO: + * 1) Move this on config_interface and handle each case + * separately eg. when we have only one STA vif, use + * AR5K_ANTMODE_SINGLE_AP + * + * 2) Allow the user to change antenna mode eg. when only + * one antenna is present + * + * 3) Allow the user to set default/tx antenna when possible + * + * 4) Default mode should handle 90% of the cases, together + * with fixed a/b and single AP modes we should be able to + * handle 99%. Sectored modes are extreme cases and i still + * haven't found a usage for them. If we decide to support them, + * then we must allow the user to set how many tx antennas we + * have available + */ + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); unlock: mutex_unlock(&sc->lock); @@ -3020,28 +3063,62 @@ ath5k_reset_tsf(struct ieee80211_hw *hw) ath5k_hw_reset_tsf(sc->ah); } +/* + * Updates the beacon that is sent by ath5k_beacon_send. For adhoc, + * this is called only once at config_bss time, for AP we do it every + * SWBA interrupt so that the TIM will reflect buffered frames. + * + * Called with the beacon lock. + */ static int -ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) +ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - unsigned long flags; int ret; + struct ath5k_softc *sc = hw->priv; + struct sk_buff *skb; + + if (WARN_ON(!vif)) { + ret = -EINVAL; + goto out; + } + + skb = ieee80211_beacon_get(hw, vif); + + if (!skb) { + ret = -ENOMEM; + goto out; + } ath5k_debug_dump_skb(sc, skb, "BC ", 1); - spin_lock_irqsave(&sc->block, flags); ath5k_txbuf_free(sc, sc->bbuf); sc->bbuf->skb = skb; ret = ath5k_beacon_setup(sc, sc->bbuf); if (ret) sc->bbuf->skb = NULL; +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) { + if (ret == 0) { ath5k_beacon_config(sc); mmiowb(); } - - return ret; } + static void set_beacon_filter(struct ieee80211_hw *hw, bool enable) { @@ -3063,11 +3140,37 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + + mutex_lock(&sc->lock); + if (WARN_ON(sc->vif != vif)) + goto unlock; + + if (changes & BSS_CHANGED_BSSID) { + /* Cache for later use during resets */ + memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN); + /* XXX: assoc id is set to 0 for now, mac80211 doesn't have + * a clean way of letting us retrieve this yet. */ + ath5k_hw_set_associd(ah, ah->ah_bssid, 0); + mmiowb(); + } + + if (changes & BSS_CHANGED_BEACON_INT) + sc->bintval = bss_conf->beacon_int; + if (changes & BSS_CHANGED_ASSOC) { - mutex_lock(&sc->lock); sc->assoc = bss_conf->assoc; if (sc->opmode == NL80211_IFTYPE_STATION) set_beacon_filter(hw, sc->assoc); - mutex_unlock(&sc->lock); } + + 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); + } + + unlock: + mutex_unlock(&sc->lock); } diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h similarity index 96% rename from drivers/net/wireless/ath5k/base.h rename to drivers/net/wireless/ath/ath5k/base.h index 822956114cd7..f9b7f2f819b7 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -46,6 +46,7 @@ #include #include #include +#include #include "ath5k.h" #include "debug.h" @@ -56,7 +57,6 @@ struct ath5k_buf { struct list_head list; - unsigned int flags; /* rx descriptor flags */ struct ath5k_desc *desc; /* virtual addr of desc */ dma_addr_t daddr; /* physical addr of desc */ struct sk_buff *skb; /* skbuff for buf */ @@ -92,6 +92,15 @@ struct ath5k_led struct led_classdev led_dev; /* led classdev */ }; +/* Rfkill */ +struct ath5k_rfkill { + /* GPIO PIN for rfkill */ + u16 gpio; + /* polarity of rfkill GPIO PIN */ + bool polarity; + /* RFKILL toggle tasklet */ + struct tasklet_struct toggleq; +}; #if CHAN_DEBUG #define ATH_CHAN_MAX (26+26+26+200+200) @@ -168,6 +177,8 @@ struct ath5k_softc { struct tasklet_struct txtq; /* tx intr tasklet */ struct ath5k_led tx_led; /* tx led */ + struct ath5k_rfkill rf_kill; + spinlock_t block; /* protects beacon */ struct tasklet_struct beacontq; /* beacon intr tasklet */ struct ath5k_buf *bbuf; /* beacon buffer */ diff --git a/drivers/net/wireless/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c similarity index 100% rename from drivers/net/wireless/ath5k/caps.c rename to drivers/net/wireless/ath/ath5k/caps.c diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c similarity index 100% rename from drivers/net/wireless/ath5k/debug.c rename to drivers/net/wireless/ath/ath5k/debug.c diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h similarity index 100% rename from drivers/net/wireless/ath5k/debug.h rename to drivers/net/wireless/ath/ath5k/debug.h diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c similarity index 100% rename from drivers/net/wireless/ath5k/desc.c rename to drivers/net/wireless/ath/ath5k/desc.c diff --git a/drivers/net/wireless/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h similarity index 100% rename from drivers/net/wireless/ath5k/desc.h rename to drivers/net/wireless/ath/ath5k/desc.h diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c similarity index 99% rename from drivers/net/wireless/ath5k/dma.c rename to drivers/net/wireless/ath/ath5k/dma.c index b65b4feb2d28..941b51130a6f 100644 --- a/drivers/net/wireless/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -80,8 +80,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) * ath5k_hw_get_rxdp - Get RX Descriptor's address * * @ah: The &struct ath5k_hw - * - * XXX: Is RXDP read and clear ? */ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) { diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c similarity index 96% rename from drivers/net/wireless/ath5k/eeprom.c rename to drivers/net/wireless/ath/ath5k/eeprom.c index c0fb3b09ba45..c56b494d417a 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -156,6 +156,17 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; } + AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val); + + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val) + ee->ee_is_hb63 = true; + else + ee->ee_is_hb63 = false; + + AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val); + 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; + return 0; } @@ -197,16 +208,16 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; ee->ee_ant_control[mode][i++] = val & 0x3f; - /* Get antenna modes */ - ah->ah_antenna[mode][0] = + /* Get antenna switch tables */ + ah->ah_ant_ctl[mode][AR5K_ANT_CTL] = (ee->ee_ant_control[mode][0] << 4); - ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = + ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] = ee->ee_ant_control[mode][1] | (ee->ee_ant_control[mode][2] << 6) | (ee->ee_ant_control[mode][3] << 12) | (ee->ee_ant_control[mode][4] << 18) | (ee->ee_ant_control[mode][5] << 24); - ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = + ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] = ee->ee_ant_control[mode][6] | (ee->ee_ant_control[mode][7] << 6) | (ee->ee_ant_control[mode][8] << 12) | @@ -640,9 +651,9 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) static inline void ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) { - const static u16 intercepts3[] = + static const u16 intercepts3[] = { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; - const static u16 intercepts3_2[] = + static const u16 intercepts3_2[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; const u16 *ip; int i; @@ -1694,9 +1705,40 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) return 0; } +static int +ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 offset; + u16 val; + int ret = 0, i; + + offset = AR5K_EEPROM_CTL(ee->ee_version) + + AR5K_EEPROM_N_CTLS(ee->ee_version); + + if (ee->ee_version < AR5K_EEPROM_VERSION_5_3) { + /* No spur info for 5GHz */ + ee->ee_spur_chans[0][0] = AR5K_EEPROM_NO_SPUR; + /* 2 channels for 2GHz (2464/2420) */ + ee->ee_spur_chans[0][1] = AR5K_EEPROM_5413_SPUR_CHAN_1; + ee->ee_spur_chans[1][1] = AR5K_EEPROM_5413_SPUR_CHAN_2; + ee->ee_spur_chans[2][1] = AR5K_EEPROM_NO_SPUR; + } else if (ee->ee_version >= AR5K_EEPROM_VERSION_5_3) { + for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { + AR5K_EEPROM_READ(offset, val); + ee->ee_spur_chans[i][0] = val; + AR5K_EEPROM_READ(offset + AR5K_EEPROM_N_SPUR_CHANS, + val); + ee->ee_spur_chans[i][1] = val; + offset++; + } + } + + return ret; +} /* - * Initialize eeprom power tables + * Initialize eeprom data structure */ int ath5k_eeprom_init(struct ath5k_hw *ah) @@ -1719,6 +1761,10 @@ ath5k_eeprom_init(struct ath5k_hw *ah) if (err < 0) return err; + err = ath5k_eeprom_read_spur_chans(ah); + if (err < 0) + return err; + return 0; } @@ -1754,16 +1800,3 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) return 0; } - -bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah) -{ - u16 data; - - ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data); - - if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data) - return true; - else - return false; -} - diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h similarity index 94% rename from drivers/net/wireless/ath5k/eeprom.h rename to drivers/net/wireless/ath/ath5k/eeprom.h index b0c0606dea0b..64be73a5edae 100644 --- a/drivers/net/wireless/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -26,6 +26,13 @@ #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ + +#define AR5K_EEPROM_RFKILL 0x0f +#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c +#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 +#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 +#define AR5K_EEPROM_RFKILL_POLARITY_S 1 + #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ @@ -66,11 +73,6 @@ #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ -#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c -#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 -#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 -#define AR5K_EEPROM_RFKILL_POLARITY_S 1 - /* Newer EEPROMs are using a different offset */ #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) @@ -211,6 +213,23 @@ #define AR5K_EEPROM_I_GAIN 10 #define AR5K_EEPROM_CCK_OFDM_DELTA 15 #define AR5K_EEPROM_N_IQ_CAL 2 +/* 5GHz/2GHz */ +enum ath5k_eeprom_freq_bands{ + AR5K_EEPROM_BAND_5GHZ = 0, + AR5K_EEPROM_BAND_2GHZ = 1, + AR5K_EEPROM_N_FREQ_BANDS, +}; +/* Spur chans per freq band */ +#define AR5K_EEPROM_N_SPUR_CHANS 5 +/* fbin value for chan 2464 x2 */ +#define AR5K_EEPROM_5413_SPUR_CHAN_1 1640 +/* fbin value for chan 2420 x2 */ +#define AR5K_EEPROM_5413_SPUR_CHAN_2 1200 +#define AR5K_EEPROM_SPUR_CHAN_MASK 0x3FFF +#define AR5K_EEPROM_NO_SPUR 0x8000 +#define AR5K_SPUR_CHAN_WIDTH 87 +#define AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz 3125 +#define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 #define AR5K_EEPROM_READ(_o, _v) do { \ ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ @@ -221,11 +240,11 @@ #define AR5K_EEPROM_READ_HDR(_o, _v) \ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ -enum ath5k_ant_setting { - AR5K_ANT_VARIABLE = 0, /* variable by programming */ - AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ - AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ - AR5K_ANT_MAX = 3, +enum ath5k_ant_table { + AR5K_ANT_CTL = 0, /* Idle switch table settings */ + AR5K_ANT_SWTABLE_A = 1, /* Switch table for antenna A */ + AR5K_ANT_SWTABLE_B = 2, /* Switch table for antenna B */ + AR5K_ANT_MAX, }; enum ath5k_ctl_mode { @@ -369,6 +388,9 @@ struct ath5k_eeprom_info { u16 ee_version; u16 ee_header; u16 ee_ant_gain; + u8 ee_rfkill_pin; + bool ee_rfkill_pol; + bool ee_is_hb63; u16 ee_misc0; u16 ee_misc1; u16 ee_misc2; @@ -436,6 +458,10 @@ struct ath5k_eeprom_info { s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES]; s8 ee_pd_gain_overlap; + /* Spur mitigation data (fbin values for spur channels) */ + u16 ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS]; + + /* Antenna raw switch tables */ u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; }; diff --git a/drivers/net/wireless/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c similarity index 100% rename from drivers/net/wireless/ath5k/gpio.c rename to drivers/net/wireless/ath/ath5k/gpio.c diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c similarity index 99% rename from drivers/net/wireless/ath5k/initvals.c rename to drivers/net/wireless/ath/ath5k/initvals.c index 61fb621ed20d..18eb5190ce4b 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -537,8 +537,6 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { { AR5K_DCU_TX_FILTER_1(15), 0x00000000 }, { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, - { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, - { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, { AR5K_STA_ID1, 0x00000000 }, { AR5K_BSS_ID0, 0x00000000 }, { AR5K_BSS_ID1, 0x00000000 }, @@ -669,7 +667,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { /*{ AR5K_PHY(650), 0x000001b5 },*/ { AR5K_PHY(651), 0x00000000 }, { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, - { AR5K_PHY_TXPOWER_RATE2, 0x20202020 }, + { AR5K_PHY_TXPOWER_RATE4, 0x20202020 }, /*{ AR5K_PHY(655), 0x13c889af },*/ { AR5K_PHY(656), 0x38490a20 }, { AR5K_PHY(657), 0x00007bb6 }, @@ -718,7 +716,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { { AR5K_PHY_SETTLING, { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, { AR5K_PHY_AGCCTL, - { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } }, + { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } }, { AR5K_PHY_NF, { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { AR5K_PHY_WEAK_OFDM_HIGH_THR, @@ -799,7 +797,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { { AR5K_PHY_DESIRED_SIZE, { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } }, + { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } }, { AR5K_PHY_AGCCOARSE, { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c similarity index 94% rename from drivers/net/wireless/ath5k/led.c rename to drivers/net/wireless/ath/ath5k/led.c index 19555fb79c9b..876725f08b6c 100644 --- a/drivers/net/wireless/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -53,8 +53,6 @@ /* Devices we match on for LED config info (typically laptops) */ static const struct pci_device_id ath5k_led_devices[] = { - /* IBM-specific AR5212 */ - { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, /* AR5211 */ { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, /* HP Compaq nc6xx, nc4000, nx6000 */ @@ -67,6 +65,12 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, /* Acer Extensa 5620z (nekoreeve@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, + /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ + { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, + /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ + { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, + /* IBM-specific AR5212 (all others) */ + { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, { } }; @@ -78,7 +82,7 @@ void ath5k_led_enable(struct ath5k_softc *sc) } } -void ath5k_led_on(struct ath5k_softc *sc) +static void ath5k_led_on(struct ath5k_softc *sc) { if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) return; diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c similarity index 99% rename from drivers/net/wireless/ath5k/pcu.c rename to drivers/net/wireless/ath/ath5k/pcu.c index 55122f1e1986..ec35503f6a40 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -736,8 +736,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) /* When in AP mode zero timer0 to start TSF */ if (ah->ah_op_mode == NL80211_IFTYPE_AP) ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - else - ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); + + ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); @@ -1003,7 +1003,7 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) * Note2: Windows driver (ndiswrapper) sets this to * 0x00000714 instead of 0x00000007 */ - if (ah->ah_version > AR5K_AR5211) { + if (ah->ah_version >= AR5K_AR5211) { ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(entry)); @@ -1038,9 +1038,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key) case ALG_CCMP: return AR5K_KEYTABLE_TYPE_CCM; case ALG_WEP: - if (key->keylen == LEN_WEP40) + if (key->keylen == WLAN_KEY_LEN_WEP40) return AR5K_KEYTABLE_TYPE_40; - else if (key->keylen == LEN_WEP104) + else if (key->keylen == WLAN_KEY_LEN_WEP104) return AR5K_KEYTABLE_TYPE_104; return -EINVAL; default: diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c similarity index 83% rename from drivers/net/wireless/ath5k/phy.c rename to drivers/net/wireless/ath/ath5k/phy.c index b48b29dca3d2..a876ca8d69ef 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -168,9 +168,6 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) * tx power and a Peak to Average Power Detector (PAPD) will try * to measure the gain. * - * TODO: Use propper tx power setting for the probe packet so - * that we don't observe a serious power drop on the receiver - * * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) * just after we enable the probe so that we don't mess with * standard traffic ? Maybe it's time to use sw interrupts and @@ -186,7 +183,7 @@ static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) /* Send the packet with 2dB below max power as * patent doc suggest */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4, AR5K_PHY_PAPD_PROBE_TXPOWER) | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); @@ -1356,6 +1353,257 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, return ret; } +/***************************\ +* Spur mitigation functions * +\***************************/ + +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u8 refclk_freq; + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + refclk_freq = 40; + else + refclk_freq = 32; + + if ((channel->center_freq % refclk_freq != 0) && + ((channel->center_freq % refclk_freq < 10) || + (channel->center_freq % refclk_freq > 22))) + return true; + else + return false; +} + +void +ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 mag_mask[4] = {0, 0, 0, 0}; + u32 pilot_mask[2] = {0, 0}; + /* Note: fbin values are scaled up by 2 */ + u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window; + s32 spur_delta_phase, spur_freq_sigma_delta; + s32 spur_offset, num_symbols_x16; + u8 num_symbol_offsets, i, freq_band; + + /* Convert current frequency to fbin value (the same way channels + * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale + * up by 2 so we can compare it later */ + if (channel->hw_value & CHANNEL_2GHZ) { + chan_fbin = (channel->center_freq - 2300) * 10; + freq_band = AR5K_EEPROM_BAND_2GHZ; + } else { + chan_fbin = (channel->center_freq - 4900) * 10; + freq_band = AR5K_EEPROM_BAND_5GHZ; + } + + /* Check if any spur_chan_fbin from EEPROM is + * within our current channel's spur detection range */ + spur_chan_fbin = AR5K_EEPROM_NO_SPUR; + spur_detection_window = AR5K_SPUR_CHAN_WIDTH; + /* XXX: Half/Quarter channels ?*/ + if (channel->hw_value & CHANNEL_TURBO) + spur_detection_window *= 2; + + for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { + spur_chan_fbin = ee->ee_spur_chans[i][freq_band]; + + /* Note: mask cleans AR5K_EEPROM_NO_SPUR flag + * so it's zero if we got nothing from EEPROM */ + if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) { + spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; + break; + } + + if ((chan_fbin - spur_detection_window <= + (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) && + (chan_fbin + spur_detection_window >= + (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) { + spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; + break; + } + } + + /* We need to enable spur filter for this channel */ + if (spur_chan_fbin) { + spur_offset = spur_chan_fbin - chan_fbin; + /* + * Calculate deltas: + * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 + * spur_delta_phase -> spur_offset / chip_freq << 11 + * Note: Both values have 100KHz resolution + */ + /* XXX: Half/Quarter rate channels ? */ + switch (channel->hw_value) { + case CHANNEL_A: + /* Both sample_freq and chip_freq are 40MHz */ + spur_delta_phase = (spur_offset << 17) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + break; + case CHANNEL_G: + /* sample_freq -> 40MHz chip_freq -> 44MHz + * (for b compatibility) */ + spur_freq_sigma_delta = (spur_offset << 8) / 55; + spur_delta_phase = (spur_offset << 17) / 25; + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + break; + case CHANNEL_T: + case CHANNEL_TG: + /* Both sample_freq and chip_freq are 80MHz */ + spur_delta_phase = (spur_offset << 16) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; + break; + default: + return; + } + + /* Calculate pilot and magnitude masks */ + + /* Scale up spur_offset by 1000 to switch to 100HZ resolution + * and divide by symbol_width to find how many symbols we have + * Note: number of symbols is scaled up by 16 */ + num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width; + + /* Spur is on a symbol if num_symbols_x16 % 16 is zero */ + if (!(num_symbols_x16 & 0xF)) + /* _X_ */ + num_symbol_offsets = 3; + else + /* _xx_ */ + num_symbol_offsets = 4; + + for (i = 0; i < num_symbol_offsets; i++) { + + /* Calculate pilot mask */ + s32 curr_sym_off = + (num_symbols_x16 / 16) + i + 25; + + /* Pilot magnitude mask seems to be a way to + * declare the boundaries for our detection + * window or something, it's 2 for the middle + * value(s) where the symbol is expected to be + * and 1 on the boundary values */ + u8 plt_mag_map = + (i == 0 || i == (num_symbol_offsets - 1)) + ? 1 : 2; + + if (curr_sym_off >= 0 && curr_sym_off <= 32) { + if (curr_sym_off <= 25) + pilot_mask[0] |= 1 << curr_sym_off; + else if (curr_sym_off >= 27) + pilot_mask[0] |= 1 << (curr_sym_off - 1); + } else if (curr_sym_off >= 33 && curr_sym_off <= 52) + pilot_mask[1] |= 1 << (curr_sym_off - 33); + + /* Calculate magnitude mask (for viterbi decoder) */ + if (curr_sym_off >= -1 && curr_sym_off <= 14) + mag_mask[0] |= + plt_mag_map << (curr_sym_off + 1) * 2; + else if (curr_sym_off >= 15 && curr_sym_off <= 30) + mag_mask[1] |= + plt_mag_map << (curr_sym_off - 15) * 2; + else if (curr_sym_off >= 31 && curr_sym_off <= 46) + mag_mask[2] |= + plt_mag_map << (curr_sym_off - 31) * 2; + else if (curr_sym_off >= 46 && curr_sym_off <= 53) + mag_mask[3] |= + plt_mag_map << (curr_sym_off - 47) * 2; + + } + + /* Write settings on hw to enable spur filter */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_RATE, 0xff); + /* XXX: Self correlator also ? */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_PILOT_MASK_EN | + AR5K_PHY_IQ_CHAN_MASK_EN | + AR5K_PHY_IQ_SPUR_FILT_EN); + + /* Set delta phase and freq sigma delta */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(spur_delta_phase, + AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) | + AR5K_REG_SM(spur_freq_sigma_delta, + AR5K_PHY_TIMING_11_SPUR_FREQ_SD) | + AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC, + AR5K_PHY_TIMING_11); + + /* Write pilot masks */ + ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, + AR5K_PHY_TIMING_8_PILOT_MASK_2, + pilot_mask[1]); + + ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, + AR5K_PHY_TIMING_10_PILOT_MASK_2, + pilot_mask[1]); + + /* Write magnitude masks */ + ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1); + ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2); + ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_MASK_4, + mag_mask[3]); + + ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1); + ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2); + ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, + AR5K_PHY_BIN_MASK2_4_MASK_4, + mag_mask[3]); + + } else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & + AR5K_PHY_IQ_SPUR_FILT_EN) { + /* Clean up spur mitigation settings and disable fliter */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_RATE, 0); + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_PILOT_MASK_EN | + AR5K_PHY_IQ_CHAN_MASK_EN | + AR5K_PHY_IQ_SPUR_FILT_EN); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11); + + /* Clear pilot masks */ + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, + AR5K_PHY_TIMING_8_PILOT_MASK_2, + 0); + + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, + AR5K_PHY_TIMING_10_PILOT_MASK_2, + 0); + + /* Clear magnitude masks */ + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_MASK_4, + 0); + + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, + AR5K_PHY_BIN_MASK2_4_MASK_4, + 0); + } +} + +/********************\ + Misc PHY functions +\********************/ + int ath5k_hw_phy_disable(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); @@ -1365,10 +1613,6 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah) return 0; } -/********************\ - Misc PHY functions -\********************/ - /* * Get the PHY Chip revision */ @@ -1417,25 +1661,189 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) return ret; } +/*****************\ +* Antenna control * +\*****************/ + void /*TODO:Boundary check*/ -ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) +ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) { ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ + if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); + ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ + if (ah->ah_version != AR5K_AR5210) - return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); + return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; return false; /*XXX: What do we return for 5210 ?*/ } +/* + * Enable/disable fast rx antenna diversity + */ +static void +ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) +{ + switch (ee_mode) { + case AR5K_EEPROM_MODE_11G: + /* XXX: This is set to + * disabled on initvals !!! */ + case AR5K_EEPROM_MODE_11A: + if (enable) + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_OFDM_DIV_DIS); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_OFDM_DIV_DIS); + break; + case AR5K_EEPROM_MODE_11B: + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_OFDM_DIV_DIS); + break; + default: + return; + } + + if (enable) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, + AR5K_PHY_RESTART_DIV_GC, 0xc); + + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, + AR5K_PHY_FAST_ANT_DIV_EN); + } else { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, + AR5K_PHY_RESTART_DIV_GC, 0x8); + + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, + AR5K_PHY_FAST_ANT_DIV_EN); + } +} + +/* + * Set antenna operating mode + */ +void +ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) +{ + 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; + u32 sta_id1 = 0; + + def_ant = ah->ah_def_ant; + + ATH5K_TRACE(ah->ah_sc); + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + case CHANNEL_T: + case CHANNEL_XR: + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + case CHANNEL_TG: + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_B: + ee_mode = AR5K_EEPROM_MODE_11B; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return; + } + + switch (ant_mode) { + case AR5K_ANTMODE_DEFAULT: + tx_ant = 0; + use_def_for_tx = false; + update_def_on_tx = false; + use_def_for_rts = false; + use_def_for_sg = false; + fast_div = true; + break; + case AR5K_ANTMODE_FIXED_A: + def_ant = 1; + tx_ant = 0; + use_def_for_tx = true; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = true; + fast_div = false; + break; + case AR5K_ANTMODE_FIXED_B: + def_ant = 2; + tx_ant = 0; + use_def_for_tx = true; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = true; + fast_div = false; + break; + case AR5K_ANTMODE_SINGLE_AP: + def_ant = 1; /* updated on tx */ + tx_ant = 0; + use_def_for_tx = true; + update_def_on_tx = true; + use_def_for_rts = true; + use_def_for_sg = true; + fast_div = true; + break; + case AR5K_ANTMODE_SECTOR_AP: + tx_ant = 1; /* variable */ + use_def_for_tx = false; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = false; + fast_div = false; + break; + case AR5K_ANTMODE_SECTOR_STA: + tx_ant = 1; /* variable */ + use_def_for_tx = true; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = false; + fast_div = true; + break; + case AR5K_ANTMODE_DEBUG: + def_ant = 1; + tx_ant = 2; + use_def_for_tx = false; + update_def_on_tx = false; + use_def_for_rts = false; + use_def_for_sg = false; + fast_div = false; + break; + default: + return; + } + + ah->ah_tx_ant = tx_ant; + ah->ah_ant_mode = ant_mode; + + sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; + sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; + sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0; + sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0; + + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS); + + if (sta_id1) + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); + + /* Note: set diversity before default antenna + * because it won't work correctly */ + ath5k_hw_set_fast_div(ah, ee_mode, fast_div); + ath5k_hw_set_def_antenna(ah, def_ant); +} + /****************\ * TX power setup * @@ -1489,6 +1897,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; + if (pwrL[0] == pwrL[1]) min_pwrL = pwrL[0]; else { @@ -1750,8 +2161,6 @@ ath5k_get_rate_pcal_data(struct ath5k_hw *ah, * Get the max edge power for this channel if * we have such data from EEPROM's Conformance Test * Limits (CTL), and limit max power if needed. - * - * FIXME: Only works for world regulatory domains */ static void ath5k_get_max_ctl_power(struct ath5k_hw *ah, @@ -1767,26 +2176,23 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, u8 ctl_idx = 0xFF; u32 target = channel->center_freq; - /* Find out a CTL for our mode that's not mapped - * on a specific reg domain. - * - * TODO: Map our current reg domain to one of the 3 available - * reg domain ids so that we can support more CTLs. */ + ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band); + switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_11A; break; case CHANNEL_G: - ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_11G; break; case CHANNEL_B: - ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_11B; break; case CHANNEL_T: - ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_TURBO; break; case CHANNEL_TG: - ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_TURBOG; break; case CHANNEL_XR: /* Fall through */ @@ -2482,8 +2888,19 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, for (i = 8; i <= 15; i++) rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; - ah->ah_txpower.txp_min_pwr = rates[7]; - ah->ah_txpower.txp_max_pwr = rates[0]; + /* Now that we have all rates setup use table offset to + * match the power range set by user with the power indices + * on PCDAC/PDADC table */ + for (i = 0; i < 16; i++) { + rates[i] += ah->ah_txpower.txp_offset; + /* Don't get out of bounds */ + if (rates[i] > 63) + rates[i] = 63; + } + + /* Min/max in 0.25dB units */ + ah->ah_txpower.txp_min_pwr = 2 * rates[7]; + ah->ah_txpower.txp_max_pwr = 2 * rates[0]; ah->ah_txpower.txp_ofdm = rates[7]; } @@ -2591,16 +3008,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return 0; } -int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) +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; + u8 ee_mode; ATH5K_TRACE(ah->ah_sc); + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + case CHANNEL_T: + case CHANNEL_XR: + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + case CHANNEL_TG: + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_B: + ee_mode = AR5K_EEPROM_MODE_11B; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, "changing txpower to %d\n", txpower); - return ath5k_hw_txpower(ah, channel, mode, txpower); + return ath5k_hw_txpower(ah, channel, ee_mode, txpower); } #undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c similarity index 98% rename from drivers/net/wireless/ath5k/qcu.c rename to drivers/net/wireless/ath/ath5k/qcu.c index 5094c394a4b2..73407b3f53ef 100644 --- a/drivers/net/wireless/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -160,7 +160,8 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) if (ah->ah_version == AR5K_AR5210) return false; - pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); + pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); + pending &= AR5K_QCU_STS_FRMPENDCNT; /* It's possible to have no frames pending even if TXE * is set. To indicate that q has not stopped return @@ -401,14 +402,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_DCU_MISC_ARBLOCK_CTL_S) | + AR5K_DCU_MISC_ARBLOCK_IGNORE | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | AR5K_DCU_MISC_BCN_ENABLE); break; case AR5K_TX_QUEUE_CAB: AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | + 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/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h similarity index 99% rename from drivers/net/wireless/ath5k/reg.h rename to drivers/net/wireless/ath/ath5k/reg.h index 7070d1543cdc..6809b54a2ad7 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -1148,6 +1148,11 @@ #define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ #define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ +#define AR5K_STA_ID1_ANTENNA_SETTINGS (AR5K_STA_ID1_DEFAULT_ANTENNA | \ + AR5K_STA_ID1_DESC_ANTENNA | \ + AR5K_STA_ID1_RTS_DEF_ANTENNA | \ + AR5K_STA_ID1_SELFGEN_DEF_ANT) + /* * First BSSID register (MAC address, lower 32bits) */ @@ -2028,7 +2033,9 @@ #define AR5K_PHY_AGCCTL 0x9860 /* Register address */ #define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ #define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ +#define AR5K_PHY_AGCCTL_OFDM_DIV_DIS 0x00000008 /* Disable antenna diversity on OFDM modes */ #define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ +#define AR5K_PHY_AGCTL_FLTR_CAL 0x00010000 /* Allow filter calibration (?) */ #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ /* @@ -2528,7 +2535,7 @@ * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] */ #define AR5K_PHY_CCK_CROSSCORR 0xa208 -#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f +#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000003f #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 /* Same address is used for antenna diversity activation */ diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c similarity index 95% rename from drivers/net/wireless/ath5k/reset.c rename to drivers/net/wireless/ath/ath5k/reset.c index 5f72c111c2e8..bd0a97a38d34 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -54,9 +54,8 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, u32 coef_scaled, coef_exp, coef_man, ds_coef_exp, ds_coef_man, clock; - if (!(ah->ah_version == AR5K_AR5212) || - !(channel->hw_value & CHANNEL_OFDM)) - BUG(); + BUG_ON(!(ah->ah_version == AR5K_AR5212) || + !(channel->hw_value & CHANNEL_OFDM)); /* Get coefficient * ALGO: coef = (5 * clock * carrier_freq) / 2) @@ -508,7 +507,7 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ath5k_eeprom_is_hb63(ah)) + else if (ee->ee_is_hb63) scal = AR5K_PHY_SCAL_32MHZ_HB63; else scal = AR5K_PHY_SCAL_32MHZ; @@ -537,26 +536,6 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) return; } -static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u8 refclk_freq; - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - refclk_freq = 40; - else - refclk_freq = 32; - - if ((channel->center_freq % refclk_freq != 0) && - ((channel->center_freq % refclk_freq < 10) || - (channel->center_freq % refclk_freq > 22))) - return true; - else - return false; -} - /* TODO: Half/Quarter rate */ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel) @@ -599,9 +578,10 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, /* Set DAC/ADC delays */ if (ah->ah_version == AR5K_AR5212) { u32 scal; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ath5k_eeprom_is_hb63(ah)) + else if (ee->ee_is_hb63) scal = AR5K_PHY_SCAL_32MHZ_HB63; else scal = AR5K_PHY_SCAL_32MHZ; @@ -698,13 +678,13 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, /* Set antenna idle switch table */ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, AR5K_PHY_ANT_CTL_SWTABLE_IDLE, - (ah->ah_antenna[ee_mode][0] | + (ah->ah_ant_ctl[ee_mode][0] | AR5K_PHY_ANT_CTL_TXRX_EN)); - /* Set antenna switch table */ - ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], + /* Set antenna switch tables */ + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], AR5K_PHY_ANT_SWITCH_TABLE_0); - ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], AR5K_PHY_ANT_SWITCH_TABLE_1); /* Noise floor threshold */ @@ -998,10 +978,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_tweak_initval_settings(ah, channel); /* - * Set TX power (FIXME) + * Set TX power */ ret = ath5k_hw_txpower(ah, channel, ee_mode, - AR5K_TUNE_DEFAULT_TXPOWER); + ah->ah_txpower.txp_max_pwr / 2); if (ret) return ret; @@ -1024,9 +1004,22 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Write OFDM timings on 5212*/ if (ah->ah_version == AR5K_AR5212 && channel->hw_value & CHANNEL_OFDM) { + struct ath5k_eeprom_info *ee = + &ah->ah_capabilities.cap_eeprom; + ret = ath5k_hw_write_ofdm_timings(ah, channel); if (ret) return ret; + + /* Note: According to docs we can have a newer + * EEPROM on old hardware, so we need to verify + * that our hardware is new enough to have spur + * mitigation registers (delta phase etc) */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5424 || + (ah->ah_mac_srev >= AR5K_SREV_AR5424 && + ee->ee_version >= AR5K_EEPROM_VERSION_5_3)) + ath5k_hw_set_spur_mitigation_filter(ah, + channel); } /*Enable/disable 802.11b mode on 5111 @@ -1042,17 +1035,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* * In case a fixed antenna was set as default - * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE - * registers. + * use the same switch table twice. */ - if (s_ant != 0) { - if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ - ant[0] = ant[1] = AR5K_ANT_FIXED_A; - else /* 2 - Aux */ - ant[0] = ant[1] = AR5K_ANT_FIXED_B; - } else { - ant[0] = AR5K_ANT_FIXED_A; - ant[1] = AR5K_ANT_FIXED_B; + if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) + ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; + else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) + ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; + else { + ant[0] = AR5K_ANT_SWTABLE_A; + ant[1] = AR5K_ANT_SWTABLE_B; } /* Commit values from EEPROM */ @@ -1260,6 +1251,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, */ ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + /* Restore antenna mode */ + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); /* * Configure QCUs/DCUs @@ -1311,23 +1304,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, if (ah->ah_version != AR5K_AR5210) ath5k_hw_set_imr(ah, ah->ah_imr); - /* - * Setup RFKill interrupt if rfkill flag is set on eeprom. - * TODO: Use gpio pin and polarity infos from eeprom - * TODO: Handle this in ath5k_intr because it'll result - * a nasty interrupt storm. - */ -#if 0 - if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { - ath5k_hw_set_gpio_input(ah, 0); - ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0); - if (ah->ah_gpio[0] == 0) - ath5k_hw_set_gpio_intr(ah, 0, 1); - else - ath5k_hw_set_gpio_intr(ah, 0, 0); - } -#endif - /* Enable 32KHz clock function for AR5212+ chips * Set clocks to 32KHz operation and use an * external 32KHz crystal when sleeping if one diff --git a/drivers/net/wireless/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h similarity index 100% rename from drivers/net/wireless/ath5k/rfbuffer.h rename to drivers/net/wireless/ath/ath5k/rfbuffer.h diff --git a/drivers/net/wireless/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h similarity index 100% rename from drivers/net/wireless/ath5k/rfgain.h rename to drivers/net/wireless/ath/ath5k/rfgain.h diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c new file mode 100644 index 000000000000..41a877b73fce --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/rfkill.c @@ -0,0 +1,121 @@ +/* + * RFKILL support for ath5k + * + * Copyright (c) 2009 Tobias Doerffel + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include "base.h" + + +static inline void ath5k_rfkill_disable(struct ath5k_softc *sc) +{ + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", + sc->rf_kill.gpio, sc->rf_kill.polarity); + ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); + ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity); +} + + +static inline void ath5k_rfkill_enable(struct ath5k_softc *sc) +{ + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", + sc->rf_kill.gpio, sc->rf_kill.polarity); + ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); + ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity); +} + +static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable) +{ + struct ath5k_hw *ah = sc->ah; + u32 curval; + + ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio); + curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); + ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ? + !!curval : !curval); +} + +static bool +ath5k_is_rfkill_set(struct ath5k_softc *sc) +{ + /* configuring GPIO for input for some reason disables rfkill */ + /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/ + return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) == + sc->rf_kill.polarity; +} + +static void +ath5k_tasklet_rfkill_toggle(unsigned long data) +{ + struct ath5k_softc *sc = (void *)data; + bool blocked; + + blocked = ath5k_is_rfkill_set(sc); + wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked); +} + + +void +ath5k_rfkill_hw_start(struct ath5k_hw *ah) +{ + struct ath5k_softc *sc = ah->ah_sc; + + /* read rfkill GPIO configuration from EEPROM header */ + sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; + sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; + + tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, + (unsigned long)sc); + + ath5k_rfkill_disable(sc); + + /* enable interrupt for rfkill switch */ + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) + ath5k_rfkill_set_intr(sc, true); +} + + +void +ath5k_rfkill_hw_stop(struct ath5k_hw *ah) +{ + struct ath5k_softc *sc = ah->ah_sc; + + /* disable interrupt for rfkill switch */ + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) + ath5k_rfkill_set_intr(sc, false); + + tasklet_kill(&sc->rf_kill.toggleq); + + /* enable RFKILL when stopping HW so Wifi LED is turned off */ + ath5k_rfkill_enable(sc); +} + diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig similarity index 97% rename from drivers/net/wireless/ath9k/Kconfig rename to drivers/net/wireless/ath/ath9k/Kconfig index 90a8dd873786..0ed1ac312aa6 100644 --- a/drivers/net/wireless/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -2,6 +2,7 @@ config ATH9K tristate "Atheros 802.11n wireless cards support" depends on PCI && MAC80211 && WLAN_80211 depends on RFKILL || RFKILL=n + select ATH_COMMON select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile similarity index 96% rename from drivers/net/wireless/ath9k/Makefile rename to drivers/net/wireless/ath/ath9k/Makefile index 1a4d4eab6fe8..783bc39eb2ff 100644 --- a/drivers/net/wireless/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -4,7 +4,6 @@ ath9k-y += hw.o \ calib.o \ ani.o \ phy.o \ - regd.o \ beacon.o \ main.o \ recv.o \ diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c similarity index 100% rename from drivers/net/wireless/ath9k/ahb.c rename to drivers/net/wireless/ath/ath9k/ahb.c diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c similarity index 99% rename from drivers/net/wireless/ath9k/ani.c rename to drivers/net/wireless/ath/ath9k/ani.c index 6c5e887d50d7..1aeafb511ddd 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -569,8 +569,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, DPRINTF(ah->ah_sc, ATH_DBG_ANI, "phyCnt1 0x%x, resetting " "counter value to 0x%x\n", - phyCnt1, - aniState->ofdmPhyErrBase); + phyCnt1, aniState->ofdmPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_MASK_1, @@ -580,8 +579,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, DPRINTF(ah->ah_sc, ATH_DBG_ANI, "phyCnt2 0x%x, resetting " "counter value to 0x%x\n", - phyCnt2, - aniState->cckPhyErrBase); + phyCnt2, aniState->cckPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_MASK_2, @@ -667,7 +665,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 cc = REG_READ(ah, AR_CCCNT); if (cycles == 0 || cycles > cc) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "cycle counter wrap. ExtBusy = 0\n"); good = 0; } else { diff --git a/drivers/net/wireless/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h similarity index 100% rename from drivers/net/wireless/ath9k/ani.h rename to drivers/net/wireless/ath/ath9k/ani.h diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h similarity index 88% rename from drivers/net/wireless/ath9k/ath9k.h rename to drivers/net/wireless/ath/ath9k/ath9k.h index 2689a08a2844..515880aa2116 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -53,11 +53,7 @@ struct ath_node; #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define ASSERT(exp) do { \ - if (unlikely(!(exp))) { \ - BUG(); \ - } \ - } while (0) +#define ASSERT(exp) BUG_ON(!(exp)) #define TSF_TO_TU(_h,_l) \ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) @@ -70,7 +66,6 @@ struct ath_config { u32 ath_aggr_prot; u16 txpowlimit; u8 cabqReadytime; - u8 swBeaconProcess; }; /*************************/ @@ -78,13 +73,17 @@ struct ath_config { /*************************/ #define ATH_TXBUF_RESET(_bf) do { \ - (_bf)->bf_status = 0; \ + (_bf)->bf_stale = false; \ (_bf)->bf_lastbf = NULL; \ (_bf)->bf_next = NULL; \ memset(&((_bf)->bf_state), 0, \ sizeof(struct ath_buf_state)); \ } while (0) +#define ATH_RXBUF_RESET(_bf) do { \ + (_bf)->bf_stale = false; \ + } while (0) + /** * enum buffer_type - Buffer type flags * @@ -110,7 +109,7 @@ struct ath_buf_state { int bfs_seqno; int bfs_tidno; int bfs_retries; - u32 bf_type; + u8 bf_type; u32 bfs_keyix; enum ath9k_key_type bfs_keytype; }; @@ -134,26 +133,21 @@ struct ath_buf { struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or an aggregate) */ struct ath_buf *bf_next; /* next subframe in the aggregate */ - void *bf_mpdu; /* enclosing frame structure */ + struct sk_buff *bf_mpdu; /* enclosing frame structure */ struct ath_desc *bf_desc; /* virtual addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer */ - u32 bf_status; + bool bf_stale; u16 bf_flags; struct ath_buf_state bf_state; dma_addr_t bf_dmacontext; }; -#define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0) -#define ATH_BUFSTATUS_STALE 0x00000002 - struct ath_descdma { - const char *dd_name; struct ath_desc *dd_desc; dma_addr_t dd_desc_paddr; u32 dd_desc_len; struct ath_buf *dd_bufptr; - dma_addr_t dd_dmacontext; }; int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, @@ -299,26 +293,6 @@ struct ath_tx_control { #define ATH_TX_XRETRY 0x02 #define ATH_TX_BAR 0x04 -/* All RSSI values are noise floor adjusted */ -struct ath_tx_stat { - int rssi; - int rssictl[ATH_MAX_ANTENNA]; - int rssiextn[ATH_MAX_ANTENNA]; - int rateieee; - int rateKbps; - int ratecode; - int flags; - u32 airtime; /* time on air per final tx rate */ -}; - -struct aggr_rifs_param { - int param_max_frames; - int param_max_len; - int param_rl; - int param_al; - struct ath_rc_series *param_rcs; -}; - struct ath_node { struct ath_softc *an_sc; struct ath_atx_tid tid[WME_NUM_TID]; @@ -366,7 +340,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_init(struct ath_softc *sc, int nbufs); -int ath_tx_cleanup(struct ath_softc *sc); +void ath_tx_cleanup(struct ath_softc *sc); struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); @@ -486,12 +460,9 @@ struct ath_led { bool registered; }; -/* Rfkill */ -#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */ - struct ath_rfkill { struct rfkill *rfkill; - struct delayed_work rfkill_poll; + struct rfkill_ops ops; char rfkill_name[32]; }; @@ -529,19 +500,20 @@ struct ath_rfkill { #define SC_OP_BEACONS BIT(1) #define SC_OP_RXAGGR BIT(2) #define SC_OP_TXAGGR BIT(3) -#define SC_OP_CHAINMASK_UPDATE BIT(4) -#define SC_OP_FULL_RESET BIT(5) -#define SC_OP_PREAMBLE_SHORT BIT(6) -#define SC_OP_PROTECT_ENABLE BIT(7) -#define SC_OP_RXFLUSH BIT(8) -#define SC_OP_LED_ASSOCIATED BIT(9) -#define SC_OP_RFKILL_REGISTERED BIT(10) -#define SC_OP_RFKILL_SW_BLOCKED BIT(11) -#define SC_OP_RFKILL_HW_BLOCKED BIT(12) -#define SC_OP_WAIT_FOR_BEACON BIT(13) -#define SC_OP_LED_ON BIT(14) -#define SC_OP_SCANNING BIT(15) -#define SC_OP_TSF_RESET BIT(16) +#define SC_OP_FULL_RESET BIT(4) +#define SC_OP_PREAMBLE_SHORT BIT(5) +#define SC_OP_PROTECT_ENABLE BIT(6) +#define SC_OP_RXFLUSH BIT(7) +#define SC_OP_LED_ASSOCIATED BIT(8) +#define SC_OP_RFKILL_REGISTERED BIT(9) +#define SC_OP_WAIT_FOR_BEACON BIT(12) +#define SC_OP_LED_ON BIT(13) +#define SC_OP_SCANNING BIT(14) +#define SC_OP_TSF_RESET BIT(15) +#define SC_OP_WAIT_FOR_CAB BIT(16) +#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) +#define SC_OP_WAIT_FOR_TX_ACK BIT(18) +#define SC_OP_BEACON_SYNC BIT(19) struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); @@ -603,8 +575,8 @@ struct ath_softc { struct ath_tx tx; struct ath_beacon beacon; struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; - struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; - struct ath_rate_table *cur_rate_table; + const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; + const struct ath_rate_table *cur_rate_table; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ath_led radio_led; @@ -617,6 +589,8 @@ struct ath_softc { int led_on_cnt; int led_off_cnt; + int beacon_interval; + struct ath_rfkill rf_kill; struct ath_ani ani; struct ath9k_node_stats nodestats; @@ -624,6 +598,7 @@ struct ath_softc { struct ath9k_debug debug; #endif struct ath_bus_ops *bus_ops; + struct ath_beacon_config cur_beacon_conf; }; struct ath_wiphy { @@ -701,7 +676,9 @@ 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->sc_flags & (SC_OP_WAIT_FOR_BEACON | + SC_OP_WAIT_FOR_PSPOLL_DATA | + SC_OP_WAIT_FOR_TX_ACK))) ath9k_hw_setpower(sc->sc_ah, sc->sc_ah->restore_mode); } @@ -722,36 +699,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, bool ath9k_wiphy_scanning(struct ath_softc *sc); void ath9k_wiphy_work(struct work_struct *work); -/* - * Read and write, they both share the same lock. We do this to serialize - * reads and writes on Atheros 802.11n PCI devices only. This is required - * as the FIFO on these devices can only accept sanely 2 requests. After - * that the device goes bananas. Serializing the reads/writes prevents this - * from happening. - */ - -static inline void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) -{ - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - iowrite32(val, ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - iowrite32(val, ah->ah_sc->mem + reg_offset); -} - -static inline unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) -{ - u32 val; - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - val = ioread32(ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - val = ioread32(ah->ah_sc->mem + reg_offset); - return val; -} +void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); +unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); #endif /* ATH9K_H */ diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c similarity index 90% rename from drivers/net/wireless/ath9k/beacon.c rename to drivers/net/wireless/ath/ath9k/beacon.c index ec995730632d..3639a2e6987d 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -43,7 +43,7 @@ static int ath_beaconq_config(struct ath_softc *sc) if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { DPRINTF(sc, ATH_DBG_FATAL, - "unable to update h/w beacon queue parameters\n"); + "Unable to update h/w beacon queue parameters\n"); return 0; } else { ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); @@ -59,11 +59,11 @@ static int ath_beaconq_config(struct ath_softc *sc) static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_buf *bf) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; struct ath_hw *ah = sc->sc_ah; struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; - struct ath_rate_table *rt; + const struct ath_rate_table *rt; int flags, antenna, ctsrate = 0, ctsduration = 0; u8 rate; @@ -132,16 +132,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, avp = (void *)vif->drv_priv; cabq = sc->beacon.cabq; - if (avp->av_bcbuf == NULL) { - DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n", - avp, avp->av_bcbuf); + if (avp->av_bcbuf == NULL) return NULL; - } /* Release the old beacon first */ bf = avp->av_bcbuf; - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; if (skb) { dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); @@ -229,7 +226,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, return; bf = avp->av_bcbuf; - skb = (struct sk_buff *) bf->bf_mpdu; + skb = bf->bf_mpdu; ath_beacon_setup(sc, avp, bf); @@ -302,7 +299,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) /* release the previous beacon frame, if it already exists. */ bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); @@ -323,8 +320,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) u64 tsfadjust; int intval; - intval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; /* * Calculate the TSF offset for this beacon slot, i.e., the @@ -374,7 +370,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); @@ -415,6 +411,7 @@ void ath_beacon_tasklet(unsigned long data) } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { DPRINTF(sc, ATH_DBG_BEACON, "beacon is officially stuck\n"); + sc->sc_flags |= SC_OP_TSF_RESET; ath_reset(sc, false); } @@ -434,8 +431,7 @@ void ath_beacon_tasklet(unsigned long data) * on the tsf to safeguard against missing an swba. */ - intval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf); @@ -512,8 +508,7 @@ void ath_beacon_tasklet(unsigned long data) * slot. Slots that are not occupied will generate nothing. */ static void ath_beacon_config_ap(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ath_vif *avp) + struct ath_beacon_config *conf) { u32 nexttbtt, intval; @@ -558,14 +553,14 @@ static void ath_beacon_config_ap(struct ath_softc *sc, * we've associated with. */ static void ath_beacon_config_sta(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ath_vif *avp) + struct ath_beacon_config *conf) { struct ath9k_beacon_state bs; int dtimperiod, dtimcount, sleepduration; int cfpperiod, cfpcount; u32 nexttbtt = 0, intval, tsftu; u64 tsf; + int num_beacons, offset, dtim_dec_count, cfp_dec_count; memset(&bs, 0, sizeof(bs)); intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; @@ -593,14 +588,27 @@ static void ath_beacon_config_sta(struct ath_softc *sc, */ tsf = ath9k_hw_gettsf64(sc->sc_ah); tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; - do { + + num_beacons = tsftu / intval + 1; + offset = tsftu % intval; + nexttbtt = tsftu - offset; + if (offset) nexttbtt += intval; - if (--dtimcount < 0) { - dtimcount = dtimperiod - 1; - if (--cfpcount < 0) - cfpcount = cfpperiod - 1; - } - } while (nexttbtt < tsftu); + + /* DTIM Beacon every dtimperiod Beacon */ + dtim_dec_count = num_beacons % dtimperiod; + /* CFP every cfpperiod DTIM Beacon */ + cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; + if (dtim_dec_count) + cfp_dec_count++; + + dtimcount -= dtim_dec_count; + if (dtimcount < 0) + dtimcount += dtimperiod; + + cfpcount -= cfp_dec_count; + if (cfpcount < 0) + cfpcount += cfpperiod; bs.bs_intval = intval; bs.bs_nexttbtt = nexttbtt; @@ -659,7 +667,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, static void ath_beacon_config_adhoc(struct ath_softc *sc, struct ath_beacon_config *conf, - struct ath_vif *avp, struct ieee80211_vif *vif) { u64 tsf; @@ -667,6 +674,14 @@ 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 */ nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); @@ -703,44 +718,50 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) + /* FIXME: Handle properly when vif is NULL */ + if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) ath_beacon_start_adhoc(sc, vif); } void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) { - struct ath_beacon_config conf; + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; + enum nl80211_iftype iftype; /* Setup the beacon configuration parameters */ - memset(&conf, 0, sizeof(struct ath_beacon_config)); - conf.beacon_interval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; - conf.listen_interval = 1; - conf.dtim_period = conf.beacon_interval; - conf.dtim_count = 1; - conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; - if (vif) { - struct ath_vif *avp = (struct ath_vif *)vif->drv_priv; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - switch(avp->av_opmode) { - case NL80211_IFTYPE_AP: - ath_beacon_config_ap(sc, &conf, avp); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - ath_beacon_config_adhoc(sc, &conf, avp, vif); - break; - case NL80211_IFTYPE_STATION: - ath_beacon_config_sta(sc, &conf, avp); - break; - default: - DPRINTF(sc, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); - return; - } + iftype = vif->type; - sc->sc_flags |= SC_OP_BEACONS; + cur_conf->beacon_interval = bss_conf->beacon_int; + cur_conf->dtim_period = bss_conf->dtim_period; + cur_conf->listen_interval = 1; + cur_conf->dtim_count = 1; + cur_conf->bmiss_timeout = + ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; + } else { + iftype = sc->sc_ah->opmode; } + + + switch (iftype) { + case NL80211_IFTYPE_AP: + ath_beacon_config_ap(sc, cur_conf); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + ath_beacon_config_adhoc(sc, cur_conf, vif); + break; + case NL80211_IFTYPE_STATION: + ath_beacon_config_sta(sc, cur_conf); + break; + default: + DPRINTF(sc, ATH_DBG_CONFIG, + "Unsupported beaconing mode\n"); + return; + } + + sc->sc_flags |= SC_OP_BEACONS; } diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c similarity index 90% rename from drivers/net/wireless/ath9k/calib.c rename to drivers/net/wireless/ath/ath9k/calib.c index e2d62e97131c..a32d7e7fecbe 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -186,7 +186,7 @@ static bool getNoiseFloorThresh(struct ath_hw *ah, } static void ath9k_hw_setup_calibration(struct ath_hw *ah, - struct hal_cal_list *currCal) + struct ath9k_cal_list *currCal) { REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, @@ -220,7 +220,7 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah, } static void ath9k_hw_reset_calibration(struct ath_hw *ah, - struct hal_cal_list *currCal) + struct ath9k_cal_list *currCal) { int i; @@ -238,13 +238,12 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah, ah->cal_samples = 0; } -static void ath9k_hw_per_calibration(struct ath_hw *ah, +static bool ath9k_hw_per_calibration(struct ath_hw *ah, struct ath9k_channel *ichan, u8 rxchainmask, - struct hal_cal_list *currCal, - bool *isCalDone) + struct ath9k_cal_list *currCal) { - *isCalDone = false; + bool iscaldone = false; if (currCal->calState == CAL_RUNNING) { if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & @@ -263,7 +262,7 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah, currCal->calData->calPostProc(ah, numChains); ichan->CalValid |= currCal->calData->calType; currCal->calState = CAL_DONE; - *isCalDone = true; + iscaldone = true; } else { ath9k_hw_setup_calibration(ah, currCal); } @@ -271,11 +270,13 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah, } else if (!(ichan->CalValid & currCal->calData->calType)) { ath9k_hw_reset_calibration(ah, currCal); } + + return iscaldone; } /* Assumes you are talking about the currently configured channel */ static bool ath9k_hw_iscal_supported(struct ath_hw *ah, - enum hal_cal_types calType) + enum ath9k_cal_types calType) { struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; @@ -284,8 +285,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hw *ah, return true; case ADC_GAIN_CAL: case ADC_DC_CAL: - if (conf->channel->band == IEEE80211_BAND_5GHZ && - conf_is_ht20(conf)) + if (!(conf->channel->band == IEEE80211_BAND_2GHZ && + conf_is_ht20(conf))) return true; break; } @@ -498,7 +499,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) { u32 iOddMeasOffset, iEvenMeasOffset, val, i; int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; - const struct hal_percal_data *calData = + const struct ath9k_percal_data *calData = ah->cal_list_curr->calData; u32 numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples; @@ -555,7 +556,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) bool ath9k_hw_reset_calvalid(struct ath_hw *ah) { struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct hal_cal_list *currCal = ah->cal_list_curr; + struct ath9k_cal_list *currCal = ah->cal_list_curr; if (!ah->curchan) return true; @@ -841,30 +842,28 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) } bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone) + u8 rxchainmask, bool longcal) { - struct hal_cal_list *currCal = ah->cal_list_curr; - - *isCalDone = true; + bool iscaldone = true; + struct ath9k_cal_list *currCal = ah->cal_list_curr; if (currCal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { - ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, - isCalDone); - if (*isCalDone) { + iscaldone = ath9k_hw_per_calibration(ah, chan, + rxchainmask, currCal); + if (iscaldone) { ah->cal_list_curr = currCal = currCal->calNext; if (currCal->calState == CAL_WAITING) { - *isCalDone = false; + iscaldone = false; ath9k_hw_reset_calibration(ah, currCal); } } } if (longcal) { - if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + if (AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah); if (OLC_FOR_AR9280_20_LATER) @@ -872,18 +871,15 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_getnf(ah, chan); ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah); - - if (chan->channelFlags & CHANNEL_CW_INT) - chan->channelFlags &= ~CHANNEL_CW_INT; } - return true; + return iscaldone; } static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - if (chan->channelFlags & CHANNEL_HT20) { + if (IS_CHAN_HT20(chan)) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, @@ -919,83 +915,66 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) return true; } -bool ath9k_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan) +bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { - if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { + if (AR_SREV_9285_12_OR_LATER(ah)) { if (!ar9285_clc(ah, 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); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } 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); + } - /* Kick off the cal */ + /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, - AH_WAIT_TIMEOUT)) { + /* Poll for offset calibration complete */ + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration failed to complete in 1ms; " "noisy environment?\n"); return false; } - 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); - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - } - - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); - - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; " - "noisy environment?\n"); - return false; - } - - 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_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); + } } /* Do PA Calibration */ - if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + if (AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah); - /* Do NF Calibration */ + /* Do NF Calibration after DC offset and other calibrations */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_NF); + REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + /* Enable IQ, ADC Gain and ADC DC offset CALs */ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); + "enabling ADC Gain Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + "enabling ADC DC Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { INIT_CAL(&ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + "enabling IQ Calibration.\n"); } ah->cal_list_curr = ah->cal_list; @@ -1009,49 +988,49 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, return true; } -const struct hal_percal_data iq_cal_multi_sample = { +const struct ath9k_percal_data iq_cal_multi_sample = { IQ_MISMATCH_CAL, MAX_CAL_SAMPLES, PER_MIN_LOG_COUNT, ath9k_hw_iqcal_collect, ath9k_hw_iqcalibrate }; -const struct hal_percal_data iq_cal_single_sample = { +const struct ath9k_percal_data iq_cal_single_sample = { IQ_MISMATCH_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ath9k_hw_iqcal_collect, ath9k_hw_iqcalibrate }; -const struct hal_percal_data adc_gain_cal_multi_sample = { +const struct ath9k_percal_data adc_gain_cal_multi_sample = { ADC_GAIN_CAL, MAX_CAL_SAMPLES, PER_MIN_LOG_COUNT, ath9k_hw_adc_gaincal_collect, ath9k_hw_adc_gaincal_calibrate }; -const struct hal_percal_data adc_gain_cal_single_sample = { +const struct ath9k_percal_data adc_gain_cal_single_sample = { ADC_GAIN_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ath9k_hw_adc_gaincal_collect, ath9k_hw_adc_gaincal_calibrate }; -const struct hal_percal_data adc_dc_cal_multi_sample = { +const struct ath9k_percal_data adc_dc_cal_multi_sample = { ADC_DC_CAL, MAX_CAL_SAMPLES, PER_MIN_LOG_COUNT, ath9k_hw_adc_dccal_collect, ath9k_hw_adc_dccal_calibrate }; -const struct hal_percal_data adc_dc_cal_single_sample = { +const struct ath9k_percal_data adc_dc_cal_single_sample = { ADC_DC_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ath9k_hw_adc_dccal_collect, ath9k_hw_adc_dccal_calibrate }; -const struct hal_percal_data adc_init_dc_cal = { +const struct ath9k_percal_data adc_init_dc_cal = { ADC_DC_INIT_CAL, MIN_CAL_SAMPLES, INIT_LOG_COUNT, diff --git a/drivers/net/wireless/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h similarity index 81% rename from drivers/net/wireless/ath9k/calib.h rename to drivers/net/wireless/ath/ath9k/calib.h index 1c74bd50700d..fe5367f14148 100644 --- a/drivers/net/wireless/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -17,13 +17,13 @@ #ifndef CALIB_H #define CALIB_H -extern const struct hal_percal_data iq_cal_multi_sample; -extern const struct hal_percal_data iq_cal_single_sample; -extern const struct hal_percal_data adc_gain_cal_multi_sample; -extern const struct hal_percal_data adc_gain_cal_single_sample; -extern const struct hal_percal_data adc_dc_cal_multi_sample; -extern const struct hal_percal_data adc_dc_cal_single_sample; -extern const struct hal_percal_data adc_init_dc_cal; +extern const struct ath9k_percal_data iq_cal_multi_sample; +extern const struct ath9k_percal_data iq_cal_single_sample; +extern const struct ath9k_percal_data adc_gain_cal_multi_sample; +extern const struct ath9k_percal_data adc_gain_cal_single_sample; +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_HIGH_VALUE -62 @@ -67,14 +67,14 @@ struct ar5416IniArray { } \ } while (0) -enum hal_cal_types { +enum ath9k_cal_types { ADC_DC_INIT_CAL = 0x1, ADC_GAIN_CAL = 0x2, ADC_DC_CAL = 0x4, IQ_MISMATCH_CAL = 0x8 }; -enum hal_cal_state { +enum ath9k_cal_state { CAL_INACTIVE, CAL_WAITING, CAL_RUNNING, @@ -87,18 +87,18 @@ enum hal_cal_state { #define PER_MIN_LOG_COUNT 2 #define PER_MAX_LOG_COUNT 10 -struct hal_percal_data { - enum hal_cal_types calType; +struct ath9k_percal_data { + enum ath9k_cal_types calType; u32 calNumSamples; u32 calCountMax; void (*calCollect) (struct ath_hw *); void (*calPostProc) (struct ath_hw *, u8); }; -struct hal_cal_list { - const struct hal_percal_data *calData; - enum hal_cal_state calState; - struct hal_cal_list *calNext; +struct ath9k_cal_list { + const struct ath9k_percal_data *calData; + enum ath9k_cal_state calState; + struct ath9k_cal_list *calNext; }; struct ath9k_nfcal_hist { @@ -116,8 +116,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone); + u8 rxchainmask, bool longcal); bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan); diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c similarity index 87% rename from drivers/net/wireless/ath9k/debug.c rename to drivers/net/wireless/ath/ath9k/debug.c index fdf9528fa49b..6d20725d6451 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -44,6 +44,44 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file) return 0; } +static ssize_t read_file_debug(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[32]; + unsigned int len; + + len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + unsigned long mask; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EINVAL; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &mask)) + return -EINVAL; + + sc->debug.debug_mask = mask; + return count; +} + +static const struct file_operations fops_debug = { + .read = read_file_debug, + .write = write_file_debug, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + static ssize_t read_file_dma(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -224,111 +262,66 @@ static const struct file_operations fops_interrupt = { .owner = THIS_MODULE }; -static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_tx_info_priv *tx_info_priv = NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->status.rates; - int final_ts_idx, idx; - - tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - final_ts_idx = tx_info_priv->tx.ts_rateindex; - idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate; - - sc->debug.stats.n_rcstats[idx].success++; -} - -static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb) +void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) { struct ath_tx_info_priv *tx_info_priv = NULL; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->status.rates; int final_ts_idx, idx; + struct ath_rc_stats *stats; tx_info_priv = ATH_TX_INFO_PRIV(tx_info); final_ts_idx = tx_info_priv->tx.ts_rateindex; idx = rates[final_ts_idx].idx; - - sc->debug.stats.legacy_rcstats[idx].success++; + stats = &sc->debug.stats.rcstats[idx]; + stats->success++; } -void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) -{ - if (conf_is_ht(&sc->hw->conf)) - ath_debug_stat_11n_rc(sc, skb); - else - ath_debug_stat_legacy_rc(sc, skb); -} - -/* FIXME: legacy rates, later on .. */ void ath_debug_stat_retries(struct ath_softc *sc, int rix, int xretries, int retries, u8 per) { - if (conf_is_ht(&sc->hw->conf)) { - int idx = sc->cur_rate_table->info[rix].dot11rate; + struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix]; - sc->debug.stats.n_rcstats[idx].xretries += xretries; - sc->debug.stats.n_rcstats[idx].retries += retries; - sc->debug.stats.n_rcstats[idx].per = per; - } -} - -static ssize_t ath_read_file_stat_11n_rc(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[1024]; - unsigned int len = 0; - int i = 0; - - len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success", - "Retries", "XRetries", "PER"); - - for (i = 0; i <= 15; i++) { - len += snprintf(buf + len, sizeof(buf) - len, - "%5s%3d: %8u %8u %8u %8u\n", "MCS", i, - sc->debug.stats.n_rcstats[i].success, - sc->debug.stats.n_rcstats[i].retries, - sc->debug.stats.n_rcstats[i].xretries, - sc->debug.stats.n_rcstats[i].per); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t ath_read_file_stat_legacy_rc(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[512]; - unsigned int len = 0; - int i = 0; - - len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); - - for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { - len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n", - sc->cur_rate_table->info[i].ratekbps / 1000, - sc->debug.stats.legacy_rcstats[i].success); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); + stats->xretries += xretries; + stats->retries += retries; + stats->per = per; } static ssize_t read_file_rcstat(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, max; + int i = 0; + ssize_t retval; if (sc->cur_rate_table == NULL) return 0; - if (conf_is_ht(&sc->hw->conf)) - return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); - else - return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos); + max = 80 + sc->cur_rate_table->rate_cnt * 64; + buf = kmalloc(max + 1, GFP_KERNEL); + if (buf == NULL) + return 0; + buf[max] = 0; + + len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success", + "Retries", "XRetries", "PER"); + + for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { + u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; + struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; + + len += snprintf(buf + len, max - len, + "%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000, + (ratekbps % 1000) / 100, stats->success, + stats->retries, stats->xretries, + stats->per); + } + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return retval; } static const struct file_operations fops_rcstat = { @@ -498,11 +491,19 @@ int ath9k_init_debug(struct ath_softc *sc) { sc->debug.debug_mask = ath9k_debug; + if (!ath9k_debugfs_root) + return -ENOENT; + sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), ath9k_debugfs_root); if (!sc->debug.debugfs_phy) goto err; + sc->debug.debugfs_debug = debugfs_create_file("debug", + S_IRUGO | 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_phy, sc, &fops_dma); if (!sc->debug.debugfs_dma) @@ -540,6 +541,7 @@ void ath9k_exit_debug(struct ath_softc *sc) debugfs_remove(sc->debug.debugfs_rcstat); debugfs_remove(sc->debug.debugfs_interrupt); debugfs_remove(sc->debug.debugfs_dma); + debugfs_remove(sc->debug.debugfs_debug); debugfs_remove(sc->debug.debugfs_phy); } diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h similarity index 84% rename from drivers/net/wireless/ath9k/debug.h rename to drivers/net/wireless/ath/ath9k/debug.h index 7b0e5419d2bc..edda15bf2c15 100644 --- a/drivers/net/wireless/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -19,20 +19,17 @@ enum ATH_DEBUG { ATH_DBG_RESET = 0x00000001, - ATH_DBG_REG_IO = 0x00000002, - ATH_DBG_QUEUE = 0x00000004, - ATH_DBG_EEPROM = 0x00000008, - ATH_DBG_CALIBRATE = 0x00000010, - ATH_DBG_CHANNEL = 0x00000020, - ATH_DBG_INTERRUPT = 0x00000040, - ATH_DBG_REGULATORY = 0x00000080, - ATH_DBG_ANI = 0x00000100, - ATH_DBG_POWER_MGMT = 0x00000200, - ATH_DBG_XMIT = 0x00000400, - ATH_DBG_BEACON = 0x00001000, - ATH_DBG_CONFIG = 0x00002000, - ATH_DBG_KEYCACHE = 0x00004000, - ATH_DBG_FATAL = 0x00008000, + ATH_DBG_QUEUE = 0x00000002, + ATH_DBG_EEPROM = 0x00000004, + ATH_DBG_CALIBRATE = 0x00000008, + ATH_DBG_INTERRUPT = 0x00000010, + ATH_DBG_REGULATORY = 0x00000020, + ATH_DBG_ANI = 0x00000040, + ATH_DBG_XMIT = 0x00000080, + ATH_DBG_BEACON = 0x00000100, + ATH_DBG_CONFIG = 0x00000200, + ATH_DBG_FATAL = 0x00000400, + ATH_DBG_PS = 0x00000800, ATH_DBG_ANY = 0xffffffff }; @@ -83,11 +80,7 @@ struct ath_interrupt_stats { u32 dtim; }; -struct ath_legacy_rc_stats { - u32 success; -}; - -struct ath_11n_rc_stats { +struct ath_rc_stats { u32 success; u32 retries; u32 xretries; @@ -96,13 +89,13 @@ struct ath_11n_rc_stats { struct ath_stats { struct ath_interrupt_stats istats; - struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */ - struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */ + struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; }; struct ath9k_debug { int debug_mask; struct dentry *debugfs_phy; + struct dentry *debugfs_debug; struct dentry *debugfs_dma; struct dentry *debugfs_interrupt; struct dentry *debugfs_rcstat; diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c similarity index 98% rename from drivers/net/wireless/ath9k/eeprom.c rename to drivers/net/wireless/ath/ath9k/eeprom.c index ffc36b0361c7..a2fda702b620 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -694,7 +694,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, #undef TMP_VAL_VPD_TABLE } -static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, +static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset) { @@ -783,11 +783,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + 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_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PDADC: Chain %d | " "PDADC %3d Value %3d | " "PDADC %3d Value %3d | " @@ -805,11 +805,9 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, } *pTxPowerIndexOffset = 0; - - return true; } -static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, +static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, @@ -910,7 +908,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ah->eep_ops->get_eeprom_rev(ah) <= 2) twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " "EXT_ADDITIVE %d\n", ctlMode, numCtlModes, isHt40CtlMode, @@ -918,7 +916,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + 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", @@ -941,7 +939,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, IS_CHAN_2GHZ(chan), AR5416_EEP4K_NUM_BAND_EDGES); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + 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), @@ -961,7 +959,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " SEL-Min ctlMode %d pCtlMode %d " "2xMaxEdge %d sP %d minCtlPwr %d\n", ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, @@ -1041,10 +1039,9 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; } - return true; } -static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, +static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, @@ -1065,22 +1062,13 @@ static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; } - if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan, + ath9k_hw_set_4k_power_per_rate_table(ah, chan, &ratesArray[0], cfgCtl, twiceAntennaReduction, twiceMaxRegulatoryPower, - powerLimit)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set " - "tx power per rate table\n"); - return -EIO; - } + powerLimit); - if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set power table\n"); - return -EIO; - } + 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]); @@ -1168,7 +1156,6 @@ static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, else ah->regulatory.max_power_level = ratesArray[i]; - return 0; } static void ath9k_hw_4k_set_addac(struct ath_hw *ah, @@ -2103,7 +2090,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, return; } -static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, +static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset) { @@ -2234,11 +2221,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + 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_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PDADC: Chain %d | PDADC %3d " "Value %3d | PDADC %3d Value %3d | " "PDADC %3d Value %3d | PDADC %3d " @@ -2255,13 +2242,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, } *pTxPowerIndexOffset = 0; - - return true; #undef SM_PD_GAIN #undef SM_PDGAIN_B } -static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, +static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, @@ -2415,14 +2400,14 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ah->eep_ops->get_eeprom_rev(ah) <= 2) twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + 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_POWER_MGMT, + 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", @@ -2441,7 +2426,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + 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), @@ -2460,7 +2445,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, minCtlPower = min(twiceMaxEdgePower, scaledPower); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " SEL-Min ctlMode %d pCtlMode %d " "2xMaxEdge %d sP %d minCtlPwr %d\n", ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, @@ -2549,10 +2534,9 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, targetPowerCckExt.tPow2x[0]; } } - return true; } -static int ath9k_hw_def_set_txpower(struct ath_hw *ah, +static void ath9k_hw_def_set_txpower(struct ath_hw *ah, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, @@ -2575,22 +2559,13 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah, ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; } - if (!ath9k_hw_set_def_power_per_rate_table(ah, chan, + ath9k_hw_set_def_power_per_rate_table(ah, chan, &ratesArray[0], cfgCtl, twiceAntennaReduction, twiceMaxRegulatoryPower, - powerLimit)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set " - "tx power per rate table\n"); - return -EIO; - } + powerLimit); - if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set power table\n"); - return -EIO; - } + 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]); @@ -2717,8 +2692,6 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah, "Invalid chainmask configuration\n"); break; } - - return 0; } static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h similarity index 99% rename from drivers/net/wireless/ath9k/eeprom.h rename to drivers/net/wireless/ath/ath9k/eeprom.h index 25b68c881ff1..67b8bd12941a 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -17,6 +17,8 @@ #ifndef EEPROM_H #define EEPROM_H +#include + #define AH_USE_EEPROM 0x1 #ifdef __BIG_ENDIAN @@ -492,7 +494,7 @@ struct eeprom_ops { struct ath9k_channel *chan); void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); - int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, + void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, u8 powerLimit); u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c similarity index 95% rename from drivers/net/wireless/ath9k/hw.c rename to drivers/net/wireless/ath/ath9k/hw.c index b15eaf8417ff..1579c9407ed5 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -84,6 +84,38 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) return ath9k_hw_mac_clks(ah, usecs); } +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) +{ + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + iowrite32(val, ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + iowrite32(val, ah->ah_sc->mem + reg_offset); +} + +unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) +{ + u32 val; + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + val = ioread32(ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + val = ioread32(ah->ah_sc->mem + reg_offset); + return val; +} + bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) { int i; @@ -97,7 +129,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) udelay(AH_TIME_QUANTUM); } - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", timeout, reg, REG_READ(ah, reg), mask, val); @@ -136,7 +168,7 @@ bool ath9k_get_channel_edges(struct ath_hw *ah, } u16 ath9k_hw_computetxtime(struct ath_hw *ah, - struct ath_rate_table *rates, + const struct ath_rate_table *rates, u32 frameLen, u16 rateix, bool shortPreamble) { @@ -181,7 +213,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, } break; default: - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Unknown phy %u (rate ix %u)\n", rates->info[rateix].phy, rateix); txTime = 0; @@ -306,7 +338,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (rdData != wrData) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "address test failed " "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", addr, wrData, rdData); @@ -318,7 +350,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (wrData != rdData) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "address test failed " "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", addr, wrData, rdData); @@ -363,10 +395,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ah->config.ack_6mb = 0x0; ah->config.cwm_ignore_extcca = 0; ah->config.pcie_powersave_enable = 0; - ah->config.pcie_l1skp_enable = 0; ah->config.pcie_clock_req = 0; - ah->config.pcie_power_reset = 0x100; - ah->config.pcie_restore = 0; ah->config.pcie_waen = 0; ah->config.analog_shiftreg = 1; ah->config.ht_enable = 1; @@ -375,13 +404,6 @@ 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.noise_immunity_level = 4; - ah->config.ofdm_weaksignal_det = 1; - ah->config.cck_weaksignal_thr = 0; - ah->config.spur_immunity_level = 2; - ah->config.firstep_level = 0; - ah->config.rssi_thr_high = 40; - ah->config.rssi_thr_low = 7; ah->config.diversity_control = 0; ah->config.antenna_switch_swap = 0; @@ -390,7 +412,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } - ah->config.intr_mitigation = 1; + ah->config.intr_mitigation = true; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) @@ -463,8 +485,8 @@ static int ath9k_hw_rfattach(struct ath_hw *ah) rfStatus = ath9k_hw_init_rf(ah, &ecode); if (!rfStatus) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "RF setup failed, status %u\n", ecode); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "RF setup failed, status: %u\n", ecode); return ecode; } @@ -488,10 +510,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) case AR_RAD2122_SREV_MAJOR: break; default: - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "5G Radio Chip Rev 0x%02X is not " - "supported by this driver\n", - ah->hw_version.analog5GhzRev); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Radio Chip Rev 0x%02X not supported\n", + val & AR_RADIO_SREV_MAJOR); return -EOPNOTSUPP; } @@ -513,12 +534,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) ah->macaddr[2 * i] = eeval >> 8; ah->macaddr[2 * i + 1] = eeval & 0xff; } - if (sum == 0 || sum == 0xffff * 3) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "mac address read failed: %pM\n", - ah->macaddr); + if (sum == 0 || sum == 0xffff * 3) return -EADDRNOTAVAIL; - } return 0; } @@ -575,11 +592,8 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) { int ecode; - if (!ath9k_hw_chip_test(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, - "hardware self-test failed\n"); + if (!ath9k_hw_chip_test(ah)) return -ENODEV; - } ecode = ath9k_hw_rf_claim(ah); if (ecode != 0) @@ -617,17 +631,14 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ath9k_hw_set_defaults(ah); - if (ah->config.intr_mitigation != 0) - ah->intr_mitigation = true; - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - DPRINTF(sc, ATH_DBG_RESET, "Couldn't reset chip\n"); + 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_RESET, "Couldn't wakeup chip\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); ecode = -EIO; goto bad; } @@ -650,7 +661,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, (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_RESET, + 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); @@ -690,10 +701,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, if (AR_SREV_9280_10_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - DPRINTF(sc, ATH_DBG_RESET, - "This Mac Chip Rev 0x%02x.%x is \n", - ah->hw_version.macVersion, ah->hw_version.macRev); - if (AR_SREV_9285_12_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, @@ -859,11 +866,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, if (AR_SREV_9280_20(ah)) ath9k_hw_init_txgain_ini(ah); - if (!ath9k_hw_fill_cap_info(ah)) { - DPRINTF(sc, ATH_DBG_RESET, "failed ath9k_hw_fill_cap_info\n"); - ecode = -EINVAL; - goto bad; - } + ath9k_hw_fill_cap_info(ah); if ((ah->hw_version.devid == AR9280_DEVID_PCI) && test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { @@ -885,8 +888,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ecode = ath9k_hw_init_macaddr(ah); if (ecode != 0) { - DPRINTF(sc, ATH_DBG_RESET, - "failed initializing mac address\n"); + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to initialize MAC address\n"); goto bad; } @@ -1054,7 +1057,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, AR_IMR_RXORN | AR_IMR_BCNMISC; - if (ah->intr_mitigation) + if (ah->config.intr_mitigation) ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; else ah->mask_reg |= AR_IMR_RXOK; @@ -1203,23 +1206,23 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, switch (ah->hw_version.devid) { case AR9280_DEVID_PCI: if (reg == 0x7894) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "ini VAL: %x EEPROM: %x\n", value, (pBase->version & 0xff)); if ((pBase->version & 0xff) > 0x0a) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PWDCLKIND: %d\n", pBase->pwdclkind); value &= ~AR_AN_TOP2_PWDCLKIND; value |= AR_AN_TOP2_PWDCLKIND & (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); } else { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PWDCLKIND Earlier Rev\n"); } - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "final ini VAL: %x\n", value); } break; @@ -1249,6 +1252,21 @@ static void ath9k_olc_init(struct ath_hw *ah) ah->PDADCdelta = 0; } +static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, + struct ath9k_channel *chan) +{ + u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); + + if (IS_CHAN_B(chan)) + ctl |= CTL_11B; + else if (IS_CHAN_G(chan)) + ctl |= CTL_11G; + else + ctl |= CTL_11A; + + return ctl; +} + static int ath9k_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) @@ -1256,7 +1274,6 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, int i, regWrites = 0; struct ieee80211_channel *channel = chan->chan; u32 modesIndex, freqIndex; - int status; switch (chan->chanmode) { case CHANNEL_A: @@ -1327,8 +1344,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, if (AR_SREV_9280(ah)) REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) && - AR_SREV_9285_12_OR_LATER(ah))) + if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah)) REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); for (i = 0; i < ah->iniCommon.ia_rows; i++) { @@ -1359,20 +1375,15 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, if (OLC_FOR_AR9280_20_LATER) ath9k_olc_init(ah); - status = ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(ah, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)); - if (status != 0) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, - "error init'ing transmit power\n"); - return -EIO; - } + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(&ah->regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) ah->regulatory.power_limit)); if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "ar5416SetRfRegs failed\n"); return -EIO; } @@ -1600,11 +1611,9 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) switch (type) { case ATH9K_RESET_POWER_ON: return ath9k_hw_set_reset_power_on(ah); - break; case ATH9K_RESET_WARM: case ATH9K_RESET_COLD: return ath9k_hw_set_reset(ah, type); - break; default: return false; } @@ -1678,7 +1687,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Could not kill baseband RX\n"); return false; } @@ -1686,29 +1695,21 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, ath9k_hw_set_regs(ah, chan, macmode); if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "failed to set channel\n"); - return false; - } + ath9k_hw_ar9280_set_channel(ah, chan); } else { if (!(ath9k_hw_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "failed to set channel\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Failed to set channel\n"); return false; } } - if (ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(ah, chan), + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(&ah->regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)) != 0) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "error init'ing transmit power\n"); - return false; - } + (u32) ah->regulatory.power_limit)); synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; if (IS_CHAN_B(chan)) @@ -2199,14 +2200,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ah->txchainmask = sc->tx_chainmask; ah->rxchainmask = sc->rx_chainmask; - if (AR_SREV_9285(ah)) { - ah->txchainmask &= 0x1; - ah->rxchainmask &= 0x1; - } else if (AR_SREV_9280(ah)) { - ah->txchainmask &= 0x3; - ah->rxchainmask &= 0x3; - } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; @@ -2242,7 +2235,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_mark_phy_inactive(ah); if (!ath9k_hw_chip_reset(ah, chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); return -EINVAL; } @@ -2304,13 +2297,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) - return -EIO; - } else { + if (AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_ar9280_set_channel(ah, chan); + else if (!(ath9k_hw_set_channel(ah, chan))) return -EIO; - } for (i = 0; i < AR_NUM_DCU; i++) REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); @@ -2335,8 +2326,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_OBS, 8); - if (ah->intr_mitigation) { - + if (ah->config.intr_mitigation) { REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); } @@ -2385,8 +2375,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) u32 keyType; if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, - "entry %u out of range\n", entry); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); return false; } @@ -2422,8 +2412,8 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) u32 macHi, macLo; if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, - "entry %u out of range\n", entry); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); return false; } @@ -2454,8 +2444,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, u32 keyType; if (entry >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, - "entry %u out of range\n", entry); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keycache entry %u out of range\n", entry); return false; } @@ -2465,7 +2455,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, break; case ATH9K_CIPHER_AES_CCM: if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "AES-CCM not supported by mac rev 0x%x\n", ah->hw_version.macRev); return false; @@ -2476,20 +2466,20 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, keyType = AR_KEYTABLE_TYPE_TKIP; if (ATH9K_IS_MIC_ENABLED(ah) && entry + 64 >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "entry %u inappropriate for TKIP\n", entry); return false; } break; case ATH9K_CIPHER_WEP: - if (k->kv_len < LEN_WEP40) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + if (k->kv_len < WLAN_KEY_LEN_WEP40) { + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "WEP key length %u too small\n", k->kv_len); return false; } - if (k->kv_len <= LEN_WEP40) + if (k->kv_len <= WLAN_KEY_LEN_WEP40) keyType = AR_KEYTABLE_TYPE_40; - else if (k->kv_len <= LEN_WEP104) + else if (k->kv_len <= WLAN_KEY_LEN_WEP104) keyType = AR_KEYTABLE_TYPE_104; else keyType = AR_KEYTABLE_TYPE_128; @@ -2498,7 +2488,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, keyType = AR_KEYTABLE_TYPE_CLR; break; default: - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "cipher %u not supported\n", k->kv_type); return false; } @@ -2508,7 +2498,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, key2 = get_unaligned_le32(k->kv_val + 6); key3 = get_unaligned_le16(k->kv_val + 10); key4 = get_unaligned_le32(k->kv_val + 12); - if (k->kv_len <= LEN_WEP104) + if (k->kv_len <= WLAN_KEY_LEN_WEP104) key4 &= 0xff; /* @@ -2716,7 +2706,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) AR_RTC_FORCE_WAKE_EN); } if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); return false; } @@ -2737,9 +2727,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) "UNDEFINED" }; - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n", - modes[ah->power_mode], modes[mode], - setChip ? "set chip " : ""); + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", + modes[ah->power_mode], modes[mode]); switch (mode) { case ATH9K_PM_AWAKE: @@ -2753,7 +2742,7 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) ath9k_set_power_network_sleep(ah, setChip); break; default: - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Unknown power mode %u\n", mode); return false; } @@ -2943,7 +2932,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) *masked = isr & ATH9K_INT_COMMON; - if (ah->intr_mitigation) { + if (ah->config.intr_mitigation) { if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) *masked |= ATH9K_INT_RX; } @@ -3000,6 +2989,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) DPRINTF(ah->ah_sc, ATH_DBG_ANY, "received PCI PERR interrupt\n"); } + *masked |= ATH9K_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, @@ -3061,7 +3051,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) } if (ints & ATH9K_INT_RX) { mask |= AR_IMR_RXERR; - if (ah->intr_mitigation) + if (ah->config.intr_mitigation) mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; else mask |= AR_IMR_RXOK | AR_IMR_RXDESC; @@ -3259,7 +3249,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, /* HW Capabilities */ /*******************/ -bool ath9k_hw_fill_cap_info(struct ath_hw *ah) +void ath9k_hw_fill_cap_info(struct ath_hw *ah) { struct ath9k_hw_capabilities *pCap = &ah->caps; u16 capField = 0, eeval; @@ -3343,8 +3333,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; - pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD; - if (ah->config.ht_enable) pCap->hw_caps |= ATH9K_HW_CAP_HT; else @@ -3368,7 +3356,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->keycache_size = AR_KEYTABLE_SIZE; pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; - pCap->num_mr_retries = 4; pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; if (AR_SREV_9285_10_OR_LATER(ah)) @@ -3378,14 +3365,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->num_gpio_pins = AR_NUM_GPIO; - if (AR_SREV_9280_10_OR_LATER(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_WOW; - pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT; - } else { - pCap->hw_caps &= ~ATH9K_HW_CAP_WOW; - pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT; - } - if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { pCap->hw_caps |= ATH9K_HW_CAP_CST; pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; @@ -3411,7 +3390,8 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || (ah->hw_version.macVersion == AR_SREV_VERSION_9160) || (ah->hw_version.macVersion == AR_SREV_VERSION_9100) || - (ah->hw_version.macVersion == AR_SREV_VERSION_9280)) + (ah->hw_version.macVersion == AR_SREV_VERSION_9280) || + (ah->hw_version.macVersion == AR_SREV_VERSION_9285)) pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; else pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; @@ -3445,8 +3425,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ah->btactive_gpio = 6; ah->wlanactive_gpio = 5; } - - return true; } bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, @@ -3754,22 +3732,19 @@ bool ath9k_hw_disable(struct ath_hw *ah) return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); } -bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) { struct ath9k_channel *chan = ah->curchan; struct ieee80211_channel *channel = chan->chan; ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); - if (ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(ah, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)) != 0) - return false; - - return true; + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(&ah->regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) ah->regulatory.power_limit)); } void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h similarity index 87% rename from drivers/net/wireless/ath9k/hw.h rename to drivers/net/wireless/ath/ath9k/hw.h index 0b594e0ee260..dd8508ef6e05 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -25,10 +25,11 @@ #include "ani.h" #include "eeprom.h" #include "calib.h" -#include "regd.h" #include "reg.h" #include "phy.h" +#include "../regd.h" + #define ATHEROS_VENDOR_ID 0x168c #define AR5416_DEVID_PCI 0x0023 #define AR5416_DEVID_PCIE 0x0024 @@ -124,29 +125,24 @@ enum wireless_mode { }; enum ath9k_hw_caps { - ATH9K_HW_CAP_CHAN_SPREAD = BIT(0), - ATH9K_HW_CAP_MIC_AESCCM = BIT(1), - ATH9K_HW_CAP_MIC_CKIP = BIT(2), - ATH9K_HW_CAP_MIC_TKIP = BIT(3), - ATH9K_HW_CAP_CIPHER_AESCCM = BIT(4), - ATH9K_HW_CAP_CIPHER_CKIP = BIT(5), - ATH9K_HW_CAP_CIPHER_TKIP = BIT(6), - ATH9K_HW_CAP_VEOL = BIT(7), - ATH9K_HW_CAP_BSSIDMASK = BIT(8), - ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(9), - ATH9K_HW_CAP_CHAN_HALFRATE = BIT(10), - ATH9K_HW_CAP_CHAN_QUARTERRATE = BIT(11), - ATH9K_HW_CAP_HT = BIT(12), - ATH9K_HW_CAP_GTT = BIT(13), - ATH9K_HW_CAP_FASTCC = BIT(14), - ATH9K_HW_CAP_RFSILENT = BIT(15), - ATH9K_HW_CAP_WOW = BIT(16), - ATH9K_HW_CAP_CST = BIT(17), - ATH9K_HW_CAP_ENHANCEDPM = BIT(18), - ATH9K_HW_CAP_AUTOSLEEP = BIT(19), - ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20), - ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21), - ATH9K_HW_CAP_BT_COEX = BIT(22) + ATH9K_HW_CAP_MIC_AESCCM = BIT(0), + ATH9K_HW_CAP_MIC_CKIP = BIT(1), + ATH9K_HW_CAP_MIC_TKIP = BIT(2), + ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), + ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), + ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), + ATH9K_HW_CAP_VEOL = BIT(6), + ATH9K_HW_CAP_BSSIDMASK = BIT(7), + ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), + ATH9K_HW_CAP_HT = BIT(9), + ATH9K_HW_CAP_GTT = BIT(10), + ATH9K_HW_CAP_FASTCC = BIT(11), + ATH9K_HW_CAP_RFSILENT = BIT(12), + ATH9K_HW_CAP_CST = BIT(13), + ATH9K_HW_CAP_ENHANCEDPM = BIT(14), + ATH9K_HW_CAP_AUTOSLEEP = BIT(15), + ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), + ATH9K_HW_CAP_BT_COEX = BIT(17) }; enum ath9k_capability_type { @@ -166,7 +162,6 @@ struct ath9k_hw_capabilities { u16 keycache_size; u16 low_5ghz_chan, high_5ghz_chan; u16 low_2ghz_chan, high_2ghz_chan; - u16 num_mr_retries; u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; @@ -184,11 +179,8 @@ struct ath9k_ops_config { int ack_6mb; int cwm_ignore_extcca; u8 pcie_powersave_enable; - u8 pcie_l1skp_enable; u8 pcie_clock_req; u32 pcie_waen; - int pcie_power_reset; - u8 pcie_restore; u8 analog_shiftreg; u8 ht_enable; u32 ofdm_trig_low; @@ -196,17 +188,10 @@ struct ath9k_ops_config { u32 cck_trig_high; u32 cck_trig_low; u32 enable_ani; - u8 noise_immunity_level; - u32 ofdm_weaksignal_det; - u32 cck_weaksignal_thr; - u8 spur_immunity_level; - u8 firstep_level; - int8_t rssi_thr_high; - int8_t rssi_thr_low; u16 diversity_control; u16 antenna_switch_swap; int serialize_regmode; - int intr_mitigation; + bool intr_mitigation; #define SPUR_DISABLE 0 #define SPUR_ENABLE_IOCTL 1 #define SPUR_ENABLE_EEPROM 2 @@ -281,13 +266,6 @@ enum ath9k_int { #define CHANNEL_HT40PLUS 0x20000 #define CHANNEL_HT40MINUS 0x40000 -#define CHANNEL_INTERFERENCE 0x01 -#define CHANNEL_DFS 0x02 -#define CHANNEL_4MS_LIMIT 0x04 -#define CHANNEL_DFS_CLEAR 0x08 -#define CHANNEL_DISALLOW_ADHOC 0x10 -#define CHANNEL_PER_11D_ADHOC 0x20 - #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) @@ -318,10 +296,6 @@ struct ath9k_channel { int16_t rawNoiseFloor; }; -#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ - (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ - (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ - (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ @@ -329,7 +303,6 @@ struct ath9k_channel { #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) -#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) #define IS_CHAN_A_5MHZ_SPACED(_c) \ @@ -420,7 +393,7 @@ struct ath_hw { struct ath9k_hw_version hw_version; struct ath9k_ops_config config; struct ath9k_hw_capabilities caps; - struct ath9k_regulatory regulatory; + struct ath_regulatory regulatory; struct ath9k_channel channels[38]; struct ath9k_channel *curchan; @@ -463,14 +436,14 @@ struct ath_hw { enum ath9k_ant_setting diversity_control; /* Calibration */ - enum hal_cal_types supp_cals; - struct hal_cal_list iq_caldata; - struct hal_cal_list adcgain_caldata; - struct hal_cal_list adcdc_calinitdata; - struct hal_cal_list adcdc_caldata; - struct hal_cal_list *cal_list; - struct hal_cal_list *cal_list_last; - struct hal_cal_list *cal_list_curr; + enum ath9k_cal_types supp_cals; + struct ath9k_cal_list iq_caldata; + struct ath9k_cal_list adcgain_caldata; + struct ath9k_cal_list adcdc_calinitdata; + struct ath9k_cal_list adcdc_caldata; + struct ath9k_cal_list *cal_list; + struct ath9k_cal_list *cal_list_last; + struct ath9k_cal_list *cal_list_curr; #define totalPowerMeasI meas0.unsign #define totalPowerMeasQ meas1.unsign #define totalIqCorrMeas meas2.sign @@ -540,7 +513,6 @@ struct ath_hw { enum ath9k_ani_cmd ani_function; u32 intr_txqs; - bool intr_mitigation; enum ath9k_ht_extprotspacing extprotspacing; u8 txchainmask; u8 rxchainmask; @@ -573,7 +545,7 @@ 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_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange); -bool ath9k_hw_fill_cap_info(struct ath_hw *ah); +void ath9k_hw_fill_cap_info(struct ath_hw *ah); bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 *result); bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, @@ -608,7 +580,8 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah, bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); u32 ath9k_hw_reverse_bits(u32 val, u32 n); bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); -u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, +u16 ath9k_hw_computetxtime(struct ath_hw *ah, + const struct ath_rate_table *rates, u32 frameLen, u16 rateix, bool shortPreamble); void ath9k_hw_get_channel_centers(struct ath_hw *ah, struct ath9k_channel *chan, @@ -617,7 +590,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah); void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); bool ath9k_hw_phy_disable(struct ath_hw *ah); bool ath9k_hw_disable(struct ath_hw *ah); -bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h similarity index 100% rename from drivers/net/wireless/ath9k/initvals.h rename to drivers/net/wireless/ath/ath9k/initvals.h diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c similarity index 93% rename from drivers/net/wireless/ath9k/mac.c rename to drivers/net/wireless/ath/ath9k/mac.c index e0a6dee45839..8ae4ec21667b 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -49,7 +49,7 @@ bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); REG_WRITE(ah, AR_Q_TXE, 1 << q); @@ -110,13 +110,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " + "inactive queue: %u\n", q); return false; } @@ -146,7 +148,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) break; DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "TSF have moved while trying to set " + "TSF has moved while trying to set " "quiet time TSF: 0x%08x\n", tsfLow); } @@ -158,8 +160,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_XMIT, - "Failed to stop Tx DMA in 100 " + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + "Failed to stop TX DMA in 100 " "msec after killing last frame\n"); break; } @@ -454,17 +456,19 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " + "inactive queue: %u\n", q); return false; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); qi->tqi_ver = qinfo->tqi_ver; qi->tqi_subtype = qinfo->tqi_subtype; @@ -521,13 +525,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " + "inactive queue: %u\n", q); return false; } @@ -575,22 +581,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, ATH9K_TX_QUEUE_INACTIVE) break; if (q == pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "no available tx queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "No available TX queue\n"); return -1; } break; default: - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", + type); return -1; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); qi = &ah->txq[q]; if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "tx queue %u already active\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "TX queue: %u already active\n", q); return -1; } memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); @@ -620,16 +627,18 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " + "inactive queue: %u\n", q); return false; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; ah->txok_interrupt_mask &= ~(1 << q); @@ -650,17 +659,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) u32 cwMin, chanCwMin, value; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " + "inactive queue: %u\n", q); return true; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { if (chan && IS_CHAN_B(chan)) @@ -894,7 +905,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) reg = REG_READ(ah, AR_OBS_BUS_1); DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "rx failed to go idle in 10 ms RXSM=0x%x\n", reg); + "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); return false; } @@ -949,8 +960,8 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) } if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "dma failed to stop in %d ms " + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "DMA failed to stop in %d ms " "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", AH_RX_STOP_DMA_TIMEOUT / 1000, REG_READ(ah, AR_CR), diff --git a/drivers/net/wireless/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h similarity index 100% rename from drivers/net/wireless/ath9k/mac.h rename to drivers/net/wireless/ath/ath9k/mac.h diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c similarity index 87% rename from drivers/net/wireless/ath9k/main.c rename to drivers/net/wireless/ath/ath9k/main.c index 13d4e6756c99..f7baa406918b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -35,14 +35,14 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); #define CHAN2G(_freq, _idx) { \ .center_freq = (_freq), \ .hw_value = (_idx), \ - .max_power = 30, \ + .max_power = 20, \ } #define CHAN5G(_freq, _idx) { \ .band = IEEE80211_BAND_5GHZ, \ .center_freq = (_freq), \ .hw_value = (_idx), \ - .max_power = 30, \ + .max_power = 20, \ } /* Some 2 GHz radios are actually tunable on 2312-2732 @@ -189,7 +189,7 @@ static u8 parse_mpdudensity(u8 mpdudensity) static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) { - struct ath_rate_table *rate_table = NULL; + const struct ath_rate_table *rate_table = NULL; struct ieee80211_supported_band *sband; struct ieee80211_rate *rate; int i, maxrates; @@ -280,14 +280,13 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, if (r) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset channel (%u Mhz) " - "reset status %u\n", + "reset status %d\n", channel->center_freq, r); spin_unlock_bh(&sc->sc_resetlock); return r; } spin_unlock_bh(&sc->sc_resetlock); - sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; sc->sc_flags &= ~SC_OP_FULL_RESET; if (ath_startrecv(sc) != 0) { @@ -330,6 +329,12 @@ static void ath_ani_calibrate(unsigned long data) if (sc->sc_flags & SC_OP_SCANNING) goto set_timer; + /* Only calibrate if awake */ + if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) + goto set_timer; + + ath9k_ps_wakeup(sc); + /* Long calibration runs independently of short calibration. */ if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { longcal = true; @@ -368,31 +373,21 @@ static void ath_ani_calibrate(unsigned long data) /* Perform calibration if necessary */ if (longcal || shortcal) { - bool iscaldone = false; + sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, + sc->rx_chainmask, longcal); - if (ath9k_hw_calibrate(ah, ah->curchan, - sc->rx_chainmask, longcal, - &iscaldone)) { - if (longcal) - sc->ani.noise_floor = - ath9k_hw_getchan_noise(ah, - ah->curchan); + if (longcal) + sc->ani.noise_floor = ath9k_hw_getchan_noise(ah, + ah->curchan); - DPRINTF(sc, ATH_DBG_ANI, - "calibrate chan %u/%x nf: %d\n", - ah->curchan->channel, - ah->curchan->channelFlags, - sc->ani.noise_floor); - } else { - DPRINTF(sc, ATH_DBG_ANY, - "calibrate chan %u/%x failed\n", - ah->curchan->channel, - ah->curchan->channelFlags); - } - sc->ani.caldone = iscaldone; + DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n", + ah->curchan->channel, ah->curchan->channelFlags, + sc->ani.noise_floor); } } + ath9k_ps_restore(sc); + set_timer: /* * Set timer interval based on previous results. @@ -408,6 +403,18 @@ static void ath_ani_calibrate(unsigned long data) mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); } +static void ath_start_ani(struct ath_softc *sc) +{ + unsigned long timestamp = jiffies_to_msecs(jiffies); + + sc->ani.longcal_timer = timestamp; + sc->ani.shortcal_timer = timestamp; + sc->ani.checkani_timer = timestamp; + + mod_timer(&sc->ani.timer, + jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); +} + /* * Update tx/rx chainmask. For legacy association, * hard code chainmask to 1x1, for 11n association, use @@ -416,7 +423,6 @@ static void ath_ani_calibrate(unsigned long data) */ void ath_update_chainmask(struct ath_softc *sc, int is_ht) { - sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; if (is_ht || (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; @@ -436,12 +442,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) an = (struct ath_node *)sta->drv_priv; - if (sc->sc_flags & SC_OP_TXAGGR) + if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); - - an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + - sta->ht_cap.ampdu_factor); - an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); + an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + + sta->ht_cap.ampdu_factor); + an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); + } } static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) @@ -457,133 +463,130 @@ static void ath9k_tasklet(unsigned long data) struct ath_softc *sc = (struct ath_softc *)data; u32 status = sc->intrstatus; - if (status & ATH9K_INT_FATAL) { - /* need a chip reset */ - ath_reset(sc, false); - return; - } else { + ath9k_ps_wakeup(sc); - if (status & - (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { - spin_lock_bh(&sc->rx.rxflushlock); - ath_rx_tasklet(sc, 0); - spin_unlock_bh(&sc->rx.rxflushlock); - } - /* XXX: optimize this */ - if (status & ATH9K_INT_TX) - ath_tx_tasklet(sc); + if (status & ATH9K_INT_FATAL) { + ath_reset(sc, false); + ath9k_ps_restore(sc); + return; + } + + if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { + spin_lock_bh(&sc->rx.rxflushlock); + ath_rx_tasklet(sc, 0); + spin_unlock_bh(&sc->rx.rxflushlock); + } + + if (status & ATH9K_INT_TX) + ath_tx_tasklet(sc); + + if ((status & ATH9K_INT_TSFOOR) && + (sc->hw->conf.flags & IEEE80211_CONF_PS)) { + /* + * TSF sync does not look correct; remain awake to sync with + * the next Beacon. + */ + DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); + sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; } /* re-enable hardware interrupt */ ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + ath9k_ps_restore(sc); } irqreturn_t ath_isr(int irq, void *dev) { +#define SCHED_INTR ( \ + ATH9K_INT_FATAL | \ + ATH9K_INT_RXORN | \ + ATH9K_INT_RXEOL | \ + ATH9K_INT_RX | \ + ATH9K_INT_TX | \ + ATH9K_INT_BMISS | \ + ATH9K_INT_CST | \ + ATH9K_INT_TSFOOR) + struct ath_softc *sc = dev; struct ath_hw *ah = sc->sc_ah; enum ath9k_int status; bool sched = false; - do { - if (sc->sc_flags & SC_OP_INVALID) { - /* - * The hardware is not ready/present, don't - * touch anything. Note this can happen early - * on if the IRQ is shared. - */ - return IRQ_NONE; - } - if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ - return IRQ_NONE; - } + /* + * The hardware is not ready/present, don't + * touch anything. Note this can happen early + * on if the IRQ is shared. + */ + if (sc->sc_flags & SC_OP_INVALID) + return IRQ_NONE; + + /* shared irq, not for us */ + + if (!ath9k_hw_intrpend(ah)) + return IRQ_NONE; + + /* + * Figure out the reason(s) for the interrupt. Note + * that the hal returns a pseudo-ISR that may include + * bits we haven't explicitly enabled so we mask the + * value to insure we only process bits we requested. + */ + ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ + status &= sc->imask; /* discard unasked-for bits */ + + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). + */ + if (!status) + return IRQ_NONE; + + /* Cache the status */ + sc->intrstatus = status; + + if (status & SCHED_INTR) + sched = true; + + /* + * If a FATAL or RXORN interrupt is received, we have to reset the + * chip immediately. + */ + if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) + goto chip_reset; + + if (status & ATH9K_INT_SWBA) + tasklet_schedule(&sc->bcon_tasklet); + + if (status & ATH9K_INT_TXURN) + ath9k_hw_updatetxtriglevel(ah, true); + + if (status & ATH9K_INT_MIB) { /* - * Figure out the reason(s) for the interrupt. Note - * that the hal returns a pseudo-ISR that may include - * bits we haven't explicitly enabled so we mask the - * value to insure we only process bits we requested. + * Disable interrupts until we service the MIB + * interrupt; otherwise it will continue to + * fire. */ - ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ - - status &= sc->imask; /* discard unasked-for bits */ - + ath9k_hw_set_interrupts(ah, 0); /* - * If there are no status bits set, then this interrupt was not - * for me (should have been caught above). + * Let the hal handle the event. We assume + * it will clear whatever condition caused + * the interrupt. */ - if (!status) - return IRQ_NONE; + ath9k_hw_procmibevent(ah, &sc->nodestats); + ath9k_hw_set_interrupts(ah, sc->imask); + } - sc->intrstatus = status; - ath9k_ps_wakeup(sc); - - if (status & ATH9K_INT_FATAL) { - /* need a chip reset */ - sched = true; - } else if (status & ATH9K_INT_RXORN) { - /* need a chip reset */ - sched = true; - } else { - if (status & ATH9K_INT_SWBA) { - /* schedule a tasklet for beacon handling */ - tasklet_schedule(&sc->bcon_tasklet); - } - if (status & ATH9K_INT_RXEOL) { - /* - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work - * at least on older hardware revs. - */ - sched = true; - } - - if (status & ATH9K_INT_TXURN) - /* bump tx trigger level */ - ath9k_hw_updatetxtriglevel(ah, true); - /* XXX: optimize this */ - if (status & ATH9K_INT_RX) - sched = true; - if (status & ATH9K_INT_TX) - sched = true; - if (status & ATH9K_INT_BMISS) - sched = true; - /* carrier sense timeout */ - if (status & ATH9K_INT_CST) - sched = true; - if (status & ATH9K_INT_MIB) { - /* - * Disable interrupts until we service the MIB - * interrupt; otherwise it will continue to - * fire. - */ - ath9k_hw_set_interrupts(ah, 0); - /* - * Let the hal handle the event. We assume - * it will clear whatever condition caused - * the interrupt. - */ - ath9k_hw_procmibevent(ah, &sc->nodestats); - ath9k_hw_set_interrupts(ah, sc->imask); - } - if (status & ATH9K_INT_TIM_TIMER) { - if (!(ah->caps.hw_caps & - ATH9K_HW_CAP_AUTOSLEEP)) { - /* Clear RxAbort bit so that we can - * receive frames */ - ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); - ath9k_hw_setrxabort(ah, 0); - sched = true; - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; - } - } - if (status & ATH9K_INT_TSFOOR) { - /* FIXME: Handle this interrupt for power save */ - sched = true; - } + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + if (status & ATH9K_INT_TIM_TIMER) { + /* Clear RxAbort bit so that we can + * receive frames */ + ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); + ath9k_hw_setrxabort(sc->sc_ah, 0); + sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; } - ath9k_ps_restore(sc); - } while (0); + +chip_reset: ath_debug_stat_interrupt(sc, status); @@ -594,6 +597,8 @@ irqreturn_t ath_isr(int irq, void *dev) } return IRQ_HANDLED; + +#undef SCHED_INTR } static u32 ath_get_extchanmode(struct ath_softc *sc, @@ -676,7 +681,7 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { /* TX MIC entry failed. No need to proceed further */ - DPRINTF(sc, ATH_DBG_KEYCACHE, + DPRINTF(sc, ATH_DBG_FATAL, "Setting TX MIC Key Failed\n"); return 0; } @@ -909,6 +914,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, if (avp->av_opmode == NL80211_IFTYPE_STATION) { 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; } /* Configure the beacon */ @@ -920,11 +932,9 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; - /* Start ANI */ - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + ath_start_ani(sc); } else { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n"); + DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); sc->curaid = 0; } } @@ -1098,14 +1108,14 @@ void ath_radio_enable(struct ath_softc *sc) int r; ath9k_ps_wakeup(sc); + ath9k_hw_configpcipowersave(ah, 0); + spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, ah->curchan, false); - if (r) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset channel %u (%uMhz) ", - "reset status %u\n", + "reset status %d\n", channel->center_freq, r); } spin_unlock_bh(&sc->sc_resetlock); @@ -1157,12 +1167,13 @@ void ath_radio_disable(struct ath_softc *sc) if (r) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset channel %u (%uMhz) " - "reset status %u\n", + "reset status %d\n", channel->center_freq, r); } spin_unlock_bh(&sc->sc_resetlock); ath9k_hw_phy_disable(ah); + ath9k_hw_configpcipowersave(ah, 1); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); ath9k_ps_restore(sc); } @@ -1181,121 +1192,69 @@ static bool ath_is_rfkill_set(struct ath_softc *sc) ah->rfkill_polarity; } -/* h/w rfkill poll function */ -static void ath_rfkill_poll(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - rf_kill.rfkill_poll.work); - bool radio_on; - - if (sc->sc_flags & SC_OP_INVALID) - return; - - radio_on = !ath_is_rfkill_set(sc); - - /* - * enable/disable radio only when there is a - * state change in RF switch - */ - if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) { - enum rfkill_state state; - - if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) { - state = radio_on ? RFKILL_STATE_SOFT_BLOCKED - : RFKILL_STATE_HARD_BLOCKED; - } else if (radio_on) { - ath_radio_enable(sc); - state = RFKILL_STATE_UNBLOCKED; - } else { - ath_radio_disable(sc); - state = RFKILL_STATE_HARD_BLOCKED; - } - - if (state == RFKILL_STATE_HARD_BLOCKED) - sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED; - else - sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED; - - rfkill_force_state(sc->rf_kill.rfkill, state); - } - - queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, - msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL)); -} - -/* s/w rfkill handler */ -static int ath_sw_toggle_radio(void *data, enum rfkill_state state) +/* s/w rfkill handlers */ +static int ath_rfkill_set_block(void *data, bool blocked) { struct ath_softc *sc = data; - switch (state) { - case RFKILL_STATE_SOFT_BLOCKED: - if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED | - SC_OP_RFKILL_SW_BLOCKED))) - ath_radio_disable(sc); - sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED; - return 0; - case RFKILL_STATE_UNBLOCKED: - if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) { - sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED; - if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) { - DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the" - "radio as it is disabled by h/w\n"); - return -EPERM; - } - ath_radio_enable(sc); - } - return 0; - default: - return -EINVAL; - } + if (blocked) + ath_radio_disable(sc); + else + ath_radio_enable(sc); + + return 0; +} + +static void ath_rfkill_poll_state(struct rfkill *rfkill, void *data) +{ + struct ath_softc *sc = data; + bool blocked = !!ath_is_rfkill_set(sc); + + if (rfkill_set_hw_state(rfkill, blocked)) + ath_radio_disable(sc); + else + ath_radio_enable(sc); } /* Init s/w rfkill */ static int ath_init_sw_rfkill(struct ath_softc *sc) { - sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy), - RFKILL_TYPE_WLAN); + sc->rf_kill.ops.set_block = ath_rfkill_set_block; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + sc->rf_kill.ops.poll = ath_rfkill_poll_state; + + snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), + "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy)); + + sc->rf_kill.rfkill = rfkill_alloc(sc->rf_kill.rfkill_name, + wiphy_dev(sc->hw->wiphy), + RFKILL_TYPE_WLAN, + &sc->rf_kill.ops, sc); if (!sc->rf_kill.rfkill) { DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n"); return -ENOMEM; } - snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), - "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy)); - sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name; - sc->rf_kill.rfkill->data = sc; - sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; - sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED; - sc->rf_kill.rfkill->user_claim_unsupported = 1; - return 0; } /* Deinitialize rfkill */ static void ath_deinit_rfkill(struct ath_softc *sc) { - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); - if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) { rfkill_unregister(sc->rf_kill.rfkill); + rfkill_destroy(sc->rf_kill.rfkill); sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED; - sc->rf_kill.rfkill = NULL; } } static int ath_start_rfkill_poll(struct ath_softc *sc) { - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - queue_delayed_work(sc->hw->workqueue, - &sc->rf_kill.rfkill_poll, 0); - if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { if (rfkill_register(sc->rf_kill.rfkill)) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to register rfkill\n"); - rfkill_free(sc->rf_kill.rfkill); + rfkill_destroy(sc->rf_kill.rfkill); /* Deinitialize the device */ ath_cleanup(sc); @@ -1362,6 +1321,17 @@ void ath_detach(struct ath_softc *sc) ath9k_ps_restore(sc); } +static int ath9k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_regulatory *reg = &sc->sc_ah->regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + static int ath_init(u16 devid, struct ath_softc *sc) { struct ath_hw *ah = NULL; @@ -1403,7 +1373,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) /* Get the hardware key cache size. */ sc->keymax = ah->caps.keycache_size; if (sc->keymax > ATH_KEYMAX) { - DPRINTF(sc, ATH_DBG_KEYCACHE, + DPRINTF(sc, ATH_DBG_ANY, "Warning, using only %u entries in %u key cache\n", ATH_KEYMAX, sc->keymax); sc->keymax = ATH_KEYMAX; @@ -1416,7 +1386,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) for (i = 0; i < sc->keymax; i++) ath9k_hw_keyreset(ah, (u16) i); - if (ath9k_regd_init(sc->sc_ah)) + if (error) goto bad; /* default to MONITOR mode */ @@ -1545,9 +1515,6 @@ static int ath_init(u16 devid, struct ath_softc *sc) sc->beacon.bslot_aphy[i] = NULL; } - /* save MISC configurations */ - sc->config.swBeaconProcess = 1; - /* setup channels and rates */ sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; @@ -1602,9 +1569,6 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - hw->wiphy->reg_notifier = ath9k_reg_notifier; - hw->wiphy->strict_regulatory = true; - hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; @@ -1625,8 +1589,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; - const struct ieee80211_regdomain *regd; int error = 0, i; + struct ath_regulatory *reg; DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); @@ -1640,6 +1604,13 @@ int ath_attach(u16 devid, struct ath_softc *sc) ath_set_hw_capab(sc, hw); + error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, + ath9k_reg_notifier); + if (error) + return error; + + reg = &sc->sc_ah->regulatory; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) @@ -1656,41 +1627,20 @@ int ath_attach(u16 devid, struct ath_softc *sc) goto error_attach; #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - /* Initialze h/w Rfkill */ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); - /* Initialize s/w rfkill */ error = ath_init_sw_rfkill(sc); if (error) goto error_attach; #endif - if (ath9k_is_world_regd(sc->sc_ah)) { - /* Anything applied here (prior to wiphy registration) gets - * saved on the wiphy orig_* parameters */ - regd = ath9k_world_regdomain(sc->sc_ah); - hw->wiphy->custom_regulatory = true; - hw->wiphy->strict_regulatory = false; - } else { - /* This gets applied in the case of the absense of CRDA, - * it's our own custom world regulatory domain, similar to - * cfg80211's but we enable passive scanning */ - regd = ath9k_default_world_regdomain(); - } - wiphy_apply_custom_regulatory(hw->wiphy, regd); - ath9k_reg_apply_radar_flags(hw->wiphy); - ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER); - INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); sc->wiphy_scheduler_int = msecs_to_jiffies(500); error = ieee80211_register_hw(hw); - if (!ath9k_is_world_regd(sc->sc_ah)) { - error = regulatory_hint(hw->wiphy, - sc->sc_ah->regulatory.alpha2); + if (!ath_is_world_regd(reg)) { + error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) goto error_attach; } @@ -1728,7 +1678,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); if (r) DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u\n", r); + "Unable to reset hardware; reset status %d\n", r); spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) @@ -1792,7 +1742,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, goto fail; } - dd->dd_name = name; dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; /* @@ -1822,7 +1771,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } ds = dd->dd_desc; DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - dd->dd_name, ds, (u32) dd->dd_desc_len, + name, ds, (u32) dd->dd_desc_len, ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); /* allocate buffers */ @@ -2021,7 +1970,7 @@ static int ath9k_start(struct ieee80211_hw *hw) r = ath9k_hw_reset(sc->sc_ah, init_channel, false); if (r) { DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u " + "Unable to reset hardware; reset status %d " "(freq %u MHz)\n", r, curchan->center_freq); spin_unlock_bh(&sc->sc_resetlock); @@ -2043,8 +1992,7 @@ static int ath9k_start(struct ieee80211_hw *hw) * here except setup the interrupt mask. */ if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to start recv logic\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); r = -EIO; goto mutex_unlock; } @@ -2095,6 +2043,46 @@ static int ath9k_tx(struct ieee80211_hw *hw, goto exit; } + if (sc->hw->conf.flags & IEEE80211_CONF_PS) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + /* + * mac80211 does not set PM field for normal data frames, so we + * need to update that based on the current PS mode. + */ + if (ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_nullfunc(hdr->frame_control) && + !ieee80211_has_pm(hdr->frame_control)) { + DPRINTF(sc, ATH_DBG_PS, "Add PM=1 for a TX frame " + "while in PS mode\n"); + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } + } + + if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { + /* + * We are using PS-Poll and mac80211 can request TX while in + * power save mode. Need to wake up hardware for the TX to be + * completed and if needed, also for RX of buffered frames. + */ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + ath9k_ps_wakeup(sc); + ath9k_hw_setrxabort(sc->sc_ah, 0); + if (ieee80211_is_pspoll(hdr->frame_control)) { + DPRINTF(sc, ATH_DBG_PS, "Sending PS-Poll to pick a " + "buffered frame\n"); + sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; + } else { + DPRINTF(sc, ATH_DBG_PS, "Wake up to complete TX\n"); + sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; + } + /* + * The actual restore operation will happen only after + * the sc_flags bit is cleared. We are just dropping + * the ps_usecount here. + */ + ath9k_ps_restore(sc); + } + memset(&txctl, 0, sizeof(struct ath_tx_control)); /* @@ -2171,10 +2159,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) } else sc->rx.rxlink = NULL; -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); -#endif + rfkill_pause_polling(sc->rf_kill.rfkill); + /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1); @@ -2257,25 +2243,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, sc->imask |= ATH9K_INT_TSFOOR; } - /* - * Some hardware processes the TIM IE and fires an - * interrupt when the TIM bit is set. For hardware - * that does, if not overridden by configuration, - * enable the TIM interrupt when operating as station. - */ - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && - (conf->type == NL80211_IFTYPE_STATION) && - !sc->config.swBeaconProcess) - sc->imask |= ATH9K_INT_TIM; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - if (conf->type == NL80211_IFTYPE_AP) { - /* TODO: is this a suitable place to start ANI for AP mode? */ - /* Start ANI */ - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); - } + if (conf->type == NL80211_IFTYPE_AP) + ath_start_ani(sc); out: mutex_unlock(&sc->mutex); @@ -2326,26 +2297,36 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ieee80211_conf *conf = &hw->conf; + struct ath_hw *ah = sc->sc_ah; mutex_lock(&sc->mutex); if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { - if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { - sc->imask |= ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); + if (!(ah->caps.hw_caps & + ATH9K_HW_CAP_AUTOSLEEP)) { + if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { + sc->imask |= ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } + ath9k_hw_setrxabort(sc->sc_ah, 1); } - ath9k_hw_setrxabort(sc->sc_ah, 1); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); } else { ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; - if (sc->imask & ATH9K_INT_TIM_TIMER) { - sc->imask &= ~ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); + if (!(ah->caps.hw_caps & + ATH9K_HW_CAP_AUTOSLEEP)) { + ath9k_hw_setrxabort(sc->sc_ah, 0); + 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); + if (sc->imask & ATH9K_INT_TIM_TIMER) { + sc->imask &= ~ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } } } } @@ -2387,114 +2368,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) sc->config.txpowlimit = 2 * conf->power_level; - /* - * The HW TSF has to be reset when the beacon interval changes. - * We set the flag here, and ath_beacon_config_ap() would take this - * into account when it gets called through the subsequent - * config_interface() call - with IFCC_BEACON in the changed field. - */ - - if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - sc->sc_flags |= SC_OP_TSF_RESET; - - mutex_unlock(&sc->mutex); - - return 0; -} - -static int ath9k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; - struct ath_vif *avp = (void *)vif->drv_priv; - u32 rfilt = 0; - int error, i; - - mutex_lock(&sc->mutex); - - /* TODO: Need to decide which hw opmode to use for multi-interface - * cases */ - if (vif->type == NL80211_IFTYPE_AP && - ah->opmode != NL80211_IFTYPE_AP) { - ah->opmode = NL80211_IFTYPE_STATION; - ath9k_hw_setopmode(ah); - memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - /* Request full reset to get hw opmode changed properly */ - sc->sc_flags |= SC_OP_FULL_RESET; - } - - if ((conf->changed & IEEE80211_IFCC_BSSID) && - !is_zero_ether_addr(conf->bssid)) { - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - /* Set BSSID */ - memcpy(sc->curbssid, conf->bssid, ETH_ALEN); - memcpy(avp->bssid, conf->bssid, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - - /* Set aggregation protection mode parameters */ - sc->config.ath_aggr_prot = 0; - - DPRINTF(sc, ATH_DBG_CONFIG, - "RX filter 0x%x bssid %pM aid 0x%x\n", - rfilt, sc->curbssid, sc->curaid); - - /* need to reconfigure the beacon */ - sc->sc_flags &= ~SC_OP_BEACONS ; - - break; - default: - break; - } - } - - if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((conf->changed & IEEE80211_IFCC_BEACON) || - (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && - conf->enable_beacon)) { - /* - * Allocate and setup the beacon frame. - * - * Stop any previous beacon DMA. This may be - * necessary, for example, when an ibss merge - * causes reconfiguration; we may be called - * with beacon transmission active. - */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - error = ath_beacon_alloc(aphy, vif); - if (error != 0) { - mutex_unlock(&sc->mutex); - return error; - } - - ath_beacon_config(sc, vif); - } - } - - /* Check for WLAN_CAPABILITY_PRIVACY ? */ - if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { - for (i = 0; i < IEEE80211_WEP_NKID; i++) - if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) - ath9k_hw_keysetmac(sc->sc_ah, - (u16)i, - sc->curbssid); - } - - /* Only legacy IBSS for now */ - if (vif->type == NL80211_IFTYPE_ADHOC) - ath_update_chainmask(sc, 0); - mutex_unlock(&sc->mutex); return 0; @@ -2523,8 +2396,10 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, *total_flags &= SUPPORTED_FILTERS; sc->rx.rxfilter = *total_flags; + ath9k_ps_wakeup(sc); rfilt = ath_calcrxfilter(sc); ath9k_hw_setrxfilter(sc->sc_ah, rfilt); + ath9k_ps_restore(sc); DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter); } @@ -2562,6 +2437,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, mutex_lock(&sc->mutex); + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + qi.tqi_aifs = params->aifs; qi.tqi_cwmin = params->cw_min; qi.tqi_cwmax = params->cw_max; @@ -2598,7 +2475,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); - DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n"); + DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); switch (cmd) { case SET_KEY: @@ -2634,9 +2511,92 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + struct ath_vif *avp = (void *)vif->drv_priv; + u32 rfilt = 0; + int error, i; mutex_lock(&sc->mutex); + /* + * TODO: Need to decide which hw opmode to use for + * multi-interface cases + * XXX: This belongs into add_interface! + */ + if (vif->type == NL80211_IFTYPE_AP && + ah->opmode != NL80211_IFTYPE_AP) { + ah->opmode = NL80211_IFTYPE_STATION; + ath9k_hw_setopmode(ah); + memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); + sc->curaid = 0; + ath9k_hw_write_associd(sc); + /* Request full reset to get hw opmode changed properly */ + sc->sc_flags |= SC_OP_FULL_RESET; + } + + if ((changed & BSS_CHANGED_BSSID) && + !is_zero_ether_addr(bss_conf->bssid)) { + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + /* Set BSSID */ + memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN); + memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); + sc->curaid = 0; + ath9k_hw_write_associd(sc); + + /* Set aggregation protection mode parameters */ + sc->config.ath_aggr_prot = 0; + + DPRINTF(sc, ATH_DBG_CONFIG, + "RX filter 0x%x bssid %pM aid 0x%x\n", + rfilt, sc->curbssid, sc->curaid); + + /* need to reconfigure the beacon */ + sc->sc_flags &= ~SC_OP_BEACONS ; + + break; + default: + break; + } + } + + if ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { + if ((changed & BSS_CHANGED_BEACON) || + (changed & BSS_CHANGED_BEACON_ENABLED && + bss_conf->enable_beacon)) { + /* + * Allocate and setup the beacon frame. + * + * Stop any previous beacon DMA. This may be + * necessary, for example, when an ibss merge + * causes reconfiguration; we may be called + * with beacon transmission active. + */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + + error = ath_beacon_alloc(aphy, vif); + if (!error) + ath_beacon_config(sc, vif); + } + } + + /* Check for WLAN_CAPABILITY_PRIVACY ? */ + if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { + for (i = 0; i < IEEE80211_WEP_NKID; i++) + if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) + ath9k_hw_keysetmac(sc->sc_ah, + (u16)i, + sc->curbssid); + } + + /* Only legacy IBSS for now */ + if (vif->type == NL80211_IFTYPE_ADHOC) + ath_update_chainmask(sc, 0); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", bss_conf->use_short_preamble); @@ -2662,6 +2622,18 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath9k_bss_assoc_info(sc, vif, bss_conf); } + /* + * The HW TSF has to be reset when the beacon interval changes. + * We set the flag here, and ath_beacon_config_ap() would take this + * into account when it gets called through the subsequent + * config_interface() call - with IFCC_BEACON in the changed field. + */ + + if (changed & BSS_CHANGED_BEACON_INT) { + sc->sc_flags |= SC_OP_TSF_RESET; + sc->beacon_interval = bss_conf->beacon_int; + } + mutex_unlock(&sc->mutex); } @@ -2771,6 +2743,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) mutex_lock(&sc->mutex); aphy->state = ATH_WIPHY_ACTIVE; sc->sc_flags &= ~SC_OP_SCANNING; + sc->sc_flags |= SC_OP_FULL_RESET; mutex_unlock(&sc->mutex); } @@ -2781,7 +2754,6 @@ struct ieee80211_ops ath9k_ops = { .add_interface = ath9k_add_interface, .remove_interface = ath9k_remove_interface, .config = ath9k_config, - .config_interface = ath9k_config_interface, .configure_filter = ath9k_configure_filter, .sta_notify = ath9k_sta_notify, .conf_tx = ath9k_conf_tx, diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c similarity index 93% rename from drivers/net/wireless/ath9k/pci.c rename to drivers/net/wireless/ath/ath9k/pci.c index 168411d322a2..ccdf20a2e9be 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -227,11 +227,6 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); -#endif - pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); @@ -256,16 +251,6 @@ static int ath_pci_resume(struct pci_dev *pdev) AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - /* - * check the h/w rfkill state on resume - * and start the rfkill poll timer - */ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - queue_delayed_work(sc->hw->workqueue, - &sc->rf_kill.rfkill_poll, 0); -#endif - return 0; } diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c similarity index 98% rename from drivers/net/wireless/ath9k/phy.c rename to drivers/net/wireless/ath/ath9k/phy.c index 8bcba906929a..aaa941561c36 100644 --- a/drivers/net/wireless/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c @@ -46,7 +46,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = ((freq - 704) * 2 - 3040) / 10; bModeSynth = 1; } else { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid channel %u MHz\n", freq); return false; } @@ -79,7 +79,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); aModeRefSel = ath9k_hw_reverse_bits(1, 2); } else { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid channel %u MHz\n", freq); return false; } @@ -96,9 +96,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) return true; } -bool -ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan) +void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, + struct ath9k_channel *chan) { u16 bMode, fracMode, aModeRefSel = 0; u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; @@ -169,8 +168,6 @@ ath9k_hw_ar9280_set_channel(struct ath_hw *ah, ah->curchan = chan; ah->curchan_rad_index = -1; - - return true; } static void diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h similarity index 99% rename from drivers/net/wireless/ath9k/phy.h rename to drivers/net/wireless/ath/ath9k/phy.h index 0f7f8e0c9c95..c70f530642f6 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -17,7 +17,7 @@ #ifndef PHY_H #define PHY_H -bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah, +void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); bool ath9k_hw_set_channel(struct ath_hw *ah, @@ -556,9 +556,6 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int r; \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, \ - "RF 0x%x V 0x%x\n", \ - INI_RA((iniarray), r, 0), (regData)[r]); \ DO_DELAY(regWr); \ } \ } while (0) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c similarity index 95% rename from drivers/net/wireless/ath9k/rc.c rename to drivers/net/wireless/ath/ath9k/rc.c index 824ccbb8b7b8..ba06e78b2f50 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -17,7 +17,7 @@ #include "ath9k.h" -static struct ath_rate_table ar5416_11na_ratetable = { +static const struct ath_rate_table ar5416_11na_ratetable = { 42, { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ @@ -155,7 +155,7 @@ static struct ath_rate_table ar5416_11na_ratetable = { /* 4ms frame limit not used for NG mode. The values filled * for HT are the 64K max aggregate limit */ -static struct ath_rate_table ar5416_11ng_ratetable = { +static const struct ath_rate_table ar5416_11ng_ratetable = { 46, { { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -302,7 +302,7 @@ static struct ath_rate_table ar5416_11ng_ratetable = { WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ }; -static struct ath_rate_table ar5416_11a_ratetable = { +static const struct ath_rate_table ar5416_11a_ratetable = { 8, { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ @@ -335,7 +335,7 @@ static struct ath_rate_table ar5416_11a_ratetable = { 0, /* Phy rates allowed initially */ }; -static struct ath_rate_table ar5416_11g_ratetable = { +static const struct ath_rate_table ar5416_11g_ratetable = { 12, { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -380,7 +380,7 @@ static struct ath_rate_table ar5416_11g_ratetable = { 0, /* Phy rates allowed initially */ }; -static struct ath_rate_table ar5416_11b_ratetable = { +static const struct ath_rate_table ar5416_11b_ratetable = { 4, { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -420,7 +420,7 @@ static inline int8_t median(int8_t a, int8_t b, int8_t c) } } -static void ath_rc_sort_validrates(struct ath_rate_table *rate_table, +static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv) { u8 i, j, idx, idx_next; @@ -461,10 +461,11 @@ static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, return ath_rc_priv->valid_rate_index[index]; } -static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, - u8 *next_idx) +static inline +int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv, + u8 cur_valid_txrate, + u8 *next_idx) { u8 i; @@ -500,7 +501,7 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) } static inline int -ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, +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) { @@ -517,14 +518,14 @@ ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, } static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, u32 capflag) { u8 i, hi = 0; u32 valid; for (i = 0; i < rate_table->rate_cnt; i++) { - valid = (ath_rc_priv->single_stream ? + valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? rate_table->info[i].valid_single_stream : rate_table->info[i].valid); if (valid == 1) { @@ -547,7 +548,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, } static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, struct ath_rateset *rateset, u32 capflag) { @@ -557,9 +558,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; - u32 valid = (ath_rc_priv->single_stream ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); + u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? + rate_table->info[j].valid_single_stream : + rate_table->info[j].valid); u8 rate = rateset->rs_rates[i]; u8 dot11rate = rate_table->info[j].dot11rate; @@ -592,7 +593,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, } static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, u8 *mcs_set, u32 capflag) { struct ath_rateset *rateset = (struct ath_rateset *)mcs_set; @@ -603,7 +604,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; - u32 valid = (ath_rc_priv->single_stream ? + u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? rate_table->info[j].valid_single_stream : rate_table->info[j].valid); u8 rate = rateset->rs_rates[i]; @@ -630,7 +631,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, static u8 ath_rc_ratefind_ht(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, int *is_probing) { u32 dt, best_thruput, this_thruput, now_msec; @@ -740,14 +741,15 @@ 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->single_stream) || + 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->single_stream)); + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))); return rate; } -static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, +static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate, struct ieee80211_tx_rate_control *txrc, u8 tries, u8 rix, int rtsctsenable) @@ -768,7 +770,7 @@ static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, } static void ath_rc_rate_set_rtscts(struct ath_softc *sc, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, struct ieee80211_tx_info *tx_info) { struct ieee80211_tx_rate *rates = tx_info->control.rates; @@ -806,12 +808,12 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, static u8 ath_rc_rate_getidx(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, u8 rix, u16 stepdown, u16 min_rate) { u32 j; - u8 nextindex; + u8 nextindex = 0; if (min_rate) { for (j = RATE_TABLE_SIZE; j > 0; j--) { @@ -837,7 +839,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_rate_control *txrc) { - struct ath_rate_table *rate_table; + 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; @@ -936,7 +938,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, } static bool ath_rc_update_per(struct ath_softc *sc, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, struct ath_tx_info_priv *tx_info_priv, int tx_rate, int xretries, int retries, @@ -1141,7 +1143,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, int rate; u8 last_per; bool state_change = false; - struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = sc->cur_rate_table; int size = ath_rc_priv->rate_table_size; if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) @@ -1275,7 +1277,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, #undef CHK_RSSI } -static int ath_rc_get_rateindex(struct ath_rate_table *rate_table, +static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate) { int rix; @@ -1299,7 +1301,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, int final_ts_idx, int xretries, int long_retry) { struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - struct ath_rate_table *rate_table; + const struct ath_rate_table *rate_table; struct ieee80211_tx_rate *rates = tx_info->status.rates; u8 flags; u32 i = 0, rix; @@ -1320,7 +1322,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, * 40 to 20 => don't update */ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) + !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; rix = ath_rc_get_rateindex(rate_table, &rates[i]); @@ -1345,18 +1347,19 @@ static void ath_rc_tx_status(struct ath_softc *sc, /* If HT40 and we have switched mode from 40 to 20 => don't update */ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) { + !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; - } rix = ath_rc_get_rateindex(rate_table, &rates[i]); ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, xretries, long_retry); } -static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, - enum ieee80211_band band, - bool is_ht, bool is_cw_40) +static const +struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, + enum ieee80211_band band, + bool is_ht, + bool is_cw_40) { int mode = 0; @@ -1390,7 +1393,7 @@ static void ath_rc_init(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, - struct ath_rate_table *rate_table) + const struct ath_rate_table *rate_table) { struct ath_rateset *rateset = &ath_rc_priv->neg_rates; u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; @@ -1420,10 +1423,6 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->valid_phy_rateidx[i][j] = 0; ath_rc_priv->valid_phy_ratecnt[i] = 0; } - ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG; - - /* Set stream capability */ - ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1; if (!rateset->rs_nrates) { /* No working rate, just initialize valid rates */ @@ -1572,12 +1571,13 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ath_rate_priv *ath_rc_priv = priv_sta; __le16 fc = hdr->frame_control; - /* lowest rate for management and multicast/broadcast frames */ - if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta) { + /* 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 = - is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; + (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ? + 1 : ATH_MGT_TXMAXTRY; return; } @@ -1590,7 +1590,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_rate_table *rate_table = NULL; + const struct ath_rate_table *rate_table = NULL; bool is_cw40, is_sgi40; int i, j = 0; @@ -1639,7 +1639,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_rate_table *rate_table = NULL; + const struct ath_rate_table *rate_table = NULL; bool oper_cw40 = false, oper_sgi40; bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? true : false; diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h similarity index 98% rename from drivers/net/wireless/ath9k/rc.h rename to drivers/net/wireless/ath/ath9k/rc.h index 199a3ce57d64..e3abd76103fd 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -24,7 +24,6 @@ struct ath_softc; #define ATH_RATE_MAX 30 #define RATE_TABLE_SIZE 64 #define MAX_TX_RATE_PHY 48 -#define WLAN_CTRL_FRAME_SIZE (2+2+6+4) /* VALID_ALL - valid for 20/40/Legacy, * VALID - Legacy only, @@ -158,7 +157,6 @@ struct ath_rateset { * @probe_interval: interval for ratectrl to probe for other rates * @prev_data_rix: rate idx of last data frame * @ht_cap: HT capabilities - * @single_stream: When TRUE, only single TX stream possible * @neg_rates: Negotatied rates * @neg_ht_rates: Negotiated HT rates */ @@ -176,10 +174,8 @@ struct ath_rate_priv { u8 max_valid_rate; u8 valid_rate_index[RATE_TABLE_SIZE]; u8 ht_cap; - u8 single_stream; u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; - u8 rc_phy_mode; u8 rate_max_phy; u32 rssi_time; u32 rssi_down_time; diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c similarity index 75% rename from drivers/net/wireless/ath9k/recv.c rename to drivers/net/wireless/ath/ath9k/recv.c index dd1f30156740..5014a19b0f75 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -283,54 +283,51 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) struct ath_buf *bf; int error = 0; - do { - spin_lock_init(&sc->rx.rxflushlock); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_lock_init(&sc->rx.rxbuflock); + spin_lock_init(&sc->rx.rxflushlock); + sc->sc_flags &= ~SC_OP_RXFLUSH; + spin_lock_init(&sc->rx.rxbuflock); - sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, - min(sc->cachelsz, - (u16)64)); + sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, + min(sc->cachelsz, (u16)64)); - DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - sc->cachelsz, sc->rx.bufsize); + DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", + sc->cachelsz, sc->rx.bufsize); - /* Initialize rx descriptors */ + /* Initialize rx descriptors */ - error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, - "rx", nbufs, 1); - if (error != 0) { + error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, + "rx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "failed to allocate rx descriptors: %d\n", error); + goto err; + } + + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); + if (skb == NULL) { + error = -ENOMEM; + goto err; + } + + bf->bf_mpdu = skb; + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + sc->rx.bufsize, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, + bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", error); - break; + "dma_mapping_error() on RX init\n"); + error = -ENOMEM; + goto err; } + bf->bf_dmacontext = bf->bf_buf_addr; + } + sc->rx.rxlink = NULL; - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); - if (skb == NULL) { - error = -ENOMEM; - break; - } - - bf->bf_mpdu = skb; - bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, - sc->rx.bufsize, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, - "dma_mapping_error() on RX init\n"); - error = -ENOMEM; - break; - } - bf->bf_dmacontext = bf->bf_buf_addr; - } - sc->rx.rxlink = NULL; - - } while (0); - +err: if (error) ath_rx_cleanup(sc); @@ -345,10 +342,8 @@ void ath_rx_cleanup(struct ath_softc *sc) list_for_each_entry(bf, &sc->rx.rxbuf, list) { skb = bf->bf_mpdu; if (skb) { - dma_unmap_single(sc->dev, - bf->bf_buf_addr, - sc->rx.bufsize, - DMA_FROM_DEVICE); + dma_unmap_single(sc->dev, bf->bf_buf_addr, + sc->rx.bufsize, DMA_FROM_DEVICE); dev_kfree_skb(skb); } } @@ -478,6 +473,159 @@ void ath_flushrecv(struct ath_softc *sc) spin_unlock_bh(&sc->rx.rxflushlock); } +static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) +{ + /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ + struct ieee80211_mgmt *mgmt; + u8 *pos, *end, id, elen; + struct ieee80211_tim_ie *tim; + + mgmt = (struct ieee80211_mgmt *)skb->data; + pos = mgmt->u.beacon.variable; + end = skb->data + skb->len; + + while (pos + 2 < end) { + id = *pos++; + elen = *pos++; + if (pos + elen > end) + break; + + if (id == WLAN_EID_TIM) { + if (elen < sizeof(*tim)) + break; + tim = (struct ieee80211_tim_ie *) pos; + if (tim->dtim_count != 0) + break; + return tim->bitmap_ctrl & 0x01; + } + + pos += elen; + } + + 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; + + if (skb->len < 24 + 8 + 2 + 2) + return; + + mgmt = (struct ieee80211_mgmt *)skb->data; + if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0) + return; /* not from our current AP */ + + 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 " + "timestamp from the AP\n"); + 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 + * frames. + */ + DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating " + "buffered broadcast/multicast frame(s)\n"); + sc->sc_flags |= SC_OP_WAIT_FOR_CAB; + return; + } + + if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) { + /* + * This can happen if a broadcast frame is dropped or the AP + * fails to send a frame indicating that all CAB frames have + * been delivered. + */ + 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) +{ + struct ieee80211_hdr *hdr; + + hdr = (struct ieee80211_hdr *)skb->data; + + /* Process Beacon and CAB receive in PS state */ + if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) && + ieee80211_is_beacon(hdr->frame_control)) + ath_rx_ps_beacon(sc, skb); + else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) && + (ieee80211_is_data(hdr->frame_control) || + 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); + } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && + !is_multicast_ether_addr(hdr->addr1) && + !ieee80211_has_morefrags(hdr->frame_control)) { + sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA; + DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having " + "received PS-Poll data (0x%x)\n", + 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)); + } +} + +static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_hdr *hdr; + + hdr = (struct ieee80211_hdr *)skb->data; + + /* Send the frame to mac80211 */ + if (is_multicast_ether_addr(hdr->addr1)) { + int i; + /* + * Deliver broadcast/multicast frames to all suitable + * virtual wiphys. + */ + /* TODO: filter based on channel configuration */ + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + struct sk_buff *nskb; + if (aphy == NULL) + continue; + nskb = skb_copy(skb, GFP_ATOMIC); + if (nskb) + __ieee80211_rx(aphy->hw, nskb, rx_status); + } + __ieee80211_rx(sc->hw, skb, rx_status); + } else { + /* Deliver unicast frames based on receiver address */ + __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, rx_status); + } +} + int ath_rx_tasklet(struct ath_softc *sc, int flush) { #define PA2DESC(_sc, _pa) \ @@ -627,7 +775,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { rx_status.flag |= RX_FLAG_DECRYPTED; - } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) + } else if (ieee80211_has_protected(fc) && !decrypt_error && skb->len >= hdrlen + 4) { keyix = skb->data[hdrlen + 3] >> 6; @@ -636,36 +784,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) } if (ah->sw_mgmt_crypto && (rx_status.flag & RX_FLAG_DECRYPTED) && - ieee80211_is_mgmt(hdr->frame_control)) { + ieee80211_is_mgmt(fc)) { /* Use software decrypt for management frames. */ rx_status.flag &= ~RX_FLAG_DECRYPTED; } - /* Send the frame to mac80211 */ - if (hdr->addr1[5] & 0x01) { - int i; - /* - * Deliver broadcast/multicast frames to all suitable - * virtual wiphys. - */ - /* TODO: filter based on channel configuration */ - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - struct sk_buff *nskb; - if (aphy == NULL) - continue; - nskb = skb_copy(skb, GFP_ATOMIC); - if (nskb) - __ieee80211_rx(aphy->hw, nskb, - &rx_status); - } - __ieee80211_rx(sc->hw, skb, &rx_status); - } else { - /* Deliver unicast frames based on receiver address */ - __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, - &rx_status); - } - /* We will now give hardware our shiny new allocated skb */ bf->bf_mpdu = requeue_skb; bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, @@ -675,8 +798,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) bf->bf_buf_addr))) { dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, + DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on RX\n"); + ath_rx_send_to_mac80211(sc, skb, &rx_status); break; } bf->bf_dmacontext = bf->bf_buf_addr; @@ -692,11 +816,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) sc->rx.rxotherant = 0; } - if (ieee80211_is_beacon(fc) && - (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); - } + if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | + SC_OP_WAIT_FOR_PSPOLL_DATA))) + ath_rx_ps(sc, skb); + + ath_rx_send_to_mac80211(sc, skb, &rx_status); + requeue: list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h similarity index 100% rename from drivers/net/wireless/ath9k/reg.h rename to drivers/net/wireless/ath/ath9k/reg.h diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c similarity index 100% rename from drivers/net/wireless/ath9k/virtual.c rename to drivers/net/wireless/ath/ath9k/virtual.c diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c similarity index 97% rename from drivers/net/wireless/ath9k/xmit.c rename to drivers/net/wireless/ath/ath9k/xmit.c index 689bdbf78808..b61a071788a5 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -283,7 +283,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; rcu_read_lock(); @@ -380,8 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); } else { /* retry the un-acked ones */ - if (bf->bf_next == NULL && - bf_last->bf_status & ATH_BUFSTATUS_STALE) { + if (bf->bf_next == NULL && bf_last->bf_stale) { struct ath_buf *tbf; tbf = ath_clone_txbuf(sc, bf_last); @@ -435,7 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, struct ath_atx_tid *tid) { - struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = sc->cur_rate_table; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rates; @@ -444,7 +443,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, u16 aggr_limit, legacy = 0, maxampdu; int i; - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; @@ -498,7 +497,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, struct ath_buf *bf, u16 frmlen) { - struct ath_rate_table *rt = sc->cur_rate_table; + 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; @@ -712,6 +711,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) return 0; if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { + txtid->state &= ~AGGR_ADDBA_PROGRESS; txtid->addba_exchangeattempts = 0; return 0; } @@ -972,7 +972,7 @@ int ath_cabq_update(struct ath_softc *sc) else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; - qi.tqi_readyTime = (sc->hw->conf.beacon_int * + qi.tqi_readyTime = (sc->beacon_interval * sc->config.cabqReadytime) / 100; ath_txq_update(sc, qnum, &qi); @@ -1004,7 +1004,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - if (bf->bf_status & ATH_BUFSTATUS_STALE) { + if (bf->bf_stale) { list_del(&bf->list); spin_unlock_bh(&txq->axq_lock); @@ -1071,7 +1071,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); if (r) DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u\n", + "Unable to reset hardware; reset status %d\n", r); spin_unlock_bh(&sc->sc_resetlock); } @@ -1408,7 +1408,7 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, int width, int half_gi, bool shortPreamble) { - struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = sc->cur_rate_table; u32 nbits, nsymbits, duration, nsymbols; u8 rc; int streams, pktlen; @@ -1440,7 +1440,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) { - struct ath_rate_table *rt = sc->cur_rate_table; + const struct ath_rate_table *rt = sc->cur_rate_table; struct ath9k_11n_rate_series series[4]; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; @@ -1452,7 +1452,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; hdr = (struct ieee80211_hdr *)skb->data; @@ -1573,8 +1573,9 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, - "dma_mapping_error() on TX\n"); + kfree(tx_info_priv); + tx_info->rate_driver_data[0] = NULL; + DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); return -ENOMEM; } @@ -1586,7 +1587,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_control *txctl) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_node *an = NULL; @@ -1790,6 +1791,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, skb_pull(skb, padsize); } + if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) { + sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK; + DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having " + "received TX status (0x%x)\n", + 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)); + } + if (frame_type == ATH9K_NOT_INTERNAL) ieee80211_tx_status(hw, skb); else @@ -1860,7 +1871,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad, int txok, bool update_rc) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); @@ -1941,7 +1952,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * it with the STALE flag. */ bf_held = NULL; - if (bf->bf_status & ATH_BUFSTATUS_STALE) { + if (bf->bf_stale) { bf_held = bf; if (list_is_last(&bf_held->list, &txq->axq_q)) { txq->axq_link = NULL; @@ -1982,7 +1993,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * however leave the last descriptor back as the holding * descriptor for hw. */ - lastbf->bf_status |= ATH_BUFSTATUS_STALE; + lastbf->bf_stale = true; INIT_LIST_HEAD(&bf_head); if (!list_is_singular(&lastbf->list)) list_cut_position(&bf_head, @@ -2048,44 +2059,38 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) { int error = 0; - do { - spin_lock_init(&sc->tx.txbuflock); + spin_lock_init(&sc->tx.txbuflock); - error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, - "tx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", - error); - break; - } + error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, + "tx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate tx descriptors: %d\n", error); + goto err; + } - error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", - error); - break; - } - - } while (0); + error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, + "beacon", ATH_BCBUF, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate beacon descriptors: %d\n", error); + goto err; + } +err: if (error != 0) ath_tx_cleanup(sc); return error; } -int ath_tx_cleanup(struct ath_softc *sc) +void ath_tx_cleanup(struct ath_softc *sc) { if (sc->beacon.bdma.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); if (sc->tx.txdma.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); - - return 0; } void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c new file mode 100644 index 000000000000..9949b11cb151 --- /dev/null +++ b/drivers/net/wireless/ath/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 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 +#include + +MODULE_AUTHOR("Atheros Communications"); +MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards."); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath/regd.c similarity index 61% rename from drivers/net/wireless/ath9k/regd.c rename to drivers/net/wireless/ath/regd.c index 4ca625102291..eef370bd1211 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -16,7 +16,9 @@ #include #include -#include "ath9k.h" +#include +#include +#include "regd.h" #include "regd_common.h" /* @@ -55,7 +57,7 @@ /* Can be used for: * 0x60, 0x61, 0x62 */ -static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = { +static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { .n_reg_rules = 5, .alpha2 = "99", .reg_rules = { @@ -65,7 +67,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = { }; /* Can be used by 0x63 and 0x65 */ -static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = { +static const struct ieee80211_regdomain ath_world_regdom_63_65 = { .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { @@ -76,7 +78,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = { }; /* Can be used by 0x64 only */ -static const struct ieee80211_regdomain ath9k_world_regdom_64 = { +static const struct ieee80211_regdomain ath_world_regdom_64 = { .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { @@ -86,7 +88,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_64 = { }; /* Can be used by 0x66 and 0x69 */ -static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = { +static const struct ieee80211_regdomain ath_world_regdom_66_69 = { .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { @@ -96,7 +98,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = { }; /* Can be used by 0x67, 0x6A and 0x68 */ -static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = { +static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { @@ -112,49 +114,51 @@ static inline bool is_wwr_sku(u16 regd) (regd == WORLD); } -static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah) +static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) { - return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG; + return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; } -bool ath9k_is_world_regd(struct ath_hw *ah) +bool ath_is_world_regd(struct ath_regulatory *reg) { - return is_wwr_sku(ath9k_regd_get_eepromRD(ah)); + return is_wwr_sku(ath_regd_get_eepromRD(reg)); } +EXPORT_SYMBOL(ath_is_world_regd); -const struct ieee80211_regdomain *ath9k_default_world_regdomain(void) +static const struct ieee80211_regdomain *ath_default_world_regdomain(void) { /* this is the most restrictive */ - return &ath9k_world_regdom_64; + return &ath_world_regdom_64; } -const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah) +static const struct +ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) { - switch (ah->regulatory.regpair->regDmnEnum) { + switch (reg->regpair->regDmnEnum) { case 0x60: case 0x61: case 0x62: - return &ath9k_world_regdom_60_61_62; + return &ath_world_regdom_60_61_62; case 0x63: case 0x65: - return &ath9k_world_regdom_63_65; + return &ath_world_regdom_63_65; case 0x64: - return &ath9k_world_regdom_64; + return &ath_world_regdom_64; case 0x66: case 0x69: - return &ath9k_world_regdom_66_69; + return &ath_world_regdom_66_69; case 0x67: case 0x68: case 0x6A: - return &ath9k_world_regdom_67_68_6A; + return &ath_world_regdom_67_68_6A; default: WARN_ON(1); - return ath9k_default_world_regdomain(); + return ath_default_world_regdomain(); } } /* Frequency is one where radar detection is required */ -static bool ath9k_is_radar_freq(u16 center_freq) +static bool ath_is_radar_freq(u16 center_freq) { return (center_freq >= 5260 && center_freq <= 5700); } @@ -168,9 +172,9 @@ static bool ath9k_is_radar_freq(u16 center_freq) * received a beacon on a channel we can enable active scan and * adhoc (or beaconing). */ -static void ath9k_reg_apply_beaconing_flags( - struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) +static void +ath_reg_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { enum ieee80211_band band; struct ieee80211_supported_band *sband; @@ -191,13 +195,15 @@ static void ath9k_reg_apply_beaconing_flags( ch = &sband->channels[i]; - if (ath9k_is_radar_freq(ch->center_freq) || + if (ath_is_radar_freq(ch->center_freq) || (ch->flags & IEEE80211_CHAN_RADAR)) continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - r = freq_reg_info(wiphy, ch->center_freq, - &bandwidth, ®_rule); + r = freq_reg_info(wiphy, + ch->center_freq, + bandwidth, + ®_rule); if (r) continue; /* @@ -227,9 +233,9 @@ static void ath9k_reg_apply_beaconing_flags( } /* Allows active scan scan on Ch 12 and 13 */ -static void ath9k_reg_apply_active_scan_flags( - struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) +static void +ath_reg_apply_active_scan_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; @@ -261,7 +267,7 @@ static void ath9k_reg_apply_active_scan_flags( */ ch = &sband->channels[11]; /* CH 12 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) @@ -269,7 +275,7 @@ static void ath9k_reg_apply_active_scan_flags( } ch = &sband->channels[12]; /* CH 13 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) @@ -278,7 +284,7 @@ static void ath9k_reg_apply_active_scan_flags( } /* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ -void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) +static void ath_reg_apply_radar_flags(struct wiphy *wiphy) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; @@ -291,7 +297,7 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; - if (!ath9k_is_radar_freq(ch->center_freq)) + if (!ath_is_radar_freq(ch->center_freq)) continue; /* We always enable radar detection/DFS on this * frequency range. Additionally we also apply on @@ -310,37 +316,31 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) } } -void ath9k_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) +static void ath_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct ath_regulatory *reg) { - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; - - switch (ah->regulatory.regpair->regDmnEnum) { + switch (reg->regpair->regDmnEnum) { case 0x60: case 0x63: case 0x66: case 0x67: - ath9k_reg_apply_beaconing_flags(wiphy, initiator); + ath_reg_apply_beaconing_flags(wiphy, initiator); break; case 0x68: - ath9k_reg_apply_beaconing_flags(wiphy, initiator); - ath9k_reg_apply_active_scan_flags(wiphy, initiator); + ath_reg_apply_beaconing_flags(wiphy, initiator); + ath_reg_apply_active_scan_flags(wiphy, initiator); break; } return; } -int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +int ath_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, + struct ath_regulatory *reg) { - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - /* We always apply this */ - ath9k_reg_apply_radar_flags(wiphy); + ath_reg_apply_radar_flags(wiphy); switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: @@ -348,39 +348,47 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) case NL80211_REGDOM_SET_BY_USER: break; case NL80211_REGDOM_SET_BY_COUNTRY_IE: - if (ath9k_is_world_regd(sc->sc_ah)) - ath9k_reg_apply_world_flags(wiphy, request->initiator); + if (ath_is_world_regd(reg)) + ath_reg_apply_world_flags(wiphy, request->initiator, + reg); break; } return 0; } +EXPORT_SYMBOL(ath_reg_notifier_apply); -bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah) +static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) { - u16 rd = ath9k_regd_get_eepromRD(ah); + u16 rd = ath_regd_get_eepromRD(reg); int i; if (rd & COUNTRY_ERD_FLAG) { /* EEPROM value is a country code */ u16 cc = rd & ~COUNTRY_ERD_FLAG; + printk(KERN_DEBUG + "ath: EEPROM indicates we should expect " + "a country code\n"); for (i = 0; i < ARRAY_SIZE(allCountries); i++) if (allCountries[i].countryCode == cc) return true; } else { /* EEPROM value is a regpair value */ + if (rd != CTRY_DEFAULT) + printk(KERN_DEBUG "ath: EEPROM indicates we " + "should expect a direct regpair map\n"); for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) if (regDomainPairs[i].regDmnEnum == rd) return true; } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "invalid regulatory domain/country code 0x%x\n", rd); + printk(KERN_DEBUG + "ath: invalid regulatory domain/country code 0x%x\n", rd); return false; } /* EEPROM country code to regpair mapping */ static struct country_code_to_enum_rd* -ath9k_regd_find_country(u16 countryCode) +ath_regd_find_country(u16 countryCode) { int i; @@ -393,7 +401,7 @@ ath9k_regd_find_country(u16 countryCode) /* EEPROM rd code to regpair mapping */ static struct country_code_to_enum_rd* -ath9k_regd_find_country_by_rd(int regdmn) +ath_regd_find_country_by_rd(int regdmn) { int i; @@ -405,13 +413,13 @@ ath9k_regd_find_country_by_rd(int regdmn) } /* Returns the map of the EEPROM set RD to a country code */ -static u16 ath9k_regd_get_default_country(u16 rd) +static u16 ath_regd_get_default_country(u16 rd) { if (rd & COUNTRY_ERD_FLAG) { struct country_code_to_enum_rd *country = NULL; u16 cc = rd & ~COUNTRY_ERD_FLAG; - country = ath9k_regd_find_country(cc); + country = ath_regd_find_country(cc); if (country != NULL) return cc; } @@ -420,7 +428,7 @@ static u16 ath9k_regd_get_default_country(u16 rd) } static struct reg_dmn_pair_mapping* -ath9k_get_regpair(int regdmn) +ath_get_regpair(int regdmn) { int i; @@ -433,87 +441,135 @@ ath9k_get_regpair(int regdmn) return NULL; } -int ath9k_regd_init(struct ath_hw *ah) +static int +ath_regd_init_wiphy(struct ath_regulatory *reg, + struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; + wiphy->strict_regulatory = true; + + if (ath_is_world_regd(reg)) { + /* + * Anything applied here (prior to wiphy registration) gets + * saved on the wiphy orig_* parameters + */ + regd = ath_world_regdomain(reg); + wiphy->custom_regulatory = true; + wiphy->strict_regulatory = false; + } else { + /* + * This gets applied in the case of the absense of CRDA, + * it's our own custom world regulatory domain, similar to + * cfg80211's but we enable passive scanning. + */ + regd = ath_default_world_regdomain(); + } + wiphy_apply_custom_regulatory(wiphy, regd); + ath_reg_apply_radar_flags(wiphy); + ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); + return 0; +} + +int +ath_regd_init(struct ath_regulatory *reg, + struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) { struct country_code_to_enum_rd *country = NULL; u16 regdmn; - if (!ath9k_regd_is_eeprom_valid(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Invalid EEPROM contents\n"); + if (!reg) + return -EINVAL; + + printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd); + + if (!ath_regd_is_eeprom_valid(reg)) { + printk(KERN_ERR "ath: Invalid EEPROM contents\n"); return -EINVAL; } - regdmn = ath9k_regd_get_eepromRD(ah); - ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn); + regdmn = ath_regd_get_eepromRD(reg); + reg->country_code = ath_regd_get_default_country(regdmn); - if (ah->regulatory.country_code == CTRY_DEFAULT && - regdmn == CTRY_DEFAULT) - ah->regulatory.country_code = CTRY_UNITED_STATES; - - if (ah->regulatory.country_code == CTRY_DEFAULT) { - country = NULL; - } else { - country = ath9k_regd_find_country(ah->regulatory.country_code); - if (country == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Country is NULL!!!!, cc= %d\n", - ah->regulatory.country_code); - return -EINVAL; - } else - regdmn = country->regDmnEnum; + if (reg->country_code == CTRY_DEFAULT && + regdmn == CTRY_DEFAULT) { + printk(KERN_DEBUG "ath: EEPROM indicates default " + "country code should be used\n"); + reg->country_code = CTRY_UNITED_STATES; } - ah->regulatory.regpair = ath9k_get_regpair(regdmn); + if (reg->country_code == CTRY_DEFAULT) { + country = NULL; + } else { + printk(KERN_DEBUG "ath: doing EEPROM country->regdmn " + "map search\n"); + country = ath_regd_find_country(reg->country_code); + if (country == NULL) { + printk(KERN_DEBUG + "ath: no valid country maps found for " + "country code: 0x%0x\n", + reg->country_code); + return -EINVAL; + } else { + regdmn = country->regDmnEnum; + printk(KERN_DEBUG "ath: country maps to " + "regdmn code: 0x%0x\n", + regdmn); + } + } - if (!ah->regulatory.regpair) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + reg->regpair = ath_get_regpair(regdmn); + + if (!reg->regpair) { + printk(KERN_DEBUG "ath: " "No regulatory domain pair found, cannot continue\n"); return -EINVAL; } if (!country) - country = ath9k_regd_find_country_by_rd(regdmn); + country = ath_regd_find_country_by_rd(regdmn); if (country) { - ah->regulatory.alpha2[0] = country->isoName[0]; - ah->regulatory.alpha2[1] = country->isoName[1]; + reg->alpha2[0] = country->isoName[0]; + reg->alpha2[1] = country->isoName[1]; } else { - ah->regulatory.alpha2[0] = '0'; - ah->regulatory.alpha2[1] = '0'; + reg->alpha2[0] = '0'; + reg->alpha2[1] = '0'; } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Country alpha2 being used: %c%c\n" - "Regulatory.Regpair detected: 0x%0x\n", - ah->regulatory.alpha2[0], ah->regulatory.alpha2[1], - ah->regulatory.regpair->regDmnEnum); + printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n", + reg->alpha2[0], reg->alpha2[1]); + printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", + reg->regpair->regDmnEnum); + ath_regd_init_wiphy(reg, wiphy, reg_notifier); return 0; } +EXPORT_SYMBOL(ath_regd_init); -u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan) +u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, + enum ieee80211_band band) { - u32 ctl = NO_CTL; - - if (!ah->regulatory.regpair || - (ah->regulatory.country_code == CTRY_DEFAULT && - is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) { - if (IS_CHAN_B(chan)) - ctl = SD_NO_CTL | CTL_11B; - else if (IS_CHAN_G(chan)) - ctl = SD_NO_CTL | CTL_11G; - else - ctl = SD_NO_CTL | CTL_11A; - return ctl; + if (!reg->regpair || + (reg->country_code == CTRY_DEFAULT && + is_wwr_sku(ath_regd_get_eepromRD(reg)))) { + return SD_NO_CTL; } - if (IS_CHAN_B(chan)) - ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B; - else if (IS_CHAN_G(chan)) - ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G; - else - ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A; + switch (band) { + case IEEE80211_BAND_2GHZ: + return reg->regpair->reg_2ghz_ctl; + case IEEE80211_BAND_5GHZ: + return reg->regpair->reg_5ghz_ctl; + default: + return NO_CTL; + } - return ctl; + return NO_CTL; } +EXPORT_SYMBOL(ath_regd_get_band_ctl); diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath/regd.h similarity index 85% rename from drivers/net/wireless/ath9k/regd.h rename to drivers/net/wireless/ath/regd.h index 9f5fbd4eea7a..07291ccb23f2 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -17,6 +17,25 @@ #ifndef REGD_H #define REGD_H +#include + +#include + +#define NO_CTL 0xff +#define SD_NO_CTL 0xE0 +#define NO_CTL 0xff +#define CTL_MODE_M 7 +#define CTL_11A 0 +#define CTL_11B 1 +#define CTL_11G 2 +#define CTL_2GHT20 5 +#define CTL_5GHT20 6 +#define CTL_2GHT40 7 +#define CTL_5GHT40 8 + +#define CTRY_DEBUG 0x1ff +#define CTRY_DEFAULT 0 + #define COUNTRY_ERD_FLAG 0x8000 #define WORLDWIDE_ROAMING_FLAG 0x4000 @@ -40,7 +59,7 @@ struct country_code_to_enum_rd { const char *isoName; }; -struct ath9k_regulatory { +struct ath_regulatory { char alpha2[2]; u16 country_code; u16 max_power_level; @@ -233,15 +252,14 @@ enum CountryCode { CTRY_BELGIUM2 = 5002 }; -bool ath9k_is_world_regd(struct ath_hw *ah); -const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah); -const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); -void ath9k_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator); -void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); -int ath9k_regd_init(struct ath_hw *ah); -bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah); -u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan); -int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); +bool ath_is_world_regd(struct ath_regulatory *reg); +int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)); +u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, + enum ieee80211_band band); +int ath_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, + struct ath_regulatory *reg); #endif diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath/regd_common.h similarity index 100% rename from drivers/net/wireless/ath9k/regd_common.h rename to drivers/net/wireless/ath/regd_common.h diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 27eef8fb7107..291a94bd46fd 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -818,7 +818,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&priv->irqlock, flags); spin_unlock_bh(&priv->timerlock); netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; } frame_ctl = IEEE80211_FTYPE_DATA; diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 77406245dc7b..ddaa859c3491 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -279,7 +279,7 @@ static int atmel_config(struct pcmcia_device *link) struct pcmcia_device_id *did; dev = link->priv; - did = handle_to_dev(link).driver_data; + did = dev_get_drvdata(&handle_to_dev(link)); DEBUG(0, "atmel_config(0x%p)\n", link); diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index aab71a70ba78..67f564e37225 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -3,7 +3,6 @@ config B43 depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA select SSB select FW_LOADER - select HW_RANDOM ---help--- b43 is a driver for the Broadcom 43xx series wireless devices. @@ -99,11 +98,11 @@ config B43_LEDS depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43) default y -# This config option automatically enables b43 RFKILL support, -# if it's possible. -config B43_RFKILL +# This config option automatically enables b43 HW-RNG support, +# if the HW-RNG core is enabled. +config B43_HWRNG bool - depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43) + depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43) default y config B43_DEBUG diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 281ef8310350..da379f4b0c3a 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -13,7 +13,7 @@ b43-y += lo.o b43-y += wa.o b43-y += dma.o b43-$(CONFIG_B43_PIO) += pio.o -b43-$(CONFIG_B43_RFKILL) += rfkill.o +b43-y += rfkill.o b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o b43-$(CONFIG_B43_DEBUG) += debugfs.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index beaf18d6e8a7..f580c2812d91 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -163,6 +163,7 @@ enum { #define B43_SHM_SH_WLCOREREV 0x0016 /* 802.11 core revision */ #define B43_SHM_SH_PCTLWDPOS 0x0008 #define B43_SHM_SH_RXPADOFF 0x0034 /* RX Padding data offset (PIO only) */ +#define B43_SHM_SH_FWCAPA 0x0042 /* Firmware capabilities (Opensource firmware only) */ #define B43_SHM_SH_PHYVER 0x0050 /* PHY version */ #define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */ #define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */ @@ -297,6 +298,10 @@ enum { #define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */ #define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */ +/* Firmware capabilities field in SHM (Opensource firmware only) */ +#define B43_FWCAPA_HWCRYPTO 0x0001 +#define B43_FWCAPA_QOS 0x0002 + /* MacFilter offsets. */ #define B43_MACFILTER_SELF 0x0000 #define B43_MACFILTER_BSSID 0x0003 @@ -596,6 +601,13 @@ struct b43_wl { /* Pointer to the ieee80211 hardware data structure */ struct ieee80211_hw *hw; + /* The number of queues that were registered with the mac80211 subsystem + * initially. This is a backup copy of hw->queues in case hw->queues has + * to be dynamically lowered at runtime (Firmware does not support QoS). + * hw->queues has to be restored to the original value before unregistering + * from the mac80211 subsystem. */ + u16 mac80211_initially_registered_queues; + struct mutex mutex; spinlock_t irq_lock; /* R/W lock for data transmission. @@ -625,12 +637,11 @@ struct b43_wl { /* Stats about the wireless interface */ struct ieee80211_low_level_stats ieee_stats; +#ifdef CONFIG_B43_HWRNG struct hwrng rng; - u8 rng_initialized; + bool rng_initialized; char rng_name[30 + 1]; - - /* The RF-kill button */ - struct b43_rfkill rfkill; +#endif /* CONFIG_B43_HWRNG */ /* List of all wireless devices on this chip */ struct list_head devlist; @@ -750,6 +761,8 @@ struct b43_wldev { bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ + bool qos_enabled; /* TRUE, if QoS is used. */ + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ /* PHY/Radio device. */ struct b43_phy phy; @@ -776,8 +789,8 @@ struct b43_wldev { /* Reason code of the last interrupt. */ u32 irq_reason; u32 dma_reason[6]; - /* saved irq enable/disable state bitfield. */ - u32 irq_savedstate; + /* The currently active generic-interrupt mask. */ + u32 irq_mask; /* Link Quality calculation context. */ struct b43_noise_calculation noisecalc; /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index eae680b53052..7964cc32b258 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1285,7 +1285,7 @@ static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev, { struct b43_dmaring *ring; - if (b43_modparam_qos) { + if (dev->qos_enabled) { /* 0 = highest priority */ switch (queue_prio) { default: diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index 76f4c7bad8b8..c8b317094c31 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -28,6 +28,7 @@ #include "b43.h" #include "leds.h" +#include "rfkill.h" static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, @@ -87,7 +88,7 @@ static void b43_led_brightness_set(struct led_classdev *led_dev, } static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, - const char *name, char *default_trigger, + const char *name, const char *default_trigger, u8 led_index, bool activelow) { int err; @@ -164,10 +165,10 @@ static void b43_map_led(struct b43_wldev *dev, snprintf(name, sizeof(name), "b43-%s::radio", wiphy_name(hw->wiphy)); b43_register_led(dev, &dev->led_radio, name, - b43_rfkill_led_name(dev), + ieee80211_get_radio_led_name(hw), led_index, activelow); - /* Sync the RF-kill LED state with the switch state. */ - if (dev->radio_hw_enable) + /* Sync the RF-kill LED state with radio and switch states. */ + if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) b43_led_turn_on(dev, led_index, activelow); break; case B43_LED_WEIRD: diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 79b685e300c7..6456afebdba1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -80,8 +80,8 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); -int b43_modparam_qos = 1; -module_param_named(qos, b43_modparam_qos, int, 0444); +static int modparam_qos = 1; +module_param_named(qos, modparam_qos, int, 0444); MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); static int modparam_btcoex = 1; @@ -538,6 +538,13 @@ void b43_hf_write(struct b43_wldev *dev, u64 value) b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); } +/* Read the firmware capabilities bitmask (Opensource firmware only) */ +static u16 b43_fwcapa_read(struct b43_wldev *dev) +{ + B43_WARN_ON(!dev->fw.opensource); + return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA); +} + void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) { u32 low, high; @@ -673,32 +680,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev) b43_set_slot_time(dev, 20); } -/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask) -{ - u32 old_mask; - - old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask); - - return old_mask; -} - -/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask) -{ - u32 old_mask; - - old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask); - - return old_mask; -} - /* Synchronize IRQ top- and bottom-half. * IRQs must be masked before calling this. * This must not be called with the irq_lock held. @@ -1593,7 +1574,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) /* This is the bottom half of the asynchronous beacon update. */ /* Ignore interrupt in the future. */ - dev->irq_savedstate &= ~B43_IRQ_BEACON; + dev->irq_mask &= ~B43_IRQ_BEACON; cmd = b43_read32(dev, B43_MMIO_MACCMD); beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); @@ -1602,7 +1583,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) /* Schedule interrupt manually, if busy. */ if (beacon0_valid && beacon1_valid) { b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON); - dev->irq_savedstate |= B43_IRQ_BEACON; + dev->irq_mask |= B43_IRQ_BEACON; return; } @@ -1641,11 +1622,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { spin_lock_irq(&wl->irq_lock); /* update beacon right away or defer to irq */ - dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); handle_irq_beacon(dev); /* The handler might have updated the IRQ mask. */ - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, - dev->irq_savedstate); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); mmiowb(); spin_unlock_irq(&wl->irq_lock); } @@ -1879,7 +1858,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) if (reason & B43_IRQ_TX_OK) handle_irq_transmit_status(dev); - b43_interrupt_enable(dev, dev->irq_savedstate); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); } @@ -1893,7 +1872,9 @@ static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason) b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); +/* Unused ring b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]); +*/ } /* Interrupt handler top-half */ @@ -1903,18 +1884,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) struct b43_wldev *dev = dev_id; u32 reason; - if (!dev) - return IRQ_NONE; + B43_WARN_ON(!dev); spin_lock(&dev->wl->irq_lock); - if (b43_status(dev) < B43_STAT_STARTED) + if (unlikely(b43_status(dev) < B43_STAT_STARTED)) { + /* This can only happen on shared IRQ lines. */ goto out; + } reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) /* shared IRQ */ goto out; ret = IRQ_HANDLED; - reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); + reason &= dev->irq_mask; if (!reason) goto out; @@ -1928,16 +1910,18 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) & 0x0001DC00; dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON) & 0x0000DC00; +/* Unused ring dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON) & 0x0000DC00; +*/ b43_interrupt_ack(dev, reason); /* disable all IRQs. They are enabled again in the bottom half. */ - dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); /* save the reason code and call our bottom half. */ dev->irq_reason = reason; tasklet_schedule(&dev->isr_tasklet); - out: +out: mmiowb(); spin_unlock(&dev->wl->irq_lock); @@ -2330,12 +2314,34 @@ static int b43_upload_microcode(struct b43_wldev *dev) dev->fw.patch = fwpatch; dev->fw.opensource = (fwdate == 0xFFFF); + /* Default to use-all-queues. */ + dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues; + dev->qos_enabled = !!modparam_qos; + /* Default to firmware/hardware crypto acceleration. */ + dev->hwcrypto_enabled = 1; + if (dev->fw.opensource) { + u16 fwcapa; + /* Patchlevel info is encoded in the "time" field. */ dev->fw.patch = fwtime; - b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n", - dev->fw.rev, dev->fw.patch, - dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : ""); + b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n", + dev->fw.rev, dev->fw.patch); + + fwcapa = b43_fwcapa_read(dev); + if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) { + b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n"); + /* Disable hardware crypto and fall back to software crypto. */ + dev->hwcrypto_enabled = 0; + } + if (!(fwcapa & B43_FWCAPA_QOS)) { + b43info(dev->wl, "QoS not supported by firmware\n"); + /* Disable QoS. Tweak hw->queues to 1. It will be restored before + * ieee80211_unregister to make sure the networking core can + * properly free possible resources. */ + dev->wl->hw->queues = 1; + dev->qos_enabled = 0; + } } else { b43info(dev->wl, "Loading firmware version %u.%u " "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", @@ -2980,6 +2986,7 @@ static void b43_security_init(struct b43_wldev *dev) b43_clear_keys(dev); } +#ifdef CONFIG_B43_HWRNG static int b43_rng_read(struct hwrng *rng, u32 *data) { struct b43_wl *wl = (struct b43_wl *)rng->priv; @@ -2995,17 +3002,21 @@ static int b43_rng_read(struct hwrng *rng, u32 *data) return (sizeof(u16)); } +#endif /* CONFIG_B43_HWRNG */ static void b43_rng_exit(struct b43_wl *wl) { +#ifdef CONFIG_B43_HWRNG if (wl->rng_initialized) hwrng_unregister(&wl->rng); +#endif /* CONFIG_B43_HWRNG */ } static int b43_rng_init(struct b43_wl *wl) { - int err; + int err = 0; +#ifdef CONFIG_B43_HWRNG snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); wl->rng.name = wl->rng_name; @@ -3018,6 +3029,7 @@ static int b43_rng_init(struct b43_wl *wl) b43err(wl, "Failed to register the random " "number generator (%d)\n", err); } +#endif /* CONFIG_B43_HWRNG */ return err; } @@ -3485,14 +3497,9 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) if (phy->ops->set_rx_antenna) phy->ops->set_rx_antenna(dev, antenna); - /* Update templates for AP/mesh mode. */ - if (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) - b43_set_beacon_int(dev, conf->beacon_int); - if (!!conf->radio_enabled != phy->radio_on) { if (conf->radio_enabled) { - b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED); + b43_software_rfkill(dev, false); b43info(dev->wl, "Radio turned on by software\n"); if (!dev->radio_hw_enable) { b43info(dev->wl, "The hardware RF-kill button " @@ -3500,7 +3507,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) "Press the button to turn it on.\n"); } } else { - b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); + b43_software_rfkill(dev, true); b43info(dev->wl, "Radio turned off by software\n"); } } @@ -3565,14 +3572,45 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; + unsigned long flags; mutex_lock(&wl->mutex); dev = wl->current_dev; if (!dev || b43_status(dev) < B43_STAT_STARTED) goto out_unlock_mutex; + + B43_WARN_ON(wl->vif != vif); + + spin_lock_irqsave(&wl->irq_lock, flags); + if (changed & BSS_CHANGED_BSSID) { + if (conf->bssid) + memcpy(wl->bssid, conf->bssid, ETH_ALEN); + else + memset(wl->bssid, 0, ETH_ALEN); + } + + if (b43_status(dev) >= B43_STAT_INITIALIZED) { + if (changed & BSS_CHANGED_BEACON && + (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || + b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43_update_templates(wl); + + if (changed & BSS_CHANGED_BSSID) + b43_write_mac_bssid_templates(dev); + } + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43_mac_suspend(dev); + /* Update templates for AP/mesh mode. */ + if (changed & BSS_CHANGED_BEACON_INT && + (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || + b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43_set_beacon_int(dev, conf->beacon_int); + if (changed & BSS_CHANGED_BASIC_RATES) b43_update_basic_rates(dev, conf->basic_rates); @@ -3586,8 +3624,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, b43_mac_enable(dev); out_unlock_mutex: mutex_unlock(&wl->mutex); - - return; } static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -3620,7 +3656,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) goto out_unlock; - if (dev->fw.pcm_request_failed) { + if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) { /* We don't have firmware for the crypto engine. * Must use software-crypto. */ err = -EOPNOTSUPP; @@ -3630,7 +3666,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, err = -EINVAL; switch (key->alg) { case ALG_WEP: - if (key->keylen == LEN_WEP40) + if (key->keylen == WLAN_KEY_LEN_WEP40) algorithm = B43_SEC_ALGO_WEP40; else algorithm = B43_SEC_ALGO_WEP104; @@ -3745,41 +3781,6 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); } -static int b43_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev = wl->current_dev; - unsigned long flags; - - if (!dev) - return -ENODEV; - mutex_lock(&wl->mutex); - spin_lock_irqsave(&wl->irq_lock, flags); - B43_WARN_ON(wl->vif != vif); - if (conf->bssid) - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - else - memset(wl->bssid, 0, ETH_ALEN); - if (b43_status(dev) >= B43_STAT_INITIALIZED) { - if (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { - B43_WARN_ON(vif->type != wl->if_type); - if (conf->changed & IEEE80211_IFCC_BEACON) - b43_update_templates(wl); - } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { - if (conf->changed & IEEE80211_IFCC_BEACON) - b43_update_templates(wl); - } - b43_write_mac_bssid_templates(dev); - } - spin_unlock_irqrestore(&wl->irq_lock, flags); - mutex_unlock(&wl->mutex); - - return 0; -} - /* Locking: wl->mutex */ static void b43_wireless_core_stop(struct b43_wldev *dev) { @@ -3793,7 +3794,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) * setting the status to INITIALIZED, as the interrupt handler * won't care about IRQs then. */ spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ spin_unlock_irqrestore(&wl->irq_lock, flags); b43_synchronize_irq(dev); @@ -3834,7 +3835,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev) /* Start data flow (TX/RX). */ b43_mac_enable(dev); - b43_interrupt_enable(dev, dev->irq_savedstate); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); /* Start maintainance work */ b43_periodic_tasks_setup(dev); @@ -3997,9 +3998,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) /* IRQ related flags */ dev->irq_reason = 0; memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); - dev->irq_savedstate = B43_IRQ_MASKTEMPLATE; + dev->irq_mask = B43_IRQ_MASKTEMPLATE; if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) - dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR; + dev->irq_mask &= ~B43_IRQ_PHY_TXERR; dev->mac_suspended = 1; @@ -4326,7 +4327,6 @@ static int b43_op_start(struct ieee80211_hw *hw) struct b43_wldev *dev = wl->current_dev; int did_init = 0; int err = 0; - bool do_rfkill_exit = 0; /* Kill all old instance specific information to make sure * the card won't use it in the short timeframe between start @@ -4340,18 +4340,12 @@ static int b43_op_start(struct ieee80211_hw *hw) wl->beacon1_uploaded = 0; wl->beacon_templates_virgin = 1; - /* First register RFkill. - * LEDs that are registered later depend on it. */ - b43_rfkill_init(dev); - mutex_lock(&wl->mutex); if (b43_status(dev) < B43_STAT_INITIALIZED) { err = b43_wireless_core_init(dev); - if (err) { - do_rfkill_exit = 1; + if (err) goto out_mutex_unlock; - } did_init = 1; } @@ -4360,17 +4354,16 @@ static int b43_op_start(struct ieee80211_hw *hw) if (err) { if (did_init) b43_wireless_core_exit(dev); - do_rfkill_exit = 1; goto out_mutex_unlock; } } + /* XXX: only do if device doesn't support rfkill irq */ + wiphy_rfkill_start_polling(hw->wiphy); + out_mutex_unlock: mutex_unlock(&wl->mutex); - if (do_rfkill_exit) - b43_rfkill_exit(dev); - return err; } @@ -4379,7 +4372,6 @@ static void b43_op_stop(struct ieee80211_hw *hw) struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; - b43_rfkill_exit(dev); cancel_work_sync(&(wl->beacon_update_trigger)); mutex_lock(&wl->mutex); @@ -4449,7 +4441,6 @@ static const struct ieee80211_ops b43_hw_ops = { .remove_interface = b43_op_remove_interface, .config = b43_op_config, .bss_info_changed = b43_op_bss_info_changed, - .config_interface = b43_op_config_interface, .configure_filter = b43_op_configure_filter, .set_key = b43_op_set_key, .get_stats = b43_op_get_stats, @@ -4462,6 +4453,7 @@ static const struct ieee80211_ops b43_hw_ops = { .sta_notify = b43_op_sta_notify, .sw_scan_start = b43_op_sw_scan_start_notifier, .sw_scan_complete = b43_op_sw_scan_complete_notifier, + .rfkill_poll = b43_rfkill_poll, }; /* Hard-reset the chip. Do not call this directly. @@ -4764,6 +4756,7 @@ static int b43_wireless_init(struct ssb_device *dev) b43err(NULL, "Could not allocate ieee80211 device\n"); goto out; } + wl = hw_to_b43_wl(hw); /* fill hw info */ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | @@ -4777,7 +4770,8 @@ static int b43_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_ADHOC); - hw->queues = b43_modparam_qos ? 4 : 1; + hw->queues = modparam_qos ? 4 : 1; + wl->mac80211_initially_registered_queues = hw->queues; hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) @@ -4785,9 +4779,7 @@ static int b43_wireless_init(struct ssb_device *dev) else SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac); - /* Get and initialize struct b43_wl */ - wl = hw_to_b43_wl(hw); - memset(wl, 0, sizeof(*wl)); + /* Initialize struct b43_wl */ wl->hw = hw; spin_lock_init(&wl->irq_lock); rwlock_init(&wl->tx_lock); @@ -4853,8 +4845,13 @@ static void b43_remove(struct ssb_device *dev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); - if (wl->current_dev == wldev) + if (wl->current_dev == wldev) { + /* Restore the queues count before unregistering, because firmware detect + * might have modified it. Restoring is important, so the networking + * stack can properly free resources. */ + wl->hw->queues = wl->mac80211_initially_registered_queues; ieee80211_unregister_hw(wl->hw); + } b43_one_core_detach(dev); @@ -4949,7 +4946,7 @@ static struct ssb_driver b43_ssb_driver = { static void b43_print_driverinfo(void) { const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", - *feat_leds = "", *feat_rfkill = ""; + *feat_leds = ""; #ifdef CONFIG_B43_PCI_AUTOSELECT feat_pci = "P"; @@ -4962,15 +4959,12 @@ static void b43_print_driverinfo(void) #endif #ifdef CONFIG_B43_LEDS feat_leds = "L"; -#endif -#ifdef CONFIG_B43_RFKILL - feat_rfkill = "R"; #endif printk(KERN_INFO "Broadcom 43xx driver loaded " - "[ Features: %s%s%s%s%s, Firmware-ID: " + "[ Features: %s%s%s%s, Firmware-ID: " B43_SUPPORTED_FIRMWARE_ID " ]\n", feat_pci, feat_pcmcia, feat_nphy, - feat_leds, feat_rfkill); + feat_leds); } static int __init b43_init(void) diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 40abcf5d1b43..950fb1b0546d 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -39,7 +39,6 @@ #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) -extern int b43_modparam_qos; extern int b43_modparam_verbose; /* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c index c836c077d51d..816e028a2620 100644 --- a/drivers/net/wireless/b43/phy_a.c +++ b/drivers/net/wireless/b43/phy_a.c @@ -480,11 +480,11 @@ static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev) } static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, - enum rfkill_state state) + bool blocked) { struct b43_phy *phy = &dev->phy; - if (state == RFKILL_STATE_UNBLOCKED) { + if (!blocked) { if (phy->radio_on) return; b43_radio_write16(dev, 0x0004, 0x00C0); diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index e176b6e0d9cf..6d241622210e 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -84,7 +84,7 @@ int b43_phy_init(struct b43_wldev *dev) phy->channel = ops->get_default_chan(dev); - ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED); + ops->software_rfkill(dev, false); err = ops->init(dev); if (err) { b43err(dev->wl, "PHY init failed\n"); @@ -104,7 +104,7 @@ int b43_phy_init(struct b43_wldev *dev) if (ops->exit) ops->exit(dev); err_block_rf: - ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); + ops->software_rfkill(dev, true); return err; } @@ -113,7 +113,7 @@ void b43_phy_exit(struct b43_wldev *dev) { const struct b43_phy_operations *ops = dev->phy.ops; - ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); + ops->software_rfkill(dev, true); if (ops->exit) ops->exit(dev); } @@ -295,18 +295,13 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) return err; } -void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state) +void b43_software_rfkill(struct b43_wldev *dev, bool blocked) { struct b43_phy *phy = &dev->phy; - if (state == RFKILL_STATE_HARD_BLOCKED) { - /* We cannot hardware-block the device */ - state = RFKILL_STATE_SOFT_BLOCKED; - } - b43_mac_suspend(dev); - phy->ops->software_rfkill(dev, state); - phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); + phy->ops->software_rfkill(dev, blocked); + phy->radio_on = !blocked; b43_mac_enable(dev); } diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index b2d99101947b..44cc918e4fc6 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -1,7 +1,7 @@ #ifndef LINUX_B43_PHY_COMMON_H_ #define LINUX_B43_PHY_COMMON_H_ -#include +#include struct b43_wldev; @@ -159,7 +159,7 @@ struct b43_phy_operations { /* Radio */ bool (*supports_hwpctl)(struct b43_wldev *dev); - void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state); + void (*software_rfkill)(struct b43_wldev *dev, bool blocked); void (*switch_analog)(struct b43_wldev *dev, bool on); int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel); unsigned int (*get_default_chan)(struct b43_wldev *dev); @@ -364,7 +364,7 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel); /** * b43_software_rfkill - Turn the radio ON or OFF in software. */ -void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state); +void b43_software_rfkill(struct b43_wldev *dev, bool blocked); /** * b43_phy_txpower_check - Check TX power output. diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index e7b98f013b0f..5300232449f6 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -2592,7 +2592,7 @@ static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev) } static void b43_gphy_op_software_rfkill(struct b43_wldev *dev, - enum rfkill_state state) + bool blocked) { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; @@ -2600,7 +2600,7 @@ static void b43_gphy_op_software_rfkill(struct b43_wldev *dev, might_sleep(); - if (state == RFKILL_STATE_UNBLOCKED) { + if (!blocked) { /* Turn radio ON */ if (phy->radio_on) return; diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 58e319d6b1ed..ea0d3a3a6a64 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -488,7 +488,7 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) } static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, - enum rfkill_state state) + bool blocked) { //TODO } diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 8bcfda5f3f07..be7b5604947b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -579,7 +579,7 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) } static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, - enum rfkill_state state) + bool blocked) {//TODO } diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 8cd9776752e6..69138e8c1db6 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -313,7 +313,7 @@ static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev, { struct b43_pio_txqueue *q; - if (b43_modparam_qos) { + if (dev->qos_enabled) { /* 0 = highest priority */ switch (queue_prio) { default: diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index afad42358693..31e55999893f 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -22,15 +22,11 @@ */ -#include "rfkill.h" #include "b43.h" -#include "phy_common.h" - -#include /* Returns TRUE, if the radio is enabled in hardware. */ -static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) +bool b43_is_hw_radio_enabled(struct b43_wldev *dev) { if (dev->phy.rev >= 3) { if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) @@ -45,166 +41,39 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) } /* The poll callback for the hardware button. */ -static void b43_rfkill_poll(struct input_polled_dev *poll_dev) +void b43_rfkill_poll(struct ieee80211_hw *hw) { - struct b43_wldev *dev = poll_dev->private; - struct b43_wl *wl = dev->wl; + struct b43_wl *wl = hw_to_b43_wl(hw); + struct b43_wldev *dev = wl->current_dev; + struct ssb_bus *bus = dev->dev->bus; bool enabled; - bool report_change = 0; + bool brought_up = false; mutex_lock(&wl->mutex); if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) { - mutex_unlock(&wl->mutex); - return; + if (ssb_bus_powerup(bus, 0)) { + mutex_unlock(&wl->mutex); + return; + } + ssb_device_enable(dev->dev, 0); + brought_up = true; } + enabled = b43_is_hw_radio_enabled(dev); + if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; - report_change = 1; b43info(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); + wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); + if (enabled != dev->phy.radio_on) + b43_software_rfkill(dev, !enabled); } + + if (brought_up) { + ssb_device_disable(dev->dev, 0); + ssb_bus_may_powerdown(bus); + } + mutex_unlock(&wl->mutex); - - /* send the radio switch event to the system - note both a key press - * and a release are required */ - if (unlikely(report_change)) { - input_report_key(poll_dev->input, KEY_WLAN, 1); - input_report_key(poll_dev->input, KEY_WLAN, 0); - } -} - -/* Called when the RFKILL toggled in software. */ -static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) -{ - struct b43_wldev *dev = data; - struct b43_wl *wl = dev->wl; - int err = -EBUSY; - - if (!wl->rfkill.registered) - return 0; - - mutex_lock(&wl->mutex); - if (b43_status(dev) < B43_STAT_INITIALIZED) - goto out_unlock; - err = 0; - switch (state) { - case RFKILL_STATE_UNBLOCKED: - if (!dev->radio_hw_enable) { - /* No luck. We can't toggle the hardware RF-kill - * button from software. */ - err = -EBUSY; - goto out_unlock; - } - if (!dev->phy.radio_on) - b43_software_rfkill(dev, state); - break; - case RFKILL_STATE_SOFT_BLOCKED: - if (dev->phy.radio_on) - b43_software_rfkill(dev, state); - break; - default: - b43warn(wl, "Received unexpected rfkill state %d.\n", state); - break; - } -out_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - -char *b43_rfkill_led_name(struct b43_wldev *dev) -{ - struct b43_rfkill *rfk = &(dev->wl->rfkill); - - if (!rfk->registered) - return NULL; - return rfkill_get_led_name(rfk->rfkill); -} - -void b43_rfkill_init(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - struct b43_rfkill *rfk = &(wl->rfkill); - int err; - - rfk->registered = 0; - - rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); - if (!rfk->rfkill) - goto out_error; - snprintf(rfk->name, sizeof(rfk->name), - "b43-%s", wiphy_name(wl->hw->wiphy)); - rfk->rfkill->name = rfk->name; - rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; - rfk->rfkill->data = dev; - rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; - rfk->rfkill->user_claim_unsupported = 1; - - rfk->poll_dev = input_allocate_polled_device(); - if (!rfk->poll_dev) { - rfkill_free(rfk->rfkill); - goto err_freed_rfk; - } - - rfk->poll_dev->private = dev; - rfk->poll_dev->poll = b43_rfkill_poll; - rfk->poll_dev->poll_interval = 1000; /* msecs */ - - rfk->poll_dev->input->name = rfk->name; - rfk->poll_dev->input->id.bustype = BUS_HOST; - rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor; - rfk->poll_dev->input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WLAN, rfk->poll_dev->input->keybit); - - err = rfkill_register(rfk->rfkill); - if (err) - goto err_free_polldev; - -#ifdef CONFIG_RFKILL_INPUT_MODULE - /* B43 RF-kill isn't useful without the rfkill-input subsystem. - * Try to load the module. */ - err = request_module("rfkill-input"); - if (err) - b43warn(wl, "Failed to load the rfkill-input module. " - "The built-in radio LED will not work.\n"); -#endif /* CONFIG_RFKILL_INPUT */ - -#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE) - b43warn(wl, "The rfkill-input subsystem is not available. " - "The built-in radio LED will not work.\n"); -#endif - - err = input_register_polled_device(rfk->poll_dev); - if (err) - goto err_unreg_rfk; - - rfk->registered = 1; - - return; -err_unreg_rfk: - rfkill_unregister(rfk->rfkill); -err_free_polldev: - input_free_polled_device(rfk->poll_dev); - rfk->poll_dev = NULL; -err_freed_rfk: - rfk->rfkill = NULL; -out_error: - rfk->registered = 0; - b43warn(wl, "RF-kill button init failed\n"); -} - -void b43_rfkill_exit(struct b43_wldev *dev) -{ - struct b43_rfkill *rfk = &(dev->wl->rfkill); - - if (!rfk->registered) - return; - rfk->registered = 0; - - input_unregister_polled_device(rfk->poll_dev); - rfkill_unregister(rfk->rfkill); - input_free_polled_device(rfk->poll_dev); - rfk->poll_dev = NULL; - rfk->rfkill = NULL; } diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h index adacf936d815..f046c3ca0519 100644 --- a/drivers/net/wireless/b43/rfkill.h +++ b/drivers/net/wireless/b43/rfkill.h @@ -1,52 +1,11 @@ #ifndef B43_RFKILL_H_ #define B43_RFKILL_H_ +struct ieee80211_hw; struct b43_wldev; +void b43_rfkill_poll(struct ieee80211_hw *hw); -#ifdef CONFIG_B43_RFKILL - -#include -#include - - -struct b43_rfkill { - /* The RFKILL subsystem data structure */ - struct rfkill *rfkill; - /* The poll device for the RFKILL input button */ - struct input_polled_dev *poll_dev; - /* Did initialization succeed? Used for freeing. */ - bool registered; - /* The unique name of this rfkill switch */ - char name[sizeof("b43-phy4294967295")]; -}; - -/* The init function returns void, because we are not interested - * in failing the b43 init process when rfkill init failed. */ -void b43_rfkill_init(struct b43_wldev *dev); -void b43_rfkill_exit(struct b43_wldev *dev); - -char * b43_rfkill_led_name(struct b43_wldev *dev); - - -#else /* CONFIG_B43_RFKILL */ -/* No RFKILL support. */ - -struct b43_rfkill { - /* empty */ -}; - -static inline void b43_rfkill_init(struct b43_wldev *dev) -{ -} -static inline void b43_rfkill_exit(struct b43_wldev *dev) -{ -} -static inline char * b43_rfkill_led_name(struct b43_wldev *dev) -{ - return NULL; -} - -#endif /* CONFIG_B43_RFKILL */ +bool b43_is_hw_radio_enabled(struct b43_wldev *dev); #endif /* B43_RFKILL_H_ */ diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index a63d88841df8..55f36a7254d9 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -118,7 +118,6 @@ u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate) void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, const u16 octets, const u8 bitrate) { - __le32 *data = &(plcp->data); __u8 *raw = plcp->raw; if (b43_is_ofdm_rate(bitrate)) { @@ -127,7 +126,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, d = b43_plcp_get_ratecode_ofdm(bitrate); B43_WARN_ON(octets & 0xF000); d |= (octets << 5); - *data = cpu_to_le32(d); + plcp->data = cpu_to_le32(d); } else { u32 plen; @@ -141,7 +140,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, raw[1] = 0x04; } else raw[1] = 0x04; - *data |= cpu_to_le32(plen << 16); + plcp->data |= cpu_to_le32(plen << 16); raw[0] = b43_plcp_get_ratecode_cck(bitrate); } } diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig index aef2298d37ac..94a463478053 100644 --- a/drivers/net/wireless/b43legacy/Kconfig +++ b/drivers/net/wireless/b43legacy/Kconfig @@ -3,7 +3,6 @@ config B43LEGACY depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA select SSB select FW_LOADER - select HW_RANDOM ---help--- b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the @@ -43,12 +42,11 @@ config B43LEGACY_LEDS depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY) default y -# RFKILL support -# This config option automatically enables b43legacy RFKILL support, -# if it's possible. -config B43LEGACY_RFKILL +# This config option automatically enables b43 HW-RNG support, +# if the HW-RNG core is enabled. +config B43LEGACY_HWRNG bool - depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY) + depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY) default y config B43LEGACY_DEBUG diff --git a/drivers/net/wireless/b43legacy/Makefile b/drivers/net/wireless/b43legacy/Makefile index 80cdb73bd140..227a77e84362 100644 --- a/drivers/net/wireless/b43legacy/Makefile +++ b/drivers/net/wireless/b43legacy/Makefile @@ -6,7 +6,7 @@ b43legacy-y += radio.o b43legacy-y += sysfs.o b43legacy-y += xmit.o # b43 RFKILL button support -b43legacy-$(CONFIG_B43LEGACY_RFKILL) += rfkill.o +b43legacy-y += rfkill.o # b43legacy LED support b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o # b43legacy debugging diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 97b0e06dfe21..77fda148ac46 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -59,7 +59,8 @@ #define B43legacy_MMIO_XMITSTAT_1 0x174 #define B43legacy_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ #define B43legacy_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ - +#define B43legacy_MMIO_TSF_CFP_REP 0x188 +#define B43legacy_MMIO_TSF_CFP_START 0x18C /* 32-bit DMA */ #define B43legacy_MMIO_DMA32_BASE0 0x200 #define B43legacy_MMIO_DMA32_BASE1 0x220 @@ -258,7 +259,6 @@ #define B43legacy_IRQ_ALL 0xFFFFFFFF #define B43legacy_IRQ_MASKTEMPLATE (B43legacy_IRQ_MAC_SUSPENDED | \ - B43legacy_IRQ_BEACON | \ B43legacy_IRQ_TBTT_INDI | \ B43legacy_IRQ_ATIM_END | \ B43legacy_IRQ_PMQ | \ @@ -596,12 +596,11 @@ struct b43legacy_wl { /* Stats about the wireless interface */ struct ieee80211_low_level_stats ieee_stats; +#ifdef CONFIG_B43LEGACY_HWRNG struct hwrng rng; u8 rng_initialized; char rng_name[30 + 1]; - - /* The RF-kill button */ - struct b43legacy_rfkill rfkill; +#endif /* List of all wireless devices on this chip */ struct list_head devlist; @@ -614,6 +613,8 @@ struct b43legacy_wl { struct sk_buff *current_beacon; bool beacon0_uploaded; bool beacon1_uploaded; + bool beacon_templates_virgin; /* Never wrote the templates? */ + struct work_struct beacon_update_trigger; }; /* Pointers to the firmware data and meta information about it. */ @@ -690,8 +691,8 @@ struct b43legacy_wldev { /* Reason code of the last interrupt. */ u32 irq_reason; u32 dma_reason[6]; - /* saved irq enable/disable state bitfield. */ - u32 irq_savedstate; + /* The currently active generic-interrupt mask. */ + u32 irq_mask; /* Link Quality calculation context. */ struct b43legacy_noise_calculation noisecalc; /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c index 3ea55b18c700..37e9be893560 100644 --- a/drivers/net/wireless/b43legacy/leds.c +++ b/drivers/net/wireless/b43legacy/leds.c @@ -28,6 +28,7 @@ #include "b43legacy.h" #include "leds.h" +#include "rfkill.h" static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index, @@ -86,7 +87,8 @@ static void b43legacy_led_brightness_set(struct led_classdev *led_dev, static int b43legacy_register_led(struct b43legacy_wldev *dev, struct b43legacy_led *led, - const char *name, char *default_trigger, + const char *name, + const char *default_trigger, u8 led_index, bool activelow) { int err; @@ -163,10 +165,10 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev, snprintf(name, sizeof(name), "b43legacy-%s::radio", wiphy_name(hw->wiphy)); b43legacy_register_led(dev, &dev->led_radio, name, - b43legacy_rfkill_led_name(dev), + ieee80211_get_radio_led_name(hw), led_index, activelow); - /* Sync the RF-kill LED state with the switch state. */ - if (dev->radio_hw_enable) + /* Sync the RF-kill LED state with radio and switch states. */ + if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev)) b43legacy_led_turn_on(dev, led_index, activelow); break; case B43legacy_LED_WEIRD: diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 879edc786713..e5136fb65ddd 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -583,35 +583,6 @@ static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev) b43legacy_set_slot_time(dev, 20); } -/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 b43legacy_interrupt_enable(struct b43legacy_wldev *dev, - u32 mask) -{ - u32 old_mask; - - old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask | - mask); - - return old_mask; -} - -/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 b43legacy_interrupt_disable(struct b43legacy_wldev *dev, - u32 mask) -{ - u32 old_mask; - - old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask & ~mask); - - return old_mask; -} - /* Synchronize IRQ top- and bottom-half. * IRQs must be masked before calling this. * This must not be called with the irq_lock held. @@ -955,23 +926,54 @@ static void b43legacy_write_template_common(struct b43legacy_wldev *dev, size + sizeof(struct b43legacy_plcp_hdr6)); } +/* Convert a b43legacy antenna number value to the PHY TX control value. */ +static u16 b43legacy_antenna_to_phyctl(int antenna) +{ + switch (antenna) { + case B43legacy_ANTENNA0: + return B43legacy_TX4_PHY_ANT0; + case B43legacy_ANTENNA1: + return B43legacy_TX4_PHY_ANT1; + } + return B43legacy_TX4_PHY_ANTLAST; +} + static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset) { unsigned int i, len, variable_len; const struct ieee80211_mgmt *bcn; const u8 *ie; bool tim_found = 0; + unsigned int rate; + u16 ctl; + int antenna; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); len = min((size_t)dev->wl->current_beacon->len, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); + rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); + /* Write the PHY TX control parameters. */ + antenna = B43legacy_ANTENNA_DEFAULT; + antenna = b43legacy_antenna_to_phyctl(antenna); + ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_BEACPHYCTL); + /* We can't send beacons with short preamble. Would get PHY errors. */ + ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL; + ctl &= ~B43legacy_TX4_PHY_ANT; + ctl &= ~B43legacy_TX4_PHY_ENC; + ctl |= antenna; + ctl |= B43legacy_TX4_PHY_ENC_CCK; + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_BEACPHYCTL, ctl); + /* Find the position of the TIM and the DTIM_period value * and write them to SHM. */ ie = bcn->u.beacon.variable; @@ -1013,7 +1015,8 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, b43legacywarn(dev->wl, "Did not find a valid TIM IE in the " "beacon template packet. AP or IBSS operation " "may be broken.\n"); - } + } else + b43legacydbg(dev->wl, "Updated beacon template\n"); } static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, @@ -1025,7 +1028,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, __le16 dur; plcp.data = 0; - b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate); + b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, size, @@ -1129,10 +1132,103 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); b43legacy_write_template_common(dev, probe_resp_data, size, ram_offset, - shm_size_offset, rate->bitrate); + shm_size_offset, rate->hw_value); kfree(probe_resp_data); } +static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev) +{ + struct b43legacy_wl *wl = dev->wl; + + if (wl->beacon0_uploaded) + return; + b43legacy_write_beacon_template(dev, 0x68, 0x18); + /* FIXME: Probe resp upload doesn't really belong here, + * but we don't use that feature anyway. */ + b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, + &__b43legacy_ratetable[3]); + wl->beacon0_uploaded = 1; +} + +static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev) +{ + struct b43legacy_wl *wl = dev->wl; + + if (wl->beacon1_uploaded) + return; + b43legacy_write_beacon_template(dev, 0x468, 0x1A); + wl->beacon1_uploaded = 1; +} + +static void handle_irq_beacon(struct b43legacy_wldev *dev) +{ + struct b43legacy_wl *wl = dev->wl; + u32 cmd, beacon0_valid, beacon1_valid; + + if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) + return; + + /* This is the bottom half of the asynchronous beacon update. */ + + /* Ignore interrupt in the future. */ + dev->irq_mask &= ~B43legacy_IRQ_BEACON; + + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); + beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID); + + /* Schedule interrupt manually, if busy. */ + if (beacon0_valid && beacon1_valid) { + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON); + dev->irq_mask |= B43legacy_IRQ_BEACON; + return; + } + + if (unlikely(wl->beacon_templates_virgin)) { + /* We never uploaded a beacon before. + * Upload both templates now, but only mark one valid. */ + wl->beacon_templates_virgin = 0; + b43legacy_upload_beacon0(dev); + b43legacy_upload_beacon1(dev); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON0_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + } else { + if (!beacon0_valid) { + b43legacy_upload_beacon0(dev); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON0_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + } else if (!beacon1_valid) { + b43legacy_upload_beacon1(dev); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON1_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + } + } +} + +static void b43legacy_beacon_update_trigger_work(struct work_struct *work) +{ + struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl, + beacon_update_trigger); + struct b43legacy_wldev *dev; + + mutex_lock(&wl->mutex); + dev = wl->current_dev; + if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) { + spin_lock_irq(&wl->irq_lock); + /* Update beacon right away or defer to IRQ. */ + handle_irq_beacon(dev); + /* The handler might have updated the IRQ mask. */ + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, + dev->irq_mask); + mmiowb(); + spin_unlock_irq(&wl->irq_lock); + } + mutex_unlock(&wl->mutex); +} + /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ static void b43legacy_update_templates(struct b43legacy_wl *wl) @@ -1156,54 +1252,24 @@ 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); } static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, u16 beacon_int) { b43legacy_time_lock(dev); - if (dev->dev->id.revision >= 3) - b43legacy_write32(dev, 0x188, (beacon_int << 16)); - else { + if (dev->dev->id.revision >= 3) { + b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP, + (beacon_int << 16)); + b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START, + (beacon_int << 10)); + } else { b43legacy_write16(dev, 0x606, (beacon_int >> 6)); b43legacy_write16(dev, 0x610, beacon_int); } b43legacy_time_unlock(dev); -} - -static void handle_irq_beacon(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - u32 cmd; - - if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) - return; - - /* This is the bottom half of the asynchronous beacon update. */ - - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) { - if (!wl->beacon0_uploaded) { - b43legacy_write_beacon_template(dev, 0x68, - B43legacy_SHM_SH_BTL0, - B43legacy_CCK_RATE_1MB); - b43legacy_write_probe_resp_template(dev, 0x268, - B43legacy_SHM_SH_PRTLEN, - &__b43legacy_ratetable[3]); - wl->beacon0_uploaded = 1; - } - cmd |= B43legacy_MACCMD_BEACON0_VALID; - } - if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) { - if (!wl->beacon1_uploaded) { - b43legacy_write_beacon_template(dev, 0x468, - B43legacy_SHM_SH_BTL1, - B43legacy_CCK_RATE_1MB); - wl->beacon1_uploaded = 1; - } - cmd |= B43legacy_MACCMD_BEACON1_VALID; - } - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int); } static void handle_irq_ucode_debug(struct b43legacy_wldev *dev) @@ -1302,7 +1368,7 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) if (reason & B43legacy_IRQ_TX_OK) handle_irq_transmit_status(dev); - b43legacy_interrupt_enable(dev, dev->irq_savedstate); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); } @@ -1354,18 +1420,18 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id) struct b43legacy_wldev *dev = dev_id; u32 reason; - if (!dev) - return IRQ_NONE; + B43legacy_WARN_ON(!dev); spin_lock(&dev->wl->irq_lock); - if (b43legacy_status(dev) < B43legacy_STAT_STARTED) + if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED)) + /* This can only happen on shared IRQ lines. */ goto out; reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) /* shared IRQ */ goto out; ret = IRQ_HANDLED; - reason &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); + reason &= dev->irq_mask; if (!reason) goto out; @@ -1389,10 +1455,9 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id) & 0x0000DC00; b43legacy_interrupt_ack(dev, reason); - /* disable all IRQs. They are enabled again in the bottom half. */ - dev->irq_savedstate = b43legacy_interrupt_disable(dev, - B43legacy_IRQ_ALL); - /* save the reason code and call our bottom half. */ + /* Disable all IRQs. They are enabled again in the bottom half. */ + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); + /* Save the reason code and call our bottom half. */ dev->irq_reason = reason; tasklet_schedule(&dev->isr_tasklet); out: @@ -1852,7 +1917,8 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev) /* Re-enable IRQs. */ spin_lock_irq(&dev->wl->irq_lock); - b43legacy_interrupt_enable(dev, dev->irq_savedstate); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, + dev->irq_mask); spin_unlock_irq(&dev->wl->irq_lock); } } @@ -1871,10 +1937,9 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev) /* Mask IRQs before suspending MAC. Otherwise * the MAC stays busy and won't suspend. */ spin_lock_irq(&dev->wl->irq_lock); - tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); spin_unlock_irq(&dev->wl->irq_lock); b43legacy_synchronize_irq(dev); - dev->irq_savedstate = tmp; b43legacy_power_saving_ctl_bits(dev, -1, 1); b43legacy_write32(dev, B43legacy_MMIO_MACCTL, @@ -2297,6 +2362,7 @@ static void b43legacy_security_init(struct b43legacy_wldev *dev) dev->max_nr_keys - 8); } +#ifdef CONFIG_B43LEGACY_HWRNG static int b43legacy_rng_read(struct hwrng *rng, u32 *data) { struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv; @@ -2312,17 +2378,21 @@ static int b43legacy_rng_read(struct hwrng *rng, u32 *data) return (sizeof(u16)); } +#endif static void b43legacy_rng_exit(struct b43legacy_wl *wl) { +#ifdef CONFIG_B43LEGACY_HWRNG if (wl->rng_initialized) hwrng_unregister(&wl->rng); +#endif } static int b43legacy_rng_init(struct b43legacy_wl *wl) { - int err; + int err = 0; +#ifdef CONFIG_B43LEGACY_HWRNG snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); wl->rng.name = wl->rng_name; @@ -2336,6 +2406,7 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl) "number generator (%d)\n", err); } +#endif return err; } @@ -2557,7 +2628,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, int antenna_tx; int antenna_rx; int err = 0; - u32 savedirqs; antenna_tx = B43legacy_ANTENNA_DEFAULT; antenna_rx = B43legacy_ANTENNA_DEFAULT; @@ -2597,7 +2667,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); goto out_unlock_mutex; } - savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); spin_unlock_irqrestore(&wl->irq_lock, flags); b43legacy_synchronize_irq(dev); @@ -2619,11 +2689,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Antennas for RX and management frame TX. */ b43legacy_mgmtframe_txantenna(dev, antenna_tx); - /* Update templates for AP mode. */ - if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) - b43legacy_set_beacon_int(dev, conf->beacon_int); - - if (!!conf->radio_enabled != phy->radio_on) { if (conf->radio_enabled) { b43legacy_radio_turn_on(dev); @@ -2641,7 +2706,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, } spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_interrupt_enable(dev, savedirqs); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); mmiowb(); spin_unlock_irqrestore(&wl->irq_lock, flags); out_unlock_mutex: @@ -2704,9 +2769,9 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, struct b43legacy_wldev *dev; struct b43legacy_phy *phy; unsigned long flags; - u32 savedirqs; mutex_lock(&wl->mutex); + B43legacy_WARN_ON(wl->vif != vif); dev = wl->current_dev; phy = &dev->phy; @@ -2719,12 +2784,35 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); goto out_unlock_mutex; } - savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); + + if (changed & BSS_CHANGED_BSSID) { + b43legacy_synchronize_irq(dev); + + if (conf->bssid) + memcpy(wl->bssid, conf->bssid, ETH_ALEN); + else + memset(wl->bssid, 0, ETH_ALEN); + } + + if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { + if (changed & BSS_CHANGED_BEACON && + (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) || + b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43legacy_update_templates(wl); + + if (changed & BSS_CHANGED_BSSID) + b43legacy_write_mac_bssid_templates(dev); + } spin_unlock_irqrestore(&wl->irq_lock, flags); - b43legacy_synchronize_irq(dev); b43legacy_mac_suspend(dev); + if (changed & BSS_CHANGED_BEACON_INT && + (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) || + b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43legacy_set_beacon_int(dev, conf->beacon_int); + if (changed & BSS_CHANGED_BASIC_RATES) b43legacy_update_basic_rates(dev, conf->basic_rates); @@ -2738,14 +2826,12 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, b43legacy_mac_enable(dev); spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_interrupt_enable(dev, savedirqs); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); /* XXX: why? */ mmiowb(); spin_unlock_irqrestore(&wl->irq_lock, flags); out_unlock_mutex: mutex_unlock(&wl->mutex); - - return; } static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, @@ -2787,40 +2873,6 @@ static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); } -static int b43legacy_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - unsigned long flags; - - if (!dev) - return -ENODEV; - mutex_lock(&wl->mutex); - spin_lock_irqsave(&wl->irq_lock, flags); - B43legacy_WARN_ON(wl->vif != vif); - if (conf->bssid) - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - else - memset(wl->bssid, 0, ETH_ALEN); - if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { - if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) { - B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP); - if (conf->changed & IEEE80211_IFCC_BEACON) - b43legacy_update_templates(wl); - } else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) { - if (conf->changed & IEEE80211_IFCC_BEACON) - b43legacy_update_templates(wl); - } - b43legacy_write_mac_bssid_templates(dev); - } - spin_unlock_irqrestore(&wl->irq_lock, flags); - mutex_unlock(&wl->mutex); - - return 0; -} - /* Locking: wl->mutex */ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) { @@ -2834,8 +2886,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) * setting the status to INITIALIZED, as the interrupt handler * won't care about IRQs then. */ spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43legacy_interrupt_disable(dev, - B43legacy_IRQ_ALL); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ spin_unlock_irqrestore(&wl->irq_lock, flags); b43legacy_synchronize_irq(dev); @@ -2875,7 +2926,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev) /* Start data flow (TX/RX) */ b43legacy_mac_enable(dev); - b43legacy_interrupt_enable(dev, dev->irq_savedstate); + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); /* Start maintenance work */ b43legacy_periodic_tasks_setup(dev); @@ -3038,7 +3089,7 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) /* IRQ related flags */ dev->irq_reason = 0; memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); - dev->irq_savedstate = B43legacy_IRQ_MASKTEMPLATE; + dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE; dev->mac_suspended = 1; @@ -3380,11 +3431,6 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) struct b43legacy_wldev *dev = wl->current_dev; int did_init = 0; int err = 0; - bool do_rfkill_exit = 0; - - /* First register RFkill. - * LEDs that are registered later depend on it. */ - b43legacy_rfkill_init(dev); /* Kill all old instance specific information to make sure * the card won't use it in the short timeframe between start @@ -3392,15 +3438,16 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) memset(wl->bssid, 0, ETH_ALEN); memset(wl->mac_addr, 0, ETH_ALEN); wl->filter_flags = 0; + wl->beacon0_uploaded = 0; + wl->beacon1_uploaded = 0; + wl->beacon_templates_virgin = 1; mutex_lock(&wl->mutex); if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { err = b43legacy_wireless_core_init(dev); - if (err) { - do_rfkill_exit = 1; + if (err) goto out_mutex_unlock; - } did_init = 1; } @@ -3409,17 +3456,15 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) if (err) { if (did_init) b43legacy_wireless_core_exit(dev); - do_rfkill_exit = 1; goto out_mutex_unlock; } } + wiphy_rfkill_start_polling(hw->wiphy); + out_mutex_unlock: mutex_unlock(&wl->mutex); - if (do_rfkill_exit) - b43legacy_rfkill_exit(dev); - return err; } @@ -3428,7 +3473,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; - b43legacy_rfkill_exit(dev); + cancel_work_sync(&(wl->beacon_update_trigger)); mutex_lock(&wl->mutex); if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) @@ -3457,13 +3502,13 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .remove_interface = b43legacy_op_remove_interface, .config = b43legacy_op_dev_config, .bss_info_changed = b43legacy_op_bss_info_changed, - .config_interface = b43legacy_op_config_interface, .configure_filter = b43legacy_op_configure_filter, .get_stats = b43legacy_op_get_stats, .get_tx_stats = b43legacy_op_get_tx_stats, .start = b43legacy_op_start, .stop = b43legacy_op_stop, .set_tim = b43legacy_op_beacon_set_tim, + .rfkill_poll = b43legacy_rfkill_poll, }; /* Hard-reset the chip. Do not call this directly. @@ -3760,6 +3805,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) spin_lock_init(&wl->leds_lock); mutex_init(&wl->mutex); INIT_LIST_HEAD(&wl->devlist); + INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); ssb_set_devtypedata(dev, wl); b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index 746d5361bba0..51866c9a2769 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -443,7 +443,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev) pio->queue3 = queue; if (dev->dev->id.revision < 3) - dev->irq_savedstate |= B43legacy_IRQ_PIO_WORKAROUND; + dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND; b43legacydbg(dev->wl, "PIO initialized\n"); err = 0; diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index b32bf6a94f19..8783022db11e 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -22,15 +22,12 @@ */ -#include "rfkill.h" #include "radio.h" #include "b43legacy.h" -#include - /* Returns TRUE, if the radio is enabled in hardware. */ -static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) +bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) { if (dev->phy.rev >= 3) { if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) @@ -45,165 +42,43 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) } /* The poll callback for the hardware button. */ -static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) +void b43legacy_rfkill_poll(struct ieee80211_hw *hw) { - struct b43legacy_wldev *dev = poll_dev->private; - struct b43legacy_wl *wl = dev->wl; + struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); + struct b43legacy_wldev *dev = wl->current_dev; + struct ssb_bus *bus = dev->dev->bus; bool enabled; - bool report_change = 0; + bool brought_up = false; mutex_lock(&wl->mutex); if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { - mutex_unlock(&wl->mutex); - return; + if (ssb_bus_powerup(bus, 0)) { + mutex_unlock(&wl->mutex); + return; + } + ssb_device_enable(dev->dev, 0); + brought_up = true; } + enabled = b43legacy_is_hw_radio_enabled(dev); + if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; - report_change = 1; b43legacyinfo(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); - } - mutex_unlock(&wl->mutex); - - /* send the radio switch event to the system - note both a key press - * and a release are required */ - if (unlikely(report_change)) { - input_report_key(poll_dev->input, KEY_WLAN, 1); - input_report_key(poll_dev->input, KEY_WLAN, 0); - } -} - -/* Called when the RFKILL toggled in software. - * This is called without locking. */ -static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) -{ - struct b43legacy_wldev *dev = data; - struct b43legacy_wl *wl = dev->wl; - int err = -EBUSY; - - if (!wl->rfkill.registered) - return 0; - - mutex_lock(&wl->mutex); - if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) - goto out_unlock; - err = 0; - switch (state) { - case RFKILL_STATE_UNBLOCKED: - if (!dev->radio_hw_enable) { - /* No luck. We can't toggle the hardware RF-kill - * button from software. */ - err = -EBUSY; - goto out_unlock; + wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); + if (enabled != dev->phy.radio_on) { + if (enabled) + b43legacy_radio_turn_on(dev); + else + b43legacy_radio_turn_off(dev, 0); } - if (!dev->phy.radio_on) - b43legacy_radio_turn_on(dev); - break; - case RFKILL_STATE_SOFT_BLOCKED: - if (dev->phy.radio_on) - b43legacy_radio_turn_off(dev, 0); - break; - default: - b43legacywarn(wl, "Received unexpected rfkill state %d.\n", - state); - break; } -out_unlock: + if (brought_up) { + ssb_device_disable(dev->dev, 0); + ssb_bus_may_powerdown(bus); + } + mutex_unlock(&wl->mutex); - - return err; } - -char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) -{ - struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); - - if (!rfk->registered) - return NULL; - return rfkill_get_led_name(rfk->rfkill); -} - -void b43legacy_rfkill_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - struct b43legacy_rfkill *rfk = &(wl->rfkill); - int err; - - rfk->registered = 0; - - rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); - if (!rfk->rfkill) - goto out_error; - snprintf(rfk->name, sizeof(rfk->name), - "b43legacy-%s", wiphy_name(wl->hw->wiphy)); - rfk->rfkill->name = rfk->name; - rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; - rfk->rfkill->data = dev; - rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; - rfk->rfkill->user_claim_unsupported = 1; - - rfk->poll_dev = input_allocate_polled_device(); - if (!rfk->poll_dev) { - rfkill_free(rfk->rfkill); - goto err_freed_rfk; - } - - rfk->poll_dev->private = dev; - rfk->poll_dev->poll = b43legacy_rfkill_poll; - rfk->poll_dev->poll_interval = 1000; /* msecs */ - - rfk->poll_dev->input->name = rfk->name; - rfk->poll_dev->input->id.bustype = BUS_HOST; - rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor; - rfk->poll_dev->input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WLAN, rfk->poll_dev->input->keybit); - - err = rfkill_register(rfk->rfkill); - if (err) - goto err_free_polldev; - -#ifdef CONFIG_RFKILL_INPUT_MODULE - /* B43legacy RF-kill isn't useful without the rfkill-input subsystem. - * Try to load the module. */ - err = request_module("rfkill-input"); - if (err) - b43legacywarn(wl, "Failed to load the rfkill-input module." - "The built-in radio LED will not work.\n"); -#endif /* CONFIG_RFKILL_INPUT */ - - err = input_register_polled_device(rfk->poll_dev); - if (err) - goto err_unreg_rfk; - - rfk->registered = 1; - - return; -err_unreg_rfk: - rfkill_unregister(rfk->rfkill); -err_free_polldev: - input_free_polled_device(rfk->poll_dev); - rfk->poll_dev = NULL; -err_freed_rfk: - rfk->rfkill = NULL; -out_error: - rfk->registered = 0; - b43legacywarn(wl, "RF-kill button init failed\n"); -} - -void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) -{ - struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); - - if (!rfk->registered) - return; - rfk->registered = 0; - - input_unregister_polled_device(rfk->poll_dev); - rfkill_unregister(rfk->rfkill); - input_free_polled_device(rfk->poll_dev); - rfk->poll_dev = NULL; - rfk->rfkill = NULL; -} - diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h index 11150a8032f0..75585571c544 100644 --- a/drivers/net/wireless/b43legacy/rfkill.h +++ b/drivers/net/wireless/b43legacy/rfkill.h @@ -1,59 +1,11 @@ #ifndef B43legacy_RFKILL_H_ #define B43legacy_RFKILL_H_ +struct ieee80211_hw; struct b43legacy_wldev; -#ifdef CONFIG_B43LEGACY_RFKILL +void b43legacy_rfkill_poll(struct ieee80211_hw *hw); -#include -#include -#include - - - -struct b43legacy_rfkill { - /* The RFKILL subsystem data structure */ - struct rfkill *rfkill; - /* The poll device for the RFKILL input button */ - struct input_polled_dev *poll_dev; - /* Did initialization succeed? Used for freeing. */ - bool registered; - /* The unique name of this rfkill switch */ - char name[sizeof("b43legacy-phy4294967295")]; -}; - -/* The init function returns void, because we are not interested - * in failing the b43 init process when rfkill init failed. */ -void b43legacy_rfkill_init(struct b43legacy_wldev *dev); -void b43legacy_rfkill_exit(struct b43legacy_wldev *dev); - -char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev); - - -#else /* CONFIG_B43LEGACY_RFKILL */ -/* No RFKILL support. */ - -struct b43legacy_rfkill { - /* empty */ -}; - -static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev) -{ -} -static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev) -{ -} -static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev) -{ -} -static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) -{ -} -static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) -{ - return NULL; -} - -#endif /* CONFIG_B43LEGACY_RFKILL */ +bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev); #endif /* B43legacy_RFKILL_H_ */ diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 12fca99f7578..b8e39dd06e99 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -274,7 +274,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, /* PHY TX Control word */ if (rate_ofdm) - phy_ctl |= B43legacy_TX4_PHY_OFDM; + phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM; if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; switch (info->antenna_sel_tx) { diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index 62e09d02788f..91633087a20b 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h @@ -67,7 +67,9 @@ struct b43legacy_txhdr_fw3 { #define B43legacy_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */ /* PHY TX control word */ -#define B43legacy_TX4_PHY_OFDM 0x0001 /* Data frame rate type */ +#define B43legacy_TX4_PHY_ENC 0x0003 /* Data frame encoding */ +#define B43legacy_TX4_PHY_ENC_CCK 0x0000 /* CCK */ +#define B43legacy_TX4_PHY_ENC_OFDM 0x0001 /* Data frame rate type */ #define B43legacy_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ #define B43legacy_TX4_PHY_ANT 0x03C0 /* Antenna selection */ #define B43legacy_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */ diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index 6693423f63fe..d313b005114e 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -377,7 +377,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct hostap_interface *iface; local_info_t *local; - int ret = 1; + int ret = NETDEV_TX_BUSY; u16 fc; struct hostap_tx_data tx; ap_tx_ret tx_ret; diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 3dad1cf8f241..ff9b5c882184 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -1423,7 +1423,7 @@ static int prism2_hw_init2(struct net_device *dev, int initial) prism2_check_sta_fw_version(local); if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR, - &dev->dev_addr, 6, 1) < 0) { + dev->dev_addr, 6, 1) < 0) { printk("%s: could not get own MAC address\n", dev->name); } diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index cbf15d703201..0e5d51086a44 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -435,7 +435,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, unsigned long pccard_attr_mem; unsigned int pccard_attr_len; void __iomem *attr_mem = NULL; - unsigned int cor_offset, cor_index; + unsigned int cor_offset = 0, cor_index = 0; u32 reg; local_info_t *local = NULL; struct net_device *dev = NULL; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 97e5647ff050..742432388ca3 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -3488,7 +3488,7 @@ static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL); static ssize_t show_cfg(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw2100_priv *p = d->driver_data; + struct ipw2100_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->config); } @@ -3497,7 +3497,7 @@ static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw2100_priv *p = d->driver_data; + struct ipw2100_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->status); } @@ -3506,7 +3506,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static ssize_t show_capability(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw2100_priv *p = d->driver_data; + struct ipw2100_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->capability); } @@ -4224,7 +4224,7 @@ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, 1 - SW based RF kill active (sysfs) 2 - HW based RF kill active 3 - Both HW and SW baed RF kill active */ - struct ipw2100_priv *priv = (struct ipw2100_priv *)d->driver_data; + struct ipw2100_priv *priv = dev_get_drvdata(d); int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | (rf_kill_active(priv) ? 0x2 : 0x0); return sprintf(buf, "%i\n", val); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index bd4dbcfe1bbe..44c29b3f6728 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -1527,7 +1527,7 @@ static DEVICE_ATTR(led, S_IWUSR | S_IRUGO, show_led, store_led); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->status); } @@ -1536,7 +1536,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static ssize_t show_cfg(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->config); } @@ -1545,7 +1545,7 @@ static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); static ssize_t show_nic_type(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); return sprintf(buf, "TYPE: %d\n", priv->nic_type); } @@ -1555,7 +1555,7 @@ static ssize_t show_ucode_version(struct device *d, struct device_attribute *attr, char *buf) { u32 len = sizeof(u32), tmp = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); if (ipw_get_ordinal(p, IPW_ORD_STAT_UCODE_VERSION, &tmp, &len)) return 0; @@ -1569,7 +1569,7 @@ static ssize_t show_rtc(struct device *d, struct device_attribute *attr, char *buf) { u32 len = sizeof(u32), tmp = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); if (ipw_get_ordinal(p, IPW_ORD_STAT_RTC, &tmp, &len)) return 0; @@ -1586,14 +1586,15 @@ static DEVICE_ATTR(rtc, S_IWUSR | S_IRUGO, show_rtc, NULL); static ssize_t show_eeprom_delay(struct device *d, struct device_attribute *attr, char *buf) { - int n = ((struct ipw_priv *)d->driver_data)->eeprom_delay; + struct ipw_priv *p = dev_get_drvdata(d); + int n = p->eeprom_delay; return sprintf(buf, "%i\n", n); } static ssize_t store_eeprom_delay(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); sscanf(buf, "%i", &p->eeprom_delay); return strnlen(buf, count); } @@ -1605,7 +1606,7 @@ static ssize_t show_command_event_reg(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT); return sprintf(buf, "0x%08x\n", reg); @@ -1615,7 +1616,7 @@ static ssize_t store_command_event_reg(struct device *d, const char *buf, size_t count) { u32 reg; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); sscanf(buf, "%x", ®); ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg); @@ -1629,7 +1630,7 @@ static ssize_t show_mem_gpio_reg(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); reg = ipw_read_reg32(p, 0x301100); return sprintf(buf, "0x%08x\n", reg); @@ -1639,7 +1640,7 @@ static ssize_t store_mem_gpio_reg(struct device *d, const char *buf, size_t count) { u32 reg; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); sscanf(buf, "%x", ®); ipw_write_reg32(p, 0x301100, reg); @@ -1653,7 +1654,7 @@ static ssize_t show_indirect_dword(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (priv->status & STATUS_INDIRECT_DWORD) reg = ipw_read_reg32(priv, priv->indirect_dword); @@ -1666,7 +1667,7 @@ static ssize_t store_indirect_dword(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); sscanf(buf, "%x", &priv->indirect_dword); priv->status |= STATUS_INDIRECT_DWORD; @@ -1680,7 +1681,7 @@ static ssize_t show_indirect_byte(struct device *d, struct device_attribute *attr, char *buf) { u8 reg = 0; - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (priv->status & STATUS_INDIRECT_BYTE) reg = ipw_read_reg8(priv, priv->indirect_byte); @@ -1693,7 +1694,7 @@ static ssize_t store_indirect_byte(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); sscanf(buf, "%x", &priv->indirect_byte); priv->status |= STATUS_INDIRECT_BYTE; @@ -1707,7 +1708,7 @@ static ssize_t show_direct_dword(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (priv->status & STATUS_DIRECT_DWORD) reg = ipw_read32(priv, priv->direct_dword); @@ -1720,7 +1721,7 @@ static ssize_t store_direct_dword(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); sscanf(buf, "%x", &priv->direct_dword); priv->status |= STATUS_DIRECT_DWORD; @@ -1747,7 +1748,7 @@ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, 1 - SW based RF kill active (sysfs) 2 - HW based RF kill active 3 - Both HW and SW baed RF kill active */ - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | (rf_kill_active(priv) ? 0x2 : 0x0); return sprintf(buf, "%i\n", val); @@ -1791,7 +1792,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); ipw_radio_kill_sw(priv, buf[0] == '1'); @@ -1803,7 +1804,7 @@ static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); int pos = 0, len = 0; if (priv->config & CFG_SPEED_SCAN) { while (priv->speed_scan[pos] != 0) @@ -1818,7 +1819,7 @@ static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); int channel, pos = 0; const char *p = buf; @@ -1857,14 +1858,14 @@ static DEVICE_ATTR(speed_scan, S_IWUSR | S_IRUGO, show_speed_scan, static ssize_t show_net_stats(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0'); } static ssize_t store_net_stats(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (buf[0] == '1') priv->config |= CFG_NET_STATS; else @@ -3176,11 +3177,8 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) /* Start the Dma */ rc = ipw_fw_dma_enable(priv); - if (priv->sram_desc.last_cb_index > 0) { - /* the DMA is already ready this would be a bug. */ - BUG(); - goto out; - } + /* the DMA is already ready this would be a bug. */ + BUG_ON(priv->sram_desc.last_cb_index > 0); do { chunk = (struct fw_chunk *)(data + offset); @@ -11526,7 +11524,8 @@ static int ipw_prom_stop(struct net_device *dev) static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { IPW_DEBUG_INFO("prom dev->xmit\n"); - return -EOPNOTSUPP; + dev_kfree_skb(skb); + return NETDEV_TX_OK; } static const struct net_device_ops ipw_prom_netdev_ops = { diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 92a26922e792..8ce6e961c5da 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -154,10 +154,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv) goto failed; } ieee = netdev_priv(dev); -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev->hard_start_xmit = ieee80211_xmit; - dev->change_mtu = ieee80211_change_mtu; -#endif ieee->dev = dev; diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c index 65a8195b3d90..da2ad5437ce5 100644 --- a/drivers/net/wireless/ipw2x00/libipw_tx.c +++ b/drivers/net/wireless/ipw2x00/libipw_tx.c @@ -539,7 +539,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); dev->stats.tx_errors++; - return 1; + return NETDEV_TX_BUSY; } EXPORT_SYMBOL(ieee80211_xmit); diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 736162324ba4..e092af09d6bf 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -5,16 +5,11 @@ config IWLWIFI select FW_LOADER select MAC80211_LEDS if IWLWIFI_LEDS select LEDS_CLASS if IWLWIFI_LEDS - select RFKILL if IWLWIFI_RFKILL config IWLWIFI_LEDS bool "Enable LED support in iwlagn and iwl3945 drivers" depends on IWLWIFI -config IWLWIFI_RFKILL - bool "Enable RF kill support in iwlagn and iwl3945 drivers" - depends on IWLWIFI - config IWLWIFI_SPECTRUM_MEASUREMENT bool "Enable Spectrum Measurement in iwlagn driver" depends on IWLWIFI diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index d79d97ad61a5..1d4e0a226fd4 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -4,7 +4,6 @@ iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o iwlcore-objs += iwl-scan.o iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o -iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o obj-$(CONFIG_IWLAGN) += iwlagn.o diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index ac22f59be9ef..225e5f889346 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -44,6 +44,15 @@ #include "iwl-core.h" #include "iwl-dev.h" +#ifdef CONFIG_IWLWIFI_DEBUG +static const char *led_type_str[] = { + __stringify(IWL_LED_TRG_TX), + __stringify(IWL_LED_TRG_RX), + __stringify(IWL_LED_TRG_ASSOC), + __stringify(IWL_LED_TRG_RADIO), + NULL +}; +#endif /* CONFIG_IWLWIFI_DEBUG */ static const struct { u16 brightness; @@ -61,7 +70,7 @@ static const struct { {10, 110, 110}, {5, 130, 130}, {0, 167, 167}, - /*SOLID_ON*/ + /* SOLID_ON */ {-1, IWL_LED_SOLID, 0} }; @@ -142,6 +151,26 @@ static int iwl3945_led_off(struct iwl_priv *priv, int led_id) return iwl_send_led_cmd(priv, &led_cmd); } +/* + * Set led on in case of association + * */ +static int iwl3945_led_associate(struct iwl_priv *priv, int led_id) +{ + IWL_DEBUG_LED(priv, "Associated\n"); + + priv->allow_blinking = 1; + return iwl3945_led_on(priv, led_id); +} +/* Set Led off in case of disassociation */ +static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id) +{ + IWL_DEBUG_LED(priv, "Disassociated\n"); + + priv->allow_blinking = 0; + + return 0; +} + /* * brightness call back function for Tx/Rx LED */ @@ -165,26 +194,21 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct iwl_led *led = container_of(led_cdev, - struct iwl_led, led_dev); + struct iwl_led, led_dev); struct iwl_priv *priv = led->priv; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", + led_type_str[led->type], brightness); + switch (brightness) { case LED_FULL: - if (led->type == IWL_LED_TRG_ASSOC) { - priv->allow_blinking = 1; - IWL_DEBUG_LED(priv, "MAC is associated\n"); - } if (led->led_on) led->led_on(priv, IWL_LED_LINK); break; case LED_OFF: - if (led->type == IWL_LED_TRG_ASSOC) { - priv->allow_blinking = 0; - IWL_DEBUG_LED(priv, "MAC is disassociated\n"); - } if (led->led_off) led->led_off(priv, IWL_LED_LINK); break; @@ -197,8 +221,6 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, } } - - /* * Register led class with the system */ @@ -237,12 +259,12 @@ static int iwl3945_led_register_led(struct iwl_priv *priv, static inline u8 get_blink_rate(struct iwl_priv *priv) { int index; - u64 current_tpt = priv->rxtxpackets; - s64 tpt = current_tpt - priv->led_tpt; + s64 tpt = priv->rxtxpackets; if (tpt < 0) tpt = -tpt; - priv->led_tpt = current_tpt; + + IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt); if (!priv->allow_blinking) index = IWL_MAX_BLINK_TBL; @@ -250,13 +272,9 @@ static inline u8 get_blink_rate(struct iwl_priv *priv) for (index = 0; index < IWL_MAX_BLINK_TBL; index++) if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) break; - return index; -} -static inline int is_rf_kill(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); + IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index); + return index; } /* @@ -272,7 +290,7 @@ void iwl3945_led_background(struct iwl_priv *priv) priv->last_blink_time = 0; return; } - if (is_rf_kill(priv)) { + if (iwl_is_rfkill(priv)) { priv->last_blink_time = 0; return; } @@ -341,8 +359,8 @@ int iwl3945_led_register(struct iwl_priv *priv) IWL_LED_TRG_ASSOC, 0, trigger); /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate; priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index af6b9d444778..5eb538d18a80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -38,6 +38,7 @@ #include "iwl-commands.h" #include "iwl-3945.h" +#include "iwl-sta.h" #define RS_NAME "iwl-3945-rs" @@ -683,11 +684,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if (sta) rate_mask = sta->supp_rates[sband->band]; - /* Send management frames and broadcast/multicast data using lowest - * rate. */ + /* 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 || - is_multicast_ether_addr(hdr->addr1) || + 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) @@ -696,6 +696,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, 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; return; } @@ -713,13 +715,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !rs_sta->ibss_sta_added) { - u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); + u8 sta_id = iwl_find_station(priv, hdr->addr1); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n", hdr->addr1); - sta_id = iwl3945_add_station(priv, - hdr->addr1, 0, CMD_ASYNC); + sta_id = iwl_add_station(priv, hdr->addr1, false, + CMD_ASYNC, NULL); } if (sta_id != IWL_INVALID_STATION) rs_sta->ibss_sta_added = 1; @@ -974,7 +976,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rcu_read_lock(); - sta = ieee80211_find_sta(hw, priv->stations_39[sta_id].sta.sta.addr); + sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); if (!sta) { rcu_read_unlock(); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 527525cc0919..46288e724889 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -98,7 +98,6 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = { * ... and set IWL_EVT_DISABLE to 1. */ void iwl3945_disable_events(struct iwl_priv *priv) { - int ret; int i; u32 base; /* SRAM address of event log header */ u32 disable_ptr; /* SRAM address of event-disable bitmap array */ @@ -159,26 +158,17 @@ void iwl3945_disable_events(struct iwl_priv *priv) return; } - ret = iwl_grab_nic_access(priv); - if (ret) { - IWL_WARN(priv, "Can not read from adapter at this time.\n"); - return; - } - disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32))); array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32))); - iwl_release_nic_access(priv); if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) { IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n", disable_ptr); - ret = iwl_grab_nic_access(priv); for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++) iwl_write_targ_mem(priv, disable_ptr + (i * sizeof(u32)), evt_disable[i]); - iwl_release_nic_access(priv); } else { IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n"); IWL_DEBUG_INFO(priv, " by writing \"1\"s into disable bitmap\n"); @@ -779,35 +769,6 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) return ; } -u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr) -{ - int i, start = IWL_AP_ID; - int ret = IWL_INVALID_STATION; - unsigned long flags; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || - (priv->iw_mode == NL80211_IFTYPE_AP)) - start = IWL_STA_ID; - - if (is_broadcast_ether_addr(addr)) - return priv->hw_params.bcast_sta_id; - - spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_params.max_stations; i++) - if ((priv->stations_39[i].used) && - (!compare_ether_addr - (priv->stations_39[i].sta.sta.addr, addr))) { - ret = i; - goto out; - } - - IWL_DEBUG_INFO(priv, "can not find STA %pM (total %d)\n", - addr, priv->num_stations); - out: - spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; -} - /** * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD: * @@ -885,13 +846,13 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) { unsigned long flags_spin; - struct iwl3945_station_entry *station; + struct iwl_station_entry *station; if (sta_id == IWL_INVALID_STATION) return IWL_INVALID_STATION; spin_lock_irqsave(&priv->sta_lock, flags_spin); - station = &priv->stations_39[sta_id]; + station = &priv->stations[sta_id]; station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; station->sta.rate_n_flags = cpu_to_le16(tx_rate); @@ -899,8 +860,7 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - iwl_send_add_sta(priv, - (struct iwl_addsta_cmd *)&station->sta, flags); + iwl_send_add_sta(priv, &station->sta, flags); IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", sta_id, tx_rate); return sta_id; @@ -908,55 +868,30 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) { - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - if (src == IWL_PWR_SRC_VAUX) { if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) { iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); - iwl_release_nic_access(priv); iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VAUX_PWR_SRC, CSR_GPIO_IN_BIT_AUX_POWER, 5000); - } else { - iwl_release_nic_access(priv); } } else { iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); - iwl_release_nic_access(priv); iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ } - spin_unlock_irqrestore(&priv->lock, flags); - return ret; + return 0; } static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { - int rc; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); @@ -973,23 +908,11 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) /* fake read to flush all prev I/O */ iwl_read_direct32(priv, FH39_RSSR_CTRL); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return 0; } static int iwl3945_tx_reset(struct iwl_priv *priv) { - int rc; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } /* bypass mode */ iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2); @@ -1017,8 +940,6 @@ static int iwl3945_tx_reset(struct iwl_priv *priv) FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -1061,7 +982,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) static int iwl3945_apm_init(struct iwl_priv *priv) { - int ret = 0; + int ret; iwl_power_initialize(priv); @@ -1083,10 +1004,6 @@ static int iwl3945_apm_init(struct iwl_priv *priv) goto out; } - ret = iwl_grab_nic_access(priv); - if (ret) - goto out; - /* enable DMA */ iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); @@ -1097,7 +1014,6 @@ static int iwl3945_apm_init(struct iwl_priv *priv) iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl_release_nic_access(priv); out: return ret; } @@ -1110,6 +1026,11 @@ static void iwl3945_nic_config(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); + /* Determine HW type */ + pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); + + IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); + if (rev_id & PCI_CFG_REV_ID_BIT_RTP) IWL_DEBUG_INFO(priv, "RTP type \n"); else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { @@ -1163,7 +1084,6 @@ static void iwl3945_nic_config(struct iwl_priv *priv) int iwl3945_hw_nic_init(struct iwl_priv *priv) { - u8 rev_id; int rc; unsigned long flags; struct iwl_rx_queue *rxq = &priv->rxq; @@ -1172,12 +1092,6 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) priv->cfg->ops->lib->apm_ops.init(priv); spin_unlock_irqrestore(&priv->lock, flags); - /* Determine HW type */ - rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); - if (rc) - return rc; - IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); - rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); if (rc) return rc; @@ -1198,22 +1112,13 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) iwl3945_rx_init(priv, rxq); - spin_lock_irqsave(&priv->lock, flags); /* Look at using this instead: rxq->need_update = 1; iwl_rx_queue_update_write_ptr(priv, rxq); */ - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); - iwl_release_nic_access(priv); - - spin_unlock_irqrestore(&priv->lock, flags); rc = iwl3945_txq_ctx_reset(priv); if (rc) @@ -1245,14 +1150,6 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) { int txq_id; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - if (iwl_grab_nic_access(priv)) { - spin_unlock_irqrestore(&priv->lock, flags); - iwl3945_hw_txq_ctx_free(priv); - return; - } /* stop SCD */ iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); @@ -1265,9 +1162,6 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) 1000); } - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - iwl3945_hw_txq_ctx_free(priv); } @@ -1312,12 +1206,8 @@ static void iwl3945_apm_stop(struct iwl_priv *priv) static int iwl3945_apm_reset(struct iwl_priv *priv) { - int rc; - unsigned long flags; - iwl3945_apm_stop_master(priv); - spin_lock_irqsave(&priv->lock, flags); iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -1327,36 +1217,31 @@ static int iwl3945_apm_reset(struct iwl_priv *priv) iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - rc = iwl_grab_nic_access(priv); - if (!rc) { - iwl_write_prph(priv, APMG_CLK_CTRL_REG, - APMG_CLK_VAL_BSM_CLK_RQT); + iwl_write_prph(priv, APMG_CLK_CTRL_REG, + APMG_CLK_VAL_BSM_CLK_RQT); - iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); - iwl_write_prph(priv, APMG_RTC_INT_STT_REG, + iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); + iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); - /* enable DMA */ - iwl_write_prph(priv, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); - udelay(10); + /* enable DMA */ + iwl_write_prph(priv, APMG_CLK_EN_REG, + APMG_CLK_VAL_DMA_CLK_RQT | + APMG_CLK_VAL_BSM_CLK_RQT); + udelay(10); - iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); - udelay(5); - iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, + udelay(5); + iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); - iwl_release_nic_access(priv); - } /* Clear the 'host command active' bit... */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - spin_unlock_irqrestore(&priv->lock, flags); - return rc; + return 0; } /** @@ -1964,6 +1849,193 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) return 0; } +static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) +{ + int rc = 0; + struct iwl_rx_packet *res = NULL; + struct iwl3945_rxon_assoc_cmd rxon_assoc; + struct iwl_host_cmd cmd = { + .id = REPLY_RXON_ASSOC, + .len = sizeof(rxon_assoc), + .meta.flags = CMD_WANT_SKB, + .data = &rxon_assoc, + }; + const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; + const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; + + if ((rxon1->flags == rxon2->flags) && + (rxon1->filter_flags == rxon2->filter_flags) && + (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && + (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); + return 0; + } + + rxon_assoc.flags = priv->staging_rxon.flags; + rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.reserved = 0; + + rc = iwl_send_cmd_sync(priv, &cmd); + if (rc) + return rc; + + res = (struct iwl_rx_packet *)cmd.meta.u.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); + + return rc; +} + +/** + * iwl3945_commit_rxon - commit staging_rxon to hardware + * + * The RXON command in staging_rxon is committed to the hardware and + * the active_rxon structure is updated with the new data. This + * function correctly transitions out of the RXON_ASSOC_MSK state if + * a HW tune is required based on the RXON structure changes. + */ +static int iwl3945_commit_rxon(struct iwl_priv *priv) +{ + /* cast away the const for active_rxon in this function */ + struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; + struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; + int rc = 0; + bool new_assoc = + !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); + + if (!iwl_is_alive(priv)) + return -1; + + /* always get timestamp with Rx frame */ + staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; + + /* select antenna */ + staging_rxon->flags &= + ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); + staging_rxon->flags |= iwl3945_get_antenna_flags(priv); + + rc = iwl_check_rxon_cmd(priv); + if (rc) { + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); + return -EINVAL; + } + + /* If we don't need to send a full RXON, we can use + * iwl3945_rxon_assoc_cmd which is used to reconfigure filter + * and other flags for the current radio configuration. */ + if (!iwl_full_rxon_required(priv)) { + rc = iwl_send_rxon_assoc(priv); + if (rc) { + IWL_ERR(priv, "Error setting RXON_ASSOC " + "configuration (%d).\n", rc); + return rc; + } + + memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); + + return 0; + } + + /* If we are currently associated and the new config requires + * an RXON_ASSOC and the new config wants the associated mask enabled, + * we must clear the associated from the active configuration + * before we apply the new config */ + if (iwl_is_associated(priv) && new_assoc) { + IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); + active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + + /* + * reserved4 and 5 could have been filled by the iwlcore code. + * Let's clear them before pushing to the 3945. + */ + active_rxon->reserved4 = 0; + active_rxon->reserved5 = 0; + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, + sizeof(struct iwl3945_rxon_cmd), + &priv->active_rxon); + + /* If the mask clearing failed then we set + * active_rxon back to what it was previously */ + if (rc) { + active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; + IWL_ERR(priv, "Error clearing ASSOC_MSK on current " + "configuration (%d).\n", rc); + return rc; + } + } + + IWL_DEBUG_INFO(priv, "Sending RXON\n" + "* with%s RXON_FILTER_ASSOC_MSK\n" + "* channel = %d\n" + "* bssid = %pM\n", + (new_assoc ? "" : "out"), + le16_to_cpu(staging_rxon->channel), + staging_rxon->bssid_addr); + + /* + * reserved4 and 5 could have been filled by the iwlcore code. + * Let's clear them before pushing to the 3945. + */ + staging_rxon->reserved4 = 0; + staging_rxon->reserved5 = 0; + + iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); + + /* Apply the new configuration */ + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, + sizeof(struct iwl3945_rxon_cmd), + staging_rxon); + if (rc) { + IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); + return rc; + } + + memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); + + iwl_clear_stations_table(priv); + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ + rc = priv->cfg->ops->lib->send_tx_power(priv); + if (rc) { + IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); + return rc; + } + + /* Add the broadcast address so we can send broadcast frames */ + if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) == + IWL_INVALID_STATION) { + IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); + return -EIO; + } + + /* If we have set the ASSOC_MSK and we are in BSS mode then + * add the IWL_AP_ID to the station rate table */ + if (iwl_is_associated(priv) && + (priv->iw_mode == NL80211_IFTYPE_STATION)) + if (iwl_add_station(priv, priv->active_rxon.bssid_addr, + true, CMD_SYNC, NULL) == IWL_INVALID_STATION) { + IWL_ERR(priv, "Error adding AP address for transmit\n"); + return -EIO; + } + + /* Init the hardware's rate fallback order based on the band */ + rc = iwl3945_init_hw_rate_table(priv); + if (rc) { + IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); + return -EIO; + } + + return 0; +} + /* will add 3945 channel switch cmd handling later */ int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) { @@ -2314,14 +2386,6 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) int iwl3945_hw_rxq_stop(struct iwl_priv *priv) { int rc; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS, @@ -2329,28 +2393,17 @@ int iwl3945_hw_rxq_stop(struct iwl_priv *priv) if (rc < 0) IWL_ERR(priv, "Can't stop Rx DMA.\n"); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return 0; } int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - int rc; - unsigned long flags; int txq_id = txq->q.id; struct iwl3945_shared *shared_data = priv->shared_virt; shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); @@ -2360,11 +2413,9 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); - iwl_release_nic_access(priv); /* fake read to flush all prev. writes */ iwl_read32(priv, FH39_TSSR_CBB_BASE); - spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -2384,13 +2435,25 @@ static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len) } } + static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) { - u16 size = (u16)sizeof(struct iwl3945_addsta_cmd); - memcpy(data, cmd, size); - return size; + struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data; + addsta->mode = cmd->mode; + memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify)); + memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo)); + addsta->station_flags = cmd->station_flags; + addsta->station_flags_msk = cmd->station_flags_msk; + addsta->tid_disable_tx = cpu_to_le16(0); + addsta->rate_n_flags = cmd->rate_n_flags; + addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; + addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; + addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; + + return (u16)sizeof(struct iwl3945_addsta_cmd); } + /** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table */ @@ -2672,10 +2735,6 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) inst_len = priv->ucode_init.len; data_len = priv->ucode_init_data.len; - rc = iwl_grab_nic_access(priv); - if (rc) - return rc; - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); @@ -2689,10 +2748,8 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) le32_to_cpu(*image)); rc = iwl3945_verify_bsm(priv); - if (rc) { - iwl_release_nic_access(priv); + if (rc) return rc; - } /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); @@ -2724,11 +2781,14 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); - iwl_release_nic_access(priv); - return 0; } +static struct iwl_hcmd_ops iwl3945_hcmd = { + .rxon_assoc = iwl3945_send_rxon_assoc, + .commit_rxon = iwl3945_commit_rxon, +}; + 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, @@ -2758,6 +2818,9 @@ static struct iwl_lib_ops iwl3945_lib = { }, .send_tx_power = iwl3945_send_tx_power, .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, + .post_associate = iwl3945_post_associate, + .isr = iwl_isr_legacy, + .config_ap = iwl3945_config_ap, }; static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { @@ -2767,6 +2830,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { static struct iwl_ops iwl3945_ops = { .lib = &iwl3945_lib, + .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, }; @@ -2779,7 +2843,8 @@ static struct iwl_cfg iwl3945_bg_cfg = { .eeprom_size = IWL3945_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .ops = &iwl3945_ops, - .mod_params = &iwl3945_mod_params + .mod_params = &iwl3945_mod_params, + .use_isr_legacy = true }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2791,7 +2856,8 @@ static struct iwl_cfg iwl3945_abg_cfg = { .eeprom_size = IWL3945_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .ops = &iwl3945_ops, - .mod_params = &iwl3945_mod_params + .mod_params = &iwl3945_mod_params, + .use_isr_legacy = true }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 55188844657b..fbb3a573463e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -36,10 +36,6 @@ #include #include -/*used for rfkill*/ -#include -#include - /* Hardware specific file defines the PCI IDs table for that hardware module */ extern struct pci_device_id iwl3945_hw_card_ids[]; @@ -155,14 +151,12 @@ struct iwl3945_frame { #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ #define STATUS_INT_ENABLED 2 #define STATUS_RF_KILL_HW 3 -#define STATUS_RF_KILL_SW 4 #define STATUS_INIT 5 #define STATUS_ALIVE 6 #define STATUS_READY 7 #define STATUS_TEMPERATURE 8 #define STATUS_GEO_CONFIGURED 9 #define STATUS_EXIT_PENDING 10 -#define STATUS_IN_SUSPEND 11 #define STATUS_STATISTICS 12 #define STATUS_SCANNING 13 #define STATUS_SCAN_ABORTING 14 @@ -203,11 +197,6 @@ struct iwl3945_ibss_seq { * for use by iwl-*.c * *****************************************************************************/ -struct iwl3945_addsta_cmd; -extern int iwl3945_send_add_station(struct iwl_priv *priv, - struct iwl3945_addsta_cmd *sta, u8 flags); -extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid, - int is_ap, u8 flags); extern int iwl3945_power_init_handle(struct iwl_priv *priv); extern int iwl3945_eeprom_init(struct iwl_priv *priv); extern int iwl3945_calc_db_from_ratio(int sig_ratio); @@ -278,6 +267,8 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); +extern void iwl3945_post_associate(struct iwl_priv *priv); +extern void iwl3945_config_ap(struct iwl_priv *priv); /** * iwl3945_hw_find_station - Find station id for a given BSSID diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 847a6220c5e6..8f3d4bc6a03f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -163,10 +163,6 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) inst_len = priv->ucode_init.len; data_len = priv->ucode_init_data.len; - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); @@ -179,10 +175,8 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); ret = iwl4965_verify_bsm(priv); - if (ret) { - iwl_release_nic_access(priv); + if (ret) return ret; - } /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); @@ -211,7 +205,6 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) * (e.g. when powering back up after power-save shutdown) */ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); - iwl_release_nic_access(priv); return 0; } @@ -229,20 +222,12 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) { dma_addr_t pinst; dma_addr_t pdata; - unsigned long flags; int ret = 0; /* bits 35:4 for 4965 */ pinst = priv->ucode_code.p_addr >> 4; pdata = priv->ucode_data_backup.p_addr >> 4; - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - /* Tell bootstrap uCode where to find image to load */ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); @@ -253,10 +238,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) * that all new ptr/size info is in place */ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, priv->ucode_code.len | BSM_DRAM_INST_LOAD); - iwl_release_nic_access(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); return ret; @@ -312,10 +293,12 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) queue_work(priv->workqueue, &priv->restart); } -static int is_fat_channel(__le32 rxon_flags) +static bool is_fat_channel(__le32 rxon_flags) { - return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) || - (rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK); + int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK) + >> RXON_FLG_CHANNEL_MODE_POS; + return ((chan_mod == CHANNEL_MODE_PURE_40) || + (chan_mod == CHANNEL_MODE_MIXED)); } /* @@ -358,10 +341,6 @@ static int iwl4965_apm_init(struct iwl_priv *priv) goto out; } - ret = iwl_grab_nic_access(priv); - if (ret) - goto out; - /* enable DMA */ iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); @@ -372,7 +351,6 @@ static int iwl4965_apm_init(struct iwl_priv *priv) iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl_release_nic_access(priv); out: return ret; } @@ -454,11 +432,9 @@ static void iwl4965_apm_stop(struct iwl_priv *priv) static int iwl4965_apm_reset(struct iwl_priv *priv) { int ret = 0; - unsigned long flags; iwl4965_apm_stop_master(priv); - spin_lock_irqsave(&priv->lock, flags); iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); @@ -475,9 +451,6 @@ static int iwl4965_apm_reset(struct iwl_priv *priv) udelay(10); - ret = iwl_grab_nic_access(priv); - if (ret) - goto out; /* Enable DMA and BSM Clock */ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); @@ -488,14 +461,10 @@ static int iwl4965_apm_reset(struct iwl_priv *priv) iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl_release_nic_access(priv); - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); wake_up_interruptible(&priv->wait_command_queue); out: - spin_unlock_irqrestore(&priv->lock, flags); - return ret; } @@ -681,18 +650,11 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) { u32 a; unsigned long flags; - int ret; int i, chan; u32 reg_val; spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - /* Clear 4965's internal Tx Scheduler data base */ priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR); a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET; @@ -759,10 +721,9 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); } - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); - return ret; + return 0; } static struct iwl_sensitivity_ranges iwl4965_sensitivity = { @@ -788,6 +749,12 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = { .nrg_th_ofdm = 100, }; +static void iwl4965_set_ct_threshold(struct iwl_priv *priv) +{ + /* want Kelvin */ + priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); +} + /** * iwl4965_hw_set_hw_params * @@ -822,7 +789,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.rx_chains_num = 2; priv->hw_params.valid_tx_ant = ANT_A | ANT_B; priv->hw_params.valid_rx_ant = ANT_A | ANT_B; - priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); + if (priv->cfg->ops->lib->temp_ops.set_ct_kill) + priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); priv->hw_params.sens = &iwl4965_sensitivity; @@ -1524,7 +1492,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) struct iwl4965_txpowertable_cmd cmd = { 0 }; int ret; u8 band = 0; - u8 is_fat = 0; + bool is_fat = false; u8 ctrl_chan_high = 0; if (test_bit(STATUS_SCANNING, &priv->status)) { @@ -1602,7 +1570,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) { int rc; u8 band = 0; - u8 is_fat = 0; + bool is_fat = false; u8 ctrl_chan_high = 0; struct iwl4965_channel_switch_cmd cmd = { 0 }; const struct iwl_channel_info *ch_info; @@ -1833,8 +1801,6 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { - int ret = 0; - if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { IWL_WARN(priv, @@ -1844,10 +1810,6 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, return -EINVAL; } - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - iwl4965_tx_queue_stop_scheduler(priv, txq_id); iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); @@ -1861,8 +1823,6 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, iwl_txq_ctx_deactivate(priv, txq_id); iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - iwl_release_nic_access(priv); - return 0; } @@ -1904,7 +1864,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, int tx_fifo, int sta_id, int tid, u16 ssn_idx) { unsigned long flags; - int ret; u16 ra_tid; if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || @@ -1922,11 +1881,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } /* Stop this Tx queue before configuring it */ iwl4965_tx_queue_stop_scheduler(priv, txq_id); @@ -1959,7 +1913,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -2268,9 +2221,10 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->txpower_work); } - 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_hcmd_utils_ops iwl4965_hcmd_utils = { @@ -2323,7 +2277,13 @@ static struct iwl_lib_ops iwl4965_lib = { }, .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl_update_chain_flags, - .temperature = iwl4965_temperature_calib, + .post_associate = iwl_post_associate, + .config_ap = iwl_config_ap, + .isr = iwl_isr_legacy, + .temp_ops = { + .temperature = iwl4965_temperature_calib, + .set_ct_kill = iwl4965_set_ct_threshold, + }, }; static struct iwl_ops iwl4965_ops = { @@ -2343,6 +2303,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, .ops = &iwl4965_ops, .mod_params = &iwl4965_mod_params, + .use_isr_legacy = true }; /* Module firmware */ @@ -2350,8 +2311,6 @@ MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); 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(disable, iwl4965_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); 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); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 15cac70e36e2..4ef6804a455a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -87,6 +87,18 @@ #define IWL50_NUM_AMPDU_QUEUES 10 #define IWL50_FIRST_AMPDU_QUEUE 10 +/* 5150 only */ +#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) + +static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) +{ + u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, + EEPROM_5000_TEMPERATURE); + /* offset = temperature - voltage / coef */ + s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); + return offset; +} + /* Fixed (non-configurable) rx data from phy */ /** diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 9452461ce864..b3c648ce8c7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -124,10 +124,6 @@ static int iwl5000_apm_init(struct iwl_priv *priv) return ret; } - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - /* enable DMA */ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); @@ -137,8 +133,6 @@ static int iwl5000_apm_init(struct iwl_priv *priv) iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl_release_nic_access(priv); - return ret; } @@ -165,12 +159,9 @@ static void iwl5000_apm_stop(struct iwl_priv *priv) static int iwl5000_apm_reset(struct iwl_priv *priv) { int ret = 0; - unsigned long flags; iwl5000_apm_stop_master(priv); - spin_lock_irqsave(&priv->lock, flags); - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -193,10 +184,6 @@ static int iwl5000_apm_reset(struct iwl_priv *priv) goto out; } - ret = iwl_grab_nic_access(priv); - if (ret) - goto out; - /* enable DMA */ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); @@ -205,11 +192,7 @@ static int iwl5000_apm_reset(struct iwl_priv *priv) /* disable L1-Active */ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - - iwl_release_nic_access(priv); - out: - spin_unlock_irqrestore(&priv->lock, flags); return ret; } @@ -252,11 +235,9 @@ static void iwl5000_nic_config(struct iwl_priv *priv) * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_grab_nic_access(priv); iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); } @@ -434,15 +415,19 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, return &priv->eeprom[address]; } -static s32 iwl5150_get_ct_threshold(struct iwl_priv *priv) +static void iwl5150_set_ct_threshold(struct iwl_priv *priv) { - const s32 volt2temp_coef = -5; - u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, - EEPROM_5000_TEMPERATURE); - /* offset = temperate - voltage / coef */ - s32 offset = temp_calib[0] - temp_calib[1] / volt2temp_coef; - s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - offset; - return threshold * volt2temp_coef; + const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; + s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - + iwl_temp_calib_to_offset(priv); + + priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; +} + +static void iwl5000_set_ct_threshold(struct iwl_priv *priv) +{ + /* want Celsius */ + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; } /* @@ -533,19 +518,9 @@ static int iwl5000_load_section(struct iwl_priv *priv, struct fw_desc *image, u32 dst_addr) { - int ret = 0; - unsigned long flags; - dma_addr_t phy_addr = image->p_addr; u32 byte_cnt = image->len; - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); @@ -574,8 +549,6 @@ static int iwl5000_load_section(struct iwl_priv *priv, FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -736,18 +709,11 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) { u32 a; unsigned long flags; - int ret; int i, chan; u32 reg_val; spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; @@ -815,7 +781,6 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) iwl_txq_ctx_activate(priv, 8); iwl_txq_ctx_activate(priv, 9); - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -868,17 +833,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_5150: - /* 5150 wants in Kelvin */ - priv->hw_params.ct_kill_threshold = - iwl5150_get_ct_threshold(priv); - break; - default: - /* all others want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; - break; - } + if (priv->cfg->ops->lib->temp_ops.set_ct_kill) + priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); /* Set initial calibration set */ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { @@ -900,7 +856,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) break; } - return 0; } @@ -1006,7 +961,6 @@ static 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; - int ret; u16 ra_tid; if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || @@ -1024,11 +978,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } /* Stop this Tx queue before configuring it */ iwl5000_tx_queue_stop_scheduler(priv, txq_id); @@ -1064,7 +1013,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -1073,8 +1021,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { - int ret; - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { IWL_ERR(priv, @@ -1084,10 +1030,6 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, return -EINVAL; } - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - iwl5000_tx_queue_stop_scheduler(priv, txq_id); iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); @@ -1101,15 +1043,16 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, iwl_txq_ctx_deactivate(priv, txq_id); iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - iwl_release_nic_access(priv); - return 0; } u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) { u16 size = (u16)sizeof(struct iwl_addsta_cmd); - memcpy(data, cmd, size); + struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; + memcpy(addsta, cmd, size); + /* resrved in 5000 */ + addsta->rate_n_flags = cpu_to_le16(0); return size; } @@ -1434,6 +1377,17 @@ static void iwl5000_temperature(struct iwl_priv *priv) priv->temperature = le32_to_cpu(priv->statistics.general.temperature); } +static void iwl5150_temperature(struct iwl_priv *priv) +{ + u32 vt = 0; + s32 offset = iwl_temp_calib_to_offset(priv); + + vt = le32_to_cpu(priv->statistics.general.temperature); + vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; + /* now vt hold the temperature in Kelvin */ + priv->temperature = KELVIN_TO_CELSIUS(vt); +} + /* Calc max signal level (dBm) among 3 possible receivers */ int iwl5000_calc_rssi(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp) @@ -1474,6 +1428,8 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, + .commit_rxon = iwl_commit_rxon, + .set_rxon_chain = iwl_set_rxon_chain, }; struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { @@ -1502,7 +1458,6 @@ struct iwl_lib_ops iwl5000_lib = { .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, - .temperature = iwl5000_temperature, .update_chain_flags = iwl_update_chain_flags, .apm_ops = { .init = iwl5000_apm_init, @@ -1527,6 +1482,63 @@ struct iwl_lib_ops iwl5000_lib = { .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 = iwl5000_set_ct_threshold, + }, +}; + +static struct iwl_lib_ops iwl5150_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 = iwl5000_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_FAT_CHANNELS, + EEPROM_5000_REG_BAND_52_FAT_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 = iwl5150_temperature, + .set_ct_kill = iwl5150_set_ct_threshold, + }, }; struct iwl_ops iwl5000_ops = { @@ -1535,6 +1547,12 @@ struct iwl_ops iwl5000_ops = { .utils = &iwl5000_hcmd_utils, }; +static struct iwl_ops iwl5150_ops = { + .lib = &iwl5150_lib, + .hcmd = &iwl5000_hcmd, + .utils = &iwl5000_hcmd_utils, +}; + struct iwl_mod_params iwl50_mod_params = { .num_of_queues = IWL50_NUM_QUEUES, .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, @@ -1630,7 +1648,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .ucode_api_max = IWL5150_UCODE_API_MAX, .ucode_api_min = IWL5150_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, + .ops = &iwl5150_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, @@ -1643,9 +1661,6 @@ struct iwl_cfg iwl5150_agn_cfg = { MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); -module_param_named(disable50, iwl50_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable50, - "manually disable the 50XX radio (default 0 [radio on])"); module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); MODULE_PARM_DESC(swcrypto50, "using software crypto engine (default 0 [hardware])\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cab7842a73aa..ff20e5048a55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -52,7 +52,7 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 /* max time to accum history 2 seconds */ -#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) +#define IWL_RATE_SCALE_FLUSH_INTVL (3*HZ) static u8 rs_ht_to_legacy[] = { IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, @@ -100,6 +100,7 @@ struct iwl_scale_tbl_info { u8 is_fat; /* 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 */ s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ u32 current_rate; /* rate_n_flags, uCode API format */ struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ @@ -135,7 +136,7 @@ struct iwl_lq_sta { u32 table_count; u32 total_failed; /* total failed frames, any/all rates */ u32 total_success; /* total successful frames, any/all rates */ - u32 flush_timer; /* time staying in mode before new search */ + u64 flush_timer; /* time staying in mode before new search */ u8 action_counter; /* # mode-switch actions tried */ u8 is_green; @@ -160,6 +161,7 @@ struct iwl_lq_sta { #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_scale_table_file; struct dentry *rs_sta_dbgfs_stats_table_file; + struct dentry *rs_sta_dbgfs_rate_scale_data_file; struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; u32 dbg_fixed_rate; #endif @@ -167,10 +169,12 @@ struct iwl_lq_sta { /* used to be in sta_info */ int last_txrate_idx; + /* last tx rate_n_flags */ + u32 last_rate_n_flags; }; static void rs_rate_scale_perform(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, + 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, @@ -191,7 +195,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits * "G" is the only table that supports CCK (the first 4 rates). */ -/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/ + static s32 expected_tpt_A[IWL_RATE_COUNT] = { 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 }; @@ -208,11 +212,11 @@ static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 }; -static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = { 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 }; -static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 }; @@ -224,14 +228,50 @@ static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 }; -static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 }; -static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 }; +/* Expected throughput metric MIMO3 */ +static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 +}; + +static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 +}; + +static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 +}; + +static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 +}; + +/* mbps, mcs */ +const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { + {"1", ""}, + {"2", ""}, + {"5.5", ""}, + {"11", ""}, + {"6", "BPSK 1/2"}, + {"9", "BPSK 1/2"}, + {"12", "QPSK 1/2"}, + {"18", "QPSK 3/4"}, + {"24", "16QAM 1/2"}, + {"36", "16QAM 3/4"}, + {"48", "64QAM 2/3"}, + {"54", "64QAM 3/4"}, + {"60", "64QAM 5/6"} +}; + +#define MCS_INDEX_PER_STREAM (8) + static inline u8 rs_extract_rate(u32 rate_n_flags) { return (u8)(rate_n_flags & 0xFF); @@ -543,6 +583,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, tbl->is_dup = 0; tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); tbl->lq_type = LQ_NONE; + tbl->max_search = IWL_MAX_SEARCH; /* legacy rate format */ if (!(rate_n_flags & RATE_MCS_HT_MSK)) { @@ -576,8 +617,10 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, tbl->lq_type = LQ_MIMO2; /* MIMO3 */ } else { - if (num_of_ant == 3) + if (num_of_ant == 3) { + tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; tbl->lq_type = LQ_MIMO3; + } } } return 0; @@ -611,19 +654,19 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, return 1; } -/* FIXME:RS: in 4965 we don't use greenfield at all */ -/* FIXME:RS: don't use greenfield for now in TX */ -#if 0 -static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) +/* in 4965 we don't use greenfield at all */ +static inline u8 rs_use_green(struct iwl_priv *priv, + struct ieee80211_conf *conf) { - return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && - priv->current_ht_config.is_green_field && - !priv->current_ht_config.non_GF_STA_present; -} -#endif -static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) -{ - return 0; + u8 is_green; + + if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) + is_green = 0; + else + is_green = (conf_is_ht(conf) && + priv->current_ht_config.is_green_field && + !priv->current_ht_config.non_GF_STA_present); + return is_green; } /** @@ -735,6 +778,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, tbl->is_fat = 0; tbl->is_SGI = 0; + tbl->max_search = IWL_MAX_SEARCH; } rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); @@ -793,7 +837,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); if (!ieee80211_is_data(hdr->frame_control) || - is_multicast_ether_addr(hdr->addr1)) + info->flags & IEEE80211_TX_CTL_NO_ACK) return; /* This packet was aggregated but doesn't carry rate scale info */ @@ -902,6 +946,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, * else look up the rate that was, finally, successful. */ tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); + lq_sta->last_rate_n_flags = tx_rate; rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); /* Update frame history window with "success" if Tx got ACKed ... */ @@ -958,7 +1003,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) - rs_rate_scale_perform(priv, hdr, sta, lq_sta); + rs_rate_scale_perform(priv, skb, sta, lq_sta); out: return; } @@ -988,6 +1033,8 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, lq_sta->table_count = 0; lq_sta->total_failed = 0; lq_sta->total_success = 0; + lq_sta->flush_timer = jiffies; + lq_sta->action_counter = 0; } /* @@ -1011,17 +1058,26 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, tbl->expected_tpt = expected_tpt_siso20MHzSGI; else tbl->expected_tpt = expected_tpt_siso20MHz; - - } else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */ + } else if (is_mimo2(tbl->lq_type)) { if (tbl->is_fat && !lq_sta->is_dup) if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo40MHzSGI; + tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; else - tbl->expected_tpt = expected_tpt_mimo40MHz; + tbl->expected_tpt = expected_tpt_mimo2_40MHz; else if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo20MHzSGI; + tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; else - tbl->expected_tpt = expected_tpt_mimo20MHz; + 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_SGI) + tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; + else + tbl->expected_tpt = expected_tpt_mimo3_40MHz; + else if (tbl->is_SGI) + tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI; + else + tbl->expected_tpt = expected_tpt_mimo3_20MHz; } else tbl->expected_tpt = expected_tpt_G; } @@ -1130,7 +1186,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, } /* - * Set up search table for MIMO + * Set up search table for MIMO2 */ static int rs_switch_to_mimo2(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, @@ -1158,10 +1214,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, tbl->lq_type = LQ_MIMO2; tbl->is_dup = lq_sta->is_dup; tbl->action = 0; + tbl->max_search = IWL_MAX_SEARCH; rate_mask = lq_sta->active_mimo2_rate; - if (priv->current_ht_config.supported_chan_width - == IWL_CHANNEL_WIDTH_40MHZ) + if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) tbl->is_fat = 1; else tbl->is_fat = 0; @@ -1183,7 +1239,73 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); + if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { + IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", + rate, rate_mask); + return -1; + } + tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); + IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", + tbl->current_rate, is_green); + return 0; +} + +/* + * Set up search table for MIMO3 + */ +static int rs_switch_to_mimo3(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta, + struct ieee80211_conf *conf, + struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl, int index) +{ + u16 rate_mask; + s32 rate; + s8 is_green = lq_sta->is_green; + + if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) + return -1; + + if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + == WLAN_HT_CAP_SM_PS_STATIC) + return -1; + + /* Need both Tx chains/antennas to support MIMO */ + if (priv->hw_params.tx_chains_num < 3) + return -1; + + IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); + + tbl->lq_type = LQ_MIMO3; + tbl->is_dup = lq_sta->is_dup; + tbl->action = 0; + 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; + else + tbl->is_fat = 0; + + /* FIXME: - don't toggle SGI here + if (tbl->is_fat) { + if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) + tbl->is_SGI = 1; + else + tbl->is_SGI = 0; + } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) + tbl->is_SGI = 1; + else + tbl->is_SGI = 0; + */ + + rs_set_expected_tpt_table(lq_sta, tbl); + + rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); + + IWL_DEBUG_RATE(priv, "LQ: MIMO3 best rate %d mask %X\n", + rate, rate_mask); if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", rate, rate_mask); @@ -1217,10 +1339,10 @@ static int rs_switch_to_siso(struct iwl_priv *priv, tbl->is_dup = lq_sta->is_dup; tbl->lq_type = LQ_SISO; tbl->action = 0; + tbl->max_search = IWL_MAX_SEARCH; rate_mask = lq_sta->active_siso_rate; - if (priv->current_ht_config.supported_chan_width - == IWL_CHANNEL_WIDTH_40MHZ) + if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) tbl->is_fat = 1; else tbl->is_fat = 0; @@ -1274,15 +1396,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv, u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret = 0; + u8 update_search_tbl_counter = 0; for (; ;) { + lq_sta->action_counter++; switch (tbl->action) { case IWL_LEGACY_SWITCH_ANTENNA1: case IWL_LEGACY_SWITCH_ANTENNA2: IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n"); - lq_sta->action_counter++; - if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && tx_chains_num <= 1) || (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && @@ -1298,6 +1420,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, if (rs_toggle_antenna(valid_tx_ant, &search_tbl->current_rate, search_tbl)) { + update_search_tbl_counter = 1; rs_set_expected_tpt_table(lq_sta, search_tbl); goto out; } @@ -1342,9 +1465,29 @@ static int rs_move_legacy_other(struct iwl_priv *priv, goto out; } break; + + case IWL_LEGACY_SWITCH_MIMO3_ABC: + IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO3\n"); + + /* Set up search table to try MIMO3 */ + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + + search_tbl->ant_type = ANT_ABC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) { + lq_sta->action_counter = 0; + goto out; + } + break; } tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) + if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; if (tbl->action == start_action) @@ -1357,8 +1500,10 @@ static int rs_move_legacy_other(struct iwl_priv *priv, out: lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) + if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; + if (update_search_tbl_counter) + search_tbl->action = tbl->action; return 0; } @@ -1381,6 +1526,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, u8 start_action = tbl->action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 update_search_tbl_counter = 0; int ret; for (;;) { @@ -1401,8 +1547,10 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, memcpy(search_tbl, tbl, sz); if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) + &search_tbl->current_rate, search_tbl)) { + update_search_tbl_counter = 1; goto out; + } break; case IWL_SISO_SWITCH_MIMO2_AB: case IWL_SISO_SWITCH_MIMO2_AC: @@ -1456,10 +1604,25 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, search_tbl->current_rate = rate_n_flags_from_tbl(priv, search_tbl, index, is_green); + update_search_tbl_counter = 1; goto out; + case IWL_SISO_SWITCH_MIMO3_ABC: + IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n"); + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + search_tbl->ant_type = ANT_ABC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + break; } tbl->action++; - if (tbl->action > IWL_SISO_SWITCH_GI) + if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) tbl->action = IWL_SISO_SWITCH_ANTENNA1; if (tbl->action == start_action) @@ -1471,15 +1634,18 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, out: lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_SISO_SWITCH_GI) + if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) tbl->action = IWL_SISO_SWITCH_ANTENNA1; + if (update_search_tbl_counter) + search_tbl->action = tbl->action; + return 0; } /* - * Try to switch to new modulation mode from MIMO + * Try to switch to new modulation mode from MIMO2 */ -static int rs_move_mimo_to_other(struct iwl_priv *priv, +static int rs_move_mimo2_to_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, struct ieee80211_sta *sta, int index) @@ -1494,6 +1660,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, u8 start_action = tbl->action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; u8 tx_chains_num = priv->hw_params.tx_chains_num; + u8 update_search_tbl_counter = 0; int ret; for (;;) { @@ -1501,7 +1668,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, switch (tbl->action) { case IWL_MIMO2_SWITCH_ANTENNA1: case IWL_MIMO2_SWITCH_ANTENNA2: - IWL_DEBUG_RATE(priv, "LQ: MIMO toggle Antennas\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n"); if (tx_chains_num <= 2) break; @@ -1511,8 +1678,10 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, memcpy(search_tbl, tbl, sz); if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) + &search_tbl->current_rate, search_tbl)) { + update_search_tbl_counter = 1; goto out; + } break; case IWL_MIMO2_SWITCH_SISO_A: case IWL_MIMO2_SWITCH_SISO_B: @@ -1549,7 +1718,165 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, HT_SHORT_GI_40MHZ)) break; - IWL_DEBUG_RATE(priv, "LQ: MIMO toggle SGI/NGI\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); + + /* Set up new search table for MIMO2 */ + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = !tbl->is_SGI; + rs_set_expected_tpt_table(lq_sta, search_tbl); + /* + * If active table already uses the fastest possible + * modulation (dual stream with short guard interval), + * and it's working well, there's no need to look + * for a better type of modulation! + */ + if (tbl->is_SGI) { + s32 tpt = lq_sta->last_tpt / 100; + if (tpt >= search_tbl->expected_tpt[index]) + break; + } + search_tbl->current_rate = + rate_n_flags_from_tbl(priv, search_tbl, + index, is_green); + update_search_tbl_counter = 1; + goto out; + + case IWL_MIMO2_SWITCH_MIMO3_ABC: + IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to MIMO3\n"); + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + search_tbl->ant_type = ANT_ABC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + + break; + } + tbl->action++; + if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) + tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; + + if (tbl->action == start_action) + break; + } + search_tbl->lq_type = LQ_NONE; + return 0; + out: + lq_sta->search_better_tbl = 1; + tbl->action++; + if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) + tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; + if (update_search_tbl_counter) + search_tbl->action = tbl->action; + + return 0; + +} + +/* + * Try to switch to new modulation mode from MIMO3 + */ +static int rs_move_mimo3_to_other(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta, + struct ieee80211_conf *conf, + struct ieee80211_sta *sta, int index) +{ + s8 is_green = lq_sta->is_green; + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); + u8 start_action = tbl->action; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; + int ret; + u8 update_search_tbl_counter = 0; + + for (;;) { + lq_sta->action_counter++; + switch (tbl->action) { + case IWL_MIMO3_SWITCH_ANTENNA1: + case IWL_MIMO3_SWITCH_ANTENNA2: + IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle Antennas\n"); + + if (tx_chains_num <= 3) + break; + + if (window->success_ratio >= IWL_RS_GOOD_RATIO) + break; + + memcpy(search_tbl, tbl, sz); + if (rs_toggle_antenna(valid_tx_ant, + &search_tbl->current_rate, search_tbl)) + goto out; + break; + case IWL_MIMO3_SWITCH_SISO_A: + case IWL_MIMO3_SWITCH_SISO_B: + case IWL_MIMO3_SWITCH_SISO_C: + IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to SISO\n"); + + /* Set up new search table for SISO */ + memcpy(search_tbl, tbl, sz); + + if (tbl->action == IWL_MIMO3_SWITCH_SISO_A) + search_tbl->ant_type = ANT_A; + else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B) + search_tbl->ant_type = ANT_B; + else + search_tbl->ant_type = ANT_C; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_siso(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + + break; + + case IWL_MIMO3_SWITCH_MIMO2_AB: + case IWL_MIMO3_SWITCH_MIMO2_AC: + case IWL_MIMO3_SWITCH_MIMO2_BC: + IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to MIMO2\n"); + + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB) + search_tbl->ant_type = ANT_AB; + else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC) + search_tbl->ant_type = ANT_AC; + else + search_tbl->ant_type = ANT_BC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + + break; + + case IWL_MIMO3_SWITCH_GI: + if (!tbl->is_fat && + !(priv->current_ht_config.sgf & + HT_SHORT_GI_20MHZ)) + break; + if (tbl->is_fat && + !(priv->current_ht_config.sgf & + HT_SHORT_GI_40MHZ)) + break; + + IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); /* Set up new search table for MIMO */ memcpy(search_tbl, tbl, sz); @@ -1569,12 +1896,12 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, search_tbl->current_rate = rate_n_flags_from_tbl(priv, search_tbl, index, is_green); + update_search_tbl_counter = 1; goto out; - } tbl->action++; - if (tbl->action > IWL_MIMO2_SWITCH_GI) - tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; + if (tbl->action > IWL_MIMO3_SWITCH_GI) + tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; if (tbl->action == start_action) break; @@ -1584,8 +1911,11 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, out: lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_MIMO2_SWITCH_GI) - tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; + if (tbl->action > IWL_MIMO3_SWITCH_GI) + tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; + if (update_search_tbl_counter) + search_tbl->action = tbl->action; + return 0; } @@ -1616,8 +1946,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) /* Elapsed time using current modulation mode */ if (lq_sta->flush_timer) flush_interval_passed = - time_after(jiffies, - (unsigned long)(lq_sta->flush_timer + + time_after(jiffies, + (unsigned long)(lq_sta->flush_timer + IWL_RATE_SCALE_FLUSH_INTVL)); /* @@ -1676,12 +2006,14 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) * Do rate scaling and search for new modulation mode. */ static void rs_rate_scale_perform(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, + struct sk_buff *skb, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta) { struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; int low = IWL_RATE_INVALID; int high = IWL_RATE_INVALID; int index; @@ -1707,11 +2039,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); - /* Send management frames and broadcast/multicast data using - * lowest rate. */ + /* Send management frames and NO_ACK data using lowest rate. */ /* TODO: this could probably be improved.. */ if (!ieee80211_is_data(hdr->frame_control) || - is_multicast_ether_addr(hdr->addr1)) + info->flags & IEEE80211_TX_CTL_NO_ACK) return; if (!sta || !lq_sta) @@ -1732,6 +2063,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, active_tbl = 1 - lq_sta->active_tbl; tbl = &(lq_sta->lq_info[active_tbl]); + if (is_legacy(tbl->lq_type)) + lq_sta->is_green = 0; + else + lq_sta->is_green = rs_use_green(priv, conf); is_green = lq_sta->is_green; /* current tx rate */ @@ -1951,6 +2286,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, update_lq = 1; index = low; } + break; case 1: /* Increase starting rate, update uCode's rate table */ @@ -1997,8 +2333,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, rs_move_legacy_other(priv, lq_sta, conf, sta, index); else if (is_siso(tbl->lq_type)) rs_move_siso_to_other(priv, lq_sta, conf, sta, index); + else if (is_mimo2(tbl->lq_type)) + rs_move_mimo2_to_other(priv, lq_sta, conf, sta, index); else - rs_move_mimo_to_other(priv, lq_sta, conf, sta, index); + rs_move_mimo3_to_other(priv, lq_sta, conf, sta, index); /* If new "search" mode was selected, set up in uCode table */ if (lq_sta->search_better_tbl) { @@ -2014,8 +2352,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl->current_rate, index); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); - } + } else + done_search = 1; + } + if (done_search && !lq_sta->stay_in_tbl) { /* If the "active" (non-search) mode was legacy, * and we've tried switching antennas, * but we haven't been able to try HT modes (not available), @@ -2023,8 +2364,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) && - lq_sta->action_counter >= 1) { - lq_sta->action_counter = 0; + lq_sta->action_counter > tbl1->max_search) { IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n"); rs_set_stay_in_table(priv, 1, lq_sta); } @@ -2033,7 +2373,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, * 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 >= IWL_ACTION_LIMIT)) { + (lq_sta->action_counter >= tbl1->max_search)) { if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && (tid != MAX_TID_COUNT)) { @@ -2047,20 +2387,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_sta, sta); } } - lq_sta->action_counter = 0; rs_set_stay_in_table(priv, 0, lq_sta); } - - /* - * Else, don't search for a new modulation mode. - * Put new timestamp in stay-in-modulation-mode flush timer if: - * 1) Not changing rates right now - * 2) Not just finishing up a search - * 3) flush timer is empty - */ - } else { - if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer)) - lq_sta->flush_timer = jiffies; } out: @@ -2156,16 +2484,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, if (sta) mask_bit = sta->supp_rates[sband->band]; - /* Send management frames and broadcast/multicast data using lowest - * rate. */ + /* Send management frames and NO_ACK data using lowest rate. */ if (!ieee80211_is_data(hdr->frame_control) || - is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) { + 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; return; } @@ -2178,8 +2507,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", hdr->addr1); - sta_id = iwl_add_station_flags(priv, hdr->addr1, - 0, CMD_ASYNC, NULL); + sta_id = iwl_add_station(priv, hdr->addr1, + false, CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { lq_sta->lq.sta_id = sta_id; @@ -2189,12 +2518,33 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, } } - if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT) - rate_idx = rate_lowest_index(sband, sta); - else if (sband->band == IEEE80211_BAND_5GHZ) + if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { rate_idx -= IWL_FIRST_OFDM_RATE; - + /* 6M and 9M shared same MCS index */ + rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; + if (rs_extract_rate(lq_sta->last_rate_n_flags) >= + IWL_RATE_MIMO3_6M_PLCP) + rate_idx = rate_idx + (2 * MCS_INDEX_PER_STREAM); + else if (rs_extract_rate(lq_sta->last_rate_n_flags) >= + IWL_RATE_MIMO2_6M_PLCP) + rate_idx = rate_idx + MCS_INDEX_PER_STREAM; + info->control.rates[0].flags = IEEE80211_TX_RC_MCS; + if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) + 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) + 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; + } else { + if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT) + rate_idx = rate_lowest_index(sband, sta); + else if (sband->band == IEEE80211_BAND_5GHZ) + rate_idx -= IWL_FIRST_OFDM_RATE; + } info->control.rates[0].idx = rate_idx; + } static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, @@ -2246,15 +2596,16 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->ibss_sta_added = 0; if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, sta->addr); + u8 sta_id = iwl_find_station(priv, + sta->addr); /* for IBSS the call are from tasklet */ IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - sta_id = iwl_add_station_flags(priv, sta->addr, - 0, CMD_ASYNC, NULL); + sta_id = iwl_add_station(priv, sta->addr, false, + CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { lq_sta->lq.sta_id = sta_id; @@ -2436,9 +2787,10 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, repeat_rate--; } - lq_cmd->agg_params.agg_frame_cnt_limit = 64; - lq_cmd->agg_params.agg_dis_start_th = 3; - lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); + lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX; + lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + lq_cmd->agg_params.agg_time_limit = + cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); } static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) @@ -2539,6 +2891,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, char *buff; int desc = 0; int i = 0; + int index = 0; ssize_t ret; struct iwl_lq_sta *lq_sta = file->private_data; @@ -2568,8 +2921,11 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); desc += sprintf(buff+desc, " %s", (tbl->is_fat) ? "40MHz" : "20MHz"); - desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : ""); + desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", + (lq_sta->is_green) ? "GF enabled" : ""); } + desc += sprintf(buff+desc, "last tx rate=0x%X\n", + lq_sta->last_rate_n_flags); desc += sprintf(buff+desc, "general:" "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", lq_sta->lq.general_params.flags, @@ -2590,10 +2946,19 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->lq.general_params.start_rate_index[2], lq_sta->lq.general_params.start_rate_index[3]); - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - desc += sprintf(buff+desc, " rate[%d] 0x%X\n", - i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { + index = iwl_hwrate_to_plcp_idx( + le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); + if (is_legacy(tbl->lq_type)) { + desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n", + i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), + iwl_rate_mcs[index].mbps); + } else { + desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps (%s)\n", + i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), + iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs); + } + } ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); kfree(buff); @@ -2620,13 +2985,14 @@ 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\n" + desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%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_dup, + lq_sta->is_green, lq_sta->lq_info[i].current_rate); for (j = 0; j < IWL_RATE_COUNT; j++) { desc += sprintf(buff+desc, @@ -2646,6 +3012,43 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { .open = open_file_generic, }; +static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + char buff[120]; + int desc = 0; + ssize_t ret; + + struct iwl_lq_sta *lq_sta = file->private_data; + struct iwl_priv *priv; + struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; + + priv = lq_sta->drv; + + if (is_Ht(tbl->lq_type)) + desc += sprintf(buff+desc, + "Bit Rate= %d Mb/s\n", + tbl->expected_tpt[lq_sta->last_txrate_idx]); + else + desc += sprintf(buff+desc, + "Bit Rate= %d Mb/s\n", + iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); + desc += sprintf(buff+desc, + "Signal Level= %d dBm\tNoise Level= %d dBm\n", + priv->last_rx_rssi, priv->last_rx_noise); + desc += sprintf(buff+desc, + "Tsf= 0x%llx\tBeacon time= 0x%08X\n", + priv->last_tsf, priv->last_beacon_time); + + ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); + return ret; +} + +static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { + .read = rs_sta_dbgfs_rate_scale_data_read, + .open = open_file_generic, +}; + static void rs_add_debugfs(void *priv, void *priv_sta, struct dentry *dir) { @@ -2656,6 +3059,9 @@ static void rs_add_debugfs(void *priv, void *priv_sta, lq_sta->rs_sta_dbgfs_stats_table_file = debugfs_create_file("rate_stats_table", 0600, dir, lq_sta, &rs_sta_dbgfs_stats_table_ops); + lq_sta->rs_sta_dbgfs_rate_scale_data_file = + debugfs_create_file("rate_scale_data", 0600, dir, + lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = debugfs_create_u8("tx_agg_tid_enable", 0600, dir, &lq_sta->tx_agg_tid_en); @@ -2667,6 +3073,7 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) struct iwl_lq_sta *lq_sta = priv_sta; debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); + debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file); debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index ab59acc405d9..25050bf315a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -241,6 +241,7 @@ enum { #define IWL_LEGACY_SWITCH_MIMO2_AB 3 #define IWL_LEGACY_SWITCH_MIMO2_AC 4 #define IWL_LEGACY_SWITCH_MIMO2_BC 5 +#define IWL_LEGACY_SWITCH_MIMO3_ABC 6 /* possible actions when in siso mode */ #define IWL_SISO_SWITCH_ANTENNA1 0 @@ -249,6 +250,8 @@ enum { #define IWL_SISO_SWITCH_MIMO2_AC 3 #define IWL_SISO_SWITCH_MIMO2_BC 4 #define IWL_SISO_SWITCH_GI 5 +#define IWL_SISO_SWITCH_MIMO3_ABC 6 + /* possible actions when in mimo mode */ #define IWL_MIMO2_SWITCH_ANTENNA1 0 @@ -257,6 +260,23 @@ enum { #define IWL_MIMO2_SWITCH_SISO_B 3 #define IWL_MIMO2_SWITCH_SISO_C 4 #define IWL_MIMO2_SWITCH_GI 5 +#define IWL_MIMO2_SWITCH_MIMO3_ABC 6 + + +/* possible actions when in mimo3 mode */ +#define IWL_MIMO3_SWITCH_ANTENNA1 0 +#define IWL_MIMO3_SWITCH_ANTENNA2 1 +#define IWL_MIMO3_SWITCH_SISO_A 2 +#define IWL_MIMO3_SWITCH_SISO_B 3 +#define IWL_MIMO3_SWITCH_SISO_C 4 +#define IWL_MIMO3_SWITCH_MIMO2_AB 5 +#define IWL_MIMO3_SWITCH_MIMO2_AC 6 +#define IWL_MIMO3_SWITCH_MIMO2_BC 7 +#define IWL_MIMO3_SWITCH_GI 8 + + +#define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI +#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC /*FIXME:RS:add possible actions for MIMO3*/ @@ -307,6 +327,13 @@ enum iwl_table_type { #define ANT_BC (ANT_B | ANT_C) #define ANT_ABC (ANT_AB | ANT_C) +#define IWL_MAX_MCS_DISPLAY_SIZE 12 + +struct iwl_rate_mcs_info { + char mbps[IWL_MAX_MCS_DISPLAY_SIZE]; + char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; +}; + static inline u8 num_of_ant(u8 mask) { return !!((mask) & ANT_A) + diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f46ba2475776..a5637c4aa85d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -102,7 +102,7 @@ MODULE_ALIAS("iwl4965"); * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -static int iwl_commit_rxon(struct iwl_priv *priv) +int iwl_commit_rxon(struct iwl_priv *priv) { /* cast away the const for active_rxon in this function */ struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; @@ -190,8 +190,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) iwl_clear_stations_table(priv); - if (!priv->error_recovering) - priv->start_calib = 0; + priv->start_calib = 0; /* Add the broadcast address so we can send broadcast frames */ if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == @@ -246,8 +245,9 @@ static int iwl_commit_rxon(struct iwl_priv *priv) void iwl_update_chain_flags(struct iwl_priv *priv) { - iwl_set_rxon_chain(priv); - iwl_commit_rxon(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + iwlcore_commit_rxon(priv); } static void iwl_clear_free_frames(struct iwl_priv *priv) @@ -503,24 +503,12 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - int ret; - unsigned long flags; int txq_id = txq->q.id; - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - /* Circular buffer (TFD queue in DRAM) physical base address */ iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return 0; } @@ -531,76 +519,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv, * ******************************************************************************/ -static void iwl_ht_conf(struct iwl_priv *priv, - struct ieee80211_bss_conf *bss_conf) -{ - struct ieee80211_sta_ht_cap *ht_conf; - struct iwl_ht_info *iwl_conf = &priv->current_ht_config; - struct ieee80211_sta *sta; - - IWL_DEBUG_MAC80211(priv, "enter: \n"); - - if (!iwl_conf->is_ht) - return; - - - /* - * It is totally wrong to base global information on something - * that is valid only when associated, alas, this driver works - * that way and I don't know how to fix it. - */ - - rcu_read_lock(); - sta = ieee80211_find_sta(priv->hw, priv->bssid); - if (!sta) { - rcu_read_unlock(); - return; - } - ht_conf = &sta->ht_cap; - - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) - iwl_conf->sgf |= HT_SHORT_GI_20MHZ; - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) - iwl_conf->sgf |= HT_SHORT_GI_40MHZ; - - iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); - iwl_conf->max_amsdu_size = - !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); - - iwl_conf->supported_chan_width = - !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); - - /* - * XXX: The HT configuration needs to be moved into iwl_mac_config() - * to be done there correctly. - */ - - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - if (conf_is_ht40_minus(&priv->hw->conf)) - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - 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 (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; - - iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); - - memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); - - iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; - iwl_conf->ht_protection = - bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - iwl_conf->non_GF_STA_present = - !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - - rcu_read_unlock(); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - #define MAX_UCODE_BEACON_INTERVAL 4096 static u16 iwl_adjust_beacon_interval(u16 beacon_val) @@ -636,7 +554,8 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) beacon_int = iwl_adjust_beacon_interval(priv->beacon_int); priv->rxon_timing.atim_window = 0; } else { - beacon_int = iwl_adjust_beacon_interval(conf->beacon_int); + 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 */ @@ -657,23 +576,6 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl_set_mode(struct iwl_priv *priv, int mode) -{ - iwl_connection_init_rx_config(priv, mode); - iwl_set_rxon_chain(priv); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - - iwl_clear_stations_table(priv); - - /* dont commit rxon if rf-kill is on*/ - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - - iwl_commit_rxon(priv); - - return 0; -} - /****************************************************************************** * * Generic RX handler implementations @@ -795,6 +697,7 @@ 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", @@ -806,32 +709,25 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - if (!iwl_grab_nic_access(priv)) { - iwl_write_direct32( - priv, HBUS_TARG_MBX_C, - HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); - - iwl_release_nic_access(priv); - } + iwl_write_direct32(priv, HBUS_TARG_MBX_C, + HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - if (!iwl_grab_nic_access(priv)) { - iwl_write_direct32( - priv, HBUS_TARG_MBX_C, + iwl_write_direct32(priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); - iwl_release_nic_access(priv); - } } 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); } } @@ -841,33 +737,19 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, clear_bit(STATUS_RF_KILL_HW, &priv->status); - if (flags & SW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_SW, &priv->status); - else - clear_bit(STATUS_RF_KILL_SW, &priv->status); - if (!(flags & RXON_CARD_DISABLED)) iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->status)) || - (test_bit(STATUS_RF_KILL_SW, &status) != - test_bit(STATUS_RF_KILL_SW, &priv->status))) - queue_work(priv->workqueue, &priv->rf_kill); + test_bit(STATUS_RF_KILL_HW, &priv->status))) + wiphy_rfkill_set_hw_state(priv->hw->wiphy, + test_bit(STATUS_RF_KILL_HW, &priv->status)); else wake_up_interruptible(&priv->wait_command_queue); } int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) { - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) - goto err; - if (src == IWL_PWR_SRC_VAUX) { if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, @@ -879,10 +761,7 @@ int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) ~APMG_PS_CTRL_MSK_PWR_SRC); } - iwl_release_nic_access(priv); -err: - spin_unlock_irqrestore(&priv->lock, flags); - return ret; + return 0; } /** @@ -946,6 +825,7 @@ void iwl_rx_handle(struct iwl_priv *priv) unsigned long flags; u8 fill_rx = 0; u32 count = 8; + int total_empty; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -956,7 +836,12 @@ void iwl_rx_handle(struct iwl_priv *priv) if (i == r) IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); - if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) + /* calculate total frames need to be restock after handling RX */ + total_empty = r - priv->rxq.write_actual; + if (total_empty < 0) + total_empty += RX_QUEUE_SIZE; + + if (total_empty > (RX_QUEUE_SIZE / 2)) fill_rx = 1; while (i != r) { @@ -995,6 +880,7 @@ void iwl_rx_handle(struct iwl_priv *priv) IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; } else { /* No handling needed */ IWL_DEBUG_RX(priv, @@ -1032,7 +918,7 @@ void iwl_rx_handle(struct iwl_priv *priv) count++; if (count >= 8) { priv->rxq.read = i; - iwl_rx_queue_restock(priv); + iwl_rx_replenish_now(priv); count = 0; } } @@ -1040,7 +926,10 @@ void iwl_rx_handle(struct iwl_priv *priv) /* Backtrack one entry */ priv->rxq.read = i; - iwl_rx_queue_restock(priv); + if (fill_rx) + iwl_rx_replenish_now(priv); + else + iwl_rx_queue_restock(priv); } /* call this function to flush any scheduled tasklet */ @@ -1051,24 +940,7 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) tasklet_kill(&priv->irq_tasklet); } -static void iwl_error_recovery(struct iwl_priv *priv) -{ - unsigned long flags; - - memcpy(&priv->staging_rxon, &priv->recovery_rxon, - sizeof(priv->staging_rxon)); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); - - iwl_rxon_add_station(priv, priv->bssid, 1); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); - priv->error_recovering = 0; - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void iwl_irq_tasklet(struct iwl_priv *priv) +static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) { u32 inta, handled = 0; u32 inta_fh; @@ -1116,6 +988,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); + priv->isr_stats.hw++; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -1128,13 +1001,17 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) #ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) + if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); + priv->isr_stats.sch++; + } /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) + if (inta & CSR_INT_BIT_ALIVE) { IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } } #endif /* Safely ignore these bits for debug checks below */ @@ -1150,6 +1027,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); + priv->isr_stats.rfkill++; + /* driver only loads ucode once setting the interface up. * the driver allows loading the ucode even if the radio * is killed. Hence update the killswitch state here. The @@ -1160,7 +1039,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) set_bit(STATUS_RF_KILL_HW, &priv->status); else clear_bit(STATUS_RF_KILL_HW, &priv->status); - queue_work(priv->workqueue, &priv->rf_kill); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); } handled |= CSR_INT_BIT_RF_KILL; @@ -1169,6 +1048,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; handled |= CSR_INT_BIT_CT_KILL; } @@ -1176,6 +1056,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_SW_ERR) { IWL_ERR(priv, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + priv->isr_stats.sw_err = inta; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -1191,6 +1073,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) iwl_txq_update_write_ptr(priv, &priv->txq[4]); iwl_txq_update_write_ptr(priv, &priv->txq[5]); + priv->isr_stats.wakeup++; + handled |= CSR_INT_BIT_WAKEUP; } @@ -1199,23 +1083,27 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { iwl_rx_handle(priv); + priv->isr_stats.rx++; handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); } if (inta & CSR_INT_BIT_FH_TX) { IWL_DEBUG_ISR(priv, "Tx interrupt\n"); + priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; /* FH finished to write, send event */ priv->ucode_write_complete = 1; wake_up_interruptible(&priv->wait_command_queue); } - if (inta & ~handled) + if (inta & ~handled) { IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } - if (inta & ~CSR_INI_SET_MASK) { + if (inta & ~(priv->inta_mask)) { IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~CSR_INI_SET_MASK); + inta & ~priv->inta_mask); IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); } @@ -1236,6 +1124,200 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } +/* tasklet for iwlagn interrupt */ +static void iwl_irq_tasklet(struct iwl_priv *priv) +{ + u32 inta = 0; + u32 handled = 0; + unsigned long flags; +#ifdef CONFIG_IWLWIFI_DEBUG + u32 inta_mask; +#endif + + spin_lock_irqsave(&priv->lock, flags); + + /* Ack/clear/reset pending uCode interrupts. + * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, + */ + iwl_write32(priv, CSR_INT, priv->inta); + + inta = priv->inta; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (priv->debug_level & 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 ", + inta, inta_mask); + } +#endif + /* saved interrupt in inta variable now we can reset priv->inta */ + priv->inta = 0; + + /* Now service all interrupt bits discovered above. */ + if (inta & CSR_INT_BIT_HW_ERR) { + IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); + + /* Tell the device to stop sending interrupts */ + iwl_disable_interrupts(priv); + + priv->isr_stats.hw++; + iwl_irq_handle_error(priv); + + handled |= CSR_INT_BIT_HW_ERR; + + spin_unlock_irqrestore(&priv->lock, flags); + + return; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + if (priv->debug_level & (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 " + "the frame/frames.\n"); + priv->isr_stats.sch++; + } + + /* Alive notification via Rx interrupt will do the real work */ + if (inta & CSR_INT_BIT_ALIVE) { + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } + } +#endif + /* Safely ignore these bits for debug checks below */ + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); + + /* HW RF KILL switch toggled */ + if (inta & CSR_INT_BIT_RF_KILL) { + int hw_rf_kill = 0; + if (!(iwl_read32(priv, CSR_GP_CNTRL) & + 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", + hw_rf_kill ? "disable radio" : "enable radio"); + + priv->isr_stats.rfkill++; + + /* driver only loads ucode once setting the interface up. + * the driver allows loading the ucode even if the radio + * is killed. Hence update the killswitch state here. The + * rfkill handler will care about restarting if needed. + */ + if (!test_bit(STATUS_ALIVE, &priv->status)) { + if (hw_rf_kill) + set_bit(STATUS_RF_KILL_HW, &priv->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->status); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); + } + + handled |= CSR_INT_BIT_RF_KILL; + } + + /* Chip got too hot and stopped itself */ + if (inta & CSR_INT_BIT_CT_KILL) { + IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; + handled |= CSR_INT_BIT_CT_KILL; + } + + /* Error detected by uCode */ + if (inta & CSR_INT_BIT_SW_ERR) { + IWL_ERR(priv, "Microcode SW error detected. " + " Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + priv->isr_stats.sw_err = inta; + iwl_irq_handle_error(priv); + handled |= CSR_INT_BIT_SW_ERR; + } + + /* uCode wakes up after power-down sleep */ + if (inta & CSR_INT_BIT_WAKEUP) { + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); + iwl_rx_queue_update_write_ptr(priv, &priv->rxq); + iwl_txq_update_write_ptr(priv, &priv->txq[0]); + iwl_txq_update_write_ptr(priv, &priv->txq[1]); + iwl_txq_update_write_ptr(priv, &priv->txq[2]); + iwl_txq_update_write_ptr(priv, &priv->txq[3]); + iwl_txq_update_write_ptr(priv, &priv->txq[4]); + iwl_txq_update_write_ptr(priv, &priv->txq[5]); + + priv->isr_stats.wakeup++; + + handled |= CSR_INT_BIT_WAKEUP; + } + + /* All uCode command responses, including Tx command responses, + * Rx "responses" (frame-received notification), and other + * notifications from uCode come through here*/ + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | + CSR_INT_BIT_RX_PERIODIC)) { + IWL_DEBUG_ISR(priv, "Rx interrupt\n"); + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { + handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); + iwl_write32(priv, CSR_FH_INT_STATUS, + CSR49_FH_INT_RX_MASK); + } + if (inta & CSR_INT_BIT_RX_PERIODIC) { + handled |= CSR_INT_BIT_RX_PERIODIC; + iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); + } + /* Sending RX interrupt require many steps to be done in the + * the device: + * 1- write interrupt to current index in ICT table. + * 2- dma RX frame. + * 3- update RX shared data to indicate last write index. + * 4- send interrupt. + * This could lead to RX race, driver could receive RX interrupt + * but the shared data changes does not reflect this. + * this could lead to RX race, RX periodic will solve this race + */ + iwl_write32(priv, CSR_INT_PERIODIC_REG, + CSR_INT_PERIODIC_DIS); + iwl_rx_handle(priv); + /* Only set RX periodic if real RX is received. */ + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) + iwl_write32(priv, CSR_INT_PERIODIC_REG, + CSR_INT_PERIODIC_ENA); + + priv->isr_stats.rx++; + } + + if (inta & CSR_INT_BIT_FH_TX) { + iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); + IWL_DEBUG_ISR(priv, "Tx interrupt\n"); + priv->isr_stats.tx++; + handled |= CSR_INT_BIT_FH_TX; + /* FH finished to write, send event */ + priv->ucode_write_complete = 1; + wake_up_interruptible(&priv->wait_command_queue); + } + + if (inta & ~handled) { + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } + + if (inta & ~(priv->inta_mask)) { + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", + inta & ~priv->inta_mask); + } + + + /* Re-enable all interrupts */ + /* only Re-enable if diabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); + + spin_unlock_irqrestore(&priv->lock, flags); + +} + + /****************************************************************************** * * uCode download functions @@ -1501,10 +1583,6 @@ static int iwl_read_ucode(struct iwl_priv *priv) return ret; } -/* temporary */ -static int iwl_mac_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *skb); - /** * iwl_alive_start - called after REPLY_ALIVE notification received * from protocol/runtime uCode (initialization uCode's @@ -1561,7 +1639,10 @@ static void iwl_alive_start(struct iwl_priv *priv) } else { /* Initialize our rx_config data */ iwl_connection_init_rx_config(priv, priv->iw_mode); - iwl_set_rxon_chain(priv); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); } @@ -1571,7 +1652,7 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); /* Configure the adapter for unassociated operation */ - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); /* At this point, the NIC is initialized and operational */ iwl_rf_kill_ct_config(priv); @@ -1582,9 +1663,6 @@ static void iwl_alive_start(struct iwl_priv *priv) set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - if (priv->error_recovering) - iwl_error_recovery(priv); - iwl_power_update_mode(priv, 1); /* reassociate for ADHOC mode */ @@ -1642,36 +1720,30 @@ static void __iwl_down(struct iwl_priv *priv) ieee80211_stop_queues(priv->hw); /* If we have not previously called iwl_init() then - * clear all bits but the RF Kill and SUSPEND bits and return */ + * clear all bits but the RF Kill bit and return */ if (!iwl_is_init(priv)) { priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_RF_KILL_SW, &priv->status) << - STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; goto exit; } - /* ...otherwise clear out all the status bits but the RF Kill and - * SUSPEND bits and continue taking the NIC down. */ + /* ...otherwise clear out all the status bits but the RF Kill + * bit and continue taking the NIC down. */ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_RF_KILL_SW, &priv->status) << - STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << STATUS_FW_ERROR | test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; + /* device going down, Stop using ICT table */ + iwl_disable_ict(priv); spin_lock_irqsave(&priv->lock, flags); iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); @@ -1680,18 +1752,13 @@ static void __iwl_down(struct iwl_priv *priv) iwl_txq_ctx_stop(priv); iwl_rxq_stop(priv); - spin_lock_irqsave(&priv->lock, flags); - if (!iwl_grab_nic_access(priv)) { - iwl_write_prph(priv, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->lock, flags); + iwl_write_prph(priv, APMG_CLK_DIS_REG, + APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); /* FIXME: apm_ops.suspend(priv) */ - if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) + if (exit_pending) priv->cfg->ops->lib->apm_ops.stop(priv); else priv->cfg->ops->lib->apm_ops.reset(priv); @@ -1715,6 +1782,49 @@ static void iwl_down(struct iwl_priv *priv) iwl_cancel_deferred_work(priv); } +#define HW_READY_TIMEOUT (50) + +static int iwl_set_hw_ready(struct iwl_priv *priv) +{ + int ret = 0; + + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); + + /* See if we got it */ + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + HW_READY_TIMEOUT); + if (ret != -ETIMEDOUT) + priv->hw_ready = true; + else + priv->hw_ready = false; + + IWL_DEBUG_INFO(priv, "hardware %s\n", + (priv->hw_ready == 1) ? "ready" : "not ready"); + return ret; +} + +static int iwl_prepare_card_hw(struct iwl_priv *priv) +{ + int ret = 0; + + IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n"); + + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PREPARE); + + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, + CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); + + if (ret != -ETIMEDOUT) + iwl_set_hw_ready(priv); + + return ret; +} + #define MAX_HW_RESTARTS 5 static int __iwl_up(struct iwl_priv *priv) @@ -1732,6 +1842,13 @@ static int __iwl_up(struct iwl_priv *priv) return -EIO; } + iwl_prepare_card_hw(priv); + + if (!priv->hw_ready) { + IWL_WARN(priv, "Exit HW not ready\n"); + return -EIO; + } + /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); @@ -1739,9 +1856,10 @@ static int __iwl_up(struct iwl_priv *priv) set_bit(STATUS_RF_KILL_HW, &priv->status); if (iwl_is_rfkill(priv)) { + wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); + iwl_enable_interrupts(priv); - IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n", - test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); + IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); return 0; } @@ -1787,9 +1905,6 @@ static int __iwl_up(struct iwl_priv *priv) continue; } - /* Clear out the uCode error bit if it is set */ - clear_bit(STATUS_FW_ERROR, &priv->status); - /* start card; "initialize" will load runtime ucode */ iwl_nic_start(priv); @@ -1836,6 +1951,9 @@ static void iwl_bg_alive_start(struct work_struct *data) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + /* enable dram interrupt */ + iwl_reset_ict(priv); + mutex_lock(&priv->mutex); iwl_alive_start(priv); mutex_unlock(&priv->mutex); @@ -1874,7 +1992,6 @@ static void iwl_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl_up(priv); mutex_unlock(&priv->mutex); - iwl_rfkill_set_hw_state(priv); } static void iwl_bg_restart(struct work_struct *data) @@ -1884,8 +2001,17 @@ static void iwl_bg_restart(struct work_struct *data) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - iwl_down(priv); - queue_work(priv->workqueue, &priv->up); + if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + mutex_lock(&priv->mutex); + priv->vif = NULL; + priv->is_open = 0; + mutex_unlock(&priv->mutex); + iwl_down(priv); + ieee80211_restart_hw(priv->hw); + } else { + iwl_down(priv); + queue_work(priv->workqueue, &priv->up); + } } static void iwl_bg_rx_replenish(struct work_struct *data) @@ -1903,7 +2029,7 @@ static void iwl_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl_post_associate(struct iwl_priv *priv) +void iwl_post_associate(struct iwl_priv *priv) { struct ieee80211_conf *conf = NULL; int ret = 0; @@ -1925,13 +2051,12 @@ static void iwl_post_associate(struct iwl_priv *priv) if (!priv->vif || !priv->is_open) return; - iwl_power_cancel_timeout(priv); iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl_setup_rxon_timing(priv); ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, @@ -1944,7 +2069,9 @@ static void iwl_post_associate(struct iwl_priv *priv) iwl_set_rxon_ht(priv, &priv->current_ht_config); - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", @@ -1966,7 +2093,7 @@ static void iwl_post_associate(struct iwl_priv *priv) } - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: @@ -1999,7 +2126,7 @@ static 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_enable_management(priv); + iwl_power_update_mode(priv, 0); /* Enable Rx differential gain and sensitivity calibrations */ iwl_chain_noise_reset(priv); @@ -2042,8 +2169,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); - iwl_rfkill_set_hw_state(priv); - if (ret) return ret; @@ -2052,9 +2177,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_INFO(priv, "Start UP work done.\n"); - if (test_bit(STATUS_IN_SUSPEND, &priv->status)) - return 0; - /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from * mac80211 will not be run successfully. */ ret = wait_event_interruptible_timeout(priv->wait_command_queue, @@ -2080,10 +2202,8 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "enter\n"); - if (!priv->is_open) { - IWL_DEBUG_MAC80211(priv, "leave - skip\n"); + if (!priv->is_open) return; - } priv->is_open = 0; @@ -2123,175 +2243,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -static int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); - - if (priv->vif) { - IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - } - - if (iwl_set_mode(priv, conf->type) == -EAGAIN) - /* we are not ready, will run again when ready */ - set_bit(STATUS_MODE_PENDING, &priv->status); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - -/** - * iwl_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ -static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - unsigned long flags = 0; - int ret = 0; - u16 ch; - int scan_active = 0; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - conf->channel->hw_value, changed); - - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - scan_active = 1; - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - } - - - /* during scanning mac80211 will delay channel setting until - * scan finish with changed = 0 - */ - if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - if (scan_active) - goto set_ch_out; - - ch = ieee80211_frequency_to_channel(conf->channel->center_freq); - ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - ret = -EINVAL; - goto set_ch_out; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d in band %d not " - "IBSS channel\n", - conf->channel->hw_value, conf->channel->band); - ret = -EINVAL; - goto set_ch_out; - } - - priv->current_ht_config.is_ht = conf_is_ht(conf); - - spin_lock_irqsave(&priv->lock, flags); - - - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) - priv->staging_rxon.flags = 0; - - iwl_set_rxon_channel(priv, conf->channel); - - iwl_set_flags_for_band(priv, conf->channel->band); - spin_unlock_irqrestore(&priv->lock, flags); - set_ch_out: - /* The list of supported rates and rate mask can be different - * for each band; since the band may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) - ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); - else - ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); - if (ret) - IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); - - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", - priv->tx_power_user_lmt, conf->power_level); - - iwl_set_tx_power(priv, conf->power_level, false); - } - - /* call to ensure that 4965 rx_chain is set properly in monitor mode */ - iwl_set_rxon_chain(priv); - - if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { - if (conf->radio_enabled && - iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " - "waiting for uCode\n"); - goto out; - } - - if (!conf->radio_enabled) - iwl_radio_kill_sw_disable_radio(priv); - } - - if (!conf->radio_enabled) { - IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); - goto out; - } - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - goto out; - } - - if (scan_active) - goto out; - - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwl_commit_rxon(priv); - else - IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); - - -out: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - return ret; -} - -static void iwl_config_ap(struct iwl_priv *priv) +void iwl_config_ap(struct iwl_priv *priv) { int ret = 0; unsigned long flags; @@ -2304,7 +2256,7 @@ static void iwl_config_ap(struct iwl_priv *priv) /* RXON - unassoc (to set timing command) */ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); /* RXON Timing */ iwl_setup_rxon_timing(priv); @@ -2314,7 +2266,8 @@ static void iwl_config_ap(struct iwl_priv *priv) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); /* FIXME: what should be the assoc_id for AP? */ priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); @@ -2340,7 +2293,7 @@ static void iwl_config_ap(struct iwl_priv *priv) } /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); spin_lock_irqsave(&priv->lock, flags); iwl_activate_qos(priv, 1); spin_unlock_irqrestore(&priv->lock, flags); @@ -2353,194 +2306,6 @@ static void iwl_config_ap(struct iwl_priv *priv) * clear sta table, add BCAST sta... */ } - -static int iwl_mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - int rc; - - if (conf == NULL) - return -EIO; - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); - return 0; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) - return -ENOMEM; - mutex_lock(&priv->mutex); - rc = iwl_mac_beacon_update(hw, beacon); - mutex_unlock(&priv->mutex); - if (rc) - return rc; - } - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - - if (conf->bssid) - IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); - -/* - * very dubious code was here; the probe filtering flag is never set: - * - if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && - !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { - */ - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - if (!conf->bssid) { - conf->bssid = priv->mac_addr; - memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", - conf->bssid); - } - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); - } - - if (iwl_is_rfkill(priv)) - goto done; - - if (conf->bssid && !is_zero_ether_addr(conf->bssid) && - !is_multicast_ether_addr(conf->bssid)) { - /* If there is currently a HW scan going on in the background - * then we need to cancel it else the RXON below will fail. */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress " - "after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - mutex_unlock(&priv->mutex); - return -EAGAIN; - } - memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); - - /* TODO: Audit driver for usage of these members and see - * if mac80211 deprecates them (priv->bssid looks like it - * shouldn't be there, but I haven't scanned the IBSS code - * to verify) - jpk */ - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_config_ap(priv); - else { - rc = iwl_commit_rxon(priv); - if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) - iwl_rxon_add_station( - priv, priv->active_rxon.bssid_addr, 1); - } - - } else { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); - } - - done: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - - return 0; -} - -static void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - if (iwl_is_ready_rf(priv)) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); - } - if (priv->vif == conf->vif) { - priv->vif = NULL; - memset(priv->bssid, 0, ETH_ALEN); - } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -} - -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) -static void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - } - - if (changes & BSS_CHANGED_HT) { - iwl_ht_conf(priv, bss_conf); - iwl_set_rxon_chain(priv); - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - /* This should never happen as this function should - * never be called from interrupt context. */ - if (WARN_ON_ONCE(in_interrupt())) - return; - 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; - - /* we have just associated, don't start scan too early - * leave time for EAPOL exchange to complete - */ - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - mutex_lock(&priv->mutex); - iwl_post_associate(priv); - mutex_unlock(&priv->mutex); - } else { - priv->assoc_id = 0; - IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); - } - } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); - iwl_send_rxon_assoc(priv); - } - -} - static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key) @@ -2623,49 +2388,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - int q; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); - return 0; - } - - q = AC_NUM - 1 - queue; - - spin_lock_irqsave(&priv->lock, flags); - - priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->txop * 32)); - - priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; - priv->qos_data.qos_active = 1; - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_activate_qos(priv, 1); - else if (priv->assoc_id && iwl_is_associated(priv)) - iwl_activate_qos(priv, 0); - - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn) @@ -2708,41 +2430,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return 0; } -static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - int i, avail; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; - q = &txq->q; - avail = iwl_queue_space(q); - - stats[i].len = q->n_window - avail; - stats[i].limit = q->n_window - q->high_mark; - stats[i].count = q->n_window; - - } - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} - static int iwl_mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -2755,120 +2442,6 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, return 0; } -static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - spin_lock_irqsave(&priv->lock, flags); - memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = 0; - priv->assoc_capability = 0; - priv->assoc_station_added = 0; - - /* new association get rid of ibss beacon skb */ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = NULL; - - priv->beacon_int = priv->hw->conf.beacon_int; - priv->timestamp = 0; - if ((priv->iw_mode == NL80211_IFTYPE_STATION)) - priv->beacon_int = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); - } - - iwl_power_update_mode(priv, 0); - - /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - - /* switch to CAM during association period. - * the ucode will block any association/authentication - * frome during assiciation period if it can not hear - * the AP because of PM. the timer enable PM back is - * association do not complete - */ - if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN | - IEEE80211_CHAN_RADAR)) - iwl_power_disable_management(priv, 3000); - - IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); - mutex_unlock(&priv->mutex); - return; - } - - iwl_set_rate(priv); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - -static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - priv->assoc_id = 0; - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - iwl_post_associate(priv); - - - return 0; -} - /***************************************************************************** * * sysfs attributes @@ -2888,7 +2461,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%08X\n", priv->debug_level); } @@ -2896,7 +2469,7 @@ static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -2919,7 +2492,7 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_version(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); struct iwl_alive_resp *palive = &priv->card_alive; ssize_t pos = 0; u16 eeprom_ver; @@ -2936,8 +2509,10 @@ static ssize_t show_version(struct device *d, if (priv->eeprom) { eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); - pos += sprintf(buf + pos, "EEPROM version: 0x%x\n", - eeprom_ver); + 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"); } @@ -2950,7 +2525,7 @@ 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) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_alive(priv)) return -EAGAIN; @@ -2963,7 +2538,7 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_ready_rf(priv)) return sprintf(buf, "off\n"); @@ -2975,7 +2550,7 @@ static ssize_t store_tx_power(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -2993,7 +2568,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); } @@ -3002,7 +2577,7 @@ static ssize_t store_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; u32 flags; int ret = strict_strtoul(buf, 0, &val); @@ -3018,7 +2593,7 @@ static ssize_t store_flags(struct device *d, else { IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); @@ -3031,7 +2606,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.filter_flags)); @@ -3041,7 +2616,7 @@ static ssize_t store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; u32 filter_flags; int ret = strict_strtoul(buf, 0, &val); @@ -3059,7 +2634,7 @@ static ssize_t store_filter_flags(struct device *d, "0x%04X\n", filter_flags); priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); @@ -3102,32 +2677,37 @@ static ssize_t show_power_level(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); int mode = priv->power_data.user_power_setting; - int system = priv->power_data.system_power_setting; int level = priv->power_data.power_mode; char *p = buf; - switch (system) { - case IWL_POWER_SYS_AUTO: - p += sprintf(p, "SYSTEM:auto"); - break; - case IWL_POWER_SYS_AC: - p += sprintf(p, "SYSTEM:ac"); - break; - case IWL_POWER_SYS_BATTERY: - p += sprintf(p, "SYSTEM:battery"); - break; - } - - p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ? - "fixed" : "auto"); - p += sprintf(p, "\tINDEX:%d", level); - p += sprintf(p, "\n"); + p += sprintf(p, "INDEX:%d\t", level); + p += sprintf(p, "USER:%d\n", mode); 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) @@ -3183,14 +2763,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->up, iwl_bg_up); INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); - INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); iwl_setup_scan_deferred_work(priv); - iwl_setup_power_deferred_work(priv); if (priv->cfg->ops->lib->setup_deferred_work) priv->cfg->ops->lib->setup_deferred_work(priv); @@ -3199,8 +2777,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) priv->statistics_periodic.data = (unsigned long)priv; priv->statistics_periodic.function = iwl_bg_statistics_periodic; - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); + if (!priv->cfg->use_isr_legacy) + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); + else + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet_legacy, (unsigned long)priv); } static void iwl_cancel_deferred_work(struct iwl_priv *priv) @@ -3210,7 +2792,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); - cancel_delayed_work_sync(&priv->set_power_save); cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); @@ -3227,7 +2808,7 @@ static struct attribute *iwl_sysfs_entries[] = { &dev_attr_debug_level.attr, #endif &dev_attr_version.attr, - + &dev_attr_qos.attr, NULL }; @@ -3243,7 +2824,6 @@ static struct ieee80211_ops iwl_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .config_interface = iwl_mac_config_interface, .configure_filter = iwl_configure_filter, .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, @@ -3291,6 +2871,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; priv->pci_dev = pdev; + priv->inta_mask = CSR_INI_SET_MASK; #ifdef CONFIG_IWLWIFI_DEBUG priv->debug_level = priv->cfg->mod_params->debug; @@ -3341,6 +2922,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (unsigned long long) pci_resource_len(pdev, 0)); IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); + /* this spin lock will be used in apm_ops.init and EEPROM access + * we should init now + */ + spin_lock_init(&priv->reg_lock); iwl_hw_detect(priv); IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", priv->cfg->name, priv->hw_rev); @@ -3349,6 +2934,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + iwl_prepare_card_hw(priv); + if (!priv->hw_ready) { + IWL_WARN(priv, "Failed, HW not ready\n"); + goto out_iounmap; + } + /* amp init */ err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { @@ -3390,18 +2981,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_free_eeprom; /* At this point both hw and priv are initialized. */ - /********************************** - * 7. Initialize module parameters - **********************************/ - - /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (priv->cfg->mod_params->disable) { - set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO(priv, "Radio disabled.\n"); - } - /******************** - * 8. Setup services + * 7. Setup services ********************/ spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); @@ -3409,8 +2990,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_enable_msi(priv->pci_dev); - err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, - DRV_NAME, priv); + iwl_alloc_isr_ict(priv); + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, + IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); goto out_disable_msi; @@ -3425,7 +3007,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_setup_rx_handlers(priv); /********************************** - * 9. Setup and register mac80211 + * 8. Setup and register mac80211 **********************************/ /* enable interrupts if needed: hw bug w/a */ @@ -3443,7 +3025,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = iwl_dbgfs_register(priv, DRV_NAME); if (err) - IWL_ERR(priv, "failed to create debugfs files\n"); + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) @@ -3451,12 +3033,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) else set_bit(STATUS_RF_KILL_HW, &priv->status); - err = iwl_rfkill_init(priv); - if (err) - IWL_ERR(priv, "Unable to initialize RFKILL system. " - "Ignoring error: %d\n", err); - else - iwl_rfkill_set_hw_state(priv); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, + test_bit(STATUS_RF_KILL_HW, &priv->status)); iwl_power_initialize(priv); return 0; @@ -3467,6 +3045,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); out_free_irq: free_irq(priv->pci_dev->irq, priv); + iwl_free_isr_ict(priv); out_disable_msi: pci_disable_msi(priv->pci_dev); iwl_uninit_drv(priv); @@ -3519,7 +3098,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_synchronize_irq(priv); - iwl_rfkill_unregister(priv); iwl_dealloc_ucode_pci(priv); if (priv->rxq.bd) @@ -3548,51 +3126,14 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_uninit_drv(priv); + iwl_free_isr_ict(priv); + if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); ieee80211_free_hw(priv->hw); } -#ifdef CONFIG_PM - -static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - - if (priv->is_open) { - set_bit(STATUS_IN_SUSPEND, &priv->status); - iwl_mac_stop(priv->hw); - priv->is_open = 1; - } - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int iwl_pci_resume(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); - iwl_enable_interrupts(priv); - - if (priv->is_open) - iwl_mac_start(priv->hw); - - clear_bit(STATUS_IN_SUSPEND, &priv->status); - return 0; -} - -#endif /* CONFIG_PM */ /***************************************************************************** * diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 735f3f19928c..a5d63672ad39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -857,7 +857,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_enable_management(priv); + iwl_power_update_mode(priv, 0); } 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 29d40746da6a..c87033bf3ad2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -614,8 +614,18 @@ enum { #define RXON_FLG_CHANNEL_MODE_POS (25) #define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25) -#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK cpu_to_le32(0x1 << 25) -#define RXON_FLG_CHANNEL_MODE_MIXED_MSK cpu_to_le32(0x2 << 25) + +/* channel mode */ +enum { + CHANNEL_MODE_LEGACY = 0, + CHANNEL_MODE_PURE_40 = 1, + CHANNEL_MODE_MIXED = 2, + CHANNEL_MODE_RESERVED = 3, +}; +#define RXON_FLG_CHANNEL_MODE_LEGACY cpu_to_le32(CHANNEL_MODE_LEGACY << RXON_FLG_CHANNEL_MODE_POS) +#define RXON_FLG_CHANNEL_MODE_PURE_40 cpu_to_le32(CHANNEL_MODE_PURE_40 << RXON_FLG_CHANNEL_MODE_POS) +#define RXON_FLG_CHANNEL_MODE_MIXED cpu_to_le32(CHANNEL_MODE_MIXED << RXON_FLG_CHANNEL_MODE_POS) + /* CTS to self (if spec allows) flag */ #define RXON_FLG_SELF_CTS_EN cpu_to_le32(0x1<<30) @@ -1057,7 +1067,7 @@ struct iwl_addsta_cmd { * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ __le16 tid_disable_tx; - __le16 reserved1; + __le16 rate_n_flags; /* 3945 only */ /* TID for which to add block-ack support. * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ @@ -1903,6 +1913,18 @@ struct iwl_link_qual_general_params { u8 start_rate_index[LINK_QUAL_AC_NUM]; } __attribute__ ((packed)); +#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ +#define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535) +#define LINK_QUAL_AGG_TIME_LIMIT_MIN (0) + +#define LINK_QUAL_AGG_DISABLE_START_DEF (3) +#define LINK_QUAL_AGG_DISABLE_START_MAX (255) +#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_MIN (0) + /** * struct iwl_link_qual_agg_params * @@ -2469,11 +2491,12 @@ struct iwl_ssid_ie { u8 ssid[32]; } __attribute__ ((packed)); -#define PROBE_OPTION_MAX_API1 0x4 -#define PROBE_OPTION_MAX 0x14 +#define PROBE_OPTION_MAX_3945 4 +#define PROBE_OPTION_MAX 20 #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 +#define IWL_MAX_PROBE_REQUEST 200 /* * REPLY_SCAN_CMD = 0x80 (command) @@ -2552,7 +2575,7 @@ struct iwl3945_scan_cmd { struct iwl3945_tx_cmd tx_cmd; /* For directed active scans (set to all-0s otherwise) */ - struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; + struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945]; /* * Probe request frame, followed by channel list. diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c54fb93e9d72..f9d16ca5b3d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -36,9 +36,9 @@ #include "iwl-debug.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-rfkill.h" #include "iwl-power.h" #include "iwl-sta.h" +#include "iwl-helpers.h" MODULE_DESCRIPTION("iwl core"); @@ -59,6 +59,8 @@ MODULE_LICENSE("GPL"); IWL_RATE_##pp##M_INDEX, \ IWL_RATE_##np##M_INDEX } +static irqreturn_t iwl_isr(int irq, void *data); + /* * Parameter order: * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate @@ -273,6 +275,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force) } EXPORT_SYMBOL(iwl_activate_qos); +/* + * AC CWmin CW max AIFSN TXOP Limit TXOP Limit + * (802.11b) (802.11a/g) + * AC_BK 15 1023 7 0 0 + * AC_BE 15 1023 3 0 0 + * AC_VI 7 15 2 6.016ms 3.008ms + * AC_VO 3 7 2 3.264ms 1.504ms + */ void iwl_reset_qos(struct iwl_priv *priv) { u16 cw_min = 15; @@ -304,6 +314,7 @@ void iwl_reset_qos(struct iwl_priv *priv) if (priv->qos_data.qos_active) aifs = 3; + /* AC_BE */ priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; @@ -311,6 +322,7 @@ void iwl_reset_qos(struct iwl_priv *priv) priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; if (priv->qos_data.qos_active) { + /* AC_BK */ i = 1; priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); @@ -318,11 +330,12 @@ void iwl_reset_qos(struct iwl_priv *priv) priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; + /* AC_VI */ i = 2; priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16((cw_min + 1) / 2 - 1); priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); + cpu_to_le16(cw_min); priv->qos_data.def_qos_parm.ac[i].aifsn = 2; if (is_legacy) priv->qos_data.def_qos_parm.ac[i].edca_txop = @@ -332,11 +345,12 @@ void iwl_reset_qos(struct iwl_priv *priv) cpu_to_le16(3008); priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; + /* AC_VO */ i = 3; priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16((cw_min + 1) / 4 - 1); priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16((cw_max + 1) / 2 - 1); + cpu_to_le16((cw_min + 1) / 2 - 1); priv->qos_data.def_qos_parm.ac[i].aifsn = 2; priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; if (is_legacy) @@ -591,10 +605,10 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) return !(ch_info->fat_extension_channel & - IEEE80211_CHAN_NO_FAT_ABOVE); + IEEE80211_CHAN_NO_HT40PLUS); else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) return !(ch_info->fat_extension_channel & - IEEE80211_CHAN_NO_FAT_BELOW); + IEEE80211_CHAN_NO_HT40MINUS); return 0; } @@ -605,19 +619,23 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; if ((!iwl_ht_conf->is_ht) || - (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || - (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE)) + (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ)) return 0; + /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 + * the bit will not set if it is pure 40MHz case + */ if (sta_ht_inf) { - if ((!sta_ht_inf->ht_supported) || - (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))) + if (!sta_ht_inf->ht_supported) return 0; } - return iwl_is_channel_extension(priv, priv->band, - le16_to_cpu(priv->staging_rxon.channel), - iwl_ht_conf->extension_chan_offset); + if (iwl_ht_conf->ht_protection & IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) + return 1; + else + 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); @@ -735,6 +753,8 @@ int iwl_full_rxon_required(struct iwl_priv *priv) priv->active_rxon.ofdm_ht_single_stream_basic_rates) || (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || + (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates != + priv->active_rxon.ofdm_ht_triple_stream_basic_rates) || (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) return 1; @@ -785,43 +805,53 @@ EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) { struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - u32 val; if (!ht_info->is_ht) { - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | - RXON_FLG_CHANNEL_MODE_PURE_40_MSK | + rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | RXON_FLG_FAT_PROT_MSK | RXON_FLG_HT_PROT_MSK); return; } - /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ - if (iwl_is_fat_tx_allowed(priv, NULL)) - rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK; - else - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | - RXON_FLG_CHANNEL_MODE_PURE_40_MSK); + /* FIXME: if the definition of ht_protection changed, the "translation" + * will be needed for rxon->flags + */ + rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); - /* Note: control channel is opposite of extension channel */ - switch (ht_info->extension_chan_offset) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; - break; - case IEEE80211_HT_PARAM_CHA_SEC_NONE: - default: - rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; - break; + /* Set up channel bandwidth: + * 20 MHz only, 20/40 mixed or pure 40 if fat 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 (rxon->flags & RXON_FLG_FAT_PROT_MSK) + rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; + else { + /* Note: control channel is opposite of extension channel */ + switch (ht_info->extension_chan_offset) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); + rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; + rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; + break; + case IEEE80211_HT_PARAM_CHA_SEC_NONE: + default: + /* channel location only valid if in Mixed mode */ + IWL_ERR(priv, "invalid extension channel offset\n"); + break; + } + } + } else { + rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; } - val = ht_info->ht_protection; - - rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS); - - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X " "rxon flags 0x%X operation mode :0x%X " @@ -901,10 +931,11 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) * never called for monitor mode. The only way mac80211 informs us about * monitor mode is through configuring filters (call to configure_filter). */ -static bool iwl_is_monitor_mode(struct iwl_priv *priv) +bool iwl_is_monitor_mode(struct iwl_priv *priv) { return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); } +EXPORT_SYMBOL(iwl_is_monitor_mode); /** * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image @@ -956,10 +987,10 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) if (iwl_is_monitor_mode(priv) && !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { - rx_chain = 0x07 << RXON_RX_CHAIN_VALID_POS; - rx_chain |= 0x06 << RXON_RX_CHAIN_FORCE_SEL_POS; - rx_chain |= 0x07 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; - rx_chain |= 0x01 << RXON_RX_CHAIN_DRIVER_FORCE_POS; + rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; + rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; + rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; + rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; } priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); @@ -1068,11 +1099,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) RXON_FILTER_ACCEPT_GRP_MSK; break; - case NL80211_IFTYPE_MONITOR: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; - priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | - RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - break; default: IWL_ERR(priv, "Unsupported interface type %d\n", mode); break; @@ -1111,16 +1137,18 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) priv->staging_rxon.cck_basic_rates = (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | - RXON_FLG_CHANNEL_MODE_PURE_40_MSK); + /* clear both MIX and PURE40 mode flag */ + priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | + RXON_FLG_CHANNEL_MODE_PURE_40); memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; + priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; } EXPORT_SYMBOL(iwl_connection_init_rx_config); -void iwl_set_rate(struct iwl_priv *priv) +static void iwl_set_rate(struct iwl_priv *priv) { const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; @@ -1166,7 +1194,6 @@ void iwl_set_rate(struct iwl_priv *priv) priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -EXPORT_SYMBOL(iwl_set_rate); void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -1230,11 +1257,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv) IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); - if (iwl_is_associated(priv)) { - memcpy(&priv->recovery_rxon, &priv->active_rxon, - sizeof(priv->recovery_rxon)); - priv->error_recovering = 1; - } if (priv->cfg->mod_params->restart_fw) queue_work(priv->workqueue, &priv->restart); } @@ -1298,19 +1320,20 @@ 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_SUPPORTS_PS; + IEEE80211_HW_SPECTRUM_MGMT; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->custom_regulatory = true; - hw->wiphy->max_scan_ssids = 1; + + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; + /* we create the 802.11 header and a zero-length SSID element */ + hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; - hw->conf.beacon_int = 100; hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) @@ -1357,7 +1380,6 @@ int iwl_init_drv(struct iwl_priv *priv) priv->ibss_beacon = NULL; spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data.lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -1378,7 +1400,9 @@ int iwl_init_drv(struct iwl_priv *priv) priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; /* Choose which receivers/antennas to use */ - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + iwl_init_scan_params(priv); iwl_reset_qos(priv); @@ -1475,11 +1499,273 @@ 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, CSR_INI_SET_MASK); + iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); } EXPORT_SYMBOL(iwl_enable_interrupts); -irqreturn_t iwl_isr(int irq, void *data) + +#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) + +/* Free dram table */ +void iwl_free_isr_ict(struct iwl_priv *priv) +{ + if (priv->ict_tbl_vir) { + pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) + + PAGE_SIZE, priv->ict_tbl_vir, + priv->ict_tbl_dma); + priv->ict_tbl_vir = NULL; + } +} +EXPORT_SYMBOL(iwl_free_isr_ict); + + +/* allocate dram shared table it is a PAGE_SIZE aligned + * also reset all data related to ICT table interrupt. + */ +int iwl_alloc_isr_ict(struct iwl_priv *priv) +{ + + if (priv->cfg->use_isr_legacy) + return 0; + /* allocate shrared data table */ + priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) * + ICT_COUNT) + PAGE_SIZE, + &priv->ict_tbl_dma); + if (!priv->ict_tbl_vir) + return -ENOMEM; + + /* align table to PAGE_SIZE boundry */ + priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); + + IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", + (unsigned long long)priv->ict_tbl_dma, + (unsigned long long)priv->aligned_ict_tbl_dma, + (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); + + priv->ict_tbl = priv->ict_tbl_vir + + (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); + + IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", + priv->ict_tbl, priv->ict_tbl_vir, + (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); + + /* reset table and index to all 0 */ + memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + priv->ict_index = 0; + + /* add periodic RX interrupt */ + priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; + return 0; +} +EXPORT_SYMBOL(iwl_alloc_isr_ict); + +/* Device is going up inform it about using ICT interrupt table, + * also we need to tell the driver to start using ICT interrupt. + */ +int iwl_reset_ict(struct iwl_priv *priv) +{ + u32 val; + unsigned long flags; + + if (!priv->ict_tbl_vir) + return 0; + + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + + memset(&priv->ict_tbl[0],0, sizeof(u32) * ICT_COUNT); + + val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; + + val |= CSR_DRAM_INT_TBL_ENABLE; + val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; + + IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " + "aligned dma address %Lx\n", + val, (unsigned long long)priv->aligned_ict_tbl_dma); + + iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); + priv->use_ict = true; + priv->ict_index = 0; + iwl_write32(priv, CSR_INT, priv->inta_mask); + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL(iwl_reset_ict); + +/* Device is going down disable ict interrupt usage */ +void iwl_disable_ict(struct iwl_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->use_ict = false; + spin_unlock_irqrestore(&priv->lock, flags); +} +EXPORT_SYMBOL(iwl_disable_ict); + +/* interrupt handler using ict table, with this interrupt driver will + * stop using INTA register to get device's interrupt, reading this register + * is expensive, device will write interrupts in ICT dram table, increment + * index then will fire interrupt to driver, driver will OR all ICT table + * entries from current index up to table entry with 0 value. the result is + * the interrupt we need to service, driver will set the entries back to 0 and + * set index. + */ +irqreturn_t iwl_isr_ict(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; + u32 val = 0; + + if (!priv) + return IRQ_NONE; + + /* dram interrupt table not set yet, + * use legacy interrupt. + */ + if (!priv->use_ict) + return iwl_isr(irq, data); + + spin_lock(&priv->lock); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. + */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!priv->ict_tbl[priv->ict_index]) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + goto none; + } + + /* read all entries that not 0 start with ict_index */ + while (priv->ict_tbl[priv->ict_index]) { + + val |= priv->ict_tbl[priv->ict_index]; + IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", + priv->ict_index, + priv->ict_tbl[priv->ict_index]); + priv->ict_tbl[priv->ict_index] = 0; + priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, + ICT_COUNT); + + } + + /* We should not get this value, just ignore it. */ + if (val == 0xffffffff) + val = 0; + + inta = (0xff & val) | ((0xff00 & val) << 16); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", + inta, inta_mask, val); + + inta &= priv->inta_mask; + priv->inta |= inta; + + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta)) + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { + /* Allow interrupt if was disabled by this handler and + * no tasklet was schedules, We should not enable interrupt, + * tasklet will enable it. + */ + iwl_enable_interrupts(priv); + } + + spin_unlock(&priv->lock); + return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. + * only Re-enable if disabled by irq. + */ + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + spin_unlock(&priv->lock); + return IRQ_NONE; +} +EXPORT_SYMBOL(iwl_isr_ict); + + +static irqreturn_t iwl_isr(int irq, void *data) +{ + struct iwl_priv *priv = data; + u32 inta, inta_mask; +#ifdef CONFIG_IWLWIFI_DEBUG + u32 inta_fh; +#endif + if (!priv) + return IRQ_NONE; + + spin_lock(&priv->lock); + + /* Disable (but don't clear!) interrupts here to avoid + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(priv, CSR_INT); + + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ + if (!inta) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); + goto none; + } + + if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { + /* Hardware disappeared. It might have already raised + * an interrupt */ + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + goto unplugged; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + if (priv->debug_level & (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); + } +#endif + + priv->inta |= inta; + /* iwl_irq_tasklet() will service interrupts and re-enable them */ + if (likely(inta)) + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + unplugged: + spin_unlock(&priv->lock); + return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. */ + /* only Re-enable if diabled by irq and no schedules tasklet. */ + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); + + spin_unlock(&priv->lock); + return IRQ_NONE; +} + +irqreturn_t iwl_isr_legacy(int irq, void *data) { struct iwl_priv *priv = data; u32 inta, inta_mask; @@ -1536,7 +1822,7 @@ irqreturn_t iwl_isr(int irq, void *data) spin_unlock(&priv->lock); return IRQ_NONE; } -EXPORT_SYMBOL(iwl_isr); +EXPORT_SYMBOL(iwl_isr_legacy); int iwl_send_bt_config(struct iwl_priv *priv) { @@ -1580,10 +1866,6 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log @@ -1599,8 +1881,6 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 } } - iwl_release_nic_access(priv); - return ret; } @@ -1618,10 +1898,6 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWL49_RTC_INST_LOWER_BOUND); @@ -1642,8 +1918,6 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, } } - iwl_release_nic_access(priv); - if (!errcnt) IWL_DEBUG_INFO(priv, "ucode image in INSTRUCTION memory is good\n"); @@ -1752,7 +2026,6 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 data2, line; u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; - int ret; if (priv->ucode_type == UCODE_INIT) base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); @@ -1764,12 +2037,6 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) return; } - ret = iwl_grab_nic_access(priv); - if (ret) { - IWL_WARN(priv, "Can not read from adapter at this time.\n"); - return; - } - count = iwl_read_targ_mem(priv, base); if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { @@ -1796,7 +2063,6 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, ilink1, ilink2); - iwl_release_nic_access(priv); } EXPORT_SYMBOL(iwl_dump_nic_error_log); @@ -1805,7 +2071,6 @@ EXPORT_SYMBOL(iwl_dump_nic_error_log); /** * iwl_print_event_log - Dump error event log to syslog * - * NOTE: Must be called with iwl_grab_nic_access() already obtained! */ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) @@ -1851,7 +2116,6 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, void iwl_dump_nic_event_log(struct iwl_priv *priv) { - int ret; u32 base; /* SRAM byte address of event log header */ u32 capacity; /* event log capacity in # entries */ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ @@ -1869,12 +2133,6 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) return; } - ret = iwl_grab_nic_access(priv); - if (ret) { - IWL_WARN(priv, "Can not read from adapter at this time.\n"); - return; - } - /* event log header */ capacity = iwl_read_targ_mem(priv, base); mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); @@ -1886,7 +2144,6 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) /* bail out if nothing in log */ if (size == 0) { IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - iwl_release_nic_access(priv); return; } @@ -1901,7 +2158,6 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) /* (then/else) start at top of log */ iwl_print_event_log(priv, 0, next_entry, mode); - iwl_release_nic_access(priv); } EXPORT_SYMBOL(iwl_dump_nic_event_log); @@ -1954,126 +2210,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) } EXPORT_SYMBOL(iwl_send_card_state); -void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) -{ - unsigned long flags; - - if (test_bit(STATUS_RF_KILL_SW, &priv->status)) - return; - - IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO OFF\n"); - - iwl_scan_cancel(priv); - /* FIXME: This is a workaround for AP */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_SW_BIT_RFKILL); - spin_unlock_irqrestore(&priv->lock, flags); - /* call the host command only if no hw rf-kill set */ - if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && - iwl_is_ready(priv)) - iwl_send_card_state(priv, - CARD_STATE_CMD_DISABLE, 0); - set_bit(STATUS_RF_KILL_SW, &priv->status); - /* make sure mac80211 stop sending Tx frame */ - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - } -} -EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio); - -int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) -{ - unsigned long flags; - - if (!test_bit(STATUS_RF_KILL_SW, &priv->status)) - return 0; - - IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO ON\n"); - - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - /* If the driver is up it will receive CARD_STATE_NOTIFICATION - * notification where it will clear SW rfkill status. - * Setting it here would break the handler. Only if the - * interface is down we can set here since we don't - * receive any further notification. - */ - if (!priv->is_open) - clear_bit(STATUS_RF_KILL_SW, &priv->status); - spin_unlock_irqrestore(&priv->lock, flags); - - /* wake up ucode */ - msleep(10); - - spin_lock_irqsave(&priv->lock, flags); - iwl_read32(priv, CSR_UCODE_DRV_GP1); - if (!iwl_grab_nic_access(priv)) - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - " - "disabled by HW switch\n"); - return 0; - } - - /* when driver is up while rfkill is on, it wont receive - * any CARD_STATE_NOTIFICATION notifications so we have to - * restart it in here - */ - if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) { - clear_bit(STATUS_RF_KILL_SW, &priv->status); - if (!iwl_is_rfkill(priv)) - queue_work(priv->workqueue, &priv->up); - } - - /* If the driver is already loaded, it will receive - * CARD_STATE_NOTIFICATION notifications and the handler will - * call restart to reload the driver. - */ - return 1; -} -EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio); - -void iwl_bg_rf_kill(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill); - - wake_up_interruptible(&priv->wait_command_queue); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - - if (!iwl_is_rfkill(priv)) { - IWL_DEBUG_RF_KILL(priv, - "HW and/or SW RF Kill no longer active, restarting " - "device\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && - test_bit(STATUS_ALIVE, &priv->status)) - queue_work(priv->workqueue, &priv->restart); - } else { - /* make sure mac80211 stop sending Tx frame */ - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - - if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) - IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - " - "disabled by SW switch\n"); - else - IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" - "Kill switch must be turned off for " - "wireless networking to work.\n"); - } - mutex_unlock(&priv->mutex); - iwl_rfkill_set_hw_state(priv); -} -EXPORT_SYMBOL(iwl_bg_rf_kill); - void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -2112,3 +2248,642 @@ void iwl_rx_reply_error(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_reply_error); +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) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + int q; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + if (queue >= AC_NUM) { + IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); + return 0; + } + + q = AC_NUM - 1 - queue; + + spin_lock_irqsave(&priv->lock, flags); + + priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); + priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); + priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; + priv->qos_data.def_qos_parm.ac[q].edca_txop = + cpu_to_le16((params->txop * 32)); + + priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; + priv->qos_data.qos_active = 1; + + if (priv->iw_mode == NL80211_IFTYPE_AP) + iwl_activate_qos(priv, 1); + else if (priv->assoc_id && iwl_is_associated(priv)) + iwl_activate_qos(priv, 0); + + spin_unlock_irqrestore(&priv->lock, flags); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + return 0; +} +EXPORT_SYMBOL(iwl_mac_conf_tx); + +static void iwl_ht_conf(struct iwl_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_sta_ht_cap *ht_conf; + struct iwl_ht_info *iwl_conf = &priv->current_ht_config; + struct ieee80211_sta *sta; + + IWL_DEBUG_MAC80211(priv, "enter: \n"); + + if (!iwl_conf->is_ht) + return; + + + /* + * It is totally wrong to base global information on something + * that is valid only when associated, alas, this driver works + * that way and I don't know how to fix it. + */ + + rcu_read_lock(); + sta = ieee80211_find_sta(priv->hw, priv->bssid); + if (!sta) { + rcu_read_unlock(); + return; + } + ht_conf = &sta->ht_cap; + + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) + iwl_conf->sgf |= HT_SHORT_GI_20MHZ; + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) + iwl_conf->sgf |= HT_SHORT_GI_40MHZ; + + iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); + iwl_conf->max_amsdu_size = + !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); + + iwl_conf->supported_chan_width = + !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); + + /* + * XXX: The HT configuration needs to be moved into iwl_mac_config() + * to be done there correctly. + */ + + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + if (conf_is_ht40_minus(&priv->hw->conf)) + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + 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 (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; + + iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); + + memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); + + iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; + iwl_conf->ht_protection = + bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; + iwl_conf->non_GF_STA_present = + !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + + rcu_read_unlock(); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} + +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) +void iwl_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + int ret; + + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); + + if (!iwl_is_alive(priv)) + return; + + mutex_lock(&priv->mutex); + + if (changes & BSS_CHANGED_BEACON && + priv->iw_mode == NL80211_IFTYPE_AP) { + dev_kfree_skb(priv->ibss_beacon); + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); + } + + if ((changes & BSS_CHANGED_BSSID) && !iwl_is_rfkill(priv)) { + /* If there is currently a HW scan going on in the background + * then we need to cancel it else the RXON below will fail. */ + if (iwl_scan_cancel_timeout(priv, 100)) { + IWL_WARN(priv, "Aborted scan still in progress " + "after 100ms\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); + mutex_unlock(&priv->mutex); + return; + } + memcpy(priv->staging_rxon.bssid_addr, + bss_conf->bssid, ETH_ALEN); + + /* TODO: Audit driver for usage of these members and see + * if mac80211 deprecates them (priv->bssid looks like it + * shouldn't be there, but I haven't scanned the IBSS code + * to verify) - jpk */ + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + + if (priv->iw_mode == NL80211_IFTYPE_AP) + iwlcore_config_ap(priv); + else { + int rc = iwlcore_commit_rxon(priv); + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) + iwl_rxon_add_station( + priv, priv->active_rxon.bssid_addr, 1); + } + } else if (!iwl_is_rfkill(priv)) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + changes & BSS_CHANGED_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) + iwl_mac_beacon_update(hw, beacon); + } + + mutex_unlock(&priv->mutex); + + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + } + + if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + } + + if (changes & BSS_CHANGED_HT) { + iwl_ht_conf(priv, bss_conf); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + } + + if (changes & BSS_CHANGED_ASSOC) { + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); + /* This should never happen as this function should + * never be called from interrupt context. */ + if (WARN_ON_ONCE(in_interrupt())) + return; + 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; + + /* we have just associated, don't start scan too early + * leave time for EAPOL exchange to complete + */ + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + mutex_lock(&priv->mutex); + priv->cfg->ops->lib->post_associate(priv); + mutex_unlock(&priv->mutex); + } else { + priv->assoc_id = 0; + IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); + } + } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { + IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); + ret = iwl_send_rxon_assoc(priv); + if (!ret) + /* Sync active_rxon with latest change. */ + memcpy((void *)&priv->active_rxon, + &priv->staging_rxon, + sizeof(struct iwl_rxon_cmd)); + } + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_bss_info_changed); + +int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + __le64 timestamp; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); + return -EIO; + } + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = skb; + + priv->assoc_id = 0; + timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + priv->timestamp = le64_to_cpu(timestamp); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_reset_qos(priv); + + priv->cfg->ops->lib->post_associate(priv); + + + return 0; +} +EXPORT_SYMBOL(iwl_mac_beacon_update); + +int iwl_set_mode(struct iwl_priv *priv, int mode) +{ + if (mode == NL80211_IFTYPE_ADHOC) { + const struct iwl_channel_info *ch_info; + + ch_info = iwl_get_channel_info(priv, + priv->band, + le16_to_cpu(priv->staging_rxon.channel)); + + if (!ch_info || !is_channel_ibss(ch_info)) { + IWL_ERR(priv, "channel %d not IBSS channel\n", + le16_to_cpu(priv->staging_rxon.channel)); + return -EINVAL; + } + } + + iwl_connection_init_rx_config(priv, mode); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + + memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); + + iwl_clear_stations_table(priv); + + /* dont commit rxon if rf-kill is on*/ + if (!iwl_is_ready_rf(priv)) + return -EAGAIN; + + iwlcore_commit_rxon(priv); + + return 0; +} +EXPORT_SYMBOL(iwl_set_mode); + +int iwl_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + + IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); + + if (priv->vif) { + IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); + return -EOPNOTSUPP; + } + + spin_lock_irqsave(&priv->lock, flags); + priv->vif = conf->vif; + priv->iw_mode = conf->type; + + spin_unlock_irqrestore(&priv->lock, flags); + + mutex_lock(&priv->mutex); + + if (conf->mac_addr) { + IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + } + + if (iwl_set_mode(priv, conf->type) == -EAGAIN) + /* we are not ready, will run again when ready */ + set_bit(STATUS_MODE_PENDING, &priv->status); + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + return 0; +} +EXPORT_SYMBOL(iwl_mac_add_interface); + +void iwl_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct iwl_priv *priv = hw->priv; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + mutex_lock(&priv->mutex); + + if (iwl_is_ready_rf(priv)) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + if (priv->vif == conf->vif) { + priv->vif = NULL; + memset(priv->bssid, 0, ETH_ALEN); + } + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + +} +EXPORT_SYMBOL(iwl_mac_remove_interface); + +/** + * iwl_mac_config - mac80211 config callback + * + * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to + * be set inappropriately and the driver currently sets the hardware up to + * use it whenever needed. + */ +int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) +{ + struct iwl_priv *priv = hw->priv; + const struct iwl_channel_info *ch_info; + struct ieee80211_conf *conf = &hw->conf; + unsigned long flags = 0; + int ret = 0; + u16 ch; + int scan_active = 0; + + mutex_lock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", + conf->channel->hw_value, changed); + + if (unlikely(!priv->cfg->mod_params->disable_hw_scan && + test_bit(STATUS_SCANNING, &priv->status))) { + scan_active = 1; + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + } + + + /* during scanning mac80211 will delay channel setting until + * scan finish with changed = 0 + */ + if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + if (scan_active) + goto set_ch_out; + + ch = ieee80211_frequency_to_channel(conf->channel->center_freq); + ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto set_ch_out; + } + + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + !is_channel_ibss(ch_info)) { + IWL_ERR(priv, "channel %d in band %d not " + "IBSS channel\n", + conf->channel->hw_value, conf->channel->band); + ret = -EINVAL; + goto set_ch_out; + } + + priv->current_ht_config.is_ht = conf_is_ht(conf); + + spin_lock_irqsave(&priv->lock, flags); + + + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) + priv->staging_rxon.flags = 0; + + iwl_set_rxon_channel(priv, conf->channel); + + iwl_set_flags_for_band(priv, conf->channel->band); + spin_unlock_irqrestore(&priv->lock, flags); + set_ch_out: + /* The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists */ + 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 (ret) + IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + } + + /* call to ensure that 4965 rx_chain is set properly in monitor mode */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + goto out; + } + + if (scan_active) + goto out; + + if (memcmp(&priv->active_rxon, + &priv->staging_rxon, sizeof(priv->staging_rxon))) + iwlcore_commit_rxon(priv); + else + IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n"); + + +out: + IWL_DEBUG_MAC80211(priv, "leave\n"); + mutex_unlock(&priv->mutex); + return ret; +} +EXPORT_SYMBOL(iwl_mac_config); + +int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats) +{ + struct iwl_priv *priv = hw->priv; + int i, avail; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + unsigned long flags; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + spin_lock_irqsave(&priv->lock, flags); + + for (i = 0; i < AC_NUM; i++) { + txq = &priv->txq[i]; + q = &txq->q; + avail = iwl_queue_space(q); + + stats[i].len = q->n_window - avail; + stats[i].limit = q->n_window - q->high_mark; + stats[i].count = q->n_window; + + } + spin_unlock_irqrestore(&priv->lock, flags); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + + return 0; +} +EXPORT_SYMBOL(iwl_mac_get_tx_stats); + +void iwl_mac_reset_tsf(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + + mutex_lock(&priv->mutex); + IWL_DEBUG_MAC80211(priv, "enter\n"); + + spin_lock_irqsave(&priv->lock, flags); + memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_reset_qos(priv); + + spin_lock_irqsave(&priv->lock, flags); + priv->assoc_id = 0; + priv->assoc_capability = 0; + priv->assoc_station_added = 0; + + /* new association get rid of ibss beacon skb */ + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = NULL; + + priv->beacon_int = priv->vif->bss_conf.beacon_int; + priv->timestamp = 0; + if ((priv->iw_mode == NL80211_IFTYPE_STATION)) + priv->beacon_int = 0; + + spin_unlock_irqrestore(&priv->lock, flags); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + if (priv->iw_mode != NL80211_IFTYPE_AP) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); + mutex_unlock(&priv->mutex); + return; + } + + iwl_set_rate(priv); + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_mac_reset_tsf); + +#ifdef CONFIG_PM + +int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct iwl_priv *priv = pci_get_drvdata(pdev); + + /* + * This function is called when system goes into suspend state + * mac80211 will call iwl_mac_stop() from the mac80211 suspend function + * first but since iwl_mac_stop() has no knowledge of who the caller is, + * it will not call apm_ops.stop() to stop the DMA operation. + * Calling apm_ops.stop here to make sure we stop the DMA. + */ + priv->cfg->ops->lib->apm_ops.stop(priv); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} +EXPORT_SYMBOL(iwl_pci_suspend); + +int iwl_pci_resume(struct pci_dev *pdev) +{ + struct iwl_priv *priv = pci_get_drvdata(pdev); + int ret; + + pci_set_power_state(pdev, PCI_D0); + ret = pci_enable_device(pdev); + if (ret) + return ret; + pci_restore_state(pdev); + iwl_enable_interrupts(priv); + + return 0; +} +EXPORT_SYMBOL(iwl_pci_resume); + +#endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a8eac8c3c1fa..dabf663e36e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -85,7 +85,10 @@ struct iwl_cmd; struct iwl_hcmd_ops { int (*rxon_assoc)(struct iwl_priv *priv); + int (*commit_rxon)(struct iwl_priv *priv); + void (*set_rxon_chain)(struct iwl_priv *priv); }; + struct iwl_hcmd_utils_ops { u16 (*get_hcmd_size)(u8 cmd_id, u16 len); u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); @@ -100,6 +103,19 @@ struct iwl_hcmd_utils_ops { struct iwl_rx_phy_res *rx_resp); }; +struct iwl_apm_ops { + int (*init)(struct iwl_priv *priv); + int (*reset)(struct iwl_priv *priv); + void (*stop)(struct iwl_priv *priv); + void (*config)(struct iwl_priv *priv); + int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); +}; + +struct iwl_temp_ops { + void (*temperature)(struct iwl_priv *priv); + void (*set_ct_kill)(struct iwl_priv *priv); +}; + struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -137,20 +153,21 @@ struct iwl_lib_ops { int (*is_valid_rtc_data_addr)(u32 addr); /* 1st ucode load */ int (*load_ucode)(struct iwl_priv *priv); - /* power management */ - struct { - int (*init)(struct iwl_priv *priv); - int (*reset)(struct iwl_priv *priv); - void (*stop)(struct iwl_priv *priv); - void (*config)(struct iwl_priv *priv); - int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); - } apm_ops; + /* power management */ + struct iwl_apm_ops apm_ops; + /* power */ int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); - void (*temperature) (struct iwl_priv *priv); + void (*post_associate) (struct iwl_priv *priv); + void (*config_ap) (struct iwl_priv *priv); + irqreturn_t (*isr) (int irq, void *data); + /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; + + /* temperature */ + struct iwl_temp_ops temp_ops; }; struct iwl_ops { @@ -160,13 +177,12 @@ struct iwl_ops { }; struct iwl_mod_params { - int disable; /* def: 0 = enable radio */ 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 */ - int disable_11n; /* def: 0 = disable 11n capabilities */ + int disable_11n; /* def: 0 = 11n capabilities enabled */ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ int antenna; /* def: 0 = both antennas (use diversity) */ int restart_fw; /* def: 1 = restart firmware */ @@ -214,6 +230,7 @@ struct iwl_cfg { u8 valid_tx_ant; u8 valid_rx_ant; bool need_pll_cfg; + bool use_isr_legacy; }; /*************************** @@ -225,6 +242,8 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, void iwl_hw_detect(struct iwl_priv *priv); void iwl_reset_qos(struct iwl_priv *priv); void iwl_activate_qos(struct iwl_priv *priv, u8 force); +int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); int iwl_check_rxon_cmd(struct iwl_priv *priv); int iwl_full_rxon_required(struct iwl_priv *priv); @@ -249,6 +268,24 @@ int iwl_setup_mac(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); int iwl_init_drv(struct iwl_priv *priv); void iwl_uninit_drv(struct iwl_priv *priv); +bool iwl_is_monitor_mode(struct iwl_priv *priv); +void iwl_post_associate(struct iwl_priv *priv); +void iwl_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); +int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); +int iwl_commit_rxon(struct iwl_priv *priv); +int iwl_set_mode(struct iwl_priv *priv, int mode); +int iwl_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf); +void iwl_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf); +int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); +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); /***************************************************** * RX handlers. @@ -271,10 +308,11 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_rx_replenish(struct iwl_priv *priv); +void iwl_rx_replenish_now(struct iwl_priv *priv); int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); int iwl_rx_queue_restock(struct iwl_priv *priv); int iwl_rx_queue_space(const struct iwl_rx_queue *q); -void iwl_rx_allocate(struct iwl_priv *priv); +void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); /* Handlers */ @@ -310,14 +348,6 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); ****************************************************/ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); -/***************************************************** - * RF -Kill - here and not in iwl-rfkill.h to be available when - * RF-kill subsystem is not compiled. - ****************************************************/ -void iwl_bg_rf_kill(struct work_struct *work); -void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv); -int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv); - /******************************************************************************* * Rate ******************************************************************************/ @@ -328,8 +358,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); -void iwl_set_rate(struct iwl_priv *priv); - u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) @@ -358,8 +386,8 @@ 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, enum ieee80211_band band, - struct ieee80211_mgmt *frame, int left); +u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, + const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); u16 iwl_get_active_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, @@ -423,7 +451,13 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, *****************************************************/ void iwl_disable_interrupts(struct iwl_priv *priv); void iwl_enable_interrupts(struct iwl_priv *priv); -irqreturn_t iwl_isr(int irq, void *data); +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); +int iwl_alloc_isr_ict(struct iwl_priv *priv); +void iwl_free_isr_ict(struct iwl_priv *priv); +irqreturn_t iwl_isr_ict(int irq, void *data); + static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) { int pos; @@ -432,12 +466,17 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); return pci_lnk_ctl; } +#ifdef CONFIG_PM +int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); +int iwl_pci_resume(struct pci_dev *pdev); +#endif /* CONFIG_PM */ /***************************************************** * 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); /***************************************************** * GEOS @@ -451,14 +490,12 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ #define STATUS_INT_ENABLED 2 #define STATUS_RF_KILL_HW 3 -#define STATUS_RF_KILL_SW 4 #define STATUS_INIT 5 #define STATUS_ALIVE 6 #define STATUS_READY 7 #define STATUS_TEMPERATURE 8 #define STATUS_GEO_CONFIGURED 9 #define STATUS_EXIT_PENDING 10 -#define STATUS_IN_SUSPEND 11 #define STATUS_STATISTICS 12 #define STATUS_SCANNING 13 #define STATUS_SCAN_ABORTING 14 @@ -487,11 +524,6 @@ static inline int iwl_is_init(struct iwl_priv *priv) return test_bit(STATUS_INIT, &priv->status); } -static inline int iwl_is_rfkill_sw(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_SW, &priv->status); -} - static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) { return test_bit(STATUS_RF_KILL_HW, &priv->status); @@ -499,7 +531,7 @@ static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) static inline int iwl_is_rfkill(struct iwl_priv *priv) { - return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv); + return iwl_is_rfkill_hw(priv); } static inline int iwl_is_ready_rf(struct iwl_priv *priv) @@ -528,7 +560,14 @@ static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) { return priv->cfg->ops->hcmd->rxon_assoc(priv); } - +static inline int iwlcore_commit_rxon(struct iwl_priv *priv) +{ + return priv->cfg->ops->hcmd->commit_rxon(priv); +} +static inline void iwlcore_config_ap(struct iwl_priv *priv) +{ + priv->cfg->ops->lib->config_ap(priv); +} static inline const struct ieee80211_supported_band *iwl_get_hw_mode( struct iwl_priv *priv, enum ieee80211_band band) { diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 6e983149b83b..f03dae1b2f36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -89,6 +89,7 @@ /* EEPROM reads */ #define CSR_EEPROM_REG (CSR_BASE+0x02c) #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_UCODE_DRV_GP1 (CSR_BASE+0x054) @@ -96,8 +97,10 @@ #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) #define CSR_LED_REG (CSR_BASE+0x094) +#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) +#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) /* Analog phase-lock-loop configuration */ #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) /* @@ -123,16 +126,18 @@ #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) -#define CSR_HW_IF_CONFIG_REG_BIT_PCI_OWN_SEM (0x00400000) -#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000) -#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000) +#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) +#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) +#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) +#define CSR_INT_PERIODIC_DIS (0x00) +#define CSR_INT_PERIODIC_ENA (0xFF) /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), * acknowledged (reset) by host writing "1" to flagged bits. */ #define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ -#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ +#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */ #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ #define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ @@ -226,6 +231,10 @@ #define CSR_EEPROM_GP_VALID_MSK (0x00000007) #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) +#define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ +#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ +#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ +#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ /* CSR GIO */ #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) @@ -251,6 +260,11 @@ /* HPET MEM debug */ #define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000) + +/* DRAM INT TABLE */ +#define CSR_DRAM_INT_TBL_ENABLE (1 << 31) +#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) + /*=== HBUS (Host-side Bus) ===*/ #define HBUS_BASE (0x400) /* diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 65d1a7f2db9e..2cf014f523be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -68,13 +68,14 @@ struct iwl_debugfs { struct dentry *dir_rf; struct dir_data_files { struct dentry *file_sram; - struct dentry *file_eeprom; + 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; } dbgfs_data_files; struct dir_rf_files { struct dentry *file_disable_sensitivity; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 64eb585f1578..11e08c068917 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -172,7 +172,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, struct iwl_priv *priv = (struct iwl_priv *)file->private_data; const size_t bufsz = sizeof(buf); - iwl_grab_nic_access(priv); for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ priv->dbgfs->sram_len - i); @@ -192,7 +191,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); } pos += scnprintf(buf + pos, bufsz - pos, "\n"); - iwl_release_nic_access(priv); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); return ret; @@ -292,7 +290,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, return ret; } -static ssize_t iwl_dbgfs_eeprom_read(struct file *file, +static ssize_t iwl_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -306,7 +304,7 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, buf_size = 4 * eeprom_len + 256; if (eeprom_len % 16) { - IWL_ERR(priv, "EEPROM size is not multiple of 16.\n"); + IWL_ERR(priv, "NVM size is not multiple of 16.\n"); return -ENODATA; } @@ -318,6 +316,13 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, } ptr = priv->eeprom; + if (!ptr) { + IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); + return -ENOMEM; + } + pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n", + (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) + ? "OTP" : "EEPROM"); for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, @@ -375,51 +380,53 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, } supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); - channels = supp_band->channels; + if (supp_band) { + channels = supp_band->channels; - pos += scnprintf(buf + pos, bufsz - pos, - "Displaying %d channels in 2.4GHz band 802.11bg):\n", - supp_band->n_channels); - - for (i = 0; i < supp_band->n_channels; i++) pos += scnprintf(buf + pos, bufsz - pos, - "%d: %ddBm: BSS%s%s, %s.\n", - ieee80211_frequency_to_channel( - channels[i].center_freq), - channels[i].max_power, - channels[i].flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS) - || (channels[i].flags & - IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i].flags & - IEEE80211_CHAN_PASSIVE_SCAN ? - "passive only" : "active/passive"); + "Displaying %d channels in 2.4GHz band 802.11bg):\n", + supp_band->n_channels); + for (i = 0; i < supp_band->n_channels; i++) + pos += scnprintf(buf + pos, bufsz - pos, + "%d: %ddBm: BSS%s%s, %s.\n", + ieee80211_frequency_to_channel( + channels[i].center_freq), + channels[i].max_power, + channels[i].flags & IEEE80211_CHAN_RADAR ? + " (IEEE 802.11h required)" : "", + ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) + || (channels[i].flags & + IEEE80211_CHAN_RADAR)) ? "" : + ", IBSS", + channels[i].flags & + IEEE80211_CHAN_PASSIVE_SCAN ? + "passive only" : "active/passive"); + } supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); - channels = supp_band->channels; + if (supp_band) { + channels = supp_band->channels; - pos += scnprintf(buf + pos, bufsz - pos, - "Displaying %d channels in 5.2GHz band (802.11a)\n", - supp_band->n_channels); - - for (i = 0; i < supp_band->n_channels; i++) pos += scnprintf(buf + pos, bufsz - pos, - "%d: %ddBm: BSS%s%s, %s.\n", - ieee80211_frequency_to_channel( - channels[i].center_freq), - channels[i].max_power, - channels[i].flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", - ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) - || (channels[i].flags & - IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i].flags & - IEEE80211_CHAN_PASSIVE_SCAN ? - "passive only" : "active/passive"); + "Displaying %d channels in 5.2GHz band (802.11a)\n", + supp_band->n_channels); + for (i = 0; i < supp_band->n_channels; i++) + pos += scnprintf(buf + pos, bufsz - pos, + "%d: %ddBm: BSS%s%s, %s.\n", + ieee80211_frequency_to_channel( + channels[i].center_freq), + channels[i].max_power, + channels[i].flags & IEEE80211_CHAN_RADAR ? + " (IEEE 802.11h required)" : "", + ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) + || (channels[i].flags & + IEEE80211_CHAN_RADAR)) ? "" : + ", IBSS", + channels[i].flags & + IEEE80211_CHAN_PASSIVE_SCAN ? + "passive only" : "active/passive"); + } ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; @@ -442,8 +449,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, test_bit(STATUS_INT_ENABLED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", test_bit(STATUS_RF_KILL_HW, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n", - test_bit(STATUS_RF_KILL_SW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", test_bit(STATUS_INIT, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", @@ -456,8 +461,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, test_bit(STATUS_GEO_CONFIGURED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", test_bit(STATUS_EXIT_PENDING, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n", - test_bit(STATUS_IN_SUSPEND, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", test_bit(STATUS_STATISTICS, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", @@ -475,14 +478,104 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } +static ssize_t iwl_dbgfs_interrupt_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 = 24 * 64; /* 24 items * 64 char per item */ + 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, + "Interrupt Statistics Report:\n"); + + pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", + priv->isr_stats.hw); + pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", + priv->isr_stats.sw); + if (priv->isr_stats.sw > 0) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tLast Restarting Code: 0x%X\n", + priv->isr_stats.sw_err); + } +#ifdef CONFIG_IWLWIFI_DEBUG + pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", + priv->isr_stats.sch); + pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", + priv->isr_stats.alive); +#endif + pos += scnprintf(buf + pos, bufsz - pos, + "HW RF KILL switch toggled:\t %u\n", + priv->isr_stats.rfkill); + + pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", + priv->isr_stats.ctkill); + + pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", + priv->isr_stats.wakeup); + + pos += scnprintf(buf + pos, bufsz - pos, + "Rx command responses:\t\t %u\n", + priv->isr_stats.rx); + for (cnt = 0; cnt < REPLY_MAX; cnt++) { + if (priv->isr_stats.rx_handlers[cnt] > 0) + pos += scnprintf(buf + pos, bufsz - pos, + "\tRx handler[%36s]:\t\t %u\n", + get_cmd_string(cnt), + priv->isr_stats.rx_handlers[cnt]); + } + + pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", + priv->isr_stats.tx); + + pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", + priv->isr_stats.unhandled); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_interrupt_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; + u32 reset_flag; + + 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", &reset_flag) != 1) + return -EFAULT; + if (reset_flag == 0) + iwl_clear_isr_stats(priv); + + return count; +} + + DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_WRITE_FILE_OPS(log_event); -DEBUGFS_READ_FILE_OPS(eeprom); +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); /* * Create the debugfs files and directories @@ -510,7 +603,7 @@ 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_FILE(eeprom, data); + DEBUGFS_ADD_FILE(nvm, data); DEBUGFS_ADD_FILE(sram, data); DEBUGFS_ADD_FILE(log_event, data); DEBUGFS_ADD_FILE(stations, data); @@ -518,6 +611,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(tx_statistics, data); DEBUGFS_ADD_FILE(channels, data); DEBUGFS_ADD_FILE(status, data); + DEBUGFS_ADD_FILE(interrupt, data); DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); @@ -540,7 +634,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) if (!priv->dbgfs) return; - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom); + 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); @@ -548,6 +642,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) 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->dir_data); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index cf7f0db58fcf..e2d620f0b6e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -41,7 +41,6 @@ #include "iwl-prph.h" #include "iwl-fh.h" #include "iwl-debug.h" -#include "iwl-rfkill.h" #include "iwl-4965-hw.h" #include "iwl-3945-hw.h" #include "iwl-3945-led.h" @@ -289,11 +288,11 @@ struct iwl_frame { #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) enum { - /* CMD_SIZE_NORMAL = 0, */ + CMD_SYNC = 0, + CMD_SIZE_NORMAL = 0, + CMD_NO_SKB = 0, CMD_SIZE_HUGE = (1 << 0), - /* CMD_SYNC = 0, */ CMD_ASYNC = (1 << 1), - /* CMD_NO_SKB = 0, */ CMD_WANT_SKB = (1 << 2), }; @@ -381,6 +380,7 @@ struct iwl_rx_queue { u32 read; u32 write; u32 free_count; + u32 write_actual; struct list_head rx_free; struct list_head rx_used; int need_update; @@ -498,22 +498,13 @@ struct iwl_qos_info { #define STA_PS_STATUS_WAKE 0 #define STA_PS_STATUS_SLEEP 1 -struct iwl3945_tid_data { - u16 seq_number; -}; - -struct iwl3945_hw_key { - enum ieee80211_key_alg alg; - int keylen; - u8 key[32]; -}; struct iwl3945_station_entry { struct iwl3945_addsta_cmd sta; - struct iwl3945_tid_data tid[MAX_TID_COUNT]; + struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used; u8 ps_status; - struct iwl3945_hw_key keyinfo; + struct iwl_hw_key keyinfo; }; struct iwl_station_entry { @@ -822,6 +813,26 @@ enum { MEASUREMENT_ACTIVE = (1 << 1), }; +enum iwl_nvm_type { + NVM_DEVICE_TYPE_EEPROM = 0, + NVM_DEVICE_TYPE_OTP, +}; + +/* interrupt statistics */ +struct isr_statistics { + u32 hw; + u32 sw; + u32 sw_err; + u32 sch; + u32 alive; + u32 rfkill; + u32 ctkill; + u32 wakeup; + u32 rx; + u32 rx_handlers[REPLY_MAX]; + u32 tx; + u32 unhandled; +}; #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ @@ -877,15 +888,14 @@ struct iwl_priv { unsigned long scan_start_tsf; void *scan; int scan_bands; - int one_direct_scan; - u8 direct_ssid_len; - u8 direct_ssid[IW_ESSID_MAX_SIZE]; + struct cfg80211_scan_request *scan_request; u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; /* spinlock */ spinlock_t lock; /* protect general shared data */ spinlock_t hcmd_lock; /* protect hcmd */ + spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; /* basic pci-network driver stuff */ @@ -919,16 +929,12 @@ struct iwl_priv { const struct iwl_rxon_cmd active_rxon; struct iwl_rxon_cmd staging_rxon; - int error_recovering; struct iwl_rxon_cmd recovery_rxon; /* 1st responses from initialize and runtime uCode images. * 4965's initialize alive response contains some calibration data. */ struct iwl_init_alive_resp card_alive_init; struct iwl_alive_resp card_alive; -#if defined(CONFIG_IWLWIFI_RFKILL) - struct rfkill *rfkill; -#endif #ifdef CONFIG_IWLWIFI_LEDS unsigned long last_blink_time; @@ -978,6 +984,9 @@ struct iwl_priv { u64 bytes; } tx_stats[3], rx_stats[3]; + /* counts interrupts */ + struct isr_statistics isr_stats; + struct iwl_power_mgr power_data; struct iwl_notif_statistics statistics; @@ -1017,6 +1026,7 @@ struct iwl_priv { /* eeprom */ u8 *eeprom; + int nvm_device_type; struct iwl_eeprom_calib_info *calib_info; enum nl80211_iftype iw_mode; @@ -1034,7 +1044,16 @@ struct iwl_priv { /*End*/ struct iwl_hw_params hw_params; + /* INT ICT Table */ + u32 *ict_tbl; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + void *ict_tbl_vir; + u32 inta; + bool use_ict; + u32 inta_mask; /* Current association information needed to configure the * hardware */ u16 assoc_id; @@ -1049,7 +1068,6 @@ struct iwl_priv { struct work_struct calibrated_work; struct work_struct scan_completed; struct work_struct rx_replenish; - struct work_struct rf_kill; struct work_struct abort_scan; struct work_struct update_link_led; struct work_struct auth_work; @@ -1059,7 +1077,6 @@ struct iwl_priv { struct tasklet_struct irq_tasklet; - struct delayed_work set_power_save; struct delayed_work init_alive_start; struct delayed_work alive_start; struct delayed_work scan_check; @@ -1090,14 +1107,12 @@ struct iwl_priv { u32 disable_tx_power_cal; struct work_struct run_time_calib_work; struct timer_list statistics_periodic; - + bool hw_ready; /*For 3945*/ #define IWL_DEFAULT_TX_POWER 0x0F struct iwl3945_notif_statistics statistics_39; - struct iwl3945_station_entry stations_39[IWL_STATION_COUNT]; - u32 sta_supp_rates; }; /*iwl_priv */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 75517d05df08..7d7554a2f341 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -152,6 +152,32 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) } EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); +static int iwlcore_get_nvm_type(struct iwl_priv *priv) +{ + u32 otpgp; + int nvm_type; + + /* OTP only valid for CP/PP and after */ + switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { + case CSR_HW_REV_TYPE_3945: + case CSR_HW_REV_TYPE_4965: + case CSR_HW_REV_TYPE_5300: + case CSR_HW_REV_TYPE_5350: + case CSR_HW_REV_TYPE_5100: + case CSR_HW_REV_TYPE_5150: + nvm_type = NVM_DEVICE_TYPE_EEPROM; + break; + default: + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); + if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) + nvm_type = NVM_DEVICE_TYPE_OTP; + else + nvm_type = NVM_DEVICE_TYPE_EEPROM; + break; + } + return nvm_type; +} + /* * The device's EEPROM semaphore prevents conflicts between driver and uCode * when accessing the EEPROM; each access is a series of pulses to/from the @@ -198,6 +224,31 @@ const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) } EXPORT_SYMBOL(iwlcore_eeprom_query_addr); +static int iwl_init_otp_access(struct iwl_priv *priv) +{ + int ret; + + /* Enable 40MHz radio clock */ + _iwl_write32(priv, CSR_GP_CNTRL, + _iwl_read32(priv, CSR_GP_CNTRL) | + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + + /* wait for clock to be ready */ + ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + 25000); + if (ret < 0) + IWL_ERR(priv, "Time out access OTP\n"); + else { + iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_RESET_REQ); + udelay(5); + iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_RESET_REQ); + } + return ret; +} + /** * iwl_eeprom_init - read EEPROM contents * @@ -209,11 +260,18 @@ int iwl_eeprom_init(struct iwl_priv *priv) { u16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); - int sz = priv->cfg->eeprom_size; + int sz; int ret; u16 addr; + u32 otpgp; + + priv->nvm_device_type = iwlcore_get_nvm_type(priv); /* allocate eeprom */ + if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) + priv->cfg->eeprom_size = + OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL; + sz = priv->cfg->eeprom_size; priv->eeprom = kzalloc(sz, GFP_KERNEL); if (!priv->eeprom) { ret = -ENOMEM; @@ -235,30 +293,77 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = -ENOENT; goto err; } - - /* eeprom is an array of 16bit values */ - for (addr = 0; addr < sz; addr += sizeof(u16)) { - u32 r; - - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - - ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { - IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); - goto done; + if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { + ret = iwl_init_otp_access(priv); + if (ret) { + IWL_ERR(priv, "Failed to initialize OTP access.\n"); + ret = -ENOENT; + goto err; + } + _iwl_write32(priv, CSR_EEPROM_GP, + iwl_read32(priv, CSR_EEPROM_GP) & + ~CSR_EEPROM_GP_IF_OWNER_MSK); + /* clear */ + _iwl_write32(priv, CSR_OTP_GP_REG, + iwl_read32(priv, CSR_OTP_GP_REG) | + CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | + CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); + + for (addr = 0; addr < sz; addr += sizeof(u16)) { + u32 r; + + _iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + + ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); + if (ret < 0) { + IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); + goto done; + } + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + /* check for ECC errors: */ + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); + if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { + /* stop in this case */ + IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n"); + goto done; + } + if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { + /* continue in this case */ + _iwl_write32(priv, CSR_OTP_GP_REG, + iwl_read32(priv, CSR_OTP_GP_REG) | + CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); + IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); + } + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); + } + } else { + /* eeprom is an array of 16bit values */ + for (addr = 0; addr < sz; addr += sizeof(u16)) { + u32 r; + + _iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + + ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); + if (ret < 0) { + IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); + goto done; + } + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } ret = 0; done: priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); err: if (ret) - kfree(priv->eeprom); + iwl_eeprom_free(priv); alloc_err: return ret; } @@ -285,7 +390,7 @@ int iwl_eeprom_check_version(struct iwl_priv *priv) return 0; err: - IWL_ERR(priv, "Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", + IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", eeprom_ver, priv->cfg->eeprom_ver, calib_ver, priv->cfg->eeprom_calib_ver); return -EINVAL; @@ -301,6 +406,8 @@ EXPORT_SYMBOL(iwl_eeprom_query_addr); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) { + if (!priv->eeprom) + return 0; return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); } EXPORT_SYMBOL(iwl_eeprom_query16); @@ -481,8 +588,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* First write that fat is not enabled, and then enable * one by one */ ch_info->fat_extension_channel = - (IEEE80211_CHAN_NO_FAT_ABOVE | - IEEE80211_CHAN_NO_FAT_BELOW); + (IEEE80211_CHAN_NO_HT40PLUS | + IEEE80211_CHAN_NO_HT40MINUS); if (!(is_channel_valid(ch_info))) { IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " @@ -561,7 +668,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) fat_extension_chan = 0; else fat_extension_chan = - IEEE80211_CHAN_NO_FAT_BELOW; + IEEE80211_CHAN_NO_HT40MINUS; /* Set up driver's info for lower half */ iwl_set_fat_chan_info(priv, ieeeband, @@ -573,7 +680,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) iwl_set_fat_chan_info(priv, ieeeband, (eeprom_ch_index[ch] + 4), &(eeprom_ch_info[ch]), - IEEE80211_CHAN_NO_FAT_ABOVE); + IEEE80211_CHAN_NO_HT40PLUS); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 3479153d96ca..195b4ef12c27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -179,6 +179,10 @@ struct iwl_eeprom_channel { #define EEPROM_5050_TX_POWER_VERSION (4) #define EEPROM_5050_EEPROM_VERSION (0x21E) +/* OTP */ +#define OTP_LOWER_BLOCKS_TOTAL (3) +#define OTP_BLOCK_SIZE (0x400) + /* 2.4 GHz */ extern const u8 iwl_eeprom_band_1[14]; diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 083ea1ffbe87..d30cb0275d19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -131,9 +131,23 @@ static inline void __iwl_set_bit(const char *f, u32 l, IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); _iwl_write32(priv, reg, val); } -#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m) +static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + __iwl_set_bit(__FILE__, __LINE__, p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} #else -#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m) +static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + _iwl_set_bit(p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} #endif static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) @@ -148,19 +162,30 @@ static inline void __iwl_clear_bit(const char *f, u32 l, IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); _iwl_write32(priv, reg, val); } -#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m) +static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + __iwl_clear_bit(__FILE__, __LINE__, p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} #else -#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m) +static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + _iwl_clear_bit(p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} #endif static inline int _iwl_grab_nic_access(struct iwl_priv *priv) { int ret; u32 val; -#ifdef CONFIG_IWLWIFI_DEBUG - if (atomic_read(&priv->restrict_refcnt)) - return 0; -#endif + /* this bit wakes up the NIC */ _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, @@ -170,12 +195,10 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) if (ret < 0) { val = _iwl_read32(priv, CSR_GP_CNTRL); IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); + _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); return -EIO; } -#ifdef CONFIG_IWLWIFI_DEBUG - atomic_inc(&priv->restrict_refcnt); -#endif return 0; } @@ -183,9 +206,6 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) static inline int __iwl_grab_nic_access(const char *f, u32 l, struct iwl_priv *priv) { - if (atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Grabbing access while already held %s %d.\n", f, l); - IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); return _iwl_grab_nic_access(priv); } @@ -198,18 +218,13 @@ static inline int __iwl_grab_nic_access(const char *f, u32 l, static inline void _iwl_release_nic_access(struct iwl_priv *priv) { -#ifdef CONFIG_IWLWIFI_DEBUG - if (atomic_dec_and_test(&priv->restrict_refcnt)) -#endif - _iwl_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + _iwl_clear_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } #ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl_release_nic_access(const char *f, u32 l, struct iwl_priv *priv) { - if (atomic_read(&priv->restrict_refcnt) <= 0) - IWL_ERR(priv, "Release unheld nic access at line %s %d.\n", f, l); IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); _iwl_release_nic_access(priv); @@ -230,16 +245,37 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, struct iwl_priv *priv, u32 reg) { u32 value = _iwl_read_direct32(priv, reg); - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Nic access not held from %s %d\n", f, l); IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, f, l); return value; } -#define iwl_read_direct32(priv, reg) \ - __iwl_read_direct32(__FILE__, __LINE__, priv, reg) +static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + u32 value; + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return value; +} + #else -#define iwl_read_direct32 _iwl_read_direct32 +static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + u32 value; + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + value = _iwl_read_direct32(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return value; + +} #endif static inline void _iwl_write_direct32(struct iwl_priv *priv, @@ -247,19 +283,17 @@ static inline void _iwl_write_direct32(struct iwl_priv *priv, { _iwl_write32(priv, reg, value); } -#ifdef CONFIG_IWLWIFI_DEBUG -static void __iwl_write_direct32(const char *f , u32 line, - struct iwl_priv *priv, u32 reg, u32 value) +static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) { - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); - _iwl_write_direct32(priv, reg, value); + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_direct32(priv, reg, value); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } -#define iwl_write_direct32(priv, reg, value) \ - __iwl_write_direct32(__func__, __LINE__, priv, reg, value) -#else -#define iwl_write_direct32 _iwl_write_direct32 -#endif static inline void iwl_write_reg_buf(struct iwl_priv *priv, u32 reg, u32 len, u32 *values) @@ -268,14 +302,23 @@ static inline void iwl_write_reg_buf(struct iwl_priv *priv, if ((priv != NULL) && (values != NULL)) { for (; 0 < len; len -= count, reg += count, values++) - _iwl_write_direct32(priv, reg, *values); + iwl_write_direct32(priv, reg, *values); } } static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { - return _iwl_poll_bit(priv, addr, mask, mask, timeout); + int t = 0; + + do { + if ((iwl_read_direct32(priv, addr) & mask) == mask) + return t; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; } #ifdef CONFIG_IWLWIFI_DEBUG @@ -305,20 +348,18 @@ static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) rmb(); return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); } -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl_read_prph(const char *f, u32 line, - struct iwl_priv *priv, u32 reg) +static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) { - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); - return _iwl_read_prph(priv, reg); -} + unsigned long reg_flags; + u32 val; -#define iwl_read_prph(priv, reg) \ - __iwl_read_prph(__func__, __LINE__, priv, reg) -#else -#define iwl_read_prph _iwl_read_prph -#endif + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + val = _iwl_read_prph(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return val; +} static inline void _iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) @@ -328,83 +369,107 @@ static inline void _iwl_write_prph(struct iwl_priv *priv, wmb(); _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); } -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_write_prph(const char *f, u32 line, - struct iwl_priv *priv, u32 addr, u32 val) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); - _iwl_write_prph(priv, addr, val); -} -#define iwl_write_prph(priv, addr, val) \ - __iwl_write_prph(__func__, __LINE__, priv, addr, val); -#else -#define iwl_write_prph _iwl_write_prph -#endif +static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_prph(priv, addr, val); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} #define _iwl_set_bits_prph(priv, reg, mask) \ _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_set_bits_prph(const char *f, u32 line, - struct iwl_priv *priv, - u32 reg, u32 mask) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); +static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); _iwl_set_bits_prph(priv, reg, mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } -#define iwl_set_bits_prph(priv, reg, mask) \ - __iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask) -#else -#define iwl_set_bits_prph _iwl_set_bits_prph -#endif #define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_set_bits_mask_prph(const char *f, u32 line, - struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) +static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, + u32 bits, u32 mask) { - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); _iwl_set_bits_mask_prph(priv, reg, bits, mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } -#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \ - __iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask) -#else -#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph -#endif static inline void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { - u32 val = _iwl_read_prph(priv, reg); + unsigned long reg_flags; + u32 val; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + val = _iwl_read_prph(priv, reg); _iwl_write_prph(priv, reg, (val & ~mask)); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) { - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); + unsigned long reg_flags; + u32 value; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + + _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); rmb(); - return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return value; } static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) { - iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); + wmb(); + _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, u32 len, u32 *values) { - iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - for (; 0 < len; len -= sizeof(u32), values++) - iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); + wmb(); + for (; 0 < len; len -= sizeof(u32), values++) + _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); + + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 19680f72087f..5e64252f80f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -176,10 +176,6 @@ static int iwl_led_associate(struct iwl_priv *priv, int led_id) static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) { priv->allow_blinking = 0; - if (iwl_is_rfkill(priv)) - iwl4965_led_off_reg(priv, led_id); - else - iwl4965_led_on_reg(priv, led_id); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 47c894530eb5..f2ea3f05f6e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -41,38 +41,33 @@ #include "iwl-power.h" /* - * Setting power level allow the card to go to sleep when not busy - * there are three factor that decide the power level to go to, they - * are list here with its priority - * 1- critical_power_setting this will be set according to card temperature. - * 2- system_power_setting this will be set by system PM manager. - * 3- user_power_setting this will be set by user either by writing to sys or - * mac80211 + * Setting power level allow the card to go to sleep when not busy. * - * if system_power_setting and user_power_setting is set to auto - * the power level will be decided according to association status and battery - * status. + * 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. */ -#define MSEC_TO_USEC 1024 #define IWL_POWER_RANGE_0_MAX (2) #define IWL_POWER_RANGE_1_MAX (10) - -#define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5 -#define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM -#define IWL_POWER_ON_AC_ASSOC IWL_POWER_MODE_CAM - - -#define IWL_CT_KILL_TEMPERATURE 110 -#define IWL_MIN_POWER_TEMPERATURE 100 -#define IWL_REDUCED_POWER_TEMPERATURE 95 - +#define NOSLP cpu_to_le16(0), 0, 0 +#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 +#define TU_TO_USEC 1024 +#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) +#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ + cpu_to_le32(X1), \ + cpu_to_le32(X2), \ + cpu_to_le32(X3), \ + cpu_to_le32(X4)} /* default power management (not Tx power) table values */ -/* for TIM 0-10 */ -static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { +/* for DTIM period 0 through IWL_POWER_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}, @@ -82,8 +77,8 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { }; -/* for TIM = 3-10 */ -static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { +/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_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}, @@ -92,8 +87,8 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} }; -/* for TIM > 11 */ -static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { +/* for DTIM period > IWL_POWER_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}, @@ -106,39 +101,15 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { /* set card power command */ static int iwl_set_power(struct iwl_priv *priv, void *cmd) { - return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, - sizeof(struct iwl_powertable_cmd), - cmd, NULL); -} -/* decide the right power level according to association status - * and battery status - */ -static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) -{ - u16 mode; - - switch (priv->power_data.user_power_setting) { - case IWL_POWER_AUTO: - /* if running on battery */ - if (priv->power_data.is_battery_active) - mode = IWL_POWER_ON_BATTERY; - else if (iwl_is_associated(priv)) - mode = IWL_POWER_ON_AC_ASSOC; - else - mode = IWL_POWER_ON_AC_DISASSOC; - break; - default: - mode = priv->power_data.user_power_setting; - break; - } - return mode; + 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_MAX; + int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM; struct iwl_powertable_cmd *cmd; int i; u16 lctl; @@ -157,7 +128,7 @@ static void iwl_power_init_handle(struct iwl_priv *priv) IWL_DEBUG_POWER(priv, "adjust power command flags\n"); - for (i = 0; i < IWL_POWER_MAX; i++) { + 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) @@ -247,33 +218,12 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; - /* If on battery, set to 3, - * if plugged into AC power, set to CAM ("continuously aware mode"), - * else user level */ + final_mode = priv->power_data.user_power_setting; - switch (setting->system_power_setting) { - case IWL_POWER_SYS_AUTO: - final_mode = iwl_get_auto_power_mode(priv); - break; - case IWL_POWER_SYS_BATTERY: - final_mode = IWL_POWER_INDEX_3; - break; - case IWL_POWER_SYS_AC: - final_mode = IWL_POWER_MODE_CAM; - break; - default: - final_mode = IWL_POWER_INDEX_3; - WARN_ON(1); - } - - if (setting->critical_power_setting > final_mode) - final_mode = setting->critical_power_setting; - - /* driver only support CAM for non STA network */ - if (priv->iw_mode != NL80211_IFTYPE_STATION) + if (setting->power_disabled) final_mode = IWL_POWER_MODE_CAM; - if (iwl_is_ready_rf(priv) && !setting->power_disabled && + if (iwl_is_ready_rf(priv) && ((setting->power_mode != final_mode) || force)) { struct iwl_powertable_cmd cmd; @@ -290,8 +240,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); - else - set_bit(STATUS_POWER_PMI, &priv->status); if (priv->cfg->ops->lib->update_chain_flags && update_chains) priv->cfg->ops->lib->update_chain_flags(priv); @@ -307,51 +255,10 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) } EXPORT_SYMBOL(iwl_power_update_mode); -/* Allow other iwl code to disable/enable power management active - * this will be useful for rate scale to disable PM during heavy - * Tx/Rx activities - */ -int iwl_power_disable_management(struct iwl_priv *priv, u32 ms) -{ - u16 prev_mode; - int ret = 0; - - if (priv->power_data.power_disabled) - return -EBUSY; - - prev_mode = priv->power_data.user_power_setting; - priv->power_data.user_power_setting = IWL_POWER_MODE_CAM; - ret = iwl_power_update_mode(priv, 0); - priv->power_data.power_disabled = 1; - priv->power_data.user_power_setting = prev_mode; - cancel_delayed_work(&priv->set_power_save); - if (ms) - queue_delayed_work(priv->workqueue, &priv->set_power_save, - msecs_to_jiffies(ms)); - - - return ret; -} -EXPORT_SYMBOL(iwl_power_disable_management); - -/* Allow other iwl code to disable/enable power management active - * this will be useful for rate scale to disable PM during high - * volume activities - */ -int iwl_power_enable_management(struct iwl_priv *priv) -{ - int ret = 0; - - priv->power_data.power_disabled = 0; - ret = iwl_power_update_mode(priv, 0); - return ret; -} -EXPORT_SYMBOL(iwl_power_enable_management); - /* set user_power_setting */ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) { - if (mode > IWL_POWER_MAX) + if (mode >= IWL_POWER_NUM) return -EINVAL; priv->power_data.user_power_setting = mode; @@ -360,86 +267,12 @@ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) } EXPORT_SYMBOL(iwl_power_set_user_mode); -/* set system_power_setting. This should be set by over all - * PM application. - */ -int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode) -{ - if (mode < IWL_POWER_SYS_MAX) - priv->power_data.system_power_setting = mode; - else - return -EINVAL; - return iwl_power_update_mode(priv, 0); -} -EXPORT_SYMBOL(iwl_power_set_system_mode); - /* initialize to default */ void iwl_power_initialize(struct iwl_priv *priv) { iwl_power_init_handle(priv); - priv->power_data.user_power_setting = IWL_POWER_AUTO; - priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; - priv->power_data.power_disabled = 0; - priv->power_data.is_battery_active = 0; - priv->power_data.critical_power_setting = 0; + priv->power_data.user_power_setting = IWL_POWER_INDEX_1; + /* default to disabled until mac80211 says otherwise */ + priv->power_data.power_disabled = 1; } EXPORT_SYMBOL(iwl_power_initialize); - -/* set critical_power_setting according to temperature value */ -int iwl_power_temperature_change(struct iwl_priv *priv) -{ - int ret = 0; - s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature); - u16 new_critical = priv->power_data.critical_power_setting; - - if (temperature > IWL_CT_KILL_TEMPERATURE) - return 0; - else if (temperature > IWL_MIN_POWER_TEMPERATURE) - new_critical = IWL_POWER_INDEX_5; - else if (temperature > IWL_REDUCED_POWER_TEMPERATURE) - new_critical = IWL_POWER_INDEX_3; - else - new_critical = IWL_POWER_MODE_CAM; - - if (new_critical != priv->power_data.critical_power_setting) - priv->power_data.critical_power_setting = new_critical; - - if (priv->power_data.critical_power_setting > - priv->power_data.power_mode) - ret = iwl_power_update_mode(priv, 0); - - return ret; -} -EXPORT_SYMBOL(iwl_power_temperature_change); - -static void iwl_bg_set_power_save(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, - struct iwl_priv, set_power_save.work); - IWL_DEBUG_POWER(priv, "update power\n"); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - - /* on starting association we disable power management - * until association, if association failed then this - * timer will expire and enable PM again. - */ - if (!iwl_is_associated(priv)) - iwl_power_enable_management(priv); - - mutex_unlock(&priv->mutex); -} -void iwl_setup_power_deferred_work(struct iwl_priv *priv) -{ - INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); -} -EXPORT_SYMBOL(iwl_setup_power_deferred_work); - -void iwl_power_cancel_timeout(struct iwl_priv *priv) -{ - cancel_delayed_work(&priv->set_power_save); -} -EXPORT_SYMBOL(iwl_power_cancel_timeout); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 18963392121e..37ba3bb7a25a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -40,56 +40,29 @@ enum { IWL_POWER_INDEX_3, IWL_POWER_INDEX_4, IWL_POWER_INDEX_5, - IWL_POWER_AUTO, - IWL_POWER_MAX = IWL_POWER_AUTO, + IWL_POWER_NUM }; -enum { - IWL_POWER_SYS_AUTO, - IWL_POWER_SYS_AC, - IWL_POWER_SYS_BATTERY, - IWL_POWER_SYS_MAX, -}; - - /* Power management (not Tx power) structures */ -#define NOSLP cpu_to_le16(0), 0, 0 -#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 -#define SLP_TOUT(T) cpu_to_le32((T) * MSEC_TO_USEC) -#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ - cpu_to_le32(X1), \ - cpu_to_le32(X2), \ - cpu_to_le32(X3), \ - cpu_to_le32(X4)} struct iwl_power_vec_entry { struct iwl_powertable_cmd cmd; u8 no_dtim; }; struct iwl_power_mgr { - spinlock_t lock; - struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX]; - struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX]; - struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX]; + 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 mac80211 or sysfs */ - u8 system_power_setting; /* set by kernel system tools */ - u8 critical_power_setting; /* set if driver over heated */ - u8 is_battery_active; /* DC/AC power */ - u8 power_disabled; /* flag to disable using power saving level */ + u8 user_power_setting; /* set by user through sysfs */ + u8 power_disabled; /* set by mac80211's CONF_PS */ }; -void iwl_setup_power_deferred_work(struct iwl_priv *priv); -void iwl_power_cancel_timeout(struct iwl_priv *priv); int iwl_power_update_mode(struct iwl_priv *priv, bool force); -int iwl_power_disable_management(struct iwl_priv *priv, u32 ms); -int iwl_power_enable_management(struct iwl_priv *priv); int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); -int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode); void iwl_power_initialize(struct iwl_priv *priv); -int iwl_power_temperature_change(struct iwl_priv *priv); #endif /* __iwl_power_setting_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c deleted file mode 100644 index 2ad9faf1508a..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ /dev/null @@ -1,145 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License 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, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ -#include -#include -#include - -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" - -/* software rf-kill from user */ -static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) -{ - struct iwl_priv *priv = data; - int err = 0; - - if (!priv->rfkill) - return 0; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return 0; - - IWL_DEBUG_RF_KILL(priv, "we received soft RFKILL set to state %d\n", state); - mutex_lock(&priv->mutex); - - switch (state) { - case RFKILL_STATE_UNBLOCKED: - if (iwl_is_rfkill_hw(priv)) { - err = -EBUSY; - goto out_unlock; - } - iwl_radio_kill_sw_enable_radio(priv); - break; - case RFKILL_STATE_SOFT_BLOCKED: - iwl_radio_kill_sw_disable_radio(priv); - break; - default: - IWL_WARN(priv, "we received unexpected RFKILL state %d\n", - state); - break; - } -out_unlock: - mutex_unlock(&priv->mutex); - - return err; -} - -int iwl_rfkill_init(struct iwl_priv *priv) -{ - struct device *device = wiphy_dev(priv->hw->wiphy); - int ret = 0; - - BUG_ON(device == NULL); - - IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n"); - priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); - if (!priv->rfkill) { - IWL_ERR(priv, "Unable to allocate RFKILL device.\n"); - ret = -ENOMEM; - goto error; - } - - priv->rfkill->name = priv->cfg->name; - priv->rfkill->data = priv; - priv->rfkill->state = RFKILL_STATE_UNBLOCKED; - priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; - priv->rfkill->user_claim_unsupported = 1; - - priv->rfkill->dev.class->suspend = NULL; - priv->rfkill->dev.class->resume = NULL; - - ret = rfkill_register(priv->rfkill); - if (ret) { - IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret); - goto free_rfkill; - } - - IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); - return ret; - -free_rfkill: - if (priv->rfkill != NULL) - rfkill_free(priv->rfkill); - priv->rfkill = NULL; - -error: - IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); - return ret; -} -EXPORT_SYMBOL(iwl_rfkill_init); - -void iwl_rfkill_unregister(struct iwl_priv *priv) -{ - - if (priv->rfkill) - rfkill_unregister(priv->rfkill); - - priv->rfkill = NULL; -} -EXPORT_SYMBOL(iwl_rfkill_unregister); - -/* set RFKILL to the right state. */ -void iwl_rfkill_set_hw_state(struct iwl_priv *priv) -{ - if (!priv->rfkill) - return; - - if (iwl_is_rfkill_hw(priv)) { - rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); - return; - } - - if (!iwl_is_rfkill_sw(priv)) - rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); - else - rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); -} -EXPORT_SYMBOL(iwl_rfkill_set_hw_state); diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h deleted file mode 100644 index 633dafb4bf1b..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License 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, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ -#ifndef __iwl_rf_kill_h__ -#define __iwl_rf_kill_h__ - -struct iwl_priv; - -#include - -#ifdef CONFIG_IWLWIFI_RFKILL - -void iwl_rfkill_set_hw_state(struct iwl_priv *priv); -void iwl_rfkill_unregister(struct iwl_priv *priv); -int iwl_rfkill_init(struct iwl_priv *priv); -#else -static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {} -static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {} -static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; } -#endif - - - -#endif /* __iwl_rf_kill_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 8f65908f66f1..2b8d40b37a1c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -145,18 +145,14 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) goto exit_unlock; } - ret = iwl_grab_nic_access(priv); - if (ret) - goto exit_unlock; - - /* Device expects a multiple of 8 */ - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write & ~0x7); - iwl_release_nic_access(priv); + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ - iwl_write32(priv, rx_wrt_ptr_reg, q->write & ~0x7); + q->write_actual = (q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); } q->need_update = 0; @@ -218,7 +214,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) /* If we've added more space for the firmware to place data, tell it. * Increment device's write pointer in multiples of 8. */ - if (write != (rxq->write & ~0x7)) { + if (rxq->write_actual != (rxq->write & ~0x7)) { spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); @@ -238,7 +234,7 @@ EXPORT_SYMBOL(iwl_rx_queue_restock); * Also restock the Rx queue via iwl_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -void iwl_rx_allocate(struct iwl_priv *priv) +void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) { struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; @@ -260,7 +256,8 @@ void iwl_rx_allocate(struct iwl_priv *priv) /* Alloc a new receive buffer */ rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, - GFP_KERNEL); + priority); + if (!rxb->skb) { IWL_CRIT(priv, "Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will @@ -295,7 +292,7 @@ void iwl_rx_replenish(struct iwl_priv *priv) { unsigned long flags; - iwl_rx_allocate(priv); + iwl_rx_allocate(priv, GFP_KERNEL); spin_lock_irqsave(&priv->lock, flags); iwl_rx_queue_restock(priv); @@ -303,6 +300,14 @@ void iwl_rx_replenish(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_rx_replenish); +void iwl_rx_replenish_now(struct iwl_priv *priv) +{ + iwl_rx_allocate(priv, GFP_ATOMIC); + + iwl_rx_queue_restock(priv); +} +EXPORT_SYMBOL(iwl_rx_replenish_now); + /* Assumes that the skb field of the buffers in 'pool' is kept accurate. * If an SKB has been detached, the POOL needs to have its SKB set to NULL @@ -358,6 +363,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; + rxq->write_actual = 0; rxq->free_count = 0; rxq->need_update = 0; return 0; @@ -396,6 +402,7 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; + rxq->write_actual = 0; rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); } @@ -403,18 +410,12 @@ EXPORT_SYMBOL(iwl_rx_queue_reset); int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { - int ret; - unsigned long flags; u32 rb_size; const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ - const u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT why this stalls RX */ + u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } + if (!priv->cfg->use_isr_legacy) + rb_timeout = RX_RB_TIMEOUT; if (priv->cfg->mod_params->amsdu_size_8K) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; @@ -452,35 +453,19 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - iwl_release_nic_access(priv); - iwl_write32(priv, CSR_INT_COALESCING, 0x40); - spin_unlock_irqrestore(&priv->lock, flags); - return 0; } int iwl_rxq_stop(struct iwl_priv *priv) { - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (unlikely(ret)) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } /* stop Rx DMA */ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - return 0; } EXPORT_SYMBOL(iwl_rxq_stop); @@ -582,8 +567,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, iwl_leds_background(priv); - if (priv->cfg->ops->lib->temperature && change) - priv->cfg->ops->lib->temperature(priv); + if (priv->cfg->ops->lib->temp_ops.temperature && change) + priv->cfg->ops->lib->temp_ops.temperature(priv); } EXPORT_SYMBOL(iwl_rx_statistics); @@ -1102,13 +1087,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) rx_status.flag |= RX_FLAG_SHORTPRE; - /* Take shortcut when only in monitor mode */ - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - iwl_pass_packet_to_mac80211(priv, include_phy, - rxb, &rx_status); - return; - } - network_packet = iwl_is_network_packet(priv, header); if (network_packet) { priv->last_rx_rssi = rx_status.signal; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 6330b91e37ce..e26875dbe859 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -445,13 +445,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, unsigned long flags; struct iwl_priv *priv = hw->priv; int ret; - u8 *ssid = NULL; - size_t ssid_len = 0; - - if (req->n_ssids) { - ssid = req->ssids[0].ssid; - ssid_len = req->ssids[0].ssid_len; - } IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -485,13 +478,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } - if (ssid_len) { - priv->one_direct_scan = 1; - priv->direct_ssid_len = ssid_len; - memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } else { - priv->one_direct_scan = 0; - } + priv->scan_request = req; ret = iwl_scan_initiate(priv); @@ -529,74 +516,15 @@ void iwl_bg_scan_check(struct work_struct *data) } EXPORT_SYMBOL(iwl_bg_scan_check); -/** - * iwl_supported_rate_to_ie - fill in the supported rate in IE field - * - * return : set the bit for each supported rate insert in ie - */ -static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, - u16 basic_rate, int *left) -{ - u16 ret_rates = 0, bit; - int i; - u8 *cnt = ie; - u8 *rates = ie + 1; - - for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { - if (bit & supported_rate) { - ret_rates |= bit; - rates[*cnt] = iwl_rates[i].ieee | - ((bit & basic_rate) ? 0x80 : 0x00); - (*cnt)++; - (*left)--; - if ((*left <= 0) || - (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) - break; - } - } - - return ret_rates; -} - - -static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, - u8 *pos, int *left) -{ - struct ieee80211_ht_cap *ht_cap; - - if (!sband || !sband->ht_cap.ht_supported) - return; - - if (*left < sizeof(struct ieee80211_ht_cap)) - return; - - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (struct ieee80211_ht_cap *) pos; - - ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap); - memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16); - ht_cap->ampdu_params_info = - (sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) | - ((sband->ht_cap.ampdu_density << 2) & - IEEE80211_HT_AMPDU_PARM_DENSITY); - *left -= sizeof(struct ieee80211_ht_cap); -} - /** * iwl_fill_probe_req - fill in all required fields and IE for probe request */ -u16 iwl_fill_probe_req(struct iwl_priv *priv, - enum ieee80211_band band, - struct ieee80211_mgmt *frame, - int left) +u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, + const u8 *ies, int ie_len, int left) { int len = 0; u8 *pos = NULL; - u16 active_rates, ret_rates, cck_rates, active_rate_basic; - const struct ieee80211_supported_band *sband = - iwl_get_hw_mode(priv, band); - /* Make sure there is enough space for the probe request, * two mandatory IEs and the data */ @@ -624,62 +552,12 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, len += 2; - /* fill in supported rate */ - left -= 2; - if (left < 0) - return 0; + if (WARN_ON(left < ie_len)) + return len; - *pos++ = WLAN_EID_SUPP_RATES; - *pos = 0; - - /* exclude 60M rate */ - active_rates = priv->rates_mask; - active_rates &= ~IWL_RATE_60M_MASK; - - active_rate_basic = active_rates & IWL_BASIC_RATES_MASK; - - cck_rates = IWL_CCK_RATES_MASK & active_rates; - ret_rates = iwl_supported_rate_to_ie(pos, cck_rates, - active_rate_basic, &left); - active_rates &= ~ret_rates; - - ret_rates = iwl_supported_rate_to_ie(pos, active_rates, - active_rate_basic, &left); - active_rates &= ~ret_rates; - - len += 2 + *pos; - pos += (*pos) + 1; - - if (active_rates == 0) - goto fill_end; - - /* fill in supported extended rate */ - /* ...next IE... */ - left -= 2; - if (left < 0) - return 0; - /* ... fill it in... */ - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos = 0; - iwl_supported_rate_to_ie(pos, active_rates, active_rate_basic, &left); - if (*pos > 0) { - len += 2 + *pos; - pos += (*pos) + 1; - } else { - pos--; - } - - fill_end: - - left -= 2; - if (left < 0) - return 0; - - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos = 0; - iwl_ht_cap_to_ie(sband, pos, &left); - if (*pos > 0) - len += 2 + *pos; + memcpy(pos, ies, ie_len); + len += ie_len; + left -= ie_len; return (u16)len; } @@ -699,11 +577,13 @@ static void iwl_bg_request_scan(struct work_struct *data) int ret = 0; u32 rate_flags = 0; u16 cmd_len; + u16 rx_chain = 0; enum ieee80211_band band; - u8 n_probes = 2; - u8 rx_chain = priv->hw_params.valid_rx_ant; + u8 n_probes = 0; + u8 rx_ant = priv->hw_params.valid_rx_ant; u8 rate; - DECLARE_SSID_BUF(ssid); + bool is_active = false; + int chan_mod; conf = ieee80211_get_hw_conf(priv->hw); @@ -795,19 +675,25 @@ static void iwl_bg_request_scan(struct work_struct *data) scan_suspend_time, interval); } - /* We should add the ability for user to lock to PASSIVE ONLY */ - if (priv->one_direct_scan) { - IWL_DEBUG_SCAN(priv, "Start direct scan for '%s'\n", - print_ssid(ssid, priv->direct_ssid, - priv->direct_ssid_len)); - scan->direct_scan[0].id = WLAN_EID_SSID; - scan->direct_scan[0].len = priv->direct_ssid_len; - memcpy(scan->direct_scan[0].ssid, - priv->direct_ssid, priv->direct_ssid_len); - n_probes++; - } else { - IWL_DEBUG_SCAN(priv, "Start indirect scan.\n"); - } + if (priv->scan_request->n_ssids) { + int i, p = 0; + IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } + is_active = true; + } else + IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; @@ -817,7 +703,9 @@ static void iwl_bg_request_scan(struct work_struct *data) if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { band = IEEE80211_BAND_2GHZ; scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) { + chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) + >> RXON_FLG_CHANNEL_MODE_POS; + if (chan_mod == CHANNEL_MODE_PURE_40) { rate = IWL_RATE_6M_PLCP; } else { rate = IWL_RATE_1M_PLCP; @@ -827,13 +715,18 @@ static void iwl_bg_request_scan(struct work_struct *data) } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { band = IEEE80211_BAND_5GHZ; rate = IWL_RATE_6M_PLCP; - scan->good_CRC_th = IWL_GOOD_CRC_TH; + /* + * If active scaning is requested but a certain channel + * is marked passive, we can do active scanning if we + * detect transmissions. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; /* Force use of chains B and C (0x6) for scan Rx for 4965 * Avoid A (0x1) because of its off-channel reception on A-band. */ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) - rx_chain = 0x6; + rx_ant = ANT_BC; } else { IWL_WARN(priv, "Invalid scan band count\n"); goto done; @@ -845,26 +738,27 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); /* MIMO is not used here, but value is required */ - scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | - cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | - (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | - (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); - - cmd_len = iwl_fill_probe_req(priv, band, - (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); + rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS; + rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; + rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; + rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; + scan->rx_chain = cpu_to_le16(rx_chain); + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) + if (iwl_is_monitor_mode(priv)) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK); scan->channel_count = - iwl_get_channels_for_scan(priv, band, 1, /* active */ - n_probes, + iwl_get_channels_for_scan(priv, band, is_active, n_probes, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); if (scan->channel_count == 0) { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 44ab03a12e40..2addf735b193 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -86,8 +86,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) spin_lock_irqsave(&priv->sta_lock, flags); - if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && - !(priv->stations_39[sta_id].used & IWL_STA_DRIVER_ACTIVE)) + if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", sta_id); @@ -228,15 +227,16 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, } /** - * iwl_add_station_flags - Add station to tables in driver and device + * iwl_add_station - Add station to tables in driver and device */ -u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, - u8 flags, struct ieee80211_sta_ht_cap *ht_info) +u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, + struct ieee80211_sta_ht_cap *ht_info) { - int i; - int sta_id = IWL_INVALID_STATION; struct iwl_station_entry *station; unsigned long flags_spin; + int i; + int sta_id = IWL_INVALID_STATION; + u16 rate; spin_lock_irqsave(&priv->sta_lock, flags_spin); if (is_ap) @@ -288,6 +288,12 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, priv->iw_mode != NL80211_IFTYPE_ADHOC) iwl_set_ht_add_station(priv, sta_id, ht_info); + /* 3945 only */ + rate = (priv->band == IEEE80211_BAND_5GHZ) ? + IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP; + /* Turn on both antennas for the station... */ + station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); /* Add station to device's station table */ @@ -295,7 +301,7 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, return sta_id; } -EXPORT_SYMBOL(iwl_add_station_flags); +EXPORT_SYMBOL(iwl_add_station); static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) { @@ -408,7 +414,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, /** * iwl_remove_station - Remove driver's knowledge of station. */ -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) +int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) { int sta_id = IWL_INVALID_STATION; int i, ret = -EINVAL; @@ -490,7 +496,7 @@ void iwl_clear_stations_table(struct iwl_priv *priv) /* keep track of static keys */ for (i = 0; i < WEP_KEYS_MAX ; i++) { if (priv->wep_keys[i].key_size) - test_and_set_bit(i, &priv->ucode_key_table); + set_bit(i, &priv->ucode_key_table); } spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -946,7 +952,7 @@ EXPORT_SYMBOL(iwl_send_lq_cmd); * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, * which requires station table entry to exist). */ -static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap) +static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) { int i, r; struct iwl_link_quality_cmd link_cmd = { @@ -979,8 +985,9 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap) link_cmd.general_params.single_stream_ant_msk = first_antenna(priv->hw_params.valid_tx_ant); link_cmd.general_params.dual_stream_ant_msk = 3; - link_cmd.agg_params.agg_dis_start_th = 3; - link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); + link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + link_cmd.agg_params.agg_time_limit = + cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); /* Update the rate scaling for control frame Tx to AP */ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; @@ -995,7 +1002,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap) * there is only one AP station with id= IWL_AP_ID * NOTE: mutex must be held before calling this function */ -int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) +int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) { struct ieee80211_sta *sta; struct ieee80211_sta_ht_cap ht_config; @@ -1020,8 +1027,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) rcu_read_unlock(); } - sta_id = iwl_add_station_flags(priv, addr, is_ap, - 0, cur_ht_config); + sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); /* Set up default rate scaling table in device's station table */ iwl_sta_init_lq(priv, addr, is_ap); @@ -1067,8 +1073,8 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return sta_id; /* Create new station table entry */ - sta_id = iwl_add_station_flags(priv, hdr->addr1, - 0, CMD_ASYNC, NULL); + sta_id = iwl_add_station(priv, hdr->addr1, false, + CMD_ASYNC, NULL); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -1079,11 +1085,6 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return priv->hw_params.bcast_sta_id; - /* If we are in monitor mode, use BCAST. This is required for - * packet injection. */ - case NL80211_IFTYPE_MONITOR: - return priv->hw_params.bcast_sta_id; - default: IWL_WARN(priv, "Unknown mode of operation: %d\n", priv->iw_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 59a586b6b56c..6deebade6361 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -51,16 +51,15 @@ void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key); -int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); +int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); +int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_clear_stations_table(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, - int is_ap, u8 flags, +u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); int iwl_sta_rx_agg_start(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 71d5b8a1a73e..85ae7a62109c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -102,13 +102,8 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) return ret; } - /* restore this queue's parameters in nic hardware. */ - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; iwl_write_direct32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); - iwl_release_nic_access(priv); /* else not in power-save mode, uCode will never sleep when we're * trying to tx (during RFKILL, we're not trying to tx). */ @@ -429,11 +424,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) goto error_kw; } spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (unlikely(ret)) { - spin_unlock_irqrestore(&priv->lock, flags); - goto error_reset; - } /* Turn off all Tx DMA fifos */ priv->cfg->ops->lib->txq_set_sched(priv, 0); @@ -441,7 +431,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4) */ @@ -460,7 +449,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) error: iwl_hw_txq_ctx_free(priv); - error_reset: iwl_free_dma_ptr(priv, &priv->kw); error_kw: iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); @@ -478,10 +466,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) /* Turn off all Tx DMA fifos */ spin_lock_irqsave(&priv->lock, flags); - if (iwl_grab_nic_access(priv)) { - spin_unlock_irqrestore(&priv->lock, flags); - return; - } priv->cfg->ops->lib->txq_set_sched(priv, 0); @@ -492,7 +476,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); } - iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); /* Deallocate memory for all Tx queues */ @@ -728,7 +711,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != NL80211_IFTYPE_MONITOR || + (!iwl_is_monitor_mode(priv) || !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */ (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || @@ -1183,8 +1166,10 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) __func__, ra, tid); sta_id = iwl_find_station(priv, ra); - if (sta_id == IWL_INVALID_STATION) + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; + } if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); @@ -1192,8 +1177,10 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) } txq_id = iwl_txq_ctx_activate_free(priv); - if (txq_id == -1) + if (txq_id == -1) { + IWL_ERR(priv, "No free aggregation queue available\n"); return -ENXIO; + } spin_lock_irqsave(&priv->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; @@ -1207,7 +1194,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) return ret; if (tid_data->tfds_in_queue == 0) { - IWL_ERR(priv, "HW queue is empty\n"); + IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); } else { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ff4d0e41d7c4..83d31606dd00 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -95,188 +95,6 @@ struct iwl_mod_params iwl3945_mod_params = { /* the rest are 0 by default */ }; -/*************** STATION TABLE MANAGEMENT **** - * mac80211 should be examined to determine if sta_info is duplicating - * the functionality provided here - */ - -/**************************************************************/ -#if 0 /* temporary disable till we add real remove station */ -/** - * iwl3945_remove_station - Remove driver's knowledge of station. - * - * NOTE: This does not remove station from device's station table. - */ -static u8 iwl3945_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) -{ - int index = IWL_INVALID_STATION; - int i; - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - - if (is_ap) - index = IWL_AP_ID; - else if (is_broadcast_ether_addr(addr)) - index = priv->hw_params.bcast_sta_id; - else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) - if (priv->stations_39[i].used && - !compare_ether_addr(priv->stations_39[i].sta.sta.addr, - addr)) { - index = i; - break; - } - - if (unlikely(index == IWL_INVALID_STATION)) - goto out; - - if (priv->stations_39[index].used) { - priv->stations_39[index].used = 0; - priv->num_stations--; - } - - BUG_ON(priv->num_stations < 0); - -out: - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; -} -#endif - -/** - * iwl3945_clear_stations_table - Clear the driver's station table - * - * NOTE: This does not clear or otherwise alter the device's station table. - */ -static void iwl3945_clear_stations_table(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->num_stations = 0; - memset(priv->stations_39, 0, sizeof(priv->stations_39)); - - spin_unlock_irqrestore(&priv->sta_lock, flags); -} - -/** - * iwl3945_add_station - Add station to station tables in driver and device - */ -u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags) -{ - int i; - int index = IWL_INVALID_STATION; - struct iwl3945_station_entry *station; - unsigned long flags_spin; - u8 rate; - - spin_lock_irqsave(&priv->sta_lock, flags_spin); - if (is_ap) - index = IWL_AP_ID; - else if (is_broadcast_ether_addr(addr)) - index = priv->hw_params.bcast_sta_id; - else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { - if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr, - addr)) { - index = i; - break; - } - - if (!priv->stations_39[i].used && - index == IWL_INVALID_STATION) - index = i; - } - - /* These two conditions has the same outcome but keep them separate - since they have different meaning */ - if (unlikely(index == IWL_INVALID_STATION)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - return index; - } - - if (priv->stations_39[index].used && - !compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - return index; - } - - IWL_DEBUG_ASSOC(priv, "Add STA ID %d: %pM\n", index, addr); - station = &priv->stations_39[index]; - station->used = 1; - priv->num_stations++; - - /* Set up the REPLY_ADD_STA command to send to device */ - memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd)); - memcpy(station->sta.sta.addr, addr, ETH_ALEN); - station->sta.mode = 0; - station->sta.sta.sta_id = index; - station->sta.station_flags = 0; - - if (priv->band == IEEE80211_BAND_5GHZ) - rate = IWL_RATE_6M_PLCP; - else - rate = IWL_RATE_1M_PLCP; - - /* Turn on both antennas for the station... */ - station->sta.rate_n_flags = - iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK); - - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - - /* Add station to device's station table */ - iwl_send_add_sta(priv, - (struct iwl_addsta_cmd *)&station->sta, flags); - return index; - -} - -static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) -{ - int rc = 0; - struct iwl_rx_packet *res = NULL; - struct iwl3945_rxon_assoc_cmd rxon_assoc; - struct iwl_host_cmd cmd = { - .id = REPLY_RXON_ASSOC, - .len = sizeof(rxon_assoc), - .meta.flags = CMD_WANT_SKB, - .data = &rxon_assoc, - }; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved = 0; - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl_rx_packet *)cmd.meta.u.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); - - return rc; -} - /** * iwl3945_get_antenna_flags - Get antenna flags for RXON command * @priv: eeprom and antenna fields are used to determine antenna flags @@ -314,150 +132,6 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) return 0; /* "diversity" is default if error */ } -/** - * iwl3945_commit_rxon - commit staging_rxon to hardware - * - * The RXON command in staging_rxon is committed to the hardware and - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. - */ -static int iwl3945_commit_rxon(struct iwl_priv *priv) -{ - /* cast away the const for active_rxon in this function */ - struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; - struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; - int rc = 0; - bool new_assoc = - !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); - - if (!iwl_is_alive(priv)) - return -1; - - /* always get timestamp with Rx frame */ - staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; - - /* select antenna */ - staging_rxon->flags &= - ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); - staging_rxon->flags |= iwl3945_get_antenna_flags(priv); - - rc = iwl_check_rxon_cmd(priv); - if (rc) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); - return -EINVAL; - } - - /* If we don't need to send a full RXON, we can use - * iwl3945_rxon_assoc_cmd which is used to reconfigure filter - * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv)) { - rc = iwl3945_send_rxon_assoc(priv); - if (rc) { - IWL_ERR(priv, "Error setting RXON_ASSOC " - "configuration (%d).\n", rc); - return rc; - } - - memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - - return 0; - } - - /* If we are currently associated and the new config requires - * an RXON_ASSOC and the new config wants the associated mask enabled, - * we must clear the associated from the active configuration - * before we apply the new config */ - if (iwl_is_associated(priv) && new_assoc) { - IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - - /* - * reserved4 and 5 could have been filled by the iwlcore code. - * Let's clear them before pushing to the 3945. - */ - active_rxon->reserved4 = 0; - active_rxon->reserved5 = 0; - rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), - &priv->active_rxon); - - /* If the mask clearing failed then we set - * active_rxon back to what it was previously */ - if (rc) { - active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERR(priv, "Error clearing ASSOC_MSK on current " - "configuration (%d).\n", rc); - return rc; - } - } - - IWL_DEBUG_INFO(priv, "Sending RXON\n" - "* with%s RXON_FILTER_ASSOC_MSK\n" - "* channel = %d\n" - "* bssid = %pM\n", - (new_assoc ? "" : "out"), - le16_to_cpu(staging_rxon->channel), - staging_rxon->bssid_addr); - - /* - * reserved4 and 5 could have been filled by the iwlcore code. - * Let's clear them before pushing to the 3945. - */ - staging_rxon->reserved4 = 0; - staging_rxon->reserved5 = 0; - - iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); - - /* Apply the new configuration */ - rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), - staging_rxon); - if (rc) { - IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); - return rc; - } - - memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - - iwl3945_clear_stations_table(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - rc = priv->cfg->ops->lib->send_tx_power(priv); - if (rc) { - IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); - return rc; - } - - /* Add the broadcast address so we can send broadcast frames */ - if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == - IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); - return -EIO; - } - - /* If we have set the ASSOC_MSK and we are in BSS mode then - * add the IWL_AP_ID to the station rate table */ - if (iwl_is_associated(priv) && - (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, - 1, 0) - == IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding AP address for transmit\n"); - return -EIO; - } - - /* Init the hardware's rate fallback order based on the band */ - rc = iwl3945_init_hw_rate_table(priv); - if (rc) { - IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); - return -EIO; - } - - return 0; -} - static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) @@ -477,32 +151,31 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, key_flags &= ~STA_KEY_FLG_INVALID; spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations_39[sta_id].keyinfo.alg = keyconf->alg; - priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen; - memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key, + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen); - memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key, + memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen); - if ((priv->stations_39[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) + if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC) - priv->stations_39[sta_id].sta.key.key_offset = + priv->stations[sta_id].sta.key.key_offset = iwl_get_free_ucode_key_index(priv); /* else, we are overriding an existing key => no need to allocated room * in uCode. */ - WARN(priv->stations_39[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, "no space for a new key"); - priv->stations_39[sta_id].sta.key.key_flags = key_flags; - priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + priv->stations[sta_id].sta.key.key_flags = key_flags; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n"); - ret = iwl_send_add_sta(priv, - (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, CMD_ASYNC); + ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -528,17 +201,16 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) unsigned long flags; spin_lock_irqsave(&priv->sta_lock, flags); - memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key)); - memset(&priv->stations_39[sta_id].sta.key, 0, + memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); + memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); - priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; - priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); - iwl_send_add_sta(priv, - (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0); + iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); return 0; } @@ -739,7 +411,8 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.atim_window = 0; } else { priv->rxon_timing.beacon_interval = - iwl3945_adjust_beacon_interval(conf->beacon_int); + 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; @@ -758,35 +431,6 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl3945_set_mode(struct iwl_priv *priv, int mode) -{ - if (mode == NL80211_IFTYPE_ADHOC) { - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->staging_rxon.channel)); - - if (!ch_info || !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d not IBSS channel\n", - le16_to_cpu(priv->staging_rxon.channel)); - return -EINVAL; - } - } - - iwl_connection_init_rx_config(priv, mode); - - iwl3945_clear_stations_table(priv); - - /* don't commit rxon if rf-kill is on*/ - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - - iwl3945_commit_rxon(priv); - - return 0; -} - static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_info *info, struct iwl_cmd *cmd, @@ -794,8 +438,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, int sta_id) { struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; - struct iwl3945_hw_key *keyinfo = - &priv->stations_39[sta_id].keyinfo; + struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; switch (keyinfo->alg) { case ALG_CCMP: @@ -893,64 +536,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, tx->next_frame_len = 0; } -/** - * iwl3945_get_sta_id - Find station's index within station table - */ -static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) -{ - int sta_id; - u16 fc = le16_to_cpu(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)) - return priv->hw_params.bcast_sta_id; - - switch (priv->iw_mode) { - - /* If we are a client station in a BSS network, use the special - * AP station entry (that's the only station we communicate with) */ - case NL80211_IFTYPE_STATION: - return IWL_AP_ID; - - /* If we are an AP, then find the station, or use BCAST */ - case NL80211_IFTYPE_AP: - sta_id = iwl3945_hw_find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - return priv->hw_params.bcast_sta_id; - - /* If this frame is going out to an IBSS network, find the station, - * or create a new station table entry */ - case NL80211_IFTYPE_ADHOC: { - /* Create new station table entry */ - sta_id = iwl3945_hw_find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC); - - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - IWL_DEBUG_DROP(priv, "Station %pM not in station map. " - "Defaulting to broadcast...\n", - hdr->addr1); - iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_params.bcast_sta_id; - } - /* If we are in monitor mode, use BCAST. This is required for - * packet injection. */ - case NL80211_IFTYPE_MONITOR: - return priv->hw_params.bcast_sta_id; - - default: - IWL_WARN(priv, "Unknown mode of operation: %d\n", - priv->iw_mode); - return priv->hw_params.bcast_sta_id; - } -} - /* * start REPLY_TX command process */ @@ -1004,7 +589,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */ + (!iwl_is_monitor_mode(priv)) && /* packet injection */ (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); @@ -1016,7 +601,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find (or create) index into station table for destination station */ - sta_id = iwl3945_get_sta_id(priv, hdr); + sta_id = iwl_get_sta_id(priv, hdr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -1028,7 +613,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - seq_number = priv->stations_39[sta_id].tid[tid].seq_number & + seq_number = priv->stations[sta_id].tid[tid].seq_number & IEEE80211_SCTL_SEQ; hdr->seq_ctrl = cpu_to_le16(seq_number) | (hdr->seq_ctrl & @@ -1088,7 +673,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; if (qc) - priv->stations_39[sta_id].tid[tid].seq_number = seq_number; + priv->stations[sta_id].tid[tid].seq_number = seq_number; } else { wait_write_ptr = 1; txq->need_update = 0; @@ -1424,18 +1009,12 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, clear_bit(STATUS_RF_KILL_HW, &priv->status); - if (flags & SW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_SW, &priv->status); - else - clear_bit(STATUS_RF_KILL_SW, &priv->status); - iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->status)) || - (test_bit(STATUS_RF_KILL_SW, &status) != - test_bit(STATUS_RF_KILL_SW, &priv->status))) - queue_work(priv->workqueue, &priv->rf_kill); + test_bit(STATUS_RF_KILL_HW, &priv->status))) + wiphy_rfkill_set_hw_state(priv->hw->wiphy, + test_bit(STATUS_RF_KILL_HW, &priv->status)); else wake_up_interruptible(&priv->wait_command_queue); } @@ -1591,7 +1170,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) /* If we've added more space for the firmware to place data, tell it. * Increment device's write pointer in multiples of 8. */ - if ((write != (rxq->write & ~0x7)) + if ((rxq->write_actual != (rxq->write & ~0x7)) || (abs(rxq->write - rxq->read) > 7)) { spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; @@ -1612,21 +1191,30 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) * Also restock the Rx queue via iwl3945_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwl3945_rx_allocate(struct iwl_priv *priv) +static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) { struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; - spin_lock_irqsave(&rxq->lock, flags); - while (!list_empty(&rxq->rx_used)) { + + while (1) { + spin_lock_irqsave(&rxq->lock, flags); + + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + return; + } + element = rxq->rx_used.next; rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + spin_unlock_irqrestore(&rxq->lock, flags); /* Alloc a new receive buffer */ rxb->skb = alloc_skb(priv->hw_params.rx_buf_size, - __GFP_NOWARN | GFP_ATOMIC); + priority); if (!rxb->skb) { if (net_ratelimit()) IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); @@ -1644,18 +1232,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) */ skb_reserve(rxb->skb, 4); - priv->alloc_rxb_skb++; - list_del(element); - /* Get physical address of RB/SKB */ rxb->real_dma_addr = pci_map_single(priv->pci_dev, rxb->skb->data, priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); + + spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &rxq->rx_free); + priv->alloc_rxb_skb++; rxq->free_count++; + spin_unlock_irqrestore(&rxq->lock, flags); } - spin_unlock_irqrestore(&rxq->lock, flags); } void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) @@ -1685,33 +1273,30 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; rxq->free_count = 0; + rxq->write_actual = 0; spin_unlock_irqrestore(&rxq->lock, flags); } -/* - * this should be called while priv->lock is locked - */ -static void __iwl3945_rx_replenish(void *data) -{ - struct iwl_priv *priv = data; - - iwl3945_rx_allocate(priv); - iwl3945_rx_queue_restock(priv); -} - - void iwl3945_rx_replenish(void *data) { struct iwl_priv *priv = data; unsigned long flags; - iwl3945_rx_allocate(priv); + iwl3945_rx_allocate(priv, GFP_KERNEL); spin_lock_irqsave(&priv->lock, flags); iwl3945_rx_queue_restock(priv); spin_unlock_irqrestore(&priv->lock, flags); } +static void iwl3945_rx_replenish_now(struct iwl_priv *priv) +{ + iwl3945_rx_allocate(priv, GFP_ATOMIC); + + iwl3945_rx_queue_restock(priv); +} + + /* Assumes that the skb field of the buffers in 'pool' is kept accurate. * If an SKB has been detached, the POOL needs to have its SKB set to NULL * This free routine walks the list of POOL entries and if SKB is set to @@ -1834,13 +1419,19 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) unsigned long flags; u8 fill_rx = 0; u32 count = 8; + int total_empty = 0; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; i = rxq->read; - if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) + /* calculate total frames need to be restock after handling RX */ + total_empty = r - priv->rxq.write_actual; + if (total_empty < 0) + total_empty += RX_QUEUE_SIZE; + + if (total_empty > (RX_QUEUE_SIZE / 2)) fill_rx = 1; /* Rx interrupt, but nothing sent from uCode */ if (i == r) @@ -1879,6 +1470,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; } else { /* No handling needed */ IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, @@ -1916,7 +1508,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) count++; if (count >= 8) { priv->rxq.read = i; - __iwl3945_rx_replenish(priv); + iwl3945_rx_replenish_now(priv); count = 0; } } @@ -1924,7 +1516,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) /* Backtrack one entry */ priv->rxq.read = i; - iwl3945_rx_queue_restock(priv); + if (fill_rx) + iwl3945_rx_replenish_now(priv); + else + iwl3945_rx_queue_restock(priv); } /* call this function to flush any scheduled tasklet */ @@ -1963,7 +1558,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) u32 i; u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; - int rc; base = le32_to_cpu(priv->card_alive.error_event_table_ptr); @@ -1972,11 +1566,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) return; } - rc = iwl_grab_nic_access(priv); - if (rc) { - IWL_WARN(priv, "Can not read from adapter at this time.\n"); - return; - } count = iwl_read_targ_mem(priv, base); @@ -2011,8 +1600,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) ilink1, ilink2, data1); } - iwl_release_nic_access(priv); - } #define EVENT_START_OFFSET (6 * sizeof(u32)) @@ -2020,7 +1607,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) /** * iwl3945_print_event_log - Dump error event log to syslog * - * NOTE: Must be called with iwl_grab_nic_access() already obtained! */ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) @@ -2063,7 +1649,6 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) { - int rc; u32 base; /* SRAM byte address of event log header */ u32 capacity; /* event log capacity in # entries */ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ @@ -2077,12 +1662,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) return; } - rc = iwl_grab_nic_access(priv); - if (rc) { - IWL_WARN(priv, "Can not read from adapter at this time.\n"); - return; - } - /* event log header */ capacity = iwl_read_targ_mem(priv, base); mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); @@ -2094,7 +1673,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) /* bail out if nothing in log */ if (size == 0) { IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - iwl_release_nic_access(priv); return; } @@ -2110,24 +1688,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) /* (then/else) start at top of log */ iwl3945_print_event_log(priv, 0, next_entry, mode); - iwl_release_nic_access(priv); -} - -static void iwl3945_error_recovery(struct iwl_priv *priv) -{ - unsigned long flags; - - memcpy(&priv->staging_rxon, &priv->recovery_rxon, - sizeof(priv->staging_rxon)); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); - - iwl3945_add_station(priv, priv->bssid, 1, 0); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); - priv->error_recovering = 0; - spin_unlock_irqrestore(&priv->lock, flags); } static void iwl3945_irq_tasklet(struct iwl_priv *priv) @@ -2178,6 +1738,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); + priv->isr_stats.hw++; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -2190,13 +1751,17 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) #ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) + if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); + priv->isr_stats.sch++; + } /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) + if (inta & CSR_INT_BIT_ALIVE) { IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } } #endif /* Safely ignore these bits for debug checks below */ @@ -2206,6 +1771,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_SW_ERR) { IWL_ERR(priv, "Microcode SW error detected. " "Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + priv->isr_stats.sw_err = inta; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -2221,6 +1788,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) iwl_txq_update_write_ptr(priv, &priv->txq[4]); iwl_txq_update_write_ptr(priv, &priv->txq[5]); + priv->isr_stats.wakeup++; handled |= CSR_INT_BIT_WAKEUP; } @@ -2229,27 +1797,28 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { iwl3945_rx_handle(priv); + priv->isr_stats.rx++; handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); } if (inta & CSR_INT_BIT_FH_TX) { IWL_DEBUG_ISR(priv, "Tx interrupt\n"); + priv->isr_stats.tx++; iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); - if (!iwl_grab_nic_access(priv)) { - iwl_write_direct32(priv, FH39_TCSR_CREDIT - (FH39_SRVC_CHNL), 0x0); - iwl_release_nic_access(priv); - } + iwl_write_direct32(priv, FH39_TCSR_CREDIT + (FH39_SRVC_CHNL), 0x0); handled |= CSR_INT_BIT_FH_TX; } - if (inta & ~handled) + if (inta & ~handled) { IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } - if (inta & ~CSR_INI_SET_MASK) { + if (inta & ~priv->inta_mask) { IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~CSR_INI_SET_MASK); + inta & ~priv->inta_mask); IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); } @@ -2413,10 +1982,6 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - rc = iwl_grab_nic_access(priv); - if (rc) - return rc; - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWL39_RTC_INST_LOWER_BOUND); @@ -2437,7 +2002,6 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le } } - iwl_release_nic_access(priv); if (!errcnt) IWL_DEBUG_INFO(priv, @@ -2461,10 +2025,6 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - rc = iwl_grab_nic_access(priv); - if (rc) - return rc; - for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log @@ -2485,8 +2045,6 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 } } - iwl_release_nic_access(priv); - return rc; } @@ -2810,20 +2368,11 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) { dma_addr_t pinst; dma_addr_t pdata; - int rc = 0; - unsigned long flags; /* bits 31:0 for 3945 */ pinst = priv->ucode_code.p_addr; pdata = priv->ucode_data_backup.p_addr; - spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - /* Tell bootstrap uCode where to find image to load */ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); @@ -2835,13 +2384,9 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, priv->ucode_code.len | BSM_DRAM_INST_LOAD); - iwl_release_nic_access(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); - return rc; + return 0; } /** @@ -2887,11 +2432,6 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv) queue_work(priv->workqueue, &priv->restart); } - -/* temporary */ -static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *skb); - /** * iwl3945_alive_start - called after REPLY_ALIVE notification received * from protocol/runtime uCode (initialization uCode's @@ -2899,7 +2439,6 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, */ static void iwl3945_alive_start(struct iwl_priv *priv) { - int rc = 0; int thermal_spin = 0; u32 rfkill; @@ -2922,17 +2461,10 @@ static void iwl3945_alive_start(struct iwl_priv *priv) goto restart; } - iwl3945_clear_stations_table(priv); - - rc = iwl_grab_nic_access(priv); - if (rc) { - IWL_WARN(priv, "Can not read RFKILL status from adapter\n"); - return; - } + iwl_clear_stations_table(priv); rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); - iwl_release_nic_access(priv); if (rfkill & 0x1) { clear_bit(STATUS_RF_KILL_HW, &priv->status); @@ -2952,9 +2484,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) /* After the ALIVE response, we can send commands to 3945 uCode */ set_bit(STATUS_ALIVE, &priv->status); - /* Clear out the uCode error bit if it is set */ - clear_bit(STATUS_FW_ERROR, &priv->status); - if (iwl_is_rfkill(priv)) return; @@ -2981,7 +2510,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl_send_bt_config(priv); /* Configure the adapter for unassociated operation */ - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl3945_reg_txpower_periodic(priv); @@ -2991,17 +2520,17 @@ static void iwl3945_alive_start(struct iwl_priv *priv) set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - if (priv->error_recovering) - iwl3945_error_recovery(priv); - /* reassociate for ADHOC mode */ if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (beacon) - iwl3945_mac_beacon_update(priv->hw, beacon); + iwl_mac_beacon_update(priv->hw, beacon); } + if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) + iwl_set_mode(priv, priv->iw_mode); + return; restart: @@ -3024,7 +2553,7 @@ static void __iwl3945_down(struct iwl_priv *priv) set_bit(STATUS_EXIT_PENDING, &priv->status); iwl3945_led_unregister(priv); - iwl3945_clear_stations_table(priv); + iwl_clear_stations_table(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -3047,31 +2576,23 @@ static void __iwl3945_down(struct iwl_priv *priv) ieee80211_stop_queues(priv->hw); /* If we have not previously called iwl3945_init() then - * clear all bits but the RF Kill and SUSPEND bits and return */ + * clear all bits but the RF Kill bits and return */ if (!iwl_is_init(priv)) { priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_RF_KILL_SW, &priv->status) << - STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; goto exit; } - /* ...otherwise clear out all the status bits but the RF Kill and - * SUSPEND bits and continue taking the NIC down. */ + /* ...otherwise clear out all the status bits but the RF Kill + * bit and continue taking the NIC down. */ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_RF_KILL_SW, &priv->status) << - STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << STATUS_FW_ERROR | test_bit(STATUS_EXIT_PENDING, &priv->status) << @@ -3085,17 +2606,12 @@ static void __iwl3945_down(struct iwl_priv *priv) iwl3945_hw_txq_ctx_stop(priv); iwl3945_hw_rxq_stop(priv); - spin_lock_irqsave(&priv->lock, flags); - if (!iwl_grab_nic_access(priv)) { - iwl_write_prph(priv, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->lock, flags); + iwl_write_prph(priv, APMG_CLK_DIS_REG, + APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); - if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) + if (exit_pending) priv->cfg->ops->lib->apm_ops.stop(priv); else priv->cfg->ops->lib->apm_ops.reset(priv); @@ -3131,12 +2647,6 @@ static int __iwl3945_up(struct iwl_priv *priv) return -EIO; } - if (test_bit(STATUS_RF_KILL_SW, &priv->status)) { - IWL_WARN(priv, "Radio disabled by SW RF kill (module " - "parameter)\n"); - return -ENODEV; - } - if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { IWL_ERR(priv, "ucode not available for device bring up\n"); return -EIO; @@ -3148,10 +2658,8 @@ static int __iwl3945_up(struct iwl_priv *priv) clear_bit(STATUS_RF_KILL_HW, &priv->status); else { set_bit(STATUS_RF_KILL_HW, &priv->status); - if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { - IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); - return -ENODEV; - } + IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); + return -ENODEV; } iwl_write32(priv, CSR_INT, 0xFFFFFFFF); @@ -3187,7 +2695,7 @@ static int __iwl3945_up(struct iwl_priv *priv) for (i = 0; i < MAX_HW_RESTARTS; i++) { - iwl3945_clear_stations_table(priv); + iwl_clear_stations_table(priv); /* load bootstrap state machine, * load bootstrap program into processor's memory, @@ -3255,15 +2763,14 @@ static void iwl3945_rfkill_poll(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, rfkill_poll.work); - unsigned long status = priv->status; if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); else set_bit(STATUS_RF_KILL_HW, &priv->status); - if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status)) - queue_work(priv->workqueue, &priv->rf_kill); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, + test_bit(STATUS_RF_KILL_HW, &priv->status)); queue_delayed_work(priv->workqueue, &priv->rfkill_poll, round_jiffies_relative(2 * HZ)); @@ -3283,9 +2790,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) int rc = 0; struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; - u8 n_probes = 2; + u8 n_probes = 0; enum ieee80211_band band; - DECLARE_SSID_BUF(ssid); + bool is_active = false; conf = ieee80211_get_hw_conf(priv->hw); @@ -3386,18 +2893,25 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan_suspend_time, interval); } - /* We should add the ability for user to lock to PASSIVE ONLY */ - if (priv->one_direct_scan) { - IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n", - print_ssid(ssid, priv->direct_ssid, - priv->direct_ssid_len)); - scan->direct_scan[0].id = WLAN_EID_SSID; - scan->direct_scan[0].len = priv->direct_ssid_len; - memcpy(scan->direct_scan[0].ssid, - priv->direct_ssid, priv->direct_ssid_len); - n_probes++; + if (priv->scan_request->n_ssids) { + int i, p = 0; + IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } + is_active = true; } else - IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n"); + IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n"); /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ @@ -3414,7 +2928,12 @@ static void iwl3945_bg_request_scan(struct work_struct *data) band = IEEE80211_BAND_2GHZ; } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { scan->tx_cmd.rate = IWL_RATE_6M_PLCP; - scan->good_CRC_th = IWL_GOOD_CRC_TH; + /* + * If active scaning is requested but a certain channel + * is marked passive, we can do active scanning if we + * detect transmissions. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; band = IEEE80211_BAND_5GHZ; } else { IWL_WARN(priv, "Invalid scan band count\n"); @@ -3422,19 +2941,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data) } scan->tx_cmd.len = cpu_to_le16( - iwl_fill_probe_req(priv, band, - (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan))); + iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan))); /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) + if (iwl_is_monitor_mode(priv)) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->channel_count = - iwl3945_get_channels_for_scan(priv, band, 1, /* active */ - n_probes, + iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); if (scan->channel_count == 0) { @@ -3482,7 +3002,6 @@ static void iwl3945_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl3945_up(priv); mutex_unlock(&priv->mutex); - iwl_rfkill_set_hw_state(priv); } static void iwl3945_bg_restart(struct work_struct *data) @@ -3492,8 +3011,17 @@ static void iwl3945_bg_restart(struct work_struct *data) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - iwl3945_down(priv); - queue_work(priv->workqueue, &priv->up); + if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + mutex_lock(&priv->mutex); + priv->vif = NULL; + priv->is_open = 0; + mutex_unlock(&priv->mutex); + iwl3945_down(priv); + ieee80211_restart_hw(priv->hw); + } else { + iwl3945_down(priv); + queue_work(priv->workqueue, &priv->up); + } } static void iwl3945_bg_rx_replenish(struct work_struct *data) @@ -3511,7 +3039,7 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl3945_post_associate(struct iwl_priv *priv) +void iwl3945_post_associate(struct iwl_priv *priv) { int rc = 0; struct ieee80211_conf *conf = NULL; @@ -3536,7 +3064,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); iwl3945_setup_rxon_timing(priv); @@ -3569,7 +3097,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) } - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: @@ -3579,7 +3107,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) case NL80211_IFTYPE_ADHOC: priv->assoc_id = 1; - iwl3945_add_station(priv, priv->bssid, 0, 0); + iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL); iwl3945_sync_sta(priv, IWL_STA_ID, (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, @@ -3601,8 +3129,6 @@ static void iwl3945_post_associate(struct iwl_priv *priv) priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } -static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); - /***************************************************************************** * * mac80211 entry point functions @@ -3638,16 +3164,11 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); - iwl_rfkill_set_hw_state(priv); - if (ret) goto out_release_irq; IWL_DEBUG_INFO(priv, "Start UP work.\n"); - if (test_bit(STATUS_IN_SUSPEND, &priv->status)) - return 0; - /* Wait for START_ALIVE from ucode. Otherwise callbacks from * mac80211 will not be run successfully. */ ret = wait_event_interruptible_timeout(priv->wait_command_queue, @@ -3726,144 +3247,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); - - if (priv->vif) { - IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - } - - if (iwl_is_ready(priv)) - iwl3945_set_mode(priv, conf->type); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - -/** - * iwl3945_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ -static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - int ret = 0; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter to channel %d\n", - conf->channel->hw_value); - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - ret = -EIO; - goto out; - } - - if (unlikely(!iwl3945_mod_params.disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - set_bit(STATUS_CONF_PENDING, &priv->status); - mutex_unlock(&priv->mutex); - return 0; - } - - spin_lock_irqsave(&priv->lock, flags); - - ch_info = iwl_get_channel_info(priv, conf->channel->band, - conf->channel->hw_value); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN(priv, - "Channel %d [%d] is INVALID for this band.\n", - conf->channel->hw_value, conf->channel->band); - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - spin_unlock_irqrestore(&priv->lock, flags); - ret = -EINVAL; - goto out; - } - - iwl_set_rxon_channel(priv, conf->channel); - - iwl_set_flags_for_band(priv, conf->channel->band); - - /* The list of supported rates and rate mask can be different - * for each phymode; since the phymode may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - -#ifdef IEEE80211_CONF_CHANNEL_SWITCH - if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { - iwl3945_hw_channel_switch(priv, conf->channel); - goto out; - } -#endif - - if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { - if (conf->radio_enabled && - iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " - "waiting for uCode\n"); - goto out; - } - - if (!conf->radio_enabled) { - iwl_radio_kill_sw_disable_radio(priv); - IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); - goto out; - } - } - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF kill\n"); - ret = -EIO; - goto out; - } - - iwl_set_rate(priv); - - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwl3945_commit_rxon(priv); - else - IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n"); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -out: - clear_bit(STATUS_CONF_PENDING, &priv->status); - mutex_unlock(&priv->mutex); - return ret; -} - -static void iwl3945_config_ap(struct iwl_priv *priv) +void iwl3945_config_ap(struct iwl_priv *priv) { int rc = 0; @@ -3875,7 +3259,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv) /* RXON - unassoc (to set timing command) */ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); /* RXON Timing */ memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -3911,8 +3295,8 @@ static void iwl3945_config_ap(struct iwl_priv *priv) } /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); - iwl3945_add_station(priv, iwl_bcast_addr, 0, 0); + iwlcore_commit_rxon(priv); + iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL); } iwl3945_send_beacon_cmd(priv); @@ -3921,189 +3305,6 @@ static void iwl3945_config_ap(struct iwl_priv *priv) * clear sta table, add BCAST sta... */ } -static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - int rc; - - if (conf == NULL) - return -EIO; - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); - return 0; - } - - /* handle this temporarily here */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) - return -ENOMEM; - mutex_lock(&priv->mutex); - rc = iwl3945_mac_beacon_update(hw, beacon); - mutex_unlock(&priv->mutex); - if (rc) - return rc; - } - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - - if (conf->bssid) - IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); - -/* - * very dubious code was here; the probe filtering flag is never set: - * - if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && - !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { - */ - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - if (!conf->bssid) { - conf->bssid = priv->mac_addr; - memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", - conf->bssid); - } - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); - } - - if (iwl_is_rfkill(priv)) - goto done; - - if (conf->bssid && !is_zero_ether_addr(conf->bssid) && - !is_multicast_ether_addr(conf->bssid)) { - /* If there is currently a HW scan going on in the background - * then we need to cancel it else the RXON below will fail. */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress " - "after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n"); - mutex_unlock(&priv->mutex); - return -EAGAIN; - } - memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); - - /* TODO: Audit driver for usage of these members and see - * if mac80211 deprecates them (priv->bssid looks like it - * shouldn't be there, but I haven't scanned the IBSS code - * to verify) - jpk */ - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl3945_config_ap(priv); - else { - rc = iwl3945_commit_rxon(priv); - if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) - iwl3945_add_station(priv, - priv->active_rxon.bssid_addr, 1, 0); - } - - } else { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); - } - - done: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - - return 0; -} - -static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - if (iwl_is_ready_rf(priv)) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); - } - if (priv->vif == conf->vif) { - priv->vif = NULL; - memset(priv->bssid, 0, ETH_ALEN); - } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) - -static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", - bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - /* This should never happen as this function should - * never be called from interrupt context. */ - if (WARN_ON_ONCE(in_interrupt())) - return; - if (bss_conf->assoc) { - priv->assoc_id = bss_conf->aid; - priv->beacon_int = bss_conf->beacon_int; - priv->timestamp = bss_conf->timestamp; - priv->assoc_capability = bss_conf->assoc_capability; - priv->power_data.dtim_period = bss_conf->dtim_period; - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - mutex_lock(&priv->mutex); - iwl3945_post_associate(priv); - mutex_unlock(&priv->mutex); - } else { - priv->assoc_id = 0; - IWL_DEBUG_MAC80211(priv, - "DISASSOC %d\n", bss_conf->assoc); - } - } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211(priv, - "Associated Changes %d\n", changes); - iwl3945_send_rxon_assoc(priv); - } - -} - static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4126,7 +3327,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static_key = !iwl_is_associated(priv); if (!static_key) { - sta_id = iwl3945_hw_find_station(priv, addr); + sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); @@ -4162,185 +3363,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - int q; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); - return 0; - } - - q = AC_NUM - 1 - queue; - - spin_lock_irqsave(&priv->lock, flags); - - priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->txop * 32)); - - priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; - priv->qos_data.qos_active = 1; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_activate_qos(priv, 1); - else if (priv->assoc_id && iwl_is_associated(priv)) - iwl_activate_qos(priv, 0); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - -static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - int i, avail; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; - q = &txq->q; - avail = iwl_queue_space(q); - - stats[i].len = q->n_window - avail; - stats[i].limit = q->n_window - q->high_mark; - stats[i].count = q->n_window; - - } - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} - -static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - iwl_reset_qos(priv); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = 0; - priv->assoc_capability = 0; - - /* new association get rid of ibss beacon skb */ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = NULL; - - priv->beacon_int = priv->hw->conf.beacon_int; - priv->timestamp = 0; - if ((priv->iw_mode == NL80211_IFTYPE_STATION)) - priv->beacon_int = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); - } - - /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - - IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); - mutex_unlock(&priv->mutex); - return; - } - - iwl_set_rate(priv); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -} - -static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - priv->assoc_id = 0; - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - iwl3945_post_associate(priv); - - - return 0; -} - /***************************************************************************** * * sysfs attributes @@ -4359,7 +3381,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%08X\n", priv->debug_level); } @@ -4367,7 +3389,7 @@ static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -4388,7 +3410,7 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_alive(priv)) return -EAGAIN; @@ -4401,7 +3423,7 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%d\n", priv->tx_power_user_lmt); } @@ -4409,7 +3431,7 @@ static ssize_t store_tx_power(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); char *p = (char *)buf; u32 val; @@ -4427,7 +3449,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); } @@ -4436,7 +3458,7 @@ static ssize_t store_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); u32 flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -4448,7 +3470,7 @@ static ssize_t store_flags(struct device *d, IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); @@ -4461,7 +3483,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.filter_flags)); @@ -4471,7 +3493,7 @@ static ssize_t store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -4484,7 +3506,7 @@ static ssize_t store_filter_flags(struct device *d, "0x%04X\n", filter_flags); priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); @@ -4624,26 +3646,11 @@ static ssize_t show_power_level(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); int mode = priv->power_data.user_power_setting; - int system = priv->power_data.system_power_setting; int level = priv->power_data.power_mode; char *p = buf; - switch (system) { - case IWL_POWER_SYS_AUTO: - p += sprintf(p, "SYSTEM:auto"); - break; - case IWL_POWER_SYS_AC: - p += sprintf(p, "SYSTEM:ac"); - break; - case IWL_POWER_SYS_BATTERY: - p += sprintf(p, "SYSTEM:battery"); - break; - } - - p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ? - "fixed" : "auto"); - p += sprintf(p, "\tINDEX:%d", level); - p += sprintf(p, "\n"); + p += sprintf(p, "INDEX:%d\t", level); + p += sprintf(p, "USER:%d\n", mode); return p - buf + 1; } @@ -4756,7 +3763,7 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "0x%08x\n", (int)priv->status); @@ -4768,10 +3775,11 @@ static ssize_t dump_error_log(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { + struct iwl_priv *priv = dev_get_drvdata(d); char *p = (char *)buf; if (p[0] == '1') - iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data); + iwl3945_dump_nic_error_log(priv); return strnlen(buf, count); } @@ -4782,10 +3790,11 @@ static ssize_t dump_event_log(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { + struct iwl_priv *priv = dev_get_drvdata(d); char *p = (char *)buf; if (p[0] == '1') - iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data); + iwl3945_dump_nic_event_log(priv); return strnlen(buf, count); } @@ -4807,7 +3816,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->up, iwl3945_bg_up); INIT_WORK(&priv->restart, iwl3945_bg_restart); INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); - INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); @@ -4864,16 +3872,15 @@ static struct ieee80211_ops iwl3945_hw_ops = { .tx = iwl3945_mac_tx, .start = iwl3945_mac_start, .stop = iwl3945_mac_stop, - .add_interface = iwl3945_mac_add_interface, - .remove_interface = iwl3945_mac_remove_interface, - .config = iwl3945_mac_config, - .config_interface = iwl3945_mac_config_interface, + .add_interface = iwl_mac_add_interface, + .remove_interface = iwl_mac_remove_interface, + .config = iwl_mac_config, .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, - .get_tx_stats = iwl3945_mac_get_tx_stats, - .conf_tx = iwl3945_mac_conf_tx, - .reset_tsf = iwl3945_mac_reset_tsf, - .bss_info_changed = iwl3945_bss_info_changed, + .get_tx_stats = iwl_mac_get_tx_stats, + .conf_tx = iwl_mac_conf_tx, + .reset_tsf = iwl_mac_reset_tsf, + .bss_info_changed = iwl_bss_info_changed, .hw_scan = iwl_mac_hw_scan }; @@ -4886,7 +3893,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->ibss_beacon = NULL; spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data.lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -4895,7 +3901,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) mutex_init(&priv->mutex); /* Clear the driver's (not device's) station table */ - iwl3945_clear_stations_table(priv); + iwl_clear_stations_table(priv); priv->data_retry_limit = -1; priv->ieee_channels = NULL; @@ -4966,13 +3972,13 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) hw->wiphy->custom_regulatory = true; - hw->wiphy->max_scan_ssids = 1; /* WILL FIX */ + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; + /* we create the 802.11 header and a zero-length SSID element */ + hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; - hw->conf.beacon_int = 100; - if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; @@ -5037,6 +4043,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; priv->pci_dev = pdev; + priv->inta_mask = CSR_INI_SET_MASK; #ifdef CONFIG_IWLWIFI_DEBUG priv->debug_level = iwl3945_mod_params.debug; @@ -5083,6 +4090,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, 0x41, 0x00); + /* this spin lock will be used in apm_ops.init and EEPROM access + * we should init now + */ + spin_lock_init(&priv->reg_lock); + /* amp init */ err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { @@ -5128,20 +4140,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); - /*********************************** - * 7. Initialize Module Parameters - * **********************************/ - - /* Initialize module parameter values here */ - /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (iwl3945_mod_params.disable) { - set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO(priv, "Radio disabled.\n"); - } - - /*********************** - * 8. Setup Services + * 7. Setup Services * ********************/ spin_lock_irqsave(&priv->lock, flags); @@ -5150,8 +4150,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_enable_msi(priv->pci_dev); - err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, - DRV_NAME, priv); + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, + IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); goto out_disable_msi; @@ -5169,7 +4169,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_setup_rx_handlers(priv); /********************************* - * 9. Setup and Register mac80211 + * 8. Setup and Register mac80211 * *******************************/ iwl_enable_interrupts(priv); @@ -5178,12 +4178,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if (err) goto out_remove_sysfs; - err = iwl_rfkill_init(priv); + err = iwl_dbgfs_register(priv, DRV_NAME); if (err) - IWL_ERR(priv, "Unable to initialize RFKILL system. " - "Ignoring error: %d\n", err); - else - iwl_rfkill_set_hw_state(priv); + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); /* Start monitoring the killswitch */ queue_delayed_work(priv->workqueue, &priv->rfkill_poll, @@ -5228,6 +4225,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); + iwl_dbgfs_unregister(priv); + set_bit(STATUS_EXIT_PENDING, &priv->status); if (priv->mac80211_registered) { @@ -5248,7 +4247,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); - iwl_rfkill_unregister(priv); cancel_delayed_work_sync(&priv->rfkill_poll); iwl3945_dealloc_ucode_pci(priv); @@ -5258,7 +4256,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_hw_txq_ctx_free(priv); iwl3945_unset_hw_params(priv); - iwl3945_clear_stations_table(priv); + iwl_clear_stations_table(priv); /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); @@ -5286,43 +4284,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) ieee80211_free_hw(priv->hw); } -#ifdef CONFIG_PM - -static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - - if (priv->is_open) { - set_bit(STATUS_IN_SUSPEND, &priv->status); - iwl3945_mac_stop(priv->hw); - priv->is_open = 1; - } - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int iwl3945_pci_resume(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); - - if (priv->is_open) - iwl3945_mac_start(priv->hw); - - clear_bit(STATUS_IN_SUSPEND, &priv->status); - return 0; -} - -#endif /* CONFIG_PM */ /***************************************************************************** * @@ -5336,8 +4297,8 @@ static struct pci_driver iwl3945_driver = { .probe = iwl3945_pci_probe, .remove = __devexit_p(iwl3945_pci_remove), #ifdef CONFIG_PM - .suspend = iwl3945_pci_suspend, - .resume = iwl3945_pci_resume, + .suspend = iwl_pci_suspend, + .resume = iwl_pci_resume, #endif }; @@ -5378,8 +4339,6 @@ MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(disable, iwl3945_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); MODULE_PARM_DESC(swcrypto, "using software crypto (default 1 [software])\n"); diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig new file mode 100644 index 000000000000..1eccb6df46dd --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -0,0 +1,23 @@ +config IWM + tristate "Intel Wireless Multicomm 3200 WiFi driver" + depends on MMC && WLAN_80211 && EXPERIMENTAL + depends on CFG80211 + select WIRELESS_EXT + select FW_LOADER + +config IWM_DEBUG + bool "Enable full debugging output in iwmc3200wifi" + depends on IWM && DEBUG_FS + ---help--- + This option will enable debug tracing and setting for iwm + + You can set the debug level and module through debugfs. By + default all modules are set to the IWL_DL_ERR level. + To see the list of debug modules and levels, see iwm/debug.h + + For example, if you want the full MLME debug output: + echo 0xff > /debug/iwm/phyN/debug/mlme + + Or, if you want the full debug, for all modules: + echo 0xff > /debug/iwm/phyN/debug/level + echo 0xff > /debug/iwm/phyN/debug/modules diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile new file mode 100644 index 000000000000..927f022545c1 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/Makefile @@ -0,0 +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-$(CONFIG_IWM_DEBUG) += debugfs.o diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h new file mode 100644 index 000000000000..836663eec257 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/bus.h @@ -0,0 +1,57 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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 __IWM_BUS_H__ +#define __IWM_BUS_H__ + +#include "iwm.h" + +struct iwm_if_ops { + int (*enable)(struct iwm_priv *iwm); + int (*disable)(struct iwm_priv *iwm); + int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count); + + int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir); + void (*debugfs_exit)(struct iwm_priv *iwm); + + const char *umac_name; + const char *calib_lmac_name; + const char *lmac_name; +}; + +static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) +{ + return iwm->bus_ops->send_chunk(iwm, buf, count); +} + +static inline int iwm_bus_enable(struct iwm_priv *iwm) +{ + return iwm->bus_ops->enable(iwm); +} + +static inline int iwm_bus_disable(struct iwm_priv *iwm) +{ + return iwm->bus_ops->disable(iwm); +} + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c new file mode 100644 index 000000000000..96f714e6e12b --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -0,0 +1,409 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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 +#include +#include +#include +#include + +#include "iwm.h" +#include "commands.h" +#include "cfg80211.h" +#include "debug.h" + +#define RATETAB_ENT(_rate, _rateid, _flags) \ + { \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ + } + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_rate iwm_rates[] = { + RATETAB_ENT(10, 0x1, 0), + RATETAB_ENT(20, 0x2, 0), + RATETAB_ENT(55, 0x4, 0), + RATETAB_ENT(110, 0x8, 0), + RATETAB_ENT(60, 0x10, 0), + RATETAB_ENT(90, 0x20, 0), + RATETAB_ENT(120, 0x40, 0), + RATETAB_ENT(180, 0x80, 0), + RATETAB_ENT(240, 0x100, 0), + RATETAB_ENT(360, 0x200, 0), + RATETAB_ENT(480, 0x400, 0), + RATETAB_ENT(540, 0x800, 0), +}; + +#define iwm_a_rates (iwm_rates + 4) +#define iwm_a_rates_size 8 +#define iwm_g_rates (iwm_rates + 0) +#define iwm_g_rates_size 12 + +static struct ieee80211_channel iwm_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct ieee80211_channel iwm_5ghz_a_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +static struct ieee80211_supported_band iwm_band_2ghz = { + .channels = iwm_2ghz_channels, + .n_channels = ARRAY_SIZE(iwm_2ghz_channels), + .bitrates = iwm_g_rates, + .n_bitrates = iwm_g_rates_size, +}; + +static struct ieee80211_supported_band iwm_band_5ghz = { + .channels = iwm_5ghz_a_channels, + .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels), + .bitrates = iwm_a_rates, + .n_bitrates = iwm_a_rates_size, +}; + +int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct iwm_bss_info *bss, *next; + struct iwm_umac_notif_bss_info *umac_bss; + struct ieee80211_mgmt *mgmt; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + s32 signal; + int freq; + + list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { + umac_bss = bss->bss; + mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); + + if (umac_bss->band == UMAC_BAND_2GHZ) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else if (umac_bss->band == UMAC_BAND_5GHZ) + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + else { + IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); + return -EINVAL; + } + + freq = ieee80211_channel_to_frequency(umac_bss->channel); + channel = ieee80211_get_channel(wiphy, freq); + signal = umac_bss->rssi * 100; + + if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt, + le16_to_cpu(umac_bss->frame_len), + signal, GFP_KERNEL)) + return -EINVAL; + } + + return 0; +} + +static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex, + 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; + + switch (type) { + case NL80211_IFTYPE_STATION: + iwm->conf.mode = UMAC_MODE_BSS; + break; + case NL80211_IFTYPE_ADHOC: + iwm->conf.mode = UMAC_MODE_IBSS; + break; + default: + return -EOPNOTSUPP; + } + + wdev->iftype = type; + + if ((old_mode == iwm->conf.mode) || !iwm->umac_profile) + return 0; + + iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode); + + if (iwm->umac_profile_active) { + int ret = iwm_invalidate_mlme_profile(iwm); + if (ret < 0) + IWM_ERR(iwm, "Couldn't invalidate profile\n"); + } + + return 0; +} + +static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + int ret; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) { + IWM_ERR(iwm, "Scan while device is not ready\n"); + return -EIO; + } + + if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) { + IWM_ERR(iwm, "Scanning already\n"); + return -EAGAIN; + } + + if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) { + IWM_ERR(iwm, "Scanning being aborted\n"); + return -EAGAIN; + } + + set_bit(IWM_STATUS_SCANNING, &iwm->status); + + ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids); + if (ret) { + clear_bit(IWM_STATUS_SCANNING, &iwm->status); + return ret; + } + + iwm->scan_request = request; + return 0; +} + +static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + if (changed & WIPHY_PARAM_RTS_THRESHOLD && + (iwm->conf.rts_threshold != wiphy->rts_threshold)) { + int ret; + + iwm->conf.rts_threshold = wiphy->rts_threshold; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_RTS_THRESHOLD, + iwm->conf.rts_threshold); + if (ret < 0) + return ret; + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD && + (iwm->conf.frag_threshold != wiphy->frag_threshold)) { + int ret; + + iwm->conf.frag_threshold = wiphy->frag_threshold; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, + CFG_FRAG_THRESHOLD, + iwm->conf.frag_threshold); + if (ret < 0) + return ret; + } + + return 0; +} + +static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + struct ieee80211_channel *chan = params->channel; + struct cfg80211_bss *bss; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return -EIO; + + /* UMAC doesn't support creating IBSS network with specified bssid. + * This should be removed after we have join only mode supported. */ + if (params->bssid) + return -EOPNOTSUPP; + + bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL, + params->ssid, params->ssid_len); + if (!bss) { + iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len); + schedule_timeout_interruptible(2 * HZ); + bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL, + params->ssid, params->ssid_len); + } + /* IBSS join only mode is not supported by UMAC ATM */ + if (bss) { + cfg80211_put_bss(bss); + return -EOPNOTSUPP; + } + + iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); + iwm->umac_profile->ibss.band = chan->band; + iwm->umac_profile->ibss.channel = iwm->channel; + iwm->umac_profile->ssid.ssid_len = params->ssid_len; + memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len); + + if (params->bssid) + memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN); + + return iwm_send_mlme_profile(iwm); +} + +static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + if (iwm->umac_profile_active) + return iwm_invalidate_mlme_profile(iwm); + + return 0; +} + +static struct cfg80211_ops iwm_cfg80211_ops = { + .change_virtual_intf = iwm_cfg80211_change_iface, + .scan = iwm_cfg80211_scan, + .set_wiphy_params = iwm_cfg80211_set_wiphy_params, + .join_ibss = iwm_cfg80211_join_ibss, + .leave_ibss = iwm_cfg80211_leave_ibss, +}; + +struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) +{ + int ret = 0; + struct wireless_dev *wdev; + + /* + * We're trying to have the following memory + * layout: + * + * +-------------------------+ + * | struct wiphy | + * +-------------------------+ + * | struct iwm_priv | + * +-------------------------+ + * | bus private data | + * | (e.g. iwm_priv_sdio) | + * +-------------------------+ + * + */ + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) { + dev_err(dev, "Couldn't allocate wireless device\n"); + return ERR_PTR(-ENOMEM); + } + + wdev->wiphy = wiphy_new(&iwm_cfg80211_ops, + sizeof(struct iwm_priv) + sizeof_bus); + if (!wdev->wiphy) { + dev_err(dev, "Couldn't allocate wiphy device\n"); + ret = -ENOMEM; + goto out_err_new; + } + + set_wiphy_dev(wdev->wiphy, dev); + wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX; + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz; + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + ret = wiphy_register(wdev->wiphy); + if (ret < 0) { + dev_err(dev, "Couldn't register wiphy device\n"); + goto out_err_register; + } + + return wdev; + + out_err_register: + wiphy_free(wdev->wiphy); + + out_err_new: + kfree(wdev); + + return ERR_PTR(ret); +} + +void iwm_wdev_free(struct iwm_priv *iwm) +{ + struct wireless_dev *wdev = iwm_to_wdev(iwm); + + if (!wdev) + return; + + wiphy_unregister(wdev->wiphy); + wiphy_free(wdev->wiphy); + kfree(wdev); +} diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.h b/drivers/net/wireless/iwmc3200wifi/cfg80211.h new file mode 100644 index 000000000000..56a34145acbf --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.h @@ -0,0 +1,31 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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 __IWM_CFG80211_H__ +#define __IWM_CFG80211_H__ + +int iwm_cfg80211_inform_bss(struct iwm_priv *iwm); +struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev); +void iwm_wdev_free(struct iwm_priv *iwm); + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c new file mode 100644 index 000000000000..834a7f544e5d --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -0,0 +1,920 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "hal.h" +#include "umac.h" +#include "commands.h" +#include "debug.h" + +static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm, + u8 lmac_cmd_id, + const void *lmac_payload, + u16 lmac_payload_size, + u8 resp) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_lmac_cmd lmac_cmd; + + lmac_cmd.id = lmac_cmd_id; + + umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH; + umac_cmd.resp = resp; + + return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd, + lmac_payload, lmac_payload_size); +} + +int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, + bool resp) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + + 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); +} + +static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = +{ + {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS}, + {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, + {4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, + {4, 3, 0, COEX_CALIBRATION_FLAGS}, + {4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, + {4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS}, + {4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS}, + {4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, + {4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, + {4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, + {6, 3, 0, COEX_XOR_RF_ON_FLAGS}, + {4, 3, 0, COEX_RF_OFF_FLAGS}, + {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, + {4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, + {4, 3, 0, COEX_RSRVD1_FLAGS}, + {4, 3, 0, COEX_RSRVD2_FLAGS} +}; + +static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = +{ + {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS}, + {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}, + {5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS}, + {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS}, + {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, + {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, + {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, + {1, 1, 0, COEX_RF_ON_FLAGS}, + {1, 1, 0, COEX_RF_OFF_FLAGS}, + {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, + {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, + {1, 1, 0, COEX_RSRVD1_FLAGS}, + {1, 1, 0, COEX_RSRVD2_FLAGS} +}; + +int iwm_send_prio_table(struct iwm_priv *iwm) +{ + struct iwm_coex_prio_table_cmd coex_table_cmd; + u32 coex_enabled, mode_enabled; + + memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd)); + + coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK; + + switch (iwm->conf.coexist_mode) { + case COEX_MODE_XOR: + case COEX_MODE_CM: + coex_enabled = 1; + break; + default: + coex_enabled = 0; + break; + } + + switch (iwm->conf.mode) { + case UMAC_MODE_BSS: + case UMAC_MODE_IBSS: + mode_enabled = 1; + break; + default: + mode_enabled = 0; + break; + } + + if (coex_enabled && mode_enabled) { + coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK | + COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK | + COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK; + + switch (iwm->conf.coexist_mode) { + case COEX_MODE_XOR: + memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl, + sizeof(iwm_sta_xor_prio_tbl)); + break; + case COEX_MODE_CM: + memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl, + sizeof(iwm_sta_cm_prio_tbl)); + break; + default: + IWM_ERR(iwm, "Invalid coex_mode 0x%x\n", + iwm->conf.coexist_mode); + break; + } + } else + IWM_WARN(iwm, "coexistense disabled\n"); + + return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD, + &coex_table_cmd, + sizeof(struct iwm_coex_prio_table_cmd), 1); +} + +int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) +{ + struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd; + + memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd)); + + cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.flags = + cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK); + + return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd, + sizeof(struct iwm_lmac_cal_cfg_cmd), 1); +} + +int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) +{ + struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd; + + memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd)); + + cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested); + cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested); + + return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd, + sizeof(struct iwm_lmac_cal_cfg_cmd), 0); +} + +int iwm_store_rxiq_calib_result(struct iwm_priv *iwm) +{ + struct iwm_calib_rxiq *rxiq; + u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ); + int grplen = sizeof(struct iwm_calib_rxiq_group); + + rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL); + if (!rxiq) { + IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n"); + return -ENOMEM; + } + + eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ); + if (IS_ERR(eeprom_rxiq)) { + IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n"); + return PTR_ERR(eeprom_rxiq); + } + + iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq; + iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq); + + rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD; + rxiq->hdr.first_grp = 0; + rxiq->hdr.grp_num = 1; + rxiq->hdr.all_data_valid = 1; + + memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen); + memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen); + + return 0; +} + +int iwm_send_calib_results(struct iwm_priv *iwm) +{ + int i, ret = 0; + + for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) { + if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM, + &iwm->calib_done_map)) { + IWM_DBG_CMD(iwm, DBG, + "Send calibration %d result\n", i); + ret |= iwm_send_lmac_ptrough_cmd(iwm, + REPLY_PHY_CALIBRATION_CMD, + iwm->calib_res[i].buf, + iwm->calib_res[i].size, 0); + + kfree(iwm->calib_res[i].buf); + iwm->calib_res[i].buf = NULL; + iwm->calib_res[i].size = 0; + } + } + + return ret; +} + +int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_reset reset; + + reset.flags = reset_flags; + + umac_cmd.id = UMAC_CMD_OPCODE_RESET; + umac_cmd.resp = resp; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset, + sizeof(struct iwm_umac_cmd_reset)); +} + +int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_set_param_fix param; + + if ((tbl != UMAC_PARAM_TBL_CFG_FIX) && + (tbl != UMAC_PARAM_TBL_FA_CFG_FIX)) + return -EINVAL; + + umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX; + umac_cmd.resp = 0; + + param.tbl = cpu_to_le16(tbl); + param.key = cpu_to_le16(key); + param.value = cpu_to_le32(value); + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ¶m, + sizeof(struct iwm_umac_cmd_set_param_fix)); +} + +int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, + void *payload, u16 payload_size) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_set_param_var *param_hdr; + u8 *param; + int ret; + + param = kzalloc(payload_size + + sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL); + if (!param) { + IWM_ERR(iwm, "Couldn't allocate param\n"); + return -ENOMEM; + } + + param_hdr = (struct iwm_umac_cmd_set_param_var *)param; + + umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR; + umac_cmd.resp = 0; + + param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR); + param_hdr->key = cpu_to_le16(key); + param_hdr->len = cpu_to_le16(payload_size); + memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var), + payload, payload_size); + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param, + sizeof(struct iwm_umac_cmd_set_param_var) + + payload_size); + kfree(param); + + return ret; +} + +int iwm_send_umac_config(struct iwm_priv *iwm, + __le32 reset_flags) +{ + int ret; + + /* Use UMAC default values */ + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_POWER_INDEX, iwm->conf.power_index); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, + CFG_FRAG_THRESHOLD, + iwm->conf.frag_threshold); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_RTS_THRESHOLD, + iwm->conf.rts_threshold); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_CTS_TO_SELF, iwm->conf.cts_to_self); + 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; + + /* + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_ASSOCIATION_TIMEOUT, + iwm->conf.assoc_timeout); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_ROAM_TIMEOUT, + iwm->conf.roam_timeout); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_WIRELESS_MODE, + WIRELESS_MODE_11A | WIRELESS_MODE_11G); + if (ret < 0) + return ret; + */ + + ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR, + iwm_to_ndev(iwm)->dev_addr, ETH_ALEN); + if (ret < 0) + return ret; + + /* UMAC PM static configurations */ + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_LEGACY_RX_TIMEOUT, 0x12C); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_LEGACY_TX_TIMEOUT, 0x15E); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_CTRL_FLAGS, 0x30001); + if (ret < 0) + return ret; + + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80); + if (ret < 0) + return ret; + + /* reset UMAC */ + ret = iwm_send_umac_reset(iwm, reset_flags, 1); + if (ret < 0) + return ret; + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC, + WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for UMAC RESET timeout\n"); + return ret; + } + + return ret; +} + +int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id) +{ + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_tx_info *tx_info = skb_to_tx_info(skb); + + udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */ + udma_cmd.credit_group = pool_id; + udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; + udma_cmd.lmac_offset = 0; + + umac_cmd.id = REPLY_TX; + umac_cmd.color = tx_info->color; + umac_cmd.resp = 0; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, + skb->data, skb->len); +} + +static int iwm_target_read(struct iwm_priv *iwm, __le32 address, + u8 *response, u32 resp_size) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + struct iwm_nonwifi_cmd *cmd; + u16 seq_num; + int ret = 0; + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ; + target_cmd.addr = address; + target_cmd.op1_sz = cpu_to_le32(resp_size); + target_cmd.op2 = 0; + target_cmd.handle_by_hw = 0; + target_cmd.resp = 1; + target_cmd.eop = 1; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); + if (ret < 0) + IWM_ERR(iwm, "Couldn't send READ command\n"); + + /* When succeding, the send_target routine returns the seq number */ + seq_num = ret; + + ret = wait_event_interruptible_timeout(iwm->nonwifi_queue, + (cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num, + UMAC_HDI_OUT_OPCODE_READ)) != NULL, + 2 * HZ); + + if (!ret) { + IWM_ERR(iwm, "Didn't receive a target READ answer\n"); + return ret; + } + + memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr), + resp_size); + + kfree(cmd); + + return ret; +} + +int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) +{ + int ret; + u8 mac_align[ALIGN(ETH_ALEN, 8)]; + + ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), + mac_align, sizeof(mac_align)); + if (ret < 0) + return ret; + + if (is_valid_ether_addr(mac_align)) + memcpy(mac, mac_align, ETH_ALEN); + else { + IWM_ERR(iwm, "Invalid EEPROM MAC\n"); + memcpy(mac, iwm->conf.mac_addr, ETH_ALEN); + get_random_bytes(&mac[3], 3); + } + + 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) + return -EAGAIN; + + 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.ucast_cipher != UMAC_CIPHER_TYPE_TKIP && + iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) { + IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n", + iwm->umac_profile->sec.ucast_cipher); + return -EAGAIN; + } + + if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 && + iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 && + iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP && + iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) { + IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n", + iwm->umac_profile->sec.mcast_cipher); + return -EAGAIN; + } + + 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.ucast_cipher != + iwm->umac_profile->sec.mcast_cipher)) { + IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n"); + } + + return 0; +} + +int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, + struct iwm_key *key) +{ + int ret; + u8 cmd[64], *sta_addr, *key_data, key_len; + s8 key_idx; + u16 cmd_size = 0; + struct iwm_umac_key_hdr *key_hdr = &key->hdr; + struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd; + struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd; + 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) + return ret; + } + + sta_addr = key->hdr.mac; + key_data = key->key; + key_len = key->key_len; + 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); + 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); + + IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n", + iwm->umac_profile->sec.mcast_cipher, + iwm->umac_profile->sec.ucast_cipher); + IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n", + iwm->umac_profile->sec.auth_type, + iwm->umac_profile->sec.flags); + + switch (key->alg) { + case UMAC_CIPHER_TYPE_WEP_40: + wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY; + wep40->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_wep40) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&wep40->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + memcpy(wep40->key, key_data, key_len); + wep40->static_key = 1; + + cmd_size = sizeof(struct iwm_umac_key_wep40); + break; + + case UMAC_CIPHER_TYPE_WEP_104: + wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY; + wep104->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_wep104) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&wep104->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + memcpy(wep104->key, key_data, key_len); + wep104->static_key = 1; + + cmd_size = sizeof(struct iwm_umac_key_wep104); + break; + + case UMAC_CIPHER_TYPE_CCMP: + key_hdr->key_idx++; + ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY; + ccmp->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&ccmp->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + + memcpy(ccmp->key, key_data, key_len); + + if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID) + memcpy(ccmp->iv_count, key->rx_seq, 6); + + cmd_size = sizeof(struct iwm_umac_key_ccmp); + break; + + case UMAC_CIPHER_TYPE_TKIP: + key_hdr->key_idx++; + tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY; + tkip->hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_tkip) - + sizeof(struct iwm_umac_wifi_if)); + + memcpy(&tkip->key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + + memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE); + memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE, + IWM_TKIP_MIC_SIZE); + memcpy(tkip->mic_rx_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); + + cmd_size = sizeof(struct iwm_umac_key_tkip); + break; + + default: + return -ENOTSUPP; + } + + if ((key->alg == UMAC_CIPHER_TYPE_CCMP) || + (key->alg == UMAC_CIPHER_TYPE_TKIP)) + /* + * UGLY_UGLY_UGLY + * Copied HACK from the MWG driver. + * Without it, the key is set before the second + * EAPOL frame is sent, and the latter is thus + * encrypted. + */ + 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; + + key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY; + key_remove.hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_key_remove) - + sizeof(struct iwm_umac_wifi_if)); + memcpy(&key_remove.key_hdr, key_hdr, + sizeof(struct iwm_umac_key_hdr)); + + ret = iwm_send_wifi_if_cmd(iwm, &key_remove, + sizeof(struct iwm_umac_key_remove), + 1); + if (ret < 0) + return ret; + + iwm->keys[key_idx].in_use = 0; + } + + return 0; + + err: + kfree(key); + return ret; +} + + +int iwm_send_mlme_profile(struct iwm_priv *iwm) +{ + int ret, i; + struct iwm_umac_profile profile; + + memcpy(&profile, iwm->umac_profile, sizeof(profile)); + + profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE; + profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) - + sizeof(struct iwm_umac_wifi_if)); + + ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); + if (ret < 0) { + 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; + + invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; + invalid.hdr.buf_size = + cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) - + sizeof(struct iwm_umac_wifi_if)); + + invalid.reason = WLAN_REASON_UNSPECIFIED; + + ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); + if (ret < 0) + return ret; + + ret = wait_event_interruptible_timeout(iwm->mlme_queue, + (iwm->umac_profile_active == 0), + 2 * HZ); + if (!ret) + return -EBUSY; + + return 0; +} + +int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_stats_req stats_req; + + stats_req.flags = cpu_to_le32(flags); + + umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST; + umac_cmd.resp = 0; + + return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req, + sizeof(struct iwm_umac_cmd_stats_req)); +} + +int iwm_send_umac_channel_list(struct iwm_priv *iwm) +{ + struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_get_channel_list *ch_list; + int size = sizeof(struct iwm_umac_cmd_get_channel_list) + + sizeof(struct iwm_umac_channel_info) * 4; + int ret; + + ch_list = kzalloc(size, GFP_KERNEL); + if (!ch_list) { + IWM_ERR(iwm, "Couldn't allocate channel list cmd\n"); + return -ENOMEM; + } + + ch_list->ch[0].band = UMAC_BAND_2GHZ; + ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID; + + ch_list->ch[1].band = UMAC_BAND_5GHZ; + ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID; + + ch_list->ch[2].band = UMAC_BAND_2GHZ; + ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; + + ch_list->ch[3].band = UMAC_BAND_5GHZ; + ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ; + ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; + + ch_list->count = cpu_to_le16(4); + + umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST; + umac_cmd.resp = 1; + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size); + + kfree(ch_list); + + return ret; +} + +int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, + int ssid_num) +{ + struct iwm_umac_cmd_scan_request req; + int i, ret; + + memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request)); + + req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST; + req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request) + - sizeof(struct iwm_umac_wifi_if)); + req.type = UMAC_WIFI_IF_SCAN_TYPE_USER; + req.timeout = 2; + req.seq_num = iwm->scan_id; + req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX); + + for (i = 0; i < req.ssid_num; i++) { + memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len); + req.ssids[i].ssid_len = ssids[i].ssid_len; + } + + ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't send scan request\n"); + return ret; + } + + iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX; + + return 0; +} + +int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len) +{ + struct cfg80211_ssid one_ssid; + + if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status)) + return 0; + + one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN); + memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len); + + return iwm_scan_ssids(iwm, &one_ssid, 1); +} + +int iwm_target_reset(struct iwm_priv *iwm) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT; + target_cmd.addr = 0; + target_cmd.op1_sz = 0; + target_cmd.op2 = 0; + target_cmd.handle_by_hw = 0; + target_cmd.resp = 0; + target_cmd.eop = 1; + + return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); +} diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h new file mode 100644 index 000000000000..36b13a130595 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -0,0 +1,419 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_COMMANDS_H__ +#define __IWM_COMMANDS_H__ + +#include + +#define IWM_BARKER_REBOOT_NOTIFICATION 0xF +#define IWM_ACK_BARKER_NOTIFICATION 0x10 + +/* UMAC commands */ +#define UMAC_RST_CTRL_FLG_LARC_CLK_EN 0x0001 +#define UMAC_RST_CTRL_FLG_LARC_RESET 0x0002 +#define UMAC_RST_CTRL_FLG_FUNC_RESET 0x0004 +#define UMAC_RST_CTRL_FLG_DEV_RESET 0x0008 +#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN 0x0010 +#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN 0x0040 +#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN 0x0080 +#define UMAC_RST_CTRL_FLG_NVM_RELOAD 0x0100 + +struct iwm_umac_cmd_reset { + __le32 flags; +} __attribute__ ((packed)); + +#define UMAC_PARAM_TBL_ORD_FIX 0x0 +#define UMAC_PARAM_TBL_ORD_VAR 0x1 +#define UMAC_PARAM_TBL_CFG_FIX 0x2 +#define UMAC_PARAM_TBL_CFG_VAR 0x3 +#define UMAC_PARAM_TBL_BSS_TRK 0x4 +#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5 +#define UMAC_PARAM_TBL_STA 0x6 +#define UMAC_PARAM_TBL_CHN 0x7 +#define UMAC_PARAM_TBL_STATISTICS 0x8 + +/* fast access table */ +enum { + CFG_FRAG_THRESHOLD = 0, + CFG_FRAME_RETRY_LIMIT, + CFG_OS_QUEUE_UTIL_TH, + CFG_RX_FILTER, + /* <-- LAST --> */ + FAST_ACCESS_CFG_TBL_FIX_LAST +}; + +/* fixed size table */ +enum { + CFG_POWER_INDEX = 0, + CFG_PM_LEGACY_RX_TIMEOUT, + CFG_PM_LEGACY_TX_TIMEOUT, + CFG_PM_CTRL_FLAGS, + CFG_PM_KEEP_ALIVE_IN_BEACONS, + CFG_BT_ON_THRESHOLD, + CFG_RTS_THRESHOLD, + CFG_CTS_TO_SELF, + CFG_COEX_MODE, + CFG_WIRELESS_MODE, + CFG_ASSOCIATION_TIMEOUT, + CFG_ROAM_TIMEOUT, + CFG_CAPABILITY_SUPPORTED_RATES, + CFG_SCAN_ALLOWED_UNASSOC_FLAGS, + CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS, + CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS, + CFG_SCAN_INTERNAL_PERIODIC_ENABLED, + CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT, + CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC, + CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN, + CFG_TLC_SUPPORTED_TX_HT_RATES, + CFG_TLC_SUPPORTED_TX_RATES, + CFG_TLC_VALID_ANTENNA, + 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_CONTROL_FLAGS, + CFG_TLC_SR_MIN_FAIL, + CFG_TLC_SR_MIN_PASS, + CFG_TLC_HT_STAY_IN_COL_PASS_THRESH, + CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH, + CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH, + CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH, + CFG_TLC_HT_FLUSH_STATS_PACKETS, + CFG_TLC_LEGACY_FLUSH_STATS_PACKETS, + CFG_TLC_LEGACY_FLUSH_STATS_MS, + CFG_TLC_HT_FLUSH_STATS_MS, + CFG_TLC_STAY_IN_COL_TIME_OUT, + CFG_TLC_AGG_SHORT_LIM, + CFG_TLC_AGG_LONG_LIM, + CFG_TLC_HT_SR_NO_DECREASE, + CFG_TLC_LEGACY_SR_NO_DECREASE, + CFG_TLC_SR_FORCE_DECREASE, + CFG_TLC_SR_ALLOW_INCREASE, + CFG_TLC_AGG_SET_LONG, + CFG_TLC_AUTO_AGGREGATION, + CFG_TLC_AGG_THRESHOLD, + CFG_TLC_TID_LOAD_THRESHOLD, + CFG_TLC_BLOCK_ACK_TIMEOUT, + CFG_TLC_NO_BA_COUNTED_AS_ONE, + CFG_TLC_NUM_BA_STREAMS_ALLOWED, + CFG_TLC_NUM_BA_STREAMS_PRESENT, + CFG_TLC_RENEW_ADDBA_DELAY, + CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD, + CFG_TLC_IS_STABLE_IN_HT, + CFG_RLC_CHAIN_CTRL, + CFG_TRK_TABLE_OP_MODE, + CFG_TRK_TABLE_RSSI_THRESHOLD, + CFG_TX_PWR_TARGET, /* Used By xVT */ + CFG_TX_PWR_LIMIT_USR, + CFG_TX_PWR_LIMIT_BSS, /* 11d limit */ + CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */ + CFG_TX_PWR_MODE, + CFG_MLME_DBG_NOTIF_BLOCK, + CFG_BT_OFF_BECONS_INTERVALS, + CFG_BT_FRAG_DURATION, + + /* <-- LAST --> */ + CFG_TBL_FIX_LAST +}; + +/* variable size table */ +enum { + CFG_NET_ADDR = 0, + CFG_PROFILE, + /* <-- LAST --> */ + CFG_TBL_VAR_LAST +}; + +struct iwm_umac_cmd_set_param_fix { + __le16 tbl; + __le16 key; + __le32 value; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_set_param_var { + __le16 tbl; + __le16 key; + __le16 len; + __le16 reserved; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_get_param { + __le16 tbl; + __le16 key; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_get_param_resp { + __le16 tbl; + __le16 key; + __le16 len; + __le16 reserved; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_eeprom_proxy_hdr { + __le32 type; + __le32 offset; + __le32 len; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_eeprom_proxy { + struct iwm_umac_cmd_eeprom_proxy_hdr hdr; + u8 buf[0]; +} __attribute__ ((packed)); + +#define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1 +#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2 + +#define UMAC_CHANNEL_FLAG_VALID BIT(0) +#define UMAC_CHANNEL_FLAG_IBSS BIT(1) +#define UMAC_CHANNEL_FLAG_ACTIVE BIT(3) +#define UMAC_CHANNEL_FLAG_RADAR BIT(4) +#define UMAC_CHANNEL_FLAG_DFS BIT(7) + +struct iwm_umac_channel_info { + u8 band; + u8 type; + u8 reserved; + u8 flags; + __le32 channels_mask; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_get_channel_list { + __le16 count; + __le16 reserved; + struct iwm_umac_channel_info ch[0]; +} __attribute__ ((packed)); + + +/* UMAC WiFi interface commands */ + +/* Coexistence mode */ +#define COEX_MODE_SA 0x1 +#define COEX_MODE_XOR 0x2 +#define COEX_MODE_CM 0x3 +#define COEX_MODE_MAX 0x4 + +/* Wireless mode */ +#define WIRELESS_MODE_11A 0x1 +#define WIRELESS_MODE_11G 0x2 + +#define UMAC_PROFILE_EX_IE_REQUIRED 0x1 +#define UMAC_PROFILE_QOS_ALLOWED 0x2 + +/* Scanning */ +#define UMAC_WIFI_IF_PROBE_OPTION_MAX 10 + +#define UMAC_WIFI_IF_SCAN_TYPE_USER 0x0 +#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1 +#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2 +#define UMAC_WIFI_IF_SCAN_TYPE_MAX 0x3 + +struct iwm_umac_ssid { + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 reserved[3]; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_scan_request { + struct iwm_umac_wifi_if hdr; + __le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */ + u8 ssid_num; + u8 seq_num; + u8 timeout; /* In seconds */ + u8 reserved; + struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX]; +} __attribute__ ((packed)); + +#define UMAC_CIPHER_TYPE_NONE 0xFF +#define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00 +#define UMAC_CIPHER_TYPE_WEP_40 0x01 +#define UMAC_CIPHER_TYPE_WEP_104 0x02 +#define UMAC_CIPHER_TYPE_TKIP 0x04 +#define UMAC_CIPHER_TYPE_CCMP 0x08 + +/* Supported authentication types - bitmap */ +#define UMAC_AUTH_TYPE_OPEN 0x00 +#define UMAC_AUTH_TYPE_LEGACY_PSK 0x01 +#define UMAC_AUTH_TYPE_8021X 0x02 +#define UMAC_AUTH_TYPE_RSNA_PSK 0x04 + +/* iwm_umac_security.flag is WPA supported -- bits[0:0] */ +#define UMAC_SEC_FLG_WPA_ON_POS 0 +#define UMAC_SEC_FLG_WPA_ON_SEED 1 +#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \ + UMAC_SEC_FLG_WPA_ON_POS) + +/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */ +#define UMAC_SEC_FLG_RSNA_ON_POS 1 +#define UMAC_SEC_FLG_RSNA_ON_SEED 1 +#define UMAC_SEC_FLG_RSNA_ON_MSK (UMAC_SEC_FLG_RSNA_ON_SEED << \ + UMAC_SEC_FLG_RSNA_ON_POS) + +/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */ +#define UMAC_SEC_FLG_WSC_ON_POS 2 +#define UMAC_SEC_FLG_WSC_ON_SEED 1 + +/* Legacy profile can use only WEP40 and WEP104 for encryption and + * OPEN or PSK for authentication */ +#define UMAC_SEC_FLG_LEGACY_PROFILE 0 + +struct iwm_umac_security { + u8 auth_type; + u8 ucast_cipher; + u8 mcast_cipher; + u8 flags; +} __attribute__ ((packed)); + +struct iwm_umac_ibss { + u8 beacon_interval; /* in millisecond */ + u8 atim; /* in millisecond */ + s8 join_only; + u8 band; + u8 channel; + u8 reserved[3]; +} __attribute__ ((packed)); + +#define UMAC_MODE_BSS 0 +#define UMAC_MODE_IBSS 1 + +#define UMAC_BSSID_MAX 4 + +struct iwm_umac_profile { + struct iwm_umac_wifi_if hdr; + __le32 mode; + struct iwm_umac_ssid ssid; + u8 bssid[UMAC_BSSID_MAX][ETH_ALEN]; + struct iwm_umac_security sec; + struct iwm_umac_ibss ibss; + __le32 channel_2ghz; + __le32 channel_5ghz; + __le16 flags; + u8 wireless_mode; + u8 bss_num; +} __attribute__ ((packed)); + +struct iwm_umac_invalidate_profile { + struct iwm_umac_wifi_if hdr; + u8 reason; + u8 reserved[3]; +} __attribute__ ((packed)); + +/* Encryption key commands */ +struct iwm_umac_key_wep40 { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 key[WLAN_KEY_LEN_WEP40]; + u8 static_key; + u8 reserved[2]; +} __attribute__ ((packed)); + +struct iwm_umac_key_wep104 { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 key[WLAN_KEY_LEN_WEP104]; + u8 static_key; + u8 reserved[2]; +} __attribute__ ((packed)); + +#define IWM_TKIP_KEY_SIZE 16 +#define IWM_TKIP_MIC_SIZE 8 +struct iwm_umac_key_tkip { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 iv_count[6]; + u8 reserved[2]; + u8 tkip_key[IWM_TKIP_KEY_SIZE]; + u8 mic_rx_key[IWM_TKIP_MIC_SIZE]; + u8 mic_tx_key[IWM_TKIP_MIC_SIZE]; +} __attribute__ ((packed)); + +struct iwm_umac_key_ccmp { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; + u8 iv_count[6]; + u8 reserved[2]; + u8 key[WLAN_KEY_LEN_CCMP]; +} __attribute__ ((packed)); + +struct iwm_umac_key_remove { + struct iwm_umac_wifi_if hdr; + struct iwm_umac_key_hdr key_hdr; +} __attribute__ ((packed)); + +struct iwm_umac_tx_key_id { + struct iwm_umac_wifi_if hdr; + u8 key_idx; + u8 reserved[3]; +} __attribute__ ((packed)); + +struct iwm_umac_cmd_stats_req { + __le32 flags; +} __attribute__ ((packed)); + +/* LMAC commands */ +int iwm_read_mac(struct iwm_priv *iwm, u8 *mac); +int iwm_send_prio_table(struct iwm_priv *iwm); +int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); +int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); +int iwm_send_calib_results(struct iwm_priv *iwm); +int iwm_store_rxiq_calib_result(struct iwm_priv *iwm); + +/* UMAC commands */ +int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, + bool resp); +int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp); +int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value); +int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, + void *payload, u16 payload_size); +int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); +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_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, + int ssid_num); +int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len); + +/* UDMA commands */ +int iwm_target_reset(struct iwm_priv *iwm); +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h new file mode 100644 index 000000000000..8fbb42d9c21f --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/debug.h @@ -0,0 +1,124 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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 __IWM_DEBUG_H__ +#define __IWM_DEBUG_H__ + +#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a) +#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a) +#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a) +#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a) + +#ifdef CONFIG_IWM_DEBUG + +#define IWM_DEBUG_MODULE(i, level, module, f, a...) \ +do { \ + if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\ + dev_printk(KERN_INFO, (iwm_to_dev(i)), \ + "%s " f, __func__ , ## a); \ +} while (0) + +#define IWM_HEXDUMP(i, level, module, pref, buf, len) \ +do { \ + if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\ + print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \ + 16, 1, buf, len, 1); \ +} while (0) + +#else + +#define IWM_DEBUG_MODULE(i, level, module, f, a...) +#define IWM_HEXDUMP(i, level, module, pref, buf, len) + +#endif /* CONFIG_IWM_DEBUG */ + +/* Debug modules */ +enum iwm_debug_module_id { + IWM_DM_BOOT = 0, + IWM_DM_FW, + IWM_DM_SDIO, + IWM_DM_NTF, + IWM_DM_RX, + IWM_DM_TX, + IWM_DM_MLME, + IWM_DM_CMD, + IWM_DM_WEXT, + __IWM_DM_NR, +}; +#define IWM_DM_DEFAULT 0 + +#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a) +#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a) +#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a) +#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a) +#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a) +#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a) +#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a) +#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a) +#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a) + +/* Debug levels */ +enum iwm_debug_level { + IWM_DL_NONE = 0, + IWM_DL_ERR, + IWM_DL_WARN, + IWM_DL_INFO, + IWM_DL_DBG, +}; +#define IWM_DL_DEFAULT IWM_DL_ERR + +struct iwm_debugfs { + struct iwm_priv *iwm; + struct dentry *rootdir; + struct dentry *devdir; + struct dentry *dbgdir; + struct dentry *txdir; + struct dentry *rxdir; + struct dentry *busdir; + + u32 dbg_level; + struct dentry *dbg_level_dentry; + + unsigned long dbg_modules; + struct dentry *dbg_modules_dentry; + + u8 dbg_module[__IWM_DM_NR]; + struct dentry *dbg_module_dentries[__IWM_DM_NR]; + + struct dentry *txq_dentry; + struct dentry *tx_credit_dentry; + struct dentry *rx_ticket_dentry; +}; + +#ifdef CONFIG_IWM_DEBUG +int iwm_debugfs_init(struct iwm_priv *iwm); +void iwm_debugfs_exit(struct iwm_priv *iwm); +#else +static inline int iwm_debugfs_init(struct iwm_priv *iwm) +{ + return 0; +} +static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {} +#endif + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c new file mode 100644 index 000000000000..0fa7b9150d58 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -0,0 +1,453 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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 +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "rx.h" +#include "debug.h" + +static struct { + u8 id; + char *name; +} iwm_debug_module[__IWM_DM_NR] = { + {IWM_DM_BOOT, "boot"}, + {IWM_DM_FW, "fw"}, + {IWM_DM_SDIO, "sdio"}, + {IWM_DM_NTF, "ntf"}, + {IWM_DM_RX, "rx"}, + {IWM_DM_TX, "tx"}, + {IWM_DM_MLME, "mlme"}, + {IWM_DM_CMD, "cmd"}, + {IWM_DM_WEXT, "wext"}, +}; + +#define add_dbg_module(dbg, name, id, initlevel) \ +do { \ + struct dentry *d; \ + dbg.dbg_module[id] = (initlevel); \ + d = debugfs_create_x8(name, 0600, dbg.dbgdir, \ + &(dbg.dbg_module[id])); \ + if (!IS_ERR(d)) \ + dbg.dbg_module_dentries[id] = d; \ +} while (0) + +static int iwm_debugfs_u32_read(void *data, u64 *val) +{ + struct iwm_priv *iwm = data; + + *val = iwm->dbg.dbg_level; + return 0; +} + +static int iwm_debugfs_dbg_level_write(void *data, u64 val) +{ + struct iwm_priv *iwm = data; + int i; + + iwm->dbg.dbg_level = val; + + for (i = 0; i < __IWM_DM_NR; i++) + iwm->dbg.dbg_module[i] = val; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level, + iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write, + "%llu\n"); + +static int iwm_debugfs_dbg_modules_write(void *data, u64 val) +{ + struct iwm_priv *iwm = data; + int i, bit; + + iwm->dbg.dbg_modules = val; + + for (i = 0; i < __IWM_DM_NR; i++) + iwm->dbg.dbg_module[i] = 0; + + for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR) + iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level; + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules, + iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write, + "%llu\n"); + +static int iwm_txrx_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + + +static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + char *buf; + int i, buf_len = 4096; + size_t len = 0; + ssize_t ret; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < IWM_TX_QUEUES; i++) { + struct iwm_tx_queue *txq = &iwm->txq[i]; + struct sk_buff *skb; + int j; + unsigned long flags; + + spin_lock_irqsave(&txq->queue.lock, flags); + + skb = (struct sk_buff *)&txq->queue; + + len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i); + len += snprintf(buf + len, buf_len - len, "\tStopped: %d\n", + __netif_subqueue_stopped(iwm_to_ndev(iwm), + txq->id)); + len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n", + txq->concat_count); + len += snprintf(buf + len, buf_len - len, "\tQueue len: %d\n", + skb_queue_len(&txq->queue)); + for (j = 0; j < skb_queue_len(&txq->queue); j++) { + struct iwm_tx_info *tx_info; + + skb = skb->next; + tx_info = skb_to_tx_info(skb); + + len += snprintf(buf + len, buf_len - len, + "\tSKB #%d\n", j); + len += snprintf(buf + len, buf_len - len, + "\t\tsta: %d\n", tx_info->sta); + len += snprintf(buf + len, buf_len - len, + "\t\tcolor: %d\n", tx_info->color); + len += snprintf(buf + len, buf_len - len, + "\t\ttid: %d\n", tx_info->tid); + } + + spin_unlock_irqrestore(&txq->queue.lock, flags); + } + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); + kfree(buf); + + return ret; +} + +static ssize_t iwm_debugfs_tx_credit_read(struct file *filp, + char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + struct iwm_tx_credit *credit = &iwm->tx_credit; + char *buf; + int i, buf_len = 4096; + size_t len = 0; + ssize_t ret; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += snprintf(buf + len, buf_len - len, + "NR pools: %d\n", credit->pool_nr); + len += snprintf(buf + len, buf_len - len, + "pools map: 0x%lx\n", credit->full_pools_map); + + len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n"); + for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) { + len += snprintf(buf + len, buf_len - len, + "pools entry #%d\n", i); + len += snprintf(buf + len, buf_len - len, + "\tid: %d\n", + credit->pools[i].id); + len += snprintf(buf + len, buf_len - len, + "\tsid: %d\n", + credit->pools[i].sid); + len += snprintf(buf + len, buf_len - len, + "\tmin_pages: %d\n", + credit->pools[i].min_pages); + len += snprintf(buf + len, buf_len - len, + "\tmax_pages: %d\n", + credit->pools[i].max_pages); + len += snprintf(buf + len, buf_len - len, + "\talloc_pages: %d\n", + credit->pools[i].alloc_pages); + len += snprintf(buf + len, buf_len - len, + "\tfreed_pages: %d\n", + credit->pools[i].total_freed_pages); + } + + len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n"); + for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) { + len += snprintf(buf + len, buf_len - len, + "spools entry #%d\n", i); + len += snprintf(buf + len, buf_len - len, + "\tid: %d\n", + credit->spools[i].id); + len += snprintf(buf + len, buf_len - len, + "\tmax_pages: %d\n", + credit->spools[i].max_pages); + len += snprintf(buf + len, buf_len - len, + "\talloc_pages: %d\n", + credit->spools[i].alloc_pages); + + } + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); + kfree(buf); + + return ret; +} + +static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, + char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + struct iwm_rx_ticket_node *ticket, *next; + char *buf; + int buf_len = 4096, i; + size_t len = 0; + ssize_t ret; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { + len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", + ticket->ticket->id); + len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n", + ticket->ticket->action); + len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n", + ticket->ticket->flags); + } + + for (i = 0; i < IWM_RX_ID_HASH; i++) { + struct iwm_rx_packet *packet, *nxt; + struct list_head *pkt_list = &iwm->rx_packets[i]; + if (!list_empty(pkt_list)) { + len += snprintf(buf + len, buf_len - len, + "Packet hash #%d\n", i); + list_for_each_entry_safe(packet, nxt, pkt_list, node) { + len += snprintf(buf + len, buf_len - len, + "\tPacket id: %d\n", + packet->id); + len += snprintf(buf + len, buf_len - len, + "\tPacket length: %lu\n", + packet->pkt_size); + } + } + } + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); + kfree(buf); + + return ret; +} + + +static const struct file_operations iwm_debugfs_txq_fops = { + .owner = THIS_MODULE, + .open = iwm_txrx_open, + .read = iwm_debugfs_txq_read, +}; + +static const struct file_operations iwm_debugfs_tx_credit_fops = { + .owner = THIS_MODULE, + .open = iwm_txrx_open, + .read = iwm_debugfs_tx_credit_read, +}; + +static const struct file_operations iwm_debugfs_rx_ticket_fops = { + .owner = THIS_MODULE, + .open = iwm_txrx_open, + .read = iwm_debugfs_rx_ticket_read, +}; + +int iwm_debugfs_init(struct iwm_priv *iwm) +{ + int i, result; + char devdir[16]; + + iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); + result = PTR_ERR(iwm->dbg.rootdir); + if (!result || IS_ERR(iwm->dbg.rootdir)) { + if (result == -ENODEV) { + IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not " + "enabled in kernel config\n"); + result = 0; /* No debugfs support */ + } + IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result); + goto error; + } + + snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm))); + + iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir); + result = PTR_ERR(iwm->dbg.devdir); + if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create devdir: %d\n", result); + goto error; + } + + iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir); + result = PTR_ERR(iwm->dbg.dbgdir); + if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result); + goto error; + } + + iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir); + result = PTR_ERR(iwm->dbg.rxdir); + if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result); + goto error; + } + + iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir); + result = PTR_ERR(iwm->dbg.txdir); + if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result); + goto error; + } + + iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir); + result = PTR_ERR(iwm->dbg.busdir); + if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result); + goto error; + } + + if (iwm->bus_ops->debugfs_init) { + result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); + if (result < 0) { + IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result); + goto error; + } + } + + + iwm->dbg.dbg_level = IWM_DL_NONE; + iwm->dbg.dbg_level_dentry = + debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm, + &fops_iwm_dbg_level); + result = PTR_ERR(iwm->dbg.dbg_level_dentry); + if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result); + goto error; + } + + + iwm->dbg.dbg_modules = IWM_DM_DEFAULT; + iwm->dbg.dbg_modules_dentry = + debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm, + &fops_iwm_dbg_modules); + result = PTR_ERR(iwm->dbg.dbg_modules_dentry); + if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result); + goto error; + } + + for (i = 0; i < __IWM_DM_NR; i++) + add_dbg_module(iwm->dbg, iwm_debug_module[i].name, + iwm_debug_module[i].id, IWM_DL_DEFAULT); + + iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200, + iwm->dbg.txdir, iwm, + &iwm_debugfs_txq_fops); + result = PTR_ERR(iwm->dbg.txq_dentry); + if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result); + goto error; + } + + iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200, + iwm->dbg.txdir, iwm, + &iwm_debugfs_tx_credit_fops); + result = PTR_ERR(iwm->dbg.tx_credit_dentry); + if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result); + goto error; + } + + iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200, + iwm->dbg.rxdir, iwm, + &iwm_debugfs_rx_ticket_fops); + result = PTR_ERR(iwm->dbg.rx_ticket_dentry); + if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result); + goto error; + } + + return 0; + + error: + return result; +} + +void iwm_debugfs_exit(struct iwm_priv *iwm) +{ + int i; + + for (i = 0; i < __IWM_DM_NR; i++) + debugfs_remove(iwm->dbg.dbg_module_dentries[i]); + + debugfs_remove(iwm->dbg.dbg_modules_dentry); + debugfs_remove(iwm->dbg.dbg_level_dentry); + debugfs_remove(iwm->dbg.txq_dentry); + debugfs_remove(iwm->dbg.tx_credit_dentry); + debugfs_remove(iwm->dbg.rx_ticket_dentry); + if (iwm->bus_ops->debugfs_exit) + iwm->bus_ops->debugfs_exit(iwm); + + debugfs_remove(iwm->dbg.busdir); + debugfs_remove(iwm->dbg.dbgdir); + debugfs_remove(iwm->dbg.txdir); + debugfs_remove(iwm->dbg.rxdir); + debugfs_remove(iwm->dbg.devdir); + debugfs_remove(iwm->dbg.rootdir); +} diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c new file mode 100644 index 000000000000..0f34b84fd2eb --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/eeprom.c @@ -0,0 +1,187 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include + +#include "iwm.h" +#include "umac.h" +#include "commands.h" +#include "eeprom.h" + +static struct iwm_eeprom_entry eeprom_map[] = { + [IWM_EEPROM_SIG] = + {"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN}, + + [IWM_EEPROM_VERSION] = + {"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN}, + + [IWM_EEPROM_OEM_HW_VERSION] = + {"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF, + IWM_EEPROM_OEM_HW_VERSION_LEN}, + + [IWM_EEPROM_MAC_VERSION] = + {"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN}, + + [IWM_EEPROM_CARD_ID] = + {"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN}, + + [IWM_EEPROM_RADIO_CONF] = + {"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN}, + + [IWM_EEPROM_SKU_CAP] = + {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN}, + + [IWM_EEPROM_CALIB_RXIQ_OFFSET] = + {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN}, + + [IWM_EEPROM_CALIB_RXIQ] = + {"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN}, +}; + + +static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id) +{ + int ret; + u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0; + u32 addr; + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_umac_cmd_eeprom_proxy eeprom_cmd; + + if (eeprom_id > (IWM_EEPROM_LAST - 1)) + return -EINVAL; + + entry_size = eeprom_map[eeprom_id].length; + + if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) { + /* indirect data */ + u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA + + IWM_EEPROM_INDIRECT_OFFSET; + + eeprom_map[eeprom_id].offset = + *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1; + } + + addr = eeprom_map[eeprom_id].offset; + + udma_cmd.eop = 1; + udma_cmd.credit_group = 0x4; + udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD; + udma_cmd.lmac_offset = 0; + + umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY; + umac_cmd.resp = 1; + + while (entry_size > 0) { + chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN); + + eeprom_cmd.hdr.type = + cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ); + eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset); + eeprom_cmd.hdr.len = cpu_to_le32(chunk_size); + + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, + &umac_cmd, &eeprom_cmd, + sizeof(struct iwm_umac_cmd_eeprom_proxy)); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't read eeprom\n"); + return ret; + } + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY, + IWM_SRC_UMAC, 2*HZ); + if (ret < 0) { + IWM_ERR(iwm, "Did not get any eeprom answer\n"); + return ret; + } + + data_offset += chunk_size; + addr_offset += chunk_size; + entry_size -= chunk_size; + } + + return 0; +} + +u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id) +{ + if (!iwm->eeprom) + return ERR_PTR(-ENODEV); + + return iwm->eeprom + eeprom_map[eeprom_id].offset; +} + +int iwm_eeprom_init(struct iwm_priv *iwm) +{ + int i, ret = 0; + char name[32]; + + iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL); + if (!iwm->eeprom) + 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", + i, eeprom_map[i].name); + break; + } + } + + IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n"); + for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) { + memset(name, 0, 32); + sprintf(name, "%s: ", eeprom_map[i].name); + + IWM_HEXDUMP(iwm, DBG, BOOT, name, + iwm->eeprom + eeprom_map[i].offset, + eeprom_map[i].length); + } + + return ret; +} + +void iwm_eeprom_exit(struct iwm_priv *iwm) +{ + kfree(iwm->eeprom); +} diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.h b/drivers/net/wireless/iwmc3200wifi/eeprom.h new file mode 100644 index 000000000000..cdb31a6a1f5f --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/eeprom.h @@ -0,0 +1,114 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_EEPROM_H__ +#define __IWM_EEPROM_H__ + +enum { + IWM_EEPROM_SIG = 0, + IWM_EEPROM_FIRST = IWM_EEPROM_SIG, + IWM_EEPROM_VERSION, + IWM_EEPROM_OEM_HW_VERSION, + IWM_EEPROM_MAC_VERSION, + IWM_EEPROM_CARD_ID, + IWM_EEPROM_RADIO_CONF, + IWM_EEPROM_SKU_CAP, + + IWM_EEPROM_INDIRECT_OFFSET, + IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET, + + IWM_EEPROM_INDIRECT_DATA, + IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA, + + IWM_EEPROM_LAST, +}; + +#define IWM_EEPROM_SIG_OFF 0x00 +#define IWM_EEPROM_VERSION_OFF (0x54 << 1) +#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1) +#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1) +#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1) +#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1) +#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1) +#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1) + +#define IWM_EEPROM_SIG_LEN 4 +#define IWM_EEPROM_VERSION_LEN 2 +#define IWM_EEPROM_OEM_HW_VERSION_LEN 2 +#define IWM_EEPROM_MAC_VERSION_LEN 1 +#define IWM_EEPROM_CARD_ID_LEN 2 +#define IWM_EEPROM_RADIO_CONF_LEN 2 +#define IWM_EEPROM_SKU_CAP_LEN 2 +#define IWM_EEPROM_INDIRECT_LEN 2 + +#define IWM_MAX_EEPROM_DATA_LEN 240 +#define IWM_EEPROM_LEN 0x800 + +#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610 +#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700 +#define IWM_EEPROM_CURRENT_VERSION 0x0612 + +#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) +#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) +#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6) + +enum { + IWM_EEPROM_CALIB_CAL_HDR, + IWM_EEPROM_CALIB_TX_POWER, + IWM_EEPROM_CALIB_XTAL, + IWM_EEPROM_CALIB_TEMPERATURE, + IWM_EEPROM_CALIB_RX_BB_FILTER, + IWM_EEPROM_CALIB_RX_IQ, + IWM_EEPROM_CALIB_MAX, +}; + +#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \ + (IWM_EEPROM_CALIB_RX_IQ << 1)) +#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq) + +struct iwm_eeprom_entry { + char *name; + u32 offset; + u32 length; +}; + +int iwm_eeprom_init(struct iwm_priv *iwm); +void iwm_eeprom_exit(struct iwm_priv *iwm); +u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id); + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c new file mode 100644 index 000000000000..ec1a15a5a0e4 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/fw.c @@ -0,0 +1,388 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "hal.h" +#include "umac.h" +#include "debug.h" +#include "fw.h" +#include "commands.h" + +static const char fw_barker[] = "*WESTOPFORNOONE*"; + +/* + * @op_code: Op code we're looking for. + * @index: There can be several instances of the same opcode within + * the firmware. Index specifies which one we're looking for. + */ +static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw, + u16 op_code, u32 index) +{ + int offset = -EINVAL, fw_offset; + u32 op_index = 0; + const u8 *fw_ptr; + struct iwm_fw_hdr_rec *rec; + + fw_offset = 0; + fw_ptr = fw->data; + + /* We first need to look for the firmware barker */ + if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) { + IWM_ERR(iwm, "No barker string in this FW\n"); + return -EINVAL; + } + + if (fw->size < IWM_HDR_LEN) { + IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size); + return -EINVAL; + } + + fw_offset += IWM_HDR_BARKER_LEN; + + while (fw_offset < fw->size) { + rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset); + + IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n", + rec->op_code, rec->len, fw_offset); + + if (rec->op_code == IWM_HDR_REC_OP_INVALID) { + IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n"); + break; + } + + if (rec->op_code == op_code) { + if (op_index == index) { + fw_offset += sizeof(struct iwm_fw_hdr_rec); + offset = fw_offset; + goto out; + } + op_index++; + } + + fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len; + } + + out: + return offset; +} + +static int iwm_load_firmware_chunk(struct iwm_priv *iwm, + const struct firmware *fw, + struct iwm_fw_img_desc *img_desc) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + u32 chunk_size; + const u8 *chunk_ptr; + int ret = 0; + + IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n", + img_desc->length, img_desc->address); + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; + target_cmd.handle_by_hw = 1; + target_cmd.op2 = 0; + target_cmd.resp = 0; + target_cmd.eop = 1; + + chunk_size = img_desc->length; + chunk_ptr = fw->data + img_desc->offset; + + while (chunk_size > 0) { + u32 tmp_chunk_size; + + tmp_chunk_size = min_t(u32, chunk_size, + IWM_MAX_NONWIFI_CMD_BUFF_SIZE); + + target_cmd.addr = cpu_to_le32(img_desc->address + + (chunk_ptr - fw->data - img_desc->offset)); + target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size); + + IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n", + tmp_chunk_size, target_cmd.addr); + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't load FW chunk\n"); + break; + } + + chunk_size -= tmp_chunk_size; + chunk_ptr += tmp_chunk_size; + } + + return ret; +} +/* + * To load a fw image to the target, we basically go through the + * fw, looking for OP_MEM_DESC records. Once we found one, we + * pass it to iwm_load_firmware_chunk(). + * The OP_MEM_DESC records contain the actuall memory chunk to be + * sent, but also the destination address. + */ +static int iwm_load_img(struct iwm_priv *iwm, const char *img_name) +{ + const struct firmware *fw; + struct iwm_fw_img_desc *img_desc; + struct iwm_fw_img_ver *ver; + int ret = 0, fw_offset; + u32 opcode_idx = 0, build_date; + char *build_tag; + + ret = request_firmware(&fw, img_name, iwm_to_dev(iwm)); + if (ret) { + IWM_ERR(iwm, "Request firmware failed"); + return ret; + } + + IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name); + + while (1) { + fw_offset = iwm_fw_op_offset(iwm, fw, + IWM_HDR_REC_OP_MEM_DESC, + opcode_idx); + if (fw_offset < 0) + break; + + img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset); + ret = iwm_load_firmware_chunk(iwm, fw, img_desc); + if (ret < 0) + goto err_release_fw; + opcode_idx++; + }; + + /* Read firmware version */ + fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0); + if (fw_offset < 0) + goto err_release_fw; + + ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset); + + /* Read build tag */ + fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0); + if (fw_offset < 0) + goto err_release_fw; + + build_tag = (char *)(fw->data + fw_offset); + + /* Read build date */ + fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0); + if (fw_offset < 0) + goto err_release_fw; + + build_date = *(u32 *)(fw->data + fw_offset); + + IWM_INFO(iwm, "%s:\n", img_name); + IWM_INFO(iwm, "\tVersion: %02X.%02X\n", ver->major, ver->minor); + IWM_INFO(iwm, "\tBuild tag: %s\n", build_tag); + IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n", + IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date), + IWM_BUILD_DAY(build_date)); + + + err_release_fw: + release_firmware(fw); + + return ret; +} + +static int iwm_load_umac(struct iwm_priv *iwm) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + int ret; + + ret = iwm_load_img(iwm, iwm->bus_ops->umac_name); + if (ret < 0) + return ret; + + /* We've loaded the UMAC, we can tell the target to jump there */ + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP; + target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR); + target_cmd.op1_sz = 0; + target_cmd.op2 = 0; + target_cmd.handle_by_hw = 0; + target_cmd.resp = 1 ; + target_cmd.eop = 1; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); + if (ret < 0) + IWM_ERR(iwm, "Couldn't send JMP command\n"); + + return ret; +} + +static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) +{ + int ret; + + ret = iwm_load_img(iwm, img_name); + if (ret < 0) + return ret; + + return iwm_send_umac_reset(iwm, + cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0); +} + +/* + * We currently have to load 3 FWs: + * 1) The UMAC (Upper MAC). + * 2) The calibration LMAC (Lower MAC). + * We then send the calibration init command, so that the device can + * run a first calibration round. + * 3) The operational LMAC, which replaces the calibration one when it's + * done with the first calibration round. + * + * Once those 3 FWs have been loaded, we send the periodic calibration + * command, and then the device is available for regular 802.11 operations. + */ +int iwm_load_fw(struct iwm_priv *iwm) +{ + int ret; + + /* We first start downloading the UMAC */ + ret = iwm_load_umac(iwm); + if (ret < 0) { + IWM_ERR(iwm, "UMAC loading failed\n"); + return ret; + } + + /* Handle UMAC_ALIVE notification */ + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC, + WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret); + return ret; + } + + /* UMAC is alive, we can download the calibration LMAC */ + ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name); + if (ret) { + IWM_ERR(iwm, "Calibration LMAC loading failed\n"); + return ret; + } + + /* Handle UMAC_INIT_COMPLETE notification */ + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration " + "LMAC: %d\n", ret); + return ret; + } + + /* Read EEPROM data */ + ret = iwm_eeprom_init(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't init eeprom array\n"); + 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 + /* Read RX IQ calibration result from EEPROM */ + if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.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); + + while (iwm->calib_done_map != iwm->conf.init_calib_map) { + ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION, + IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for calibration result timeout\n"); + goto out; + } + 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); + } + + /* Handle LMAC CALIBRATION_COMPLETE notification */ + ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION, + IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n"); + goto out; + } + + IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map); + + iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1); + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC, + WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Wait for UMAC RESET timeout\n"); + goto out; + } + + /* Download the operational LMAC */ + ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name); + if (ret) { + IWM_ERR(iwm, "LMAC loading failed\n"); + goto out; + } + + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret); + goto out; + } + + iwm_send_prio_table(iwm); + iwm_send_calib_results(iwm); + iwm_send_periodic_calib_cfg(iwm, iwm->conf.periodic_calib_map); + + return 0; + + out: + iwm_eeprom_exit(iwm); + return ret; +} diff --git a/drivers/net/wireless/iwmc3200wifi/fw.h b/drivers/net/wireless/iwmc3200wifi/fw.h new file mode 100644 index 000000000000..c70a3b40dad3 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/fw.h @@ -0,0 +1,100 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_FW_H__ +#define __IWM_FW_H__ + +/** + * struct iwm_fw_hdr_rec - An iwm firmware image is a + * concatenation of various records. Each of them is + * defined by an ID (aka op code), a length, and the + * actual data. + * @op_code: The record ID, see IWM_HDR_REC_OP_* + * + * @len: The record payload length + * + * @buf: The record payload + */ +struct iwm_fw_hdr_rec { + u16 op_code; + u16 len; + u8 buf[0]; +}; + +/* Header's definitions */ +#define IWM_HDR_LEN (512) +#define IWM_HDR_BARKER_LEN (16) + +/* Header's opcodes */ +#define IWM_HDR_REC_OP_INVALID (0x00) +#define IWM_HDR_REC_OP_BUILD_DATE (0x01) +#define IWM_HDR_REC_OP_BUILD_TAG (0x02) +#define IWM_HDR_REC_OP_SW_VER (0x03) +#define IWM_HDR_REC_OP_HW_SKU (0x04) +#define IWM_HDR_REC_OP_BUILD_OPT (0x05) +#define IWM_HDR_REC_OP_MEM_DESC (0x06) +#define IWM_HDR_REC_USERDEFS (0x07) + +/* Header's records length (in bytes) */ +#define IWM_HDR_REC_LEN_BUILD_DATE (4) +#define IWM_HDR_REC_LEN_BUILD_TAG (64) +#define IWM_HDR_REC_LEN_SW_VER (4) +#define IWM_HDR_REC_LEN_HW_SKU (4) +#define IWM_HDR_REC_LEN_BUILD_OPT (4) +#define IWM_HDR_REC_LEN_MEM_DESC (12) +#define IWM_HDR_REC_LEN_USERDEF (64) + +#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff) +#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff) +#define IWM_BUILD_DAY(date) (date & 0xff) + +struct iwm_fw_img_desc { + u32 offset; + u32 address; + u32 length; +}; + +struct iwm_fw_img_ver { + u8 minor; + u8 major; + u16 reserved; +}; + +int iwm_load_fw(struct iwm_priv *iwm); + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c new file mode 100644 index 000000000000..ee127fe4f43f --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -0,0 +1,464 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +/* + * Hardware Abstraction Layer for iwm. + * + * This file mostly defines an abstraction API for + * sending various commands to the target. + * + * We have 2 types of commands: wifi and non-wifi ones. + * + * - wifi commands: + * They are used for sending LMAC and UMAC commands, + * and thus are the most commonly used ones. + * There are 2 different wifi command types, the regular + * one and the LMAC one. The former is used to send + * UMAC commands (see UMAC_CMD_OPCODE_* from umac.h) + * while the latter is used for sending commands to the + * LMAC. If you look at LMAC commands you'll se that they + * are actually regular iwlwifi target commands encapsulated + * into a special UMAC command called UMAC passthrough. + * This is due to the fact the the host talks exclusively + * to the UMAC and so there needs to be a special UMAC + * command for talking to the LMAC. + * This is how a wifi command is layed out: + * ------------------------ + * | iwm_udma_out_wifi_hdr | + * ------------------------ + * | SW meta_data (32 bits) | + * ------------------------ + * | iwm_dev_cmd_hdr | + * ------------------------ + * | payload | + * | .... | + * + * - non-wifi, or general commands: + * Those commands are handled by the device's bootrom, + * and are typically sent when the UMAC and the LMAC + * are not yet available. + * * This is how a non-wifi command is layed out: + * --------------------------- + * | iwm_udma_out_nonwifi_hdr | + * --------------------------- + * | payload | + * | .... | + + * + * All the commands start with a UDMA header, which is + * basically a 32 bits field. The 4 LSB there define + * an opcode that allows the target to differentiate + * between wifi (opcode is 0xf) and non-wifi commands + * (opcode is [0..0xe]). + * + * When a command (wifi or non-wifi) is supposed to receive + * an answer, we queue the command buffer. When we do receive + * a command response from the UMAC, we go through the list + * of pending command, and pass both the command and the answer + * to the rx handler. Each command is sent with a unique + * sequence id, and the answer is sent with the same one. This + * is how we're supposed to match an answer with its command. + * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi() + * for the implementation details. + */ +#include +#include + +#include "iwm.h" +#include "bus.h" +#include "hal.h" +#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) +{ + INIT_LIST_HEAD(&cmd->pending); + + spin_lock(&iwm->cmd_lock); + + cmd->resp_received = 0; + + 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 %= UMAC_NONWIFI_SEQ_NUM_MAX; + + if (udma_cmd->resp) + list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd); + + spin_unlock(&iwm->cmd_lock); + + cmd->buf.start = cmd->buf.payload; + cmd->buf.len = 0; + + memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); +} + +u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) +{ + u16 seq_num = iwm->wifi_seq_num; + + iwm->wifi_seq_num++; + iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX; + + return seq_num; +} + +static void iwm_wifi_cmd_init(struct iwm_priv *iwm, + struct iwm_wifi_cmd *cmd, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + struct iwm_lmac_cmd *lmac_cmd, + u16 payload_size) +{ + INIT_LIST_HEAD(&cmd->pending); + + spin_lock(&iwm->cmd_lock); + + cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm); + umac_cmd->seq_num = cpu_to_le16(cmd->seq_num); + + if (umac_cmd->resp) + list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd); + + spin_unlock(&iwm->cmd_lock); + + cmd->buf.start = cmd->buf.payload; + cmd->buf.len = 0; + + if (lmac_cmd) { + cmd->buf.start -= sizeof(struct iwm_lmac_hdr); + + lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num); + lmac_cmd->count = cpu_to_le16(payload_size); + + memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd)); + + umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr)); + } else + umac_cmd->count = 0; + + umac_cmd->count = cpu_to_le16(payload_size + + le16_to_cpu(umac_cmd->count)); + udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) + + le16_to_cpu(umac_cmd->count)); + + memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); + memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd)); +} + +void iwm_cmd_flush(struct iwm_priv *iwm) +{ + struct iwm_wifi_cmd *wcmd, *wnext; + struct iwm_nonwifi_cmd *nwcmd, *nwnext; + + list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) { + list_del(&wcmd->pending); + kfree(wcmd); + } + + list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd, + pending) { + list_del(&nwcmd->pending); + kfree(nwcmd); + } +} + +struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) +{ + struct iwm_wifi_cmd *cmd, *next; + + list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending) + if (cmd->seq_num == seq_num) { + list_del(&cmd->pending); + return cmd; + } + + return NULL; +} + +struct iwm_nonwifi_cmd * +iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode) +{ + struct iwm_nonwifi_cmd *cmd, *next; + + list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) + if ((cmd->seq_num == seq_num) && + (cmd->udma_cmd.opcode == cmd_opcode) && + (cmd->resp_received)) { + list_del(&cmd->pending); + return cmd; + } + + return NULL; +} + +static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm, + struct iwm_udma_out_nonwifi_hdr *hdr, + struct iwm_udma_nonwifi_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode); + SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1); + SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW, + cmd->handle_by_hw); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE); + SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM, + le16_to_cpu(cmd->seq_num)); + + hdr->addr = cmd->addr; + hdr->op1_sz = cmd->op1_sz; + hdr->op2 = cmd->op2; +} + +static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm, + struct iwm_nonwifi_cmd *cmd) +{ + struct iwm_udma_out_nonwifi_hdr *udma_hdr; + struct iwm_nonwifi_cmd_buff *buf; + struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd; + + buf = &cmd->buf; + + buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr); + buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr); + + udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start); + + iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd); + + IWM_DBG_CMD(iwm, DBG, + "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, " + "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, " + "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp, + udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, + udma_cmd->op1_sz, udma_cmd->op2); + + return iwm_bus_send_chunk(iwm, buf->start, buf->len); +} + +void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop) +{ + struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf; + + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop); +} + +void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm, + struct iwm_udma_out_wifi_hdr *hdr, + struct iwm_udma_wifi_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop); + SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE); + + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT, + le16_to_cpu(cmd->count)); + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group); + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid); + SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset); +} + +void iwm_build_umac_hdr(struct iwm_priv *iwm, + struct iwm_umac_fw_cmd_hdr *hdr, + struct iwm_umac_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT, + le16_to_cpu(cmd->count)); + SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color); + SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp); + + hdr->cmd.cmd = cmd->id; + hdr->cmd.seq_num = cmd->seq_num; +} + +static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_wifi_out_hdr *umac_hdr; + struct iwm_wifi_cmd_buff *buf; + struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd; + struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd; + int ret; + + buf = &cmd->buf; + + buf->start -= sizeof(struct iwm_umac_wifi_out_hdr); + buf->len += sizeof(struct iwm_umac_wifi_out_hdr); + + umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start); + + iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd); + iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd); + + IWM_DBG_CMD(iwm, DBG, + "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, " + "eop = 0x%x, count = 0x%x, credit_group = 0x%x, " + "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n", + UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id, + udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group, + udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num); + + if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH) + IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n", + cmd->lmac_cmd.id); + + ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len); + + /* We keep sending UMAC reset regardless of the command credits. + * The UMAC is supposed to be reset anyway and the Tx credits are + * reinitialized afterwards. If we are lucky, the reset could + * still be done even though we have run out of credits for the + * command pool at this moment.*/ + if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) { + IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n", + umac_cmd->id); + return ret; + } + + return iwm_bus_send_chunk(iwm, buf->start, buf->len); +} + +/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */ +int iwm_hal_send_target_cmd(struct iwm_priv *iwm, + struct iwm_udma_nonwifi_cmd *udma_cmd, + const void *payload) +{ + struct iwm_nonwifi_cmd *cmd; + int ret; + + cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); + if (!cmd) { + IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n"); + return -ENOMEM; + } + + 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) { + cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz); + memcpy(&cmd->buf.payload, payload, cmd->buf.len); + } + + ret = iwm_send_udma_nonwifi_cmd(iwm, cmd); + + if (!udma_cmd->resp) + kfree(cmd); + + if (ret < 0) + return ret; + + return cmd->seq_num; +} + +static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, + struct iwm_lmac_cmd *cmd) +{ + memset(hdr, 0, sizeof(*hdr)); + + hdr->id = cmd->id; + hdr->flags = 0; /* Is this ever used? */ + hdr->seq_num = cmd->seq_num; +} + +/* + * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC. + * Sending command to the LMAC is equivalent to sending a + * regular UMAC command with the LMAC passtrough or the LMAC + * wrapper UMAC command IDs. + */ +int iwm_hal_send_host_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + struct iwm_lmac_cmd *lmac_cmd, + const void *payload, u16 payload_size) +{ + struct iwm_wifi_cmd *cmd; + struct iwm_lmac_hdr *hdr; + int lmac_hdr_len = 0; + int ret; + + cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL); + if (!cmd) { + IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n"); + return -ENOMEM; + } + + iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size); + + if (lmac_cmd) { + hdr = (struct iwm_lmac_hdr *)(cmd->buf.start); + + iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd); + lmac_hdr_len = sizeof(struct iwm_lmac_hdr); + } + + memcpy(cmd->buf.payload, payload, payload_size); + cmd->buf.len = le16_to_cpu(umac_cmd->count); + + ret = iwm_send_udma_wifi_cmd(iwm, cmd); + + /* We free the cmd if we're not expecting any response */ + if (!umac_cmd->resp) + kfree(cmd); + return ret; +} + +/* + * iwm_hal_send_umac_cmd(): This is a special case for + * iwm_hal_send_host_cmd() to send direct UMAC cmd (without + * LMAC involved). + */ +int iwm_hal_send_umac_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + const void *payload, u16 payload_size) +{ + return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL, + payload, payload_size); +} diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h new file mode 100644 index 000000000000..0adfdc85765d --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/hal.h @@ -0,0 +1,236 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef _IWM_HAL_H_ +#define _IWM_HAL_H_ + +#include "umac.h" + +#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED) +#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED) +#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED) + +#define SET_VAL8(s, name, val) \ +do { \ + s = (s & ~(name##_SEED << name##_POS)) | \ + ((val & name##_SEED) << name##_POS); \ +} while (0) + +#define SET_VAL16(s, name, val) \ +do { \ + s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \ + ((val & name##_SEED) << name##_POS)); \ +} while (0) + +#define SET_VAL32(s, name, val) \ +do { \ + s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \ + ((val & name##_SEED) << name##_POS)); \ +} while (0) + + +#define UDMA_UMAC_INIT { .eop = 1, \ + .credit_group = 0x4, \ + .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \ + .lmac_offset = 0 } +#define UDMA_LMAC_INIT { .eop = 1, \ + .credit_group = 0x4, \ + .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \ + .lmac_offset = 4 } + + +/* UDMA IN OP CODE -- cmd bits [3:0] */ +#define UDMA_IN_OPCODE_MASK 0xF + +#define UDMA_IN_OPCODE_GENERAL_RESP 0x0 +#define UDMA_IN_OPCODE_READ_RESP 0x1 +#define UDMA_IN_OPCODE_WRITE_RESP 0x2 +#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5 +#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6 +#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7 +#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8 +#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9 +#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA +#define UDMA_IN_OPCODE_SW_MSG 0xB +#define UDMA_IN_OPCODE_WIFI 0xF +#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F +#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F + +/* HW API: udma_hdi_nonwifi API (OUT and IN) */ + +/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */ +#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9 +#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1 + +/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */ +#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11 +#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1 + +/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */ +#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12 +#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF + +/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */ +#define UDMA_IN_NW_HW_SEQ_NUM_POS 12 +#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF + +/* UDMA IN Non-WIFI HW signature -- bits [16:31] */ +#define UDMA_IN_NW_HW_SIG_POS 16 +#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF + +/* fixed signature */ +#define UDMA_IN_NW_HW_SIG 0xCBBC + +/* UDMA IN Non-WIFI HW block length -- bits [32:35] */ +#define UDMA_IN_NW_HW_LENGTH_SEED 0xF +#define UDMA_IN_NW_HW_LENGTH_POS 32 + +/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */ + +#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032 +#define IWM_MAX_WIFI_HEADERS_SIZE 32 +#define IWM_MAX_NONWIFI_HEADERS_SIZE 16 +#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ + IWM_MAX_NONWIFI_HEADERS_SIZE) +#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ + IWM_MAX_WIFI_HEADERS_SIZE) + +#define IWM_HAL_CONCATENATE_BUF_SIZE 8192 + +struct iwm_wifi_cmd_buff { + u16 len; + u8 *start; + u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE]; + u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE]; +}; + +struct iwm_nonwifi_cmd_buff { + u16 len; + u8 *start; + u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE]; + u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE]; +}; + +struct iwm_udma_nonwifi_cmd { + u8 opcode; + u8 eop; + u8 resp; + u8 handle_by_hw; + __le32 addr; + __le32 op1_sz; + __le32 op2; + __le16 seq_num; +}; + +struct iwm_udma_wifi_cmd { + __le16 count; + u8 eop; + u8 credit_group; + u8 ra_tid; + u8 lmac_offset; +}; + +struct iwm_umac_cmd { + u8 id; + __le16 count; + u8 resp; + __le16 seq_num; + u8 color; +}; + +struct iwm_lmac_cmd { + u8 id; + __le16 count; + u8 resp; + __le16 seq_num; +}; + +struct iwm_nonwifi_cmd { + u16 seq_num; + bool resp_received; + struct list_head pending; + struct iwm_udma_nonwifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_lmac_cmd lmac_cmd; + struct iwm_nonwifi_cmd_buff buf; + u32 flags; +}; + +struct iwm_wifi_cmd { + u16 seq_num; + struct list_head pending; + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_lmac_cmd lmac_cmd; + struct iwm_wifi_cmd_buff buf; + u32 flags; +}; + +void iwm_cmd_flush(struct iwm_priv *iwm); + +struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, + u16 seq_num); +struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, + u8 seq_num, u8 cmd_opcode); + + +int iwm_hal_send_target_cmd(struct iwm_priv *iwm, + struct iwm_udma_nonwifi_cmd *ucmd, + const void *payload); + +int iwm_hal_send_host_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + struct iwm_lmac_cmd *lmac_cmd, + const void *payload, u16 payload_size); + +int iwm_hal_send_umac_cmd(struct iwm_priv *iwm, + struct iwm_udma_wifi_cmd *udma_cmd, + struct iwm_umac_cmd *umac_cmd, + const void *payload, u16 payload_size); + +u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm); + +void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop); +void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm, + struct iwm_udma_out_wifi_hdr *hdr, + struct iwm_udma_wifi_cmd *cmd); +void iwm_build_umac_hdr(struct iwm_priv *iwm, + struct iwm_umac_fw_cmd_hdr *hdr, + struct iwm_umac_cmd *cmd); +#endif /* _IWM_HAL_H_ */ diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h new file mode 100644 index 000000000000..635c16ee6186 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -0,0 +1,346 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_H__ +#define __IWM_H__ + +#include +#include +#include + +#include "debug.h" +#include "hal.h" +#include "umac.h" +#include "lmac.h" +#include "eeprom.h" + +#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" +#define IWM_AUTHOR "" + +#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 +#define IWM_SRC_NUM 3 + +#define IWM_POWER_INDEX_MIN 0 +#define IWM_POWER_INDEX_MAX 5 +#define IWM_POWER_INDEX_DEFAULT 3 + +struct iwm_conf { + u32 sdio_ior_timeout; + unsigned long init_calib_map; + unsigned long periodic_calib_map; + bool reset_on_fatal_err; + bool auto_connect; + bool wimax_not_present; + bool enable_qos; + u32 mode; + + u32 power_index; + u32 frag_threshold; + u32 rts_threshold; + bool cts_to_self; + + u32 assoc_timeout; + u32 roam_timeout; + u32 wireless_mode; + u32 coexist_mode; + + u8 ibss_band; + u8 ibss_channel; + + u8 mac_addr[ETH_ALEN]; +#ifdef CONFIG_IWM_B0_HW_SUPPORT + bool hw_b0; +#endif +}; + +enum { + COEX_MODE_SA = 1, + COEX_MODE_XOR, + COEX_MODE_CM, + COEX_MODE_MAX, +}; + +struct iwm_if_ops; +struct iwm_wifi_cmd; + +struct pool_entry { + int id; /* group id */ + int sid; /* super group id */ + int min_pages; /* min capacity in pages */ + int max_pages; /* max capacity in pages */ + int alloc_pages; /* allocated # of pages. incresed by driver */ + int total_freed_pages; /* total freed # of pages. incresed by UMAC */ +}; + +struct spool_entry { + int id; + int max_pages; + int alloc_pages; +}; + +struct iwm_tx_credit { + spinlock_t lock; + int pool_nr; + unsigned long full_pools_map; /* bitmap for # of filled tx pools */ + struct pool_entry pools[IWM_MACS_OUT_GROUPS]; + struct spool_entry spools[IWM_MACS_OUT_SGROUPS]; +}; + +struct iwm_notif { + struct list_head pending; + u32 cmd_id; + void *cmd; + u8 src; + void *buf; + unsigned long buf_size; +}; + +struct iwm_sta_info { + u8 addr[ETH_ALEN]; + bool valid; + bool qos; + u8 color; +}; + +struct iwm_tx_info { + u8 sta; + u8 color; + u8 tid; +}; + +struct iwm_rx_info { + unsigned long rx_size; + unsigned long rx_buf_size; +}; + +#define IWM_NUM_KEYS 4 + +struct iwm_umac_key_hdr { + u8 mac[ETH_ALEN]; + u8 key_idx; + u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */ +} __attribute__ ((packed)); + +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]; +}; + +#define IWM_RX_ID_HASH 0xff +#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH) + +#define IWM_STA_TABLE_NUM 16 +#define IWM_TX_LIST_SIZE 64 +#define IWM_RX_LIST_SIZE 256 + +#define IWM_SCAN_ID_MAX 0xff + +#define IWM_STATUS_READY 0 +#define IWM_STATUS_SCANNING 1 +#define IWM_STATUS_SCAN_ABORTING 2 +#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; + struct workqueue_struct *wq; + struct work_struct worker; + u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE]; + int concat_count; + u8 *concat_ptr; +}; + +/* Queues 0 ~ 3 for AC data, 5 for iPAN */ +#define IWM_TX_QUEUES 5 +#define IWM_TX_DATA_QUEUES 4 +#define IWM_TX_CMD_QUEUE 4 + +struct iwm_bss_info { + struct list_head node; + struct cfg80211_bss *cfg_bss; + struct iwm_umac_notif_bss_info *bss; +}; + +typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd); + +#define IWM_WATCHDOG_PERIOD (6 * HZ) + +struct iwm_priv { + struct wireless_dev *wdev; + struct iwm_if_ops *bus_ops; + + struct iwm_conf conf; + + unsigned long status; + unsigned long radio; + + struct list_head pending_notif; + wait_queue_head_t notif_queue; + + wait_queue_head_t nonwifi_queue; + + unsigned long calib_done_map; + struct { + u8 *buf; + u32 size; + } calib_res[CALIBRATION_CMD_NUM]; + + struct iwm_umac_profile *umac_profile; + bool umac_profile_active; + + u8 bssid[ETH_ALEN]; + u8 channel; + u16 rate; + + struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM]; + struct list_head bss_list; + + void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX]) + (struct iwm_priv *priv, u8 *buf, unsigned long buf_size); + + const iwm_handler *umac_handlers; + const iwm_handler *lmac_handlers; + DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM); + DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM); + DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM); + + struct list_head wifi_pending_cmd; + struct list_head nonwifi_pending_cmd; + u16 wifi_seq_num; + u8 nonwifi_seq_num; + spinlock_t cmd_lock; + + u32 core_enabled; + + u8 scan_id; + struct cfg80211_scan_request *scan_request; + + struct sk_buff_head rx_list; + struct list_head rx_tickets; + struct list_head rx_packets[IWM_RX_ID_HASH]; + struct workqueue_struct *rx_wq; + struct work_struct rx_worker; + + struct iwm_tx_credit tx_credit; + struct iwm_tx_queue txq[IWM_TX_QUEUES]; + + struct iwm_key keys[IWM_NUM_KEYS]; + struct iwm_key *default_key; + + wait_queue_head_t mlme_queue; + + struct iw_statistics wstats; + struct delayed_work stats_request; + + struct iwm_debugfs dbg; + + u8 *eeprom; + struct timer_list watchdog; + struct work_struct reset_worker; + struct rfkill *rfkill; + + char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); +}; + +static inline void *iwm_private(struct iwm_priv *iwm) +{ + BUG_ON(!iwm); + return &iwm->private; +} + +#define hw_to_iwm(h) (h->iwm) +#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy)) +#define iwm_to_wiphy(i) (i->wdev->wiphy) +#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w)) +#define iwm_to_wdev(i) (i->wdev) +#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w)) +#define iwm_to_ndev(i) (i->wdev->netdev) +#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr)) +#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); +int iwm_mode_to_nl80211_iftype(int mode); +int iwm_priv_init(struct iwm_priv *iwm); +void iwm_reset(struct iwm_priv *iwm); +void iwm_tx_credit_init_pools(struct iwm_priv *iwm, + struct iwm_umac_notif_alive *alive); +int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb); +int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, + u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size); +int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout); +void iwm_init_default_profile(struct iwm_priv *iwm, + struct iwm_umac_profile *profile); +void iwm_link_on(struct iwm_priv *iwm); +void iwm_link_off(struct iwm_priv *iwm); +int iwm_up(struct iwm_priv *iwm); +int iwm_down(struct iwm_priv *iwm); + +/* TX API */ +void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages); +void iwm_tx_worker(struct work_struct *work); +int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev); + +/* RX API */ +void iwm_rx_setup_handlers(struct iwm_priv *iwm); +int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size); +int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, + struct iwm_wifi_cmd *cmd); +void iwm_rx_free(struct iwm_priv *iwm); + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h new file mode 100644 index 000000000000..db2e5eea1895 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/lmac.h @@ -0,0 +1,457 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_LMAC_H__ +#define __IWM_LMAC_H__ + +struct iwm_lmac_hdr { + u8 id; + u8 flags; + __le16 seq_num; +} __attribute__ ((packed)); + +/* LMAC commands */ +#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1 + +struct iwm_lmac_cal_cfg_elt { + __le32 enable; /* 1 means LMAC needs to do something */ + __le32 start; /* 1 to start calibration, 0 to stop */ + __le32 send_res; /* 1 for sending back results */ + __le32 apply_res; /* 1 for applying calibration results to HW */ + __le32 reserved; +} __attribute__ ((packed)); + +struct iwm_lmac_cal_cfg_status { + struct iwm_lmac_cal_cfg_elt init; + struct iwm_lmac_cal_cfg_elt periodic; + __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */ +} __attribute__ ((packed)); + +struct iwm_lmac_cal_cfg_cmd { + struct iwm_lmac_cal_cfg_status ucode_cfg; + struct iwm_lmac_cal_cfg_status driver_cfg; + __le32 reserved; +} __attribute__ ((packed)); + +struct iwm_lmac_cal_cfg_resp { + __le32 status; +} __attribute__ ((packed)); + +#define IWM_CARD_STATE_SW_HW_ENABLED 0x00 +#define IWM_CARD_STATE_HW_DISABLED 0x01 +#define IWM_CARD_STATE_SW_DISABLED 0x02 +#define IWM_CARD_STATE_CTKILL_DISABLED 0x04 +#define IWM_CARD_STATE_IS_RXON 0x10 + +struct iwm_lmac_card_state { + __le32 flags; +} __attribute__ ((packed)); + +/** + * COEX_PRIORITY_TABLE_CMD + * + * Priority entry for each state + * Will keep two tables, for STA and WIPAN + */ +enum { + /* UN-ASSOCIATION PART */ + COEX_UNASSOC_IDLE = 0, + COEX_UNASSOC_MANUAL_SCAN, + COEX_UNASSOC_AUTO_SCAN, + + /* CALIBRATION */ + COEX_CALIBRATION, + COEX_PERIODIC_CALIBRATION, + + /* CONNECTION */ + COEX_CONNECTION_ESTAB, + + /* ASSOCIATION PART */ + COEX_ASSOCIATED_IDLE, + COEX_ASSOC_MANUAL_SCAN, + COEX_ASSOC_AUTO_SCAN, + COEX_ASSOC_ACTIVE_LEVEL, + + /* RF ON/OFF */ + COEX_RF_ON, + COEX_RF_OFF, + COEX_STAND_ALONE_DEBUG, + + /* IPNN */ + COEX_IPAN_ASSOC_LEVEL, + + /* RESERVED */ + COEX_RSRVD1, + COEX_RSRVD2, + + COEX_EVENTS_NUM +}; + +#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK 0x1 +#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK 0x2 +#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK 0x4 + +struct coex_event { + u8 req_prio; + u8 win_med_prio; + u8 reserved; + u8 flags; +} __attribute__ ((packed)); + +#define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1 +#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4 +#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK 0x8 +#define COEX_FLAGS_COEX_ENABLE_MSK 0x80 + +struct iwm_coex_prio_table_cmd { + u8 flags; + u8 reserved[3]; + struct coex_event sta_prio[COEX_EVENTS_NUM]; +} __attribute__ ((packed)); + +/* Coexistence definitions + * + * Constants to fill in the Priorities' Tables + * RP - Requested Priority + * WP - Win Medium Priority: priority assigned when the contention has been won + * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and + * COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK + */ + +#define COEX_UNASSOC_IDLE_FLAGS 0 +#define COEX_UNASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_UNASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_CALIBRATION_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_PERIODIC_CALIBRATION_FLAGS 0 +/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX + * disconnect from network. */ +#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ + COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) +#define COEX_ASSOCIATED_IDLE_FLAGS 0 +#define COEX_ASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_ASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0 +#define COEX_RF_ON_FLAGS 0 +#define COEX_RF_OFF_FLAGS 0 +#define COEX_STAND_ALONE_DEBUG_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) +#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ + COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) +#define COEX_RSRVD1_FLAGS 0 +#define COEX_RSRVD2_FLAGS 0 +/* XOR_RF_ON is the event wrapping all radio ownership. We need + * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */ +#define COEX_XOR_RF_ON_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ + COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ + COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) + +/* LMAC OP CODES */ +#define REPLY_PAD 0x0 +#define REPLY_ALIVE 0x1 +#define REPLY_ERROR 0x2 +#define REPLY_ECHO 0x3 +#define REPLY_HALT 0x6 + +/* RXON state commands */ +#define REPLY_RX_ON 0x10 +#define REPLY_RX_ON_ASSOC 0x11 +#define REPLY_RX_OFF 0x12 +#define REPLY_QOS_PARAM 0x13 +#define REPLY_RX_ON_TIMING 0x14 +#define REPLY_INTERNAL_QOS_PARAM 0x15 +#define REPLY_RX_INT_TIMEOUT_CNFG 0x16 +#define REPLY_NULL 0x17 + +/* Multi-Station support */ +#define REPLY_ADD_STA 0x18 +#define REPLY_REMOVE_STA 0x19 +#define REPLY_RESET_ALL_STA 0x1a + +/* RX, TX */ +#define REPLY_ALM_RX 0x1b +#define REPLY_TX 0x1c +#define REPLY_TXFIFO_FLUSH 0x1e + +/* MISC commands */ +#define REPLY_MGMT_MCAST_KEY 0x1f +#define REPLY_WEPKEY 0x20 +#define REPLY_INIT_IV 0x21 +#define REPLY_WRITE_MIB 0x22 +#define REPLY_READ_MIB 0x23 +#define REPLY_RADIO_FE 0x24 +#define REPLY_TXFIFO_CFG 0x25 +#define REPLY_WRITE_READ 0x26 +#define REPLY_INSTALL_SEC_KEY 0x27 + + +#define REPLY_RATE_SCALE 0x47 +#define REPLY_LEDS_CMD 0x48 +#define REPLY_TX_LINK_QUALITY_CMD 0x4e +#define REPLY_ANA_MIB_OVERRIDE_CMD 0x4f +#define REPLY_WRITE2REG_CMD 0x50 + +/* winfi-wifi coexistence */ +#define COEX_PRIORITY_TABLE_CMD 0x5a +#define COEX_MEDIUM_NOTIFICATION 0x5b +#define COEX_EVENT_CMD 0x5c + +/* more Protocol and Protocol-test commands */ +#define REPLY_MAX_SLEEP_TIME_CMD 0x61 +#define CALIBRATION_CFG_CMD 0x65 +#define CALIBRATION_RES_NOTIFICATION 0x66 +#define CALIBRATION_COMPLETE_NOTIFICATION 0x67 + +/* Measurements */ +#define REPLY_QUIET_CMD 0x71 +#define REPLY_CHANNEL_SWITCH 0x72 +#define CHANNEL_SWITCH_NOTIFICATION 0x73 + +#define REPLY_SPECTRUM_MEASUREMENT_CMD 0x74 +#define SPECTRUM_MEASURE_NOTIFICATION 0x75 +#define REPLY_MEASUREMENT_ABORT_CMD 0x76 + +/* Power Management */ +#define POWER_TABLE_CMD 0x77 +#define SAVE_RESTORE_ADRESS_CMD 0x78 +#define REPLY_WATERMARK_CMD 0x79 +#define PM_DEBUG_STATISTIC_NOTIFIC 0x7B +#define PD_FLUSH_N_NOTIFICATION 0x7C + +/* Scan commands and notifications */ +#define REPLY_SCAN_REQUEST_CMD 0x80 +#define REPLY_SCAN_ABORT_CMD 0x81 +#define SCAN_START_NOTIFICATION 0x82 +#define SCAN_RESULTS_NOTIFICATION 0x83 +#define SCAN_COMPLETE_NOTIFICATION 0x84 + +/* Continuous TX commands */ +#define REPLY_CONT_TX_CMD 0x85 +#define END_OF_CONT_TX_NOTIFICATION 0x86 + +/* Timer/Eeprom commands */ +#define TIMER_CMD 0x87 +#define EEPROM_WRITE_CMD 0x88 + +/* PAPD commands */ +#define FEEDBACK_REQUEST_NOTIFICATION 0x8b +#define REPLY_CW_CMD 0x8c + +/* IBSS/AP commands Continue */ +#define BEACON_NOTIFICATION 0x90 +#define REPLY_TX_BEACON 0x91 +#define REPLY_REQUEST_ATIM 0x93 +#define WHO_IS_AWAKE_NOTIFICATION 0x94 +#define TX_PWR_DBM_LIMIT_CMD 0x95 +#define QUIET_NOTIFICATION 0x96 +#define TX_PWR_TABLE_CMD 0x97 +#define TX_ANT_CONFIGURATION_CMD 0x98 +#define MEASURE_ABORT_NOTIFICATION 0x99 +#define REPLY_CALIBRATION_TUNE 0x9a + +/* bt config command */ +#define REPLY_BT_CONFIG 0x9b +#define REPLY_STATISTICS_CMD 0x9c +#define STATISTICS_NOTIFICATION 0x9d + +/* RF-KILL commands and notifications */ +#define REPLY_CARD_STATE_CMD 0xa0 +#define CARD_STATE_NOTIFICATION 0xa1 + +/* Missed beacons notification */ +#define MISSED_BEACONS_NOTIFICATION 0xa2 +#define MISSED_BEACONS_NOTIFICATION_TH_CMD 0xa3 + +#define REPLY_CT_KILL_CONFIG_CMD 0xa4 + +/* HD commands and notifications */ +#define REPLY_HD_PARAMS_CMD 0xa6 +#define HD_PARAMS_NOTIFICATION 0xa7 +#define SENSITIVITY_CMD 0xa8 +#define U_APSD_PARAMS_CMD 0xa9 +#define NOISY_PLATFORM_CMD 0xaa +#define ILLEGAL_CMD 0xac +#define REPLY_PHY_CALIBRATION_CMD 0xb0 +#define REPLAY_RX_GAIN_CALIB_CMD 0xb1 + +/* WiPAN commands */ +#define REPLY_WIPAN_PARAMS_CMD 0xb2 +#define REPLY_WIPAN_RX_ON_CMD 0xb3 +#define REPLY_WIPAN_RX_ON_TIMING 0xb4 +#define REPLY_WIPAN_TX_PWR_TABLE_CMD 0xb5 +#define REPLY_WIPAN_RXON_ASSOC_CMD 0xb6 +#define REPLY_WIPAN_QOS_PARAM 0xb7 +#define WIPAN_REPLY_WEPKEY 0xb8 + +/* BeamForming commands */ +#define BEAMFORMER_CFG_CMD 0xba +#define BEAMFORMEE_NOTIFICATION 0xbb + +/* TGn new Commands */ +#define REPLY_RX_PHY_CMD 0xc0 +#define REPLY_RX_MPDU_CMD 0xc1 +#define REPLY_MULTICAST_HASH 0xc2 +#define REPLY_KDR_RX 0xc3 +#define REPLY_RX_DSP_EXT_INFO 0xc4 +#define REPLY_COMPRESSED_BA 0xc5 + +/* PNC commands */ +#define PNC_CONFIG_CMD 0xc8 +#define PNC_UPDATE_TABLE_CMD 0xc9 +#define XVT_GENERAL_CTRL_CMD 0xca +#define REPLY_LEGACY_RADIO_FE 0xdd + +/* WoWLAN commands */ +#define WOWLAN_PATTERNS 0xe0 +#define WOWLAN_WAKEUP_FILTER 0xe1 +#define WOWLAN_TSC_RSC_PARAM 0xe2 +#define WOWLAN_TKIP_PARAM 0xe3 +#define WOWLAN_KEK_KCK_MATERIAL 0xe4 +#define WOWLAN_GET_STATUSES 0xe5 +#define WOWLAN_TX_POWER_PER_DB 0xe6 +#define REPLY_WOWLAN_GET_STATUSES WOWLAN_GET_STATUSES + +#define REPLY_DEBUG_CMD 0xf0 +#define REPLY_DSP_DEBUG_CMD 0xf1 +#define REPLY_DEBUG_MONITOR_CMD 0xf2 +#define REPLY_DEBUG_XVT_CMD 0xf3 +#define REPLY_DEBUG_DC_CALIB 0xf4 +#define REPLY_DYNAMIC_BP 0xf5 + +/* General purpose Commands */ +#define REPLY_GP1_CMD 0xfa +#define REPLY_GP2_CMD 0xfb +#define REPLY_GP3_CMD 0xfc +#define REPLY_GP4_CMD 0xfd +#define REPLY_REPLAY_WRAPPER 0xfe +#define REPLY_FRAME_DURATION_CALC_CMD 0xff + +#define LMAC_COMMAND_ID_MAX 0xff +#define LMAC_COMMAND_ID_NUM (LMAC_COMMAND_ID_MAX + 1) + + +/* Calibration */ + +enum { + PHY_CALIBRATE_DC_CMD = 0, + PHY_CALIBRATE_LO_CMD = 1, + PHY_CALIBRATE_RX_BB_CMD = 2, + PHY_CALIBRATE_TX_IQ_CMD = 3, + PHY_CALIBRATE_RX_IQ_CMD = 4, + PHY_CALIBRATION_NOISE_CMD = 5, + PHY_CALIBRATE_AGC_TABLE_CMD = 6, + PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 7, + PHY_CALIBRATE_OPCODES_NUM, + SHILOH_PHY_CALIBRATE_DC_CMD = 8, + SHILOH_PHY_CALIBRATE_LO_CMD = 9, + SHILOH_PHY_CALIBRATE_RX_BB_CMD = 10, + SHILOH_PHY_CALIBRATE_TX_IQ_CMD = 11, + SHILOH_PHY_CALIBRATE_RX_IQ_CMD = 12, + SHILOH_PHY_CALIBRATION_NOISE_CMD = 13, + SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD = 14, + SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, + SHILOH_PHY_CALIBRATE_BASE_BAND_CMD = 16, + SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD = 17, + CALIBRATION_CMD_NUM, +}; + +struct iwm_lmac_calib_hdr { + u8 opcode; + u8 first_grp; + u8 grp_num; + u8 all_data_valid; +} __attribute__ ((packed)); + +#define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7 +#define IWM_CALIB_FREQ_GROUPS_NR 5 +#define IWM_CALIB_DC_MODES_NR 12 + +struct iwm_calib_rxiq_entry { + u16 ptam_postdist_ars; + u16 ptam_postdist_arc; +} __attribute__ ((packed)); + +struct iwm_calib_rxiq_group { + struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR]; +} __attribute__ ((packed)); + +struct iwm_lmac_calib_rxiq { + struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR]; +} __attribute__ ((packed)); + +struct iwm_calib_rxiq { + struct iwm_lmac_calib_hdr hdr; + struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR]; +} __attribute__ ((packed)); + +#define LMAC_STA_ID_SEED 0x0f +#define LMAC_STA_ID_POS 0 + +#define LMAC_STA_COLOR_SEED 0x7 +#define LMAC_STA_COLOR_POS 4 + +struct iwm_lmac_power_report { + u8 pa_status; + u8 pa_integ_res_A[3]; + u8 pa_integ_res_B[3]; + u8 pa_integ_res_C[3]; +} __attribute__ ((packed)); + +struct iwm_lmac_tx_resp { + u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */ + u8 bt_kill_cnt; + __le16 retry_cnt; + __le32 initial_tx_rate; + __le16 wireless_media_time; + struct iwm_lmac_power_report power_report; + __le32 tfd_info; + __le16 seq_ctl; + __le16 byte_cnt; + u8 tlc_rate_info; + u8 ra_tid; + __le16 frame_ctl; + __le32 status; +} __attribute__ ((packed)); + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c new file mode 100644 index 000000000000..6a2640f16b6d --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -0,0 +1,680 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "bus.h" +#include "umac.h" +#include "commands.h" +#include "hal.h" +#include "fw.h" +#include "rx.h" + +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) | + BIT(PHY_CALIBRATE_LO_CMD) | + BIT(PHY_CALIBRATE_TX_IQ_CMD) | + BIT(PHY_CALIBRATE_RX_IQ_CMD) | + BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), + .reset_on_fatal_err = 1, + .auto_connect = 1, + .wimax_not_present = 0, + .enable_qos = 1, + .mode = UMAC_MODE_BSS, + + /* UMAC configuration */ + .power_index = 0, + .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, + .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, + .cts_to_self = 0, + + .assoc_timeout = 2, + .roam_timeout = 10, + .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G, + .coexist_mode = COEX_MODE_CM, + + /* IBSS */ + .ibss_band = UMAC_BAND_2GHZ, + .ibss_channel = 1, + + .mac_addr = {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03}, +}; + +static int modparam_reset; +module_param_named(reset, modparam_reset, bool, 0644); +MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])"); + +int iwm_mode_to_nl80211_iftype(int mode) +{ + switch (mode) { + case UMAC_MODE_BSS: + return NL80211_IFTYPE_STATION; + case UMAC_MODE_IBSS: + return NL80211_IFTYPE_ADHOC; + default: + return NL80211_IFTYPE_UNSPECIFIED; + } + + return 0; +} + +static void iwm_statistics_request(struct work_struct *work) +{ + struct iwm_priv *iwm = + container_of(work, struct iwm_priv, stats_request.work); + + iwm_send_umac_stats_req(iwm, 0); +} + +static void iwm_reset_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + struct iwm_umac_profile *profile = NULL; + int uninitialized_var(ret), retry = 0; + + iwm = container_of(work, struct iwm_priv, reset_worker); + + if (iwm->umac_profile_active) { + profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL); + if (profile) + memcpy(profile, iwm->umac_profile, sizeof(*profile)); + else + IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); + } + + iwm_down(iwm); + + while (retry++ < 3) { + ret = iwm_up(iwm); + if (!ret) + break; + + schedule_timeout_uninterruptible(10 * HZ); + } + + if (ret) { + IWM_WARN(iwm, "iwm_up() failed: %d\n", ret); + + kfree(profile); + return; + } + + if (profile) { + IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n"); + memcpy(iwm->umac_profile, profile, sizeof(*profile)); + iwm_send_mlme_profile(iwm); + kfree(profile); + } +} + +static void iwm_watchdog(unsigned long data) +{ + struct iwm_priv *iwm = (struct iwm_priv *)data; + + IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); + + if (modparam_reset) + schedule_work(&iwm->reset_worker); +} + +int iwm_priv_init(struct iwm_priv *iwm) +{ + int i; + char name[32]; + + iwm->status = 0; + INIT_LIST_HEAD(&iwm->pending_notif); + init_waitqueue_head(&iwm->notif_queue); + init_waitqueue_head(&iwm->nonwifi_queue); + init_waitqueue_head(&iwm->mlme_queue); + memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf)); + spin_lock_init(&iwm->tx_credit.lock); + INIT_LIST_HEAD(&iwm->wifi_pending_cmd); + INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd); + iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE; + iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE; + spin_lock_init(&iwm->cmd_lock); + iwm->scan_id = 1; + INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); + INIT_WORK(&iwm->reset_worker, iwm_reset_worker); + INIT_LIST_HEAD(&iwm->bss_list); + + skb_queue_head_init(&iwm->rx_list); + INIT_LIST_HEAD(&iwm->rx_tickets); + for (i = 0; i < IWM_RX_ID_HASH; i++) + INIT_LIST_HEAD(&iwm->rx_packets[i]); + + INIT_WORK(&iwm->rx_worker, iwm_rx_worker); + + iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx"); + if (!iwm->rx_wq) + return -EAGAIN; + + for (i = 0; i < IWM_TX_QUEUES; i++) { + INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker); + snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i); + iwm->txq[i].id = i; + iwm->txq[i].wq = create_singlethread_workqueue(name); + if (!iwm->txq[i].wq) + return -EAGAIN; + + skb_queue_head_init(&iwm->txq[i].queue); + } + + for (i = 0; i < IWM_NUM_KEYS; i++) + memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); + + iwm->default_key = NULL; + + init_timer(&iwm->watchdog); + iwm->watchdog.function = iwm_watchdog; + iwm->watchdog.data = (unsigned long)iwm; + + return 0; +} + +/* + * We reset all the structures, and we reset the UMAC. + * After calling this routine, you're expected to reload + * the firmware. + */ +void iwm_reset(struct iwm_priv *iwm) +{ + struct iwm_notif *notif, *next; + + if (test_bit(IWM_STATUS_READY, &iwm->status)) + iwm_target_reset(iwm); + + iwm->status = 0; + iwm->scan_id = 1; + + list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { + list_del(¬if->pending); + kfree(notif->buf); + kfree(notif); + } + + iwm_cmd_flush(iwm); + + flush_workqueue(iwm->rx_wq); + + iwm_link_off(iwm); +} + +/* + * Notification code: + * + * We're faced with the following issue: Any host command can + * have an answer or not, and if there's an answer to expect, + * it can be treated synchronously or asynchronously. + * To work around the synchronous answer case, we implemented + * our notification mechanism. + * When a code path needs to wait for a command response + * synchronously, it calls notif_handle(), which waits for the + * right notification to show up, and then process it. Before + * starting to wait, it registered as a waiter for this specific + * answer (by toggling a bit in on of the handler_map), so that + * the rx code knows that it needs to send a notification to the + * waiting processes. It does so by calling iwm_notif_send(), + * which adds the notification to the pending notifications list, + * and then wakes the waiting processes up. + */ +int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, + u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size) +{ + struct iwm_notif *notif; + + notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL); + if (!notif) { + IWM_ERR(iwm, "Couldn't alloc memory for notification\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(¬if->pending); + notif->cmd = cmd; + notif->cmd_id = cmd_id; + notif->src = source; + notif->buf = kzalloc(buf_size, GFP_KERNEL); + if (!notif->buf) { + IWM_ERR(iwm, "Couldn't alloc notification buffer\n"); + kfree(notif); + return -ENOMEM; + } + notif->buf_size = buf_size; + memcpy(notif->buf, buf, buf_size); + list_add_tail(¬if->pending, &iwm->pending_notif); + + wake_up_interruptible(&iwm->notif_queue); + + return 0; +} + +static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, + u8 source) +{ + struct iwm_notif *notif, *next; + + list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { + if ((notif->cmd_id == cmd) && (notif->src == source)) { + list_del(¬if->pending); + return notif; + } + } + + return NULL; +} + +static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd, + u8 source, long timeout) +{ + int ret; + struct iwm_notif *notif; + unsigned long *map = NULL; + + switch (source) { + case IWM_SRC_LMAC: + map = &iwm->lmac_handler_map[0]; + break; + case IWM_SRC_UMAC: + map = &iwm->umac_handler_map[0]; + break; + case IWM_SRC_UDMA: + map = &iwm->udma_handler_map[0]; + break; + } + + set_bit(cmd, map); + + ret = wait_event_interruptible_timeout(iwm->notif_queue, + ((notif = iwm_notif_find(iwm, cmd, source)) != NULL), + timeout); + clear_bit(cmd, map); + + if (!ret) + return NULL; + + return notif; +} + +int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout) +{ + int ret; + struct iwm_notif *notif; + + notif = iwm_notif_wait(iwm, cmd, source, timeout); + if (!notif) + return -ETIME; + + ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd); + kfree(notif->buf); + kfree(notif); + + return ret; +} + +static int iwm_config_boot_params(struct iwm_priv *iwm) +{ + struct iwm_udma_nonwifi_cmd target_cmd; + int ret; + + /* check Wimax is off and config debug monitor */ + if (iwm->conf.wimax_not_present) { + u32 data1 = 0x1f; + u32 addr1 = 0x606BE258; + + u32 data2_set = 0x0; + u32 data2_clr = 0x1; + u32 addr2 = 0x606BE100; + + u32 data3 = 0x1; + u32 addr3 = 0x606BEC00; + + target_cmd.resp = 0; + target_cmd.handle_by_hw = 0; + target_cmd.eop = 1; + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; + target_cmd.addr = cpu_to_le32(addr1); + target_cmd.op1_sz = cpu_to_le32(sizeof(u32)); + target_cmd.op2 = 0; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1); + if (ret < 0) { + IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); + return ret; + } + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE; + target_cmd.addr = cpu_to_le32(addr2); + target_cmd.op1_sz = cpu_to_le32(data2_set); + target_cmd.op2 = cpu_to_le32(data2_clr); + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1); + if (ret < 0) { + IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); + return ret; + } + + target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; + target_cmd.addr = cpu_to_le32(addr3); + target_cmd.op1_sz = cpu_to_le32(sizeof(u32)); + target_cmd.op2 = 0; + + ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3); + if (ret < 0) { + IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); + return ret; + } + } + + return 0; +} + +void iwm_init_default_profile(struct iwm_priv *iwm, + struct iwm_umac_profile *profile) +{ + memset(profile, 0, sizeof(struct iwm_umac_profile)); + + profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN; + profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; + profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE; + profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE; + + if (iwm->conf.enable_qos) + profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED); + + profile->wireless_mode = iwm->conf.wireless_mode; + profile->mode = cpu_to_le32(iwm->conf.mode); + + profile->ibss.atim = 0; + profile->ibss.beacon_interval = 100; + profile->ibss.join_only = 0; + profile->ibss.band = iwm->conf.ibss_band; + profile->ibss.channel = iwm->conf.ibss_channel; +} + +void iwm_link_on(struct iwm_priv *iwm) +{ + netif_carrier_on(iwm_to_ndev(iwm)); + netif_tx_wake_all_queues(iwm_to_ndev(iwm)); + + iwm_send_umac_stats_req(iwm, 0); +} + +void iwm_link_off(struct iwm_priv *iwm) +{ + struct iw_statistics *wstats = &iwm->wstats; + int i; + + netif_tx_stop_all_queues(iwm_to_ndev(iwm)); + netif_carrier_off(iwm_to_ndev(iwm)); + + for (i = 0; i < IWM_TX_QUEUES; i++) { + skb_queue_purge(&iwm->txq[i].queue); + + iwm->txq[i].concat_count = 0; + iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf; + + flush_workqueue(iwm->txq[i].wq); + } + + iwm_rx_free(iwm); + + cancel_delayed_work(&iwm->stats_request); + memset(wstats, 0, sizeof(struct iw_statistics)); + wstats->qual.updated = IW_QUAL_ALL_INVALID; + + del_timer_sync(&iwm->watchdog); +} + +static void iwm_bss_list_clean(struct iwm_priv *iwm) +{ + struct iwm_bss_info *bss, *next; + + list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { + list_del(&bss->node); + kfree(bss->bss); + kfree(bss); + } +} + +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"); + return ret; + } + + ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Didn't get a channel list notification\n"); + return ret; + } + + return 0; +} + +int iwm_up(struct iwm_priv *iwm) +{ + int ret; + struct iwm_notif *notif_reboot, *notif_ack = NULL; + + ret = iwm_bus_enable(iwm); + if (ret) { + IWM_ERR(iwm, "Couldn't enable function\n"); + return ret; + } + + iwm_rx_setup_handlers(iwm); + + /* Wait for initial BARKER_REBOOT from hardware */ + notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION, + IWM_SRC_UDMA, 2 * HZ); + if (!notif_reboot) { + IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n"); + goto err_disable; + } + + /* We send the barker back */ + ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16); + if (ret) { + IWM_ERR(iwm, "REBOOT barker response failed\n"); + kfree(notif_reboot); + goto err_disable; + } + + kfree(notif_reboot->buf); + kfree(notif_reboot); + + /* Wait for ACK_BARKER from hardware */ + notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION, + IWM_SRC_UDMA, 2 * HZ); + if (!notif_ack) { + IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n"); + goto err_disable; + } + + kfree(notif_ack->buf); + kfree(notif_ack); + + /* We start to config static boot parameters */ + ret = iwm_config_boot_params(iwm); + if (ret) { + IWM_ERR(iwm, "Config boot parameters failed\n"); + goto err_disable; + } + + ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr); + if (ret) { + IWM_ERR(iwm, "MAC reading failed\n"); + goto err_disable; + } + + /* We can load the FWs */ + ret = iwm_load_fw(iwm); + if (ret) { + IWM_ERR(iwm, "FW loading failed\n"); + goto err_disable; + } + + /* We configure the UMAC and enable the wifi module */ + ret = iwm_send_umac_config(iwm, + cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) | + cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) | + cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN)); + if (ret) { + IWM_ERR(iwm, "UMAC config failed\n"); + goto err_fw; + } + + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Didn't get a wifi core status notification\n"); + goto err_fw; + } + + if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN | + UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) { + IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n", + iwm->core_enabled); + ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS, + IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); + if (ret) { + IWM_ERR(iwm, "Didn't get a core status notification\n"); + goto err_fw; + } + + if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN | + UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) { + IWM_ERR(iwm, "Not all cores enabled: 0x%x\n", + iwm->core_enabled); + goto err_fw; + } else { + IWM_INFO(iwm, "All cores enabled\n"); + } + } + + 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; + } + + /* Set the READY bit to indicate interface is brought up successfully */ + set_bit(IWM_STATUS_READY, &iwm->status); + + return 0; + + err_profile: + kfree(iwm->umac_profile); + iwm->umac_profile = NULL; + + err_fw: + iwm_eeprom_exit(iwm); + + err_disable: + ret = iwm_bus_disable(iwm); + if (ret < 0) + IWM_ERR(iwm, "Couldn't disable function\n"); + + return -EIO; +} + +int iwm_down(struct iwm_priv *iwm) +{ + int ret; + + /* The interface is already down */ + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return 0; + + if (iwm->scan_request) { + cfg80211_scan_done(iwm->scan_request, true); + iwm->scan_request = NULL; + } + + 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->core_enabled = 0; + + ret = iwm_bus_disable(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't disable function\n"); + return ret; + } + + return 0; +} diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c new file mode 100644 index 000000000000..68e2c3b6c7a1 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -0,0 +1,162 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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. + * + */ + +/* + * This is the netdev related hooks for iwm. + * + * Some interesting code paths: + * + * iwm_open() (Called at netdev interface bringup time) + * -> iwm_up() (main.c) + * -> iwm_bus_enable() + * -> if_sdio_enable() (In case of an SDIO bus) + * -> sdio_enable_func() + * -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker) + * -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker) + * -> iwm_load_fw() (fw.c) + * -> iwm_load_umac() + * -> iwm_load_lmac() (Calibration LMAC) + * -> iwm_load_lmac() (Operational LMAC) + * -> iwm_send_umac_config() + * + * iwm_stop() (Called at netdev interface bringdown time) + * -> iwm_down() + * -> iwm_bus_disable() + * -> if_sdio_disable() (In case of an SDIO bus) + * -> sdio_disable_func() + */ +#include + +#include "iwm.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; +} + +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; +} + +/* + * iwm AC to queue mapping + * + * AC_VO -> queue 3 + * AC_VI -> queue 2 + * AC_BE -> queue 1 + * AC_BK -> queue 0 + */ +static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + skb->priority = cfg80211_classify8021d(skb); + + return iwm_1d_to_queue[skb->priority]; +} + +static const struct net_device_ops iwm_netdev_ops = { + .ndo_open = iwm_open, + .ndo_stop = iwm_stop, + .ndo_start_xmit = iwm_xmit_frame, + .ndo_select_queue = iwm_select_queue, +}; + +void *iwm_if_alloc(int sizeof_bus, struct device *dev, + struct iwm_if_ops *if_ops) +{ + struct net_device *ndev; + struct wireless_dev *wdev; + struct iwm_priv *iwm; + int ret = 0; + + wdev = iwm_wdev_alloc(sizeof_bus, dev); + if (!wdev) { + dev_err(dev, "no memory for wireless device instance\n"); + return ERR_PTR(-ENOMEM); + } + + iwm = wdev_to_iwm(wdev); + iwm->bus_ops = if_ops; + iwm->wdev = wdev; + iwm_priv_init(iwm); + wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); + + ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, + IWM_TX_QUEUES); + if (!ndev) { + dev_err(dev, "no memory for network device instance\n"); + goto out_wdev; + } + + 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)); + ret = register_netdev(ndev); + if (ret < 0) { + dev_err(dev, "Failed to register netdev: %d\n", ret); + goto out_ndev; + } + + wdev->netdev = ndev; + + return iwm; + + out_ndev: + free_netdev(ndev); + + out_wdev: + iwm_wdev_free(iwm); + return ERR_PTR(ret); +} + +void iwm_if_free(struct iwm_priv *iwm) +{ + int i; + + if (!iwm_to_ndev(iwm)) + return; + + unregister_netdev(iwm_to_ndev(iwm)); + free_netdev(iwm_to_ndev(iwm)); + iwm_wdev_free(iwm); + destroy_workqueue(iwm->rx_wq); + for (i = 0; i < IWM_TX_QUEUES; i++) + destroy_workqueue(iwm->txq[i].wq); +} diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c new file mode 100644 index 000000000000..d73cf96c6dc6 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -0,0 +1,1431 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "hal.h" +#include "umac.h" +#include "lmac.h" +#include "commands.h" +#include "rx.h" +#include "cfg80211.h" +#include "eeprom.h" + +static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr) +{ + if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) || + (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL)) + return -EINVAL; + + return 0; +} + +static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr) +{ + return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr), + 16); +} + +/* + * Notification handlers: + * + * For every possible notification we can receive from the + * target, we have a handler. + * When we get a target notification, and there is no one + * waiting for it, it's just processed through the rx code + * path: + * + * iwm_rx_handle() + * -> iwm_rx_handle_umac() + * -> iwm_rx_handle_wifi() + * -> iwm_rx_handle_resp() + * -> iwm_ntf_*() + * + * OR + * + * -> iwm_rx_handle_non_wifi() + * + * If there are processes waiting for this notification, then + * iwm_rx_handle_wifi() just wakes those processes up and they + * grab the pending notification. + */ +static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_error *error; + struct iwm_fw_error_hdr *fw_err; + + 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)); + IWM_ERR(iwm, "\tStatus: 0x%x\n", le32_to_cpu(fw_err->status)); + IWM_ERR(iwm, "\tPC: 0x%x\n", le32_to_cpu(fw_err->pc)); + IWM_ERR(iwm, "\tblink1: %d\n", le32_to_cpu(fw_err->blink1)); + IWM_ERR(iwm, "\tblink2: %d\n", le32_to_cpu(fw_err->blink2)); + IWM_ERR(iwm, "\tilink1: %d\n", le32_to_cpu(fw_err->ilink1)); + IWM_ERR(iwm, "\tilink2: %d\n", le32_to_cpu(fw_err->ilink2)); + IWM_ERR(iwm, "\tData1: 0x%x\n", le32_to_cpu(fw_err->data1)); + IWM_ERR(iwm, "\tData2: 0x%x\n", le32_to_cpu(fw_err->data2)); + IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num)); + IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status)); + IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status)); + IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status)); + + return 0; +} + +static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_alive *alive_resp = + (struct iwm_umac_notif_alive *)(buf); + u16 status = le16_to_cpu(alive_resp->status); + + if (status == UMAC_NTFY_ALIVE_STATUS_ERR) { + IWM_ERR(iwm, "Receive error UMAC_ALIVE\n"); + return -EIO; + } + + iwm_tx_credit_init_pools(iwm, alive_resp); + + return 0; +} + +static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_init_complete *init_complete = + (struct iwm_umac_notif_init_complete *)(buf); + u16 status = le16_to_cpu(init_complete->status); + + if (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR) { + IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n"); + set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio); + } else { + IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n"); + clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio); + } + + return 0; +} + +static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + int pool_nr, total_freed_pages; + unsigned long pool_map; + int i, id; + struct iwm_umac_notif_page_dealloc *dealloc = + (struct iwm_umac_notif_page_dealloc *)buf; + + pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT); + pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK); + + IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, " + "update map 0x%lx\n", pool_nr, pool_map); + + spin_lock(&iwm->tx_credit.lock); + + for (i = 0; i < pool_nr; i++) { + id = GET_VAL32(dealloc->grp_info[i], + UMAC_DEALLOC_NTFY_GROUP_NUM); + if (test_bit(id, &pool_map)) { + total_freed_pages = GET_VAL32(dealloc->grp_info[i], + UMAC_DEALLOC_NTFY_PAGE_CNT); + iwm_tx_credit_inc(iwm, id, total_freed_pages); + } + } + + spin_unlock(&iwm->tx_credit.lock); + + return 0; +} + +static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n"); + + return 0; +} + +static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]); + + return 0; +} + +static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_lmac_tx_resp *tx_resp; + struct iwm_umac_wifi_in_hdr *hdr; + + tx_resp = (struct iwm_lmac_tx_resp *) + (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_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)); + + return 0; +} + + +static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + u8 opcode; + u8 *calib_buf; + struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + + opcode = hdr->opcode; + + BUG_ON(opcode >= CALIBRATION_CMD_NUM || + opcode < PHY_CALIBRATE_OPCODES_NUM); + + IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n", + opcode); + + buf_size -= sizeof(struct iwm_umac_wifi_in_hdr); + calib_buf = iwm->calib_res[opcode].buf; + + if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) { + kfree(calib_buf); + calib_buf = kzalloc(buf_size, GFP_KERNEL); + if (!calib_buf) { + IWM_ERR(iwm, "Memory allocation failed: calib_res\n"); + return -ENOMEM; + } + iwm->calib_res[opcode].buf = calib_buf; + iwm->calib_res[opcode].size = buf_size; + } + + memcpy(calib_buf, hdr, buf_size); + set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map); + + return 0; +} + +static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_NTF(iwm, DBG, "Calibration completed\n"); + + return 0; +} + +static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_lmac_cal_cfg_resp *cal_resp; + + cal_resp = (struct iwm_lmac_cal_cfg_resp *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + + IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n", + le32_to_cpu(cal_resp->status)); + + return 0; +} + +static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_wifi_status *status = + (struct iwm_umac_notif_wifi_status *)buf; + + iwm->core_enabled |= le16_to_cpu(status->status); + + return 0; +} + +static struct iwm_rx_ticket_node * +iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket) +{ + struct iwm_rx_ticket_node *ticket_node; + + ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL); + if (!ticket_node) { + IWM_ERR(iwm, "Couldn't allocate ticket node\n"); + return ERR_PTR(-ENOMEM); + } + + ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL); + if (!ticket_node->ticket) { + IWM_ERR(iwm, "Couldn't allocate RX ticket\n"); + kfree(ticket_node); + return ERR_PTR(-ENOMEM); + } + + memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket)); + INIT_LIST_HEAD(&ticket_node->node); + + return ticket_node; +} + +static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node) +{ + kfree(ticket_node->ticket); + kfree(ticket_node); +} + +static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) +{ + u8 id_hash = IWM_RX_ID_GET_HASH(id); + struct list_head *packet_list; + struct iwm_rx_packet *packet, *next; + + packet_list = &iwm->rx_packets[id_hash]; + + list_for_each_entry_safe(packet, next, packet_list, node) + if (packet->id == id) + return packet; + + return NULL; +} + +static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf, + u32 size, u16 id) +{ + struct iwm_rx_packet *packet; + + packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL); + if (!packet) { + IWM_ERR(iwm, "Couldn't allocate packet\n"); + return ERR_PTR(-ENOMEM); + } + + packet->skb = dev_alloc_skb(size); + if (!packet->skb) { + IWM_ERR(iwm, "Couldn't allocate packet SKB\n"); + kfree(packet); + return ERR_PTR(-ENOMEM); + } + + packet->pkt_size = size; + + skb_put(packet->skb, size); + memcpy(packet->skb->data, buf, size); + INIT_LIST_HEAD(&packet->node); + packet->id = id; + + return packet; +} + +void iwm_rx_free(struct iwm_priv *iwm) +{ + struct iwm_rx_ticket_node *ticket, *nt; + struct iwm_rx_packet *packet, *np; + int i; + + list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { + list_del(&ticket->node); + iwm_rx_ticket_node_free(ticket); + } + + for (i = 0; i < IWM_RX_ID_HASH; i++) { + list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], + node) { + list_del(&packet->node); + kfree_skb(packet->skb); + kfree(packet); + } + } +} + +static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_rx_ticket *ntf_rx_ticket = + (struct iwm_umac_notif_rx_ticket *)buf; + struct iwm_rx_ticket *ticket = + (struct iwm_rx_ticket *)ntf_rx_ticket->tickets; + int i, schedule_rx = 0; + + for (i = 0; i < ntf_rx_ticket->num_tickets; i++) { + struct iwm_rx_ticket_node *ticket_node; + + switch (le16_to_cpu(ticket->action)) { + case IWM_RX_TICKET_RELEASE: + case IWM_RX_TICKET_DROP: + /* We can push the packet to the stack */ + ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket); + if (IS_ERR(ticket_node)) + return PTR_ERR(ticket_node); + + IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n", + ticket->id); + list_add_tail(&ticket_node->node, &iwm->rx_tickets); + + /* + * We received an Rx ticket, most likely there's + * a packet pending for it, it's not worth going + * through the packet hash list to double check. + * Let's just fire the rx worker.. + */ + schedule_rx = 1; + + break; + + default: + IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n", + ticket->action); + } + + ticket++; + } + + if (schedule_rx) + queue_work(iwm->rx_wq, &iwm->rx_worker); + + return 0; +} + +static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_wifi_in_hdr *wifi_hdr; + struct iwm_rx_packet *packet; + u16 id, buf_offset; + u32 packet_size; + + IWM_DBG_NTF(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, "Packet id: %d\n", id); + IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); + + packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id); + if (IS_ERR(packet)) + return PTR_ERR(packet); + + list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]); + + /* We might (unlikely) have received the packet _after_ the ticket */ + queue_work(iwm->rx_wq, &iwm->rx_worker); + + return 0; +} + +/* MLME handlers */ +static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_assoc_start *start; + + start = (struct iwm_umac_notif_assoc_start *)buf; + + set_bit(IWM_STATUS_ASSOCIATING, &iwm->status); + + IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n", + start->bssid, le32_to_cpu(start->roam_reason)); + + wake_up_interruptible(&iwm->mlme_queue); + + return 0; +} + +static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + 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)) { + case UMAC_ASSOC_COMPLETE_SUCCESS: + set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + memcpy(iwm->bssid, complete->bssid, ETH_ALEN); + iwm->channel = complete->channel; + + iwm_link_on(iwm); + + memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN); + break; + case UMAC_ASSOC_COMPLETE_FAILURE: + clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + memset(iwm->bssid, 0, ETH_ALEN); + iwm->channel = 0; + + iwm_link_off(iwm); + 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; +} + +static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_profile_invalidate *invalid; + + invalid = (struct iwm_umac_notif_profile_invalidate *)buf; + + IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", + le32_to_cpu(invalid->reason)); + + clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); + clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + + iwm->umac_profile_active = 0; + memset(iwm->bssid, 0, ETH_ALEN); + iwm->channel = 0; + + iwm_link_off(iwm); + + wake_up_interruptible(&iwm->mlme_queue); + + return 0; +} + +static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + int ret; + struct iwm_umac_notif_scan_complete *scan_complete = + (struct iwm_umac_notif_scan_complete *)buf; + u32 result = le32_to_cpu(scan_complete->result); + + IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n", + le32_to_cpu(scan_complete->type), + le32_to_cpu(scan_complete->result), + scan_complete->seq_num); + + if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) { + IWM_ERR(iwm, "Scan complete while device not scanning\n"); + return -EIO; + } + if (!iwm->scan_request) + return 0; + + ret = iwm_cfg80211_inform_bss(iwm); + + cfg80211_scan_done(iwm->scan_request, + (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret); + iwm->scan_request = NULL; + + return ret; +} + +static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_sta_info *umac_sta = + (struct iwm_umac_notif_sta_info *)buf; + struct iwm_sta_info *sta; + int i; + + switch (le32_to_cpu(umac_sta->opcode)) { + case UMAC_OPCODE_ADD_MODIFY: + sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)]; + + IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, " + "addr = %pM, qos = %d\n", + sta->valid ? "Modify" : "Add", + GET_VAL8(umac_sta->sta_id, LMAC_STA_ID), + GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR), + umac_sta->mac_addr, + umac_sta->flags & UMAC_STA_FLAG_QOS); + + sta->valid = 1; + sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS; + sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR); + memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN); + break; + case UMAC_OPCODE_REMOVE: + IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, " + "addr = %pM\n", + GET_VAL8(umac_sta->sta_id, LMAC_STA_ID), + GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR), + umac_sta->mac_addr); + + sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)]; + + if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN)) + sta->valid = 0; + + break; + case UMAC_OPCODE_CLEAR_ALL: + for (i = 0; i < IWM_STA_TABLE_NUM; i++) + iwm->sta_table[i].valid = 0; + + break; + default: + break; + } + + return 0; +} + +static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_mgmt *mgmt; + struct iwm_umac_notif_bss_info *umac_bss = + (struct iwm_umac_notif_bss_info *)buf; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + struct iwm_bss_info *bss, *next; + s32 signal; + int freq; + u16 frame_len = le16_to_cpu(umac_bss->frame_len); + size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len; + + mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); + + IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid); + IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type)); + IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n", + le32_to_cpu(umac_bss->timestamp)); + IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n", + le16_to_cpu(umac_bss->table_idx)); + IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band); + IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel); + IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); + IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); + + list_for_each_entry_safe(bss, next, &iwm->bss_list, node) + if (bss->bss->table_idx == umac_bss->table_idx) + break; + + if (&bss->node != &iwm->bss_list) { + /* Remove the old BSS entry, we will add it back later. */ + list_del(&bss->node); + kfree(bss->bss); + } else { + /* New BSS entry */ + + bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL); + if (!bss) { + IWM_ERR(iwm, "Couldn't allocate bss_info\n"); + return -ENOMEM; + } + } + + bss->bss = kzalloc(bss_len, GFP_KERNEL); + if (!bss) { + kfree(bss); + IWM_ERR(iwm, "Couldn't allocate bss\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&bss->node); + memcpy(bss->bss, umac_bss, bss_len); + + if (umac_bss->band == UMAC_BAND_2GHZ) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else if (umac_bss->band == UMAC_BAND_5GHZ) + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + else { + IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); + goto err; + } + + freq = ieee80211_channel_to_frequency(umac_bss->channel); + channel = ieee80211_get_channel(wiphy, freq); + signal = umac_bss->rssi * 100; + + bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel, + mgmt, frame_len, + signal, GFP_KERNEL); + if (!bss->cfg_bss) + goto err; + + list_add_tail(&bss->node, &iwm->bss_list); + + return 0; + err: + kfree(bss->bss); + kfree(bss); + + return -EINVAL; +} + +static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_bss_removed *bss_rm = + (struct iwm_umac_notif_bss_removed *)buf; + struct iwm_bss_info *bss, *next; + u16 table_idx; + int i; + + for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { + table_idx = (le16_to_cpu(bss_rm->entries[i]) + & IWM_BSS_REMOVE_INDEX_MSK); + list_for_each_entry_safe(bss, next, &iwm->bss_list, node) + if (bss->bss->table_idx == cpu_to_le16(table_idx)) { + struct ieee80211_mgmt *mgmt; + + mgmt = (struct ieee80211_mgmt *) + (bss->bss->frame_buf); + IWM_DBG_MLME(iwm, ERR, + "BSS removed: %pM\n", + mgmt->bssid); + list_del(&bss->node); + kfree(bss->bss); + kfree(bss); + } + } + + return 0; +} + +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 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; + } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { + ie = mgt->u.reassoc_req.variable;; + event = IWEVASSOCREQIE; + } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { + ie = mgt->u.assoc_resp.variable;; + event = IWEVASSOCRESPIE; + } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { + ie = mgt->u.reassoc_resp.variable;; + event = IWEVASSOCRESPIE; + } 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; +} + +static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_wifi_if *notif = + (struct iwm_umac_notif_wifi_if *)buf; + + switch (notif->status) { + case WIFI_IF_NTFY_ASSOC_START: + return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_ASSOC_COMPLETE: + return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: + return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_CONNECTION_TERMINATED: + IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); + break; + case WIFI_IF_NTFY_SCAN_COMPLETE: + return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_STA_TABLE_CHANGE: + return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: + IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); + break; + case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: + return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); + case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: + return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd); + break; + case WIFI_IF_NTFY_MGMT_FRAME: + return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd); + case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START: + case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE: + case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START: + case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT: + case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START: + case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE: + case WIFI_DBG_IF_NTFY_CNCT_ATC_START: + case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION: + case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP: + case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP: + IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n", + notif->status); + break; + default: + IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status); + break; + } + + return 0; +} + +#define IWM_STATS_UPDATE_INTERVAL (2 * HZ) + +static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf; + struct iw_statistics *wstats = &iwm->wstats; + u16 max_rate = 0; + int i; + + IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n"); + + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) { + max_rate = max_t(u16, max_rate, + max(le16_to_cpu(stats->tx_rate[i]), + le16_to_cpu(stats->rx_rate[i]))); + } + /* UMAC passes rate info multiplies by 2 */ + iwm->rate = max_rate >> 1; + } + + wstats->status = 0; + + wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid); + wstats->discard.code = le32_to_cpu(stats->rx_drop_decode); + wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly); + wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry); + + wstats->miss.beacon = le32_to_cpu(stats->missed_beacons); + + /* according to cfg80211 */ + if (stats->rssi_dbm < -110) + wstats->qual.qual = 0; + else if (stats->rssi_dbm > -40) + wstats->qual.qual = 70; + else + wstats->qual.qual = stats->rssi_dbm + 110; + + wstats->qual.level = stats->rssi_dbm; + wstats->qual.noise = stats->noise_dbm; + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; + + schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL); + + mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD)); + + return 0; +} + +static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy = + (struct iwm_umac_cmd_eeprom_proxy *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr; + u32 hdr_offset = le32_to_cpu(hdr->offset); + u32 hdr_len = le32_to_cpu(hdr->len); + u32 hdr_type = le32_to_cpu(hdr->type); + + IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n", + hdr_type, hdr_len, hdr_offset); + + 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); + break; + case IWM_UMAC_CMD_EEPROM_TYPE_WRITE: + default: + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_cmd_get_channel_list *ch_list = + (struct iwm_umac_cmd_get_channel_list *) + (buf + sizeof(struct iwm_umac_wifi_in_hdr)); + struct wiphy *wiphy = iwm_to_wiphy(iwm); + struct ieee80211_supported_band *band; + int i; + + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + + for (i = 0; i < band->n_channels; i++) { + unsigned long ch_mask_0 = + le32_to_cpu(ch_list->ch[0].channels_mask); + unsigned long ch_mask_2 = + le32_to_cpu(ch_list->ch[2].channels_mask); + + if (!test_bit(i, &ch_mask_0)) + band->channels[i].flags |= IEEE80211_CHAN_DISABLED; + + if (!test_bit(i, &ch_mask_2)) + band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS; + } + + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + + for (i = 0; i < min(band->n_channels, 32); i++) { + unsigned long ch_mask_1 = + le32_to_cpu(ch_list->ch[1].channels_mask); + unsigned long ch_mask_3 = + le32_to_cpu(ch_list->ch[3].channels_mask); + + if (!test_bit(i, &ch_mask_1)) + band->channels[i].flags |= IEEE80211_CHAN_DISABLED; + + if (!test_bit(i, &ch_mask_3)) + band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS; + } + + return 0; +} + +static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + struct iwm_umac_wifi_if *hdr = + (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); + + switch (hdr->oid) { + case UMAC_WIFI_IF_CMD_SET_PROFILE: + iwm->umac_profile_active = 1; + wake_up_interruptible(&iwm->mlme_queue); + break; + default: + break; + } + + return 0; +} + +static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, struct iwm_wifi_cmd *cmd) +{ + 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); + + IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n", + 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); + + return 0; +} + +static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size) +{ + struct iwm_umac_wifi_in_hdr *wifi_hdr; + struct iwm_wifi_cmd *cmd; + u8 source, cmd_id; + u16 seq_num; + u32 count; + u8 resp; + + wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; + cmd_id = wifi_hdr->sw_hdr.cmd.cmd; + + source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + if (source >= IWM_SRC_NUM) { + IWM_CRIT(iwm, "invalid source %d\n", source); + return -EINVAL; + } + + count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT)); + count += sizeof(struct iwm_umac_wifi_in_hdr) - + sizeof(struct iwm_dev_cmd_hdr); + if (count > buf_size) { + IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size); + return -EINVAL; + } + + resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS); + + seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); + + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", + cmd_id, source, seq_num); + + /* + * If this is a response to a previously sent command, there must + * be a pending command for this sequence number. + */ + cmd = iwm_get_pending_wifi_cmd(iwm, seq_num); + + /* Notify the caller only for sync commands. */ + switch (source) { + case UMAC_HDI_IN_SOURCE_FHRX: + if (iwm->lmac_handlers[cmd_id] && + test_bit(cmd_id, &iwm->lmac_handler_map[0])) + return iwm_notif_send(iwm, cmd, cmd_id, source, + buf, count); + break; + case UMAC_HDI_IN_SOURCE_FW: + if (iwm->umac_handlers[cmd_id] && + test_bit(cmd_id, &iwm->umac_handler_map[0])) + return iwm_notif_send(iwm, cmd, cmd_id, source, + buf, count); + break; + case UMAC_HDI_IN_SOURCE_UDMA: + break; + } + + return iwm_rx_handle_resp(iwm, buf, count, cmd); +} + +int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + u8 source, cmd_id; + struct iwm_umac_wifi_in_hdr *wifi_hdr; + int ret = 0; + + wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; + cmd_id = wifi_hdr->sw_hdr.cmd.cmd; + + source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); + + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source); + + switch (source) { + case UMAC_HDI_IN_SOURCE_FHRX: + if (iwm->lmac_handlers[cmd_id]) + ret = iwm->lmac_handlers[cmd_id] + (iwm, buf, buf_size, cmd); + break; + case UMAC_HDI_IN_SOURCE_FW: + if (iwm->umac_handlers[cmd_id]) + ret = iwm->umac_handlers[cmd_id] + (iwm, buf, buf_size, cmd); + break; + case UMAC_HDI_IN_SOURCE_UDMA: + ret = -EINVAL; + break; + } + + kfree(cmd); + + return ret; +} + +static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size) +{ + u8 seq_num; + struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; + struct iwm_nonwifi_cmd *cmd, *next; + + seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); + + /* + * We received a non wifi answer. + * Let's check if there's a pending command for it, and if so + * replace the command payload with the buffer, and then wake the + * callers up. + * That means we only support synchronised non wifi command response + * schemes. + */ + list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) + if (cmd->seq_num == seq_num) { + cmd->resp_received = 1; + cmd->buf.len = buf_size; + memcpy(cmd->buf.hdr, buf, buf_size); + wake_up_interruptible(&iwm->nonwifi_queue); + } + + return 0; +} + +static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size) +{ + int ret = 0; + u8 op_code; + unsigned long buf_offset = 0; + struct iwm_udma_in_hdr *hdr; + + /* + * To allow for a more efficient bus usage, UMAC + * messages are encapsulated into UDMA ones. This + * way we can have several UMAC messages in one bus + * transfer. + * A UDMA frame size is always aligned on 16 bytes, + * and a UDMA frame must not start with a UMAC_PAD_TERMINAL + * word. This is how we parse a bus frame into several + * UDMA ones. + */ + while (buf_offset < buf_size) { + + hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset); + + if (iwm_rx_check_udma_hdr(hdr) < 0) { + IWM_DBG_RX(iwm, DBG, "End of frame\n"); + break; + } + + op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE); + + IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code); + + if (op_code == UMAC_HDI_IN_OPCODE_WIFI) { + ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset, + buf_size - buf_offset); + } else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) { + if (GET_VAL32(hdr->cmd, + UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) != + UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) { + IWM_ERR(iwm, "Incorrect hw signature\n"); + return -EINVAL; + } + ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset, + buf_size - buf_offset); + } else { + IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code); + ret |= -EINVAL; + } + + buf_offset += iwm_rx_resp_size(hdr); + } + + return ret; +} + +int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size) +{ + struct iwm_udma_in_hdr *hdr; + + hdr = (struct iwm_udma_in_hdr *)buf; + + switch (le32_to_cpu(hdr->cmd)) { + case UMAC_REBOOT_BARKER: + return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, + IWM_SRC_UDMA, buf, buf_size); + case UMAC_ACK_BARKER: + return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION, + IWM_SRC_UDMA, NULL, 0); + default: + IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd); + return iwm_rx_handle_umac(iwm, buf, buf_size); + } + + return 0; +} + +static const iwm_handler iwm_umac_handlers[] = +{ + [UMAC_NOTIFY_OPCODE_ERROR] = iwm_ntf_error, + [UMAC_NOTIFY_OPCODE_ALIVE] = iwm_ntf_umac_alive, + [UMAC_NOTIFY_OPCODE_INIT_COMPLETE] = iwm_ntf_init_complete, + [UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS] = iwm_ntf_wifi_status, + [UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_mlme, + [UMAC_NOTIFY_OPCODE_PAGE_DEALLOC] = iwm_ntf_tx_credit_update, + [UMAC_NOTIFY_OPCODE_RX_TICKET] = iwm_ntf_rx_ticket, + [UMAC_CMD_OPCODE_RESET] = iwm_ntf_umac_reset, + [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, + [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, + [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, + [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, + [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, +}; + +static const iwm_handler iwm_lmac_handlers[] = +{ + [REPLY_TX] = iwm_ntf_tx, + [REPLY_ALIVE] = iwm_ntf_lmac_version, + [CALIBRATION_RES_NOTIFICATION] = iwm_ntf_calib_res, + [CALIBRATION_COMPLETE_NOTIFICATION] = iwm_ntf_calib_complete, + [CALIBRATION_CFG_CMD] = iwm_ntf_calib_cfg, + [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, + [CARD_STATE_NOTIFICATION] = iwm_ntf_card_state, +}; + +void iwm_rx_setup_handlers(struct iwm_priv *iwm) +{ + iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers; + iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers; +} + +static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len) +{ + struct ieee80211_hdr *hdr; + unsigned int hdr_len; + + hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_has_protected(hdr->frame_control)) + return; + + hdr_len = ieee80211_hdrlen(hdr->frame_control); + if (hdr_total_len <= hdr_len) + return; + + memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len); + skb_pull(skb, (hdr_total_len - hdr_len)); +} + +static void iwm_rx_adjust_packet(struct iwm_priv *iwm, + struct iwm_rx_packet *packet, + struct iwm_rx_ticket_node *ticket_node) +{ + u32 payload_offset = 0, payload_len; + struct iwm_rx_ticket *ticket = ticket_node->ticket; + struct iwm_rx_mpdu_hdr *mpdu_hdr; + struct ieee80211_hdr *hdr; + + mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data; + payload_offset += sizeof(struct iwm_rx_mpdu_hdr); + /* Padding is 0 or 2 bytes */ + payload_len = le16_to_cpu(mpdu_hdr->len) + + (le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK); + payload_len -= ticket->tail_len; + + IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, " + "ticket offset:%d ticket tail len:%d\n", + payload_len, payload_offset, ticket->payload_offset, + ticket->tail_len); + + IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len); + + skb_pull(packet->skb, payload_offset); + skb_trim(packet->skb, payload_len); + + iwm_remove_iv(packet->skb, ticket->payload_offset); + + hdr = (struct ieee80211_hdr *) packet->skb->data; + if (ieee80211_is_data_qos(hdr->frame_control)) { + /* UMAC handed QOS_DATA frame with 2 padding bytes appended + * to the qos_ctl field in IEEE 802.11 headers. */ + memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2, + packet->skb->data, + ieee80211_hdrlen(hdr->frame_control) - + IEEE80211_QOS_CTL_LEN); + hdr = (struct ieee80211_hdr *) skb_pull(packet->skb, + IEEE80211_QOS_CTL_LEN + 2); + hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); + } + + IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ", + packet->skb->data, packet->skb->len); +} + +static void classify8023(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + /* frame has qos control */ + skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK; + } else { + skb->priority = 0; + } +} + +static void iwm_rx_process_packet(struct iwm_priv *iwm, + struct iwm_rx_packet *packet, + struct iwm_rx_ticket_node *ticket_node) +{ + int ret; + struct sk_buff *skb = packet->skb; + struct wireless_dev *wdev = iwm_to_wdev(iwm); + struct net_device *ndev = iwm_to_ndev(iwm); + + IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id); + + switch (le16_to_cpu(ticket_node->ticket->action)) { + case IWM_RX_TICKET_RELEASE: + IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); + classify8023(skb); + iwm_rx_adjust_packet(iwm, packet, ticket_node); + ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); + if (ret < 0) { + IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " + "%d\n", ret); + break; + } + + IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); + + skb->dev = iwm_to_ndev(iwm); + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + memset(skb->cb, 0, sizeof(skb->cb)); + + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += skb->len; + + if (netif_rx(skb) == NET_RX_DROP) { + IWM_ERR(iwm, "Packet dropped\n"); + ndev->stats.rx_dropped++; + } + break; + case IWM_RX_TICKET_DROP: + IWM_DBG_RX(iwm, DBG, "DROP packet\n"); + kfree_skb(packet->skb); + break; + default: + IWM_ERR(iwm, "Unknow ticket action: %d\n", + le16_to_cpu(ticket_node->ticket->action)); + kfree_skb(packet->skb); + } + + kfree(packet); + iwm_rx_ticket_node_free(ticket_node); +} + +/* + * Rx data processing: + * + * We're receiving Rx packet from the LMAC, and Rx ticket from + * the UMAC. + * To forward a target data packet upstream (i.e. to the + * kernel network stack), we must have received an Rx ticket + * that tells us we're allowed to release this packet (ticket + * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates, + * among other things, where valid data actually starts in the Rx + * packet. + */ +void iwm_rx_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + struct iwm_rx_ticket_node *ticket, *next; + + iwm = container_of(work, struct iwm_priv, rx_worker); + + /* + * We go through the tickets list and if there is a pending + * packet for it, we push it upstream. + * We stop whenever a ticket is missing its packet, as we're + * supposed to send the packets in order. + */ + list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { + struct iwm_rx_packet *packet = + iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); + + if (!packet) { + IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " + "to be handled first\n", + le16_to_cpu(ticket->ticket->id)); + return; + } + + list_del(&ticket->node); + list_del(&packet->node); + iwm_rx_process_packet(iwm, packet, ticket); + } +} + diff --git a/drivers/net/wireless/iwmc3200wifi/rx.h b/drivers/net/wireless/iwmc3200wifi/rx.h new file mode 100644 index 000000000000..da0db91cee59 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/rx.h @@ -0,0 +1,60 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_RX_H__ +#define __IWM_RX_H__ + +#include + +#include "umac.h" + +struct iwm_rx_ticket_node { + struct list_head node; + struct iwm_rx_ticket *ticket; +}; + +struct iwm_rx_packet { + struct list_head node; + u16 id; + struct sk_buff *skb; + unsigned long pkt_size; +}; + +void iwm_rx_worker(struct work_struct *work); + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c new file mode 100644 index 000000000000..b54da677b371 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -0,0 +1,516 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +/* + * This is the SDIO bus specific hooks for iwm. + * It also is the module's entry point. + * + * Interesting code paths: + * iwm_sdio_probe() (Called by an SDIO bus scan) + * -> iwm_if_alloc() (netdev.c) + * -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy) + * -> wiphy_new() + * -> wiphy_register() + * -> alloc_netdev_mq() + * -> register_netdev() + * + * iwm_sdio_remove() + * -> iwm_if_free() (netdev.c) + * -> unregister_netdev() + * -> iwm_wdev_free() (cfg80211.c) + * -> wiphy_unregister() + * -> wiphy_free() + * + * iwm_sdio_isr() (called in process context from the SDIO core code) + * -> queue_work(.., isr_worker) + * -- [async] --> iwm_sdio_isr_worker() + * -> iwm_rx_handle() + */ + +#include +#include +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "bus.h" +#include "sdio.h" + +static void iwm_sdio_isr_worker(struct work_struct *work) +{ + struct iwm_sdio_priv *hw; + struct iwm_priv *iwm; + struct iwm_rx_info *rx_info; + struct sk_buff *skb; + u8 *rx_buf; + unsigned long rx_size; + + hw = container_of(work, struct iwm_sdio_priv, isr_worker); + iwm = hw_to_iwm(hw); + + while (!skb_queue_empty(&iwm->rx_list)) { + skb = skb_dequeue(&iwm->rx_list); + rx_info = skb_to_rx_info(skb); + rx_size = rx_info->rx_size; + rx_buf = skb->data; + + IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size); + if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0) + IWM_WARN(iwm, "RX error\n"); + + kfree_skb(skb); + } +} + +static void iwm_sdio_isr(struct sdio_func *func) +{ + struct iwm_priv *iwm; + struct iwm_sdio_priv *hw; + struct iwm_rx_info *rx_info; + struct sk_buff *skb; + unsigned long buf_size, read_size; + int ret; + u8 val; + + hw = sdio_get_drvdata(func); + iwm = hw_to_iwm(hw); + + buf_size = hw->blk_size; + + /* We're checking the status */ + val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret); + if (val == 0 || ret < 0) { + IWM_ERR(iwm, "Wrong INTR_STATUS\n"); + return; + } + + /* See if we have free buffers */ + if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) { + IWM_ERR(iwm, "No buffer for more Rx frames\n"); + return; + } + + /* We first read the transaction size */ + read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret); + read_size = read_size << 8; + + if (ret < 0) { + IWM_ERR(iwm, "Couldn't read the xfer size\n"); + return; + } + + /* We need to clear the INT register */ + sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't clear the INT register\n"); + return; + } + + while (buf_size < read_size) + buf_size <<= 1; + + skb = dev_alloc_skb(buf_size); + if (!skb) { + IWM_ERR(iwm, "Couldn't alloc RX skb\n"); + return; + } + rx_info = skb_to_rx_info(skb); + rx_info->rx_size = read_size; + rx_info->rx_buf_size = buf_size; + + /* Now we can read the actual buffer */ + ret = sdio_memcpy_fromio(func, skb_put(skb, read_size), + IWM_SDIO_DATA_ADDR, read_size); + + /* The skb is put on a driver's specific Rx SKB list */ + skb_queue_tail(&iwm->rx_list, skb); + + /* We can now schedule the actual worker */ + queue_work(hw->isr_wq, &hw->isr_worker); +} + +static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw) +{ + struct iwm_priv *iwm = hw_to_iwm(hw); + + flush_workqueue(hw->isr_wq); + + skb_queue_purge(&iwm->rx_list); +} + +/* Bus ops */ +static int if_sdio_enable(struct iwm_priv *iwm) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + int ret; + + sdio_claim_host(hw->func); + + ret = sdio_enable_func(hw->func); + if (ret) { + IWM_ERR(iwm, "Couldn't enable the device: is TOP driver " + "loaded and functional?\n"); + goto release_host; + } + + iwm_reset(iwm); + + ret = sdio_claim_irq(hw->func, iwm_sdio_isr); + if (ret) { + IWM_ERR(iwm, "Failed to claim irq: %d\n", ret); + goto release_host; + } + + sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret); + goto release_irq; + } + + sdio_release_host(hw->func); + + IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n"); + + return 0; + + release_irq: + sdio_release_irq(hw->func); + release_host: + sdio_release_host(hw->func); + + return ret; +} + +static int if_sdio_disable(struct iwm_priv *iwm) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + int ret; + + iwm_reset(iwm); + + sdio_claim_host(hw->func); + sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret); + if (ret < 0) + IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret); + + sdio_release_irq(hw->func); + sdio_disable_func(hw->func); + sdio_release_host(hw->func); + + iwm_sdio_rx_free(hw); + + IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n"); + + return 0; +} + +static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + int aligned_count = ALIGN(count, hw->blk_size); + int ret; + + if ((unsigned long)buf & 0x3) { + IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf); + /* TODO: Is this a hardware limitation? use get_unligned */ + return -EINVAL; + } + + sdio_claim_host(hw->func); + ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf, + aligned_count); + sdio_release_host(hw->func); + + return ret; +} + +/* debugfs hooks */ +static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct iwm_priv *iwm = filp->private_data; + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + char *buf; + u8 cccr; + int buf_len = 4096, ret; + size_t len = 0; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + sdio_claim_host(hw->func); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IOEx: 0x%x\n", cccr); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IORx: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IENx: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_INTx: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_IF: 0x%x\n", cccr); + + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_CAPS: 0x%x\n", cccr); + + cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret); + if (ret) { + IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n"); + goto err; + } + len += snprintf(buf + len, buf_len - len, "CCCR_CIS: 0x%x\n", cccr); + + ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); +err: + sdio_release_host(hw->func); + + kfree(buf); + + return ret; +} + +static const struct file_operations iwm_debugfs_sdio_fops = { + .owner = THIS_MODULE, + .open = iwm_debugfs_sdio_open, + .read = iwm_debugfs_sdio_read, +}; + +static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir) +{ + int result; + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + + hw->cccr_dentry = debugfs_create_file("cccr", 0200, + parent_dir, iwm, + &iwm_debugfs_sdio_fops); + result = PTR_ERR(hw->cccr_dentry); + if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result); + return result; + } + + return 0; +} + +static void if_sdio_debugfs_exit(struct iwm_priv *iwm) +{ + struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); + + debugfs_remove(hw->cccr_dentry); +} + +static struct iwm_if_ops if_sdio_ops = { + .enable = if_sdio_enable, + .disable = if_sdio_disable, + .send_chunk = if_sdio_send_chunk, + .debugfs_init = if_sdio_debugfs_init, + .debugfs_exit = if_sdio_debugfs_exit, + .umac_name = "iwmc3200wifi-umac-sdio.bin", + .calib_lmac_name = "iwmc3200wifi-calib-sdio.bin", + .lmac_name = "iwmc3200wifi-lmac-sdio.bin", +}; + +static int iwm_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + struct iwm_priv *iwm; + struct iwm_sdio_priv *hw; + struct device *dev = &func->dev; + int ret; + + /* check if TOP has already initialized the card */ + sdio_claim_host(func); + ret = sdio_enable_func(func); + if (ret) { + dev_err(dev, "wait for TOP to enable the device\n"); + sdio_release_host(func); + return ret; + } + + ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE); + + sdio_disable_func(func); + sdio_release_host(func); + + if (ret < 0) { + dev_err(dev, "Failed to set block size: %d\n", ret); + return ret; + } + + iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops); + if (IS_ERR(iwm)) { + dev_err(dev, "allocate SDIO interface failed\n"); + return PTR_ERR(iwm); + } + + hw = iwm_private(iwm); + hw->iwm = iwm; + + ret = iwm_debugfs_init(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Debugfs registration failed\n"); + goto if_free; + } + + sdio_set_drvdata(func, hw); + + hw->func = func; + hw->blk_size = IWM_SDIO_BLK_SIZE; + + hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio"); + if (!hw->isr_wq) { + ret = -ENOMEM; + goto debugfs_exit; + } + + INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker); + + dev_info(dev, "IWM SDIO probe\n"); + + return 0; + + debugfs_exit: + iwm_debugfs_exit(iwm); + if_free: + iwm_if_free(iwm); + return ret; +} + +static void iwm_sdio_remove(struct sdio_func *func) +{ + struct iwm_sdio_priv *hw = sdio_get_drvdata(func); + struct iwm_priv *iwm = hw_to_iwm(hw); + struct device *dev = &func->dev; + + iwm_debugfs_exit(iwm); + iwm_if_free(iwm); + destroy_workqueue(hw->isr_wq); + + sdio_set_drvdata(func, NULL); + + dev_info(dev, "IWM SDIO remove\n"); + + return; +} + +static const struct sdio_device_id iwm_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_IWM) }, + { /* end: all zeroes */ }, +}; +MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids); + +static struct sdio_driver iwm_sdio_driver = { + .name = "iwm_sdio", + .id_table = iwm_sdio_ids, + .probe = iwm_sdio_probe, + .remove = iwm_sdio_remove, +}; + +static int __init iwm_sdio_init_module(void) +{ + int ret; + + ret = sdio_register_driver(&iwm_sdio_driver); + + return ret; +} + +static void __exit iwm_sdio_exit_module(void) +{ + sdio_unregister_driver(&iwm_sdio_driver); +} + +module_init(iwm_sdio_init_module); +module_exit(iwm_sdio_exit_module); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR); diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h new file mode 100644 index 000000000000..b3c156b08dda --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/sdio.h @@ -0,0 +1,67 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#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 +#define IWM_SDIO_INTR_CLEAR_ADDR 0x13 +#define IWM_SDIO_INTR_GET_SIZE_ADDR 0x2C + +#define IWM_SDIO_BLK_SIZE 256 + +#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private) + +struct iwm_sdio_priv { + struct sdio_func *func; + struct iwm_priv *iwm; + + struct workqueue_struct *isr_wq; + struct work_struct isr_worker; + + struct dentry *cccr_dentry; + + unsigned int blk_size; +}; + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c new file mode 100644 index 000000000000..e3b4f7902daf --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/tx.c @@ -0,0 +1,492 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +/* + * iwm Tx theory of operation: + * + * 1) We receive a 802.3 frame from the stack + * 2) We convert it to a 802.11 frame [iwm_xmit_frame] + * 3) We queue it to its corresponding tx queue [iwm_xmit_frame] + * 4) We schedule the tx worker. There is one worker per tx + * queue. [iwm_xmit_frame] + * 5) The tx worker is scheduled + * 6) We go through every queued skb on the tx queue, and for each + * and every one of them: [iwm_tx_worker] + * a) We check if we have enough Tx credits (see below for a Tx + * credits description) for the frame length. [iwm_tx_worker] + * b) If we do, we aggregate the Tx frame into a UDMA one, by + * concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker] + * c) When we run out of credits, or when we reach the maximum + * concatenation size, we actually send the concatenated UDMA + * frame. [iwm_tx_worker] + * + * When we run out of Tx credits, the skbs are filling the tx queue, + * and eventually we will stop the netdev queue. [iwm_tx_worker] + * The tx queue is emptied as we're getting new tx credits, by + * scheduling the tx_worker. [iwm_tx_credit_inc] + * The netdev queue is started again when we have enough tx credits, + * and when our tx queue has some reasonable amout of space available + * (i.e. half of the max size). [iwm_tx_worker] + */ + +#include +#include +#include + +#include "iwm.h" +#include "debug.h" +#include "commands.h" +#include "hal.h" +#include "umac.h" +#include "bus.h" + +#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff + +#define BYTES_TO_PAGES(n) (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \ + (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0)) + +#define pool_id_to_queue(id) ((id < IWM_TX_CMD_QUEUE) ? id : id - 1) +#define queue_to_pool_id(q) ((q < IWM_TX_CMD_QUEUE) ? q : q + 1) + +/* require to hold tx_credit lock */ +static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id) +{ + struct pool_entry *pool = &tx_credit->pools[id]; + struct spool_entry *spool = &tx_credit->spools[pool->sid]; + int spool_pages; + + /* number of pages can be taken from spool by this pool */ + spool_pages = spool->max_pages - spool->alloc_pages + + max(pool->min_pages - pool->alloc_pages, 0); + + return min(pool->max_pages - pool->alloc_pages, spool_pages); +} + +static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb) +{ + u32 npages = BYTES_TO_PAGES(nb); + + if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id)) + return 1; + + set_bit(id, &iwm->tx_credit.full_pools_map); + + IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n", + pool_id_to_queue(id), + iwm_tx_credit_get(&iwm->tx_credit, id)); + + return 0; +} + +void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages) +{ + struct pool_entry *pool; + struct spool_entry *spool; + int freed_pages; + int queue; + + BUG_ON(id >= IWM_MACS_OUT_GROUPS); + + pool = &iwm->tx_credit.pools[id]; + spool = &iwm->tx_credit.spools[pool->sid]; + + freed_pages = total_freed_pages - pool->total_freed_pages; + IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id); + + if (!freed_pages) { + IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n"); + return; + } else if (freed_pages < 0) + freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1; + + if (pool->alloc_pages > pool->min_pages) { + int spool_pages = pool->alloc_pages - pool->min_pages; + spool_pages = min(spool_pages, freed_pages); + spool->alloc_pages -= spool_pages; + } + + pool->alloc_pages -= freed_pages; + pool->total_freed_pages = total_freed_pages; + + IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, " + "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages, + pool->total_freed_pages, pool->sid, spool->alloc_pages); + + if (test_bit(id, &iwm->tx_credit.full_pools_map) && + (pool->alloc_pages < pool->max_pages / 2)) { + clear_bit(id, &iwm->tx_credit.full_pools_map); + + queue = pool_id_to_queue(id); + + IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available " + "credit: %d\n", queue, + iwm_tx_credit_get(&iwm->tx_credit, id)); + queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); + } +} + +static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages) +{ + struct pool_entry *pool; + struct spool_entry *spool; + int spool_pages; + + IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n", + alloc_pages, id); + + BUG_ON(id >= IWM_MACS_OUT_GROUPS); + + pool = &iwm->tx_credit.pools[id]; + spool = &iwm->tx_credit.spools[pool->sid]; + + spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages; + + if (pool->alloc_pages >= pool->min_pages) + spool->alloc_pages += alloc_pages; + else if (spool_pages > 0) + spool->alloc_pages += spool_pages; + + pool->alloc_pages += alloc_pages; + + IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, " + "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages, + pool->total_freed_pages, pool->sid, spool->alloc_pages); +} + +int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb) +{ + u32 npages = BYTES_TO_PAGES(nb); + int ret = 0; + + spin_lock(&iwm->tx_credit.lock); + + if (!iwm_tx_credit_ok(iwm, id, nb)) { + IWM_DBG_TX(iwm, DBG, "No credit avaliable for pool[%d]\n", id); + ret = -ENOSPC; + goto out; + } + + iwm_tx_credit_dec(iwm, id, npages); + + out: + spin_unlock(&iwm->tx_credit.lock); + return ret; +} + +/* + * Since we're on an SDIO or USB bus, we are not sharing memory + * for storing to be transmitted frames. The host needs to push + * them upstream. As a consequence there needs to be a way for + * the target to let us know if it can actually take more TX frames + * or not. This is what Tx credits are for. + * + * For each Tx HW queue, we have a Tx pool, and then we have one + * unique super pool (spool), which is actually a global pool of + * all the UMAC pages. + * For each Tx pool we have a min_pages, a max_pages fields, and a + * alloc_pages fields. The alloc_pages tracks the number of pages + * currently allocated from the tx pool. + * Here are the rules to check if given a tx frame we have enough + * tx credits for it: + * 1) We translate the frame length into a number of UMAC pages. + * Let's call them n_pages. + * 2) For the corresponding tx pool, we check if n_pages + + * pool->alloc_pages is higher than pool->min_pages. min_pages + * represent a set of pre-allocated pages on the tx pool. If + * that's the case, then we need to allocate those pages from + * the spool. We can do so until we reach spool->max_pages. + * 3) Each tx pool is not allowed to allocate more than pool->max_pages + * from the spool, so once we're over min_pages, we can allocate + * pages from the spool, but not more than max_pages. + * + * When the tx code path needs to send a tx frame, it checks first + * if it has enough tx credits, following those rules. [iwm_tx_credit_get] + * If it does, it then updates the pool and spool counters and + * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec] + * On the other side, when the UMAC is done transmitting frames, it + * will send a credit update notification to the host. This is when + * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc, + * called from rx.c:iwm_ntf_tx_credit_update] + * + */ +void iwm_tx_credit_init_pools(struct iwm_priv *iwm, + struct iwm_umac_notif_alive *alive) +{ + int i, sid, pool_pages; + + spin_lock(&iwm->tx_credit.lock); + + iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count); + iwm->tx_credit.full_pools_map = 0; + memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry)); + + IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr); + + for (i = 0; i < iwm->tx_credit.pool_nr; i++) { + __le32 page_grp_state = alive->page_grp_state[i]; + + iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_GRP_NUM); + iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_SGRP_NUM); + iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE); + iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE); + iwm->tx_credit.pools[i].alloc_pages = 0; + iwm->tx_credit.pools[i].total_freed_pages = 0; + + sid = iwm->tx_credit.pools[i].sid; + pool_pages = iwm->tx_credit.pools[i].min_pages; + + if (iwm->tx_credit.spools[sid].max_pages == 0) { + iwm->tx_credit.spools[sid].id = sid; + iwm->tx_credit.spools[sid].max_pages = + GET_VAL32(page_grp_state, + UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE); + iwm->tx_credit.spools[sid].alloc_pages = 0; + } + + iwm->tx_credit.spools[sid].alloc_pages += pool_pages; + + IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity " + "min: %d, max: %d, pool alloc: %d, total_free: %d, " + "super poll alloc: %d\n", + i, iwm->tx_credit.pools[i].id, + iwm->tx_credit.pools[i].sid, + iwm->tx_credit.pools[i].min_pages, + iwm->tx_credit.pools[i].max_pages, + iwm->tx_credit.pools[i].alloc_pages, + iwm->tx_credit.pools[i].total_freed_pages, + iwm->tx_credit.spools[sid].alloc_pages); + } + + spin_unlock(&iwm->tx_credit.lock); +} + +#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr) + +static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, + int pool_id, u8 *buf) +{ + struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf; + struct iwm_udma_wifi_cmd udma_cmd; + struct iwm_umac_cmd umac_cmd; + struct iwm_tx_info *tx_info = skb_to_tx_info(skb); + + udma_cmd.count = cpu_to_le16(skb->len + + sizeof(struct iwm_umac_fw_cmd_hdr)); + /* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be + * called later to set EOP for the last packet. */ + udma_cmd.eop = 0; + udma_cmd.credit_group = pool_id; + udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; + udma_cmd.lmac_offset = 0; + + umac_cmd.id = REPLY_TX; + umac_cmd.count = cpu_to_le16(skb->len); + umac_cmd.color = tx_info->color; + umac_cmd.resp = 0; + umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm)); + + iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd); + iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd); + + memcpy(buf + sizeof(*hdr), skb->data, skb->len); + + return 0; +} + +static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, + struct iwm_tx_queue *txq) +{ + int ret; + + if (!txq->concat_count) + return 0; + + IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n", + txq->id, txq->concat_count); + + /* mark EOP for the last packet */ + iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); + + ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); + + txq->concat_count = 0; + txq->concat_ptr = txq->concat_buf; + + return ret; +} + +#define CONFIG_IWM_TX_CONCATENATED 1 + +void iwm_tx_worker(struct work_struct *work) +{ + struct iwm_priv *iwm; + struct iwm_tx_info *tx_info = NULL; + struct sk_buff *skb; + int cmdlen, ret; + struct iwm_tx_queue *txq; + int pool_id; + + txq = container_of(work, struct iwm_tx_queue, worker); + iwm = container_of(txq, struct iwm_priv, txq[txq->id]); + + pool_id = queue_to_pool_id(txq->id); + + while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) && + !skb_queue_empty(&txq->queue)) { + + skb = skb_dequeue(&txq->queue); + tx_info = skb_to_tx_info(skb); + cmdlen = IWM_UDMA_HDR_LEN + skb->len; + + IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: " + "%d, color: %d\n", txq->id, skb, tx_info->sta, + tx_info->color); + +#if !CONFIG_IWM_TX_CONCATENATED + /* temporarily keep this to comparing the performance */ + ret = iwm_send_packet(iwm, skb, pool_id); +#else + + if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE) + iwm_tx_send_concat_packets(iwm, txq); + + ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen); + if (ret) { + IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue " + "%d, Tx worker stopped\n", txq->id); + skb_queue_head(&txq->queue, skb); + break; + } + + txq->concat_ptr = txq->concat_buf + txq->concat_count; + iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr); + txq->concat_count += ALIGN(cmdlen, 16); +#endif + kfree_skb(skb); + } + + iwm_tx_send_concat_packets(iwm, txq); + + if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) && + !test_bit(pool_id, &iwm->tx_credit.full_pools_map) && + (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) { + IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id); + netif_wake_subqueue(iwm_to_ndev(iwm), txq->id); + } +} + +int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct iwm_priv *iwm = ndev_to_iwm(netdev); + struct net_device *ndev = iwm_to_ndev(iwm); + struct wireless_dev *wdev = iwm_to_wdev(iwm); + u8 *dst_addr; + struct iwm_tx_info *tx_info; + struct iwm_tx_queue *txq; + struct iwm_sta_info *sta_info; + u8 sta_id; + u16 queue; + int ret; + + if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: " + "not associated\n"); + netif_tx_stop_all_queues(netdev); + goto drop; + } + + queue = skb_get_queue_mapping(skb); + BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */ + + txq = &iwm->txq[queue]; + + /* No free space for Tx, tx_worker is too slow */ + if (skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) { + IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue); + netif_stop_subqueue(netdev, queue); + return NETDEV_TX_BUSY; + } + + ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype, + iwm->bssid, 0); + if (ret) { + IWM_ERR(iwm, "build wifi header failed\n"); + goto drop; + } + + dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1; + + for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) { + sta_info = &iwm->sta_table[sta_id]; + if (sta_info->valid && + !memcmp(dst_addr, sta_info->addr, ETH_ALEN)) + break; + } + + if (sta_id == IWM_STA_TABLE_NUM) { + IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n", + dst_addr); + goto drop; + } + + tx_info = skb_to_tx_info(skb); + tx_info->sta = sta_id; + tx_info->color = sta_info->color; + /* UMAC uses TID 8 (vs. 0) for non QoS packets */ + if (sta_info->qos) + tx_info->tid = skb->priority; + else + tx_info->tid = IWM_UMAC_MGMT_TID; + + skb_queue_tail(&iwm->txq[queue].queue, skb); + + queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); + + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + return NETDEV_TX_OK; + + drop: + ndev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h new file mode 100644 index 000000000000..4a95cce1f0a6 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/umac.h @@ -0,0 +1,744 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + */ + +#ifndef __IWM_UMAC_H__ +#define __IWM_UMAC_H__ + +struct iwm_udma_in_hdr { + __le32 cmd; + __le32 size; +} __attribute__ ((packed)); + +struct iwm_udma_out_nonwifi_hdr { + __le32 cmd; + __le32 addr; + __le32 op1_sz; + __le32 op2; +} __attribute__ ((packed)); + +struct iwm_udma_out_wifi_hdr { + __le32 cmd; + __le32 meta_data; +} __attribute__ ((packed)); + +/* Sequence numbering */ +#define UMAC_WIFI_SEQ_NUM_BASE 1 +#define UMAC_WIFI_SEQ_NUM_MAX 0x4000 +#define UMAC_NONWIFI_SEQ_NUM_BASE 1 +#define UMAC_NONWIFI_SEQ_NUM_MAX 0x10 + +/* MAC address address */ +#define WICO_MAC_ADDRESS_ADDR 0x604008F8 + +/* RA / TID */ +#define UMAC_HDI_ACT_TBL_IDX_TID_POS 0 +#define UMAC_HDI_ACT_TBL_IDX_TID_SEED 0xF + +#define UMAC_HDI_ACT_TBL_IDX_RA_POS 4 +#define UMAC_HDI_ACT_TBL_IDX_RA_SEED 0xF + +#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC 0xF +#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC 0x9 +#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC 0xA + +#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \ + ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ + (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) +#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \ + ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ + (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) + +/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */ +#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0 +#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF + +/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */ +#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS 4 +#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED 0xF + +/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */ +#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS 8 +#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED 0xFF + +/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */ +#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS 16 +#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED 0xFF + +/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */ +#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS 24 +#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED 0xFF + +/* Barkers */ +#define UMAC_REBOOT_BARKER 0xdeadbeef +#define UMAC_ACK_BARKER 0xfeedbabe +#define UMAC_PAD_TERMINAL 0xadadadad + +/* UMAC JMP address */ +#define UMAC_MU_FW_INST_DATA_12_ADDR 0xBF0000 + +/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */ +#define UMAC_HDI_OUT_CMD_OPCODE_POS 0 +#define UMAC_HDI_OUT_CMD_OPCODE_SEED 0xF + +/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */ +#define UMAC_HDI_OUT_CMD_EOT_POS 10 +#define UMAC_HDI_OUT_CMD_EOT_SEED 0x1 + +/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */ +#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS 11 +#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED 0x1 + +/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */ +#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS 12 +#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF + +/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */ +#define UMAC_HDI_OUT_CMD_SIGNATURE_POS 16 +#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED 0xFFFF + +/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */ +#define UMAC_HDI_OUT_BYTE_COUNT_POS 0 +#define UMAC_HDI_OUT_BYTE_COUNT_SEED 0xFFF + +/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */ +#define UMAC_HDI_OUT_CREDIT_GRP_POS 12 +#define UMAC_HDI_OUT_CREDIT_GRP_SEED 0xF + +/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */ +#define UMAC_HDI_OUT_RATID_POS 16 +#define UMAC_HDI_OUT_RATID_SEED 0xFF + +/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */ +#define UMAC_HDI_OUT_LMAC_OFFSET_POS 24 +#define UMAC_HDI_OUT_LMAC_OFFSET_SEED 0xFF + +/* Signature */ +#define UMAC_HDI_OUT_SIGNATURE 0xCBBC + +/* buffer alignment */ +#define UMAC_HDI_BUF_ALIGN_MSK 0xF + +/* iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */ +#define UMAC_HDI_IN_CMD_OPCODE_POS 0 +#define UMAC_HDI_IN_CMD_OPCODE_SEED 0xF + +/* iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */ +#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS 4 +#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED 0x7 + +/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */ +#define UMAC_HDI_IN_CMD_SOURCE_POS 4 +#define UMAC_HDI_IN_CMD_SOURCE_SEED 0x3 + +/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */ +#define UMAC_HDI_IN_CMD_EOT_POS 6 +#define UMAC_HDI_IN_CMD_EOT_SEED 0x1 + +/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */ +#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS 7 +#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED 0x1 + +/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */ +#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS 8 +#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED 0x1 + +/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */ +#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS 9 +#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED 0x7FFFFF + +/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */ +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS 12 +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF + +/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */ +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS 16 +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED 0xFFFF + +/* Fixed Non-WiFi signature */ +#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG 0xCBBC + +/* IN NTFY op-codes */ +#define UMAC_NOTIFY_OPCODE_ALIVE 0xA1 +#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE 0xA2 +#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS 0xA3 +#define UMAC_NOTIFY_OPCODE_ERROR 0xA4 +#define UMAC_NOTIFY_OPCODE_DEBUG 0xA5 +#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER 0xB0 +#define UMAC_NOTIFY_OPCODE_STATS 0xB1 +#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC 0xB3 +#define UMAC_NOTIFY_OPCODE_RX_TICKET 0xB4 +#define UMAC_NOTIFY_OPCODE_MAX (UMAC_NOTIFY_OPCODE_RX_TICKET -\ + UMAC_NOTIFY_OPCODE_ALIVE + 1) +#define UMAC_NOTIFY_OPCODE_FIRST (UMAC_NOTIFY_OPCODE_ALIVE) + +/* HDI OUT OP CODE */ +#define UMAC_HDI_OUT_OPCODE_PING 0x0 +#define UMAC_HDI_OUT_OPCODE_READ 0x1 +#define UMAC_HDI_OUT_OPCODE_WRITE 0x2 +#define UMAC_HDI_OUT_OPCODE_JUMP 0x3 +#define UMAC_HDI_OUT_OPCODE_REBOOT 0x4 +#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT 0x5 +#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT 0x6 +#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE 0x7 +/* #define UMAC_HDI_OUT_OPCODE_RESERVED 0x8..0xA */ +#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG 0xB +#define UMAC_HDI_OUT_OPCODE_WIFI 0xF + +/* HDI IN OP CODE -- Non WiFi*/ +#define UMAC_HDI_IN_OPCODE_PING 0x0 +#define UMAC_HDI_IN_OPCODE_READ 0x1 +#define UMAC_HDI_IN_OPCODE_WRITE 0x2 +#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT 0x5 +#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT 0x6 +#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE 0x7 +#define UMAC_HDI_IN_OPCODE_EP_MGMT 0x8 +#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE 0x9 +#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE 0xA +#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG 0xB +#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \ + (UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1) +#define UMAC_HDI_IN_OPCODE_WIFI 0xF + +/* HDI IN SOURCE */ +#define UMAC_HDI_IN_SOURCE_FHRX 0x0 +#define UMAC_HDI_IN_SOURCE_UDMA 0x1 +#define UMAC_HDI_IN_SOURCE_FW 0x2 +#define UMAC_HDI_IN_SOURCE_RESERVED 0x3 + +/* OUT CMD op-codes */ +#define UMAC_CMD_OPCODE_ECHO 0x01 +#define UMAC_CMD_OPCODE_HALT 0x02 +#define UMAC_CMD_OPCODE_RESET 0x03 +#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT 0x09 +#define UMAC_CMD_OPCODE_URB_CANCEL_ACK 0x0A +#define UMAC_CMD_OPCODE_DCACHE_FLUSH 0x0B +#define UMAC_CMD_OPCODE_EEPROM_PROXY 0x0C +#define UMAC_CMD_OPCODE_TX_ECHO 0x0D +#define UMAC_CMD_OPCODE_DBG_MON 0x0E +#define UMAC_CMD_OPCODE_INTERNAL_TX 0x0F +#define UMAC_CMD_OPCODE_SET_PARAM_FIX 0x10 +#define UMAC_CMD_OPCODE_SET_PARAM_VAR 0x11 +#define UMAC_CMD_OPCODE_GET_PARAM 0x12 +#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER 0x13 +#define UMAC_CMD_OPCODE_TARGET 0x14 +#define UMAC_CMD_OPCODE_STATISTIC_REQUEST 0x15 +#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16 +#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17 +#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18 +#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA +#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB +#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC +#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER 0xFD +#define UMAC_CMD_OPCODE_WIFI_WRAPPER 0xFE +#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH 0xFF + +/* UMAC WiFi interface op-codes */ +#define UMAC_WIFI_IF_CMD_SET_PROFILE 0x11 +#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE 0x12 +#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST 0x13 +#define UMAC_WIFI_IF_CMD_SCAN_REQUEST 0x14 +#define UMAC_WIFI_IF_CMD_SCAN_CONFIG 0x15 +#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY 0x16 +#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY 0x17 +#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY 0x18 +#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY 0x19 +#define UMAC_WIFI_IF_CMD_REMOVE_KEY 0x1A +#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B +#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C +#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E +#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20 + +/* UMAC WiFi interface ports */ +#define UMAC_WIFI_IF_FLG_PORT_DEF 0x00 +#define UMAC_WIFI_IF_FLG_PORT_PAN 0x01 +#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID WIFI_IF_FLG_PORT_DEF + +/* UMAC WiFi interface actions */ +#define UMAC_WIFI_IF_FLG_ACT_GET 0x10 +#define UMAC_WIFI_IF_FLG_ACT_SET 0x20 + +/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */ +#define UMAC_FW_CMD_BYTE_COUNT_POS 0 +#define UMAC_FW_CMD_BYTE_COUNT_SEED 0xFFF + +/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */ +#define UMAC_FW_CMD_STATUS_POS 12 +#define UMAC_FW_CMD_STATUS_SEED 0xF + +/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */ +#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS 16 +#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED 0x1 + +/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */ +#define UMAC_FW_CMD_TX_FW_CMD_POS 17 +#define UMAC_FW_CMD_TX_FW_CMD_SEED 0x1 + +/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */ +#define UMAC_FW_CMD_TX_PLAINTEXT_POS 18 +#define UMAC_FW_CMD_TX_PLAINTEXT_SEED 0x1 + +/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */ +#define UMAC_FW_CMD_TX_STA_COLOR_POS 20 +#define UMAC_FW_CMD_TX_STA_COLOR_SEED 0x7 + +/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */ +#define UMAC_FW_CMD_TX_LIFETIME_TU_POS 24 +#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED 0xFF + +/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */ +#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS 5 +#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED 0x1 + +/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */ +#define UMAC_DEV_CMD_FLAGS_ABORT_POS 6 +#define UMAC_DEV_CMD_FLAGS_ABORT_SEED 0x1 + +/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */ +#define DEV_CMD_FLAGS_FLD_INTERNAL_POS 7 +#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED 0x1 + +/* Rx */ +/* Rx actions */ +#define IWM_RX_TICKET_DROP 0x0 +#define IWM_RX_TICKET_RELEASE 0x1 +#define IWM_RX_TICKET_SNIFFER 0x2 +#define IWM_RX_TICKET_ENQUEUE 0x3 + +/* Rx flags */ +#define IWM_RX_TICKET_PAD_SIZE_MSK 0x2 +#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4 +#define IWM_RX_TICKET_AMSDU_MSK 0x8 +#define IWM_RX_TICKET_DROP_REASON_POS 4 +#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS) + +#define IWM_RX_DROP_NO_DROP 0x0 +#define IWM_RX_DROP_BAD_CRC 0x1 +/* L2P no address match */ +#define IWM_RX_DROP_LMAC_ADDR_FILTER 0x2 +/* Multicast address not in list */ +#define IWM_RX_DROP_MCAST_ADDR_FILTER 0x3 +/* Control frames are not sent to the driver */ +#define IWM_RX_DROP_CTL_FRAME 0x4 +/* Our frame is back */ +#define IWM_RX_DROP_OUR_TX 0x5 +/* Association class filtering */ +#define IWM_RX_DROP_CLASS_FILTER 0x6 +/* Duplicated frame */ +#define IWM_RX_DROP_DUPLICATE_FILTER 0x7 +/* Decryption error */ +#define IWM_RX_DROP_SEC_ERR 0x8 +/* Unencrypted frame while encryption is on */ +#define IWM_RX_DROP_SEC_NO_ENCRYPTION 0x9 +/* Replay check failure */ +#define IWM_RX_DROP_SEC_REPLAY_ERR 0xa +/* uCode and FW key color mismatch, check before replay */ +#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH 0xb +#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE 0xc +/* No fragmentations Db is found */ +#define IWM_RX_DROP_FRAG_NO_RESOURCE 0xd +/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */ +#define IWM_RX_DROP_FRAG_ERR 0xe +#define IWM_RX_DROP_FRAG_LOST 0xf +#define IWM_RX_DROP_FRAG_COMPLETE 0x10 +/* Should be handled by UMAC */ +#define IWM_RX_DROP_MANAGEMENT 0x11 +/* STA not found by UMAC */ +#define IWM_RX_DROP_NO_STATION 0x12 +/* NULL or QoS NULL */ +#define IWM_RX_DROP_NULL_DATA 0x13 +#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL 0x14 +#define IWM_RX_DROP_BA_REORDER_DUPLICATE 0x15 + +struct iwm_rx_ticket { + __le16 action; + __le16 id; + __le16 flags; + u8 payload_offset; /* includes: MAC header, pad, IV */ + u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */ +} __attribute__ ((packed)); + +struct iwm_rx_mpdu_hdr { + __le16 len; + __le16 reserved; +} __attribute__ ((packed)); + +/* UMAC SW WIFI API */ + +struct iwm_dev_cmd_hdr { + u8 cmd; + u8 flags; + __le16 seq_num; +} __attribute__ ((packed)); + +struct iwm_umac_fw_cmd_hdr { + __le32 meta_data; + struct iwm_dev_cmd_hdr cmd; +} __attribute__ ((packed)); + +struct iwm_umac_wifi_out_hdr { + struct iwm_udma_out_wifi_hdr hw_hdr; + struct iwm_umac_fw_cmd_hdr sw_hdr; +} __attribute__ ((packed)); + +struct iwm_umac_nonwifi_out_hdr { + struct iwm_udma_out_nonwifi_hdr hw_hdr; +} __attribute__ ((packed)); + +struct iwm_umac_wifi_in_hdr { + struct iwm_udma_in_hdr hw_hdr; + struct iwm_umac_fw_cmd_hdr sw_hdr; +} __attribute__ ((packed)); + +struct iwm_umac_nonwifi_in_hdr { + struct iwm_udma_in_hdr hw_hdr; + __le32 time_stamp; +} __attribute__ ((packed)); + +#define IWM_UMAC_PAGE_SIZE 0x200 + +/* Notify structures */ +struct iwm_fw_version { + u8 minor; + u8 major; + __le16 id; +}; + +struct iwm_fw_build { + u8 type; + u8 subtype; + u8 platform; + u8 opt; +}; + +struct iwm_fw_alive_hdr { + struct iwm_fw_version ver; + struct iwm_fw_build build; + __le32 os_build; + __le32 log_hdr_addr; + __le32 log_buf_addr; + __le32 sys_timer_addr; +}; + +#define WAIT_NOTIF_TIMEOUT (2 * HZ) +#define SCAN_COMPLETE_TIMEOUT (3 * HZ) + +#define UMAC_NTFY_ALIVE_STATUS_ERR 0xDEAD +#define UMAC_NTFY_ALIVE_STATUS_OK 0xCAFE + +#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR 0xDEAD +#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK 0xCAFE + +#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN 0x40 +#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN 0x80 + +#define IWM_MACS_OUT_GROUPS 6 +#define IWM_MACS_OUT_SGROUPS 1 + + +#define WIFI_IF_NTFY_ASSOC_START 0x80 +#define WIFI_IF_NTFY_ASSOC_COMPLETE 0x81 +#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE 0x82 +#define WIFI_IF_NTFY_CONNECTION_TERMINATED 0x83 +#define WIFI_IF_NTFY_SCAN_COMPLETE 0x84 +#define WIFI_IF_NTFY_STA_TABLE_CHANGE 0x85 +#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED 0x86 +#define WIFI_IF_NTFY_RADIO_PREEMPTION 0x87 +#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED 0x88 +#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED 0x89 +#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS 0x8A +#define WIFI_IF_NTFY_MGMT_FRAME 0x8B + +/* DEBUG INDICATIONS */ +#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START 0xE0 +#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE 0xE1 +#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START 0xE2 +#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT 0xE3 +#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START 0xE4 +#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE 0xE5 +#define WIFI_DBG_IF_NTFY_CNCT_ATC_START 0xE6 +#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION 0xE7 +#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8 +#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9 + +/* Notification structures */ +struct iwm_umac_notif_wifi_if { + struct iwm_umac_wifi_in_hdr hdr; + u8 status; + u8 flags; + __le16 buf_size; +} __attribute__ ((packed)); + +#define UMAC_ROAM_REASON_FIRST_SELECTION 0x1 +#define UMAC_ROAM_REASON_AP_DEAUTH 0x2 +#define UMAC_ROAM_REASON_AP_CONNECT_LOST 0x3 +#define UMAC_ROAM_REASON_RSSI 0x4 +#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM 0x5 +#define UMAC_ROAM_REASON_IBSS_COALESCING 0x6 + +struct iwm_umac_notif_assoc_start { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 roam_reason; + u8 bssid[ETH_ALEN]; + u8 reserved[2]; +} __attribute__ ((packed)); + +#define UMAC_ASSOC_COMPLETE_SUCCESS 0x0 +#define UMAC_ASSOC_COMPLETE_FAILURE 0x1 + +struct iwm_umac_notif_assoc_complete { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 status; + u8 bssid[ETH_ALEN]; + u8 band; + u8 channel; +} __attribute__ ((packed)); + +#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0 +#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1 +#define UMAC_PROFILE_INVALID_REQUEST 0x2 +#define UMAC_PROFILE_INVALID_RF_PREEMPTED 0x3 + +struct iwm_umac_notif_profile_invalidate { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 reason; +} __attribute__ ((packed)); + +#define UMAC_SCAN_RESULT_SUCCESS 0x0 +#define UMAC_SCAN_RESULT_ABORTED 0x1 +#define UMAC_SCAN_RESULT_REJECTED 0x2 +#define UMAC_SCAN_RESULT_FAILED 0x3 + +struct iwm_umac_notif_scan_complete { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 type; + __le32 result; + u8 seq_num; +} __attribute__ ((packed)); + +#define UMAC_OPCODE_ADD_MODIFY 0x0 +#define UMAC_OPCODE_REMOVE 0x1 +#define UMAC_OPCODE_CLEAR_ALL 0x2 + +#define UMAC_STA_FLAG_QOS 0x1 + +struct iwm_umac_notif_sta_info { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 opcode; + u8 mac_addr[ETH_ALEN]; + u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */ + u8 flags; +} __attribute__ ((packed)); + +#define UMAC_BAND_2GHZ 0 +#define UMAC_BAND_5GHZ 1 + +#define UMAC_CHANNEL_WIDTH_20MHZ 0 +#define UMAC_CHANNEL_WIDTH_40MHZ 1 + +struct iwm_umac_notif_bss_info { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 type; + __le32 timestamp; + __le16 table_idx; + __le16 frame_len; + u8 band; + u8 channel; + s8 rssi; + u8 reserved; + u8 frame_buf[1]; +} __attribute__ ((packed)); + +#define IWM_BSS_REMOVE_INDEX_MSK 0x0fff +#define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00 + +#define IWM_BSS_REMOVE_FLG_AGE 0x1000 +#define IWM_BSS_REMOVE_FLG_TIMEOUT 0x2000 +#define IWM_BSS_REMOVE_FLG_TABLE_FULL 0x4000 + +struct iwm_umac_notif_bss_removed { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le32 count; + __le16 entries[0]; +} __attribute__ ((packed)); + +struct iwm_umac_notif_mgt_frame { + struct iwm_umac_notif_wifi_if mlme_hdr; + __le16 len; + u8 frame[1]; +} __attribute__ ((packed)); + +struct iwm_umac_notif_alive { + struct iwm_umac_wifi_in_hdr hdr; + __le16 status; + __le16 reserved1; + struct iwm_fw_alive_hdr alive_data; + __le16 reserved2; + __le16 page_grp_count; + __le32 page_grp_state[IWM_MACS_OUT_GROUPS]; +} __attribute__ ((packed)); + +struct iwm_umac_notif_init_complete { + __le16 status; + __le16 reserved; +} __attribute__ ((packed)); + +/* error categories */ +enum { + UMAC_SYS_ERR_CAT_NONE = 0, + UMAC_SYS_ERR_CAT_BOOT, + UMAC_SYS_ERR_CAT_UMAC, + UMAC_SYS_ERR_CAT_UAXM, + UMAC_SYS_ERR_CAT_LMAC, + UMAC_SYS_ERR_CAT_MAX +}; + +struct iwm_fw_error_hdr { + __le32 category; + __le32 status; + __le32 pc; + __le32 blink1; + __le32 blink2; + __le32 ilink1; + __le32 ilink2; + __le32 data1; + __le32 data2; + __le32 line_num; + __le32 umac_status; + __le32 lmac_status; + __le32 sdio_status; +} __attribute__ ((packed)); + +struct iwm_umac_notif_error { + struct iwm_umac_wifi_in_hdr hdr; + struct iwm_fw_error_hdr err; +} __attribute__ ((packed)); + +#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0 +#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff +#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS 8 +#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED 0xffffff +#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS 0 +#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED 0xffffff +#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS 24 +#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED 0xf + +struct iwm_umac_notif_page_dealloc { + struct iwm_umac_wifi_in_hdr hdr; + __le32 changes; + __le32 grp_info[IWM_MACS_OUT_GROUPS]; +} __attribute__ ((packed)); + +struct iwm_umac_notif_wifi_status { + struct iwm_umac_wifi_in_hdr hdr; + __le16 status; + __le16 reserved; +} __attribute__ ((packed)); + +struct iwm_umac_notif_rx_ticket { + struct iwm_umac_wifi_in_hdr hdr; + u8 num_tickets; + u8 reserved[3]; + struct iwm_rx_ticket tickets[1]; +} __attribute__ ((packed)); + +/* Tx/Rx rates window (number of max of last update window per second) */ +#define UMAC_NTF_RATE_SAMPLE_NR 4 + +#define IWM_UMAC_MGMT_TID 8 +#define IWM_UMAC_TID_NR 8 + +struct iwm_umac_notif_stats { + struct iwm_umac_wifi_in_hdr hdr; + __le32 flags; + __le32 timestamp; + __le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */ + __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR]; + __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR]; + s32 rssi_dbm; + s32 noise_dbm; + __le32 supp_rates; + __le32 missed_beacons; + __le32 rx_beacons; + __le32 rx_dir_pkts; + __le32 rx_nondir_pkts; + __le32 rx_multicast; + __le32 rx_errors; + __le32 rx_drop_other_bssid; + __le32 rx_drop_decode; + __le32 rx_drop_reassembly; + __le32 rx_drop_bad_len; + __le32 rx_drop_overflow; + __le32 rx_drop_crc; + __le32 rx_drop_missed; + __le32 tx_dir_pkts; + __le32 tx_nondir_pkts; + __le32 tx_failure; + __le32 tx_errors; + __le32 tx_drop_max_retry; + __le32 tx_err_abort; + __le32 tx_err_carrier; + __le32 rx_bytes; + __le32 tx_bytes; + __le32 tx_power; + __le32 tx_max_power; + __le32 roam_threshold; + __le32 ap_assoc_nr; + __le32 scan_full; + __le32 scan_abort; + __le32 ap_nr; + __le32 roam_nr; + __le32 roam_missed_beacons; + __le32 roam_rssi; + __le32 roam_unassoc; + __le32 roam_deauth; + __le32 roam_ap_loadblance; +} __attribute__ ((packed)); + +/* WiFi interface wrapper header */ +struct iwm_umac_wifi_if { + u8 oid; + u8 flags; + __le16 buf_size; +} __attribute__ ((packed)); + +#define IWM_SEQ_NUM_HOST_MSK 0x0000 +#define IWM_SEQ_NUM_UMAC_MSK 0x4000 +#define IWM_SEQ_NUM_LMAC_MSK 0x8000 +#define IWM_SEQ_NUM_MSK 0xC000 + +#endif diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c new file mode 100644 index 000000000000..584c94d0f399 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -0,0 +1,723 @@ +/* + * Intel Wireless Multicomm 3200 WiFi driver + * + * Copyright (C) 2009 Intel Corporation + * Samuel Ortiz + * Zhu Yi + * + * 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 +#include +#include +#include +#include +#include +#include + +#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/11d.c b/drivers/net/wireless/libertas/11d.c index 4bc46a60ae2f..9a5408e7d94a 100644 --- a/drivers/net/wireless/libertas/11d.c +++ b/drivers/net/wireless/libertas/11d.c @@ -207,7 +207,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband); lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo, COUNTRY_CODE_LEN + 1 + - sizeof(struct ieeetypes_subbandset) * nr_subband); + sizeof(struct ieee_subbandset) * nr_subband); return 0; } @@ -302,11 +302,9 @@ static u8 lbs_region_chan_supported_11d(u8 region, u8 chan) * @param parsed_region_chan pointer to parsed_region_chan_11d * @return 0 */ -static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* - countryinfo, +static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo, u8 band, - struct parsed_region_chan_11d * - parsed_region_chan) + struct parsed_region_chan_11d *parsed_region_chan) { u8 nr_subband, nrchan; u8 lastchan, firstchan; @@ -331,7 +329,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30); if ((*(countryinfo->countrycode)) == 0 - || (countryinfo->len <= COUNTRY_CODE_LEN)) { + || (countryinfo->header.len <= COUNTRY_CODE_LEN)) { /* No region Info or Wrong region info: treat as No 11D info */ goto done; } @@ -349,8 +347,8 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* memcpy(parsed_region_chan->countrycode, countryinfo->countrycode, COUNTRY_CODE_LEN); - nr_subband = (countryinfo->len - COUNTRY_CODE_LEN) / - sizeof(struct ieeetypes_subbandset); + nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) / + sizeof(struct ieee_subbandset); for (j = 0, lastchan = 0; j < nr_subband; j++) { @@ -502,7 +500,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, { struct cmd_ds_802_11d_domain_info *pdomaininfo = &cmd->params.domaininfo; - struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain; + struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; u8 nr_subband = priv->domainreg.nr_subband; lbs_deb_enter(LBS_DEB_11D); @@ -524,16 +522,16 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, sizeof(domain->countrycode)); domain->header.len = - cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) + + cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) + sizeof(domain->countrycode)); if (nr_subband) { memcpy(domain->subband, priv->domainreg.subband, - nr_subband * sizeof(struct ieeetypes_subbandset)); + nr_subband * sizeof(struct ieee_subbandset)); cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + le16_to_cpu(domain->header.len) + - sizeof(struct mrvlietypesheader) + + sizeof(struct mrvl_ie_header) + S_DS_GEN); } else { cmd->size = @@ -556,7 +554,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) { struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp; - struct mrvlietypes_domainparamset *domain = &domaininfo->domain; + struct mrvl_ie_domain_param_set *domain = &domaininfo->domain; u16 action = le16_to_cpu(domaininfo->action); s16 ret = 0; u8 nr_subband = 0; @@ -567,7 +565,7 @@ int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) (int)le16_to_cpu(resp->size)); nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / - sizeof(struct ieeetypes_subbandset); + sizeof(struct ieee_subbandset); lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband); diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h index 4f4f47f0f878..fb75d3e321a0 100644 --- a/drivers/net/wireless/libertas/11d.h +++ b/drivers/net/wireless/libertas/11d.h @@ -20,35 +20,36 @@ struct cmd_ds_command; /** Data structure for Country IE*/ -struct ieeetypes_subbandset { +struct ieee_subbandset { u8 firstchan; u8 nrchan; u8 maxtxpwr; } __attribute__ ((packed)); -struct ieeetypes_countryinfoset { - u8 element_id; - u8 len; +struct ieee_ie_country_info_set { + struct ieee_ie_header header; + u8 countrycode[COUNTRY_CODE_LEN]; - struct ieeetypes_subbandset subband[1]; + struct ieee_subbandset subband[1]; }; -struct ieeetypes_countryinfofullset { - u8 element_id; - u8 len; +struct ieee_ie_country_info_full_set { + struct ieee_ie_header header; + u8 countrycode[COUNTRY_CODE_LEN]; - struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; + struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; } __attribute__ ((packed)); -struct mrvlietypes_domainparamset { - struct mrvlietypesheader header; +struct mrvl_ie_domain_param_set { + struct mrvl_ie_header header; + u8 countrycode[COUNTRY_CODE_LEN]; - struct ieeetypes_subbandset subband[1]; + struct ieee_subbandset subband[1]; } __attribute__ ((packed)); struct cmd_ds_802_11d_domain_info { __le16 action; - struct mrvlietypes_domainparamset domain; + struct mrvl_ie_domain_param_set domain; } __attribute__ ((packed)); /** domain regulatory information */ @@ -57,7 +58,7 @@ struct lbs_802_11d_domain_reg { u8 countrycode[COUNTRY_CODE_LEN]; /** No. of subband*/ u8 nr_subband; - struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; + struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; }; struct chan_power_11d { diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index a0e440cd8967..b9b374119033 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -12,15 +12,14 @@ #include "scan.h" #include "cmd.h" -static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp); - static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/* The firmware needs certain bits masked out of the beacon-derviced capability - * field when associating/joining to BSSs. +/* The firmware needs the following bits masked out of the beacon-derived + * capability field when associating/joining to a BSS: + * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) */ #define CAPINFO_MASK (~(0xda00)) @@ -102,6 +101,295 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) } +static u8 iw_auth_to_ieee_auth(u8 auth) +{ + if (auth == IW_AUTH_ALG_OPEN_SYSTEM) + return 0x00; + else if (auth == IW_AUTH_ALG_SHARED_KEY) + return 0x01; + else if (auth == IW_AUTH_ALG_LEAP) + return 0x80; + + lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth); + return 0; +} + +/** + * @brief This function prepares the authenticate command. AUTHENTICATE only + * sets the authentication suite for future associations, as the firmware + * handles authentication internally during the ASSOCIATE command. + * + * @param priv A pointer to struct lbs_private structure + * @param bssid The peer BSSID with which to authenticate + * @param auth The authentication mode to use (from wireless.h) + * + * @return 0 or -1 + */ +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); + + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + memcpy(cmd.bssid, bssid, ETH_ALEN); + + 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); + + ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); + + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + + +static int lbs_assoc_post(struct lbs_private *priv, + struct cmd_ds_802_11_associate_response *resp) +{ + int ret = 0; + union iwreq_data wrqu; + struct bss_descriptor *bss; + u16 status_code; + + lbs_deb_enter(LBS_DEB_ASSOC); + + if (!priv->in_progress_assoc_req) { + lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); + ret = -1; + goto done; + } + bss = &priv->in_progress_assoc_req->bss; + + /* + * Older FW versions map the IEEE 802.11 Status Code in the association + * response to the following values returned in resp->statuscode: + * + * IEEE Status Code Marvell Status Code + * 0 -> 0x0000 ASSOC_RESULT_SUCCESS + * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * others -> 0x0003 ASSOC_RESULT_REFUSED + * + * Other response codes: + * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) + * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for + * association response from the AP) + */ + + status_code = le16_to_cpu(resp->statuscode); + if (priv->fwrelease < 0x09000000) { + switch (status_code) { + case 0x00: + break; + case 0x01: + lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); + break; + case 0x02: + lbs_deb_assoc("ASSOC_RESP: internal timer " + "expired while waiting for the AP\n"); + break; + case 0x03: + lbs_deb_assoc("ASSOC_RESP: association " + "refused by AP\n"); + break; + case 0x04: + lbs_deb_assoc("ASSOC_RESP: authentication " + "refused by AP\n"); + break; + default: + lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " + " unknown\n", status_code); + break; + } + } else { + /* v9+ returns the AP's association response */ + lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code); + } + + if (status_code) { + lbs_mac_event_disconnected(priv); + ret = -1; + goto done; + } + + lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", + (void *) (resp + sizeof (resp->hdr)), + le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr)); + + /* Send a Media Connected event, according to the Spec */ + priv->connect_status = LBS_CONNECTED; + + /* Update current SSID and BSSID */ + memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + priv->curbssparams.ssid_len = bss->ssid_len; + memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); + + priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; + priv->NF[TYPE_RXPD][TYPE_AVG] = 0; + + memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); + memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); + priv->nextSNRNF = 0; + priv->numSNRNF = 0; + + netif_carrier_on(priv->dev); + if (!priv->tx_pending_len) + netif_wake_queue(priv->dev); + + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + +/** + * @brief This function prepares an association-class command. + * + * @param priv A pointer to struct lbs_private structure + * @param assoc_req The association request describing the BSS to associate + * or reassociate with + * @param command The actual command, either CMD_802_11_ASSOCIATE or + * CMD_802_11_REASSOCIATE + * + * @return 0 or -1 + */ +static int lbs_associate(struct lbs_private *priv, + struct assoc_request *assoc_req, + u16 command) +{ + struct cmd_ds_802_11_associate cmd; + int ret = 0; + struct bss_descriptor *bss = &assoc_req->bss; + u8 *pos = &(cmd.iebuf[0]); + u16 tmpcap, tmplen, tmpauth; + struct mrvl_ie_ssid_param_set *ssid; + struct mrvl_ie_ds_param_set *ds; + struct mrvl_ie_cf_param_set *cf; + struct mrvl_ie_rates_param_set *rates; + struct mrvl_ie_rsn_param_set *rsn; + struct mrvl_ie_auth_type *auth; + + lbs_deb_enter(LBS_DEB_ASSOC); + + BUG_ON((command != CMD_802_11_ASSOCIATE) && + (command != CMD_802_11_REASSOCIATE)); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.command = cpu_to_le16(command); + + /* Fill in static fields */ + memcpy(cmd.bssid, bss->bssid, ETH_ALEN); + cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); + + /* Capability info */ + tmpcap = (bss->capability & CAPINFO_MASK); + if (bss->mode == IW_MODE_INFRA) + tmpcap |= WLAN_CAPABILITY_ESS; + cmd.capability = cpu_to_le16(tmpcap); + lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); + + /* SSID */ + ssid = (struct mrvl_ie_ssid_param_set *) pos; + ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); + tmplen = bss->ssid_len; + ssid->header.len = cpu_to_le16(tmplen); + memcpy(ssid->ssid, bss->ssid, tmplen); + pos += sizeof(ssid->header) + tmplen; + + ds = (struct mrvl_ie_ds_param_set *) pos; + ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); + ds->header.len = cpu_to_le16(1); + ds->channel = bss->phy.ds.channel; + pos += sizeof(ds->header) + 1; + + cf = (struct mrvl_ie_cf_param_set *) pos; + cf->header.type = cpu_to_le16(TLV_TYPE_CF); + tmplen = sizeof(*cf) - sizeof (cf->header); + cf->header.len = cpu_to_le16(tmplen); + /* IE payload should be zeroed, firmware fills it in for us */ + pos += sizeof(*cf); + + rates = (struct mrvl_ie_rates_param_set *) pos; + rates->header.type = cpu_to_le16(TLV_TYPE_RATES); + memcpy(&rates->rates, &bss->rates, MAX_RATES); + tmplen = MAX_RATES; + if (get_common_rates(priv, rates->rates, &tmplen)) { + ret = -1; + goto done; + } + pos += sizeof(rates->header) + tmplen; + rates->header.len = cpu_to_le16(tmplen); + lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); + + /* Copy the infra. association rates into Current BSS state structure */ + memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); + memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); + + /* Set MSB on basic rates as the firmware requires, but _after_ + * copying to current bss rates. + */ + lbs_set_basic_rate_flags(rates->rates, tmplen); + + /* 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); + tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode); + 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); + } + + /* WPA/WPA2 IEs */ + if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { + rsn = (struct mrvl_ie_rsn_param_set *) pos; + /* WPA_IE or WPA2_IE */ + rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); + tmplen = (u16) assoc_req->wpa_ie[1]; + rsn->header.len = cpu_to_le16(tmplen); + memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); + lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn, + sizeof(rsn->header) + tmplen); + pos += sizeof(rsn->header) + tmplen; + } + + cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) + + (u16)(pos - (u8 *) &cmd.iebuf)); + + /* update curbssparams */ + priv->curbssparams.channel = bss->phy.ds.channel; + + if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { + ret = -1; + goto done; + } + + ret = lbs_cmd_with_response(priv, command, &cmd); + if (ret == 0) { + ret = lbs_assoc_post(priv, + (struct cmd_ds_802_11_associate_response *) &cmd); + } + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + /** * @brief Associate to a specific BSS discovered in a scan * @@ -110,7 +398,7 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) * * @return 0-success, otherwise fail */ -static int lbs_associate(struct lbs_private *priv, +static int lbs_try_associate(struct lbs_private *priv, struct assoc_request *assoc_req) { int ret; @@ -118,11 +406,15 @@ static int lbs_associate(struct lbs_private *priv, lbs_deb_enter(LBS_DEB_ASSOC); - ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, - 0, CMD_OPTION_WAITFORRSP, - 0, assoc_req->bss.bssid); - if (ret) - goto out; + /* FW v9 and higher indicate authentication suites as a TLV in the + * association command, not as a separate authentication command. + */ + if (priv->fwrelease < 0x09000000) { + ret = lbs_set_authentication(priv, assoc_req->bss.bssid, + priv->secinfo.auth_mode); + if (ret) + goto out; + } /* Use short preamble only when both the BSS and firmware support it */ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && @@ -133,14 +425,78 @@ static int lbs_associate(struct lbs_private *priv, if (ret) goto out; - ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, - 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); + ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } +static int lbs_adhoc_post(struct lbs_private *priv, + struct cmd_ds_802_11_ad_hoc_result *resp) +{ + int ret = 0; + u16 command = le16_to_cpu(resp->hdr.command); + u16 result = le16_to_cpu(resp->hdr.result); + union iwreq_data wrqu; + struct bss_descriptor *bss; + DECLARE_SSID_BUF(ssid); + + lbs_deb_enter(LBS_DEB_JOIN); + + if (!priv->in_progress_assoc_req) { + lbs_deb_join("ADHOC_RESP: no in-progress association " + "request\n"); + ret = -1; + goto done; + } + bss = &priv->in_progress_assoc_req->bss; + + /* + * Join result code 0 --> SUCCESS + */ + if (result) { + lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); + if (priv->connect_status == LBS_CONNECTED) + lbs_mac_event_disconnected(priv); + ret = -1; + goto done; + } + + /* Send a Media Connected event, according to the Spec */ + priv->connect_status = LBS_CONNECTED; + + if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { + /* Update the created network descriptor with the new BSSID */ + memcpy(bss->bssid, resp->bssid, ETH_ALEN); + } + + /* Set the BSSID from the joined/started descriptor */ + memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); + + /* Set the new SSID to current SSID */ + memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + priv->curbssparams.ssid_len = bss->ssid_len; + + netif_carrier_on(priv->dev); + if (!priv->tx_pending_len) + netif_wake_queue(priv->dev); + + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + + lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", + print_ssid(ssid, bss->ssid, bss->ssid_len), + priv->curbssparams.bssid, + priv->curbssparams.channel); + +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + /** * @brief Join an adhoc network found in a previous scan * @@ -219,11 +575,10 @@ static int lbs_adhoc_join(struct lbs_private *priv, memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); - memcpy(&cmd.bss.phyparamset, &bss->phyparamset, - sizeof(union ieeetypes_phyparamset)); + memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set)); - memcpy(&cmd.bss.ssparamset, &bss->ssparamset, - sizeof(union IEEEtypes_ssparamset)); + memcpy(&cmd.bss.ibss, &bss->ss.ibss, + sizeof(struct ieee_ie_ibss_param_set)); cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", @@ -260,7 +615,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, */ lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); - cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow); + cmd.bss.ibss.atimwindow = bss->atimwindow; if (assoc_req->secinfo.wep_enabled) { u16 tmp = le16_to_cpu(cmd.bss.capability); @@ -287,8 +642,10 @@ static int lbs_adhoc_join(struct lbs_private *priv, } ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); - if (ret == 0) - ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); + if (ret == 0) { + ret = lbs_adhoc_post(priv, + (struct cmd_ds_802_11_ad_hoc_result *)&cmd); + } out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); @@ -343,22 +700,24 @@ static int lbs_adhoc_start(struct lbs_private *priv, WARN_ON(!assoc_req->channel); /* set Physical parameter set */ - cmd.phyparamset.dsparamset.elementid = WLAN_EID_DS_PARAMS; - cmd.phyparamset.dsparamset.len = 1; - cmd.phyparamset.dsparamset.currentchan = assoc_req->channel; + cmd.ds.header.id = WLAN_EID_DS_PARAMS; + cmd.ds.header.len = 1; + cmd.ds.channel = assoc_req->channel; /* set IBSS parameter set */ - cmd.ssparamset.ibssparamset.elementid = WLAN_EID_IBSS_PARAMS; - cmd.ssparamset.ibssparamset.len = 2; - cmd.ssparamset.ibssparamset.atimwindow = 0; + cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; + cmd.ibss.header.len = 2; + cmd.ibss.atimwindow = cpu_to_le16(0); /* set capability info */ tmpcap = WLAN_CAPABILITY_IBSS; - if (assoc_req->secinfo.wep_enabled) { - lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n"); + if (assoc_req->secinfo.wep_enabled || + assoc_req->secinfo.WPAenabled || + assoc_req->secinfo.WPA2enabled) { + lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n"); tmpcap |= WLAN_CAPABILITY_PRIVACY; } else - lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n"); + lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n"); cmd.capability = cpu_to_le16(tmpcap); @@ -395,7 +754,8 @@ static int lbs_adhoc_start(struct lbs_private *priv, ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); if (ret == 0) - ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); + ret = lbs_adhoc_post(priv, + (struct cmd_ds_802_11_ad_hoc_result *)&cmd); out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); @@ -720,7 +1080,7 @@ static int assoc_helper_essid(struct lbs_private *priv, assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); if (bss != NULL) { memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - ret = lbs_associate(priv, assoc_req); + ret = lbs_try_associate(priv, assoc_req); } else { lbs_deb_assoc("SSID not found; cannot associate\n"); } @@ -772,8 +1132,9 @@ static int assoc_helper_bssid(struct lbs_private *priv, memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); if (assoc_req->mode == IW_MODE_INFRA) { - ret = lbs_associate(priv, assoc_req); - lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); + ret = lbs_try_associate(priv, assoc_req); + lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n", + ret); } else if (assoc_req->mode == IW_MODE_ADHOC) { lbs_adhoc_join(priv, assoc_req); } @@ -1466,57 +1827,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) } -/** - * @brief This function prepares command of authenticate. - * - * @param priv A pointer to struct lbs_private structure - * @param cmd A pointer to cmd_ds_command structure - * @param pdata_buf Void cast of pointer to a BSSID to authenticate with - * - * @return 0 or -1 - */ -int lbs_cmd_80211_authenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf) -{ - struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth; - int ret = -1; - u8 *bssid = pdata_buf; - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) - + S_DS_GEN); - - /* translate auth mode to 802.11 defined wire value */ - switch (priv->secinfo.auth_mode) { - case IW_AUTH_ALG_OPEN_SYSTEM: - pauthenticate->authtype = 0x00; - break; - case IW_AUTH_ALG_SHARED_KEY: - pauthenticate->authtype = 0x01; - break; - case IW_AUTH_ALG_LEAP: - pauthenticate->authtype = 0x80; - break; - default: - lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n", - priv->secinfo.auth_mode); - goto out; - } - - memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); - - lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", - bssid, pauthenticate->authtype); - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - /** * @brief Deauthenticate from a specific BSS * @@ -1550,285 +1860,3 @@ int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], return ret; } -int lbs_cmd_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *cmd, void *pdata_buf) -{ - struct cmd_ds_802_11_associate *passo = &cmd->params.associate; - int ret = 0; - struct assoc_request *assoc_req = pdata_buf; - struct bss_descriptor *bss = &assoc_req->bss; - u8 *pos; - u16 tmpcap, tmplen; - struct mrvlietypes_ssidparamset *ssid; - struct mrvlietypes_phyparamset *phy; - struct mrvlietypes_ssparamset *ss; - struct mrvlietypes_ratesparamset *rates; - struct mrvlietypes_rsnparamset *rsn; - - lbs_deb_enter(LBS_DEB_ASSOC); - - pos = (u8 *) passo; - - if (!priv) { - ret = -1; - goto done; - } - - cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE); - - memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr)); - pos += sizeof(passo->peerstaaddr); - - /* set the listen interval */ - passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); - - pos += sizeof(passo->capability); - pos += sizeof(passo->listeninterval); - pos += sizeof(passo->bcnperiod); - pos += sizeof(passo->dtimperiod); - - ssid = (struct mrvlietypes_ssidparamset *) pos; - ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); - tmplen = bss->ssid_len; - ssid->header.len = cpu_to_le16(tmplen); - memcpy(ssid->ssid, bss->ssid, tmplen); - pos += sizeof(ssid->header) + tmplen; - - phy = (struct mrvlietypes_phyparamset *) pos; - phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); - tmplen = sizeof(phy->fh_ds.dsparamset); - phy->header.len = cpu_to_le16(tmplen); - memcpy(&phy->fh_ds.dsparamset, - &bss->phyparamset.dsparamset.currentchan, - tmplen); - pos += sizeof(phy->header) + tmplen; - - ss = (struct mrvlietypes_ssparamset *) pos; - ss->header.type = cpu_to_le16(TLV_TYPE_CF); - tmplen = sizeof(ss->cf_ibss.cfparamset); - ss->header.len = cpu_to_le16(tmplen); - pos += sizeof(ss->header) + tmplen; - - rates = (struct mrvlietypes_ratesparamset *) pos; - rates->header.type = cpu_to_le16(TLV_TYPE_RATES); - memcpy(&rates->rates, &bss->rates, MAX_RATES); - tmplen = MAX_RATES; - if (get_common_rates(priv, rates->rates, &tmplen)) { - ret = -1; - goto done; - } - pos += sizeof(rates->header) + tmplen; - rates->header.len = cpu_to_le16(tmplen); - lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); - - /* Copy the infra. association rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(rates->rates, tmplen); - - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - rsn = (struct mrvlietypes_rsnparamset *) pos; - /* WPA_IE or WPA2_IE */ - rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); - tmplen = (u16) assoc_req->wpa_ie[1]; - rsn->header.len = cpu_to_le16(tmplen); - memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); - lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn, - sizeof(rsn->header) + tmplen); - pos += sizeof(rsn->header) + tmplen; - } - - /* update curbssparams */ - priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; - - if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { - ret = -1; - goto done; - } - - cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); - - /* set the capability info */ - tmpcap = (bss->capability & CAPINFO_MASK); - if (bss->mode == IW_MODE_INFRA) - tmpcap |= WLAN_CAPABILITY_ESS; - passo->capability = cpu_to_le16(tmpcap); - lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -int lbs_ret_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - int ret = 0; - union iwreq_data wrqu; - struct ieeetypes_assocrsp *passocrsp; - struct bss_descriptor *bss; - u16 status_code; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (!priv->in_progress_assoc_req) { - lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - passocrsp = (struct ieeetypes_assocrsp *) &resp->params; - - /* - * Older FW versions map the IEEE 802.11 Status Code in the association - * response to the following values returned in passocrsp->statuscode: - * - * IEEE Status Code Marvell Status Code - * 0 -> 0x0000 ASSOC_RESULT_SUCCESS - * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * others -> 0x0003 ASSOC_RESULT_REFUSED - * - * Other response codes: - * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) - * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for - * association response from the AP) - */ - - status_code = le16_to_cpu(passocrsp->statuscode); - switch (status_code) { - case 0x00: - break; - case 0x01: - lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); - break; - case 0x02: - lbs_deb_assoc("ASSOC_RESP: internal timer " - "expired while waiting for the AP\n"); - break; - case 0x03: - lbs_deb_assoc("ASSOC_RESP: association " - "refused by AP\n"); - break; - case 0x04: - lbs_deb_assoc("ASSOC_RESP: authentication " - "refused by AP\n"); - break; - default: - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " - " unknown\n", status_code); - break; - } - - if (status_code) { - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params, - le16_to_cpu(resp->size) - S_DS_GEN); - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - /* Update current SSID and BSSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; - priv->NF[TYPE_RXPD][TYPE_AVG] = 0; - - memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); - memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); - priv->nextSNRNF = 0; - priv->numSNRNF = 0; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp) -{ - int ret = 0; - u16 command = le16_to_cpu(resp->command); - u16 result = le16_to_cpu(resp->result); - struct cmd_ds_802_11_ad_hoc_result *adhoc_resp; - union iwreq_data wrqu; - struct bss_descriptor *bss; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_JOIN); - - adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp; - - if (!priv->in_progress_assoc_req) { - lbs_deb_join("ADHOC_RESP: no in-progress association " - "request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Join result code 0 --> SUCCESS - */ - if (result) { - lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); - if (priv->connect_status == LBS_CONNECTED) - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { - /* Update the created network descriptor with the new BSSID */ - memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN); - } - - /* Set the BSSID from the joined/started descriptor */ - memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - /* Set the new SSID to current SSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - priv->curbssparams.bssid, - priv->curbssparams.channel); - -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 8b7336dd02a3..6e765e9f91a3 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h @@ -8,22 +8,9 @@ void lbs_association_worker(struct work_struct *work); struct assoc_request *lbs_get_association_request(struct lbs_private *priv); -struct cmd_ds_command; -int lbs_cmd_80211_authenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); - int lbs_adhoc_stop(struct lbs_private *priv); int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], u16 reason); -int lbs_cmd_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); - -int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, - struct cmd_ds_command *resp); -int lbs_ret_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *resp); #endif /* _LBS_ASSOC_H */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 8c3605cdc64c..01db705a38ec 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -119,6 +119,19 @@ int lbs_update_hw_spec(struct lbs_private *priv) lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", cmd.hwifversion, cmd.version); + /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ + /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ + /* 5.110.22 have mesh command with 0xa3 command id */ + /* 10.0.0.p0 FW brings in mesh config command with different id */ + /* Check FW version MSB and initialize mesh_fw_ver */ + if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) + priv->mesh_fw_ver = MESH_FW_OLD; + else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && + (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) + priv->mesh_fw_ver = MESH_FW_NEW; + else + priv->mesh_fw_ver = MESH_NONE; + /* Clamp region code to 8-bit since FW spec indicates that it should * only ever be 8-bit, even though the field size is 16-bit. Some firmware * returns non-zero high 8 bits here. @@ -1036,17 +1049,26 @@ static int __lbs_mesh_config_send(struct lbs_private *priv, uint16_t action, uint16_t type) { int ret; + u16 command = CMD_MESH_CONFIG_OLD; lbs_deb_enter(LBS_DEB_CMD); - cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG); + /* + * Command id is 0xac for v10 FW along with mesh interface + * id in bits 14-13-12. + */ + if (priv->mesh_fw_ver == MESH_FW_NEW) + command = CMD_MESH_CONFIG | + (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); + + cmd->hdr.command = cpu_to_le16(command); cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); cmd->hdr.result = 0; cmd->type = cpu_to_le16(type); cmd->action = cpu_to_le16(action); - ret = lbs_cmd_with_response(priv, CMD_MESH_CONFIG, cmd); + ret = lbs_cmd_with_response(priv, command, cmd); lbs_deb_leave(LBS_DEB_CMD); return ret; @@ -1198,8 +1220,7 @@ static void lbs_submit_command(struct lbs_private *priv, command = le16_to_cpu(cmd->command); /* These commands take longer */ - if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE || - command == CMD_802_11_AUTHENTICATE) + if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE) timeo = 5 * HZ; lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", @@ -1393,15 +1414,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action); break; - case CMD_802_11_ASSOCIATE: - case CMD_802_11_REASSOCIATE: - ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); - break; - - case CMD_802_11_AUTHENTICATE: - ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf); - break; - case CMD_MAC_REG_ACCESS: case CMD_BBP_REG_ACCESS: case CMD_RF_REG_ACCESS: @@ -1448,8 +1460,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, break; case CMD_802_11_LED_GPIO_CTRL: { - struct mrvlietypes_ledgpio *gpio = - (struct mrvlietypes_ledgpio*) + struct mrvl_ie_ledgpio *gpio = + (struct mrvl_ie_ledgpio*) cmdptr->params.ledgpio.data; memmove(&cmdptr->params.ledgpio, diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index bcf2a9756fb6..c42d3faa2660 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -5,7 +5,7 @@ #include #include #include - +#include #include #include "host.h" @@ -154,11 +154,11 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv, lbs_deb_enter(LBS_DEB_CMD); /* store the non average value */ - priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR); - priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor); + priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); + priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor); - priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR); - priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor); + priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); + priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor); priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], @@ -210,12 +210,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_reg_access(priv, respcmd, resp); break; - case CMD_RET_802_11_ASSOCIATE: - case CMD_RET(CMD_802_11_ASSOCIATE): - case CMD_RET(CMD_802_11_REASSOCIATE): - ret = lbs_ret_80211_associate(priv, resp); - break; - case CMD_RET(CMD_802_11_SET_AFC): case CMD_RET(CMD_802_11_GET_AFC): spin_lock_irqsave(&priv->driver_lock, flags); @@ -225,7 +219,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, break; - case CMD_RET(CMD_802_11_AUTHENTICATE): case CMD_RET(CMD_802_11_BEACON_STOP): break; diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 50e28a0cdfee..811ffc3ef414 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -183,12 +183,12 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf, */ static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size) { - struct mrvlietypesheader *tlv_h; + struct mrvl_ie_header *tlv_h; uint16_t length; ssize_t pos = 0; while (pos < size) { - tlv_h = (struct mrvlietypesheader *) tlv; + tlv_h = (struct mrvl_ie_header *) tlv; if (!tlv_h->len) return NULL; if (tlv_h->type == cpu_to_le16(tlv_type)) @@ -206,7 +206,7 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask, size_t count, loff_t *ppos) { struct cmd_ds_802_11_subscribe_event *subscribed; - struct mrvlietypes_thresholds *got; + struct mrvl_ie_thresholds *got; struct lbs_private *priv = file->private_data; ssize_t ret = 0; size_t pos = 0; @@ -259,7 +259,7 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, loff_t *ppos) { struct cmd_ds_802_11_subscribe_event *events; - struct mrvlietypes_thresholds *tlv; + struct mrvl_ie_thresholds *tlv; struct lbs_private *priv = file->private_data; ssize_t buf_size; int value, freq, new_mask; diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index e8dfde39abfc..48da157d6cda 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -227,6 +227,20 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define TxPD_CONTROL_WDS_FRAME (1<<17) #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME +/** Mesh interface ID */ +#define MESH_IFACE_ID 0x0001 +/** Mesh id should be in bits 14-13-12 */ +#define MESH_IFACE_BIT_OFFSET 0x000c +/** Mesh enable bit in FW capability */ +#define MESH_CAPINFO_ENABLE_MASK (1<<16) + +/** FW definition from Marvell v5 */ +#define MRVL_FW_V5 (0x05) +/** FW definition from Marvell v10 */ +#define MRVL_FW_V10 (0x0a) +/** FW major revision definition */ +#define MRVL_FW_MAJOR_REV(x) ((x)>>24) + /** RxPD status */ #define MRVDRV_RXPD_STATUS_OK 0x0001 @@ -380,6 +394,13 @@ enum KEY_INFO_WPA { KEY_INFO_WPA_ENABLED = 0x04 }; +/** mesh_fw_ver */ +enum _mesh_fw_ver { + MESH_NONE = 0, /* MESH is not supported */ + MESH_FW_OLD, /* MESH is supported in FW V5 */ + MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ +}; + /* Default values for fwt commands. */ #define FWT_DEFAULT_METRIC 0 #define FWT_DEFAULT_DIR 1 diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 27e81fd97c94..f9ec69e04734 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -101,6 +101,7 @@ struct lbs_mesh_stats { /** Private structure for the MV device */ struct lbs_private { int mesh_open; + int mesh_fw_ver; int infra_open; int mesh_autostart_enabled; @@ -337,7 +338,7 @@ struct bss_descriptor { u32 rssi; u32 channel; u16 beaconperiod; - u32 atimwindow; + __le16 atimwindow; /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ u8 mode; @@ -347,10 +348,10 @@ struct bss_descriptor { unsigned long last_scanned; - union ieeetypes_phyparamset phyparamset; - union IEEEtypes_ssparamset ssparamset; + union ieee_phy_param_set phy; + union ieee_ss_param_set ss; - struct ieeetypes_countryinfofullset countryinfo; + struct ieee_ie_country_info_full_set countryinfo; u8 wpa_ie[MAX_WPA_IE_LEN]; size_t wpa_ie_len; diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index d4457ef808a6..fe8f0cb737bc 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -83,8 +83,11 @@ #define CMD_FWT_ACCESS 0x0095 #define CMD_802_11_MONITOR_MODE 0x0098 #define CMD_MESH_ACCESS 0x009b -#define CMD_MESH_CONFIG 0x00a3 +#define CMD_MESH_CONFIG_OLD 0x00a3 +#define CMD_MESH_CONFIG 0x00ac #define CMD_SET_BOOT2_VER 0x00a5 +#define CMD_FUNC_INIT 0x00a9 +#define CMD_FUNC_SHUTDOWN 0x00aa #define CMD_802_11_BEACON_CTRL 0x00b0 /* For the IEEE Power Save */ diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index a899aeb676bb..0a2e29140add 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -13,8 +13,19 @@ /* TxPD descriptor */ struct txpd { - /* Current Tx packet status */ - __le32 tx_status; + /* union to cope up with later FW revisions */ + union { + /* Current Tx packet status */ + __le32 tx_status; + struct { + /* BSS type: client, AP, etc. */ + u8 bss_type; + /* BSS number */ + u8 bss_num; + /* Reserved */ + __le16 reserved; + } bss; + } u; /* Tx control */ __le32 tx_control; __le32 tx_packet_location; @@ -36,8 +47,17 @@ struct txpd { /* RxPD Descriptor */ struct rxpd { - /* Current Rx packet status */ - __le16 status; + /* union to cope up with later FW revisions */ + union { + /* Current Rx packet status */ + __le16 status; + struct { + /* BSS type: client, AP, etc. */ + u8 bss_type; + /* BSS number */ + u8 bss_num; + } bss; + } u; /* SNR */ u8 snr; @@ -230,7 +250,9 @@ struct cmd_ds_gspi_bus_config { } __attribute__ ((packed)); struct cmd_ds_802_11_authenticate { - u8 macaddr[ETH_ALEN]; + struct cmd_header hdr; + + u8 bssid[ETH_ALEN]; u8 authtype; u8 reserved[10]; } __attribute__ ((packed)); @@ -243,22 +265,23 @@ struct cmd_ds_802_11_deauthenticate { } __attribute__ ((packed)); struct cmd_ds_802_11_associate { - u8 peerstaaddr[6]; + struct cmd_header hdr; + + u8 bssid[6]; __le16 capability; __le16 listeninterval; __le16 bcnperiod; u8 dtimperiod; - -#if 0 - mrvlietypes_ssidparamset_t ssidParamSet; - mrvlietypes_phyparamset_t phyparamset; - mrvlietypes_ssparamset_t ssparamset; - mrvlietypes_ratesparamset_t ratesParamSet; -#endif + u8 iebuf[512]; /* Enough for required and most optional IEs */ } __attribute__ ((packed)); -struct cmd_ds_802_11_associate_rsp { - struct ieeetypes_assocrsp assocRsp; +struct cmd_ds_802_11_associate_response { + struct cmd_header hdr; + + __le16 capability; + __le16 statuscode; + __le16 aid; + u8 iebuf[512]; } __attribute__ ((packed)); struct cmd_ds_802_11_set_wep { @@ -515,9 +538,11 @@ struct cmd_ds_802_11_ad_hoc_start { u8 bsstype; __le16 beaconperiod; u8 dtimperiod; /* Reserved on v9 and later */ - union IEEEtypes_ssparamset ssparamset; - union ieeetypes_phyparamset phyparamset; - __le16 probedelay; + struct ieee_ie_ibss_param_set ibss; + u8 reserved1[4]; + struct ieee_ie_ds_param_set ds; + u8 reserved2[4]; + __le16 probedelay; /* Reserved on v9 and later */ __le16 capability; u8 rates[MAX_RATES]; u8 tlv_memory_size_pad[100]; @@ -538,8 +563,10 @@ struct adhoc_bssdesc { u8 dtimperiod; __le64 timestamp; __le64 localtime; - union ieeetypes_phyparamset phyparamset; - union IEEEtypes_ssparamset ssparamset; + struct ieee_ie_ds_param_set ds; + u8 reserved1[4]; + struct ieee_ie_ibss_param_set ibss; + u8 reserved2[4]; __le16 capability; u8 rates[MAX_RATES]; @@ -745,8 +772,6 @@ struct cmd_ds_command { /* command Body */ union { struct cmd_ds_802_11_ps_mode psmode; - struct cmd_ds_802_11_associate associate; - struct cmd_ds_802_11_authenticate auth; struct cmd_ds_802_11_get_stat gstat; struct cmd_ds_802_3_get_stat gstat_8023; struct cmd_ds_802_11_rf_antenna rant; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index cedeac6322fe..2a5b083bf9bd 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -273,7 +273,28 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r */ #define IF_CS_PRODUCT_ID 0x0000001C #define IF_CS_CF8385_B1_REV 0x12 +#define IF_CS_CF8381_B3_REV 0x04 +/* + * Used to detect other cards than CF8385 since their revisions of silicon + * doesn't match those from CF8385, eg. CF8381 B3 works with this driver. + */ +#define CF8381_MANFID 0x02db +#define CF8381_CARDID 0x6064 +#define CF8385_MANFID 0x02df +#define CF8385_CARDID 0x8103 + +static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) +{ + return (p_dev->manf_id == CF8381_MANFID && + p_dev->card_id == CF8381_CARDID); +} + +static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) +{ + return (p_dev->manf_id == CF8385_MANFID && + p_dev->card_id == CF8385_CARDID); +} /********************************************************************/ /* I/O and interrupt handling */ @@ -757,6 +778,7 @@ static void if_cs_release(struct pcmcia_device *p_dev) static int if_cs_probe(struct pcmcia_device *p_dev) { int ret = -ENOMEM; + unsigned int prod_id; struct lbs_private *priv; struct if_cs_card *card; /* CIS parsing */ @@ -859,7 +881,14 @@ static int if_cs_probe(struct pcmcia_device *p_dev) p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); /* Check if we have a current silicon */ - if (if_cs_read8(card, IF_CS_PRODUCT_ID) < IF_CS_CF8385_B1_REV) { + prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); + if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { + lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); + ret = -ENODEV; + goto out2; + } + + if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); ret = -ENODEV; goto out2; @@ -950,7 +979,8 @@ static void if_cs_detach(struct pcmcia_device *p_dev) /********************************************************************/ static struct pcmcia_device_id if_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x02df, 0x8103), + PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), + PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 76f4c653d641..8cdb88c6ca28 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -39,8 +39,24 @@ #include "decl.h" #include "defs.h" #include "dev.h" +#include "cmd.h" #include "if_sdio.h" +/* The if_sdio_remove() callback function is called when + * user removes this module from kernel space or ejects + * the card from the slot. The driver handles these 2 cases + * differently for SD8688 combo chip. + * If the user is removing the module, the FUNC_SHUTDOWN + * command for SD8688 is sent to the firmware. + * If the card is removed, there is no need to send this command. + * + * The variable 'user_rmmod' is used to distinguish these two + * scenarios. This flag is initialized as FALSE in case the card + * is removed, and will be set to TRUE for module removal when + * module_exit function is called. + */ +static u8 user_rmmod; + static char *lbs_helper_name = NULL; module_param_named(helper_name, lbs_helper_name, charp, 0644); @@ -48,8 +64,11 @@ static char *lbs_fw_name = NULL; module_param_named(fw_name, lbs_fw_name, charp, 0644); static const struct sdio_device_id if_sdio_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, - { /* end: all zeroes */ }, + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, + SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, + SDIO_DEVICE_ID_MARVELL_8688WLAN) }, + { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, if_sdio_ids); @@ -63,16 +82,22 @@ struct if_sdio_model { static struct if_sdio_model if_sdio_models[] = { { /* 8385 */ - .model = 0x04, + .model = IF_SDIO_MODEL_8385, .helper = "sd8385_helper.bin", .firmware = "sd8385.bin", }, { /* 8686 */ - .model = 0x0B, + .model = IF_SDIO_MODEL_8686, .helper = "sd8686_helper.bin", .firmware = "sd8686.bin", }, + { + /* 8688 */ + .model = IF_SDIO_MODEL_8688, + .helper = "sd8688_helper.bin", + .firmware = "sd8688.bin", + }, }; struct if_sdio_packet { @@ -87,6 +112,7 @@ struct if_sdio_card { int model; unsigned long ioport; + unsigned int scratch_reg; const char *helper; const char *firmware; @@ -98,25 +124,29 @@ struct if_sdio_card { struct workqueue_struct *workqueue; struct work_struct packet_worker; + + u8 rx_unit; }; /********************************************************************/ /* I/O */ /********************************************************************/ +/* + * For SD8385/SD8686, this function reads firmware status after + * the image is downloaded, or reads RX packet length when + * interrupt (with IF_SDIO_H_INT_UPLD bit set) is received. + * For SD8688, this function reads firmware status only. + */ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) { - int ret, reg; + int ret; u16 scratch; - if (card->model == 0x04) - reg = IF_SDIO_SCRATCH_OLD; - else - reg = IF_SDIO_SCRATCH; - - scratch = sdio_readb(card->func, reg, &ret); + scratch = sdio_readb(card->func, card->scratch_reg, &ret); if (!ret) - scratch |= sdio_readb(card->func, reg + 1, &ret) << 8; + scratch |= sdio_readb(card->func, card->scratch_reg + 1, + &ret) << 8; if (err) *err = ret; @@ -127,6 +157,46 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) return scratch; } +static u8 if_sdio_read_rx_unit(struct if_sdio_card *card) +{ + int ret; + u8 rx_unit; + + rx_unit = sdio_readb(card->func, IF_SDIO_RX_UNIT, &ret); + + if (ret) + rx_unit = 0; + + return rx_unit; +} + +static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err) +{ + int ret; + u16 rx_len; + + switch (card->model) { + case IF_SDIO_MODEL_8385: + case IF_SDIO_MODEL_8686: + rx_len = if_sdio_read_scratch(card, &ret); + break; + case IF_SDIO_MODEL_8688: + default: /* for newer chipsets */ + rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); + if (!ret) + rx_len <<= card->rx_unit; + else + rx_len = 0xffff; /* invalid length */ + + break; + } + + if (err) + *err = ret; + + return rx_len; +} + static int if_sdio_handle_cmd(struct if_sdio_card *card, u8 *buffer, unsigned size) { @@ -207,7 +277,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card, lbs_deb_enter(LBS_DEB_SDIO); - if (card->model == 0x04) { + if (card->model == IF_SDIO_MODEL_8385) { event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); if (ret) goto out; @@ -245,7 +315,7 @@ static int if_sdio_card_to_host(struct if_sdio_card *card) lbs_deb_enter(LBS_DEB_SDIO); - size = if_sdio_read_scratch(card, &ret); + size = if_sdio_read_rx_len(card, &ret); if (ret) goto out; @@ -488,7 +558,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) ret = 0; release: - sdio_set_block_size(card->func, 0); sdio_release_host(card->func); kfree(chunk_buffer); release_fw: @@ -624,7 +693,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card) ret = 0; release: - sdio_set_block_size(card->func, 0); sdio_release_host(card->func); kfree(chunk_buffer); release_fw: @@ -653,6 +721,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) if (ret) goto out; + lbs_deb_sdio("firmware status = %#x\n", scratch); + if (scratch == IF_SDIO_FIRMWARE_OK) { lbs_deb_sdio("firmware already loaded\n"); goto success; @@ -667,6 +737,9 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) goto out; success: + sdio_claim_host(card->func); + sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); + sdio_release_host(card->func); ret = 0; out: @@ -820,10 +893,10 @@ static int if_sdio_probe(struct sdio_func *func, if (sscanf(func->card->info[i], "ID: %x", &model) == 1) break; - if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { - model = 4; - break; - } + if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { + model = IF_SDIO_MODEL_8385; + break; + } } if (i == func->card->num_info) { @@ -837,6 +910,20 @@ static int if_sdio_probe(struct sdio_func *func, card->func = func; card->model = model; + + switch (card->model) { + case IF_SDIO_MODEL_8385: + card->scratch_reg = IF_SDIO_SCRATCH_OLD; + break; + case IF_SDIO_MODEL_8686: + card->scratch_reg = IF_SDIO_SCRATCH; + break; + case IF_SDIO_MODEL_8688: + default: /* for newer chipsets */ + card->scratch_reg = IF_SDIO_FW_STATUS; + break; + } + spin_lock_init(&card->lock); card->workqueue = create_workqueue("libertas_sdio"); INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); @@ -914,15 +1001,40 @@ static int if_sdio_probe(struct sdio_func *func, priv->fw_ready = 1; + sdio_claim_host(func); + + /* + * Get rx_unit if the chip is SD8688 or newer. + * SD8385 & SD8686 do not have rx_unit. + */ + if ((card->model != IF_SDIO_MODEL_8385) + && (card->model != IF_SDIO_MODEL_8686)) + card->rx_unit = if_sdio_read_rx_unit(card); + else + card->rx_unit = 0; + /* * Enable interrupts now that everything is set up */ - sdio_claim_host(func); sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret); sdio_release_host(func); if (ret) goto reclaim; + /* + * FUNC_INIT is required for SD8688 WLAN/BT multiple functions + */ + if (card->model == IF_SDIO_MODEL_8688) { + struct cmd_header cmd; + + memset(&cmd, 0, sizeof(cmd)); + + lbs_deb_sdio("send function INIT command\n"); + if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), + lbs_cmd_copyback, (unsigned long) &cmd)) + lbs_pr_alert("CMD_FUNC_INIT cmd failed\n"); + } + ret = lbs_start_card(priv); if (ret) goto err_activate_card; @@ -968,6 +1080,22 @@ static void if_sdio_remove(struct sdio_func *func) card = sdio_get_drvdata(func); + if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { + /* + * FUNC_SHUTDOWN is required for SD8688 WLAN/BT + * multiple functions + */ + struct cmd_header cmd; + + memset(&cmd, 0, sizeof(cmd)); + + lbs_deb_sdio("send function SHUTDOWN command\n"); + if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN, + &cmd, sizeof(cmd), lbs_cmd_copyback, + (unsigned long) &cmd)) + lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n"); + } + card->priv->surpriseremoved = 1; lbs_deb_sdio("call remove card\n"); @@ -1015,6 +1143,9 @@ static int __init if_sdio_init_module(void) ret = sdio_register_driver(&if_sdio_driver); + /* Clear the flag in case user removes the card. */ + user_rmmod = 0; + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); return ret; @@ -1024,6 +1155,9 @@ static void __exit if_sdio_exit_module(void) { lbs_deb_enter(LBS_DEB_SDIO); + /* Set the flag as user is removing this module. */ + user_rmmod = 1; + sdio_unregister_driver(&if_sdio_driver); lbs_deb_leave(LBS_DEB_SDIO); diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 533bdfbf5d2a..60c9b2fcef03 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h @@ -12,6 +12,10 @@ #ifndef _LBS_IF_SDIO_H #define _LBS_IF_SDIO_H +#define IF_SDIO_MODEL_8385 0x04 +#define IF_SDIO_MODEL_8686 0x0b +#define IF_SDIO_MODEL_8688 0x10 + #define IF_SDIO_IOPORT 0x00 #define IF_SDIO_H_INT_MASK 0x04 @@ -38,8 +42,14 @@ #define IF_SDIO_SCRATCH 0x34 #define IF_SDIO_SCRATCH_OLD 0x80fe +#define IF_SDIO_FW_STATUS 0x40 #define IF_SDIO_FIRMWARE_OK 0xfedc +#define IF_SDIO_RX_LEN 0x42 +#define IF_SDIO_RX_UNIT 0x43 + #define IF_SDIO_EVENT 0x80fc +#define IF_SDIO_BLOCK_SIZE 256 + #endif diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 07311e71af92..f8c2898d82b0 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -51,13 +50,6 @@ struct if_spi_card { u16 card_id; u8 card_rev; - /* Pin number for our GPIO chip-select. */ - /* TODO: Once the generic SPI layer has some additional features, we - * should take this out and use the normal chip select here. - * We need support for chip select delays, and not dropping chipselect - * after each word. */ - int gpio_cs; - /* The last time that we initiated an SPU operation */ unsigned long prev_xfer_time; @@ -119,9 +111,6 @@ static struct chip_ident chip_id_to_device_name[] = { * First we have to put a SPU register name on the bus. Then we can * either read from or write to that register. * - * For 16-bit transactions, byte order on the bus is big-endian. - * We don't have to worry about that here, though. - * The translation takes place in the SPI routines. */ static void spu_transaction_init(struct if_spi_card *card) @@ -133,12 +122,10 @@ static void spu_transaction_init(struct if_spi_card *card) * If not, we have to busy-wait to be on the safe side. */ ndelay(400); } - gpio_set_value(card->gpio_cs, 0); /* assert CS */ } static void spu_transaction_finish(struct if_spi_card *card) { - gpio_set_value(card->gpio_cs, 1); /* drop CS */ card->prev_xfer_time = jiffies; } @@ -147,7 +134,14 @@ static void spu_transaction_finish(struct if_spi_card *card) static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) { int err = 0; - u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK; + u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK); + struct spi_message m; + struct spi_transfer reg_trans; + struct spi_transfer data_trans; + + spi_message_init(&m); + memset(®_trans, 0, sizeof(reg_trans)); + memset(&data_trans, 0, sizeof(data_trans)); /* You must give an even number of bytes to the SPU, even if it * doesn't care about the last one. */ @@ -156,29 +150,26 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) spu_transaction_init(card); /* write SPU register index */ - err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); - if (err) - goto out; + reg_trans.tx_buf = ®_out; + reg_trans.len = sizeof(reg_out); - err = spi_write(card->spi, buf, len); + data_trans.tx_buf = buf; + data_trans.len = len; -out: + spi_message_add_tail(®_trans, &m); + spi_message_add_tail(&data_trans, &m); + + err = spi_sync(card->spi, &m); spu_transaction_finish(card); return err; } static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val) { - return spu_write(card, reg, (u8 *)&val, sizeof(u16)); -} + u16 buff; -static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val) -{ - /* The lower 16 bits are written first. */ - u16 out[2]; - out[0] = val & 0xffff; - out[1] = (val & 0xffff0000) >> 16; - return spu_write(card, reg, (u8 *)&out, sizeof(u32)); + buff = cpu_to_le16(val); + return spu_write(card, reg, (u8 *)&buff, sizeof(u16)); } static inline int spu_reg_is_port_reg(u16 reg) @@ -195,10 +186,13 @@ static inline int spu_reg_is_port_reg(u16 reg) static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) { - unsigned int i, delay; + unsigned int delay; int err = 0; - u16 zero = 0; - u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK; + u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK); + struct spi_message m; + struct spi_transfer reg_trans; + struct spi_transfer dummy_trans; + struct spi_transfer data_trans; /* You must take an even number of bytes from the SPU, even if you * don't care about the last one. */ @@ -206,29 +200,34 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) spu_transaction_init(card); + spi_message_init(&m); + memset(®_trans, 0, sizeof(reg_trans)); + memset(&dummy_trans, 0, sizeof(dummy_trans)); + memset(&data_trans, 0, sizeof(data_trans)); + /* write SPU register index */ - err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); - if (err) - goto out; + reg_trans.tx_buf = ®_out; + reg_trans.len = sizeof(reg_out); + spi_message_add_tail(®_trans, &m); delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay : card->spu_reg_delay; if (card->use_dummy_writes) { /* Clock in dummy cycles while the SPU fills the FIFO */ - for (i = 0; i < delay / 16; ++i) { - err = spi_write(card->spi, (u8 *)&zero, sizeof(u16)); - if (err) - return err; - } + dummy_trans.len = delay / 8; + spi_message_add_tail(&dummy_trans, &m); } else { /* Busy-wait while the SPU fills the FIFO */ - ndelay(100 + (delay * 10)); + reg_trans.delay_usecs = + DIV_ROUND_UP((100 + (delay * 10)), 1000); } /* read in data */ - err = spi_read(card->spi, buf, len); + data_trans.rx_buf = buf; + data_trans.len = len; + spi_message_add_tail(&data_trans, &m); -out: + err = spi_sync(card->spi, &m); spu_transaction_finish(card); return err; } @@ -236,18 +235,25 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) /* Read 16 bits from an SPI register */ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) { - return spu_read(card, reg, (u8 *)val, sizeof(u16)); + u16 buf; + int ret; + + ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); + if (ret == 0) + *val = le16_to_cpup(&buf); + return ret; } /* Read 32 bits from an SPI register. * The low 16 bits are read first. */ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) { - u16 buf[2]; + u32 buf; int err; - err = spu_read(card, reg, (u8 *)buf, sizeof(u32)); + + err = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); if (!err) - *val = buf[0] | (buf[1] << 16); + *val = le32_to_cpup(&buf); return err; } @@ -731,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 %u\n", + "our maximum skb size is %lu\n", __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); err = -EINVAL; goto out; @@ -814,6 +820,13 @@ static void if_spi_e2h(struct if_spi_card *card) if (err) goto out; + /* re-enable the card event interrupt */ + spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, + ~IF_SPI_HICU_CARD_EVENT); + + /* generate a card interrupt */ + spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT); + spin_lock_irqsave(&priv->driver_lock, flags); lbs_queue_event(priv, cause & 0xff); spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1020,6 +1033,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) struct libertas_spi_platform_data *pdata = spi->dev.platform_data; int err = 0; u32 scratch; + struct sched_param param = { .sched_priority = 1 }; lbs_deb_enter(LBS_DEB_SPI); @@ -1043,7 +1057,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, card); card->pdata = pdata; card->spi = spi; - card->gpio_cs = pdata->gpio_cs; card->prev_xfer_time = jiffies; sema_init(&card->spi_ready, 0); @@ -1052,26 +1065,18 @@ static int __devinit if_spi_probe(struct spi_device *spi) INIT_LIST_HEAD(&card->data_packet_list); spin_lock_init(&card->buffer_lock); - /* set up GPIO CS line. TODO: use regular CS line */ - err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select"); - if (err) - goto free_card; - err = gpio_direction_output(card->gpio_cs, 1); - if (err) - goto free_gpio; - /* Initialize the SPI Interface Unit */ err = spu_init(card, pdata->use_dummy_writes); if (err) - goto free_gpio; + goto free_card; err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); if (err) - goto free_gpio; + goto free_card; /* Firmware load */ err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); if (err) - goto free_gpio; + goto free_card; if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) lbs_deb_spi("Firmware is already loaded for " "Marvell WLAN 802.11 adapter\n"); @@ -1079,7 +1084,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) err = if_spi_calculate_fw_names(card->card_id, card->helper_fw_name, card->main_fw_name); if (err) - goto free_gpio; + goto free_card; lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " "(chip_id = 0x%04x, chip_rev = 0x%02x) " @@ -1090,23 +1095,23 @@ static int __devinit if_spi_probe(struct spi_device *spi) spi->max_speed_hz); err = if_spi_prog_helper_firmware(card); if (err) - goto free_gpio; + goto free_card; err = if_spi_prog_main_firmware(card); if (err) - goto free_gpio; + goto free_card; lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); } err = spu_set_interrupt_mode(card, 0, 1); if (err) - goto free_gpio; + goto free_card; /* Register our card with libertas. * This will call alloc_etherdev */ priv = lbs_add_card(card, &spi->dev); if (!priv) { err = -ENOMEM; - goto free_gpio; + goto free_card; } card->priv = priv; priv->card = card; @@ -1123,6 +1128,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) lbs_pr_err("error creating SPI thread: err=%d\n", err); goto remove_card; } + if (sched_setscheduler(card->spi_thread, SCHED_FIFO, ¶m)) + lbs_pr_err("Error setting scheduler, using default.\n"); + err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); if (err) { @@ -1148,8 +1156,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) if_spi_terminate_spi_thread(card); remove_card: lbs_remove_card(priv); /* will call free_netdev */ -free_gpio: - gpio_free(card->gpio_cs); free_card: free_if_spi_card(card); out: @@ -1170,7 +1176,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) free_irq(spi->irq, card); if_spi_terminate_spi_thread(card); lbs_remove_card(priv); /* will call free_netdev */ - gpio_free(card->gpio_cs); 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 ea3dc038be76..d649caebf08a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -686,8 +686,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, return; } - if (!in_interrupt()) - BUG(); + BUG_ON(!in_interrupt()); spin_lock(&priv->driver_lock); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8ae935ac32f1..89575e448015 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1307,8 +1307,10 @@ int lbs_start_card(struct lbs_private *priv) lbs_update_channel(priv); - /* 5.0.16p0 is known to NOT support any mesh */ - if (priv->fwrelease > 0x05001000) { + /* Check mesh FW version and appropriately send the mesh start + * command + */ + if (priv->mesh_fw_ver == MESH_FW_OLD) { /* Enable mesh, if supported, and work out which TLV it uses. 0x100 + 291 is an unofficial value used in 5.110.20.pXX 0x100 + 37 is the official value used in 5.110.21.pXX @@ -1322,27 +1324,35 @@ int lbs_start_card(struct lbs_private *priv) It's just that 5.110.20.pXX will not have done anything useful */ - priv->mesh_tlv = 0x100 + 291; + priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->curbssparams.channel)) { - priv->mesh_tlv = 0x100 + 37; + priv->mesh_tlv = TLV_TYPE_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->curbssparams.channel)) priv->mesh_tlv = 0; } - if (priv->mesh_tlv) { - lbs_add_mesh(priv); + } else if (priv->mesh_fw_ver == MESH_FW_NEW) { + /* 10.0.0.pXX new firmwares should succeed with TLV + * 0x100+37; Do not invoke command with old TLV. + */ + priv->mesh_tlv = TLV_TYPE_MESH_ID; + if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, + priv->curbssparams.channel)) + priv->mesh_tlv = 0; + } + if (priv->mesh_tlv) { + lbs_add_mesh(priv); - if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) - lbs_pr_err("cannot register lbs_mesh attribute\n"); + if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) + lbs_pr_err("cannot register lbs_mesh attribute\n"); - /* While rtap isn't related to mesh, only mesh-enabled - * firmware implements the rtap functionality via - * CMD_802_11_MONITOR_MODE. - */ - if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) - lbs_pr_err("cannot register lbs_rtap attribute\n"); - } + /* While rtap isn't related to mesh, only mesh-enabled + * firmware implements the rtap functionality via + * CMD_802_11_MONITOR_MODE. + */ + if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) + lbs_pr_err("cannot register lbs_rtap attribute\n"); } lbs_debugfs_init_one(priv, dev); diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 8e669775cb5d..65f02cc6752f 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -25,7 +25,6 @@ struct rfc1042hdr { } __attribute__ ((packed)); struct rxpackethdr { - struct rxpd rx_pd; struct eth803hdr eth803_hdr; struct rfc1042hdr rfc1042_hdr; } __attribute__ ((packed)); @@ -158,10 +157,18 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) if (priv->monitormode) return process_rxed_802_11_packet(priv, skb); - p_rx_pkt = (struct rxpackethdr *) skb->data; - p_rx_pd = &p_rx_pkt->rx_pd; - if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME)) - dev = priv->mesh_dev; + p_rx_pd = (struct rxpd *) skb->data; + p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + + le32_to_cpu(p_rx_pd->pkt_ptr)); + if (priv->mesh_dev) { + if (priv->mesh_fw_ver == MESH_FW_OLD) { + if (p_rx_pd->rx_control & RxPD_MESH_FRAME) + dev = priv->mesh_dev; + } else if (priv->mesh_fw_ver == MESH_FW_NEW) { + if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID) + dev = priv->mesh_dev; + } + } lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min_t(unsigned int, skb->len, 100)); @@ -174,20 +181,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) goto done; } - /* - * Check rxpd status and update 802.3 stat, - */ - if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { - lbs_deb_rx("rx err: frame received with bad status\n"); - lbs_pr_alert("rxpd not ok\n"); - dev->stats.rx_errors++; - ret = 0; - dev_kfree_skb(skb); - goto done; - } - - lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", - skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); + lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n", + skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr), + skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr)); lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, sizeof(p_rx_pkt->eth803_hdr.dest_addr)); @@ -221,14 +217,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header * that was removed */ - hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt; + hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; } else { lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", (u8 *) & p_rx_pkt->rfc1042_hdr, sizeof(p_rx_pkt->rfc1042_hdr)); /* Chop off the rxpd */ - hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt; + hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd; } /* Chop off the leading header bytes so the skb points to the start of @@ -334,14 +330,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, goto done; } - /* - * Check rxpd status and update 802.3 stat, - */ - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { - //lbs_deb_rx("rx err: frame received with bad status\n"); - dev->stats.rx_errors++; - } - lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); @@ -353,8 +341,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, radiotap_hdr.hdr.it_pad = 0; radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr)); radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT); - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) - radiotap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS; radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate); /* XXX must check no carryout */ radiotap_hdr.antsignal = prxpd->snr + prxpd->nf; diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 8124db36aaff..601b54249677 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -27,12 +27,12 @@ + 40) /* 40 for WPAIE */ //! Memory needed to store a max sized channel List TLV for a firmware scan -#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvlietypesheader) \ +#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvl_ie_header) \ + (MRVDRV_MAX_CHANNELS_PER_SCAN \ * sizeof(struct chanscanparamset))) //! Memory needed to store a max number/size SSID TLV for a firmware scan -#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) +#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvl_ie_ssid_param_set)) //! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max #define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ @@ -211,7 +211,7 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, */ static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) { - struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; + struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv; ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); @@ -249,7 +249,7 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, int chan_count) { size_t size = sizeof(struct chanscanparamset) *chan_count; - struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv; + struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv; chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); memcpy(chan_tlv->chanscanparam, chan_list, size); @@ -270,7 +270,7 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, static int lbs_scan_add_rates_tlv(uint8_t *tlv) { int i; - struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv; + struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); tlv += sizeof(rate_tlv->header); @@ -513,12 +513,12 @@ void lbs_scan_worker(struct work_struct *work) static int lbs_process_bss(struct bss_descriptor *bss, uint8_t **pbeaconinfo, int *bytesleft) { - struct ieeetypes_fhparamset *pFH; - struct ieeetypes_dsparamset *pDS; - struct ieeetypes_cfparamset *pCF; - struct ieeetypes_ibssparamset *pibss; + struct ieee_ie_fh_param_set *fh; + struct ieee_ie_ds_param_set *ds; + struct ieee_ie_cf_param_set *cf; + struct ieee_ie_ibss_param_set *ibss; DECLARE_SSID_BUF(ssid); - struct ieeetypes_countryinfoset *pcountryinfo; + struct ieee_ie_country_info_set *pcountryinfo; uint8_t *pos, *end, *p; uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; uint16_t beaconsize = 0; @@ -616,50 +616,49 @@ static int lbs_process_bss(struct bss_descriptor *bss, break; case WLAN_EID_FH_PARAMS: - pFH = (struct ieeetypes_fhparamset *) pos; - memmove(&bss->phyparamset.fhparamset, pFH, - sizeof(struct ieeetypes_fhparamset)); + fh = (struct ieee_ie_fh_param_set *) pos; + memcpy(&bss->phy.fh, fh, sizeof(*fh)); lbs_deb_scan("got FH IE\n"); break; case WLAN_EID_DS_PARAMS: - pDS = (struct ieeetypes_dsparamset *) pos; - bss->channel = pDS->currentchan; - memcpy(&bss->phyparamset.dsparamset, pDS, - sizeof(struct ieeetypes_dsparamset)); + ds = (struct ieee_ie_ds_param_set *) pos; + bss->channel = ds->channel; + memcpy(&bss->phy.ds, ds, sizeof(*ds)); lbs_deb_scan("got DS IE, channel %d\n", bss->channel); break; case WLAN_EID_CF_PARAMS: - pCF = (struct ieeetypes_cfparamset *) pos; - memcpy(&bss->ssparamset.cfparamset, pCF, - sizeof(struct ieeetypes_cfparamset)); + cf = (struct ieee_ie_cf_param_set *) pos; + memcpy(&bss->ss.cf, cf, sizeof(*cf)); lbs_deb_scan("got CF IE\n"); break; case WLAN_EID_IBSS_PARAMS: - pibss = (struct ieeetypes_ibssparamset *) pos; - bss->atimwindow = le16_to_cpu(pibss->atimwindow); - memmove(&bss->ssparamset.ibssparamset, pibss, - sizeof(struct ieeetypes_ibssparamset)); + ibss = (struct ieee_ie_ibss_param_set *) pos; + bss->atimwindow = ibss->atimwindow; + memcpy(&bss->ss.ibss, ibss, sizeof(*ibss)); lbs_deb_scan("got IBSS IE\n"); break; case WLAN_EID_COUNTRY: - pcountryinfo = (struct ieeetypes_countryinfoset *) pos; + pcountryinfo = (struct ieee_ie_country_info_set *) pos; lbs_deb_scan("got COUNTRY IE\n"); - if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) - || pcountryinfo->len > 254) { - lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n", - pcountryinfo->len, sizeof(pcountryinfo->countrycode)); + if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode) + || pcountryinfo->header.len > 254) { + lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n", + __func__, + pcountryinfo->header.len, + sizeof(pcountryinfo->countrycode)); ret = -1; goto done; } - memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2); + memcpy(&bss->countryinfo, pcountryinfo, + pcountryinfo->header.len + 2); lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", (uint8_t *) pcountryinfo, - (int) (pcountryinfo->len + 2)); + (int) (pcountryinfo->header.len + 2)); break; case WLAN_EID_EXT_SUPP_RATES: @@ -1130,7 +1129,7 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, goto done; } - bytesleft = le16_to_cpu(scanresp->bssdescriptsize); + bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize); lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); scanrespsize = le16_to_cpu(resp->size); diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index f10aa39a6b68..160cfd8311c0 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -132,8 +132,12 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) txpd->tx_packet_length = cpu_to_le16(pkt_len); txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); - if (dev == priv->mesh_dev) - txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); + if (dev == priv->mesh_dev) { + if (priv->mesh_fw_ver == MESH_FW_OLD) + txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); + else if (priv->mesh_fw_ver == MESH_FW_NEW) + txpd->u.bss.bss_num = MESH_IFACE_ID; + } lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index fb7a2d1a2525..99905df65b25 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -8,9 +8,14 @@ #include #include -struct ieeetypes_cfparamset { - u8 elementid; +struct ieee_ie_header { + u8 id; u8 len; +} __attribute__ ((packed)); + +struct ieee_ie_cf_param_set { + struct ieee_ie_header header; + u8 cfpcnt; u8 cfpperiod; __le16 cfpmaxduration; @@ -18,42 +23,35 @@ struct ieeetypes_cfparamset { } __attribute__ ((packed)); -struct ieeetypes_ibssparamset { - u8 elementid; - u8 len; +struct ieee_ie_ibss_param_set { + struct ieee_ie_header header; + __le16 atimwindow; } __attribute__ ((packed)); -union IEEEtypes_ssparamset { - struct ieeetypes_cfparamset cfparamset; - struct ieeetypes_ibssparamset ibssparamset; +union ieee_ss_param_set { + struct ieee_ie_cf_param_set cf; + struct ieee_ie_ibss_param_set ibss; } __attribute__ ((packed)); -struct ieeetypes_fhparamset { - u8 elementid; - u8 len; +struct ieee_ie_fh_param_set { + struct ieee_ie_header header; + __le16 dwelltime; u8 hopset; u8 hoppattern; u8 hopindex; } __attribute__ ((packed)); -struct ieeetypes_dsparamset { - u8 elementid; - u8 len; - u8 currentchan; +struct ieee_ie_ds_param_set { + struct ieee_ie_header header; + + u8 channel; } __attribute__ ((packed)); -union ieeetypes_phyparamset { - struct ieeetypes_fhparamset fhparamset; - struct ieeetypes_dsparamset dsparamset; -} __attribute__ ((packed)); - -struct ieeetypes_assocrsp { - __le16 capability; - __le16 statuscode; - __le16 aid; - u8 iebuffer[1]; +union ieee_phy_param_set { + struct ieee_ie_fh_param_set fh; + struct ieee_ie_ds_param_set ds; } __attribute__ ((packed)); /** TLV type ID definition */ @@ -94,30 +92,33 @@ struct ieeetypes_assocrsp { #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) #define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) +#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) +#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) +#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) /** TLV related data structures*/ -struct mrvlietypesheader { +struct mrvl_ie_header { __le16 type; __le16 len; } __attribute__ ((packed)); -struct mrvlietypes_data { - struct mrvlietypesheader header; +struct mrvl_ie_data { + struct mrvl_ie_header header; u8 Data[1]; } __attribute__ ((packed)); -struct mrvlietypes_ratesparamset { - struct mrvlietypesheader header; +struct mrvl_ie_rates_param_set { + struct mrvl_ie_header header; u8 rates[1]; } __attribute__ ((packed)); -struct mrvlietypes_ssidparamset { - struct mrvlietypesheader header; +struct mrvl_ie_ssid_param_set { + struct mrvl_ie_header header; u8 ssid[1]; } __attribute__ ((packed)); -struct mrvlietypes_wildcardssidparamset { - struct mrvlietypesheader header; +struct mrvl_ie_wildcard_ssid_param_set { + struct mrvl_ie_header header; u8 MaxSsidlength; u8 ssid[1]; } __attribute__ ((packed)); @@ -142,91 +143,72 @@ struct chanscanparamset { __le16 maxscantime; } __attribute__ ((packed)); -struct mrvlietypes_chanlistparamset { - struct mrvlietypesheader header; +struct mrvl_ie_chanlist_param_set { + struct mrvl_ie_header header; struct chanscanparamset chanscanparam[1]; } __attribute__ ((packed)); -struct cfparamset { +struct mrvl_ie_cf_param_set { + struct mrvl_ie_header header; u8 cfpcnt; u8 cfpperiod; __le16 cfpmaxduration; __le16 cfpdurationremaining; } __attribute__ ((packed)); -struct ibssparamset { - __le16 atimwindow; +struct mrvl_ie_ds_param_set { + struct mrvl_ie_header header; + u8 channel; } __attribute__ ((packed)); -struct mrvlietypes_ssparamset { - struct mrvlietypesheader header; - union { - struct cfparamset cfparamset[1]; - struct ibssparamset ibssparamset[1]; - } cf_ibss; -} __attribute__ ((packed)); - -struct fhparamset { - __le16 dwelltime; - u8 hopset; - u8 hoppattern; - u8 hopindex; -} __attribute__ ((packed)); - -struct dsparamset { - u8 currentchan; -} __attribute__ ((packed)); - -struct mrvlietypes_phyparamset { - struct mrvlietypesheader header; - union { - struct fhparamset fhparamset[1]; - struct dsparamset dsparamset[1]; - } fh_ds; -} __attribute__ ((packed)); - -struct mrvlietypes_rsnparamset { - struct mrvlietypesheader header; +struct mrvl_ie_rsn_param_set { + struct mrvl_ie_header header; u8 rsnie[1]; } __attribute__ ((packed)); -struct mrvlietypes_tsftimestamp { - struct mrvlietypesheader header; +struct mrvl_ie_tsf_timestamp { + struct mrvl_ie_header header; __le64 tsftable[1]; } __attribute__ ((packed)); +/* v9 and later firmware only */ +struct mrvl_ie_auth_type { + struct mrvl_ie_header header; + __le16 auth; +} __attribute__ ((packed)); + /** Local Power capability */ -struct mrvlietypes_powercapability { - struct mrvlietypesheader header; +struct mrvl_ie_power_capability { + struct mrvl_ie_header header; s8 minpower; s8 maxpower; } __attribute__ ((packed)); /* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */ -struct mrvlietypes_thresholds { - struct mrvlietypesheader header; +struct mrvl_ie_thresholds { + struct mrvl_ie_header header; u8 value; u8 freq; } __attribute__ ((packed)); -struct mrvlietypes_beaconsmissed { - struct mrvlietypesheader header; +struct mrvl_ie_beacons_missed { + struct mrvl_ie_header header; u8 beaconmissed; u8 reserved; } __attribute__ ((packed)); -struct mrvlietypes_numprobes { - struct mrvlietypesheader header; +struct mrvl_ie_num_probes { + struct mrvl_ie_header header; __le16 numprobes; } __attribute__ ((packed)); -struct mrvlietypes_bcastprobe { - struct mrvlietypesheader header; +struct mrvl_ie_bcast_probe { + struct mrvl_ie_header header; __le16 bcastprobe; } __attribute__ ((packed)); -struct mrvlietypes_numssidprobe { - struct mrvlietypesheader header; +struct mrvl_ie_num_ssid_probe { + struct mrvl_ie_header header; __le16 numssidprobe; } __attribute__ ((packed)); @@ -235,8 +217,8 @@ struct led_pin { u8 pin; } __attribute__ ((packed)); -struct mrvlietypes_ledgpio { - struct mrvlietypesheader header; +struct mrvl_ie_ledgpio { + struct mrvl_ie_header header; struct led_pin ledpin[1]; } __attribute__ ((packed)); @@ -248,8 +230,8 @@ struct led_bhv { } __attribute__ ((packed)); -struct mrvlietypes_ledbhv { - struct mrvlietypesheader header; +struct mrvl_ie_ledbhv { + struct mrvl_ie_header header; struct led_bhv ledbhv[1]; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 59634c33b1f9..392337b37b1d 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -461,8 +461,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, return; } - if (!in_interrupt()) - BUG(); + BUG_ON(!in_interrupt()); spin_lock(&priv->driver_lock); memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN, diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index e7289e2e7f16..10a99e26d392 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -366,36 +366,6 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) return 0; } -static int lbtf_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct lbtf_private *priv = hw->priv; - struct sk_buff *beacon; - - switch (priv->vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - beacon = ieee80211_beacon_get(hw, vif); - if (beacon) { - lbtf_beacon_set(priv, beacon); - kfree_skb(beacon); - lbtf_beacon_ctrl(priv, 1, hw->conf.beacon_int); - } - break; - default: - break; - } - - if (conf->bssid) { - u8 null_bssid[ETH_ALEN] = {0}; - bool activate = compare_ether_addr(conf->bssid, null_bssid); - lbtf_set_bssid(priv, activate, conf->bssid); - } - - return 0; -} - #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) static void lbtf_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, @@ -451,6 +421,29 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct lbtf_private *priv = hw->priv; + struct sk_buff *beacon; + + if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) { + switch (priv->vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + beacon = ieee80211_beacon_get(hw, vif); + if (beacon) { + lbtf_beacon_set(priv, beacon); + kfree_skb(beacon); + lbtf_beacon_ctrl(priv, 1, + bss_conf->beacon_int); + } + break; + default: + break; + } + } + + if (changes & BSS_CHANGED_BSSID) { + bool activate = !is_zero_ether_addr(bss_conf->bssid); + lbtf_set_bssid(priv, activate, bss_conf->bssid); + } if (changes & BSS_CHANGED_ERP_PREAMBLE) { if (bss_conf->use_short_preamble) @@ -459,8 +452,6 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, priv->preamble = CMD_TYPE_LONG_PREAMBLE; lbtf_set_radio_control(priv); } - - return; } static const struct ieee80211_ops lbtf_ops = { @@ -470,7 +461,6 @@ static const struct ieee80211_ops lbtf_ops = { .add_interface = lbtf_op_add_interface, .remove_interface = lbtf_op_remove_interface, .config = lbtf_op_config, - .config_interface = lbtf_op_config_interface, .configure_filter = lbtf_op_configure_filter, .bss_info_changed = lbtf_op_bss_info_changed, }; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index d4fdc8b7d7d8..e789c6e9938c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -280,7 +280,6 @@ struct mac80211_hwsim_data { struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; struct ieee80211_channel *channel; - int radio_enabled; unsigned long beacon_int; /* in jiffies unit */ unsigned int rx_filter; int started; @@ -291,6 +290,14 @@ struct mac80211_hwsim_data { bool ps_poll_pending; struct dentry *debugfs; struct dentry *debugfs_ps; + + /* + * Only radios in the same group can communicate together (the + * channel has to match too). Each bit represents a group. A + * radio can be in more then one group. + */ + u64 group; + struct dentry *debugfs_group; }; @@ -410,9 +417,9 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, if (data == data2) continue; - if (!data2->started || !data2->radio_enabled || - !hwsim_ps_rx_ok(data2, skb) || - data->channel->center_freq != data2->channel->center_freq) + if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || + data->channel->center_freq != data2->channel->center_freq || + !(data->group & data2->group)) continue; nskb = skb_copy(skb, GFP_ATOMIC); @@ -432,7 +439,6 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct mac80211_hwsim_data *data = hw->priv; bool ack; struct ieee80211_tx_info *txi; @@ -444,13 +450,6 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } - if (!data->radio_enabled) { - printk(KERN_DEBUG "%s: dropped TX frame since radio " - "disabled\n", wiphy_name(hw->wiphy)); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - ack = mac80211_hwsim_tx_frame(hw, skb); txi = IEEE80211_SKB_CB(skb); @@ -537,7 +536,7 @@ static void mac80211_hwsim_beacon(unsigned long arg) struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; struct mac80211_hwsim_data *data = hw->priv; - if (!data->started || !data->radio_enabled) + if (!data->started) return; ieee80211_iterate_active_interfaces_atomic( @@ -553,18 +552,14 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) struct mac80211_hwsim_data *data = hw->priv; struct ieee80211_conf *conf = &hw->conf; - printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n", + printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n", wiphy_name(hw->wiphy), __func__, - conf->channel->center_freq, conf->radio_enabled, - conf->beacon_int); + conf->channel->center_freq, + !!(conf->flags & IEEE80211_CONF_IDLE), + !!(conf->flags & IEEE80211_CONF_PS)); data->channel = conf->channel; - data->radio_enabled = conf->radio_enabled; - data->beacon_int = 1024 * conf->beacon_int / 1000 * HZ / 1000; - if (data->beacon_int < 1) - data->beacon_int = 1; - - if (!data->started || !data->radio_enabled) + if (!data->started || !data->beacon_int) del_timer(&data->beacon_timer); else mod_timer(&data->beacon_timer, jiffies + data->beacon_int); @@ -592,35 +587,26 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, *total_flags = data->rx_filter; } -static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - - hwsim_check_magic(vif); - if (conf->changed & IEEE80211_IFCC_BSSID) { - DECLARE_MAC_BUF(mac); - printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", - wiphy_name(hw->wiphy), __func__, - conf->bssid); - memcpy(vp->bssid, conf->bssid, ETH_ALEN); - } - return 0; -} - static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { struct hwsim_vif_priv *vp = (void *)vif->drv_priv; + struct mac80211_hwsim_data *data = hw->priv; hwsim_check_magic(vif); printk(KERN_DEBUG "%s:%s(changed=0x%x)\n", wiphy_name(hw->wiphy), __func__, changed); + if (changed & BSS_CHANGED_BSSID) { + printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", + wiphy_name(hw->wiphy), __func__, + info->bssid); + memcpy(vp->bssid, info->bssid, ETH_ALEN); + } + if (changed & BSS_CHANGED_ASSOC) { printk(KERN_DEBUG " %s: ASSOC: assoc=%d aid=%d\n", wiphy_name(hw->wiphy), info->assoc, info->aid); @@ -628,6 +614,14 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, vp->aid = info->aid; } + if (changed & BSS_CHANGED_BEACON_INT) { + printk(KERN_DEBUG " %s: BCNINT: %d\n", + wiphy_name(hw->wiphy), info->beacon_int); + data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; + if (WARN_ON(!data->beacon_int)) + data->beacon_int = 1; + } + if (changed & BSS_CHANGED_ERP_CTS_PROT) { printk(KERN_DEBUG " %s: ERP_CTS_PROT: %d\n", wiphy_name(hw->wiphy), info->use_cts_prot); @@ -646,7 +640,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_HT) { printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", wiphy_name(hw->wiphy), - info->ht.operation_mode); + info->ht_operation_mode); } if (changed & BSS_CHANGED_BASIC_RATES) { @@ -704,7 +698,6 @@ static const struct ieee80211_ops mac80211_hwsim_ops = .remove_interface = mac80211_hwsim_remove_interface, .config = mac80211_hwsim_config, .configure_filter = mac80211_hwsim_configure_filter, - .config_interface = mac80211_hwsim_config_interface, .bss_info_changed = mac80211_hwsim_bss_info_changed, .sta_notify = mac80211_hwsim_sta_notify, .set_tim = mac80211_hwsim_set_tim, @@ -725,6 +718,7 @@ static void mac80211_hwsim_free(void) spin_unlock_bh(&hwsim_radio_lock); list_for_each_entry(data, &tmplist, list) { + debugfs_remove(data->debugfs_group); debugfs_remove(data->debugfs_ps); debugfs_remove(data->debugfs); ieee80211_unregister_hw(data->hw); @@ -782,8 +776,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) pspoll->aid = cpu_to_le16(0xc000 | vp->aid); memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); memcpy(pspoll->ta, mac, ETH_ALEN); - if (data->radio_enabled && - !mac80211_hwsim_tx_frame(data->hw, skb)) + if (!mac80211_hwsim_tx_frame(data->hw, skb)) printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__); dev_kfree_skb(skb); } @@ -814,8 +807,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, memcpy(hdr->addr1, vp->bssid, ETH_ALEN); memcpy(hdr->addr2, mac, ETH_ALEN); memcpy(hdr->addr3, vp->bssid, ETH_ALEN); - if (data->radio_enabled && - !mac80211_hwsim_tx_frame(data->hw, skb)) + if (!mac80211_hwsim_tx_frame(data->hw, skb)) printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__); dev_kfree_skb(skb); } @@ -877,6 +869,24 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, "%llu\n"); +static int hwsim_fops_group_read(void *dat, u64 *val) +{ + struct mac80211_hwsim_data *data = dat; + *val = data->group; + return 0; +} + +static int hwsim_fops_group_write(void *dat, u64 val) +{ + struct mac80211_hwsim_data *data = dat; + data->group = val; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, + hwsim_fops_group_read, hwsim_fops_group_write, + "%llx\n"); + static int __init init_mac80211_hwsim(void) { int i, err = 0; @@ -981,6 +991,8 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->bands[band] = sband; } + /* By default all radios are belonging to the first group */ + data->group = 1; /* Work to be done prior to ieee80211_register_hw() */ switch (regtest) { @@ -1105,6 +1117,9 @@ static int __init init_mac80211_hwsim(void) data->debugfs_ps = debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); + data->debugfs_group = debugfs_create_file("group", 0666, + data->debugfs, data, + &hwsim_fops_group); setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, (unsigned long) hw); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a9a970469c2a..a263d5c84c08 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2369,7 +2369,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, if (info->use_cts_prot) { prot_mode = MWL8K_FRAME_PROT_11G; } else { - switch (info->ht.operation_mode & + switch (info->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) { case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; @@ -3089,19 +3089,6 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) return rc ? -EINVAL : 0; } -static int mwl8k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - u32 changed = conf->changed; - - if (changed & IEEE80211_IFCC_BSSID) - memcpy(mv_vif->bssid, conf->bssid, IEEE80211_ADDR_LEN); - - return 0; -} - struct mwl8k_bss_info_changed_worker { struct mwl8k_work_struct header; struct ieee80211_vif *vif; @@ -3183,8 +3170,12 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, { struct mwl8k_bss_info_changed_worker *worker; struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); int rc; + if (changed & BSS_CHANGED_BSSID) + memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN); + if ((changed & BSS_CHANGED_ASSOC) == 0) return; @@ -3442,7 +3433,6 @@ static const struct ieee80211_ops mwl8k_ops = { .add_interface = mwl8k_add_interface, .remove_interface = mwl8k_remove_interface, .config = mwl8k_config, - .config_interface = mwl8k_config_interface, .bss_info_changed = mwl8k_bss_info_changed, .configure_filter = mwl8k_configure_filter, .set_rts_threshold = mwl8k_set_rts_threshold, diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index ecf8b6ed5a47..db3df947d8ed 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -125,6 +125,7 @@ struct p54_led_dev { struct led_classdev led_dev; char name[P54_LED_MAX_NAME_LEN + 1]; + unsigned int toggled; unsigned int index; unsigned int registered; }; @@ -133,55 +134,74 @@ struct p54_led_dev { struct p54_common { struct ieee80211_hw *hw; - u32 rx_start; - u32 rx_end; - struct sk_buff_head tx_queue; + struct ieee80211_vif *vif; void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb); int (*open)(struct ieee80211_hw *dev); void (*stop)(struct ieee80211_hw *dev); - int mode; + struct sk_buff_head tx_queue; + struct mutex conf_mutex; + + /* memory management (as seen by the firmware) */ + u32 rx_start; + u32 rx_end; u16 rx_mtu; u8 headroom; u8 tailroom; - struct mutex conf_mutex; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u8 rx_diversity_mask; - u8 tx_diversity_mask; - struct pda_iq_autocal_entry *iq_autocal; - unsigned int iq_autocal_len; - struct p54_cal_database *output_limit; - struct p54_cal_database *curve_data; - struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; - unsigned int filter_flags; - bool use_short_slot; - u16 rxhw; - u8 version; + + /* firmware/hardware info */ unsigned int tx_hdr_len; unsigned int fw_var; unsigned int fw_interface; - unsigned int output_power; - u32 tsf_low32; - u32 tsf_high32; - u32 basic_rate_mask; - u16 wakeup_timer; - u16 aid; + u8 version; + + /* (e)DCF / QOS state */ + bool use_short_slot; struct ieee80211_tx_queue_stats tx_stats[8]; struct p54_edcf_queue_param qos_params[8]; - struct ieee80211_low_level_stats stats; - struct delayed_work work; - struct sk_buff *cached_beacon; + + /* Radio data */ + u16 rxhw; + u8 rx_diversity_mask; + u8 tx_diversity_mask; + unsigned int output_power; int noise; - void *eeprom; - struct completion eeprom_comp; + /* calibration, output power limit and rssi<->dBm conversation data */ + struct pda_iq_autocal_entry *iq_autocal; + unsigned int iq_autocal_len; + struct p54_cal_database *curve_data; + struct p54_cal_database *output_limit; + struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; + + /* BBP/MAC state */ + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u16 wakeup_timer; + unsigned int filter_flags; + int mode; + u32 tsf_low32, tsf_high32; + u32 basic_rate_mask; + u16 aid; + struct sk_buff *cached_beacon; + + /* cryptographic engine information */ u8 privacy_caps; u8 rx_keycache_size; + unsigned long *used_rxkeys; + /* LED management */ #ifdef CONFIG_P54_LEDS - struct p54_led_dev assoc_led; - struct p54_led_dev tx_led; + struct p54_led_dev leds[4]; + struct delayed_work led_work; #endif /* CONFIG_P54_LEDS */ u16 softled_state; /* bit field of glowing LEDs */ + + /* statistics */ + struct ieee80211_low_level_stats stats; + struct delayed_work work; + + /* eeprom handling */ + void *eeprom; + struct completion eeprom_comp; }; int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c8f0232ee5e0..b618bd14583f 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -249,7 +249,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) dev->queues = P54_QUEUE_AC_NUM; } - if (!modparam_nohwcrypt) + if (!modparam_nohwcrypt) { printk(KERN_INFO "%s: cryptographic accelerator " "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(dev->wiphy), @@ -259,6 +259,26 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) (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); @@ -749,8 +769,6 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi); rx_status.noise = priv->noise; - /* XX correct? */ - rx_status.qual = (100 * hdr->rssi) / 127; if (hdr->rate & 0x10) rx_status.flag |= RX_FLAG_SHORTPRE; if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) @@ -804,44 +822,37 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_tx_info *info; struct p54_tx_info *range; unsigned long flags; - u32 freed = 0, last_addr = priv->rx_start; - if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) + if (unlikely(!skb || !dev || skb_queue_empty(&priv->tx_queue))) return; - /* - * don't try to free an already unlinked skb + /* There used to be a check here to see if the SKB was on the + * TX queue or not. This can never happen because all SKBs we + * see here successfully went through p54_assign_address() + * which means the SKB is on the ->tx_queue. */ - 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) { + if (!skb_queue_is_first(&priv->tx_queue, skb)) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb->prev); + ni = IEEE80211_SKB_CB(skb_queue_prev(&priv->tx_queue, skb)); mr = (struct p54_tx_info *)ni->rate_driver_data; - last_addr = mr->end_addr; } - if (skb->next != (struct sk_buff *)&priv->tx_queue) { + if (!skb_queue_is_last(&priv->tx_queue, skb)) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb->next); + ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, skb)); mr = (struct p54_tx_info *)ni->rate_driver_data; - freed = mr->start_addr - last_addr; - } else - freed = priv->rx_end - last_addr; + } __skb_unlink(skb, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); dev_kfree_skb_any(skb); - - if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 + - IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom) - p54_wake_free_queues(dev); + p54_wake_free_queues(dev); } EXPORT_SYMBOL_GPL(p54_free_skb); @@ -853,15 +864,13 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev, unsigned long flags; spin_lock_irqsave(&priv->tx_queue.lock, flags); - entry = priv->tx_queue.next; - while (entry != (struct sk_buff *)&priv->tx_queue) { + skb_queue_walk(&priv->tx_queue, entry) { 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; @@ -875,37 +884,29 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct sk_buff *entry; u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom; struct p54_tx_info *range = NULL; - u32 freed = 0; - u32 last_addr = priv->rx_start; 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) { + skb_queue_walk(&priv->tx_queue, entry) { 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) { - last_addr = range->end_addr; - entry = entry->next; + if (range->start_addr != addr) continue; - } - if (entry->next != (struct sk_buff *)&priv->tx_queue) { + if (!skb_queue_is_last(&priv->tx_queue, entry)) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(entry->next); + ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, + entry)); mr = (struct p54_tx_info *)ni->rate_driver_data; - freed = mr->start_addr - last_addr; - } else - freed = priv->rx_end - last_addr; + } - last_addr = range->end_addr; __skb_unlink(entry, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); @@ -992,9 +993,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) spin_unlock_irqrestore(&priv->tx_queue.lock, flags); out: - if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 + - IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom) - p54_wake_free_queues(dev); + p54_wake_free_queues(dev); } static void p54_rx_eeprom_readback(struct ieee80211_hw *dev, @@ -1044,6 +1043,7 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb) 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); @@ -1057,6 +1057,8 @@ static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) 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; @@ -1162,23 +1164,21 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, } } - entry = priv->tx_queue.next; - while (left--) { + 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; + target_skb = skb_queue_prev(&priv->tx_queue, entry); 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; + target_skb = skb_peek_tail(&priv->tx_queue); largest_hole = max(largest_hole, priv->rx_end - last_addr - len); if (!skb_queue_empty(&priv->tx_queue)) { info = IEEE80211_SKB_CB(target_skb); @@ -1452,7 +1452,8 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, if (info->control.sta) *aid = info->control.sta->aid; - else + + if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; break; } @@ -1939,7 +1940,8 @@ static int p54_set_ps(struct ieee80211_hw *dev) int i; if (dev->conf.flags & IEEE80211_CONF_PS) - mode = P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC; + mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | + P54_PSM_CHECKSUM | P54_PSM_MCBC; else mode = P54_PSM_CAM; @@ -1957,9 +1959,10 @@ static int p54_set_ps(struct ieee80211_hw *dev) psm->intervals[i].periods = cpu_to_le16(1); } - psm->beacon_rssi_skip_max = 60; + psm->beacon_rssi_skip_max = 200; psm->rssi_delta_threshold = 0; - psm->nr = 0; + psm->nr = 10; + psm->exclude[0] = 0; priv->tx(dev, skb); @@ -2081,20 +2084,21 @@ static int p54_start(struct ieee80211_hw *dev) 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); + skb_queue_purge(&priv->tx_queue); priv->cached_beacon = NULL; priv->tsf_high32 = priv->tsf_low32 = 0; mutex_unlock(&priv->conf_mutex); @@ -2111,6 +2115,8 @@ static int p54_add_interface(struct ieee80211_hw *dev, return -EOPNOTSUPP; } + priv->vif = conf->vif; + switch (conf->type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: @@ -2135,6 +2141,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev, 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; @@ -2174,41 +2181,6 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) return ret; } -static int p54_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct p54_common *priv = dev->priv; - int ret = 0; - - mutex_lock(&priv->conf_mutex); - if (conf->changed & IEEE80211_IFCC_BSSID) { - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - ret = p54_setup_mac(dev); - if (ret) - goto out; - } - - if (conf->changed & IEEE80211_IFCC_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; - ret = p54_set_edcf(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, @@ -2312,8 +2284,32 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, u32 changed) { struct p54_common *priv = dev->priv; + int ret; - if (changed & BSS_CHANGED_ERP_SLOT) { + 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); } @@ -2334,7 +2330,6 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, p54_setup_mac(dev); } } - } static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, @@ -2344,61 +2339,84 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, 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; - if (cmd == DISABLE_KEY) - algo = 0; - else { + 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))) - return -EOPNOTSUPP; + 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)) - return -EOPNOTSUPP; + 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)) - return -EOPNOTSUPP; + 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: - return -EOPNOTSUPP; + 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 (key->keyidx > priv->rx_keycache_size) { - /* - * The device supports the choosen algorithm, but the firmware - * does not provide enough key slots to store all of them. - * So, incoming frames have to be decoded by the mac80211 stack, - * but we can still offload encryption for outgoing frames. - */ - - return 0; - } - - mutex_lock(&priv->conf_mutex); skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey), - P54_CONTROL_TYPE_RX_KEYCACHE, GFP_ATOMIC); + P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL); if (!skb) { - mutex_unlock(&priv->conf_mutex); - return -ENOMEM; + bitmap_release_region(priv->used_rxkeys, slot, 0); + ret = -ENOSPC; + goto out_unlock; } - /* TODO: some devices have 4 more free slots for rx keys */ rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey)); - rxkey->entry = key->keyidx; + rxkey->entry = slot; rxkey->key_id = key->keyidx; rxkey->key_type = algo; if (sta) @@ -2416,11 +2434,51 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, } priv->tx(dev, skb); + key->hw_key_idx = slot; + +out_unlock: mutex_unlock(&priv->conf_mutex); - return 0; + 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) { @@ -2428,28 +2486,23 @@ static void p54_led_brightness_set(struct led_classdev *led_dev, led_dev); struct ieee80211_hw *dev = led->hw_dev; struct p54_common *priv = dev->priv; - int err; - /* Don't toggle the LED, when the device is down. */ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) return ; - if (brightness != LED_OFF) - priv->softled_state |= BIT(led->index); - else - priv->softled_state &= ~BIT(led->index); - - err = p54_set_leds(dev); - if (err && net_ratelimit()) - printk(KERN_ERR "%s: failed to update %s LED.\n", - wiphy_name(dev->wiphy), led_dev->name); + if (brightness) { + led->toggled++; + queue_delayed_work(priv->hw->workqueue, &priv->led_work, + HZ/10); + } } static int p54_register_led(struct ieee80211_hw *dev, - struct p54_led_dev *led, 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) @@ -2482,19 +2535,30 @@ static int p54_init_leds(struct ieee80211_hw *dev) * TODO: * Figure out if the EEPROM contains some hints about the number * of available/programmable LEDs of the device. - * But for now, we can assume that we have two programmable LEDs. */ - err = p54_register_led(dev, &priv->assoc_led, 0, "assoc", + 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, &priv->tx_led, 1, "tx", + 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; } @@ -2502,11 +2566,11 @@ static int p54_init_leds(struct ieee80211_hw *dev) static void p54_unregister_leds(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; + int i; - if (priv->tx_led.registered) - led_classdev_unregister(&priv->tx_led.led_dev); - if (priv->assoc_led.registered) - led_classdev_unregister(&priv->assoc_led.led_dev); + 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 */ @@ -2520,7 +2584,6 @@ static const struct ieee80211_ops p54_ops = { .sta_notify = p54_sta_notify, .set_key = p54_set_key, .config = p54_config, - .config_interface = p54_config_interface, .bss_info_changed = p54_bss_info_changed, .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, @@ -2607,21 +2670,10 @@ void p54_free_common(struct ieee80211_hw *dev) 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); - -static int __init p54_init(void) -{ - return 0; -} - -static void __exit p54_exit(void) -{ -} - -module_init(p54_init); -module_exit(p54_exit); diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index d1fe577de3d4..83116baeb110 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -96,7 +96,7 @@ static void p54spi_spi_write(struct p54s_priv *priv, u8 address, spi_message_add_tail(&t[0], &m); t[1].tx_buf = buf; - t[1].len = len; + t[1].len = len & ~1; spi_message_add_tail(&t[1], &m); if (len % 2) { @@ -167,18 +167,34 @@ static const struct p54spi_spi_reg p54spi_registers_array[] = static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) { int i; - __le32 buffer; for (i = 0; i < 2000; i++) { - p54spi_spi_read(priv, reg, &buffer, sizeof(buffer)); - if (buffer == bits) + __le32 buffer = p54spi_read32(priv, reg); + if ((buffer & bits) == bits) return 1; - - msleep(1); } return 0; } +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))) { + dev_err(&priv->spi->dev, "spi_write_dma not allowed " + "to DMA write.\n"); + return -EAGAIN; + } + + p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, + cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); + + p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len)); + p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base); + p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len); + return 0; +} + static int p54spi_request_firmware(struct ieee80211_hw *dev) { struct p54s_priv *priv = dev->priv; @@ -228,8 +244,15 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev) static int p54spi_upload_firmware(struct ieee80211_hw *dev) { struct p54s_priv *priv = dev->priv; - unsigned long fw_len, fw_addr; - long _fw_len; + unsigned long fw_len, _fw_len; + unsigned int offset = 0; + int err = 0; + u8 *fw; + + fw_len = priv->firmware->size; + fw = kmemdup(priv->firmware->data, fw_len, GFP_KERNEL); + if (!fw) + return -ENOMEM; /* stop the device */ p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( @@ -244,36 +267,17 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) msleep(TARGET_BOOT_SLEEP); - fw_addr = ISL38XX_DEV_FIRMWARE_ADDR; - fw_len = priv->firmware->size; - while (fw_len > 0) { _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); - p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, - cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); - - if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, - cpu_to_le32(HOST_ALLOWED)) == 0) { - dev_err(&priv->spi->dev, "fw_upload not allowed " - "to DMA write."); - return -EAGAIN; - } - - p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, - cpu_to_le16(_fw_len)); - p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, - cpu_to_le32(fw_addr)); - - p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, - &priv->firmware->data, _fw_len); + err = p54spi_spi_write_dma(priv, cpu_to_le32( + ISL38XX_DEV_FIRMWARE_ADDR + offset), + (fw + offset), _fw_len); + if (err < 0) + goto out; fw_len -= _fw_len; - fw_addr += _fw_len; - - /* FIXME: I think this doesn't work if firmware is large, - * this loop goes to second round. fw->data is not - * increased at all! */ + offset += _fw_len; } BUG_ON(fw_len != 0); @@ -292,7 +296,10 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT)); msleep(TARGET_BOOT_SLEEP); - return 0; + +out: + kfree(fw); + return err; } static void p54spi_power_off(struct p54s_priv *priv) @@ -318,29 +325,21 @@ static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val) p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val)); } -static void p54spi_wakeup(struct p54s_priv *priv) +static int p54spi_wakeup(struct p54s_priv *priv) { - unsigned long timeout; - u32 ints; - /* wake the chip */ p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, cpu_to_le32(SPI_TARGET_INT_WAKEUP)); /* And wait for the READY interrupt */ - timeout = jiffies + HZ; - - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); - while (!(ints & SPI_HOST_INT_READY)) { - if (time_after(jiffies, timeout)) - goto out; - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, + cpu_to_le32(SPI_HOST_INT_READY))) { + dev_err(&priv->spi->dev, "INT_READY timeout\n"); + return -EBUSY; } p54spi_int_ack(priv, SPI_HOST_INT_READY); - -out: - return; + return 0; } static inline void p54spi_sleep(struct p54s_priv *priv) @@ -372,27 +371,48 @@ static int p54spi_rx(struct p54s_priv *priv) { struct sk_buff *skb; u16 len; + u16 rx_head[2]; +#define READAHEAD_SZ (sizeof(rx_head)-sizeof(u16)) - p54spi_wakeup(priv); + if (p54spi_wakeup(priv) < 0) + return -EBUSY; - /* dummy read to flush SPI DMA controller bug */ - p54spi_read16(priv, SPI_ADRS_GEN_PURP_1); - - len = p54spi_read16(priv, SPI_ADRS_DMA_DATA); + /* Read data size and first data word in one SPI transaction + * This is workaround for firmware/DMA bug, + * when first data word gets lost under high load. + */ + p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, rx_head, sizeof(rx_head)); + len = rx_head[0]; if (len == 0) { - dev_err(&priv->spi->dev, "rx request of zero bytes"); + p54spi_sleep(priv); + dev_err(&priv->spi->dev, "rx request of zero bytes\n"); return 0; } - skb = dev_alloc_skb(len); + /* Firmware may insert up to 4 padding bytes after the lmac header, + * but it does not amend the size of SPI data transfer. + * Such packets has correct data size in header, thus referencing + * past the end of allocated skb. Reserve extra 4 bytes for this case */ + skb = dev_alloc_skb(len + 4); if (!skb) { + p54spi_sleep(priv); dev_err(&priv->spi->dev, "could not alloc skb"); - return 0; + return -ENOMEM; } - p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); + if (len <= READAHEAD_SZ) { + memcpy(skb_put(skb, len), rx_head + 1, len); + } else { + memcpy(skb_put(skb, READAHEAD_SZ), rx_head + 1, READAHEAD_SZ); + p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, + skb_put(skb, len - READAHEAD_SZ), + len - READAHEAD_SZ); + } p54spi_sleep(priv); + /* Put additional bytes to compensate for the possible + * alignment-caused truncation */ + skb_put(skb, 4); if (p54_rx(priv->hw, skb) == 0) dev_kfree_skb(skb); @@ -414,39 +434,28 @@ static irqreturn_t p54spi_interrupt(int irq, void *config) static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) { struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - struct p54s_dma_regs dma_regs; - unsigned long timeout; int ret = 0; - u32 ints; - p54spi_wakeup(priv); + if (p54spi_wakeup(priv) < 0) + return -EBUSY; - dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE); - dma_regs.len = cpu_to_le16(skb->len); - dma_regs.addr = hdr->req_id; + ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len); + if (ret < 0) + goto out; - p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, - sizeof(dma_regs)); - - p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len); - - timeout = jiffies + 2 * HZ; - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); - while (!(ints & SPI_HOST_INT_WR_READY)) { - if (time_after(jiffies, timeout)) { - dev_err(&priv->spi->dev, "WR_READY timeout"); - ret = -1; - goto out; - } - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, + cpu_to_le32(SPI_HOST_INT_WR_READY))) { + dev_err(&priv->spi->dev, "WR_READY timeout\n"); + ret = -EAGAIN; + goto out; } p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); - p54spi_sleep(priv); -out: if (FREE_AFTER_TX(skb)) p54_free_skb(priv->hw, skb); +out: + p54spi_sleep(priv); return ret; } @@ -516,8 +525,7 @@ static void p54spi_work(struct work_struct *work) mutex_lock(&priv->mutex); - if (priv->fw_state == FW_STATE_OFF && - priv->fw_state == FW_STATE_RESET) + if (priv->fw_state == FW_STATE_OFF) goto out; ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); @@ -544,11 +552,6 @@ static void p54spi_work(struct work_struct *work) } ret = p54spi_wq_tx(priv); - if (ret < 0) - goto out; - - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); - out: mutex_unlock(&priv->mutex); } diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 6cc6cbc9234f..0e877a104a89 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -81,6 +81,29 @@ static struct usb_device_id p54u_table[] __devinitdata = { MODULE_DEVICE_TABLE(usb, p54u_table); +static const struct { + u32 intf; + enum p54u_hw_type type; + const char *fw; + const char *fw_legacy; + char hw[20]; +} p54u_fwlist[__NUM_P54U_HWTYPES] = { + { + .type = P54U_NET2280, + .intf = FW_LM86, + .fw = "isl3886usb", + .fw_legacy = "isl3890usb", + .hw = "ISL3886 + net2280", + }, + { + .type = P54U_3887, + .intf = FW_LM87, + .fw = "isl3887usb", + .fw_legacy = "isl3887usb_bare", + .hw = "ISL3887", + }, +}; + static void p54u_rx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; @@ -125,11 +148,7 @@ static void p54u_rx_cb(struct urb *urb) } skb_reset_tail_pointer(skb); skb_trim(skb, 0); - if (urb->transfer_buffer != skb_tail_pointer(skb)) { - /* this should not happen */ - WARN_ON(1); - urb->transfer_buffer = skb_tail_pointer(skb); - } + urb->transfer_buffer = skb_tail_pointer(skb); } skb_queue_tail(&priv->rx_queue, skb); usb_anchor_urb(urb, &priv->submitted); @@ -206,53 +225,6 @@ static int p54u_init_urbs(struct ieee80211_hw *dev) return ret; } -static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54u_priv *priv = dev->priv; - struct urb *addr_urb, *data_urb; - int err = 0; - - addr_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!addr_urb) - return; - - data_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!data_urb) { - usb_free_urb(addr_urb); - return; - } - - usb_fill_bulk_urb(addr_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - &((struct p54_hdr *)skb->data)->req_id, 4, - p54u_tx_dummy_cb, dev); - usb_fill_bulk_urb(data_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, FREE_AFTER_TX(skb) ? - p54u_tx_cb : p54u_tx_dummy_cb, skb); - addr_urb->transfer_flags |= URB_ZERO_PACKET; - data_urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(addr_urb, &priv->submitted); - err = usb_submit_urb(addr_urb, GFP_ATOMIC); - if (err) { - usb_unanchor_urb(addr_urb); - goto out; - } - - usb_anchor_urb(data_urb, &priv->submitted); - err = usb_submit_urb(data_urb, GFP_ATOMIC); - if (err) - usb_unanchor_urb(data_urb); - - out: - usb_free_urb(addr_urb); - usb_free_urb(data_urb); - - if (err) - p54_free_skb(dev, skb); -} - static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) { u32 chk = 0; @@ -425,20 +397,16 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep, data, len, &alen, 2000); } -static const char p54u_romboot_3887[] = "~~~~"; -static const char p54u_firmware_upload_3887[] = "<\r"; - -static int p54u_device_reset_3887(struct ieee80211_hw *dev) +static int p54u_device_reset(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING); - u8 buf[4]; if (lock) { ret = usb_lock_device_for_reset(priv->udev, priv->intf); if (ret < 0) { dev_err(&priv->udev->dev, "(p54usb) unable to lock " - " device for reset: %d\n", ret); + "device for reset (%d)!\n", ret); return ret; } } @@ -447,26 +415,34 @@ static int p54u_device_reset_3887(struct ieee80211_hw *dev) if (lock) usb_unlock_device(priv->udev); - if (ret) { + if (ret) dev_err(&priv->udev->dev, "(p54usb) unable to reset " - "device: %d\n", ret); - return ret; - } + "device (%d)!\n", ret); + + return ret; +} + +static const char p54u_romboot_3887[] = "~~~~"; +static int p54u_firmware_reset_3887(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + u8 buf[4]; + int ret; memcpy(&buf, p54u_romboot_3887, sizeof(buf)); ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(buf)); if (ret) dev_err(&priv->udev->dev, "(p54usb) unable to jump to " - "boot ROM: %d\n", ret); + "boot ROM (%d)!\n", ret); return ret; } +static const char p54u_firmware_upload_3887[] = "<\r"; static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; int err, alen; u8 carry = 0; u8 *buf, *tmp; @@ -475,51 +451,29 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) struct x2_header *hdr; unsigned long timeout; + err = p54u_firmware_reset_3887(dev); + if (err) + return err; + tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL); if (!buf) { dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware" "upload buffer!\n"); - err = -ENOMEM; - goto err_bufalloc; + return -ENOMEM; } - err = p54u_device_reset_3887(dev); - if (err) - goto err_reset; - - err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev); - if (err) { - dev_err(&priv->udev->dev, "p54usb: cannot find firmware " - "(isl3887usb)\n"); - err = request_firmware(&fw_entry, "isl3887usb_bare", - &priv->udev->dev); - if (err) - goto err_req_fw_failed; - } - - err = p54_parse_firmware(dev, fw_entry); - if (err) - goto err_upload_failed; - - if (priv->common.fw_interface != FW_LM87) { - dev_err(&priv->udev->dev, "wrong firmware, " - "please get a LM87 firmware and try again.\n"); - err = -EINVAL; - goto err_upload_failed; - } - - left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); + left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size); strcpy(buf, p54u_firmware_upload_3887); left -= strlen(p54u_firmware_upload_3887); tmp += strlen(p54u_firmware_upload_3887); - data = fw_entry->data; - remains = fw_entry->size; + data = priv->fw->data; + remains = priv->fw->size; hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887)); memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); - hdr->fw_length = cpu_to_le32(fw_entry->size); + hdr->fw_length = cpu_to_le32(priv->fw->size); hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr, sizeof(u32)*2)); left -= sizeof(*hdr); @@ -561,7 +515,8 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) left = block_size = min((unsigned int)P54U_FW_BLOCK, remains); } - *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size)); + *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data, + priv->fw->size)); err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); if (err) { dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n"); @@ -612,19 +567,14 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) if (err) goto err_upload_failed; - err_upload_failed: - release_firmware(fw_entry); - err_req_fw_failed: - err_reset: +err_upload_failed: kfree(buf); - err_bufalloc: return err; } static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE; int err, alen; void *buf; @@ -639,33 +589,6 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) return -ENOMEM; } - err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) cannot find firmware " - "(isl3886usb)\n"); - err = request_firmware(&fw_entry, "isl3890usb", - &priv->udev->dev); - if (err) { - kfree(buf); - return err; - } - } - - err = p54_parse_firmware(dev, fw_entry); - if (err) { - kfree(buf); - release_firmware(fw_entry); - return err; - } - - if (priv->common.fw_interface != FW_LM86) { - dev_err(&priv->udev->dev, "wrong firmware, " - "please get a LM86(USB) firmware and try again.\n"); - kfree(buf); - release_firmware(fw_entry); - return -EINVAL; - } - #define P54U_WRITE(type, addr, data) \ do {\ err = p54u_write(priv, buf, type,\ @@ -765,8 +688,8 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); /* finally, we can upload firmware now! */ - remains = fw_entry->size; - data = fw_entry->data; + remains = priv->fw->size; + data = priv->fw->data; offset = ISL38XX_DEV_FIRMWARE_ADDR; while (remains) { @@ -875,12 +798,54 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) #undef P54U_WRITE #undef P54U_READ - fail: - release_firmware(fw_entry); +fail: kfree(buf); return err; } +static int p54u_load_firmware(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + int err, i; + + BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES); + + for (i = 0; i < __NUM_P54U_HWTYPES; i++) + if (p54u_fwlist[i].type == priv->hw_type) + break; + + if (i == __NUM_P54U_HWTYPES) + return -EOPNOTSUPP; + + err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev); + if (err) { + dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " + "(%d)!\n", p54u_fwlist[i].fw, err); + + err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy, + &priv->udev->dev); + if (err) + return err; + } + + err = p54_parse_firmware(dev, priv->fw); + if (err) + goto out; + + if (priv->common.fw_interface != p54u_fwlist[i].intf) { + dev_err(&priv->udev->dev, "wrong firmware, please get " + "a firmware for \"%s\" and try again.\n", + p54u_fwlist[i].hw); + err = -EINVAL; + } + +out: + if (err) + release_firmware(priv->fw); + + return err; +} + static int p54u_open(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; @@ -922,6 +887,7 @@ static int __devinit p54u_probe(struct usb_interface *intf, } priv = dev->priv; + priv->hw_type = P54U_INVALID_HW; SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -953,37 +919,48 @@ static int __devinit p54u_probe(struct usb_interface *intf, priv->common.open = p54u_open; priv->common.stop = p54u_stop; if (recognized_pipes < P54U_PIPE_NUMBER) { +#ifdef CONFIG_PM + /* ISL3887 needs a full reset on resume */ + udev->reset_resume = 1; + err = p54u_device_reset(dev); +#endif + priv->hw_type = P54U_3887; - err = p54u_upload_firmware_3887(dev); - if (priv->common.fw_interface == FW_LM87) { - dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); - priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); - priv->common.tx = p54u_tx_lm87; - } else - priv->common.tx = p54u_tx_3887; + dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); + priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); + priv->common.tx = p54u_tx_lm87; + priv->upload_fw = p54u_upload_firmware_3887; } else { priv->hw_type = P54U_NET2280; dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); priv->common.tx = p54u_tx_net2280; - err = p54u_upload_firmware_net2280(dev); + priv->upload_fw = p54u_upload_firmware_net2280; } + err = p54u_load_firmware(dev); if (err) goto err_free_dev; + err = priv->upload_fw(dev); + if (err) + goto err_free_fw; + p54u_open(dev); err = p54_read_eeprom(dev); p54u_stop(dev); if (err) - goto err_free_dev; + goto err_free_fw; err = p54_register_common(dev, &udev->dev); if (err) - goto err_free_dev; + goto err_free_fw; return 0; - err_free_dev: +err_free_fw: + release_firmware(priv->fw); + +err_free_dev: ieee80211_free_hw(dev); usb_set_intfdata(intf, NULL); usb_put_dev(udev); @@ -1002,20 +979,64 @@ static void __devexit p54u_disconnect(struct usb_interface *intf) 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) { + struct ieee80211_hw *dev = usb_get_intfdata(intf); + + if (!dev) + return -ENODEV; + + p54u_stop(dev); return 0; } +static int p54u_resume(struct usb_interface *intf) +{ + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct p54u_priv *priv; + + if (!dev) + return -ENODEV; + + priv = dev->priv; + if (unlikely(!(priv->upload_fw && priv->fw))) + return 0; + + return priv->upload_fw(dev); +} + static int p54u_post_reset(struct usb_interface *intf) { + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct p54u_priv *priv; + int err; + + err = p54u_resume(intf); + if (err) + return err; + + /* reinitialize old device state */ + priv = dev->priv; + if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) + ieee80211_restart_hw(dev); + return 0; } +#ifdef CONFIG_PM + +static int p54u_suspend(struct usb_interface *intf, pm_message_t message) +{ + return p54u_pre_reset(intf); +} + +#endif /* CONFIG_PM */ + static struct usb_driver p54u_driver = { .name = "p54usb", .id_table = p54u_table, @@ -1023,6 +1044,11 @@ static struct usb_driver p54u_driver = { .disconnect = p54u_disconnect, .pre_reset = p54u_pre_reset, .post_reset = p54u_post_reset, +#ifdef CONFIG_PM + .suspend = p54u_suspend, + .resume = p54u_resume, + .reset_resume = p54u_resume, +#endif /* CONFIG_PM */ .soft_unbind = 1, }; diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h index 8bc58982d8dd..e935b79f7f75 100644 --- a/drivers/net/wireless/p54/p54usb.h +++ b/drivers/net/wireless/p54/p54usb.h @@ -123,18 +123,26 @@ struct p54u_rx_info { struct ieee80211_hw *dev; }; +enum p54u_hw_type { + P54U_INVALID_HW, + P54U_NET2280, + P54U_3887, + + /* keep last */ + __NUM_P54U_HWTYPES, +}; + struct p54u_priv { struct p54_common common; struct usb_device *udev; struct usb_interface *intf; - enum { - P54U_NET2280 = 0, - P54U_3887 - } hw_type; + int (*upload_fw)(struct ieee80211_hw *dev); + enum p54u_hw_type hw_type; spinlock_t lock; struct sk_buff_head rx_queue; struct usb_anchor submitted; + const struct firmware *fw; }; #endif /* P54USB_H */ diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index ef3ef4551b31..8f6210993448 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -87,7 +87,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) unsigned long flags; unsigned char wds_mac[6]; u32 curr_frag; - int err = 0; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); @@ -107,8 +106,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) isl38xx_w32_flush(priv->device_base, ISL38XX_DEV_INT_UPDATE, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); - - err = -EBUSY; goto drop_free; } /* Check alignment and WDS frame formatting. The start of the packet should @@ -152,7 +149,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) if (unlikely(newskb == NULL)) { printk(KERN_ERR "%s: Cannot allocate skb\n", ndev->name); - err = -ENOMEM; goto drop_free; } newskb_offset = (4 - (long) newskb->data) & 0x03; @@ -197,8 +193,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) if (unlikely(pci_map_address == 0)) { printk(KERN_WARNING "%s: cannot map buffer to PCI\n", ndev->name); - - err = -EIO; goto drop_free; } /* Place the fragment in the control block structure. */ @@ -246,7 +240,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) ndev->stats.tx_dropped++; spin_unlock_irqrestore(&priv->slock, flags); dev_kfree_skb(skb); - return err; + return NETDEV_TX_OK; } static inline int diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index fa90d1d8d82e..b10b0383dfa5 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -892,7 +892,7 @@ static int ray_dev_init(struct net_device *dev) #endif /* RAY_IMMEDIATE_INIT */ /* copy mac and broadcast addresses to linux device */ - memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); + memcpy(dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); memset(dev->broadcast, 0xff, ETH_ALEN); DEBUG(2, "ray_dev_init ending\n"); @@ -923,7 +923,7 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!(pcmcia_dev_present(link))) { DEBUG(2, "ray_dev_start_xmit - device not present\n"); - return -1; + return NETDEV_TX_LOCKED; } DEBUG(3, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev); if (local->authentication_state == NEED_TO_AUTH) { @@ -931,7 +931,7 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!build_auth_frame(local, local->auth_id, OPEN_AUTH_REQUEST)) { local->authentication_state = AUTHENTICATED; netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; } } @@ -944,7 +944,7 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) case XMIT_NO_CCS: case XMIT_NEED_AUTH: netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; case XMIT_NO_INTR: case XMIT_MSG_BAD: case XMIT_OK: diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index ff0042ffe3e9..3bec3dbd3450 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2,7 +2,7 @@ * Driver for RNDIS based wireless USB devices. * * Copyright (C) 2007 by Bjorge Dijkstra - * Copyright (C) 2008 by Jussi Kivilinna + * Copyright (C) 2008-2009 by Jussi Kivilinna * * 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 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -156,43 +157,55 @@ MODULE_PARM_DESC(workaround_interval, #define NDIS_802_11_LENGTH_RATES_EX 16 enum ndis_80211_net_type { - ndis_80211_type_freq_hop, - ndis_80211_type_direct_seq, - ndis_80211_type_ofdm_a, - ndis_80211_type_ofdm_g + NDIS_80211_TYPE_FREQ_HOP, + NDIS_80211_TYPE_DIRECT_SEQ, + NDIS_80211_TYPE_OFDM_A, + NDIS_80211_TYPE_OFDM_G }; enum ndis_80211_net_infra { - ndis_80211_infra_adhoc, - ndis_80211_infra_infra, - ndis_80211_infra_auto_unknown + NDIS_80211_INFRA_ADHOC, + NDIS_80211_INFRA_INFRA, + NDIS_80211_INFRA_AUTO_UNKNOWN }; enum ndis_80211_auth_mode { - ndis_80211_auth_open, - ndis_80211_auth_shared, - ndis_80211_auth_auto_switch, - ndis_80211_auth_wpa, - ndis_80211_auth_wpa_psk, - ndis_80211_auth_wpa_none, - ndis_80211_auth_wpa2, - ndis_80211_auth_wpa2_psk + NDIS_80211_AUTH_OPEN, + NDIS_80211_AUTH_SHARED, + NDIS_80211_AUTH_AUTO_SWITCH, + NDIS_80211_AUTH_WPA, + NDIS_80211_AUTH_WPA_PSK, + NDIS_80211_AUTH_WPA_NONE, + NDIS_80211_AUTH_WPA2, + NDIS_80211_AUTH_WPA2_PSK }; enum ndis_80211_encr_status { - ndis_80211_encr_wep_enabled, - ndis_80211_encr_disabled, - ndis_80211_encr_wep_key_absent, - ndis_80211_encr_not_supported, - ndis_80211_encr_tkip_enabled, - ndis_80211_encr_tkip_key_absent, - ndis_80211_encr_ccmp_enabled, - ndis_80211_encr_ccmp_key_absent + NDIS_80211_ENCR_WEP_ENABLED, + NDIS_80211_ENCR_DISABLED, + NDIS_80211_ENCR_WEP_KEY_ABSENT, + NDIS_80211_ENCR_NOT_SUPPORTED, + NDIS_80211_ENCR_TKIP_ENABLED, + NDIS_80211_ENCR_TKIP_KEY_ABSENT, + NDIS_80211_ENCR_CCMP_ENABLED, + NDIS_80211_ENCR_CCMP_KEY_ABSENT }; enum ndis_80211_priv_filter { - ndis_80211_priv_accept_all, - ndis_80211_priv_8021x_wep + NDIS_80211_PRIV_ACCEPT_ALL, + NDIS_80211_PRIV_8021X_WEP +}; + +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), + NDIS_80211_ADDKEY_PAIRWISE_KEY = cpu_to_le32(1 << 30), + NDIS_80211_ADDKEY_TRANSMIT_KEY = cpu_to_le32(1 << 31) +}; + +enum ndis_80211_addwep_bits { + NDIS_80211_ADDWEP_PERCLIENT_KEY = cpu_to_le32(1 << 30), + NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) }; struct ndis_80211_ssid { @@ -308,7 +321,6 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, #define CAP_MODE_80211B 2 #define CAP_MODE_80211G 4 #define CAP_MODE_MASK 7 -#define CAP_SUPPORT_TXPOWER 8 #define WORK_LINK_UP (1<<0) #define WORK_LINK_DOWN (1<<1) @@ -316,25 +328,61 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, #define COMMAND_BUFFER_SIZE (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set)) -/* RNDIS device private data */ -struct rndis_wext_private { - char name[32]; +static const struct ieee80211_channel rndis_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; +static const struct ieee80211_rate rndis_rates[] = { + { .bitrate = 10 }, + { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60 }, + { .bitrate = 90 }, + { .bitrate = 120 }, + { .bitrate = 180 }, + { .bitrate = 240 }, + { .bitrate = 360 }, + { .bitrate = 480 }, + { .bitrate = 540 } +}; + +/* RNDIS device private data */ +struct rndis_wlan_private { struct usbnet *usbdev; + struct wireless_dev wdev; + + struct cfg80211_scan_request *scan_request; + struct workqueue_struct *workqueue; struct delayed_work stats_work; + struct delayed_work scan_work; struct work_struct work; struct mutex command_lock; spinlock_t stats_lock; unsigned long work_pending; + struct ieee80211_supported_band band; + struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; + struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; + struct iw_statistics iwstats; struct iw_statistics privstats; - int nick_len; - char nick[32]; - int caps; int multicast_size; @@ -357,6 +405,7 @@ struct rndis_wext_private { int encr_tx_key_index; char encr_keys[4][32]; int encr_key_len[4]; + char encr_key_wpa[4]; int wpa_version; int wpa_keymgmt; int wpa_authalg; @@ -368,8 +417,22 @@ struct rndis_wext_private { u8 command_buffer[COMMAND_BUFFER_SIZE]; }; +/* + * cfg80211 ops + */ +static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); -static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 }; +static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request); + +static struct cfg80211_ops rndis_config_ops = { + .change_virtual_intf = rndis_change_virtual_intf, + .scan = rndis_scan, +}; + +static void *rndis_wiphy_privid = &rndis_wiphy_privid; static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; @@ -378,13 +441,13 @@ static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -static struct rndis_wext_private *get_rndis_wext_priv(struct usbnet *dev) +static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev) { - return (struct rndis_wext_private *)dev->driver_priv; + return (struct rndis_wlan_private *)dev->driver_priv; } -static u32 get_bcm4320_power(struct rndis_wext_private *priv) +static u32 get_bcm4320_power(struct rndis_wlan_private *priv) { return BCM4320_DEFAULT_TXPOWER * bcm4320_power_output[priv->param_power_output] / 100; @@ -417,7 +480,7 @@ static int rndis_error_status(__le32 rndis_status) static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) { - struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); union { void *buf; struct rndis_msg_hdr *header; @@ -463,7 +526,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) { - struct rndis_wext_private *priv = get_rndis_wext_priv(dev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); union { void *buf; struct rndis_msg_hdr *header; @@ -684,7 +747,7 @@ static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int ret; ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid)); @@ -731,7 +794,7 @@ static int is_associated(struct usbnet *usbdev) static int disassociate(struct usbnet *usbdev, int reset_ssid) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ndis_80211_ssid ssid; int i, ret = 0; @@ -763,7 +826,7 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid) static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tmp; int auth_mode, ret; @@ -772,23 +835,23 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg) if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) { if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X) - auth_mode = ndis_80211_auth_wpa2; + auth_mode = NDIS_80211_AUTH_WPA2; else - auth_mode = ndis_80211_auth_wpa2_psk; + auth_mode = NDIS_80211_AUTH_WPA2_PSK; } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) { if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X) - auth_mode = ndis_80211_auth_wpa; + auth_mode = NDIS_80211_AUTH_WPA; else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK) - auth_mode = ndis_80211_auth_wpa_psk; + auth_mode = NDIS_80211_AUTH_WPA_PSK; else - auth_mode = ndis_80211_auth_wpa_none; + auth_mode = NDIS_80211_AUTH_WPA_NONE; } else if (authalg & IW_AUTH_ALG_SHARED_KEY) { if (authalg & IW_AUTH_ALG_OPEN_SYSTEM) - auth_mode = ndis_80211_auth_auto_switch; + auth_mode = NDIS_80211_AUTH_AUTO_SWITCH; else - auth_mode = ndis_80211_auth_shared; + auth_mode = NDIS_80211_AUTH_SHARED; } else - auth_mode = ndis_80211_auth_open; + auth_mode = NDIS_80211_AUTH_OPEN; tmp = cpu_to_le32(auth_mode); ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp, @@ -806,16 +869,16 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg) static int set_priv_filter(struct usbnet *usbdev) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tmp; devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version); if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 || priv->wpa_version & IW_AUTH_WPA_VERSION_WPA) - tmp = cpu_to_le32(ndis_80211_priv_8021x_wep); + tmp = cpu_to_le32(NDIS_80211_PRIV_8021X_WEP); else - tmp = cpu_to_le32(ndis_80211_priv_accept_all); + tmp = cpu_to_le32(NDIS_80211_PRIV_ACCEPT_ALL); return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp, sizeof(tmp)); @@ -824,7 +887,7 @@ static int set_priv_filter(struct usbnet *usbdev) static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tmp; int encr_mode, ret; @@ -833,18 +896,18 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) groupwise); if (pairwise & IW_AUTH_CIPHER_CCMP) - encr_mode = ndis_80211_encr_ccmp_enabled; + encr_mode = NDIS_80211_ENCR_CCMP_ENABLED; else if (pairwise & IW_AUTH_CIPHER_TKIP) - encr_mode = ndis_80211_encr_tkip_enabled; + encr_mode = NDIS_80211_ENCR_TKIP_ENABLED; else if (pairwise & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) - encr_mode = ndis_80211_encr_wep_enabled; + encr_mode = NDIS_80211_ENCR_WEP_ENABLED; else if (groupwise & IW_AUTH_CIPHER_CCMP) - encr_mode = ndis_80211_encr_ccmp_enabled; + encr_mode = NDIS_80211_ENCR_CCMP_ENABLED; else if (groupwise & IW_AUTH_CIPHER_TKIP) - encr_mode = ndis_80211_encr_tkip_enabled; + encr_mode = NDIS_80211_ENCR_TKIP_ENABLED; else - encr_mode = ndis_80211_encr_disabled; + encr_mode = NDIS_80211_ENCR_DISABLED; tmp = cpu_to_le32(encr_mode); ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp, @@ -862,7 +925,7 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) static int set_assoc_params(struct usbnet *usbdev) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg); set_priv_filter(usbdev); @@ -874,7 +937,7 @@ static int set_assoc_params(struct usbnet *usbdev) static int set_infra_mode(struct usbnet *usbdev, int mode) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tmp; int ret, i; @@ -894,7 +957,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode) 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) + 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); } @@ -907,12 +970,12 @@ static int set_infra_mode(struct usbnet *usbdev, int mode) static void set_default_iw_params(struct usbnet *usbdev) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); priv->wpa_keymgmt = 0; priv->wpa_version = 0; - set_infra_mode(usbdev, ndis_80211_infra_infra); + set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA); set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED, IW_AUTH_ALG_OPEN_SYSTEM); set_priv_filter(usbdev); @@ -933,7 +996,7 @@ static int deauthenticate(struct usbnet *usbdev) /* index must be 0 - N, as per NDIS */ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ndis_80211_wep_key ndis_key; int ret; @@ -948,7 +1011,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) memcpy(&ndis_key.material, key, key_len); if (index == priv->encr_tx_key_index) { - ndis_key.index |= cpu_to_le32(1 << 31); + ndis_key.index |= NDIS_80211_ADDWEP_TRANSMIT_KEY; ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104, IW_AUTH_CIPHER_NONE); if (ret) @@ -965,16 +1028,85 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) } priv->encr_key_len[index] = key_len; + priv->encr_key_wpa[index] = 0; memcpy(&priv->encr_keys[index], key, key_len); 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) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + struct ndis_80211_key ndis_key; + int ret; + + if (index < 0 || index >= 4) + return -EINVAL; + if (key_len > sizeof(ndis_key.material) || key_len < 0) + return -EINVAL; + if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) + return -EINVAL; + if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr) + return -EINVAL; + + devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index, + !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), + !!(flags & NDIS_80211_ADDKEY_PAIRWISE_KEY), + !!(flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)); + + memset(&ndis_key, 0, sizeof(ndis_key)); + + ndis_key.size = cpu_to_le32(sizeof(ndis_key) - + sizeof(ndis_key.material) + 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) { + /* 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); + memcpy(ndis_key.material + 16, key + 24, 8); + memcpy(ndis_key.material + 24, key + 16, 8); + } else + memcpy(ndis_key.material, key, key_len); + + if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) + memcpy(ndis_key.rsc, rx_seq, 6); + + if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { + /* pairwise key */ + memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN); + } else { + /* group key */ + if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) + memset(ndis_key.bssid, 0xff, ETH_ALEN); + else + get_bssid(usbdev, ndis_key.bssid); + } + + ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key, + le32_to_cpu(ndis_key.size)); + devdbg(usbdev, "add_wpa_key: OID_802_11_ADD_KEY -> %08X", ret); + if (ret != 0) + return ret; + + priv->encr_key_len[index] = key_len; + priv->encr_key_wpa[index] = 1; + + if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY) + priv->encr_tx_key_index = index; + + return 0; +} + + /* remove_key is for both wep and wpa */ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ndis_80211_remove_key remove_key; __le32 keyindex; int ret; @@ -983,6 +1115,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) 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])); if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP || @@ -994,7 +1127,8 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) if (bssid) { /* pairwise key */ if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0) - remove_key.index |= cpu_to_le32(1 << 30); + remove_key.index |= + NDIS_80211_ADDKEY_PAIRWISE_KEY; memcpy(remove_key.bssid, bssid, sizeof(remove_key.bssid)); } else @@ -1027,7 +1161,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) static void set_multicast_list(struct usbnet *usbdev) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct dev_mc_list *mclist; __le32 filter; int ret, i, size; @@ -1085,6 +1219,173 @@ static void set_multicast_list(struct usbnet *usbdev) } +/* + * cfg80211 ops + */ +static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct net_device *dev; + struct usbnet *usbdev; + 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; + break; + case NL80211_IFTYPE_STATION: + mode = NDIS_80211_INFRA_INFRA; + break; + default: + return -EINVAL; + } + + return set_infra_mode(usbdev, mode); +} + + +#define SCAN_DELAY_JIFFIES (HZ) +static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) +{ + struct usbnet *usbdev = netdev_priv(dev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + int ret; + __le32 tmp; + + devdbg(usbdev, "cfg80211.scan"); + + if (!request) + return -EINVAL; + + if (priv->scan_request && priv->scan_request != request) + return -EBUSY; + + priv->scan_request = request; + + tmp = cpu_to_le32(1); + ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, + sizeof(tmp)); + if (ret == 0) { + /* Wait before retrieving scan results from device */ + queue_delayed_work(priv->workqueue, &priv->scan_work, + SCAN_DELAY_JIFFIES); + } + + return ret; +} + + +static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, + struct ndis_80211_bssid_ex *bssid) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + struct ieee80211_channel *channel; + s32 signal; + u64 timestamp; + u16 capability; + u16 beacon_interval; + struct ndis_80211_fixed_ies *fixed; + int ie_len, bssid_len; + u8 *ie; + + /* parse bssid structure */ + bssid_len = le32_to_cpu(bssid->length); + + if (bssid_len < sizeof(struct ndis_80211_bssid_ex) + + sizeof(struct ndis_80211_fixed_ies)) + return NULL; + + fixed = (struct ndis_80211_fixed_ies *)bssid->ies; + + ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); + ie_len = min(bssid_len - (int)sizeof(*bssid), + (int)le32_to_cpu(bssid->ie_length)); + ie_len -= sizeof(struct ndis_80211_fixed_ies); + if (ie_len < 0) + return NULL; + + /* extract data for cfg80211_inform_bss */ + channel = ieee80211_get_channel(priv->wdev.wiphy, + KHZ_TO_MHZ(le32_to_cpu(bssid->config.ds_config))); + if (!channel) + return NULL; + + signal = level_to_qual(le32_to_cpu(bssid->rssi)); + timestamp = le64_to_cpu(*(__le64 *)fixed->timestamp); + capability = le16_to_cpu(fixed->capabilities); + beacon_interval = le16_to_cpu(fixed->beacon_interval); + + return cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, + timestamp, capability, beacon_interval, ie, ie_len, signal, + GFP_KERNEL); +} + + +static int rndis_check_bssid_list(struct usbnet *usbdev) +{ + void *buf = NULL; + struct ndis_80211_bssid_list_ex *bssid_list; + struct ndis_80211_bssid_ex *bssid; + int ret = -EINVAL, len, count, bssid_len; + + devdbg(usbdev, "check_bssid_list"); + + len = CONTROL_BUFFER_SIZE; + buf = kmalloc(len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); + if (ret != 0) + goto out; + + bssid_list = buf; + bssid = bssid_list->bssid; + bssid_len = le32_to_cpu(bssid->length); + count = le32_to_cpu(bssid_list->num_items); + devdbg(usbdev, "check_bssid_list: %d BSSIDs found", count); + + while (count && ((void *)bssid + bssid_len) <= (buf + len)) { + rndis_bss_info_update(usbdev, bssid); + + bssid = (void *)bssid + bssid_len; + bssid_len = le32_to_cpu(bssid->length); + count--; + } + +out: + kfree(buf); + return ret; +} + + +static void rndis_get_scan_results(struct work_struct *work) +{ + struct rndis_wlan_private *priv = + container_of(work, struct rndis_wlan_private, scan_work.work); + struct usbnet *usbdev = priv->usbdev; + int ret; + + devdbg(usbdev, "get_scan_results"); + + ret = rndis_check_bssid_list(usbdev); + + cfg80211_scan_done(priv->scan_request, ret < 0); + + priv->scan_request = NULL; +} + + /* * wireless extension handlers */ @@ -1097,124 +1398,6 @@ static int rndis_iw_commit(struct net_device *dev, } -static int rndis_iw_get_range(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - int len, ret, i, j, num, has_80211g_rates; - u8 rates[8]; - __le32 tx_power; - - devdbg(usbdev, "SIOCGIWRANGE"); - - /* clear iw_range struct */ - memset(range, 0, sizeof(*range)); - wrqu->data.length = sizeof(*range); - - range->txpower_capa = IW_TXPOW_MWATT; - range->num_txpower = 1; - if (priv->caps & CAP_SUPPORT_TXPOWER) { - len = sizeof(tx_power); - ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, - &tx_power, &len); - if (ret == 0 && le32_to_cpu(tx_power) != 0xFF) - range->txpower[0] = le32_to_cpu(tx_power); - else - range->txpower[0] = get_bcm4320_power(priv); - } else - range->txpower[0] = get_bcm4320_power(priv); - - len = sizeof(rates); - ret = rndis_query_oid(usbdev, OID_802_11_SUPPORTED_RATES, &rates, - &len); - has_80211g_rates = 0; - if (ret == 0) { - j = 0; - for (i = 0; i < len; i++) { - if (rates[i] == 0) - break; - range->bitrate[j] = (rates[i] & 0x7f) * 500000; - /* check for non 802.11b rates */ - if (range->bitrate[j] == 6000000 || - range->bitrate[j] == 9000000 || - (range->bitrate[j] >= 12000000 && - range->bitrate[j] != 22000000)) - has_80211g_rates = 1; - j++; - } - range->num_bitrates = j; - } else - range->num_bitrates = 0; - - /* fill in 802.11g rates */ - if (has_80211g_rates) { - num = range->num_bitrates; - for (i = 0; i < ARRAY_SIZE(rates_80211g); i++) { - for (j = 0; j < num; j++) { - if (range->bitrate[j] == - rates_80211g[i] * 1000000) - break; - } - if (j == num) - range->bitrate[range->num_bitrates++] = - rates_80211g[i] * 1000000; - if (range->num_bitrates == IW_MAX_BITRATES) - break; - } - - /* estimated max real througput in bps */ - range->throughput = 54 * 1000 * 1000 / 2; - - /* ~35% more with afterburner */ - if (priv->param_afterburner) - range->throughput = range->throughput / 100 * 135; - } else { - /* estimated max real througput in bps */ - range->throughput = 11 * 1000 * 1000 / 2; - } - - range->num_channels = 14; - - for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) { - range->freq[i].i = i + 1; - range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000; - range->freq[i].e = 1; - } - range->num_frequency = i; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - range->max_qual.qual = 100; - range->max_qual.level = 154; - range->max_qual.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_INVALID; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = WIRELESS_EXT; - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - return 0; -} - - -static int rndis_iw_get_name(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - strcpy(wrqu->name, priv->name); - return 0; -} - - static int rndis_iw_set_essid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { @@ -1314,7 +1497,7 @@ static int rndis_iw_set_auth(struct net_device *dev, { struct iw_param *p = &wrqu->param; struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int ret = -ENOTSUPP; switch (p->flags & IW_AUTH_INDEX) { @@ -1395,7 +1578,7 @@ static int rndis_iw_get_auth(struct net_device *dev, { struct iw_param *p = &wrqu->param; struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); switch (p->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: @@ -1422,60 +1605,11 @@ static int rndis_iw_get_auth(struct net_device *dev, } -static int rndis_iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - switch (priv->infra_mode) { - case ndis_80211_infra_adhoc: - wrqu->mode = IW_MODE_ADHOC; - break; - case ndis_80211_infra_infra: - wrqu->mode = IW_MODE_INFRA; - break; - /*case ndis_80211_infra_auto_unknown:*/ - default: - wrqu->mode = IW_MODE_AUTO; - break; - } - devdbg(usbdev, "SIOCGIWMODE: %08x", wrqu->mode); - return 0; -} - - -static int rndis_iw_set_mode(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - int mode; - - devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode); - - switch (wrqu->mode) { - case IW_MODE_ADHOC: - mode = ndis_80211_infra_adhoc; - break; - case IW_MODE_INFRA: - mode = ndis_80211_infra_infra; - break; - /*case IW_MODE_AUTO:*/ - default: - mode = ndis_80211_infra_auto_unknown; - break; - } - - return set_infra_mode(usbdev, mode); -} - - static int rndis_iw_set_encode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int ret, index, key_len; u8 *key; @@ -1538,10 +1672,8 @@ 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_wext_private *priv = get_rndis_wext_priv(usbdev); - struct ndis_80211_key ndis_key; - int keyidx, ret; - u8 *addr; + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + int keyidx, flags; keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; @@ -1564,250 +1696,16 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) return remove_key(usbdev, keyidx, NULL); - if (ext->key_len > sizeof(ndis_key.material)) - return -1; - - memset(&ndis_key, 0, sizeof(ndis_key)); - - ndis_key.size = cpu_to_le32(sizeof(ndis_key) - - sizeof(ndis_key.material) + ext->key_len); - ndis_key.length = cpu_to_le32(ext->key_len); - ndis_key.index = cpu_to_le32(keyidx); - - if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - memcpy(ndis_key.rsc, ext->rx_seq, 6); - ndis_key.index |= cpu_to_le32(1 << 29); - } - - addr = ext->addr.sa_data; - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - /* group key */ - if (priv->infra_mode == ndis_80211_infra_adhoc) - memset(ndis_key.bssid, 0xff, ETH_ALEN); - else - get_bssid(usbdev, ndis_key.bssid); - } else { - /* pairwise key */ - ndis_key.index |= cpu_to_le32(1 << 30); - memcpy(ndis_key.bssid, addr, ETH_ALEN); - } - + flags = 0; + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) + flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ; + if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) + flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY; if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - ndis_key.index |= cpu_to_le32(1 << 31); + flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY; - if (ext->alg == IW_ENCODE_ALG_TKIP && ext->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, ext->key, 16); - memcpy(ndis_key.material + 16, ext->key + 24, 8); - memcpy(ndis_key.material + 24, ext->key + 16, 8); - } else - memcpy(ndis_key.material, ext->key, ext->key_len); - - ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key, - le32_to_cpu(ndis_key.size)); - devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret); - if (ret != 0) - return ret; - - priv->encr_key_len[keyidx] = ext->key_len; - memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len); - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - priv->encr_tx_key_index = keyidx; - - return 0; -} - - -static int rndis_iw_set_scan(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - union iwreq_data evt; - int ret = -EINVAL; - __le32 tmp; - - devdbg(usbdev, "SIOCSIWSCAN"); - - if (wrqu->data.flags == 0) { - tmp = cpu_to_le32(1); - ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, - sizeof(tmp)); - evt.data.flags = 0; - evt.data.length = 0; - wireless_send_event(dev, SIOCGIWSCAN, &evt, NULL); - } - return ret; -} - - -static char *rndis_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *cev, - char *end_buf, - struct ndis_80211_bssid_ex *bssid) -{ - struct usbnet *usbdev = netdev_priv(dev); - u8 *ie; - char *current_val; - int bssid_len, ie_len, i; - u32 beacon, atim; - struct iw_event iwe; - unsigned char sbuf[32]; - - bssid_len = le32_to_cpu(bssid->length); - - devdbg(usbdev, "BSSID %pM", bssid->mac); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_ADDR_LEN); - - devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length), - bssid->ssid.essid); - iwe.cmd = SIOCGIWESSID; - iwe.u.essid.length = le32_to_cpu(bssid->ssid.length); - iwe.u.essid.flags = 1; - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, bssid->ssid.essid); - - devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra)); - iwe.cmd = SIOCGIWMODE; - switch (le32_to_cpu(bssid->net_infra)) { - case ndis_80211_infra_adhoc: - iwe.u.mode = IW_MODE_ADHOC; - break; - case ndis_80211_infra_infra: - iwe.u.mode = IW_MODE_INFRA; - break; - /*case ndis_80211_infra_auto_unknown:*/ - default: - iwe.u.mode = IW_MODE_AUTO; - break; - } - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_UINT_LEN); - - devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config)); - iwe.cmd = SIOCGIWFREQ; - dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq); - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_FREQ_LEN); - - devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->rssi)); - iwe.u.qual.level = le32_to_cpu(bssid->rssi); - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_INVALID; - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_QUAL_LEN); - - devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy)); - iwe.cmd = SIOCGIWENCODE; - iwe.u.data.length = 0; - if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all) - iwe.u.data.flags = IW_ENCODE_DISABLED; - else - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); - - devdbg(usbdev, "RATES:"); - current_val = cev + iwe_stream_lcp_len(info); - iwe.cmd = SIOCGIWRATE; - for (i = 0; i < sizeof(bssid->rates); i++) { - if (bssid->rates[i] & 0x7f) { - iwe.u.bitrate.value = - ((bssid->rates[i] & 0x7f) * - 500000); - devdbg(usbdev, " %d", iwe.u.bitrate.value); - current_val = iwe_stream_add_value(info, cev, - current_val, end_buf, &iwe, - IW_EV_PARAM_LEN); - } - } - - if ((current_val - cev) > iwe_stream_lcp_len(info)) - cev = current_val; - - beacon = le32_to_cpu(bssid->config.beacon_period); - devdbg(usbdev, "BCN_INT %d", beacon); - iwe.cmd = IWEVCUSTOM; - snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); - iwe.u.data.length = strlen(sbuf); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); - - atim = le32_to_cpu(bssid->config.atim_window); - devdbg(usbdev, "ATIM %d", atim); - iwe.cmd = IWEVCUSTOM; - snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); - iwe.u.data.length = strlen(sbuf); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); - - ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); - ie_len = min(bssid_len - (int)sizeof(*bssid), - (int)le32_to_cpu(bssid->ie_length)); - ie_len -= sizeof(struct ndis_80211_fixed_ies); - while (ie_len >= 2 && 2 + ie[1] <= ie_len) { - if ((ie[0] == WLAN_EID_GENERIC && ie[1] >= 4 && - memcmp(ie + 2, "\x00\x50\xf2\x01", 4) == 0) || - ie[0] == WLAN_EID_RSN) { - devdbg(usbdev, "IE: WPA%d", - (ie[0] == WLAN_EID_RSN) ? 2 : 1); - iwe.cmd = IWEVGENIE; - /* arbitrary cut-off at 64 */ - iwe.u.data.length = min(ie[1] + 2, 64); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, ie); - } - - ie_len -= 2 + ie[1]; - ie += 2 + ie[1]; - } - - return cev; -} - - -static int rndis_iw_get_scan(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - void *buf = NULL; - char *cev = extra; - struct ndis_80211_bssid_list_ex *bssid_list; - struct ndis_80211_bssid_ex *bssid; - int ret = -EINVAL, len, count, bssid_len; - - devdbg(usbdev, "SIOCGIWSCAN"); - - len = CONTROL_BUFFER_SIZE; - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); - - if (ret != 0) - goto out; - - bssid_list = buf; - bssid = bssid_list->bssid; - bssid_len = le32_to_cpu(bssid->length); - count = le32_to_cpu(bssid_list->num_items); - devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); - - while (count && ((void *)bssid + bssid_len) <= (buf + len)) { - cev = rndis_translate_scan(dev, info, cev, - extra + IW_SCAN_MAX_DATA, bssid); - bssid = (void *)bssid + bssid_len; - bssid_len = le32_to_cpu(bssid->length); - count--; - } - -out: - wrqu->data.length = cev - extra; - wrqu->data.flags = 0; - kfree(buf); - return ret; + return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr, + ext->rx_seq, ext->alg, flags); } @@ -1815,7 +1713,7 @@ static int rndis_iw_set_genie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int ret = 0; #ifdef DEBUG @@ -1849,7 +1747,7 @@ static int rndis_iw_get_genie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); devdbg(usbdev, "SIOCGIWGENIE"); @@ -1936,39 +1834,6 @@ static int rndis_iw_get_frag(struct net_device *dev, } -static int rndis_iw_set_nick(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - devdbg(usbdev, "SIOCSIWNICK"); - - priv->nick_len = wrqu->data.length; - if (priv->nick_len > 32) - priv->nick_len = 32; - - memcpy(priv->nick, extra, priv->nick_len); - return 0; -} - - -static int rndis_iw_get_nick(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - wrqu->data.flags = 1; - wrqu->data.length = priv->nick_len; - memcpy(extra, priv->nick, priv->nick_len); - - devdbg(usbdev, "SIOCGIWNICK: '%s'", priv->nick); - - return 0; -} - - static int rndis_iw_set_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -2021,20 +1886,12 @@ 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_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tx_power; - int ret = 0, len; if (priv->radio_on) { - if (priv->caps & CAP_SUPPORT_TXPOWER) { - len = sizeof(tx_power); - ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, - &tx_power, &len); - if (ret != 0) - return ret; - } else - /* fake incase not supported */ - tx_power = cpu_to_le32(get_bcm4320_power(priv)); + /* 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); @@ -2047,7 +1904,7 @@ static int rndis_iw_get_txpower(struct net_device *dev, devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value); - return ret; + return 0; } @@ -2055,9 +1912,8 @@ 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_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tx_power = 0; - int ret = 0; if (!wrqu->txpower.disabled) { if (wrqu->txpower.flags == IW_TXPOW_MWATT) @@ -2080,22 +1936,10 @@ static int rndis_iw_set_txpower(struct net_device *dev, devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power)); if (le32_to_cpu(tx_power) != 0) { - if (priv->caps & CAP_SUPPORT_TXPOWER) { - /* turn radio on first */ - if (!priv->radio_on) - disassociate(usbdev, 1); - - ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL, - &tx_power, sizeof(tx_power)); - if (ret != 0) - ret = -EOPNOTSUPP; - return ret; - } else { - /* txpower unsupported, just turn radio on */ - if (!priv->radio_on) - return disassociate(usbdev, 1); - return 0; /* all ready on */ - } + /* 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 */ @@ -2125,7 +1969,7 @@ static int rndis_iw_set_mlme(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct iw_mlme *mlme = (struct iw_mlme *)extra; unsigned char bssid[ETH_ALEN]; @@ -2150,7 +1994,7 @@ static int rndis_iw_set_mlme(struct net_device *dev, static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev) { struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); unsigned long flags; spin_lock_irqsave(&priv->stats_lock, flags); @@ -2165,20 +2009,18 @@ static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev) static const iw_handler rndis_iw_handler[] = { IW_IOCTL(SIOCSIWCOMMIT) = rndis_iw_commit, - IW_IOCTL(SIOCGIWNAME) = rndis_iw_get_name, + IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq, IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq, - IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode, - IW_IOCTL(SIOCGIWMODE) = rndis_iw_get_mode, - IW_IOCTL(SIOCGIWRANGE) = rndis_iw_get_range, + IW_IOCTL(SIOCSIWMODE) = (iw_handler) cfg80211_wext_siwmode, + IW_IOCTL(SIOCGIWMODE) = (iw_handler) cfg80211_wext_giwmode, + IW_IOCTL(SIOCGIWRANGE) = (iw_handler) cfg80211_wext_giwrange, IW_IOCTL(SIOCSIWAP) = rndis_iw_set_bssid, IW_IOCTL(SIOCGIWAP) = rndis_iw_get_bssid, - IW_IOCTL(SIOCSIWSCAN) = rndis_iw_set_scan, - IW_IOCTL(SIOCGIWSCAN) = rndis_iw_get_scan, + IW_IOCTL(SIOCSIWSCAN) = (iw_handler) cfg80211_wext_siwscan, + IW_IOCTL(SIOCGIWSCAN) = (iw_handler) cfg80211_wext_giwscan, IW_IOCTL(SIOCSIWESSID) = rndis_iw_set_essid, IW_IOCTL(SIOCGIWESSID) = rndis_iw_get_essid, - IW_IOCTL(SIOCSIWNICKN) = rndis_iw_set_nick, - IW_IOCTL(SIOCGIWNICKN) = rndis_iw_get_nick, IW_IOCTL(SIOCGIWRATE) = rndis_iw_get_rate, IW_IOCTL(SIOCSIWRTS) = rndis_iw_set_rts, IW_IOCTL(SIOCGIWRTS) = rndis_iw_get_rts, @@ -2195,28 +2037,28 @@ static const iw_handler rndis_iw_handler[] = IW_IOCTL(SIOCSIWMLME) = rndis_iw_set_mlme, }; -static const iw_handler rndis_wext_private_handler[] = { +static const iw_handler rndis_wlan_private_handler[] = { }; -static const struct iw_priv_args rndis_wext_private_args[] = { +static const struct iw_priv_args rndis_wlan_private_args[] = { }; static const struct iw_handler_def rndis_iw_handlers = { .num_standard = ARRAY_SIZE(rndis_iw_handler), - .num_private = ARRAY_SIZE(rndis_wext_private_handler), - .num_private_args = ARRAY_SIZE(rndis_wext_private_args), + .num_private = ARRAY_SIZE(rndis_wlan_private_handler), + .num_private_args = ARRAY_SIZE(rndis_wlan_private_args), .standard = (iw_handler *)rndis_iw_handler, - .private = (iw_handler *)rndis_wext_private_handler, - .private_args = (struct iw_priv_args *)rndis_wext_private_args, + .private = (iw_handler *)rndis_wlan_private_handler, + .private_args = (struct iw_priv_args *)rndis_wlan_private_args, .get_wireless_stats = rndis_get_wireless_stats, }; -static void rndis_wext_worker(struct work_struct *work) +static void rndis_wlan_worker(struct work_struct *work) { - struct rndis_wext_private *priv = - container_of(work, struct rndis_wext_private, work); + struct rndis_wlan_private *priv = + container_of(work, struct rndis_wlan_private, work); struct usbnet *usbdev = priv->usbdev; union iwreq_data evt; unsigned char bssid[ETH_ALEN]; @@ -2277,10 +2119,10 @@ static void rndis_wext_worker(struct work_struct *work) set_multicast_list(usbdev); } -static void rndis_wext_set_multicast_list(struct net_device *dev) +static void rndis_wlan_set_multicast_list(struct net_device *dev) { struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) return; @@ -2289,9 +2131,9 @@ static void rndis_wext_set_multicast_list(struct net_device *dev) queue_work(priv->workqueue, &priv->work); } -static void rndis_wext_link_change(struct usbnet *usbdev, int state) +static void rndis_wlan_link_change(struct usbnet *usbdev, int state) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); /* queue work to avoid recursive calls into rndis_command */ set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending); @@ -2299,22 +2141,14 @@ static void rndis_wext_link_change(struct usbnet *usbdev, int state) } -static int rndis_wext_get_caps(struct usbnet *usbdev) +static int rndis_wlan_get_caps(struct usbnet *usbdev) { struct { __le32 num_items; __le32 items[8]; } networks_supported; int len, retval, i, n; - __le32 tx_power; - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - /* determine if supports setting txpower */ - len = sizeof(tx_power); - retval = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, &tx_power, - &len); - if (retval == 0 && le32_to_cpu(tx_power) != 0xFF) - priv->caps |= CAP_SUPPORT_TXPOWER; + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); /* determine supported modes */ len = sizeof(networks_supported); @@ -2326,24 +2160,18 @@ static int rndis_wext_get_caps(struct usbnet *usbdev) n = 8; for (i = 0; i < n; i++) { switch (le32_to_cpu(networks_supported.items[i])) { - case ndis_80211_type_freq_hop: - case ndis_80211_type_direct_seq: + case NDIS_80211_TYPE_FREQ_HOP: + case NDIS_80211_TYPE_DIRECT_SEQ: priv->caps |= CAP_MODE_80211B; break; - case ndis_80211_type_ofdm_a: + case NDIS_80211_TYPE_OFDM_A: priv->caps |= CAP_MODE_80211A; break; - case ndis_80211_type_ofdm_g: + case NDIS_80211_TYPE_OFDM_G: priv->caps |= CAP_MODE_80211G; break; } } - if (priv->caps & CAP_MODE_80211A) - strcat(priv->name, "a"); - if (priv->caps & CAP_MODE_80211B) - strcat(priv->name, "b"); - if (priv->caps & CAP_MODE_80211G) - strcat(priv->name, "g"); } return retval; @@ -2353,8 +2181,8 @@ static int rndis_wext_get_caps(struct usbnet *usbdev) #define STATS_UPDATE_JIFFIES (HZ) static void rndis_update_wireless_stats(struct work_struct *work) { - struct rndis_wext_private *priv = - container_of(work, struct rndis_wext_private, stats_work.work); + struct rndis_wlan_private *priv = + container_of(work, struct rndis_wlan_private, stats_work.work); struct usbnet *usbdev = priv->usbdev; struct iw_statistics iwstats; __le32 rssi, tmp; @@ -2387,7 +2215,7 @@ static void rndis_update_wireless_stats(struct work_struct *work) if (ret == 0) { memset(&iwstats.qual, 0, sizeof(iwstats.qual)); iwstats.qual.qual = level_to_qual(le32_to_cpu(rssi)); - iwstats.qual.level = le32_to_cpu(rssi); + iwstats.qual.level = level_to_qual(le32_to_cpu(rssi)); iwstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; @@ -2457,9 +2285,19 @@ static void rndis_update_wireless_stats(struct work_struct *work) } -static int bcm4320_early_init(struct usbnet *usbdev) +static int bcm4320a_early_init(struct usbnet *usbdev) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + /* bcm4320a doesn't handle configuration parameters well. Try + * set any and you get partially zeroed mac and broken device. + */ + + return 0; +} + + +static int bcm4320b_early_init(struct usbnet *usbdev) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); char buf[8]; /* Early initialization settings, setting these won't have effect @@ -2525,33 +2363,41 @@ static int bcm4320_early_init(struct usbnet *usbdev) } /* same as rndis_netdev_ops but with local multicast handler */ -static const struct net_device_ops rndis_wext_netdev_ops = { +static const struct net_device_ops rndis_wlan_netdev_ops = { .ndo_open = usbnet_open, .ndo_stop = usbnet_stop, .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = rndis_wext_set_multicast_list, + .ndo_set_multicast_list = rndis_wlan_set_multicast_list, }; -static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) +static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) { - struct rndis_wext_private *priv; + struct wiphy *wiphy; + struct rndis_wlan_private *priv; int retval, len; __le32 tmp; - /* allocate rndis private data */ - priv = kzalloc(sizeof(struct rndis_wext_private), GFP_KERNEL); - if (!priv) + /* allocate wiphy and rndis private data + * NOTE: We only support a single virtual interface, so wiphy + * and wireless_dev are somewhat synonymous for this device. + */ + wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wlan_private)); + if (!wiphy) return -ENOMEM; + priv = wiphy_priv(wiphy); + usbdev->net->ieee80211_ptr = &priv->wdev; + priv->wdev.wiphy = wiphy; + priv->wdev.iftype = NL80211_IFTYPE_STATION; + /* These have to be initialized before calling generic_rndis_bind(). - * Otherwise we'll be in big trouble in rndis_wext_early_init(). + * Otherwise we'll be in big trouble in rndis_wlan_early_init(). */ usbdev->driver_priv = priv; - strcpy(priv->name, "IEEE802.11"); usbdev->net->wireless_handlers = &rndis_iw_handlers; priv->usbdev = usbdev; @@ -2560,8 +2406,9 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) /* because rndis_command() sleeps we need to use workqueue */ priv->workqueue = create_singlethread_workqueue("rndis_wlan"); - INIT_WORK(&priv->work, rndis_wext_worker); + INIT_WORK(&priv->work, rndis_wlan_worker); INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); + INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results); /* try bind rndis_host */ retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); @@ -2573,9 +2420,9 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) * picks up rssi to closest station instead of to access point). * * rndis_host wants to avoid all OID as much as possible - * so do promisc/multicast handling in rndis_wext. + * so do promisc/multicast handling in rndis_wlan. */ - usbdev->net->netdev_ops = &rndis_wext_netdev_ops; + usbdev->net->netdev_ops = &rndis_wlan_netdev_ops; tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, @@ -2600,7 +2447,32 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) | IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; - rndis_wext_get_caps(usbdev); + /* fill-out wiphy structure and register w/ cfg80211 */ + memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN); + wiphy->privid = rndis_wiphy_privid; + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC); + wiphy->max_scan_ssids = 1; + + /* TODO: fill-out band information based on priv->caps */ + rndis_wlan_get_caps(usbdev); + + memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); + memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rndis_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(rndis_rates); + wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; + + set_wiphy_dev(wiphy, &usbdev->udev->dev); + + if (wiphy_register(wiphy)) { + retval = -ENODEV; + goto fail; + } + set_default_iw_params(usbdev); /* turn radio on */ @@ -2615,36 +2487,40 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) fail: cancel_delayed_work_sync(&priv->stats_work); + cancel_delayed_work_sync(&priv->scan_work); cancel_work_sync(&priv->work); flush_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue); - kfree(priv); + wiphy_free(wiphy); return retval; } -static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf) +static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf) { - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); /* turn radio off */ disassociate(usbdev, 0); cancel_delayed_work_sync(&priv->stats_work); + cancel_delayed_work_sync(&priv->scan_work); cancel_work_sync(&priv->work); flush_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue); if (priv && priv->wpa_ie_len) kfree(priv->wpa_ie); - kfree(priv); rndis_unbind(usbdev, intf); + + wiphy_unregister(priv->wdev.wiphy); + wiphy_free(priv->wdev.wiphy); } -static int rndis_wext_reset(struct usbnet *usbdev) +static int rndis_wlan_reset(struct usbnet *usbdev) { return deauthenticate(usbdev); } @@ -2653,40 +2529,40 @@ static int rndis_wext_reset(struct usbnet *usbdev) static const struct driver_info bcm4320b_info = { .description = "Wireless RNDIS device, BCM4320b based", .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, - .bind = rndis_wext_bind, - .unbind = rndis_wext_unbind, + .bind = rndis_wlan_bind, + .unbind = rndis_wlan_unbind, .status = rndis_status, .rx_fixup = rndis_rx_fixup, .tx_fixup = rndis_tx_fixup, - .reset = rndis_wext_reset, - .early_init = bcm4320_early_init, - .link_change = rndis_wext_link_change, + .reset = rndis_wlan_reset, + .early_init = bcm4320b_early_init, + .link_change = rndis_wlan_link_change, }; static const struct driver_info bcm4320a_info = { .description = "Wireless RNDIS device, BCM4320a based", .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, - .bind = rndis_wext_bind, - .unbind = rndis_wext_unbind, + .bind = rndis_wlan_bind, + .unbind = rndis_wlan_unbind, .status = rndis_status, .rx_fixup = rndis_rx_fixup, .tx_fixup = rndis_tx_fixup, - .reset = rndis_wext_reset, - .early_init = bcm4320_early_init, - .link_change = rndis_wext_link_change, + .reset = rndis_wlan_reset, + .early_init = bcm4320a_early_init, + .link_change = rndis_wlan_link_change, }; -static const struct driver_info rndis_wext_info = { +static const struct driver_info rndis_wlan_info = { .description = "Wireless RNDIS device", .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, - .bind = rndis_wext_bind, - .unbind = rndis_wext_unbind, + .bind = rndis_wlan_bind, + .unbind = rndis_wlan_unbind, .status = rndis_status, .rx_fixup = rndis_rx_fixup, .tx_fixup = rndis_tx_fixup, - .reset = rndis_wext_reset, - .early_init = bcm4320_early_init, - .link_change = rndis_wext_link_change, + .reset = rndis_wlan_reset, + .early_init = bcm4320a_early_init, + .link_change = rndis_wlan_link_change, }; /*-------------------------------------------------------------------------*/ @@ -2796,11 +2672,11 @@ static const struct usb_device_id products [] = { { /* RNDIS is MSFT's un-official variant of CDC ACM */ USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), - .driver_info = (unsigned long) &rndis_wext_info, + .driver_info = (unsigned long) &rndis_wlan_info, }, { /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), - .driver_info = (unsigned long) &rndis_wext_info, + .driver_info = (unsigned long) &rndis_wlan_info, }, { }, // END }; diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 1ae11c7f17af..8aab3e6754bd 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -77,6 +77,20 @@ config RT73USB When compiled as a module, this driver will be called rt73usb. +config RT2800USB + tristate "Ralink rt2800 (USB) support" + depends on USB + 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. + Supported chips: RT2770, RT2870 & RT3070. + + When compiled as a module, this driver will be called "rt2800usb.ko". + config RT2X00_LIB_PCI tristate select RT2X00_LIB @@ -88,6 +102,9 @@ config RT2X00_LIB_USB config RT2X00_LIB tristate +config RT2X00_LIB_HT + boolean + config RT2X00_LIB_FIRMWARE boolean select FW_LOADER diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index f22d808d8c51..bfc7226f0afe 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -8,6 +8,7 @@ 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 obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o @@ -17,3 +18,4 @@ obj-$(CONFIG_RT2500PCI) += rt2500pci.o obj-$(CONFIG_RT61PCI) += rt61pci.o obj-$(CONFIG_RT2500USB) += rt2500usb.o obj-$(CONFIG_RT73USB) += rt73usb.o +obj-$(CONFIG_RT2800USB) += rt2800usb.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0f08773328c6..435f945fe64d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -335,10 +335,11 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, preamble_mask = erp->short_preamble << 3; rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, - erp->ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, erp->ack_timeout); rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, erp->ack_consume_time); + rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); + rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); @@ -371,6 +372,11 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); rt2x00pci_register_write(rt2x00dev, CSR11, reg); + rt2x00pci_register_read(rt2x00dev, CSR12, ®); + rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); + rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, CSR12, reg); + rt2x00pci_register_read(rt2x00dev, CSR18, ®); rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); @@ -503,24 +509,6 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, CSR11, reg); } -static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, - libconf->conf->beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, - libconf->conf->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, CSR12, reg); -} - static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -532,7 +520,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00pci_register_read(rt2x00dev, CSR20, ®); rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, - (libconf->conf->beacon_int - 20) * 16); + (rt2x00dev->beacon_int - 20) * 16); rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); @@ -558,8 +546,6 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) rt2400pci_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - rt2400pci_config_duration(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) rt2400pci_config_ps(rt2x00dev, libconf); } @@ -1361,7 +1347,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2460, value, reg); + rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && !rt2x00_rf(&rt2x00dev->chip, RF2421)) { @@ -1580,7 +1566,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 276a8232aaa0..08b30d01e67d 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -341,10 +341,11 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, preamble_mask = erp->short_preamble << 3; rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, - erp->ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, erp->ack_timeout); rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, erp->ack_consume_time); + rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); + rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); @@ -377,6 +378,11 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); rt2x00pci_register_write(rt2x00dev, CSR11, reg); + rt2x00pci_register_read(rt2x00dev, CSR12, ®); + rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); + rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, CSR12, reg); + rt2x00pci_register_read(rt2x00dev, CSR18, ®); rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); @@ -552,24 +558,6 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, CSR11, reg); } -static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, - libconf->conf->beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, - libconf->conf->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, CSR12, reg); -} - static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -581,7 +569,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00pci_register_read(rt2x00dev, CSR20, ®); rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, - (libconf->conf->beacon_int - 20) * 16); + (rt2x00dev->beacon_int - 20) * 16); rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); @@ -609,8 +597,6 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) rt2500pci_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - rt2500pci_config_duration(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) rt2500pci_config_ps(rt2x00dev, libconf); } @@ -1525,7 +1511,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2560, value, reg); + rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && !rt2x00_rf(&rt2x00dev->chip, RF2523) && @@ -1879,7 +1865,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9e630e70fc97..66daf68ff0ee 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -503,6 +503,10 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); + rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); + rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, erp->beacon_int * 4); + rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); @@ -632,17 +636,6 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, rt2500usb_rf_write(rt2x00dev, 3, rf3); } -static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, - libconf->conf->beacon_int * 4); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); -} - static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -654,7 +647,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, - libconf->conf->beacon_int - 20); + rt2x00dev->beacon_int - 20); rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); @@ -680,8 +673,6 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) rt2500usb_config_txpower(rt2x00dev, libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - rt2500usb_config_duration(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) rt2500usb_config_ps(rt2x00dev, libconf); } @@ -1559,7 +1550,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } @@ -1908,7 +1899,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c new file mode 100644 index 000000000000..37561667925b --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -0,0 +1,3078 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + 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: rt2800usb + Abstract: rt2800usb device specific routines. + Supported chipsets: RT2800U. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rt2x00.h" +#include "rt2x00usb.h" +#include "rt2800usb.h" + +/* + * Allow hardware encryption to be disabled. + */ +static int modparam_nohwcrypt = 1; +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +/* + * Register access. + * All access to the CSR registers will go through the methods + * rt2x00usb_register_read and rt2x00usb_register_write. + * BBP and RF register require indirect register access, + * and use the CSR registers BBPCSR and RFCSR to achieve this. + * These indirect registers work with busy bits, + * and we will try maximal REGISTER_BUSY_COUNT times to access + * the register while taking a REGISTER_BUSY_DELAY us delay + * between each attampt. When the busy bit is still set at that time, + * the access attempt is considered to have failed, + * and we will print an error. + * The _lock versions must be used if you already hold the csr_mutex + */ +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RFCSR(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) +#define WAIT_FOR_MCU(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), H2M_MAILBOX_CSR, \ + H2M_MAILBOX_CSR_OWNER, (__reg)) + +static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_BBP(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rfcsr_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rfcsr_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_RFCSR(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u32 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); + rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the MCU becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_MCU(rt2x00dev, ®)) { + rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); + rt2x00usb_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); + + reg = 0; + rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); + rt2x00usb_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +static const struct rt2x00debug rt2800usb_rt2x00debug = { + .owner = THIS_MODULE, + .csr = { + .read = rt2x00usb_register_read, + .write = rt2x00usb_register_write, + .flags = RT2X00DEBUGFS_OFFSET, + .word_base = CSR_REG_BASE, + .word_size = sizeof(u32), + .word_count = CSR_REG_SIZE / sizeof(u32), + }, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, + .word_base = EEPROM_BASE, + .word_size = sizeof(u16), + .word_count = EEPROM_SIZE / sizeof(u16), + }, + .bbp = { + .read = rt2800usb_bbp_read, + .write = rt2800usb_bbp_write, + .word_base = BBP_BASE, + .word_size = sizeof(u8), + .word_count = BBP_SIZE / sizeof(u8), + }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2800usb_rf_write, + .word_base = RF_BASE, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, +}; +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + +#ifdef CONFIG_RT2X00_LIB_RFKILL +static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + 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, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int bg_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + unsigned int polarity = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_POLARITY); + unsigned int ledmode = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_MODE); + + if (led->type == LED_TYPE_RADIO) { + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? 0x20 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * The specs tell us the following levels: + * 0, 1 ,3, 7, 15, 31 + * to determine the level in a simple way we can simply + * work with bitshifting: + * (1 << level) - 1 + */ + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + (1 << brightness / (LED_FULL / 6)) - 1, + polarity); + } +} + +static int rt2800usb_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00usb_register_read(led->rt2x00dev, LED_CFG, ®); + rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); + rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); + rt2x00usb_register_write(led->rt2x00dev, LED_CFG, reg); + + return 0; +} + +static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2800usb_brightness_set; + led->led_dev.blink_set = rt2800usb_blink_set; + led->flags = LED_INITIALIZED; +} +#endif /* CONFIG_RT2X00_LIB_LEDS */ + +/* + * Configuration handlers. + */ +static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct mac_wcid_entry wcid_entry; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + u32 reg; + + offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->cmd == SET_KEY) * crypto->bssidx); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + + memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || + (crypto->cipher == CIPHER_TKIP_NO_MIC) || + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; + rt2x00usb_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + offset = MAC_WCID_ENTRY(key->hw_key_idx); + + memset(&wcid_entry, 0, sizeof(wcid_entry)); + if (crypto->cmd == SET_KEY) + memcpy(&wcid_entry, crypto->address, ETH_ALEN); + rt2x00usb_register_multiwrite(rt2x00dev, offset, + &wcid_entry, sizeof(wcid_entry)); +} + +static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + struct rt2x00_field32 field; + int timeout; + u32 offset; + u32 reg; + + if (crypto->cmd == SET_KEY) { + key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = SHARED_KEY_ENTRY(key->hw_key_idx); + timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + offset, &key_entry, + sizeof(key_entry), + timeout); + } + + /* + * The cipher types are stored over multiple registers + * starting with SHARED_KEY_MODE_BASE each word will have + * 32 bits and contains the cipher types for 2 bssidx each. + * Using the correct defines correctly will cause overhead, + * so just calculate the correct offset. + */ + field.bit_offset = 4 * (key->hw_key_idx % 8); + field.bit_mask = 0x7 << field.bit_offset; + + offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + /* + * Update WCID information + */ + rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + int timeout; + u32 offset; + + if (crypto->cmd == SET_KEY) { + /* + * 1 pairwise key is possible per AID, this means that the AID + * equals our hw_key_idx. Make sure the WCID starts _after_ the + * last possible shared key entry. + */ + if (crypto->aid > (256 - 32)) + return -ENOSPC; + + key->hw_key_idx = 32 + crypto->aid; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); + timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + offset, &key_entry, + sizeof(key_entry), + timeout); + } + + /* + * Update WCID information + */ + rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00usb_register_read(rt2x00dev, RX_FILTER_CFG, ®); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, + !(filter_flags & FIF_CONTROL)); + rt2x00usb_register_write(rt2x00dev, RX_FILTER_CFG, reg); +} + +static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) +{ + unsigned int beacon_base; + u32 reg; + + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00usb_register_write(rt2x00dev, beacon_base, 0); + + /* + * Enable synchronisation. + */ + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } + + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); + + rt2x00usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, + conf->mac, sizeof(conf->mac)); + } + + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); + conf->bssid[1] = cpu_to_le32(reg); + + rt2x00usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, + conf->bssid, sizeof(conf->bssid)); + } +} + +static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, + DIV_ROUND_UP(erp->ack_timeout, erp->slot_time)); + rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, + !!erp->short_preamble); + rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, + !!erp->short_preamble); + rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, + erp->cts_protection ? 2 : 0); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, + erp->basic_rates); + rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); + rt2x00usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, XIFS_TIME_CFG, ®); + rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); + rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); +} + +static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, + struct antenna_setup *ant) +{ + u8 r1; + u8 r3; + + rt2800usb_bbp_read(rt2x00dev, 1, &r1); + rt2800usb_bbp_read(rt2x00dev, 3, &r3); + + /* + * Configure the TX antenna. + */ + switch ((int)ant->tx) { + case 1: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + case 3: + /* Do nothing */ + break; + } + + /* + * Configure the RX antenna. + */ + switch ((int)ant->rx) { + case 1: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); + break; + case 3: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); + break; + } + + rt2800usb_bbp_write(rt2x00dev, 3, r3); + rt2800usb_bbp_write(rt2x00dev, 1, r1); +} + +static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u16 eeprom; + short lna_gain; + + if (libconf->rf.channel <= 14) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); + } else if (libconf->rf.channel <= 64) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); + } else { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); + } + + rt2x00dev->lna_gain = lna_gain; +} + +static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); + + if (rt2x00dev->default_ant.tx == 1) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); + + if (rt2x00dev->default_ant.rx == 1) { + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + } else if (rt2x00dev->default_ant.rx == 2) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + + if (rf->channel > 14) { + /* + * When TX power is below 0, we should increase it by 7 to + * make it a positive value (Minumum value is -7). + * However this means that values between 0 and 7 have + * double meaning, and we should set a 7DBm boost flag. + */ + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, + (info->tx_power1 >= 0)); + + if (info->tx_power1 < 0) + info->tx_power1 += 7; + + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power1)); + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, + (info->tx_power2 >= 0)); + + if (info->tx_power2 < 0) + info->tx_power2 += 7; + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power2)); + } else { + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power2)); + } + + rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); +} + +static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u8 rfcsr; + + rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf1); + rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf3); + + rt2800usb_rfcsr_read(rt2x00dev, 6, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); + rt2800usb_rfcsr_write(rt2x00dev, 6, rfcsr); + + rt2800usb_rfcsr_read(rt2x00dev, 12, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2800usb_rfcsr_write(rt2x00dev, 12, rfcsr); + + rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); + rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); + + rt2800usb_rfcsr_write(rt2x00dev, 24, + rt2x00dev->calibration[conf_is_ht40(conf)]); + + rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); + rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); +} + +static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u32 reg; + unsigned int tx_pin; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info); + else + rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info); + + /* + * Change BBP settings + */ + rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 86, 0); + + if (rf->channel <= 14) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { + rt2800usb_bbp_write(rt2x00dev, 82, 0x62); + rt2800usb_bbp_write(rt2x00dev, 75, 0x46); + } else { + rt2800usb_bbp_write(rt2x00dev, 82, 0x84); + rt2800usb_bbp_write(rt2x00dev, 75, 0x50); + } + } else { + rt2800usb_bbp_write(rt2x00dev, 82, 0xf2); + + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) + rt2800usb_bbp_write(rt2x00dev, 75, 0x46); + else + rt2800usb_bbp_write(rt2x00dev, 75, 0x50); + } + + rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, ®); + rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); + rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); + rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg); + + tx_pin = 0; + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.tx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); + } + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.rx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + } + + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); + + rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + rt2800usb_bbp_read(rt2x00dev, 3, &bbp); + rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2800usb_bbp_write(rt2x00dev, 3, bbp); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + if (conf_is_ht40(conf)) { + rt2800usb_bbp_write(rt2x00dev, 69, 0x1a); + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 73, 0x16); + } else { + rt2800usb_bbp_write(rt2x00dev, 69, 0x16); + rt2800usb_bbp_write(rt2x00dev, 70, 0x08); + rt2800usb_bbp_write(rt2x00dev, 73, 0x11); + } + } + + msleep(1); +} + +static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev, + const int txpower) +{ + u32 reg; + u32 value = TXPOWER_G_TO_DEV(txpower); + u8 r1; + + rt2800usb_bbp_read(rt2x00dev, 1, &r1); + rt2x00_set_field8(®, BBP1_TX_POWER, 0); + rt2800usb_bbp_write(rt2x00dev, 1, r1); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_0, ®); + rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_1, ®); + rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_2, ®); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_3, ®); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_4, ®); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg); +} + +static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TX_RTY_CFG, ®); + rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, + libconf->conf->short_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, + libconf->conf->long_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); + rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg); +} + +static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + + rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, + libconf->conf->listen_interval - 1); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + } else { + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + + rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + } +} + +static void rt2800usb_config(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags) +{ + /* Always recalculate LNA gain before changing configuration */ + rt2800usb_config_lna_gain(rt2x00dev, libconf); + + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) + rt2800usb_config_channel(rt2x00dev, libconf->conf, + &libconf->rf, &libconf->channel); + if (flags & IEEE80211_CONF_CHANGE_POWER) + rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + rt2800usb_config_retry_limit(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2800usb_config_ps(rt2x00dev, libconf); +} + +/* + * Link tuning + */ +static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); + qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); +} + +static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev) +{ + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) + return 0x1c + (2 * rt2x00dev->lna_gain); + else + return 0x2e + rt2x00dev->lna_gain; + } + + if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + return 0x32 + (rt2x00dev->lna_gain * 5) / 3; + else + return 0x3a + (rt2x00dev->lna_gain * 5) / 3; +} + +static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) +{ + if (qual->vgc_level != vgc_level) { + rt2800usb_bbp_write(rt2x00dev, 66, vgc_level); + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; + } +} + +static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + rt2800usb_set_vgc(rt2x00dev, qual, + rt2800usb_get_default_vgc(rt2x00dev)); +} + +static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) +{ + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) + return; + + /* + * When RSSI is better then -80 increase VGC level with 0x10 + */ + rt2800usb_set_vgc(rt2x00dev, qual, + rt2800usb_get_default_vgc(rt2x00dev) + + ((qual->rssi > -80) * 0x10)); +} + +/* + * Firmware functions + */ +static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) +{ + return FIRMWARE_RT2870; +} + +static bool rt2800usb_check_crc(const u8 *data, const size_t len) +{ + u16 fw_crc; + u16 crc; + + /* + * The last 2 bytes in the firmware array are the crc checksum itself, + * this means that we should never pass those 2 bytes to the crc + * algorithm. + */ + fw_crc = (data[len - 2] << 8 | data[len - 1]); + + /* + * Use the crc ccitt algorithm. + * This will return the same value as the legacy driver which + * used bit ordering reversion on the both the firmware bytes + * before input input as well as on the final output. + * Obviously using crc ccitt directly is much more efficient. + */ + crc = crc_ccitt(~0, data, len - 2); + + /* + * There is a small difference between the crc-itu-t + bitrev and + * the crc-ccitt crc calculation. In the latter method the 2 bytes + * will be swapped, use swab16 to convert the crc to the correct + * value. + */ + crc = swab16(crc); + + return fw_crc == crc; +} + +static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) +{ + u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; + size_t offset = 0; + + /* + * Firmware files: + * There are 2 variations of the rt2870 firmware. + * a) size: 4kb + * b) size: 8kb + * Note that (b) contains 2 seperate firmware blobs of 4k + * within the file. The first blob is the same firmware as (a), + * but the second blob is for the additional chipsets. + */ + if (len != 4096 && len != 8192) + return FW_BAD_LENGTH; + + /* + * Check if we need the upper 4kb firmware data or not. + */ + if ((len == 4096) && + (chipset != 0x2860) && + (chipset != 0x2872) && + (chipset != 0x3070)) + return FW_BAD_VERSION; + + /* + * 8kb firmware files must be checked as if it were + * 2 seperate firmware files. + */ + while (offset < len) { + if (!rt2800usb_check_crc(data + offset, 4096)) + return FW_BAD_CRC; + + offset += 4096; + } + + return FW_OK; +} + +static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) +{ + unsigned int i; + int status; + u32 reg; + u32 offset; + u32 length; + u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; + + /* + * Check which section of the firmware we need. + */ + if ((chipset == 0x2860) || + (chipset == 0x2872) || + (chipset == 0x3070)) { + offset = 0; + length = 4096; + } else { + offset = 4096; + length = 4096; + } + + /* + * Wait for stable hardware. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; + } + + /* + * Write firmware to device. + */ + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + FIRMWARE_IMAGE_BASE, + data + offset, length, + REGISTER_TIMEOUT32(length)); + + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + + /* + * Send firmware request to device to load firmware, + * we need to specify a long timeout time. + */ + status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, + 0, USB_MODE_FIRMWARE, + REGISTER_TIMEOUT_FIRMWARE); + if (status < 0) { + ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); + return status; + } + + msleep(10); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + + /* + * Send signal to firmware during boot time. + */ + rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + + if ((chipset == 0x3070) || + (chipset == 0x3071) || + (chipset == 0x3572)) { + udelay(200); + rt2800usb_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); + udelay(10); + } + + /* + * Wait for device to stabilize. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "PBF system register not ready.\n"); + return -EBUSY; + } + + /* + * Initialize firmware. + */ + rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + return 0; +} + +/* + * Initialization functions. + */ +static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + unsigned int i; + + /* + * Wait untill BBP and RF are ready. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; + } + + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); + + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_RESET, REGISTER_TIMEOUT); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00usb_register_read(rt2x00dev, BCN_OFFSET0, ®); + rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ + rt2x00usb_register_write(rt2x00dev, BCN_OFFSET0, reg); + + rt2x00usb_register_read(rt2x00dev, BCN_OFFSET1, ®); + rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ + rt2x00usb_register_write(rt2x00dev, BCN_OFFSET1, reg); + + rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); + rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + } else { + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + } + + rt2x00usb_register_read(rt2x00dev, TX_LINK_CFG, ®); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); + rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); + rt2x00usb_register_write(rt2x00dev, TX_LINK_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); + rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); + if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && + rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); + rt2x00usb_register_write(rt2x00dev, MAX_LEN_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); + + rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); + rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + rt2x00usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); + + rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, + IEEE80211_MAX_RTS_THRESHOLD); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ + for (i = 0; i < 256; i++) { + u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); + + rt2x00usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); + rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + + for (i = 0; i < 16; i++) + rt2x00usb_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); + + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0); + + rt2x00usb_register_read(rt2x00dev, USB_CYC_CFG, ®); + rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); + rt2x00usb_register_write(rt2x00dev, USB_CYC_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG0, ®); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); + rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG0, reg); + + rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG1, ®); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); + rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG1, reg); + + rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 3); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); + rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG0, reg); + + rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG1, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); + rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG1, reg); + + /* + * We must clear the error counters. + * These registers are cleared on read, + * so we may pass a useless variable to store the value. + */ + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT1, ®); + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT2, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT0, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT1, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT2, ®); + + return 0; +} + +static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_STATUS_CFG, ®); + if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) + return 0; + + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u8 value; + + /* + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ + rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800usb_bbp_read(rt2x00dev, 0, &value); + if ((value != 0xff) && (value != 0x00)) + return 0; + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) || + rt2800usb_wait_bbp_ready(rt2x00dev))) + return -EACCES; + + rt2800usb_bbp_write(rt2x00dev, 65, 0x2c); + rt2800usb_bbp_write(rt2x00dev, 66, 0x38); + rt2800usb_bbp_write(rt2x00dev, 69, 0x12); + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 73, 0x10); + rt2800usb_bbp_write(rt2x00dev, 81, 0x37); + rt2800usb_bbp_write(rt2x00dev, 82, 0x62); + rt2800usb_bbp_write(rt2x00dev, 83, 0x6a); + rt2800usb_bbp_write(rt2x00dev, 84, 0x99); + rt2800usb_bbp_write(rt2x00dev, 86, 0x00); + rt2800usb_bbp_write(rt2x00dev, 91, 0x04); + rt2800usb_bbp_write(rt2x00dev, 92, 0x00); + rt2800usb_bbp_write(rt2x00dev, 103, 0x00); + rt2800usb_bbp_write(rt2x00dev, 105, 0x05); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 69, 0x16); + rt2800usb_bbp_write(rt2x00dev, 73, 0x12); + } + + if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 84, 0x19); + } + + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 84, 0x99); + rt2800usb_bbp_write(rt2x00dev, 105, 0x05); + } + + for (i = 0; i < EEPROM_BBP_SIZE; i++) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); + + if (eeprom != 0xffff && eeprom != 0x0000) { + reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); + value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); + rt2800usb_bbp_write(rt2x00dev, reg_id, value); + } + } + + return 0; +} + +static u8 rt2800usb_init_rx_filter(struct rt2x00_dev *rt2x00dev, + bool bw40, u8 rfcsr24, u8 filter_target) +{ + unsigned int i; + u8 bbp; + u8 rfcsr; + u8 passband; + u8 stopband; + u8 overtuned = 0; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); + rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * Set power & frequency of passband test tone + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0); + + for (i = 0; i < 100; i++) { + rt2800usb_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800usb_bbp_read(rt2x00dev, 55, &passband); + if (passband) + break; + } + + /* + * Set power & frequency of stopband test tone + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0x06); + + for (i = 0; i < 100; i++) { + rt2800usb_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800usb_bbp_read(rt2x00dev, 55, &stopband); + + if ((passband - stopband) <= filter_target) { + rfcsr24++; + overtuned += ((passband - stopband) == filter_target); + } else + break; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + } + + rfcsr24 -= !!overtuned; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + return rfcsr24; +} + +static int rt2800usb_init_rfcsr(struct rt2x00_dev *rt2x00dev) +{ + u8 rfcsr; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + return 0; + + /* + * Init RF calibration. + */ + rt2800usb_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); + rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); + msleep(1); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); + rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); + + rt2800usb_rfcsr_write(rt2x00dev, 4, 0x40); + rt2800usb_rfcsr_write(rt2x00dev, 5, 0x03); + rt2800usb_rfcsr_write(rt2x00dev, 6, 0x02); + rt2800usb_rfcsr_write(rt2x00dev, 7, 0x70); + rt2800usb_rfcsr_write(rt2x00dev, 9, 0x0f); + rt2800usb_rfcsr_write(rt2x00dev, 10, 0x71); + rt2800usb_rfcsr_write(rt2x00dev, 11, 0x21); + rt2800usb_rfcsr_write(rt2x00dev, 12, 0x7b); + rt2800usb_rfcsr_write(rt2x00dev, 14, 0x90); + rt2800usb_rfcsr_write(rt2x00dev, 15, 0x58); + rt2800usb_rfcsr_write(rt2x00dev, 16, 0xb3); + rt2800usb_rfcsr_write(rt2x00dev, 17, 0x92); + rt2800usb_rfcsr_write(rt2x00dev, 18, 0x2c); + rt2800usb_rfcsr_write(rt2x00dev, 19, 0x02); + rt2800usb_rfcsr_write(rt2x00dev, 20, 0xba); + rt2800usb_rfcsr_write(rt2x00dev, 21, 0xdb); + rt2800usb_rfcsr_write(rt2x00dev, 24, 0x16); + rt2800usb_rfcsr_write(rt2x00dev, 25, 0x01); + rt2800usb_rfcsr_write(rt2x00dev, 27, 0x03); + rt2800usb_rfcsr_write(rt2x00dev, 29, 0x1f); + + /* + * Set RX Filter calibration for 20MHz and 40MHz + */ + rt2x00dev->calibration[0] = + rt2800usb_init_rx_filter(rt2x00dev, false, 0x07, 0x16); + rt2x00dev->calibration[1] = + rt2800usb_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + + /* + * Set back to initial state + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0); + + rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); + rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * set BBP back to BW20 + */ + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + return 0; +} + +/* + * Device state switch handlers. + */ +static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, + enum dev_state state) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, + (state == STATE_RADIO_RX_ON) || + (state == STATE_RADIO_RX_ON_LINK)); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +} + +static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && + !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) + return 0; + + msleep(1); + } + + ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + u16 word; + + /* + * Initialize all registers. + */ + if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || + rt2800usb_init_registers(rt2x00dev) || + rt2800usb_init_bbp(rt2x00dev) || + rt2800usb_init_rfcsr(rt2x00dev))) + return -EIO; + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + udelay(50); + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + + rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); + rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); + /* Don't use bulk in aggregation when working with USB 1.1 */ + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, + (rt2x00dev->rx->usb_maxpacket == 512)); + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); + /* + * Total room for RX frames in kilobytes, PBF might still exceed + * this limit so reduce the number to prevent errors. + */ + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, + ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); + rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + /* + * Initialize LED control + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); + rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + word & 0xff, (word >> 8) & 0xff); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); + rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + word & 0xff, (word >> 8) & 0xff); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); + rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + word & 0xff, (word >> 8) & 0xff); + + return 0; +} + +static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, 0); + + /* Wait for DMA, ignore error */ + rt2800usb_wait_wpdma_ready(rt2x00dev); + + rt2x00usb_disable_radio(rt2x00dev); +} + +static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, + enum dev_state state) +{ + if (state == STATE_AWAKE) + rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + else + rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + + return 0; +} + +static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, + enum dev_state state) +{ + int retval = 0; + + switch (state) { + case STATE_RADIO_ON: + /* + * 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. + */ + rt2800usb_set_state(rt2x00dev, STATE_AWAKE); + msleep(1); + retval = rt2800usb_enable_radio(rt2x00dev); + break; + case STATE_RADIO_OFF: + /* + * After the radio has been disablee, the device should + * be put to sleep for powersaving. + */ + rt2800usb_disable_radio(rt2x00dev); + rt2800usb_set_state(rt2x00dev, STATE_SLEEP); + break; + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + case STATE_RADIO_RX_OFF: + case STATE_RADIO_RX_OFF_LINK: + rt2800usb_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + /* No support, but no error either */ + break; + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt2800usb_set_state(rt2x00dev, state); + break; + default: + retval = -ENOTSUPP; + break; + } + + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + + return retval; +} + +/* + * TX descriptor initialization + */ +static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb, + struct txentry_desc *txdesc) +{ + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + __le32 *txi = skbdesc->desc; + __le32 *txwi = &txi[TXINFO_DESC_SIZE / sizeof(__le32)]; + u32 word; + + /* + * Initialize TX Info descriptor + */ + rt2x00_desc_read(txwi, 0, &word); + rt2x00_set_field32(&word, TXWI_W0_FRAG, + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); + rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); + rt2x00_set_field32(&word, TXWI_W0_TS, + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_AMPDU, + test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); + rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs); + rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); + rt2x00_set_field32(&word, TXWI_W0_BW, + test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, + test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); + rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); + rt2x00_desc_write(txwi, 0, word); + + rt2x00_desc_read(txwi, 1, &word); + rt2x00_set_field32(&word, TXWI_W1_ACK, + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_NSEQ, + test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); + rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, + test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? + txdesc->key_idx : 0xff); + rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, + skb->len - txdesc->l2pad); + rt2x00_set_field32(&word, TXWI_W1_PACKETID, + skbdesc->entry->entry_idx); + rt2x00_desc_write(txwi, 1, word); + + /* + * Always write 0 to IV/EIV fields, hardware will insert the IV + * from the IVEIV register when TXINFO_W0_WIV is set to 0. + * When TXINFO_W0_WIV is set to 1 it will use the IV data + * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which + * crypto entry in the registers should be used to encrypt the frame. + */ + _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); + _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); + + /* + * Initialize TX descriptor + */ + rt2x00_desc_read(txi, 0, &word); + rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, + skb->len + TXWI_DESC_SIZE); + rt2x00_set_field32(&word, TXINFO_W0_WIV, + !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); + rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); + rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0); + rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0); + rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST, + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); + rt2x00_desc_write(txi, 0, word); +} + +/* + * TX data initialization + */ +static void rt2800usb_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Add the descriptor in front of the skb. + */ + skb_push(entry->skb, entry->queue->desc_size); + memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry->skb->data; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + /* + * Write entire beacon with descriptor to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, beacon_base, + entry->skb->data, entry->skb->len, + REGISTER_TIMEOUT32(entry->skb->len)); + + /* + * Clean up the beacon skb. + */ + dev_kfree_skb(entry->skb); + entry->skb = NULL; +} + +static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +{ + int length; + + /* + * The length _must_ include 4 bytes padding, + * it should always be multiple of 4, + * but it must _not_ be a multiple of the USB packet size. + */ + length = roundup(entry->skb->len + 4, 4); + length += (4 * !(length % entry->queue->usb_maxpacket)); + + return length; +} + +static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid queue) +{ + u32 reg; + + if (queue != QID_BEACON) { + rt2x00usb_kick_tx_queue(rt2x00dev, queue); + return; + } + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } +} + +/* + * RX control handlers + */ +static void rt2800usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *rxd = (__le32 *)entry->skb->data; + __le32 *rxwi; + u32 rxd0; + u32 rxwi0; + u32 rxwi1; + u32 rxwi2; + u32 rxwi3; + + /* + * Copy descriptor to the skbdesc->desc buffer, making it safe from + * moving of frame data in rt2x00usb. + */ + memcpy(skbdesc->desc, rxd, skbdesc->desc_len); + rxd = (__le32 *)skbdesc->desc; + rxwi = &rxd[RXD_DESC_SIZE / sizeof(__le32)]; + + /* + * It is now safe to read the descriptor on all architectures. + */ + rt2x00_desc_read(rxd, 0, &rxd0); + rt2x00_desc_read(rxwi, 0, &rxwi0); + rt2x00_desc_read(rxwi, 1, &rxwi1); + rt2x00_desc_read(rxwi, 2, &rxwi2); + rt2x00_desc_read(rxwi, 3, &rxwi3); + + if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; + + if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { + rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); + rxdesc->cipher_status = + rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); + } + + if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { + /* + * Hardware has stripped IV/EIV data from 802.11 frame during + * decryption. Unfortunately the descriptor doesn't contain + * any fields with the EIV/IV data either, so they can't + * be restored by rt2x00lib. + */ + rxdesc->flags |= RX_FLAG_IV_STRIPPED; + + if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) + rxdesc->flags |= RX_FLAG_DECRYPTED; + else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) + rxdesc->flags |= RX_FLAG_MMIC_ERROR; + } + + if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; + + if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) + rxdesc->dev_flags |= RXDONE_L2PAD; + + if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) + rxdesc->flags |= RX_FLAG_SHORT_GI; + + if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) + rxdesc->flags |= RX_FLAG_40MHZ; + + /* + * Detect RX rate, always use MCS as signal type. + */ + rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; + rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); + rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); + + /* + * Mask of 0x8 bit to remove the short preamble flag. + */ + if (rxdesc->rate_mode == RATE_MODE_CCK) + rxdesc->signal &= ~0x8; + + rxdesc->rssi = + (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + + rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; + + rxdesc->noise = + (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + + rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; + + rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); + + /* + * Remove RXWI descriptor from start of buffer. + */ + skb_pull(entry->skb, skbdesc->desc_len); + skb_trim(entry->skb, rxdesc->size); +} + +/* + * Device probe functions. + */ +static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) +{ + u16 word; + u8 *mac; + u8 default_lna_gain; + + rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); + + /* + * Start validation of the data that has been read. + */ + 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)); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); + if (word == 0xffff) { + rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); + rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); + rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); + rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); + } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { + /* + * There is a max of 2 RX streams for RT2870 series + */ + if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) + rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); + rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); + if (word == 0xffff) { + rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); + rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); + rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); + rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); + EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); + if ((word & 0x00ff) == 0x00ff) { + rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); + rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, + LED_MODE_TXRX_ACTIVITY); + rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); + EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); + } + + /* + * During the LNA validation we are going to use + * lna0 as correct value. Note that EEPROM_LNA + * is never validated. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); + default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); + if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, + default_lna_gain); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); + if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, + default_lna_gain); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + + return 0; +} + +static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + u16 value; + u16 eeprom; + + /* + * Read EEPROM word for configuration. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + + /* + * Identify RF chipset. + */ + value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00_set_chip(rt2x00dev, RT2870, value, reg); + + /* + * The check for rt2860 is not a typo, some rt2870 hardware + * identifies itself as rt2860 in the CSR register. + */ + if (!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28600000) && + !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28700000) && + !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28800000) && + !rt2x00_check_rev(&rt2x00dev->chip, 0xffff0000, 0x30700000)) { + ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); + return -ENODEV; + } + + if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && + !rt2x00_rf(&rt2x00dev->chip, RF2850) && + !rt2x00_rf(&rt2x00dev->chip, RF2720) && + !rt2x00_rf(&rt2x00dev->chip, RF2750) && + !rt2x00_rf(&rt2x00dev->chip, RF3020) && + !rt2x00_rf(&rt2x00dev->chip, RF2020)) { + ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); + return -ENODEV; + } + + /* + * Identify default antenna configuration. + */ + rt2x00dev->default_ant.tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); + rt2x00dev->default_ant.rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); + + /* + * Read frequency offset and RF programming sequence. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); + + /* + * Read external LNA informations. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + + if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) + __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) + __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + + /* + * 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. + */ +#ifdef CONFIG_RT2X00_LIB_LEDS + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, + &rt2x00dev->led_mcu_reg); +#endif /* CONFIG_RT2X00_LIB_LEDS */ + + return 0; +} + +/* + * RF value list for rt2870 + * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) + */ +static const struct rf_channel rf_vals[] = { + { 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b }, + { 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f }, + { 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b }, + { 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f }, + { 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b }, + { 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f }, + { 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b }, + { 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f }, + { 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b }, + { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f }, + { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b }, + { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f }, + { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b }, + { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 }, + { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 }, + { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 }, + { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 }, + { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b }, + { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b }, + { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 }, + { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 }, + { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b }, + { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 }, + { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 }, + { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 }, + + /* 802.11 HyperLan 2 */ + { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, + { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 }, + { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 }, + { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 }, + { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, + { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, + { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, + { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 }, + { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 }, + { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 }, + { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b }, + { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 }, + { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b }, + { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 }, + { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b }, + { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 }, + + /* 802.11 UNII */ + { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 }, + { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 }, + { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f }, + { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f }, + { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 }, + { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 }, + { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 }, + { 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f }, + { 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 }, + { 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 }, + { 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f }, + + /* 802.11 Japan */ + { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b }, + { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 }, + { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b }, + { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 }, + { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 }, + { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b }, + { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 }, +}; + +/* + * RF value list for rt3070 + * Supports: 2.4 GHz + */ +static const struct rf_channel rf_vals_3070[] = { + {1, 241, 2, 2 }, + {2, 241, 2, 7 }, + {3, 242, 2, 2 }, + {4, 242, 2, 7 }, + {5, 243, 2, 2 }, + {6, 243, 2, 7 }, + {7, 244, 2, 2 }, + {8, 244, 2, 7 }, + {9, 245, 2, 2 }, + {10, 245, 2, 7 }, + {11, 246, 2, 2 }, + {12, 246, 2, 7 }, + {13, 247, 2, 2 }, + {14, 248, 2, 4 }, +}; + +static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) +{ + struct hw_mode_spec *spec = &rt2x00dev->spec; + struct channel_info *info; + char *tx_power1; + char *tx_power2; + unsigned int i; + u16 eeprom; + + /* + * Initialize all hw fields. + */ + rt2x00dev->hw->flags = + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; + rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; + + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + + /* + * Initialize HT information. + */ + spec->ht.ht_supported = true; + spec->ht.cap = + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_TX_STBC | + IEEE80211_HT_CAP_RX_STBC | + IEEE80211_HT_CAP_PSMP_SUPPORT; + spec->ht.ampdu_factor = 3; + spec->ht.ampdu_density = 4; + spec->ht.mcs.tx_params = + IEEE80211_HT_MCS_TX_DEFINED | + IEEE80211_HT_MCS_TX_RX_DIFF | + ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); + + switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { + case 3: + spec->ht.mcs.rx_mask[2] = 0xff; + case 2: + spec->ht.mcs.rx_mask[1] = 0xff; + case 1: + spec->ht.mcs.rx_mask[0] = 0xff; + spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ + break; + } + + /* + * Initialize hw_mode information. + */ + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; + + if (rt2x00_rf(&rt2x00dev->chip, RF2820) || + rt2x00_rf(&rt2x00dev->chip, RF2720)) { + spec->num_channels = 14; + spec->channels = rf_vals; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || + rt2x00_rf(&rt2x00dev->chip, RF2750)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; + spec->num_channels = ARRAY_SIZE(rf_vals); + spec->channels = rf_vals; + } else if (rt2x00_rf(&rt2x00dev->chip, RF3020) || + rt2x00_rf(&rt2x00dev->chip, RF2020)) { + spec->num_channels = ARRAY_SIZE(rf_vals_3070); + spec->channels = rf_vals_3070; + } + + /* + * Create channel information array + */ + info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + spec->channels_info = info; + + tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); + tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + + for (i = 0; i < 14; i++) { + info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); + info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); + } + + if (spec->num_channels > 14) { + tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); + tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); + + for (i = 14; i < spec->num_channels; i++) { + info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); + info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); + } + } + + return 0; +} + +static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) +{ + int retval; + + /* + * Allocate eeprom data. + */ + retval = rt2800usb_validate_eeprom(rt2x00dev); + if (retval) + return retval; + + retval = rt2800usb_init_eeprom(rt2x00dev); + if (retval) + return retval; + + /* + * Initialize hw specifications. + */ + retval = rt2800usb_probe_hw_mode(rt2x00dev); + if (retval) + return retval; + + /* + * This device requires firmware. + */ + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + if (!modparam_nohwcrypt) + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + + /* + * Set the rssi offset. + */ + rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + + return 0; +} + +/* + * IEEE80211 stack callback functions. + */ +static void rt2800usb_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, + u32 *iv32, u16 *iv16) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + + offset = MAC_IVEIV_ENTRY(hw_key_idx); + rt2x00usb_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); + memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); +} + +static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u32 reg; + bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); + + rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); + rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + return 0; +} + +static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, + const struct ieee80211_tx_queue_params *params) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + struct rt2x00_field32 field; + int retval; + u32 reg; + u32 offset; + + /* + * First pass the configuration through rt2x00lib, that will + * update the queue settings and validate the input. After that + * we are free to update the registers based on the value + * in the queue parameter. + */ + retval = rt2x00mac_conf_tx(hw, queue_idx, params); + if (retval) + return retval; + + /* + * We only need to perform additional register initialization + * for WMM queues/ + */ + if (queue_idx >= 4) + return 0; + + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + + /* Update WMM TXOP register */ + offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); + field.bit_offset = (queue_idx & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, queue->txop); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + /* Update WMM registers */ + field.bit_offset = queue_idx * 4; + field.bit_mask = 0xf << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); + rt2x00_set_field32(®, field, queue->aifs); + rt2x00usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_min); + rt2x00usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_max); + rt2x00usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); + + /* Update EDCA registers */ + offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); + rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + return 0; +} + +static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u64 tsf; + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW1, ®); + tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; + rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW0, ®); + tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); + + return tsf; +} + +static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .configure_filter = rt2x00mac_configure_filter, + .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, + .get_tkip_seq = rt2800usb_get_tkip_seq, + .set_rts_threshold = rt2800usb_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800usb_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, + .get_tsf = rt2800usb_get_tsf, +}; + +static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { + .probe_hw = rt2800usb_probe_hw, + .get_firmware_name = rt2800usb_get_firmware_name, + .check_firmware = rt2800usb_check_firmware, + .load_firmware = rt2800usb_load_firmware, + .initialize = rt2x00usb_initialize, + .uninitialize = rt2x00usb_uninitialize, + .clear_entry = rt2x00usb_clear_entry, + .set_device_state = rt2800usb_set_device_state, + .rfkill_poll = rt2800usb_rfkill_poll, + .link_stats = rt2800usb_link_stats, + .reset_tuner = rt2800usb_reset_tuner, + .link_tuner = rt2800usb_link_tuner, + .write_tx_desc = rt2800usb_write_tx_desc, + .write_tx_data = rt2x00usb_write_tx_data, + .write_beacon = rt2800usb_write_beacon, + .get_tx_data_len = rt2800usb_get_tx_data_len, + .kick_tx_queue = rt2800usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_tx_queue, + .fill_rxdone = rt2800usb_fill_rxdone, + .config_shared_key = rt2800usb_config_shared_key, + .config_pairwise_key = rt2800usb_config_pairwise_key, + .config_filter = rt2800usb_config_filter, + .config_intf = rt2800usb_config_intf, + .config_erp = rt2800usb_config_erp, + .config_ant = rt2800usb_config_ant, + .config = rt2800usb_config, +}; + +static const struct data_queue_desc rt2800usb_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = AGGREGATION_SIZE, + .desc_size = RXD_DESC_SIZE + RXWI_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb), +}; + +static const struct data_queue_desc rt2800usb_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = AGGREGATION_SIZE, + .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb), +}; + +static const struct data_queue_desc rt2800usb_queue_bcn = { + .entry_num = 8 * BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb), +}; + +static const struct rt2x00_ops rt2800usb_ops = { + .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 8, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .tx_queues = NUM_TX_QUEUES, + .rx = &rt2800usb_queue_rx, + .tx = &rt2800usb_queue_tx, + .bcn = &rt2800usb_queue_bcn, + .lib = &rt2800usb_rt2x00_ops, + .hw = &rt2800usb_mac80211_ops, +#ifdef CONFIG_RT2X00_LIB_DEBUGFS + .debugfs = &rt2800usb_rt2x00debug, +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +}; + +/* + * rt2800usb module information. + */ +static struct usb_device_id rt2800usb_device_table[] = { + /* Abocom */ + { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AirTies */ + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Amigo */ + { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Amit */ + { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AzureWave */ + { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Belkin */ + { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Buffalo */ + { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Conceptronic */ + { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Corega */ + { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* D-Link */ + { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Edimax */ + { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Encore */ + { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* EnGenius */ + { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gemtek */ + { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gigabyte */ + { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Hawking */ + { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* I-O DATA */ + { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* LevelOne */ + { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Linksys */ + { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Logitec */ + { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Motorola */ + { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ovislink */ + { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Pegatron */ + { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Philips */ + { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Planex */ + { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Qcom */ + { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Quanta */ + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ralink */ + { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Samsung */ + { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Siemens */ + { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sitecom */ + { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* SMC */ + { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sparklan */ + { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sweex */ + { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* U-Media*/ + { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ZCOM */ + { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zinwell */ + { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zyxel */ + { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { 0, } +}; + +MODULE_AUTHOR(DRV_PROJECT); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver."); +MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards"); +MODULE_DEVICE_TABLE(usb, rt2800usb_device_table); +MODULE_FIRMWARE(FIRMWARE_RT2870); +MODULE_LICENSE("GPL"); + +static struct usb_driver rt2800usb_driver = { + .name = KBUILD_MODNAME, + .id_table = rt2800usb_device_table, + .probe = rt2x00usb_probe, + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, +}; + +static int __init rt2800usb_init(void) +{ + return usb_register(&rt2800usb_driver); +} + +static void __exit rt2800usb_exit(void) +{ + usb_deregister(&rt2800usb_driver); +} + +module_init(rt2800usb_init); +module_exit(rt2800usb_exit); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h new file mode 100644 index 000000000000..61a8be61d3f5 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -0,0 +1,1945 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + 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: rt2800usb + Abstract: Data structures and registers for the rt2800usb module. + Supported chipsets: RT2800U. + */ + +#ifndef RT2800USB_H +#define RT2800USB_H + +/* + * RF chip defines. + * + * RF2820 2.4G 2T3R + * RF2850 2.4G/5G 2T3R + * RF2720 2.4G 1T2R + * RF2750 2.4G/5G 1T2R + * RF3020 2.4G 1T1R + * RF2020 2.4G B/G + */ +#define RF2820 0x0001 +#define RF2850 0x0002 +#define RF2720 0x0003 +#define RF2750 0x0004 +#define RF3020 0x0005 +#define RF2020 0x0006 + +/* + * RT2870 version + */ +#define RT2860C_VERSION 0x28600100 +#define RT2860D_VERSION 0x28600101 +#define RT2880E_VERSION 0x28720200 +#define RT2883_VERSION 0x28830300 +#define RT3070_VERSION 0x30700200 + +/* + * Signal information. + * Defaul offset is required for RSSI <-> dBm conversion. + */ +#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ + +/* + * Register layout information. + */ +#define CSR_REG_BASE 0x1000 +#define CSR_REG_SIZE 0x0800 +#define EEPROM_BASE 0x0000 +#define EEPROM_SIZE 0x0110 +#define BBP_BASE 0x0000 +#define BBP_SIZE 0x0080 +#define RF_BASE 0x0004 +#define RF_SIZE 0x0010 + +/* + * Number of TX queues. + */ +#define NUM_TX_QUEUES 4 + +/* + * USB registers. + */ + +/* + * HOST-MCU shared memory + */ +#define HOST_CMD_CSR 0x0404 +#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) + +/* + * INT_SOURCE_CSR: Interrupt source register. + * Write one to clear corresponding bit. + * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c + */ +#define INT_SOURCE_CSR 0x0200 +#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) +#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) +#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) +#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. + */ +#define INT_MASK_CSR 0x0204 +#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) +#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_MASK_CSR_TBTT FIELD32(0x00000800) +#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) +#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * WPDMA_GLO_CFG + */ +#define WPDMA_GLO_CFG 0x0208 +#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) +#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) +#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) +#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) +#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) +#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) +#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) +#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) +#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) + +/* + * WPDMA_RST_IDX + */ +#define WPDMA_RST_IDX 0x020c +#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) +#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) +#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) +#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) +#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) +#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) +#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) + +/* + * DELAY_INT_CFG + */ +#define DELAY_INT_CFG 0x0210 +#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) +#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) +#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) +#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) +#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) +#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) + +/* + * WMM_AIFSN_CFG: Aifsn for each EDCA AC + * AIFSN0: AC_BE + * AIFSN1: AC_BK + * AIFSN1: AC_VI + * AIFSN1: AC_VO + */ +#define WMM_AIFSN_CFG 0x0214 +#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) +#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) +#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) +#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) + +/* + * WMM_CWMIN_CSR: CWmin for each EDCA AC + * CWMIN0: AC_BE + * CWMIN1: AC_BK + * CWMIN1: AC_VI + * CWMIN1: AC_VO + */ +#define WMM_CWMIN_CFG 0x0218 +#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) +#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) +#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) +#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) + +/* + * WMM_CWMAX_CSR: CWmax for each EDCA AC + * CWMAX0: AC_BE + * CWMAX1: AC_BK + * CWMAX1: AC_VI + * CWMAX1: AC_VO + */ +#define WMM_CWMAX_CFG 0x021c +#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) +#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) +#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) +#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) + +/* + * AC_TXOP0: AC_BK/AC_BE TXOP register + * AC0TXOP: AC_BK in unit of 32us + * AC1TXOP: AC_BE in unit of 32us + */ +#define WMM_TXOP0_CFG 0x0220 +#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) +#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) + +/* + * AC_TXOP1: AC_VO/AC_VI TXOP register + * AC2TXOP: AC_VI in unit of 32us + * AC3TXOP: AC_VO in unit of 32us + */ +#define WMM_TXOP1_CFG 0x0224 +#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) +#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) + +/* + * GPIO_CTRL_CFG: + */ +#define GPIO_CTRL_CFG 0x0228 +#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) +#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) +#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) +#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) +#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) +#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) +#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) +#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) +#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) + +/* + * MCU_CMD_CFG + */ +#define MCU_CMD_CFG 0x022c + +/* + * AC_BK register offsets + */ +#define TX_BASE_PTR0 0x0230 +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c + +/* + * AC_BE register offsets + */ +#define TX_BASE_PTR1 0x0240 +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c + +/* + * AC_VI register offsets + */ +#define TX_BASE_PTR2 0x0250 +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c + +/* + * AC_VO register offsets + */ +#define TX_BASE_PTR3 0x0260 +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c + +/* + * HCCA register offsets + */ +#define TX_BASE_PTR4 0x0270 +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c + +/* + * MGMT register offsets + */ +#define TX_BASE_PTR5 0x0280 +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c + +/* + * RX register offsets + */ +#define RX_BASE_PTR 0x0290 +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + +/* + * USB_DMA_CFG + * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. + * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. + * PHY_CLEAR: phy watch dog enable. + * TX_CLEAR: Clear USB DMA TX path. + * TXOP_HALT: Halt TXOP count down when TX buffer is full. + * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. + * RX_BULK_EN: Enable USB DMA Rx. + * TX_BULK_EN: Enable USB DMA Tx. + * EP_OUT_VALID: OUT endpoint data valid. + * RX_BUSY: USB DMA RX FSM busy. + * TX_BUSY: USB DMA TX FSM busy. + */ +#define USB_DMA_CFG 0x02a0 +#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) +#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) +#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) +#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) +#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) +#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) +#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) +#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) +#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) +#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) +#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) + +/* + * USB_CYC_CFG + */ +#define USB_CYC_CFG 0x02a4 +#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) + +/* + * PBF_SYS_CTRL + * HOST_RAM_WRITE: enable Host program ram write selection + */ +#define PBF_SYS_CTRL 0x0400 +#define PBF_SYS_CTRL_READY FIELD32(0x00000080) +#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040c +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 + +/* + * BCN_OFFSET0: + */ +#define BCN_OFFSET0 0x042c +#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) +#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) +#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) +#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) + +/* + * BCN_OFFSET1: + */ +#define BCN_OFFSET1 0x0430 +#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) +#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) +#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) +#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c + +/* + * RF registers + */ +#define RF_CSR_CFG 0x0500 +#define RF_CSR_CFG_DATA FIELD32(0x000000ff) +#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) +#define RF_CSR_CFG_WRITE FIELD32(0x00010000) +#define RF_CSR_CFG_BUSY FIELD32(0x00020000) + +/* + * MAC Control/Status Registers(CSR). + * Some values are set in TU, whereas 1 TU == 1024 us. + */ + +/* + * MAC_CSR0: ASIC revision number. + * ASIC_REV: 0 + * ASIC_VER: 2870 + */ +#define MAC_CSR0 0x1000 +#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) +#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) + +/* + * MAC_SYS_CTRL: + */ +#define MAC_SYS_CTRL 0x1004 +#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) +#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) +#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) +#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) +#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) +#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) +#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) +#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) + +/* + * MAC_ADDR_DW0: STA MAC register 0 + */ +#define MAC_ADDR_DW0 0x1008 +#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_ADDR_DW1: STA MAC register 1 + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK + */ +#define MAC_ADDR_DW1 0x100c +#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) + +/* + * MAC_BSSID_DW0: BSSID register 0 + */ +#define MAC_BSSID_DW0 0x1010 +#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_BSSID_DW1: BSSID register 1 + * BSS_ID_MASK: + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) + * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) + * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + */ +#define MAC_BSSID_DW1 0x1014 +#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) +#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) + +/* + * MAX_LEN_CFG: Maximum frame length register. + * MAX_MPDU: rt2860b max 16k bytes + * MAX_PSDU: Maximum PSDU length + * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 + */ +#define MAX_LEN_CFG 0x1018 +#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) +#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) +#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) +#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) + +/* + * BBP_CSR_CFG: BBP serial control register + * VALUE: Register value to program into BBP + * REG_NUM: Selected BBP register + * READ_CONTROL: 0 write BBP, 1 read BBP + * BUSY: ASIC is busy executing BBP commands + * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks + * BBP_RW_MODE: 0 serial, 1 paralell + */ +#define BBP_CSR_CFG 0x101c +#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) +#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) +#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) +#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) +#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) +#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) + +/* + * RF_CSR_CFG0: RF control register + * REGID_AND_VALUE: Register value to program into RF + * BITWIDTH: Selected RF register + * STANDBYMODE: 0 high when standby, 1 low when standby + * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate + * BUSY: ASIC is busy executing RF commands + */ +#define RF_CSR_CFG0 0x1020 +#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) +#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) +#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) +#define RF_CSR_CFG0_SEL FIELD32(0x40000000) +#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) + +/* + * RF_CSR_CFG1: RF control register + * REGID_AND_VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG1 0x1024 +#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) + +/* + * RF_CSR_CFG2: RF control register + * VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG2 0x1028 +#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) + +/* + * LED_CFG: LED control + * color LED's: + * 0: off + * 1: blinking upon TX2 + * 2: periodic slow blinking + * 3: always on + * LED polarity: + * 0: active low + * 1: active high + */ +#define LED_CFG 0x102c +#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) +#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) +#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) +#define LED_CFG_R_LED_MODE FIELD32(0x03000000) +#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) +#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) +#define LED_CFG_LED_POLAR FIELD32(0x40000000) + +/* + * XIFS_TIME_CFG: MAC timing + * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX + * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX + * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX + * when MAC doesn't reference BBP signal BBRXEND + * EIFS: unit 1us + * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer + * + */ +#define XIFS_TIME_CFG 0x1100 +#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) +#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) +#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) +#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) +#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) + +/* + * BKOFF_SLOT_CFG: + */ +#define BKOFF_SLOT_CFG 0x1104 +#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) +#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) + +/* + * NAV_TIME_CFG: + */ +#define NAV_TIME_CFG 0x1108 +#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) +#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) +#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) +#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) + +/* + * CH_TIME_CFG: count as channel busy + */ +#define CH_TIME_CFG 0x110c + +/* + * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us + */ +#define PBF_LIFE_TIMER 0x1110 + +/* + * BCN_TIME_CFG: + * BEACON_INTERVAL: in unit of 1/16 TU + * TSF_TICKING: Enable TSF auto counting + * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + * BEACON_GEN: Enable beacon generator + */ +#define BCN_TIME_CFG 0x1114 +#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) +#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) +#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) +#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) +#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) +#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) + +/* + * TBTT_SYNC_CFG: + */ +#define TBTT_SYNC_CFG 0x1118 + +/* + * TSF_TIMER_DW0: Local lsb TSF timer, read-only + */ +#define TSF_TIMER_DW0 0x111c +#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) + +/* + * TSF_TIMER_DW1: Local msb TSF timer, read-only + */ +#define TSF_TIMER_DW1 0x1120 +#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) + +/* + * TBTT_TIMER: TImer remains till next TBTT, read-only + */ +#define TBTT_TIMER 0x1124 + +/* + * INT_TIMER_CFG: + */ +#define INT_TIMER_CFG 0x1128 + +/* + * INT_TIMER_EN: GP-timer and pre-tbtt Int enable + */ +#define INT_TIMER_EN 0x112c + +/* + * CH_IDLE_STA: channel idle time + */ +#define CH_IDLE_STA 0x1130 + +/* + * CH_BUSY_STA: channel busy time + */ +#define CH_BUSY_STA 0x1134 + +/* + * MAC_STATUS_CFG: + * BBP_RF_BUSY: When set to 0, BBP and RF are stable. + * if 1 or higher one of the 2 registers is busy. + */ +#define MAC_STATUS_CFG 0x1200 +#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) + +/* + * PWR_PIN_CFG: + */ +#define PWR_PIN_CFG 0x1204 + +/* + * AUTOWAKEUP_CFG: Manual power control / status register + * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set + * AUTOWAKE: 0:sleep, 1:awake + */ +#define AUTOWAKEUP_CFG 0x1208 +#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) +#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) +#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) + +/* + * EDCA_AC0_CFG: + */ +#define EDCA_AC0_CFG 0x1300 +#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC1_CFG: + */ +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC2_CFG: + */ +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC3_CFG: + */ +#define EDCA_AC3_CFG 0x130c +#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_TID_AC_MAP: + */ +#define EDCA_TID_AC_MAP 0x1310 + +/* + * TX_PWR_CFG_0: + */ +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) +#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) +#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) +#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_1: + */ +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) +#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) +#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) +#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_2: + */ +#define TX_PWR_CFG_2 0x131c +#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) +#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) +#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) +#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) +#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) +#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) +#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) +#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_3: + */ +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) +#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) +#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) +#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) +#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) +#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_4: + */ +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) +#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) +#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) +#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) + +/* + * TX_PIN_CFG: + */ +#define TX_PIN_CFG 0x1328 +#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) +#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) +#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) +#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) +#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) +#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) +#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) +#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) +#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) +#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) +#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) +#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) +#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) +#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) +#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) +#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) +#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) +#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) +#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) +#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) + +/* + * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz + */ +#define TX_BAND_CFG 0x132c +#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_A FIELD32(0x00000002) +#define TX_BAND_CFG_BG FIELD32(0x00000004) + +/* + * TX_SW_CFG0: + */ +#define TX_SW_CFG0 0x1330 + +/* + * TX_SW_CFG1: + */ +#define TX_SW_CFG1 0x1334 + +/* + * TX_SW_CFG2: + */ +#define TX_SW_CFG2 0x1338 + +/* + * TXOP_THRES_CFG: + */ +#define TXOP_THRES_CFG 0x133c + +/* + * TXOP_CTRL_CFG: + */ +#define TXOP_CTRL_CFG 0x1340 + +/* + * TX_RTS_CFG: + * RTS_THRES: unit:byte + * RTS_FBK_EN: enable rts rate fallback + */ +#define TX_RTS_CFG 0x1344 +#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) +#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) +#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) + +/* + * TX_TIMEOUT_CFG: + * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us + * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure + * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. + * it is recommended that: + * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + */ +#define TX_TIMEOUT_CFG 0x1348 +#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) +#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) +#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) + +/* + * TX_RTY_CFG: + * SHORT_RTY_LIMIT: short retry limit + * LONG_RTY_LIMIT: long retry limit + * LONG_RTY_THRE: Long retry threshoold + * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * AGG_RTY_MODE: Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable + */ +#define TX_RTY_CFG 0x134c +#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) +#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) +#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) +#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) +#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) +#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) + +/* + * TX_LINK_CFG: + * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us + * MFB_ENABLE: TX apply remote MFB 1:enable + * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable + * 0: not apply remote remote unsolicit (MFS=7) + * TX_MRQ_EN: MCS request TX enable + * TX_RDG_EN: RDG TX enable + * TX_CF_ACK_EN: Piggyback CF-ACK enable + * REMOTE_MFB: remote MCS feedback + * REMOTE_MFS: remote MCS feedback sequence number + */ +#define TX_LINK_CFG 0x1350 +#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) +#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) +#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) +#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) +#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) +#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) +#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) +#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) + +/* + * HT_FBK_CFG0: + */ +#define HT_FBK_CFG0 0x1354 +#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) +#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) +#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) +#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) +#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) +#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) +#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) +#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) + +/* + * HT_FBK_CFG1: + */ +#define HT_FBK_CFG1 0x1358 +#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) +#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) +#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) +#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) +#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) +#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) +#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) +#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG0: + */ +#define LG_FBK_CFG0 0x135c +#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) +#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) +#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) +#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) +#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG1: + */ +#define LG_FBK_CFG1 0x1360 +#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) + +/* + * CCK_PROT_CFG: CCK Protection + * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) + * PROTECT_CTRL: Protection control frame type for CCK TX + * 0:none, 1:RTS/CTS, 2:CTS-to-self + * PROTECT_NAV: TXOP protection type for CCK TX + * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect + * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow + * RTS_TH_EN: RTS threshold enable on CCK TX + */ +#define CCK_PROT_CFG 0x1364 +#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * OFDM_PROT_CFG: OFDM Protection + */ +#define OFDM_PROT_CFG 0x1368 +#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM20_PROT_CFG: MM20 Protection + */ +#define MM20_PROT_CFG 0x136c +#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM40_PROT_CFG: MM40 Protection + */ +#define MM40_PROT_CFG 0x1370 +#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF20_PROT_CFG: GF20 Protection + */ +#define GF20_PROT_CFG 0x1374 +#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF40_PROT_CFG: GF40 Protection + */ +#define GF40_PROT_CFG 0x1378 +#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * EXP_CTS_TIME: + */ +#define EXP_CTS_TIME 0x137c + +/* + * EXP_ACK_TIME: + */ +#define EXP_ACK_TIME 0x1380 + +/* + * RX_FILTER_CFG: RX configuration register. + */ +#define RX_FILTER_CFG 0x1400 +#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) +#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) +#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) +#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) +#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) +#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) +#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) +#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) +#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) +#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) +#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) +#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) +#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) +#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) +#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) +#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) +#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) + +/* + * AUTO_RSP_CFG: + * AUTORESPONDER: 0: disable, 1: enable + * BAC_ACK_POLICY: 0:long, 1:short preamble + * CTS_40_MMODE: Response CTS 40MHz duplicate mode + * CTS_40_MREF: Response CTS 40MHz duplicate mode + * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble + * DUAL_CTS_EN: Power bit value in control frame + * ACK_CTS_PSM_BIT:Power bit value in control frame + */ +#define AUTO_RSP_CFG 0x1404 +#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) +#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) +#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) +#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) +#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) +#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) +#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) + +/* + * LEGACY_BASIC_RATE: + */ +#define LEGACY_BASIC_RATE 0x1408 + +/* + * HT_BASIC_RATE: + */ +#define HT_BASIC_RATE 0x140c + +/* + * HT_CTRL_CFG: + */ +#define HT_CTRL_CFG 0x1410 + +/* + * SIFS_COST_CFG: + */ +#define SIFS_COST_CFG 0x1414 + +/* + * RX_PARSER_CFG: + * Set NAV for all received frames + */ +#define RX_PARSER_CFG 0x1418 + +/* + * TX_SEC_CNT0: + */ +#define TX_SEC_CNT0 0x1500 + +/* + * RX_SEC_CNT0: + */ +#define RX_SEC_CNT0 0x1504 + +/* + * CCMP_FC_MUTE: + */ +#define CCMP_FC_MUTE 0x1508 + +/* + * TXOP_HLDR_ADDR0: + */ +#define TXOP_HLDR_ADDR0 0x1600 + +/* + * TXOP_HLDR_ADDR1: + */ +#define TXOP_HLDR_ADDR1 0x1604 + +/* + * TXOP_HLDR_ET: + */ +#define TXOP_HLDR_ET 0x1608 + +/* + * QOS_CFPOLL_RA_DW0: + */ +#define QOS_CFPOLL_RA_DW0 0x160c + +/* + * QOS_CFPOLL_RA_DW1: + */ +#define QOS_CFPOLL_RA_DW1 0x1610 + +/* + * QOS_CFPOLL_QC: + */ +#define QOS_CFPOLL_QC 0x1614 + +/* + * RX_STA_CNT0: RX PLCP error count & RX CRC error count + */ +#define RX_STA_CNT0 0x1700 +#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) +#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT1: RX False CCA count & RX LONG frame count + */ +#define RX_STA_CNT1 0x1704 +#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) +#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT2: + */ +#define RX_STA_CNT2 0x1708 +#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) +#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) + +/* + * TX_STA_CNT0: TX Beacon count + */ +#define TX_STA_CNT0 0x170c +#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) + +/* + * TX_STA_CNT1: TX tx count + */ +#define TX_STA_CNT1 0x1710 +#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) +#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) + +/* + * TX_STA_CNT2: TX tx count + */ +#define TX_STA_CNT2 0x1714 +#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) + +/* + * TX_STA_FIFO: TX Result for specific PID status fifo register + */ +#define TX_STA_FIFO 0x1718 +#define TX_STA_FIFO_VALID FIELD32(0x00000001) +#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) +#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) +#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) +#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) +#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) +#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) + +/* + * TX_AGG_CNT: Debug counter + */ +#define TX_AGG_CNT 0x171c +#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT0: + */ +#define TX_AGG_CNT0 0x1720 +#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT1: + */ +#define TX_AGG_CNT1 0x1724 +#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT2: + */ +#define TX_AGG_CNT2 0x1728 +#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT3: + */ +#define TX_AGG_CNT3 0x172c +#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT4: + */ +#define TX_AGG_CNT4 0x1730 +#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT5: + */ +#define TX_AGG_CNT5 0x1734 +#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT6: + */ +#define TX_AGG_CNT6 0x1738 +#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT7: + */ +#define TX_AGG_CNT7 0x173c +#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) + +/* + * MPDU_DENSITY_CNT: + * TX_ZERO_DEL: TX zero length delimiter count + * RX_ZERO_DEL: RX zero length delimiter count + */ +#define MPDU_DENSITY_CNT 0x1740 +#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) +#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) + +/* + * Security key table memory. + * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry + * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry + * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry + * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry + * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry + * SHARED_KEY_MODE_BASE: 4-byte * 16-entry + */ +#define MAC_WCID_BASE 0x1800 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 +#define MAC_IVEIV_TABLE_BASE 0x6000 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 +#define SHARED_KEY_TABLE_BASE 0x6c00 +#define SHARED_KEY_MODE_BASE 0x7000 + +#define MAC_WCID_ENTRY(__idx) \ + ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) +#define PAIRWISE_KEY_ENTRY(__idx) \ + ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define MAC_IVEIV_ENTRY(__idx) \ + ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) +#define MAC_WCID_ATTR_ENTRY(__idx) \ + ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) +#define SHARED_KEY_ENTRY(__idx) \ + ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define SHARED_KEY_MODE_ENTRY(__idx) \ + ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + +struct mac_wcid_entry { + u8 mac[6]; + u8 reserved[2]; +} __attribute__ ((packed)); + +struct hw_key_entry { + u8 key[16]; + u8 tx_mic[8]; + u8 rx_mic[8]; +} __attribute__ ((packed)); + +struct mac_iveiv_entry { + u8 iv[8]; +} __attribute__ ((packed)); + +/* + * MAC_WCID_ATTRIBUTE: + */ +#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) +#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) +#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) +#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) + +/* + * SHARED_KEY_MODE: + */ +#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) +#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) +#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) +#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) +#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) +#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) +#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) +#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) + +/* + * HOST-MCU communication + */ + +/* + * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. + */ +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) +#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) + +/* + * H2M_MAILBOX_CID: + */ +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) +#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) + +/* + * H2M_MAILBOX_STATUS: + */ +#define H2M_MAILBOX_STATUS 0x701c + +/* + * H2M_INT_SRC: + */ +#define H2M_INT_SRC 0x7024 + +/* + * H2M_BBP_AGENT: + */ +#define H2M_BBP_AGENT 0x7028 + +/* + * MCU_LEDCS: LED control for MCU Mailbox. + */ +#define MCU_LEDCS_LED_MODE FIELD8(0x1f) +#define MCU_LEDCS_POLARITY FIELD8(0x01) + +/* + * HW_CS_CTS_BASE: + * Carrier-sense CTS frame base address. + * It's where mac stores carrier-sense frame for carrier-sense function. + */ +#define HW_CS_CTS_BASE 0x7700 + +/* + * HW_DFS_CTS_BASE: + * FS CTS frame base address. It's where mac stores CTS frame for DFS. + */ +#define HW_DFS_CTS_BASE 0x7780 + +/* + * TXRX control registers - base address 0x3000 + */ + +/* + * TXRX_CSR1: + * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. + */ +#define TXRX_CSR1 0x77d0 + +/* + * HW_DEBUG_SETTING_BASE: + * since NULL frame won't be that long (256 byte) + * We steal 16 tail bytes to save debugging settings + */ +#define HW_DEBUG_SETTING_BASE 0x77f0 +#define HW_DEBUG_SETTING_BASE2 0x7770 + +/* + * HW_BEACON_BASE + * In order to support maximum 8 MBSS and its maximum length + * is 512 bytes for each beacon + * Three section discontinue memory segments will be used. + * 1. The original region for BCN 0~3 + * 2. Extract memory from FCE table for BCN 4~5 + * 3. Extract memory from Pair-wise key table for BCN 6~7 + * It occupied those memory of wcid 238~253 for BCN 6 + * and wcid 222~237 for BCN 7 + * + * IMPORTANT NOTE: Not sure why legacy driver does this, + * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. + */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7a00 +#define HW_BEACON_BASE2 0x7c00 +#define HW_BEACON_BASE3 0x7e00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5dc0 +#define HW_BEACON_BASE7 0x5bc0 + +#define HW_BEACON_OFFSET(__index) \ + ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ + (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) + +/* + * 8051 firmware image. + */ +#define FIRMWARE_RT2870 "rt2870.bin" +#define FIRMWARE_IMAGE_BASE 0x3000 + +/* + * BBP registers. + * The wordsize of the BBP is 8 bits. + */ + +/* + * BBP 1: TX Antenna + */ +#define BBP1_TX_POWER FIELD8(0x07) +#define BBP1_TX_ANTENNA FIELD8(0x18) + +/* + * BBP 3: RX Antenna + */ +#define BBP3_RX_ANTENNA FIELD8(0x18) +#define BBP3_HT40_PLUS FIELD8(0x20) + +/* + * BBP 4: Bandwidth + */ +#define BBP4_TX_BF FIELD8(0x01) +#define BBP4_BANDWIDTH FIELD8(0x18) + +/* + * RFCSR registers + * The wordsize of the RFCSR is 8 bits. + */ + +/* + * RFCSR 6: + */ +#define RFCSR6_R FIELD8(0x03) + +/* + * RFCSR 7: + */ +#define RFCSR7_RF_TUNING FIELD8(0x01) + +/* + * RFCSR 12: + */ +#define RFCSR12_TX_POWER FIELD8(0x1f) + +/* + * RFCSR 22: + */ +#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) + +/* + * RFCSR 23: + */ +#define RFCSR23_FREQ_OFFSET FIELD8(0x7f) + +/* + * RFCSR 30: + */ +#define RFCSR30_RF_CALIBRATION FIELD8(0x80) + +/* + * RF registers + */ + +/* + * RF 2 + */ +#define RF2_ANTENNA_RX2 FIELD32(0x00000040) +#define RF2_ANTENNA_TX1 FIELD32(0x00004000) +#define RF2_ANTENNA_RX1 FIELD32(0x00020000) + +/* + * RF 3 + */ +#define RF3_TXPOWER_G FIELD32(0x00003e00) +#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) +#define RF3_TXPOWER_A FIELD32(0x00003c00) + +/* + * RF 4 + */ +#define RF4_TXPOWER_G FIELD32(0x000007c0) +#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) +#define RF4_TXPOWER_A FIELD32(0x00000780) +#define RF4_FREQ_OFFSET FIELD32(0x001f8000) +#define RF4_HT40 FIELD32(0x00200000) + +/* + * EEPROM content. + * The wordsize of the EEPROM is 16 bits. + */ + +/* + * EEPROM Version + */ +#define EEPROM_VERSION 0x0001 +#define EEPROM_VERSION_FAE FIELD16(0x00ff) +#define EEPROM_VERSION_VERSION FIELD16(0xff00) + +/* + * HW MAC address. + */ +#define EEPROM_MAC_ADDR_0 0x0002 +#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_1 0x0003 +#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_2 0x0004 +#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) + +/* + * EEPROM ANTENNA config + * RXPATH: 1: 1R, 2: 2R, 3: 3R + * TXPATH: 1: 1T, 2: 2T + */ +#define EEPROM_ANTENNA 0x001a +#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) +#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) +#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) + +/* + * EEPROM NIC config + * CARDBUS_ACCEL: 0 - enable, 1 - disable + */ +#define EEPROM_NIC 0x001b +#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) +#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) +#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) +#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) +#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) +#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) +#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) +#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) +#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) +#define EEPROM_NIC_BW40M_A FIELD16(0x0200) + +/* + * EEPROM frequency + */ +#define EEPROM_FREQ 0x001d +#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) +#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) +#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) + +/* + * EEPROM LED + * POLARITY_RDY_G: Polarity RDY_G setting. + * POLARITY_RDY_A: Polarity RDY_A setting. + * POLARITY_ACT: Polarity ACT setting. + * POLARITY_GPIO_0: Polarity GPIO0 setting. + * POLARITY_GPIO_1: Polarity GPIO1 setting. + * POLARITY_GPIO_2: Polarity GPIO2 setting. + * POLARITY_GPIO_3: Polarity GPIO3 setting. + * POLARITY_GPIO_4: Polarity GPIO4 setting. + * LED_MODE: Led mode. + */ +#define EEPROM_LED1 0x001e +#define EEPROM_LED2 0x001f +#define EEPROM_LED3 0x0020 +#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) +#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) +#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) +#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) +#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) +#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) +#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) +#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) +#define EEPROM_LED_LED_MODE FIELD16(0x1f00) + +/* + * EEPROM LNA + */ +#define EEPROM_LNA 0x0022 +#define EEPROM_LNA_BG FIELD16(0x00ff) +#define EEPROM_LNA_A0 FIELD16(0xff00) + +/* + * EEPROM RSSI BG offset + */ +#define EEPROM_RSSI_BG 0x0023 +#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI BG2 offset + */ +#define EEPROM_RSSI_BG2 0x0024 +#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) + +/* + * EEPROM RSSI A offset + */ +#define EEPROM_RSSI_A 0x0025 +#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI A2 offset + */ +#define EEPROM_RSSI_A2 0x0026 +#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) + +/* + * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. + * This is delta in 40MHZ. + * VALUE: Tx Power dalta value (MAX=4) + * TYPE: 1: Plus the delta value, 0: minus the delta value + * TXPOWER: Enable: + */ +#define EEPROM_TXPOWER_DELTA 0x0028 +#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) +#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) +#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) + +/* + * EEPROM TXPOWER 802.11BG + */ +#define EEPROM_TXPOWER_BG1 0x0029 +#define EEPROM_TXPOWER_BG2 0x0030 +#define EEPROM_TXPOWER_BG_SIZE 7 +#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) + +/* + * EEPROM TXPOWER 802.11A + */ +#define EEPROM_TXPOWER_A1 0x003c +#define EEPROM_TXPOWER_A2 0x0053 +#define EEPROM_TXPOWER_A_SIZE 6 +#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) + +/* + * EEPROM TXpower byrate: 20MHZ power + */ +#define EEPROM_TXPOWER_BYRATE 0x006f + +/* + * EEPROM BBP. + */ +#define EEPROM_BBP_START 0x0078 +#define EEPROM_BBP_SIZE 16 +#define EEPROM_BBP_VALUE FIELD16(0x00ff) +#define EEPROM_BBP_REG_ID FIELD16(0xff00) + +/* + * MCU mailbox commands. + */ +#define MCU_SLEEP 0x30 +#define MCU_WAKEUP 0x31 +#define MCU_RADIO_OFF 0x35 +#define MCU_CURRENT 0x36 +#define MCU_LED 0x50 +#define MCU_LED_STRENGTH 0x51 +#define MCU_LED_1 0x52 +#define MCU_LED_2 0x53 +#define MCU_LED_3 0x54 +#define MCU_RADAR 0x60 +#define MCU_BOOT_SIGNAL 0x72 +#define MCU_BBP_SIGNAL 0x80 +#define MCU_POWER_SAVE 0x83 + +/* + * MCU mailbox tokens + */ +#define TOKEN_WAKUP 3 + +/* + * DMA descriptor defines. + */ +#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) +#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) + +/* + * TX descriptor format for TX, PRIO and Beacon Ring. + */ + +/* + * Word0 + */ +#define TXD_W0_SD_PTR0 FIELD32(0xffffffff) + +/* + * Word1 + */ +#define TXD_W1_SD_LEN1 FIELD32(0x00003fff) +#define TXD_W1_LAST_SEC1 FIELD32(0x00004000) +#define TXD_W1_BURST FIELD32(0x00008000) +#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) +#define TXD_W1_LAST_SEC0 FIELD32(0x40000000) +#define TXD_W1_DMA_DONE FIELD32(0x80000000) + +/* + * Word2 + */ +#define TXD_W2_SD_PTR1 FIELD32(0xffffffff) + +/* + * Word3 + * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI + * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. + * 0:MGMT, 1:HCCA 2:EDCA + */ +#define TXD_W3_WIV FIELD32(0x01000000) +#define TXD_W3_QSEL FIELD32(0x06000000) +#define TXD_W3_TCO FIELD32(0x20000000) +#define TXD_W3_UCO FIELD32(0x40000000) +#define TXD_W3_ICO FIELD32(0x80000000) + +/* + * TX Info structure + */ + +/* + * Word0 + * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI + * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. + * 0:MGMT, 1:HCCA 2:EDCA + * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid + * DMA_TX_BURST: used ONLY in USB bulk Aggregation. + * Force USB DMA transmit frame from current selected endpoint + */ +#define TXINFO_W0_USB_DMA_TX_PKT_LEN FIELD32(0x0000ffff) +#define TXINFO_W0_WIV FIELD32(0x01000000) +#define TXINFO_W0_QSEL FIELD32(0x06000000) +#define TXINFO_W0_SW_USE_LAST_ROUND FIELD32(0x08000000) +#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000) +#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) + +/* + * TX WI structure + */ + +/* + * Word0 + * FRAG: 1 To inform TKIP engine this is a fragment. + * MIMO_PS: The remote peer is in dynamic MIMO-PS mode + * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs + * BW: Channel bandwidth 20MHz or 40 MHz + * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED + */ +#define TXWI_W0_FRAG FIELD32(0x00000001) +#define TXWI_W0_MIMO_PS FIELD32(0x00000002) +#define TXWI_W0_CF_ACK FIELD32(0x00000004) +#define TXWI_W0_TS FIELD32(0x00000008) +#define TXWI_W0_AMPDU FIELD32(0x00000010) +#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) +#define TXWI_W0_TX_OP FIELD32(0x00000300) +#define TXWI_W0_MCS FIELD32(0x007f0000) +#define TXWI_W0_BW FIELD32(0x00800000) +#define TXWI_W0_SHORT_GI FIELD32(0x01000000) +#define TXWI_W0_STBC FIELD32(0x06000000) +#define TXWI_W0_IFS FIELD32(0x08000000) +#define TXWI_W0_PHYMODE FIELD32(0xc0000000) + +/* + * Word1 + */ +#define TXWI_W1_ACK FIELD32(0x00000001) +#define TXWI_W1_NSEQ FIELD32(0x00000002) +#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) +#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) +#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define TXWI_W1_PACKETID FIELD32(0xf0000000) + +/* + * Word2 + */ +#define TXWI_W2_IV FIELD32(0xffffffff) + +/* + * Word3 + */ +#define TXWI_W3_EIV FIELD32(0xffffffff) + +/* + * RX descriptor format for RX Ring. + */ + +/* + * Word0 + * UNICAST_TO_ME: This RX frame is unicast to me. + * MULTICAST: This is a multicast frame. + * BROADCAST: This is a broadcast frame. + * MY_BSS: this frame belongs to the same BSSID. + * CRC_ERROR: CRC error. + * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid. + * AMSDU: rx with 802.3 header, not 802.11 header. + */ + +#define RXD_W0_BA FIELD32(0x00000001) +#define RXD_W0_DATA FIELD32(0x00000002) +#define RXD_W0_NULLDATA FIELD32(0x00000004) +#define RXD_W0_FRAG FIELD32(0x00000008) +#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) +#define RXD_W0_MULTICAST FIELD32(0x00000020) +#define RXD_W0_BROADCAST FIELD32(0x00000040) +#define RXD_W0_MY_BSS FIELD32(0x00000080) +#define RXD_W0_CRC_ERROR FIELD32(0x00000100) +#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) +#define RXD_W0_AMSDU FIELD32(0x00000800) +#define RXD_W0_HTC FIELD32(0x00001000) +#define RXD_W0_RSSI FIELD32(0x00002000) +#define RXD_W0_L2PAD FIELD32(0x00004000) +#define RXD_W0_AMPDU FIELD32(0x00008000) +#define RXD_W0_DECRYPTED FIELD32(0x00010000) +#define RXD_W0_PLCP_RSSI FIELD32(0x00020000) +#define RXD_W0_CIPHER_ALG FIELD32(0x00040000) +#define RXD_W0_LAST_AMSDU FIELD32(0x00080000) +#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) + +/* + * RX WI structure + */ + +/* + * Word0 + */ +#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) +#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) +#define RXWI_W0_BSSID FIELD32(0x00001c00) +#define RXWI_W0_UDF FIELD32(0x0000e000) +#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define RXWI_W0_TID FIELD32(0xf0000000) + +/* + * Word1 + */ +#define RXWI_W1_FRAG FIELD32(0x0000000f) +#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) +#define RXWI_W1_MCS FIELD32(0x007f0000) +#define RXWI_W1_BW FIELD32(0x00800000) +#define RXWI_W1_SHORT_GI FIELD32(0x01000000) +#define RXWI_W1_STBC FIELD32(0x06000000) +#define RXWI_W1_PHYMODE FIELD32(0xc0000000) + +/* + * Word2 + */ +#define RXWI_W2_RSSI0 FIELD32(0x000000ff) +#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) +#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) + +/* + * Word3 + */ +#define RXWI_W3_SNR0 FIELD32(0x000000ff) +#define RXWI_W3_SNR1 FIELD32(0x0000ff00) + +/* + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. + */ +#define MIN_G_TXPOWER 0 +#define MIN_A_TXPOWER -7 +#define MAX_G_TXPOWER 31 +#define MAX_A_TXPOWER 15 +#define DEFAULT_TXPOWER 5 + +#define TXPOWER_G_FROM_DEV(__txpower) \ + ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_G_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) + +#define TXPOWER_A_FROM_DEV(__txpower) \ + ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_A_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) + +#endif /* RT2800USB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 84bd6f19acb0..a498dde024e1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -102,6 +102,15 @@ #define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate)) #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) +/* + * Determine the alignment requirement, + * to make sure the 802.11 payload is padded to a 4-byte boundrary + * we must determine the address of the payload and calculate the + * amount of bytes needed to move the data. + */ +#define ALIGN_SIZE(__skb, __header) \ + ( ((unsigned long)((__skb)->data + (__header))) & 3 ) + /* * Standard timing and size defines. * These values should follow the ieee80211 specifications. @@ -138,6 +147,7 @@ struct rt2x00_chip { #define RT2561 0x0302 #define RT2661 0x0401 #define RT2571 0x1300 +#define RT2870 0x1600 u16 rf; u32 rev; @@ -357,6 +367,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) * for @tx_power_a, @tx_power_bg and @channels. * @channels: Device/chipset specific channel values (See &struct rf_channel). * @channels_info: Additional information for channels (See &struct channel_info). + * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). */ struct hw_mode_spec { unsigned int supported_bands; @@ -370,6 +381,8 @@ struct hw_mode_spec { unsigned int num_channels; const struct rf_channel *channels; const struct channel_info *channels_info; + + struct ieee80211_sta_ht_cap ht; }; /* @@ -404,6 +417,8 @@ struct rt2x00lib_erp { short pifs; short difs; short eifs; + + u16 beacon_int; }; /* @@ -590,6 +605,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_SCHEDULED, DRIVER_REQUIRE_DMA, DRIVER_REQUIRE_COPY_IV, + DRIVER_REQUIRE_L2PAD, /* * Driver features @@ -606,6 +622,7 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, + CONFIG_CHANNEL_HT40, }; /* @@ -671,6 +688,12 @@ struct rt2x00_dev { */ unsigned long flags; + /* + * Device information, Bus IRQ and name (PCI, SoC) + */ + int irq; + const char *name; + /* * Chipset identification. */ @@ -771,6 +794,18 @@ struct rt2x00_dev { */ u8 freq_offset; + /* + * Calibration information (for rt2800usb & rt2800pci). + * [0] -> BW20 + * [1] -> BW40 + */ + u8 calibration[2]; + + /* + * Beacon interval. + */ + u16 beacon_int; + /* * Low level statistics which will have * to be kept up to date while device is running. @@ -860,6 +895,18 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, rt2x00dev->chip.rev = rev; } +static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev, + const u16 rt) +{ + rt2x00dev->chip.rt = rt; +} + +static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev, + const u16 rf, const u32 rev) +{ + rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev); +} + static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) { return (chipset->rt == chip); @@ -875,11 +922,10 @@ static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) return chipset->rev; } -static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, - const u32 rev) +static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, + const u32 mask, const u32 rev) { - return (((chipset->rev & 0xffff0) == rev) && - !!(chipset->rev & 0x0000f)); + return ((chipset->rev & mask) == rev); } /** @@ -925,9 +971,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 9c2f5517af2a..3e019a12df2e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -106,6 +106,10 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, } erp.basic_rates = bss_conf->basic_rates; + erp.beacon_int = bss_conf->beacon_int; + + /* Update global beacon interval time, this is needed for PS support */ + rt2x00dev->beacon_int = bss_conf->beacon_int; rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); } @@ -173,6 +177,11 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, libconf.conf = conf; if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { + if (conf_is_ht40(conf)) + __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + else + __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + memcpy(&libconf.rf, &rt2x00dev->spec.channels[conf->channel->hw_value], sizeof(libconf.rf)); diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 0b41845d9543..bc4e81e21841 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -33,7 +33,7 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) { switch (key->alg) { case ALG_WEP: - if (key->keylen == LEN_WEP40) + if (key->keylen == WLAN_KEY_LEN_WEP40) return CIPHER_WEP64; else return CIPHER_WEP128; @@ -65,7 +65,8 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); txdesc->key_idx = hw_key->hw_key_idx; - txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); + txdesc->iv_offset = txdesc->header_length; + txdesc->iv_len = hw_key->iv_len; if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags); @@ -103,47 +104,44 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, return overhead; } -void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len) +void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); - if (unlikely(!iv_len)) + if (unlikely(!txdesc->iv_len)) return; /* Copy IV/EIV data */ - memcpy(skbdesc->iv, skb->data + header_length, iv_len); + memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len); } -void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len) +void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); - if (unlikely(!iv_len)) + if (unlikely(!txdesc->iv_len)) return; /* Copy IV/EIV data */ - memcpy(skbdesc->iv, skb->data + header_length, iv_len); + memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len); /* Move ieee80211 header */ - memmove(skb->data + iv_len, skb->data, header_length); + memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset); /* Pull buffer to correct size */ - skb_pull(skb, iv_len); + skb_pull(skb, txdesc->iv_len); /* IV/EIV data has officially be stripped */ - skbdesc->flags |= FRAME_DESC_IV_STRIPPED; + skbdesc->flags |= SKBDESC_IV_STRIPPED; } -void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) +void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); const unsigned int iv_len = ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); - if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) + if (!(skbdesc->flags & SKBDESC_IV_STRIPPED)) return; skb_push(skb, iv_len); @@ -155,14 +153,15 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) memcpy(skb->data + header_length, skbdesc->iv, iv_len); /* IV/EIV data has returned into the frame */ - skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; + skbdesc->flags &= ~SKBDESC_IV_STRIPPED; } -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, +void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc) { unsigned int payload_len = rxdesc->size - header_length; + unsigned int align = ALIGN_SIZE(skb, header_length); unsigned int iv_len; unsigned int icv_len; unsigned int transfer = 0; @@ -192,32 +191,48 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, } /* - * Make room for new data, note that we increase both - * headsize and tailsize when required. The tailsize is - * only needed when ICV data needs to be inserted and - * the padding is smaller than the ICV data. - * When alignment requirements is greater than the - * ICV data we must trim the skb to the correct size - * because we need to remove the extra bytes. + * Make room for new data. There are 2 possibilities + * either the alignment is already present between + * the 802.11 header and payload. In that case we + * we have to move the header less then the iv_len + * since we can use the already available l2pad bytes + * for the iv data. + * When the alignment must be added manually we must + * move the header more then iv_len since we must + * make room for the payload move as well. */ - skb_push(skb, iv_len + align); - if (align < icv_len) - skb_put(skb, icv_len - align); - else if (align > icv_len) - skb_trim(skb, rxdesc->size + iv_len + icv_len); + if (l2pad) { + skb_push(skb, iv_len - align); + skb_put(skb, icv_len); - /* Move ieee80211 header */ - memmove(skb->data + transfer, - skb->data + transfer + iv_len + align, - header_length); - transfer += header_length; + /* Move ieee80211 header */ + memmove(skb->data + transfer, + skb->data + transfer + (iv_len - align), + header_length); + transfer += header_length; + } else { + skb_push(skb, iv_len + align); + if (align < icv_len) + skb_put(skb, icv_len - align); + else if (align > icv_len) + skb_trim(skb, rxdesc->size + iv_len + icv_len); + + /* Move ieee80211 header */ + memmove(skb->data + transfer, + skb->data + transfer + iv_len + align, + header_length); + transfer += header_length; + } /* Copy IV/EIV data */ memcpy(skb->data + transfer, rxdesc->iv, iv_len); transfer += iv_len; - /* Move payload */ - if (align) { + /* + * Move payload for alignment purposes. Note that + * this is only needed when no l2 padding is present. + */ + if (!l2pad) { memmove(skb->data + transfer, skb->data + transfer + align, payload_len); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 5752aaae906b..57813e72c808 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -227,6 +227,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); + unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); u8 rate_idx, rate_flags; /* @@ -234,6 +235,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, */ rt2x00queue_unmap_skb(rt2x00dev, entry->skb); + /* + * Remove L2 padding which was added during + */ + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + rt2x00queue_payload_align(entry->skb, true, header_length); + /* * If the IV/EIV data was stripped from the frame before it was * passed to the hardware, we should now reinsert it again because @@ -241,7 +248,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * frame as it was passed to us. */ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) - rt2x00crypto_tx_insert_iv(entry->skb); + rt2x00crypto_tx_insert_iv(entry->skb, header_length); /* * Send frame to debugfs immediately, after this call is completed @@ -253,7 +260,8 @@ void rt2x00lib_txdone(struct queue_entry *entry, * Update TX statistics. */ rt2x00dev->link.qual.tx_success += - test_bit(TXDONE_SUCCESS, &txdesc->flags); + test_bit(TXDONE_SUCCESS, &txdesc->flags) || + test_bit(TXDONE_UNKNOWN, &txdesc->flags); rt2x00dev->link.qual.tx_failed += test_bit(TXDONE_FAILURE, &txdesc->flags); @@ -271,14 +279,16 @@ void rt2x00lib_txdone(struct queue_entry *entry, tx_info->status.rates[1].idx = -1; /* terminate */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) + if (test_bit(TXDONE_SUCCESS, &txdesc->flags) || + test_bit(TXDONE_UNKNOWN, &txdesc->flags)) tx_info->flags |= IEEE80211_TX_STAT_ACK; else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) rt2x00dev->low_level_stats.dot11ACKFailureCount++; } if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) + if (test_bit(TXDONE_SUCCESS, &txdesc->flags) || + test_bit(TXDONE_UNKNOWN, &txdesc->flags)) rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) rt2x00dev->low_level_stats.dot11RTSFailureCount++; @@ -316,19 +326,54 @@ void rt2x00lib_txdone(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); +static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, + struct rxdone_entry_desc *rxdesc) +{ + struct ieee80211_supported_band *sband; + const struct rt2x00_rate *rate; + unsigned int i; + int signal; + int type; + + /* + * For non-HT rates the MCS value needs to contain the + * actually used rate modulation (CCK or OFDM). + */ + if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) + signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal); + else + signal = rxdesc->signal; + + type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); + + sband = &rt2x00dev->bands[rt2x00dev->curr_band]; + for (i = 0; i < sband->n_bitrates; i++) { + rate = rt2x00_get_rate(sband->bitrates[i].hw_value); + + if (((type == RXDONE_SIGNAL_PLCP) && + (rate->plcp == signal)) || + ((type == RXDONE_SIGNAL_BITRATE) && + (rate->bitrate == signal)) || + ((type == RXDONE_SIGNAL_MCS) && + (rate->mcs == signal))) { + return i; + } + } + + WARNING(rt2x00dev, "Frame received with unrecognized signal, " + "signal=0x%.4x, type=%d.\n", signal, type); + return 0; +} + void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - struct ieee80211_supported_band *sband; - const struct rt2x00_rate *rate; unsigned int header_length; - unsigned int align; - unsigned int i; - int idx = -1; - + bool l2pad; + int rate_idx; /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. @@ -348,12 +393,15 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); + /* Trim buffer to correct size */ + skb_trim(entry->skb, rxdesc.size); + /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - align = ((unsigned long)(entry->skb->data + header_length)) & 3; + l2pad = !!(rxdesc.dev_flags & RXDONE_L2PAD); /* * Hardware might have stripped the IV/EIV/ICV data, @@ -362,40 +410,24 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, * in which case we should reinsert the data into the frame. */ if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && - (rxdesc.flags & RX_FLAG_IV_STRIPPED)) { - rt2x00crypto_rx_insert_iv(entry->skb, align, - header_length, &rxdesc); - } else if (align) { - skb_push(entry->skb, align); - /* Move entire frame in 1 command */ - memmove(entry->skb->data, entry->skb->data + align, - rxdesc.size); - } - - /* Update data pointers, trim buffer to correct size */ - skb_trim(entry->skb, rxdesc.size); + (rxdesc.flags & RX_FLAG_IV_STRIPPED)) + rt2x00crypto_rx_insert_iv(entry->skb, l2pad, header_length, + &rxdesc); + else + rt2x00queue_payload_align(entry->skb, l2pad, header_length); /* - * Update RX statistics. + * Check if the frame was received using HT. In that case, + * the rate is the MCS index and should be passed to mac80211 + * directly. Otherwise we need to translate the signal to + * the correct bitrate index. */ - sband = &rt2x00dev->bands[rt2x00dev->curr_band]; - for (i = 0; i < sband->n_bitrates; i++) { - rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - - if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && - (rate->plcp == rxdesc.signal)) || - ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) && - (rate->bitrate == rxdesc.signal))) { - idx = i; - break; - } - } - - if (idx < 0) { - WARNING(rt2x00dev, "Frame received with unrecognized signal," - "signal=0x%.2x, type=%d.\n", rxdesc.signal, - (rxdesc.dev_flags & RXDONE_SIGNAL_MASK)); - idx = 0; + if (rxdesc.rate_mode == RATE_MODE_CCK || + rxdesc.rate_mode == RATE_MODE_OFDM) { + rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); + } else { + rxdesc.flags |= RX_FLAG_HT; + rate_idx = rxdesc.signal; } /* @@ -405,7 +437,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rt2x00debug_update_crypto(rt2x00dev, &rxdesc); rx_status->mactime = rxdesc.timestamp; - rx_status->rate_idx = idx; + rx_status->rate_idx = rate_idx; rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); rx_status->signal = rxdesc.rssi; rx_status->noise = rxdesc.noise; @@ -440,72 +472,84 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = { .bitrate = 10, .ratemask = BIT(0), .plcp = 0x00, + .mcs = RATE_MCS(RATE_MODE_CCK, 0), }, { .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 20, .ratemask = BIT(1), .plcp = 0x01, + .mcs = RATE_MCS(RATE_MODE_CCK, 1), }, { .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 55, .ratemask = BIT(2), .plcp = 0x02, + .mcs = RATE_MCS(RATE_MODE_CCK, 2), }, { .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 110, .ratemask = BIT(3), .plcp = 0x03, + .mcs = RATE_MCS(RATE_MODE_CCK, 3), }, { .flags = DEV_RATE_OFDM, .bitrate = 60, .ratemask = BIT(4), .plcp = 0x0b, + .mcs = RATE_MCS(RATE_MODE_OFDM, 0), }, { .flags = DEV_RATE_OFDM, .bitrate = 90, .ratemask = BIT(5), .plcp = 0x0f, + .mcs = RATE_MCS(RATE_MODE_OFDM, 1), }, { .flags = DEV_RATE_OFDM, .bitrate = 120, .ratemask = BIT(6), .plcp = 0x0a, + .mcs = RATE_MCS(RATE_MODE_OFDM, 2), }, { .flags = DEV_RATE_OFDM, .bitrate = 180, .ratemask = BIT(7), .plcp = 0x0e, + .mcs = RATE_MCS(RATE_MODE_OFDM, 3), }, { .flags = DEV_RATE_OFDM, .bitrate = 240, .ratemask = BIT(8), .plcp = 0x09, + .mcs = RATE_MCS(RATE_MODE_OFDM, 4), }, { .flags = DEV_RATE_OFDM, .bitrate = 360, .ratemask = BIT(9), .plcp = 0x0d, + .mcs = RATE_MCS(RATE_MODE_OFDM, 5), }, { .flags = DEV_RATE_OFDM, .bitrate = 480, .ratemask = BIT(10), .plcp = 0x08, + .mcs = RATE_MCS(RATE_MODE_OFDM, 6), }, { .flags = DEV_RATE_OFDM, .bitrate = 540, .ratemask = BIT(11), .plcp = 0x0c, + .mcs = RATE_MCS(RATE_MODE_OFDM, 7), }, }; @@ -581,6 +625,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; + memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap, + &spec->ht, sizeof(spec->ht)); } /* @@ -597,6 +643,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; + memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap, + &spec->ht, sizeof(spec->ht)); } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c new file mode 100644 index 000000000000..e3cec839e540 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -0,0 +1,69 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + 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: rt2x00lib + Abstract: rt2x00 HT specific routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; + + if (tx_info->control.sta) + txdesc->mpdu_density = + tx_info->control.sta->ht_cap.ampdu_density; + else + txdesc->mpdu_density = 0; + + txdesc->ba_size = 7; /* FIXME: What value is needed? */ + txdesc->stbc = 0; /* FIXME: What value is needed? */ + + txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txdesc->mcs |= 0x08; + + /* + * Convert flags + */ + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) + __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); + + /* + * Determine HT Mix/Greenfield rate mode + */ + if (txrate->flags & IEEE80211_TX_RC_MCS) + txdesc->rate_mode = RATE_MODE_HT_MIX; + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) + txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); +} diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index d83e3794d340..0bf2715fa93a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -32,8 +32,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 ) +#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) +#define RFKILL_POLL_INTERVAL 1000 /* * rt2x00_rate: Per rate device information @@ -48,6 +48,7 @@ struct rt2x00_rate { unsigned short ratemask; unsigned short plcp; + unsigned short mcs; }; extern const struct rt2x00_rate rt2x00_supported_rates[12]; @@ -57,6 +58,14 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) return &rt2x00_supported_rates[hw_value & 0xff]; } +#define RATE_MCS(__mode, __mcs) \ + ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) + +static inline int rt2x00_get_rate_mcs(const u16 mcs_value) +{ + return (mcs_value & 0x00ff); +} + /* * Radio control handlers. */ @@ -112,6 +121,23 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); */ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +/** + * rt2x00queue_payload_align - Align 802.11 payload to 4-byte boundary + * @skb: The skb to align + * @l2pad: Should L2 padding be used + * @header_length: Length of 802.11 header + * + * This function prepares the @skb to be send to the device or mac80211. + * If @l2pad is set to true padding will occur between the 802.11 header + * and payload. Otherwise the padding will be done in front of the 802.11 + * header. + * When @l2pad is set the function will check for the &SKBDESC_L2_PADDED + * flag in &skb_frame_desc. If that flag is set, the padding is removed + * and the flag cleared. Otherwise the padding is added and the flag is set. + */ +void rt2x00queue_payload_align(struct sk_buff *skb, + bool l2pad, unsigned int header_length); + /** * rt2x00queue_write_tx_frame - Write TX frame to hardware * @queue: Queue over which the frame should be send @@ -295,10 +321,12 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc); unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); -void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len); -void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len); -void rt2x00crypto_tx_insert_iv(struct sk_buff *skb); -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, +void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, + struct txentry_desc *txdesc); +void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, + struct txentry_desc *txdesc); +void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length); +void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc); #else @@ -319,27 +347,42 @@ static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev } static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, - unsigned int iv_len) + struct txentry_desc *txdesc) { } static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, - unsigned int iv_len) + struct txentry_desc *txdesc) { } -static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) +static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, + unsigned int header_length) { } -static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, - unsigned int align, +static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc) { } #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +/* + * HT handlers. + */ +#ifdef CONFIG_RT2X00_LIB_HT +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate); +#else +static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ +} +#endif /* CONFIG_RT2X00_LIB_HT */ + /* * RFkill handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 7eb5cd7e5f32..eb9b981b9139 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -387,7 +387,7 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) rt2x00link_antenna_reset(rt2x00dev); } -void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) +static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) { struct link_qual *qual = &rt2x00dev->link.qual; diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c41a0b9e473d..c4c06b4e1f08 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -390,56 +390,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) } EXPORT_SYMBOL_GPL(rt2x00mac_config); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(vif); - int update_bssid = 0; - int status = 0; - - /* - * 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; - - spin_lock(&intf->lock); - - /* - * conf->bssid can be NULL if coming from the internal - * beacon update routine. - */ - if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { - update_bssid = 1; - memcpy(&intf->bssid, conf->bssid, ETH_ALEN); - } - - spin_unlock(&intf->lock); - - /* - * Call rt2x00_config_intf() outside of the spinlock context since - * the call will sleep for USB drivers. By using the ieee80211_if_conf - * values as arguments we make keep access to rt2x00_intf thread safe - * even without the lock. - */ - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, - update_bssid ? conf->bssid : NULL); - - /* - * Update the beacon. - */ - if (conf->changed & (IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED)) - status = rt2x00queue_update_beacon(rt2x00dev, vif, - conf->enable_beacon); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); - void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -623,6 +573,44 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); unsigned int delayed = 0; + int update_bssid = 0; + + /* + * 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; + + spin_lock(&intf->lock); + + /* + * conf->bssid can be NULL if coming from the internal + * beacon update routine. + */ + if (changes & BSS_CHANGED_BSSID) { + update_bssid = 1; + memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); + } + + spin_unlock(&intf->lock); + + /* + * Call rt2x00_config_intf() outside of the spinlock context since + * the call will sleep for USB drivers. By using the ieee80211_if_conf + * values as arguments we make keep access to rt2x00_intf thread safe + * even without the lock. + */ + if (changes & BSS_CHANGED_BSSID) + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, + update_bssid ? bss_conf->bssid : NULL); + + /* + * Update the beacon. + */ + if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) + rt2x00queue_update_beacon(rt2x00dev, vif, + bss_conf->enable_beacon); /* * When the association status has changed we must reset the link diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 9730b4f8fd26..cdd5154bd4c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -170,7 +170,6 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) { - struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); struct data_queue *queue; int status; @@ -186,11 +185,11 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) /* * Register interrupt handler. */ - status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler, - IRQF_SHARED, pci_name(pci_dev), rt2x00dev); + status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler, + IRQF_SHARED, rt2x00dev->name, rt2x00dev); if (status) { ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", - pci_dev->irq, status); + rt2x00dev->irq, status); goto exit; } @@ -270,6 +269,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; + u16 chip; retval = pci_request_regions(pci_dev, pci_name(pci_dev)); if (retval) { @@ -307,6 +307,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) rt2x00dev->dev = &pci_dev->dev; rt2x00dev->ops = ops; rt2x00dev->hw = hw; + rt2x00dev->irq = pci_dev->irq; + rt2x00dev->name = pci_name(pci_dev); + + /* + * Determine RT chipset by reading PCI header. + */ + pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); + rt2x00_set_chip_rt(rt2x00dev, chip); retval = rt2x00pci_alloc_reg(rt2x00dev); if (retval) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a5664bd8493e..44e5b3279ca7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -148,6 +148,35 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) dev_kfree_skb_any(skb); } +void rt2x00queue_payload_align(struct sk_buff *skb, + bool l2pad, unsigned int header_length) +{ + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + unsigned int frame_length = skb->len; + unsigned int align = ALIGN_SIZE(skb, header_length); + + if (!align) + return; + + if (l2pad) { + if (skbdesc->flags & SKBDESC_L2_PADDED) { + /* Remove L2 padding */ + memmove(skb->data + align, skb->data, header_length); + skb_pull(skb, align); + skbdesc->flags &= ~SKBDESC_L2_PADDED; + } else { + /* Add L2 padding */ + skb_push(skb, align); + memmove(skb->data, skb->data + align, header_length); + skbdesc->flags |= SKBDESC_L2_PADDED; + } + } else { + /* Generic payload alignment to 4-byte boundary */ + skb_push(skb, align); + memmove(skb->data, skb->data + align, frame_length); + } +} + static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, struct txentry_desc *txdesc) { @@ -258,6 +287,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, txdesc->cw_max = entry->queue->cw_max; txdesc->aifs = entry->queue->aifs; + /* + * Header and alignment information. + */ + txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); + /* * Check whether this frame is to be acked. */ @@ -326,6 +361,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * Apply TX descriptor handling by components */ rt2x00crypto_create_tx_descriptor(entry, txdesc); + rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); rt2x00queue_create_tx_descriptor_seq(entry, txdesc); rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); } @@ -368,7 +404,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct txentry_desc txdesc; struct skb_frame_desc *skbdesc; - unsigned int iv_len = 0; u8 rate_idx, rate_flags; if (unlikely(rt2x00queue_full(queue))) @@ -390,9 +425,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) entry->skb = skb; rt2x00queue_create_tx_descriptor(entry, &txdesc); - if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL) - iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; - /* * All information is retrieved from the skb->cb array, * now we should claim ownership of the driver part of that @@ -415,11 +447,15 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) - rt2x00crypto_tx_copy_iv(skb, iv_len); + rt2x00crypto_tx_copy_iv(skb, &txdesc); else - rt2x00crypto_tx_remove_iv(skb, iv_len); + rt2x00crypto_tx_remove_iv(skb, &txdesc); } + if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) + rt2x00queue_payload_align(entry->skb, true, + txdesc.header_length); + /* * It could be possible that the queue was corrupted and this * call failed. Since we always return NETDEV_TX_OK to mac80211, diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 97e2ab08f080..b5e06347c8a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -35,9 +35,12 @@ * for USB devices this restriction does not apply, but the value of * 2432 makes sense since it is big enough to contain the maximum fragment * size according to the ieee802.11 specs. + * The aggregation size depends on support from the driver, but should + * be something around 3840 bytes. */ -#define DATA_FRAME_SIZE 2432 -#define MGMT_FRAME_SIZE 256 +#define DATA_FRAME_SIZE 2432 +#define MGMT_FRAME_SIZE 256 +#define AGGREGATION_SIZE 3840 /** * DOC: Number of entries per queue @@ -87,13 +90,16 @@ enum data_queue_qid { * * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX - * @FRAME_DESC_IV_STRIPPED: Frame contained a IV/EIV provided by + * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by * mac80211 but was stripped for processing by the driver. + * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, + * the padded bytes are located between header and payload. */ enum skb_frame_desc_flags { SKBDESC_DMA_MAPPED_RX = 1 << 0, SKBDESC_DMA_MAPPED_TX = 1 << 1, - FRAME_DESC_IV_STRIPPED = 1 << 2, + SKBDESC_IV_STRIPPED = 1 << 2, + SKBDESC_L2_PADDED = 1 << 3 }; /** @@ -145,16 +151,20 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) * * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. + * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value. * @RXDONE_MY_BSS: Does this frame originate from device's BSS. * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. * @RXDONE_CRYPTO_ICV: Driver provided ICV data. + * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary. */ enum rxdone_entry_desc_flags { - RXDONE_SIGNAL_PLCP = 1 << 0, - RXDONE_SIGNAL_BITRATE = 1 << 1, - RXDONE_MY_BSS = 1 << 2, - RXDONE_CRYPTO_IV = 1 << 3, - RXDONE_CRYPTO_ICV = 1 << 4, + RXDONE_SIGNAL_PLCP = BIT(0), + RXDONE_SIGNAL_BITRATE = BIT(1), + RXDONE_SIGNAL_MCS = BIT(2), + RXDONE_MY_BSS = BIT(3), + RXDONE_CRYPTO_IV = BIT(4), + RXDONE_CRYPTO_ICV = BIT(5), + RXDONE_L2PAD = BIT(6), }; /** @@ -163,7 +173,7 @@ enum rxdone_entry_desc_flags { * from &rxdone_entry_desc to a signal value type. */ #define RXDONE_SIGNAL_MASK \ - ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE ) + ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS ) /** * struct rxdone_entry_desc: RX Entry descriptor @@ -177,6 +187,7 @@ enum rxdone_entry_desc_flags { * @size: Data size of the received frame. * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). + * @rate_mode: Rate mode (See @enum rate_modulation). * @cipher: Cipher type used during decryption. * @cipher_status: Decryption status. * @iv: IV/EIV data used during decryption. @@ -190,6 +201,7 @@ struct rxdone_entry_desc { int size; int flags; int dev_flags; + u16 rate_mode; u8 cipher; u8 cipher_status; @@ -243,6 +255,9 @@ struct txdone_entry_desc { * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared). * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware. * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware. + * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. + * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. + * @ENTRY_TXD_HT_SHORT_GI: Use short GI. */ enum txentry_desc_flags { ENTRY_TXD_RTS_FRAME, @@ -258,6 +273,9 @@ enum txentry_desc_flags { ENTRY_TXD_ENCRYPT_PAIRWISE, ENTRY_TXD_ENCRYPT_IV, ENTRY_TXD_ENCRYPT_MMIC, + ENTRY_TXD_HT_AMPDU, + ENTRY_TXD_HT_BW_40, + ENTRY_TXD_HT_SHORT_GI, }; /** @@ -267,11 +285,17 @@ enum txentry_desc_flags { * * @flags: Descriptor flags (See &enum queue_entry_flags). * @queue: Queue identification (See &enum data_queue_qid). + * @header_length: Length of 802.11 header. + * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary. * @length_high: PLCP length high word. * @length_low: PLCP length low word. * @signal: PLCP signal. * @service: PLCP service. + * @msc: MCS. + * @stbc: STBC. + * @ba_size: BA size. * @rate_mode: Rate mode (See @enum rate_modulation). + * @mpdu_density: MDPU density. * @retry_limit: Max number of retries. * @aifs: AIFS value. * @ifs: IFS value. @@ -280,18 +304,26 @@ enum txentry_desc_flags { * @cipher: Cipher type used for encryption. * @key_idx: Key index used for encryption. * @iv_offset: Position where IV should be inserted by hardware. + * @iv_len: Length of IV data. */ struct txentry_desc { unsigned long flags; enum data_queue_qid queue; + u16 header_length; + u16 l2pad; + u16 length_high; u16 length_low; u16 signal; u16 service; + u16 mcs; + u16 stbc; + u16 ba_size; u16 rate_mode; + u16 mpdu_density; short retry_limit; short aifs; @@ -302,6 +334,7 @@ struct txentry_desc { enum cipher cipher; u16 key_idx; u16 iv_offset; + u16 iv_len; }; /** diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 2ca8b7a9722c..49b29ff90c47 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -603,15 +603,22 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); + rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); @@ -938,25 +945,6 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); } -static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, - libconf->conf->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); -} - static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -968,7 +956,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, - libconf->conf->beacon_int - 10); + rt2x00dev->beacon_int - 10); rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); @@ -1016,8 +1004,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev, rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) rt61pci_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - rt61pci_config_duration(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) rt61pci_config_ps(rt2x00dev, libconf); } @@ -2308,7 +2294,6 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) u32 reg; u16 value; u16 eeprom; - u16 device; /* * Read EEPROM word for configuration. @@ -2317,14 +2302,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify RF chipset. - * To determine the RT chip we have to read the - * PCI header of the device. */ - pci_read_config_word(to_pci_dev(rt2x00dev->dev), - PCI_CONFIG_HEADER_DEVICE, &device); value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, device, value, reg); + rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && !rt2x00_rf(&rt2x00dev->chip, RF5325) && @@ -2740,7 +2721,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 41e8959919f6..6c71f77c8165 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -62,12 +62,6 @@ * PCI registers. */ -/* - * PCI Configuration Header - */ -#define PCI_CONFIG_HEADER_VENDOR 0x0000 -#define PCI_CONFIG_HEADER_DEVICE 0x0002 - /* * HOST_CMD_CSR: For HOST to interrupt embedded processor */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 853b2b279b64..c18848836f2d 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -566,15 +566,22 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); + rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); @@ -834,25 +841,6 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); } -static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, - libconf->conf->beacon_int * 16); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); -} - static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -864,7 +852,7 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, - libconf->conf->beacon_int - 10); + rt2x00dev->beacon_int - 10); rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); @@ -906,8 +894,6 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev, rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) rt73usb_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - rt73usb_config_duration(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) rt73usb_config_ps(rt2x00dev, libconf); } @@ -1846,7 +1832,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || + rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } @@ -2259,7 +2246,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile index c113b3e69046..37e3d4db0c40 100644 --- a/drivers/net/wireless/rtl818x/Makefile +++ b/drivers/net/wireless/rtl818x/Makefile @@ -1,5 +1,5 @@ rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o -rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o +rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o obj-$(CONFIG_RTL8180) += rtl8180.o obj-$(CONFIG_RTL8187) += rtl8187.o diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 387c133ec0f2..7e65d7c31802 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -702,30 +702,26 @@ static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int rtl8180_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); - - if (is_valid_ether_addr(conf->bssid)) - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); - - return 0; -} - static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { struct rtl8180_priv *priv = dev->priv; + int i; + + if (changed & BSS_CHANGED_BSSID) { + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->BSSID[i], + info->bssid[i]); + + if (is_valid_ether_addr(info->bssid)) + rtl818x_iowrite8(priv, &priv->map->MSR, + RTL818X_MSR_INFRA); + else + rtl818x_iowrite8(priv, &priv->map->MSR, + RTL818X_MSR_NO_LINK); + } if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) priv->rf->conf_erp(dev, info); @@ -770,7 +766,6 @@ static const struct ieee80211_ops rtl8180_ops = { .add_interface = rtl8180_add_interface, .remove_interface = rtl8180_remove_interface, .config = rtl8180_config, - .config_interface = rtl8180_config_interface, .bss_info_changed = rtl8180_bss_info_changed, .configure_filter = rtl8180_configure_filter, }; diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index edeff82a4d06..c09bfefc70f3 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -16,6 +16,7 @@ #define RTL8187_H #include "rtl818x.h" +#include "rtl8187_leds.h" #define RTL8187_EEPROM_TXPWR_BASE 0x05 #define RTL8187_EEPROM_MAC_ADDR 0x07 @@ -102,6 +103,12 @@ struct rtl8187_priv { struct usb_anchor anchored; struct delayed_work work; struct ieee80211_hw *dev; +#ifdef CONFIG_RTL8187_LEDS + struct rtl8187_led led_tx; + struct rtl8187_led led_rx; + struct delayed_work led_on; + struct delayed_work led_off; +#endif u16 txpwr_base; u8 asic_rev; u8 is_rtl8187b; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index d51ba0a88c23..294250e294dd 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -29,6 +29,9 @@ #include "rtl8187.h" #include "rtl8187_rtl8225.h" +#ifdef CONFIG_RTL8187_LEDS +#include "rtl8187_leds.h" +#endif MODULE_AUTHOR("Michael Wu "); MODULE_AUTHOR("Andrea Merello "); @@ -320,12 +323,7 @@ static void rtl8187_rx_cb(struct urb *urb) unsigned long f; spin_lock_irqsave(&priv->rx_queue.lock, f); - if (skb->next) - __skb_unlink(skb, &priv->rx_queue); - else { - spin_unlock_irqrestore(&priv->rx_queue.lock, f); - return; - } + __skb_unlink(skb, &priv->rx_queue); spin_unlock_irqrestore(&priv->rx_queue.lock, f); skb_put(skb, urb->actual_length); @@ -736,10 +734,10 @@ static const u8 rtl8187b_reg_table[][3] = { {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, - {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0}, + {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, - {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, - {0x8E, 0x08, 0}, {0x8F, 0x00, 0} + {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, + {0x8F, 0x00, 0} }; static int rtl8187b_init_hw(struct ieee80211_hw *dev) @@ -1089,32 +1087,6 @@ static int rtl8187_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int rtl8187_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - u8 reg; - - mutex_lock(&priv->conf_mutex); - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); - - if (is_valid_ether_addr(conf->bssid)) { - reg = RTL818X_MSR_INFRA; - if (priv->is_rtl8187b) - reg |= RTL818X_MSR_ENEDCA; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } else { - reg = RTL818X_MSR_NO_LINK; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } - - mutex_unlock(&priv->conf_mutex); - return 0; -} - /* * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for * example. Thus we have to use raw values for AC_*_PARAM register addresses. @@ -1192,6 +1164,27 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, u32 changed) { struct rtl8187_priv *priv = dev->priv; + int i; + u8 reg; + + if (changed & BSS_CHANGED_BSSID) { + mutex_lock(&priv->conf_mutex); + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->BSSID[i], + info->bssid[i]); + + if (is_valid_ether_addr(info->bssid)) { + reg = RTL818X_MSR_INFRA; + if (priv->is_rtl8187b) + reg |= RTL818X_MSR_ENEDCA; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } else { + reg = RTL818X_MSR_NO_LINK; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } + + mutex_unlock(&priv->conf_mutex); + } if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) rtl8187_conf_erp(priv, info->use_short_slot, @@ -1273,7 +1266,6 @@ static const struct ieee80211_ops rtl8187_ops = { .add_interface = rtl8187_add_interface, .remove_interface = rtl8187_remove_interface, .config = rtl8187_config, - .config_interface = rtl8187_config_interface, .bss_info_changed = rtl8187_bss_info_changed, .configure_filter = rtl8187_configure_filter, .conf_tx = rtl8187_conf_tx @@ -1480,9 +1472,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr >> 8; } - if (priv->is_rtl8187b) - printk(KERN_WARNING "rtl8187: 8187B chip detected.\n"); - /* * XXX: Once this driver supports anything that requires * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ. @@ -1514,6 +1503,12 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, wiphy_name(dev->wiphy), dev->wiphy->perm_addr, chip_name, priv->asic_rev, priv->rf->name); +#ifdef CONFIG_RTL8187_LEDS + eeprom_93cx6_read(&eeprom, 0x3F, ®); + reg &= 0xFF; + rtl8187_leds_init(dev, reg); +#endif + return 0; err_free_dmabuf: @@ -1533,6 +1528,9 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf) if (!dev) return; +#ifdef CONFIG_RTL8187_LEDS + rtl8187_leds_exit(dev); +#endif ieee80211_unregister_hw(dev); priv = dev->priv; diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c new file mode 100644 index 000000000000..b44253592243 --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -0,0 +1,218 @@ +/* + * Linux LED driver for RTL8187 + * + * Copyright 2009 Larry Finger + * + * Based on the LED handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * Thanks to Realtek for their support! + * + * 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. + */ + +#ifdef CONFIG_RTL8187_LEDS + +#include +#include +#include + +#include "rtl8187.h" +#include "rtl8187_leds.h" + +static void led_turn_on(struct work_struct *work) +{ + /* As this routine does read/write operations on the hardware, it must + * be run from a work queue. + */ + u8 reg; + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + led_on.work); + struct rtl8187_led *led = &priv->led_tx; + + /* Don't change the LED, when the device is down. */ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return ; + + /* Skip if the LED is not registered. */ + if (!led->dev) + return; + mutex_lock(&priv->conf_mutex); + switch (led->ledpin) { + case LED_PIN_GPIO0: + rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00); + break; + case LED_PIN_LED0: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_LED1: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_HW: + default: + break; + } + mutex_unlock(&priv->conf_mutex); +} + +static void led_turn_off(struct work_struct *work) +{ + /* As this routine does read/write operations on the hardware, it must + * be run from a work queue. + */ + u8 reg; + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + led_off.work); + struct rtl8187_led *led = &priv->led_tx; + + /* Don't change the LED, when the device is down. */ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return ; + + /* Skip if the LED is not registered. */ + if (!led->dev) + return; + mutex_lock(&priv->conf_mutex); + switch (led->ledpin) { + case LED_PIN_GPIO0: + rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01); + break; + case LED_PIN_LED0: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_LED1: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_HW: + default: + break; + } + mutex_unlock(&priv->conf_mutex); +} + +/* Callback from the LED subsystem. */ +static void rtl8187_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, + led_dev); + struct ieee80211_hw *hw = led->dev; + struct rtl8187_priv *priv = hw->priv; + + if (brightness == LED_OFF) { + queue_delayed_work(hw->workqueue, &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); + } else + queue_delayed_work(hw->workqueue, &priv->led_on, 0); +} + +static int rtl8187_register_led(struct ieee80211_hw *dev, + struct rtl8187_led *led, const char *name, + const char *default_trigger, u8 ledpin) +{ + int err; + struct rtl8187_priv *priv = dev->priv; + + if (led->dev) + return -EEXIST; + if (!default_trigger) + return -EINVAL; + led->dev = dev; + led->ledpin = ledpin; + strncpy(led->name, name, sizeof(led->name)); + + led->led_dev.name = led->name; + led->led_dev.default_trigger = default_trigger; + led->led_dev.brightness_set = rtl8187_led_brightness_set; + + err = led_classdev_register(&priv->udev->dev, &led->led_dev); + if (err) { + printk(KERN_INFO "LEDs: Failed to register %s\n", name); + led->dev = NULL; + return err; + } + return 0; +} + +static void rtl8187_unregister_led(struct rtl8187_led *led) +{ + led_classdev_unregister(&led->led_dev); + led->dev = NULL; +} + +void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) +{ + struct rtl8187_priv *priv = dev->priv; + char name[RTL8187_LED_MAX_NAME_LEN + 1]; + u8 ledpin; + int err; + + /* According to the vendor driver, the LED operation depends on the + * customer ID encoded in the EEPROM + */ + printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid); + switch (custid) { + case EEPROM_CID_RSVD0: + case EEPROM_CID_RSVD1: + case EEPROM_CID_SERCOMM_PS: + case EEPROM_CID_QMI: + case EEPROM_CID_DELL: + case EEPROM_CID_TOSHIBA: + ledpin = LED_PIN_GPIO0; + break; + case EEPROM_CID_ALPHA0: + ledpin = LED_PIN_LED0; + break; + case EEPROM_CID_HW: + ledpin = LED_PIN_HW; + break; + default: + ledpin = LED_PIN_GPIO0; + } + + INIT_DELAYED_WORK(&priv->led_on, led_turn_on); + INIT_DELAYED_WORK(&priv->led_off, led_turn_off); + + snprintf(name, sizeof(name), + "rtl8187-%s::tx", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_tx, name, + ieee80211_get_tx_led_name(dev), ledpin); + if (err) + goto error; + snprintf(name, sizeof(name), + "rtl8187-%s::rx", wiphy_name(dev->wiphy)); + 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); + return; + } + /* registration of RX LED failed - unregister TX */ + rtl8187_unregister_led(&priv->led_tx); +error: + /* If registration of either failed, cancel delayed work */ + cancel_delayed_work_sync(&priv->led_off); + cancel_delayed_work_sync(&priv->led_on); +} + +void rtl8187_leds_exit(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + + rtl8187_unregister_led(&priv->led_tx); + /* turn the LED off before exiting */ + queue_delayed_work(dev->workqueue, &priv->led_off, 0); + cancel_delayed_work_sync(&priv->led_off); + rtl8187_unregister_led(&priv->led_rx); +} +#endif /* def CONFIG_RTL8187_LED */ + diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h new file mode 100644 index 000000000000..a0332027aead --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h @@ -0,0 +1,57 @@ +/* + * Definitions for RTL8187 leds + * + * Copyright 2009 Larry Finger + * + * Based on the LED handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * 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 RTL8187_LED_H +#define RTL8187_LED_H + +#ifdef CONFIG_RTL8187_LEDS + +#define RTL8187_LED_MAX_NAME_LEN 21 + +#include +#include + +enum { + LED_PIN_LED0, + LED_PIN_LED1, + LED_PIN_GPIO0, + LED_PIN_HW +}; + +enum { + EEPROM_CID_RSVD0 = 0x00, + EEPROM_CID_RSVD1 = 0xFF, + EEPROM_CID_ALPHA0 = 0x01, + EEPROM_CID_SERCOMM_PS = 0x02, + EEPROM_CID_HW = 0x03, + EEPROM_CID_TOSHIBA = 0x04, + EEPROM_CID_QMI = 0x07, + EEPROM_CID_DELL = 0x08 +}; + +struct rtl8187_led { + struct ieee80211_hw *dev; + /* The LED class device */ + struct led_classdev led_dev; + /* The pin/method used to control the led */ + u8 ledpin; + /* The unique name string for this LED device. */ + char name[RTL8187_LED_MAX_NAME_LEN + 1]; +}; + +void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); +void rtl8187_leds_exit(struct ieee80211_hw *dev); + +#endif /* def CONFIG_RTL8187_LED */ + +#endif /* RTL8187_LED_H */ diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index f95204632690..38366a56b71f 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -1540,7 +1540,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev) if (!netif_running(dev)) { printk(KERN_ERR "%s: xmit call when iface is down\n", dev->name); - return (1); + return NETDEV_TX_BUSY; } netif_stop_queue(dev); @@ -2509,7 +2509,7 @@ static void strip_dev_setup(struct net_device *dev) * netdev_priv(dev) Already holds a pointer to our struct strip */ - *(MetricomAddress *) & dev->broadcast = broadcast_address; + *(MetricomAddress *)dev->broadcast = broadcast_address; dev->dev_addr[0] = 0; dev->addr_len = sizeof(MetricomAddress); diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index 3ab3eb957189..ab7fc5c0c8b4 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -2867,12 +2867,8 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) spin_unlock_irqrestore(&lp->spinlock, flags); /* Check that we can continue */ if (lp->tx_n_in_use == (NTXBLOCKS - 1)) - return 1; + return NETDEV_TX_BUSY; } -#ifdef DEBUG_TX_ERROR - if (skb->next) - printk(KERN_INFO "skb has next\n"); -#endif /* Do we need some padding? */ /* Note : on wireless the propagation time is in the order of 1us, @@ -2884,10 +2880,10 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) skb_copy_from_linear_data(skb, data, skb->len); /* Write packet on the card */ if(wv_packet_write(dev, data, ETH_ZLEN)) - return 1; /* We failed */ + return NETDEV_TX_BUSY; /* We failed */ } else if(wv_packet_write(dev, skb->data, skb->len)) - return 1; /* We failed */ + return NETDEV_TX_BUSY; /* We failed */ dev_kfree_skb(skb); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index fa2821be44c2..6af706408ac0 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -3107,11 +3107,6 @@ wavelan_packet_xmit(struct sk_buff * skb, * so the Tx buffer is now free */ } -#ifdef DEBUG_TX_ERROR - if (skb->next) - printk(KERN_INFO "skb has next\n"); -#endif - /* Check if we need some padding */ /* Note : on wireless the propagation time is in the order of 1us, * and we don't have the Ethernet specific requirement of beeing diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig new file mode 100644 index 000000000000..a82c4cd436d8 --- /dev/null +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -0,0 +1,11 @@ +config WL12XX + tristate "TI wl1251/wl1271 support" + depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS && EXPERIMENTAL + select FW_LOADER + select CRC7 + ---help--- + This module adds support for wireless adapters based on + TI wl1251/wl1271 chipsets. + + If you choose to build a module, it'll be called wl12xx. Say N if + unsure. diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile new file mode 100644 index 000000000000..d43de27dc54c --- /dev/null +++ b/drivers/net/wireless/wl12xx/Makefile @@ -0,0 +1,4 @@ +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 diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c new file mode 100644 index 000000000000..1cfd458ad5ab --- /dev/null +++ b/drivers/net/wireless/wl12xx/acx.c @@ -0,0 +1,689 @@ +#include "acx.h" + +#include +#include +#include + +#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, ¶ms, 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, ¶m, 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/acx.h b/drivers/net/wireless/wl12xx/acx.h new file mode 100644 index 000000000000..fb2d2340993c --- /dev/null +++ b/drivers/net/wireless/wl12xx/acx.h @@ -0,0 +1,1245 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_ACX_H__ +#define __WL12XX_ACX_H__ + +#include "wl12xx.h" + +/* Target's information element */ +struct acx_header { + u16 id; + 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 wl12xx_psm_mode { + /* Active mode */ + WL12XX_PSM_CAM = 0, + + /* Power save mode */ + WL12XX_PSM_PS = 1, + + /* Extreme low power */ + WL12XX_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)); + +#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, + 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 + +struct acx_data_path_params { + struct acx_header header; + + u16 rx_packet_ring_chunk_size; + u16 tx_packet_ring_chunk_size; + + u8 rx_packet_ring_chunk_num; + u8 tx_packet_ring_chunk_num; + + /* + * Maximum number of packets that can be gathered + * in the TX complete ring before an interrupt + * is generated. + */ + u8 tx_complete_threshold; + + /* Number of pending TX complete entries in cyclic ring.*/ + u8 tx_complete_ring_depth; + + /* + * Max num microseconds since a packet enters the TX + * complete ring until an interrupt is generated. + */ + u32 tx_complete_timeout; +} __attribute__ ((packed)); + + +struct acx_data_path_params_resp { + struct acx_header header; + + u16 rx_packet_ring_chunk_size; + u16 tx_packet_ring_chunk_size; + + u8 rx_packet_ring_chunk_num; + u8 tx_packet_ring_chunk_num; + + u8 pad[2]; + + u32 rx_packet_ring_addr; + u32 tx_packet_ring_addr; + + u32 rx_control_addr; + u32 tx_control_addr; + + u32 tx_complete_addr; +} __attribute__ ((packed)); + +#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 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)); + +enum { + QOS_AC_BE = 0, + QOS_AC_BK, + QOS_AC_VI, + QOS_AC_VO, + QOS_HIGHEST_AC_INDEX = QOS_AC_VO, +}; + +#define MAX_NUM_OF_AC (QOS_HIGHEST_AC_INDEX+1) +#define FIRST_AC_INDEX QOS_AC_BE +#define MAX_NUM_OF_802_1d_TAGS 8 +#define AC_PARAMS_MAX_TSID 15 +#define MAX_APSD_CONF 0xffff + +#define QOS_TX_HIGH_MIN (0) +#define QOS_TX_HIGH_MAX (100) + +#define QOS_TX_HIGH_BK_DEF (25) +#define QOS_TX_HIGH_BE_DEF (35) +#define QOS_TX_HIGH_VI_DEF (35) +#define QOS_TX_HIGH_VO_DEF (35) + +#define QOS_TX_LOW_BK_DEF (15) +#define QOS_TX_LOW_BE_DEF (25) +#define QOS_TX_LOW_VI_DEF (25) +#define QOS_TX_LOW_VO_DEF (25) + +struct acx_tx_queue_qos_config { + struct acx_header header; + + u8 qid; + u8 pad[3]; + + /* Max number of blocks allowd in the queue */ + u16 high_threshold; + + /* Lowest memory blocks guaranteed for this queue */ + u16 low_threshold; +} __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 multicast_grp_addr_start { + 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_fw_gen_frame_rates { + struct acx_header header; + + u8 tx_ctrl_frame_rate; /* RATE_* */ + u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */ + u8 tx_mgt_frame_rate; + u8 tx_mgt_frame_mod; +} __attribute__ ((packed)); + +/* STA MAC */ +struct 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; + + u32 options; + 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; + + u8 current_tx_power; + u8 padding[3]; +} __attribute__ ((packed)); + +struct acx_dot11_default_key { + struct acx_header header; + + u8 id; + u8 pad[3]; +} __attribute__ ((packed)); + +struct acx_tsf_info { + struct acx_header header; + + u32 current_tsf_msb; + u32 current_tsf_lsb; + u32 last_TBTT_msb; + u32 last_TBTT_lsb; + u8 last_dtim_count; + 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*/ + 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)); + +enum { + ACX_WAKE_UP_CONDITIONS = 0x0002, + ACX_MEM_CFG = 0x0003, + ACX_SLOT = 0x0004, + ACX_QUEUE_HEAD = 0x0005, /* for MASTER mode only */ + ACX_AC_CFG = 0x0007, + ACX_MEM_MAP = 0x0008, + ACX_AID = 0x000A, + ACX_RADIO_PARAM = 0x000B, /* Not used */ + ACX_CFG = 0x000C, /* Not used */ + ACX_FW_REV = 0x000D, + ACX_MEDIUM_USAGE = 0x000F, + ACX_RX_CFG = 0x0010, + ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ + ACX_BSS_IN_PS = 0x0012, /* for AP only */ + ACX_STATISTICS = 0x0013, /* Debug API */ + ACX_FEATURE_CFG = 0x0015, + ACX_MISC_CFG = 0x0017, /* Not used */ + ACX_TID_CFG = 0x001A, + ACX_BEACON_FILTER_OPT = 0x001F, + ACX_LOW_RSSI = 0x0020, + ACX_NOISE_HIST = 0x0021, + ACX_HDK_VERSION = 0x0022, /* ??? */ + ACX_PD_THRESHOLD = 0x0023, + ACX_DATA_PATH_PARAMS = 0x0024, /* WO */ + ACX_DATA_PATH_RESP_PARAMS = 0x0024, /* RO */ + ACX_CCA_THRESHOLD = 0x0025, + ACX_EVENT_MBOX_MASK = 0x0026, +#ifdef FW_RUNNING_AS_AP + ACX_DTIM_PERIOD = 0x0027, /* for AP only */ +#else + ACX_WR_TBTT_AND_DTIM = 0x0027, /* STA only */ +#endif + ACX_ACI_OPTION_CFG = 0x0029, /* OBSOLETE (for 1251)*/ + ACX_GPIO_CFG = 0x002A, /* Not used */ + ACX_GPIO_SET = 0x002B, /* Not used */ + ACX_PM_CFG = 0x002C, /* To Be Documented */ + ACX_CONN_MONIT_PARAMS = 0x002D, + ACX_AVERAGE_RSSI = 0x002E, /* Not used */ + ACX_CONS_TX_FAILURE = 0x002F, + ACX_BCN_DTIM_OPTIONS = 0x0031, + ACX_SG_ENABLE = 0x0032, + ACX_SG_CFG = 0x0033, + ACX_ANTENNA_DIVERSITY_CFG = 0x0035, /* To Be Documented */ + ACX_LOW_SNR = 0x0037, /* To Be Documented */ + 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_FW_GEN_FRAME_RATES = 0x0042, + 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_POWER_LEVEL_TABLE = 0x004D, + ACX_BET_ENABLE = 0x0050, + DOT11_STATION_ID = 0x1001, + DOT11_RX_MSDU_LIFE_TIME = 0x1004, + DOT11_CUR_TX_PWR = 0x100D, + DOT11_DEFAULT_KEY = 0x1010, + 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 wl12xx_acx_frame_rates(struct wl12xx *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, + 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, + enum acx_ctsprotect_type ctsprotect); +int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats); + +#endif /* __WL12XX_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c new file mode 100644 index 000000000000..48ac08c429bd --- /dev/null +++ b/drivers/net/wireless/wl12xx/boot.c @@ -0,0 +1,295 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 + +#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/boot.h b/drivers/net/wireless/wl12xx/boot.h new file mode 100644 index 000000000000..4fa73132baae --- /dev/null +++ b/drivers/net/wireless/wl12xx/boot.h @@ -0,0 +1,40 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 "wl12xx.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); + +/* number of times we try to read the INIT interrupt */ +#define INIT_LOOP 20000 + +/* delay between retries */ +#define INIT_LOOP_DELAY 50 + +#endif diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c new file mode 100644 index 000000000000..f73ab602b7ae --- /dev/null +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -0,0 +1,353 @@ +#include "cmd.h" + +#include +#include +#include + +#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/cmd.h b/drivers/net/wireless/wl12xx/cmd.h new file mode 100644 index 000000000000..aa307dcd081f --- /dev/null +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -0,0 +1,265 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_CMD_H__ +#define __WL12XX_CMD_H__ + +#include "wl12xx.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, + 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, + void *buf, size_t buf_len); + +/* unit ms */ +#define WL12XX_COMMAND_TIMEOUT 2000 + +#define WL12XX_MAX_TEMPLATE_SIZE 300 + +struct wl12xx_cmd_packet_template { + __le16 size; + u8 template[WL12XX_MAX_TEMPLATE_SIZE]; +} __attribute__ ((packed)); + +enum wl12xx_commands { + CMD_RESET = 0, + 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_VBM = 10, + CMD_START_JOIN = 11, + CMD_SET_KEYS = 12, + CMD_READ_MEMORY = 13, + CMD_WRITE_MEMORY = 14, + CMD_BEACON = 19, + CMD_PROBE_RESP = 20, + CMD_NULL_DATA = 21, + CMD_PROBE_REQ = 22, + CMD_TEST = 23, + CMD_RADIO_CALIBRATE = 25, /* OBSOLETE */ + CMD_ENABLE_RX_PATH = 27, /* OBSOLETE */ + CMD_NOISE_HIST = 28, + CMD_RX_RESET = 29, + CMD_PS_POLL = 30, + CMD_QOS_NULL_DATA = 31, + 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, + + NUM_COMMANDS, + MAX_COMMAND_ID = 0xFFFF, +}; + +#define MAX_CMD_PARAMS 572 + +struct wl12xx_command { + u16 id; + u16 status; + u8 parameters[MAX_CMD_PARAMS]; +}; + +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 { + /* 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 + + +struct basic_scan_parameters { + u32 rx_config_options; + u32 rx_filter_options; + + /* + * Scan options: + * bit 0: When this bit is set, passive scan. + * bit 1: Band, when this bit is set we scan + * in the 5Ghz band. + * bit 2: voice mode, 0 for normal scan. + * bit 3: scan priority, 1 for high priority. + */ + u16 scan_options; + + /* Number of channels to scan */ + u8 num_channels; + + /* Number opf probe requests to send, per channel */ + u8 num_probe_requests; + + /* Rate and modulation for probe requests */ + u16 tx_rate; + + u8 tid_trigger; + u8 ssid_len; + u32 ssid[8]; + +} __attribute__ ((packed)); + +struct basic_scan_channel_parameters { + u32 min_duration; /* in TU */ + u32 max_duration; /* in TU */ + u32 bssid_lsb; + u16 bssid_msb; + + /* + * bits 0-3: Early termination count. + * bits 4-5: Early termination condition. + */ + u8 early_termination; + + u8 tx_power_att; + u8 channel; + u8 pad[3]; +} __attribute__ ((packed)); + +/* SCAN parameters */ +#define SCAN_MAX_NUM_OF_CHANNELS 16 + +struct cmd_scan { + struct basic_scan_parameters params; + struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; +} __attribute__ ((packed)); + +enum { + BSS_TYPE_IBSS = 0, + BSS_TYPE_STA_BSS = 2, + BSS_TYPE_AP_BSS = 3, + MAX_BSS_TYPE = 0xFF +}; + +#define JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ +#define JOIN_CMD_CTRL_EARLY_WAKEUP_ENABLE 0x01 /* Early wakeup time */ + + +struct cmd_join { + 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). + */ + u16 basic_rate_set; + u8 dtim_interval; + u8 tx_ctrl_frame_rate; /* OBSOLETE */ + u8 tx_ctrl_frame_mod; /* OBSOLETE */ + /* + * 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 tx_mgt_frame_rate; /* OBSOLETE */ + u8 tx_mgt_frame_mod; /* OBSOLETE */ + u8 reserved; +} __attribute__ ((packed)); + + +#endif /* __WL12XX_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c new file mode 100644 index 000000000000..cdb368ce4dae --- /dev/null +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -0,0 +1,508 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 "debugfs.h" + +#include + +#include "wl12xx.h" +#include "acx.h" + +/* ms */ +#define WL12XX_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 wl12xx *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 = wl12xx_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 wl12xx *wl = file->private_data; \ + char buf[buflen]; \ + int res; \ + \ + wl12xx_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 = wl12xx_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 wl12xx_debugfs_update_stats(struct wl12xx *wl) +{ + mutex_lock(&wl->mutex); + + if (wl->state == WL12XX_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); + wl->stats.fw_stats_update = jiffies; + } + + mutex_unlock(&wl->mutex); +} + +static int wl12xx_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 wl12xx *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 = wl12xx_open_file_generic, +}; + +static void wl12xx_debugfs_delete_files(struct wl12xx *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 wl12xx_debugfs_add_files(struct wl12xx *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) + wl12xx_debugfs_delete_files(wl); + + return ret; +} + +void wl12xx_debugfs_reset(struct wl12xx *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 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 = wl12xx_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 wl12xx_debugfs_exit(struct wl12xx *wl) +{ + wl12xx_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/debugfs.h b/drivers/net/wireless/wl12xx/debugfs.h new file mode 100644 index 000000000000..562cdcbcc874 --- /dev/null +++ b/drivers/net/wireless/wl12xx/debugfs.h @@ -0,0 +1,33 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 WL12XX_DEBUGFS_H +#define WL12XX_DEBUGFS_H + +#include "wl12xx.h" + +int wl12xx_debugfs_init(struct wl12xx *wl); +void wl12xx_debugfs_exit(struct wl12xx *wl); +void wl12xx_debugfs_reset(struct wl12xx *wl); + +#endif /* WL12XX_DEBUGFS_H */ diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c new file mode 100644 index 000000000000..99529ca89a7e --- /dev/null +++ b/drivers/net/wireless/wl12xx/event.c @@ -0,0 +1,127 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 "wl12xx.h" +#include "reg.h" +#include "spi.h" +#include "event.h" +#include "ps.h" + +static int wl12xx_event_scan_complete(struct wl12xx *wl, + struct event_mailbox *mbox) +{ + wl12xx_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", + mbox->scheduled_scan_status, + mbox->scheduled_scan_channels); + + if (wl->scanning) { + mutex_unlock(&wl->mutex); + ieee80211_scan_completed(wl->hw, false); + mutex_lock(&wl->mutex); + wl->scanning = false; + } + + return 0; +} + +static void wl12xx_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); +} + +static int wl12xx_event_process(struct wl12xx *wl, struct event_mailbox *mbox) +{ + int ret; + u32 vector; + + wl12xx_event_mbox_dump(mbox); + + vector = mbox->events_vector & ~(mbox->events_mask); + wl12xx_debug(DEBUG_EVENT, "vector: 0x%x", vector); + + if (vector & SCAN_COMPLETE_EVENT_ID) { + ret = wl12xx_event_scan_complete(wl, mbox); + if (ret < 0) + return ret; + } + + if (vector & BSS_LOSE_EVENT_ID) { + wl12xx_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); + + if (wl->psm_requested && wl->psm) { + ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE); + if (ret < 0) + return ret; + } + } + + return 0; +} + +int wl12xx_event_unmask(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_event_mbox_mask(wl, ~(wl->event_mask)); + if (ret < 0) + return ret; + + return 0; +} + +void wl12xx_event_mbox_config(struct wl12xx *wl) +{ + wl->mbox_ptr[0] = wl12xx_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", + wl->mbox_ptr[0], wl->mbox_ptr[1]); +} + +int wl12xx_event_handle(struct wl12xx *wl, u8 mbox_num) +{ + struct event_mailbox mbox; + int ret; + + wl12xx_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, + sizeof(struct event_mailbox)); + + /* process the descriptor */ + ret = wl12xx_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); + + return 0; +} diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h new file mode 100644 index 000000000000..1f4c2f7438a7 --- /dev/null +++ b/drivers/net/wireless/wl12xx/event.h @@ -0,0 +1,121 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_EVENT_H__ +#define __WL12XX_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 { + RESERVED1_EVENT_ID = BIT(0), + RESERVED2_EVENT_ID = BIT(1), + MEASUREMENT_START_EVENT_ID = BIT(2), + SCAN_COMPLETE_EVENT_ID = BIT(3), + CALIBRATION_COMPLETE_EVENT_ID = BIT(4), + ROAMING_TRIGGER_LOW_RSSI_EVENT_ID = BIT(5), + PS_REPORT_EVENT_ID = BIT(6), + SYNCHRONIZATION_TIMEOUT_EVENT_ID = BIT(7), + HEALTH_REPORT_EVENT_ID = BIT(8), + ACI_DETECTION_EVENT_ID = BIT(9), + DEBUG_REPORT_EVENT_ID = BIT(10), + MAC_STATUS_EVENT_ID = BIT(11), + DISCONNECT_EVENT_COMPLETE_ID = BIT(12), + JOIN_EVENT_COMPLETE_ID = BIT(13), + CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(14), + BSS_LOSE_EVENT_ID = BIT(15), + ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(16), + MEASUREMENT_COMPLETE_EVENT_ID = BIT(17), + AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(18), + SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(19), + PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(20), + RESET_BSS_EVENT_ID = BIT(21), + REGAINED_BSS_EVENT_ID = BIT(22), + ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID = BIT(23), + ROAMING_TRIGGER_LOW_SNR_EVENT_ID = BIT(24), + ROAMING_TRIGGER_REGAINED_SNR_EVENT_ID = BIT(25), + + DBG_EVENT_ID = BIT(26), + BT_PTA_SENSE_EVENT_ID = BIT(27), + BT_PTA_PREDICTION_EVENT_ID = BIT(28), + BT_PTA_AVALANCHE_EVENT_ID = BIT(29), + + PLT_RX_CALIBRATION_COMPLETE_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)); + +struct event_mailbox { + u32 events_vector; + u32 events_mask; + u32 reserved_1; + u32 reserved_2; + + char average_rssi_level; + u8 ps_status; + u8 channel_switch_status; + u8 scheduled_scan_status; + + /* Channels scanned by the scheduled scan */ + u16 scheduled_scan_channels; + + /* If bit 0 is set -> target's fatal error */ + u16 health_report; + u16 bad_fft_counter; + u8 bt_pta_sense_info; + u8 bt_pta_protective_info; + u32 reserved; + u32 debug_report[2]; + + /* Number of FCS errors since last event */ + u32 fcs_err_counter; + + struct event_debug_report report; + u8 average_snr_level; + 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); + +#endif diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c new file mode 100644 index 000000000000..2a573a6010bd --- /dev/null +++ b/drivers/net/wireless/wl12xx/init.c @@ -0,0 +1,200 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include + +#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/init.h b/drivers/net/wireless/wl12xx/init.h new file mode 100644 index 000000000000..c8b6cd0b7c3e --- /dev/null +++ b/drivers/net/wireless/wl12xx/init.h @@ -0,0 +1,40 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_INIT_H__ +#define __WL12XX_INIT_H__ + +#include "wl12xx.h" + +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 diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c new file mode 100644 index 000000000000..603d6114882e --- /dev/null +++ b/drivers/net/wireless/wl12xx/main.c @@ -0,0 +1,1358 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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) +{ + disable_irq(wl->irq); +} + +static void wl12xx_power_off(struct wl12xx *wl) +{ + wl->set_power(false); +} + +static void wl12xx_power_on(struct wl12xx *wl) +{ + wl->set_power(true); +} + +static irqreturn_t wl12xx_irq(int irq, void *cookie) +{ + struct wl12xx *wl; + + wl12xx_debug(DEBUG_IRQ, "IRQ"); + + wl = cookie; + + schedule_work(&wl->irq_work); + + return IRQ_HANDLED; +} + +static int wl12xx_fetch_firmware(struct wl12xx *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, wl->chip.fw_filename, &wl->spi->dev); + + if (ret < 0) { + wl12xx_error("could not get firmware: %d", ret); + return ret; + } + + if (fw->size % 4) { + wl12xx_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) { + wl12xx_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 wl12xx_fetch_nvs(struct wl12xx *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, wl->chip.nvs_filename, &wl->spi->dev); + + if (ret < 0) { + wl12xx_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", + fw->size); + ret = -EILSEQ; + goto out; + } + + wl->nvs_len = fw->size; + wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); + + if (!wl->nvs) { + wl12xx_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 wl12xx_fw_wakeup(struct wl12xx *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); + + 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); + } +} + +static int wl12xx_chip_wakeup(struct wl12xx *wl) +{ + int ret = 0; + + wl12xx_power_on(wl); + msleep(wl->chip.power_on_sleep); + wl12xx_spi_reset(wl); + wl12xx_spi_init(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, + 0x00000000, + 0x00000000, + REGISTERS_BASE, + REGISTERS_DOWN_SIZE); + + /* ELP module wake up */ + wl12xx_fw_wakeup(wl); + + /* whal_FwCtrl_BootSm() */ + + /* 0. read chip id from CHIP_ID */ + wl->chip.id = wl12xx_reg_read32(wl, CHIP_ID_B); + + /* 1. check if chip id is valid */ + + 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); + + 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); + ret = -ENODEV; + goto out; + } + + if (wl->fw == NULL) { + ret = wl12xx_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); + if (ret < 0) + goto out; + } + +out: + return ret; +} + +static void wl12xx_filter_work(struct work_struct *work) +{ + struct wl12xx *wl = + container_of(work, struct wl12xx, filter_work); + int ret; + + mutex_lock(&wl->mutex); + + if (wl->state == WL12XX_STATE_OFF) + goto out; + + ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0); + if (ret < 0) + goto out; + +out: + mutex_unlock(&wl->mutex); +} + +int wl12xx_plt_start(struct wl12xx *wl) +{ + int ret; + + 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; + } + + wl->state = WL12XX_STATE_PLT; + + ret = wl12xx_chip_wakeup(wl); + if (ret < 0) + return ret; + + ret = wl->chip.op_boot(wl); + if (ret < 0) + return ret; + + wl12xx_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); + + ret = wl->chip.op_plt_init(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_plt_stop(struct wl12xx *wl) +{ + wl12xx_notice("power down"); + + if (wl->state != WL12XX_STATE_PLT) { + wl12xx_error("cannot power down because not in PLT " + "state: %d", wl->state); + return -EBUSY; + } + + wl12xx_disable_interrupts(wl); + wl12xx_power_off(wl); + + wl->state = WL12XX_STATE_OFF; + + return 0; +} + + +static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct wl12xx *wl = hw->priv; + + skb_queue_tail(&wl->tx_queue, skb); + + 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) >= WL12XX_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 wl12xx_op_start(struct ieee80211_hw *hw) +{ + struct wl12xx *wl = hw->priv; + int ret = 0; + + wl12xx_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", + wl->state); + ret = -EBUSY; + goto out; + } + + ret = wl12xx_chip_wakeup(wl); + if (ret < 0) + return ret; + + ret = wl->chip.op_boot(wl); + if (ret < 0) + goto out; + + ret = wl->chip.op_hw_init(wl); + if (ret < 0) + goto out; + + ret = wl12xx_acx_station_id(wl); + if (ret < 0) + goto out; + + wl->state = WL12XX_STATE_ON; + + wl12xx_info("firmware booted (%s)", wl->chip.fw_ver); + +out: + if (ret < 0) + wl12xx_power_off(wl); + + mutex_unlock(&wl->mutex); + + return ret; +} + +static void wl12xx_op_stop(struct ieee80211_hw *hw) +{ + struct wl12xx *wl = hw->priv; + + wl12xx_info("down"); + + wl12xx_debug(DEBUG_MAC80211, "mac80211 stop"); + + mutex_lock(&wl->mutex); + + WARN_ON(wl->state != WL12XX_STATE_ON); + + if (wl->scanning) { + mutex_unlock(&wl->mutex); + ieee80211_scan_completed(wl->hw, true); + mutex_lock(&wl->mutex); + wl->scanning = false; + } + + wl->state = WL12XX_STATE_OFF; + + wl12xx_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 */ + wl12xx_tx_flush(wl); + + wl12xx_power_off(wl); + + memset(wl->bssid, 0, ETH_ALEN); + wl->listen_int = 1; + wl->bss_type = MAX_BSS_TYPE; + + wl->data_in_count = 0; + wl->rx_counter = 0; + wl->rx_handled = 0; + wl->rx_current_buffer = 0; + wl->rx_last_id = 0; + wl->next_tx_complete = 0; + wl->elp = false; + wl->psm = 0; + wl->tx_queue_stopped = false; + wl->power_level = WL12XX_DEFAULT_POWER_LEVEL; + + wl12xx_debugfs_reset(wl); + + mutex_unlock(&wl->mutex); +} + +static int wl12xx_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct wl12xx *wl = hw->priv; + DECLARE_MAC_BUF(mac); + int ret = 0; + + wl12xx_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; + } + + 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); + if (ret < 0) + goto out; + } + +out: + mutex_unlock(&wl->mutex); + return ret; +} + +static void wl12xx_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + wl12xx_debug(DEBUG_MAC80211, "mac80211 remove interface"); +} + +static int wl12xx_build_null_data(struct wl12xx *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 wl12xx_cmd_template_set(wl, CMD_NULL_DATA, &template, + sizeof(template)); + +} + +static int wl12xx_build_ps_poll(struct wl12xx *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 wl12xx_cmd_template_set(wl, CMD_PS_POLL, &template, + sizeof(template)); + +} + +static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct wl12xx *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", + 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; + + wl->channel = channel; + } + + ret = wl12xx_build_null_data(wl); + if (ret < 0) + goto out; + + if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { + wl12xx_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 = wl12xx_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + } else if (!(conf->flags & IEEE80211_CONF_PS) && + wl->psm_requested) { + wl12xx_info("psm disabled"); + + wl->psm_requested = false; + + if (wl->psm) + ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE); + } + + if (conf->power_level != wl->power_level) { + ret = wl12xx_acx_tx_power(wl, conf->power_level); + if (ret < 0) + goto out; + + wl->power_level = conf->power_level; + } + +out: + mutex_unlock(&wl->mutex); + return ret; +} + +#define WL12XX_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, + unsigned int changed, + unsigned int *total, + int mc_count, + struct dev_addr_list *mc_list) +{ + struct wl12xx *wl = hw->priv; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 configure filter"); + + *total &= WL12XX_SUPPORTED_FILTERS; + changed &= WL12XX_SUPPORTED_FILTERS; + + if (changed == 0) + /* no filters which we support changed */ + return; + + /* 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; + + if (*total & FIF_PROMISC_IN_BSS) { + wl->rx_config |= CFG_BSSID_FILTER_EN; + wl->rx_config |= CFG_RX_ALL_GOOD; + } + if (*total & FIF_ALLMULTI) + /* + * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive + * all multicast frames + */ + wl->rx_config &= ~CFG_MC_FILTER_EN; + if (*total & FIF_FCSFAIL) + wl->rx_filter |= CFG_RX_FCS_ERROR; + if (*total & FIF_BCN_PRBRESP_PROMISC) { + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + wl->rx_config &= ~CFG_SSID_FILTER_EN; + } + if (*total & FIF_CONTROL) + wl->rx_filter |= CFG_RX_CTL_EN; + if (*total & FIF_OTHER_BSS) + wl->rx_filter &= ~CFG_BSSID_FILTER_EN; + + /* + * 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); */ +} + +/* HW encryption */ +static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key, + enum set_key_cmd cmd, + struct ieee80211_key_conf *mac80211_key, + const u8 *addr) +{ + switch (mac80211_key->alg) { + case ALG_WEP: + if (is_broadcast_ether_addr(addr)) + key->key_type = KEY_WEP_DEFAULT; + else + key->key_type = KEY_WEP_ADDR; + + mac80211_key->hw_key_idx = mac80211_key->keyidx; + break; + case ALG_TKIP: + if (is_broadcast_ether_addr(addr)) + key->key_type = KEY_TKIP_MIC_GROUP; + else + key->key_type = KEY_TKIP_MIC_PAIRWISE; + + mac80211_key->hw_key_idx = mac80211_key->keyidx; + break; + case ALG_CCMP: + if (is_broadcast_ether_addr(addr)) + key->key_type = KEY_AES_GROUP; + else + key->key_type = KEY_AES_PAIRWISE; + mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + break; + default: + wl12xx_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, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct wl12xx *wl = hw->priv; + struct acx_set_key wl_key; + 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"); + + memset(&wl_key, 0, sizeof(wl_key)); + + 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", + key->alg, key->keyidx, key->keylen, key->flags); + wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); + + mutex_lock(&wl->mutex); + + switch (cmd) { + case SET_KEY: + wl_key.key_action = KEY_ADD_OR_REPLACE; + break; + case DISABLE_KEY: + wl_key.key_action = KEY_REMOVE; + break; + default: + wl12xx_error("Unsupported key cmd 0x%x", cmd); + break; + } + + ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr); + if (ret < 0) { + wl12xx_error("Set KEY type failed"); + goto out; + } + + if (wl_key.key_type != KEY_WEP_DEFAULT) + memcpy(wl_key.addr, addr, ETH_ALEN); + + if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) || + (wl_key.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); + + } else { + memcpy(wl_key.key, key->key, key->keylen); + } + wl_key.key_size = key->keylen; + + wl_key.id = key->keyidx; + wl_key.ssid_profile = 0; + + wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", &wl_key, sizeof(wl_key)); + + if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key, sizeof(wl_key)) < 0) { + wl12xx_error("Set KEY failed"); + ret = -EOPNOTSUPP; + goto out; + } + +out: + mutex_unlock(&wl->mutex); + return ret; +} + +static int wl12xx_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 wl12xx_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; +} + + +static int wl12xx_build_probe_req(struct wl12xx *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 = wl12xx_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); + size += sizeof(struct wl12xx_ie_header) + rates->header.len; + + wl12xx_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); + + return wl12xx_cmd_template_set(wl, CMD_PROBE_REQ, &template, + size); +} + +static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len, + u8 active_scan, u8 high_prio, u8 num_channels, + u8 probe_requests) +{ + 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; + + 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); + + /* High priority scan */ + if (!active_scan) + scan_options |= SCAN_PASSIVE; + if (high_prio) + scan_options |= SCAN_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_le16(1 << 1); /* 2 Mbps */ + params->params.tid_trigger = 0; + + for (i = 0; i < num_channels; i++) { + params->channels[i].min_duration = cpu_to_le32(30000); + params->channels[i].max_duration = cpu_to_le32(60000); + memset(¶ms->channels[i].bssid_lsb, 0xff, 4); + memset(¶ms->channels[i].bssid_msb, 0xff, 2); + params->channels[i].early_termination = 0; + params->channels[i].tx_power_att = 0; + params->channels[i].channel = i + 1; + memset(params->channels[i].pad, 0, 3); + } + + for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++) + memset(¶ms->channels[i], 0, + sizeof(struct basic_scan_channel_parameters)); + + if (len && ssid) { + params->params.ssid_len = len; + memcpy(params->params.ssid, ssid, len); + } else { + params->params.ssid_len = 0; + memset(params->params.ssid, 0, 32); + } + + ret = wl12xx_build_probe_req(wl, ssid, len); + if (ret < 0) { + wl12xx_error("PROBE request template failed"); + goto out; + } + + ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan, + sizeof(u32)); + if (ret < 0) { + wl12xx_error("Split SCAN failed"); + goto out; + } + + wl12xx_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); + + wl->scanning = true; + + ret = wl12xx_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); + if (ret < 0) + wl12xx_error("SCAN failed"); + + wl12xx_spi_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); + wl->scanning = false; + ret = -EIO; + goto out; + } + +out: + kfree(params); + return ret; + +} + +static int wl12xx_op_hw_scan(struct ieee80211_hw *hw, + struct cfg80211_scan_request *req) +{ + struct wl12xx *wl = hw->priv; + int ret; + u8 *ssid = NULL; + size_t ssid_len = 0; + + wl12xx_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 = wl12xx_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); + mutex_unlock(&wl->mutex); + + return ret; +} + +static int wl12xx_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct wl12xx *wl = hw->priv; + int ret; + + ret = wl12xx_acx_rts_threshold(wl, (u16) value); + + if (ret < 0) + wl12xx_warning("wl12xx_op_set_rts_threshold failed: %d", ret); + + return ret; +} + +static void wl12xx_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; + struct sk_buff *beacon; + int ret; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 bss info changed"); + + mutex_lock(&wl->mutex); + + if (changed & BSS_CHANGED_ASSOC) { + if (bss_conf->assoc) { + wl->aid = bss_conf->aid; + + ret = wl12xx_build_ps_poll(wl, wl->aid); + if (ret < 0) + goto out; + + ret = wl12xx_acx_aid(wl, wl->aid); + if (ret < 0) + goto out; + + /* 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); + if (ret < 0) + goto out; + } + } + } + if (changed & BSS_CHANGED_ERP_SLOT) { + if (bss_conf->use_short_slot) + ret = wl12xx_acx_slot(wl, SLOT_TIME_SHORT); + else + ret = wl12xx_acx_slot(wl, SLOT_TIME_LONG); + if (ret < 0) { + wl12xx_warning("Set slot time failed %d", ret); + goto out; + } + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + if (bss_conf->use_short_preamble) + wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); + else + wl12xx_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); + else + ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_DISABLE); + if (ret < 0) { + wl12xx_warning("Set ctsprotect failed %d", ret); + goto out; + } + } + + if (changed & BSS_CHANGED_BSSID) { + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + + ret = wl12xx_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); + if (ret < 0) + goto out; + } + } + + if (changed & BSS_CHANGED_BEACON) { + beacon = ieee80211_beacon_get(hw, vif); + ret = wl12xx_cmd_template_set(wl, CMD_BEACON, beacon->data, + beacon->len); + + if (ret < 0) { + dev_kfree_skb(beacon); + goto out; + } + + ret = wl12xx_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, + beacon->len); + + dev_kfree_skb(beacon); + + if (ret < 0) + goto out; + + ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0); + + if (ret < 0) + goto out; + } + +out: + mutex_unlock(&wl->mutex); +} + + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_rate wl12xx_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 wl12xx_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 wl12xx_band_2ghz = { + .channels = wl12xx_channels, + .n_channels = ARRAY_SIZE(wl12xx_channels), + .bitrates = wl12xx_rates, + .n_bitrates = ARRAY_SIZE(wl12xx_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 int wl12xx_register_hw(struct wl12xx *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) { + wl12xx_error("unable to register mac80211 hw: %d", ret); + return ret; + } + + wl->mac80211_registered = true; + + wl12xx_notice("loaded"); + + return 0; +} + +static int wl12xx_init_ieee80211(struct wl12xx *wl) +{ + /* The tx descriptor buffer and the TKIP space */ + wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc) + + WL12XX_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] = &wl12xx_band_2ghz; + + SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); + + return 0; +} + +#define WL12XX_DEFAULT_CHANNEL 1 +static int __devinit wl12xx_probe(struct spi_device *spi) +{ + struct wl12xx_platform_data *pdata; + struct ieee80211_hw *hw; + struct wl12xx *wl; + int ret, 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); + if (!hw) { + wl12xx_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; + + 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; + wl->scanning = false; + wl->default_key = 0; + wl->listen_int = 1; + wl->rx_counter = 0; + 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->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; + + for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) + wl->tx_frames[i] = NULL; + + wl->next_tx_complete = 0; + + /* + * 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 = WL12XX_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; + } + + 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; +} + +static int __devexit wl12xx_remove(struct spi_device *spi) +{ + struct wl12xx *wl = dev_get_drvdata(&spi->dev); + + ieee80211_unregister_hw(wl->hw); + + wl12xx_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, + }, + + .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); + + wl12xx_notice("unloaded"); +} + +module_init(wl12xx_init); +module_exit(wl12xx_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kalle Valo , " + "Luciano Coelho "); diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c new file mode 100644 index 000000000000..83a10117330b --- /dev/null +++ b/drivers/net/wireless/wl12xx/ps.c @@ -0,0 +1,151 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 "reg.h" +#include "ps.h" +#include "spi.h" + +#define WL12XX_WAKEUP_TIMEOUT 2000 + +/* Routines to toggle sleep mode while in ELP */ +void wl12xx_ps_elp_sleep(struct wl12xx *wl) +{ + if (wl->elp || !wl->psm) + return; + + wl12xx_debug(DEBUG_PSM, "chip to elp"); + + wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); + + wl->elp = true; +} + +int wl12xx_ps_elp_wakeup(struct wl12xx *wl) +{ + unsigned long timeout; + u32 elp_reg; + + if (!wl->elp) + return 0; + + wl12xx_debug(DEBUG_PSM, "waking up chip from elp"); + + timeout = jiffies + msecs_to_jiffies(WL12XX_WAKEUP_TIMEOUT); + + wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); + + elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + + /* + * FIXME: we should wait for irq from chip but, as a temporary + * solution to simplify locking, let's poll instead + */ + while (!(elp_reg & ELPCTRL_WLAN_READY)) { + if (time_after(jiffies, timeout)) { + wl12xx_error("elp wakeup timeout"); + return -ETIMEDOUT; + } + msleep(1); + elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + } + + wl12xx_debug(DEBUG_PSM, "wakeup time: %u ms", + jiffies_to_msecs(jiffies) - + (jiffies_to_msecs(timeout) - WL12XX_WAKEUP_TIMEOUT)); + + wl->elp = false; + + return 0; +} + +static int wl12xx_ps_set_elp(struct wl12xx *wl, bool enable) +{ + int ret; + + if (enable) { + wl12xx_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); + if (ret < 0) + return ret; + + wl12xx_ps_elp_sleep(wl); + } else { + wl12xx_debug(DEBUG_PSM, "sleep auth cam"); + + /* + * When the target is in ELP, we can only + * access the ELP control register. Thus, + * we have to wake the target up before + * changing the power authorization. + */ + + wl12xx_ps_elp_wakeup(wl); + + ret = wl12xx_acx_sleep_auth(wl, WL12XX_PSM_CAM); + if (ret < 0) + return ret; + } + + return 0; +} + +int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_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); + if (ret < 0) + return ret; + + ret = wl12xx_ps_set_elp(wl, true); + if (ret < 0) + return ret; + + wl->psm = 1; + break; + case STATION_ACTIVE_MODE: + default: + wl12xx_debug(DEBUG_PSM, "leaving psm"); + ret = wl12xx_ps_set_elp(wl, false); + if (ret < 0) + return ret; + + ret = wl12xx_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/ps.h b/drivers/net/wireless/wl12xx/ps.h new file mode 100644 index 000000000000..5d7c52553830 --- /dev/null +++ b/drivers/net/wireless/wl12xx/ps.h @@ -0,0 +1,36 @@ +#ifndef __WL12XX_PS_H__ +#define __WL12XX_PS_H__ + +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 "wl12xx.h" +#include "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); + + +#endif /* __WL12XX_PS_H__ */ diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h new file mode 100644 index 000000000000..e421643215cd --- /dev/null +++ b/drivers/net/wireless/wl12xx/reg.h @@ -0,0 +1,745 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include "wl12xx.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 + +/* + * Interrupt registers. + * 64 bit interrupt sources registers ws ced. + * sme interupts were removed and new ones were added. + * Order was changed. + */ +#define FIQ_MASK (REGISTERS_BASE + 0x0400) +#define FIQ_MASK_L (REGISTERS_BASE + 0x0400) +#define FIQ_MASK_H (REGISTERS_BASE + 0x0404) +#define FIQ_MASK_SET (REGISTERS_BASE + 0x0408) +#define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408) +#define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C) +#define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410) +#define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410) +#define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414) +#define IRQ_MASK (REGISTERS_BASE + 0x0418) +#define IRQ_MASK_L (REGISTERS_BASE + 0x0418) +#define IRQ_MASK_H (REGISTERS_BASE + 0x041C) +#define IRQ_MASK_SET (REGISTERS_BASE + 0x0420) +#define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420) +#define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424) +#define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428) +#define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428) +#define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C) +#define ECPU_MASK (REGISTERS_BASE + 0x0448) +#define FIQ_STS_L (REGISTERS_BASE + 0x044C) +#define FIQ_STS_H (REGISTERS_BASE + 0x0450) +#define IRQ_STS_L (REGISTERS_BASE + 0x0454) +#define IRQ_STS_H (REGISTERS_BASE + 0x0458) +#define INT_STS_ND (REGISTERS_BASE + 0x0464) +#define INT_STS_RAW_L (REGISTERS_BASE + 0x0464) +#define INT_STS_RAW_H (REGISTERS_BASE + 0x0468) +#define INT_STS_CLR (REGISTERS_BASE + 0x04B4) +#define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4) +#define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8) +#define INT_ACK (REGISTERS_BASE + 0x046C) +#define INT_ACK_L (REGISTERS_BASE + 0x046C) +#define INT_ACK_H (REGISTERS_BASE + 0x0470) +#define INT_TRIG (REGISTERS_BASE + 0x0474) +#define INT_TRIG_L (REGISTERS_BASE + 0x0474) +#define INT_TRIG_H (REGISTERS_BASE + 0x0478) +#define HOST_STS_L (REGISTERS_BASE + 0x045C) +#define HOST_STS_H (REGISTERS_BASE + 0x0460) +#define HOST_MASK (REGISTERS_BASE + 0x0430) +#define HOST_MASK_L (REGISTERS_BASE + 0x0430) +#define HOST_MASK_H (REGISTERS_BASE + 0x0434) +#define HOST_MASK_SET (REGISTERS_BASE + 0x0438) +#define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438) +#define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C) +#define HOST_MASK_CLR (REGISTERS_BASE + 0x0440) +#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) +#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) + +/* Host Interrupts*/ +#define HINT_MASK (REGISTERS_BASE + 0x0494) +#define HINT_MASK_SET (REGISTERS_BASE + 0x0498) +#define HINT_MASK_CLR (REGISTERS_BASE + 0x049C) +#define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0) +/*1150 spec calls this HINT_STS_RAW*/ +#define HINT_STS_ND (REGISTERS_BASE + 0x04B0) +#define HINT_STS_CLR (REGISTERS_BASE + 0x04A4) +#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) + ------------------------------------------ + 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) + + +/*=============================================== + Phy regs + ===============================================*/ +#define ACX_PHY_ADDR_REG SBB_ADDR +#define ACX_PHY_DATA_REG SBB_DATA +#define ACX_PHY_CTRL_REG SBB_CTL +#define ACX_PHY_REG_WR_MASK 0x00000001ul +#define ACX_PHY_REG_RD_MASK 0x00000002ul + + +/*=============================================== + 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 + +/* + * Indirect slave register/memory registers + * ---------------------------------------- + */ +#define HW_SLAVE_REG_ADDR_REG 0x00000004 +#define HW_SLAVE_REG_DATA_REG 0x00000008 +#define HW_SLAVE_REG_CTRL_REG 0x0000000c + +#define SLAVE_AUTO_INC 0x00010000 +#define SLAVE_NO_AUTO_INC 0x00000000 +#define SLAVE_HOST_LITTLE_ENDIAN 0x00000000 + +#define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR +#define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA +#define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL +#define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL + +#define HW_FUNC_EVENT_INT_EN 0x8000 +#define HW_FUNC_EVENT_MASK_REG 0x00000034 + +#define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP) + +/*=============================================== + 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. + +******************************************************************************/ + + +#define TNETW1251_CHIP_ID_PG1_0 0x07010101 +#define TNETW1251_CHIP_ID_PG1_1 0x07020101 +#define TNETW1251_CHIP_ID_PG1_2 0x07030101 + +/************************************************************************* + + 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/rx.c new file mode 100644 index 000000000000..981ea259eb89 --- /dev/null +++ b/drivers/net/wireless/wl12xx/rx.c @@ -0,0 +1,208 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include + +#include "wl12xx.h" +#include "reg.h" +#include "spi.h" +#include "rx.h" + +static void wl12xx_rx_header(struct wl12xx *wl, + struct wl12xx_rx_descriptor *desc) +{ + u32 rx_packet_ring_addr; + + rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr; + 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)); +} + +static void wl12xx_rx_status(struct wl12xx *wl, + struct wl12xx_rx_descriptor *desc, + struct ieee80211_rx_status *status, + u8 beacon) +{ + memset(status, 0, sizeof(struct ieee80211_rx_status)); + + status->band = IEEE80211_BAND_2GHZ; + status->mactime = desc->timestamp; + + /* + * The rx status timestamp is a 32 bits value while the TSF is a + * 64 bits one. + * For IBSS merging, TSF is mandatory, so we have to get it + * somehow, so we ask for ACX_TSF_INFO. + * That could be moved to the get_tsf() hook, but unfortunately, + * 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; + } + + status->signal = desc->rssi; + status->qual = (desc->rssi - WL12XX_RX_MIN_RSSI) * 100 / + (WL12XX_RX_MAX_RSSI - WL12XX_RX_MIN_RSSI); + status->qual = min(status->qual, 100); + status->qual = max(status->qual, 0); + + /* + * FIXME: guessing that snr needs to be divided by two, otherwise + * the values don't make any sense + */ + status->noise = desc->rssi - desc->snr / 2; + + status->freq = ieee80211_channel_to_frequency(desc->channel); + + status->flag |= RX_FLAG_TSFT; + + if (desc->flags & RX_DESC_ENCRYPTION_MASK) { + status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; + + if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL))) + status->flag |= RX_FLAG_DECRYPTED; + + if (unlikely(desc->flags & RX_DESC_MIC_FAIL)) + status->flag |= RX_FLAG_MMIC_ERROR; + } + + if (unlikely(!(desc->flags & RX_DESC_VALID_FCS))) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + + /* FIXME: set status->rate_idx */ +} + +static void wl12xx_rx_body(struct wl12xx *wl, + struct wl12xx_rx_descriptor *desc) +{ + struct sk_buff *skb; + struct ieee80211_rx_status status; + u8 *rx_buffer, beacon = 0; + u16 length, *fc; + u32 curr_id, last_id_inc, rx_packet_ring_addr; + + length = WL12XX_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", + curr_id, last_id_inc); + wl->rx_last_id = curr_id; + } else { + wl->rx_last_id = last_id_inc; + } + + rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr + + sizeof(struct wl12xx_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"); + return; + } + + rx_buffer = skb_put(skb, length); + wl12xx_spi_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; + + fc = (u16 *)skb->data; + + if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) + beacon = 1; + + wl12xx_rx_status(wl, desc, &status, beacon); + + wl12xx_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, + beacon ? "beacon" : ""); + + ieee80211_rx(wl->hw, skb, &status); +} + +static void wl12xx_rx_ack(struct wl12xx *wl) +{ + u32 data, addr; + + if (wl->rx_current_buffer) { + addr = ACX_REG_INTERRUPT_TRIG_H; + data = INTR_TRIG_RX_PROC1; + } else { + addr = ACX_REG_INTERRUPT_TRIG; + data = INTR_TRIG_RX_PROC0; + } + + wl12xx_reg_write32(wl, addr, data); + + /* Toggle buffer ring */ + wl->rx_current_buffer = !wl->rx_current_buffer; +} + + +void wl12xx_rx(struct wl12xx *wl) +{ + struct wl12xx_rx_descriptor rx_desc; + + if (wl->state != WL12XX_STATE_ON) + return; + + /* We first read the frame's header */ + wl12xx_rx_header(wl, &rx_desc); + + /* Now we can read the body */ + wl12xx_rx_body(wl, &rx_desc); + + /* Finally, we need to ACK the RX */ + wl12xx_rx_ack(wl); + + return; +} diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h new file mode 100644 index 000000000000..8a23fdea5016 --- /dev/null +++ b/drivers/net/wireless/wl12xx/rx.h @@ -0,0 +1,122 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_RX_H__ +#define __WL12XX_RX_H__ + +#include + +/* + * RX PATH + * + * The Rx path uses a double buffer and an rx_contro structure, each located + * at a fixed address in the device memory. The host keeps track of which + * buffer is available and alternates between them on a per packet basis. + * The size of each of the two buffers is large enough to hold the longest + * 802.3 packet. + * The RX path goes like that: + * 1) The target generates an interrupt each time a new packet is received. + * There are 2 RX interrupts, one for each buffer. + * 2) The host reads the received packet from one of the double buffers. + * 3) The host triggers a target interrupt. + * 4) The target prepares the next RX packet. + */ + +#define WL12XX_RX_MAX_RSSI -30 +#define WL12XX_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 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 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 + +struct wl12xx_rx_descriptor { + u32 timestamp; /* In microseconds */ + u16 length; /* Paylod length, including headers */ + u16 flags; + + /* + * 0 - 802.11 + * 1 - 802.3 + * 2 - IP + * 3 - Raw Codec + */ + u8 type; + + /* + * Recevied Rate: + * 0x0A - 1MBPS + * 0x14 - 2MBPS + * 0x37 - 5_5MBPS + * 0x0B - 6MBPS + * 0x0F - 9MBPS + * 0x6E - 11MBPS + * 0x0A - 12MBPS + * 0x0E - 18MBPS + * 0xDC - 22MBPS + * 0x09 - 24MBPS + * 0x0D - 36MBPS + * 0x08 - 48MBPS + * 0x0C - 54MBPS + */ + u8 rate; + + u8 mod_pre; /* Modulation and preamble */ + u8 channel; + + /* + * 0 - 2.4 Ghz + * 1 - 5 Ghz + */ + u8 band; + + s8 rssi; /* in dB */ + u8 rcpi; /* in dB */ + u8 snr; /* in dB */ +} __attribute__ ((packed)); + +void wl12xx_rx(struct wl12xx *wl); + +#endif diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c new file mode 100644 index 000000000000..abdf171a47e7 --- /dev/null +++ b/drivers/net/wireless/wl12xx/spi.c @@ -0,0 +1,358 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include +#include + +#include "wl12xx.h" +#include "wl12xx_80211.h" +#include "reg.h" +#include "spi.h" +#include "ps.h" + +static int wl12xx_translate_reg_addr(struct wl12xx *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) +{ + return addr - wl->physical_mem_addr + wl->virtual_mem_addr; +} + + +void wl12xx_spi_reset(struct wl12xx *wl) +{ + u8 *cmd; + struct spi_transfer t; + struct spi_message m; + + cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); + if (!cmd) { + wl12xx_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->spi, &m); + + wl12xx_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); +} + +void wl12xx_spi_init(struct wl12xx *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) { + wl12xx_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->spi, &m); + + wl12xx_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); +} + +/* Set the SPI partitions to access the chip addresses + * + * There are two VIRTUAL (SPI) 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 wl12xx_set_partition(struct wl12xx *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 spi_transfer t; + struct spi_message m; + u32 *cmd; + size_t len; + int addr; + + 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)); + addr = HW_ACCESS_PART0_SIZE_ADDR; + len = 2 * sizeof(struct wl12xx_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", + mem_start, mem_size); + wl12xx_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" + " address range. Truncating partition[0]."); + mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; + wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + mem_start, mem_size); + wl12xx_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 */ + wl12xx_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", + mem_start, mem_size); + wl12xx_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" + " overlapping partition[0]. Adjusted."); + reg_size = mem_start - reg_start; + wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + mem_start, mem_size); + wl12xx_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; + + t.tx_buf = tx_buf; + t.len = sizeof(tx_buf); + spi_message_add_tail(&t, &m); + + spi_sync(wl->spi, &m); +} + +void wl12xx_spi_read(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + struct spi_transfer t[3]; + struct spi_message m; + char busy_buf[TNETWIF_READ_OFFSET_BYTES]; + 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; + + 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 = TNETWIF_READ_OFFSET_BYTES; + 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->spi, &m); + + /* FIXME: check busy words */ + + wl12xx_dump(DEBUG_SPI, "spi_read cmd -> ", &cmd, sizeof(cmd)); + wl12xx_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); +} + +void wl12xx_spi_write(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + struct spi_transfer t[2]; + struct spi_message m; + 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; + + 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->spi, &m); + + wl12xx_dump(DEBUG_SPI, "spi_write cmd -> ", &cmd, sizeof(cmd)); + wl12xx_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); +} + +void wl12xx_spi_mem_read(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + int physical; + + physical = wl12xx_translate_mem_addr(wl, addr); + + wl12xx_spi_read(wl, physical, buf, len); +} + +void wl12xx_spi_mem_write(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + int physical; + + physical = wl12xx_translate_mem_addr(wl, addr); + + wl12xx_spi_write(wl, physical, buf, len); +} + +u32 wl12xx_mem_read32(struct wl12xx *wl, int addr) +{ + return wl12xx_read32(wl, wl12xx_translate_mem_addr(wl, addr)); +} + +void wl12xx_mem_write32(struct wl12xx *wl, int addr, u32 val) +{ + wl12xx_write32(wl, wl12xx_translate_mem_addr(wl, addr), val); +} + +u32 wl12xx_reg_read32(struct wl12xx *wl, int addr) +{ + return wl12xx_read32(wl, wl12xx_translate_reg_addr(wl, addr)); +} + +void wl12xx_reg_write32(struct wl12xx *wl, int addr, u32 val) +{ + wl12xx_write32(wl, wl12xx_translate_reg_addr(wl, addr), val); +} diff --git a/drivers/net/wireless/wl12xx/spi.h b/drivers/net/wireless/wl12xx/spi.h new file mode 100644 index 000000000000..fd3227e904a8 --- /dev/null +++ b/drivers/net/wireless/wl12xx/spi.h @@ -0,0 +1,109 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_SPI_H__ +#define __WL12XX_SPI_H__ + +#include "cmd.h" +#include "acx.h" +#include "reg.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 + +#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 TNETWIF_READ_OFFSET_BYTES 8 +#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ + ((TNETWIF_READ_OFFSET_BYTES - 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); + +/* 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); + +/* Registers IO */ +u32 wl12xx_reg_read32(struct wl12xx *wl, int addr); +void wl12xx_reg_write32(struct wl12xx *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); + +static inline u32 wl12xx_read32(struct wl12xx *wl, int addr) +{ + u32 response; + + wl12xx_spi_read(wl, addr, &response, sizeof(u32)); + + return response; +} + +static inline void wl12xx_write32(struct wl12xx *wl, int addr, u32 val) +{ + wl12xx_spi_write(wl, addr, &val, sizeof(u32)); +} + +#endif /* __WL12XX_SPI_H__ */ diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c new file mode 100644 index 000000000000..62145e205a8c --- /dev/null +++ b/drivers/net/wireless/wl12xx/tx.c @@ -0,0 +1,557 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include + +#include "wl12xx.h" +#include "reg.h" +#include "spi.h" +#include "tx.h" +#include "ps.h" + +static bool wl12xx_tx_double_buffer_busy(struct wl12xx *wl, u32 data_out_count) +{ + int used, data_in_count; + + data_in_count = wl->data_in_count; + + if (data_in_count < data_out_count) + /* data_in_count has wrapped */ + data_in_count += TX_STATUS_DATA_OUT_COUNT_MASK + 1; + + used = data_in_count - data_out_count; + + WARN_ON(used < 0); + WARN_ON(used > DP_TX_PACKET_RING_CHUNK_NUM); + + if (used >= DP_TX_PACKET_RING_CHUNK_NUM) + return true; + else + return false; +} + +static int wl12xx_tx_path_status(struct wl12xx *wl) +{ + u32 status, addr, data_out_count; + bool busy; + + addr = wl->data_path->tx_control_addr; + status = wl12xx_mem_read32(wl, addr); + data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK; + busy = wl12xx_tx_double_buffer_busy(wl, data_out_count); + + if (busy) + return -EBUSY; + + return 0; +} + +static int wl12xx_tx_id(struct wl12xx *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 void wl12xx_tx_control(struct tx_double_buffer_desc *tx_hdr, + struct ieee80211_tx_info *control, u16 fc) +{ + *(u16 *)&tx_hdr->control = 0; + + tx_hdr->control.rate_policy = 0; + + /* 802.11 packets */ + tx_hdr->control.packet_type = 0; + + if (control->flags & IEEE80211_TX_CTL_NO_ACK) + tx_hdr->control.ack_policy = 1; + + tx_hdr->control.tx_complete = 1; + + if ((fc & IEEE80211_FTYPE_DATA) && + ((fc & IEEE80211_STYPE_QOS_DATA) || + (fc & IEEE80211_STYPE_QOS_NULLFUNC))) + tx_hdr->control.qos = 1; +} + +/* RSN + MIC = 8 + 8 = 16 bytes (worst case - AES). */ +#define MAX_MSDU_SECURITY_LENGTH 16 +#define MAX_MPDU_SECURITY_LENGTH 16 +#define WLAN_QOS_HDR_LEN 26 +#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) +{ + u16 payload_len, frag_threshold, mem_blocks; + u16 num_mpdus, mem_blocks_per_frag; + + frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; + tx_hdr->frag_threshold = cpu_to_le16(frag_threshold); + + payload_len = tx_hdr->length + MAX_MSDU_SECURITY_LENGTH; + + if (payload_len > frag_threshold) { + mem_blocks_per_frag = + ((frag_threshold + MAX_MPDU_HEADER_AND_SECURITY) / + HW_BLOCK_SIZE) + 1; + num_mpdus = payload_len / frag_threshold; + mem_blocks = num_mpdus * mem_blocks_per_frag; + payload_len -= num_mpdus * frag_threshold; + num_mpdus++; + + } else { + mem_blocks_per_frag = 0; + mem_blocks = 0; + num_mpdus = 1; + } + + mem_blocks += (payload_len / HW_BLOCK_SIZE) + 1; + + if (num_mpdus > 1) + mem_blocks += min(num_mpdus, mem_blocks_per_frag); + + tx_hdr->num_mem_blocks = mem_blocks; +} + +static int wl12xx_tx_fill_hdr(struct wl12xx *wl, struct sk_buff *skb, + struct ieee80211_tx_info *control) +{ + struct tx_double_buffer_desc *tx_hdr; + struct ieee80211_rate *rate; + int id; + u16 fc; + + if (!skb) + return -EINVAL; + + id = wl12xx_tx_id(wl, skb); + if (id < 0) + return id; + + fc = *(u16 *)skb->data; + tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb, + sizeof(*tx_hdr)); + + tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr)); + rate = ieee80211_get_tx_rate(wl->hw, control); + tx_hdr->rate = cpu_to_le16(rate->hw_value); + tx_hdr->expiry_time = cpu_to_le32(1 << 16); + tx_hdr->id = id; + + /* 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); + + return 0; +} + +/* We copy the packet to the target */ +static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb, + struct ieee80211_tx_info *control) +{ + struct tx_double_buffer_desc *tx_hdr; + int len; + u32 addr; + + if (!skb) + return -EINVAL; + + tx_hdr = (struct tx_double_buffer_desc *) skb->data; + + if (control->control.hw_key && + control->control.hw_key->alg == ALG_TKIP) { + int hdrlen; + u16 fc; + u8 *pos; + + fc = *(u16 *)(skb->data + sizeof(*tx_hdr)); + tx_hdr->length += WL12XX_TKIP_IV_SPACE; + + hdrlen = ieee80211_hdrlen(fc); + + pos = skb_push(skb, WL12XX_TKIP_IV_SPACE); + memmove(pos, pos + WL12XX_TKIP_IV_SPACE, + sizeof(*tx_hdr) + hdrlen); + } + + /* Revisit. 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; + wl12xx_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 { + wl12xx_info("No handler, fixme!"); + return -EINVAL; + } + } + + /* Our skb->data at this point includes the HW header */ + len = WL12XX_TX_ALIGN(skb->len); + + if (wl->data_in_count & 0x1) + addr = wl->data_path->tx_packet_ring_addr + + wl->data_path->tx_packet_ring_chunk_size; + else + addr = wl->data_path->tx_packet_ring_addr; + + wl12xx_spi_mem_write(wl, addr, skb->data, len); + + wl12xx_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) +{ + u32 data, addr; + + if (wl->data_in_count & 0x1) { + addr = ACX_REG_INTERRUPT_TRIG_H; + data = INTR_TRIG_TX_PROC1; + } else { + addr = ACX_REG_INTERRUPT_TRIG; + data = INTR_TRIG_TX_PROC0; + } + + wl12xx_reg_write32(wl, addr, data); + + /* Bumping data in */ + wl->data_in_count = (wl->data_in_count + 1) & + TX_STATUS_DATA_OUT_COUNT_MASK; +} + +/* caller must hold wl->mutex */ +static int wl12xx_tx_frame(struct wl12xx *wl, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info; + int ret = 0; + u8 idx; + + info = IEEE80211_SKB_CB(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); + if (ret < 0) + return ret; + } + } + + ret = wl12xx_tx_path_status(wl); + if (ret < 0) + return ret; + + ret = wl12xx_tx_fill_hdr(wl, skb, info); + if (ret < 0) + return ret; + + ret = wl12xx_tx_send_packet(wl, skb, info); + if (ret < 0) + return ret; + + wl12xx_tx_trigger(wl); + + return ret; +} + +void wl12xx_tx_work(struct work_struct *work) +{ + struct wl12xx *wl = container_of(work, struct wl12xx, tx_work); + struct sk_buff *skb; + bool woken_up = false; + int ret; + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL12XX_STATE_OFF)) + goto out; + + while ((skb = skb_dequeue(&wl->tx_queue))) { + if (!woken_up) { + wl12xx_ps_elp_wakeup(wl); + woken_up = true; + } + + ret = wl12xx_tx_frame(wl, skb); + if (ret == -EBUSY) { + /* firmware buffer is full, stop queues */ + wl12xx_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; + } + } + +out: + if (woken_up) + wl12xx_ps_elp_sleep(wl); + + mutex_unlock(&wl->mutex); +} + +static const char *wl12xx_tx_parse_status(u8 status) +{ + /* 8 bit status field, one character per bit plus null */ + static char buf[9]; + int i = 0; + + memset(buf, 0, sizeof(buf)); + + if (status & TX_DMA_ERROR) + buf[i++] = 'm'; + if (status & TX_DISABLED) + buf[i++] = 'd'; + if (status & TX_RETRY_EXCEEDED) + buf[i++] = 'r'; + if (status & TX_TIMEOUT) + buf[i++] = 't'; + if (status & TX_KEY_NOT_FOUND) + buf[i++] = 'k'; + if (status & TX_ENCRYPT_FAIL) + buf[i++] = 'e'; + if (status & TX_UNAVAILABLE_PRIORITY) + buf[i++] = 'p'; + + /* bit 0 is unused apparently */ + + return buf; +} + +static void wl12xx_tx_packet_cb(struct wl12xx *wl, + struct tx_result *result) +{ + struct ieee80211_tx_info *info; + struct sk_buff *skb; + int hdrlen, ret; + u8 *frame; + + skb = wl->tx_frames[result->id]; + if (skb == NULL) { + wl12xx_error("SKB for packet %d is NULL", result->id); + return; + } + + info = IEEE80211_SKB_CB(skb); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (result->status == TX_SUCCESS)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = result->ack_failures + 1; + wl->stats.retry_count += result->ack_failures; + + /* + * We have to remove our private TX header before pushing + * the skb back to mac80211. + */ + frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); + 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); + } + + wl12xx_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)); + + + ieee80211_tx_status(wl->hw, skb); + + wl->tx_frames[result->id] = NULL; + + if (wl->tx_queue_stopped) { + wl12xx_debug(DEBUG_TX, "cb: queue was stopped"); + + skb = skb_dequeue(&wl->tx_queue); + + /* The skb can be NULL because tx_work might have been + scheduled before the queue was stopped making the + queue empty */ + + if (skb) { + ret = wl12xx_tx_frame(wl, skb); + if (ret == -EBUSY) { + /* firmware buffer is still full */ + wl12xx_debug(DEBUG_TX, "cb: fw buffer " + "still full"); + skb_queue_head(&wl->tx_queue, skb); + return; + } else if (ret < 0) { + dev_kfree_skb(skb); + return; + } + } + + wl12xx_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) +{ + 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)) + return; + + /* First we read the result */ + wl12xx_spi_mem_read(wl, wl->data_path->tx_complete_addr, + result, sizeof(result)); + + result_index = wl->next_tx_complete; + + for (i = 0; i < ARRAY_SIZE(result); i++) { + result_ptr = &result[result_index]; + + if (result_ptr->done_1 == 1 && + result_ptr->done_2 == 1) { + wl12xx_tx_packet_cb(wl, result_ptr); + + result_ptr->done_1 = 0; + result_ptr->done_2 = 0; + + result_index = (result_index + 1) & + (FW_TX_CMPLT_BLOCK_SIZE - 1); + num_complete++; + } else { + break; + } + } + + /* Every completed frame needs to be acknowledged */ + if (num_complete) { + /* + * If we've wrapped, we have to clear + * the results in 2 steps. + */ + 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)); + + + } 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)); + + } 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)); + } + + } + + wl->next_tx_complete = result_index; +} + +/* caller must hold wl->mutex */ +void wl12xx_tx_flush(struct wl12xx *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); + + wl12xx_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/tx.h b/drivers/net/wireless/wl12xx/tx.h new file mode 100644 index 000000000000..dc82691f4c14 --- /dev/null +++ b/drivers/net/wireless/wl12xx/tx.h @@ -0,0 +1,215 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_TX_H__ +#define __WL12XX_TX_H__ + +#include + +/* + * + * TX PATH + * + * The Tx path uses a double buffer and a tx_control structure, each located + * at a fixed address in the device's memory. On startup, the host retrieves + * the pointers to these addresses. A double buffer allows for continuous data + * flow towards the device. The host keeps track of which buffer is available + * and alternates between these two buffers on a per packet basis. + * + * The size of each of the two buffers is large enough to hold the longest + * 802.3 packet - maximum size Ethernet packet + header + descriptor. + * TX complete indication will be received a-synchronously in a TX done cyclic + * buffer which is composed of 16 tx_result descriptors structures and is used + * in a cyclic manner. + * + * The TX (HOST) procedure is as follows: + * 1. Read the Tx path status, that will give the data_out_count. + * 2. goto 1, if not possible. + * i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double + * buffer). + * 3. Copy the packet (preceded by double_buffer_desc), if possible. + * i.e. if data_in_count - data_out_count < HwBuffer size (2 for double + * buffer). + * 4. increment data_in_count. + * 5. Inform the firmware by generating a firmware internal interrupt. + * 6. FW will increment data_out_count after it reads the buffer. + * + * The TX Complete procedure: + * 1. To get a TX complete indication the host enables the tx_complete flag in + * the TX descriptor Structure. + * 2. For each packet with a Tx Complete field set, the firmware adds the + * transmit results to the cyclic buffer (txDoneRing) and sets both done_1 + * and done_2 to 1 to indicate driver ownership. + * 3. The firmware sends a Tx Complete interrupt to the host to trigger the + * host to process the new data. Note: interrupt will be send per packet if + * TX complete indication was requested in tx_control or per crossing + * aggregation threshold. + * 4. After receiving the Tx Complete interrupt, the host reads the + * TxDescriptorDone information in a cyclic manner and clears both done_1 + * and done_2 fields. + * + */ + +#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 + +struct tx_control { + /* Rate Policy (class) index */ + unsigned rate_policy:3; + + /* When set, no ack policy is expected */ + unsigned ack_policy:1; + + /* + * Packet type: + * 0 -> 802.11 + * 1 -> 802.3 + * 2 -> IP + * 3 -> raw codec + */ + unsigned packet_type:2; + + /* If set, this is a QoS-Null or QoS-Data frame */ + unsigned qos:1; + + /* + * If set, the target triggers the tx complete INT + * upon frame sending completion. + */ + unsigned tx_complete:1; + + /* 2 bytes padding before packet header */ + unsigned xfer_pad:1; + + unsigned reserved:7; +} __attribute__ ((packed)); + + +struct tx_double_buffer_desc { + /* Length of payload, including headers. */ + u16 length; + + /* + * A bit mask that specifies the initial rate to be used + * Possible values are: + * 0x0001 - 1Mbits + * 0x0002 - 2Mbits + * 0x0004 - 5.5Mbits + * 0x0008 - 6Mbits + * 0x0010 - 9Mbits + * 0x0020 - 11Mbits + * 0x0040 - 12Mbits + * 0x0080 - 18Mbits + * 0x0100 - 22Mbits + * 0x0200 - 24Mbits + * 0x0400 - 36Mbits + * 0x0800 - 48Mbits + * 0x1000 - 54Mbits + */ + u16 rate; + + /* Time in us that a packet can spend in the target */ + u32 expiry_time; + + /* index of the TX queue used for this packet */ + u8 xmit_queue; + + /* Used to identify a packet */ + u8 id; + + struct tx_control control; + + /* + * The FW should cut the packet into fragments + * of this size. + */ + u16 frag_threshold; + + /* Numbers of HW queue blocks to be allocated */ + u8 num_mem_blocks; + + u8 reserved; +} __attribute__ ((packed)); + +enum { + TX_SUCCESS = 0, + TX_DMA_ERROR = BIT(7), + TX_DISABLED = BIT(6), + TX_RETRY_EXCEEDED = BIT(5), + TX_TIMEOUT = BIT(4), + TX_KEY_NOT_FOUND = BIT(3), + TX_ENCRYPT_FAIL = BIT(2), + TX_UNAVAILABLE_PRIORITY = BIT(1), +}; + +struct tx_result { + /* + * Ownership synchronization between the host and + * the firmware. If done_1 and done_2 are cleared, + * owned by the FW (no info ready). + */ + u8 done_1; + + /* same as double_buffer_desc->id */ + u8 id; + + /* + * Total air access duration consumed by this + * packet, including all retries and overheads. + */ + u16 medium_usage; + + /* Total media delay (from 1st EDCA AIFS counter until TX Complete). */ + u32 medium_delay; + + /* Time between host xfer and tx complete */ + u32 fw_hnadling_time; + + /* The LS-byte of the last TKIP sequence number. */ + u8 lsb_seq_num; + + /* Retry count */ + u8 ack_failures; + + /* At which rate we got a ACK */ + u16 rate; + + u16 reserved; + + /* TX_* */ + u8 status; + + /* See done_1 */ + 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); + +#endif diff --git a/drivers/net/wireless/wl12xx/wl1251.c b/drivers/net/wireless/wl12xx/wl1251.c new file mode 100644 index 000000000000..ce1561a41fa4 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1251.c @@ -0,0 +1,709 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 +#include + +#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 new file mode 100644 index 000000000000..1f4a44330394 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -0,0 +1,165 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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_H__ +#define __WL1251_H__ + +#include + +#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; + + /* + * 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 + +#endif diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h new file mode 100644 index 000000000000..48641437414b --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -0,0 +1,409 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 __WL12XX_H__ +#define __WL12XX_H__ + +#include +#include +#include +#include + +#define DRIVER_NAME "wl12xx" +#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 wl12xx_error(fmt, arg...) \ + printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) + +#define wl12xx_warning(fmt, arg...) \ + printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) + +#define wl12xx_notice(fmt, arg...) \ + printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) + +#define wl12xx_info(fmt, arg...) \ + printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) + +#define wl12xx_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) \ + 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 wl12xx_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 WL12XX_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; +}; + +enum wl12xx_state { + WL12XX_STATE_OFF, + WL12XX_STATE_ON, + WL12XX_STATE_PLT, +}; + +enum wl12xx_partition_type { + PART_DOWN, + PART_WORK, + PART_DRPW, + + PART_TABLE_LEN +}; + +struct wl12xx_partition { + u32 size; + u32 start; +}; + +struct wl12xx_partition_set { + struct wl12xx_partition mem; + struct wl12xx_partition reg; +}; + +struct wl12xx; + +/* FIXME: I'm not sure about this structure name */ +struct wl12xx_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 acx_statistics *fw_stats; + unsigned long fw_stats_update; + + unsigned int retry_count; + unsigned int excessive_retries; +}; + +struct wl12xx_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 wl12xx { + struct ieee80211_hw *hw; + bool mac80211_registered; + + struct spi_device *spi; + + void (*set_power)(bool enable); + int irq; + + enum wl12xx_state state; + struct mutex mutex; + + int physical_mem_addr; + int physical_reg_addr; + int virtual_mem_addr; + int virtual_reg_addr; + + struct wl12xx_chip chip; + + 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]; + + /* + * 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; + + /* The target interrupt mask */ + u32 intr_mask; + struct work_struct irq_work; + + /* The mbox event mask */ + u32 event_mask; + + /* Mailbox pointers */ + u32 mbox_ptr[2]; + + /* Are we currently scanning */ + bool scanning; + + /* Our association ID */ + u16 aid; + + /* 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; + + /* we can be in psm, but not in elp, we have to differentiate */ + bool psm; + + /* PSM mode requested */ + bool psm_requested; + + /* in dBm */ + int power_level; + + struct wl12xx_stats stats; + struct wl12xx_debugfs debugfs; +}; + +int wl12xx_plt_start(struct wl12xx *wl); +int wl12xx_plt_stop(struct wl12xx *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 WL12XX_TX_QUEUE_MAX_LENGTH 20 + +/* 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 CHIP_ID_1251_PG10 (0x7010101) +#define CHIP_ID_1251_PG11 (0x7020101) +#define CHIP_ID_1251_PG12 (0x7030101) +#define CHIP_ID_1271_PG10 (0x4030101) + +#endif diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h new file mode 100644 index 000000000000..657c2dbcb7d3 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -0,0 +1,156 @@ +#ifndef __WL12XX_80211_H__ +#define __WL12XX_80211_H__ + +#include /* ETH_ALEN */ + +/* RATES */ +#define IEEE80211_CCK_RATE_1MB 0x02 +#define IEEE80211_CCK_RATE_2MB 0x04 +#define IEEE80211_CCK_RATE_5MB 0x0B +#define IEEE80211_CCK_RATE_11MB 0x16 +#define IEEE80211_OFDM_RATE_6MB 0x0C +#define IEEE80211_OFDM_RATE_9MB 0x12 +#define IEEE80211_OFDM_RATE_12MB 0x18 +#define IEEE80211_OFDM_RATE_18MB 0x24 +#define IEEE80211_OFDM_RATE_24MB 0x30 +#define IEEE80211_OFDM_RATE_36MB 0x48 +#define IEEE80211_OFDM_RATE_48MB 0x60 +#define IEEE80211_OFDM_RATE_54MB 0x6C +#define IEEE80211_BASIC_RATE_MASK 0x80 + +#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) +#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) +#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) +#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) +#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) +#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) +#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) +#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) +#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) +#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) +#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) +#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) + +#define IEEE80211_CCK_RATES_MASK 0x0000000F +#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ + IEEE80211_CCK_RATE_2MB_MASK) +#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ + IEEE80211_CCK_RATE_5MB_MASK | \ + IEEE80211_CCK_RATE_11MB_MASK) + +#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 +#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ + IEEE80211_OFDM_RATE_12MB_MASK | \ + IEEE80211_OFDM_RATE_24MB_MASK) +#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ + IEEE80211_OFDM_RATE_9MB_MASK | \ + IEEE80211_OFDM_RATE_18MB_MASK | \ + IEEE80211_OFDM_RATE_36MB_MASK | \ + IEEE80211_OFDM_RATE_48MB_MASK | \ + IEEE80211_OFDM_RATE_54MB_MASK) +#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ + IEEE80211_CCK_DEFAULT_RATES_MASK) + + +/* This really should be 8, but not for our firmware */ +#define MAX_SUPPORTED_RATES 32 +#define COUNTRY_STRING_LEN 3 +#define MAX_COUNTRY_TRIPLETS 32 + +/* Headers */ +struct ieee80211_header { + __le16 frame_ctl; + __le16 duration_id; + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct wl12xx_ie_header { + u8 id; + u8 len; +} __attribute__ ((packed)); + +/* IEs */ + +struct wl12xx_ie_ssid { + struct wl12xx_ie_header header; + char ssid[IW_ESSID_MAX_SIZE]; +} __attribute__ ((packed)); + +struct wl12xx_ie_rates { + struct wl12xx_ie_header header; + u8 rates[MAX_SUPPORTED_RATES]; +} __attribute__ ((packed)); + +struct wl12xx_ie_ds_params { + struct wl12xx_ie_header header; + u8 channel; +} __attribute__ ((packed)); + +struct country_triplet { + u8 channel; + u8 num_channels; + u8 max_tx_power; +} __attribute__ ((packed)); + +struct wl12xx_ie_country { + struct wl12xx_ie_header header; + u8 country_string[COUNTRY_STRING_LEN]; + struct country_triplet triplets[MAX_COUNTRY_TRIPLETS]; +} __attribute__ ((packed)); + + +/* Templates */ + +struct wl12xx_beacon_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __attribute__ ((packed)); + +struct wl12xx_null_data_template { + struct ieee80211_header header; +} __attribute__ ((packed)); + +struct wl12xx_ps_poll_template { + u16 fc; + u16 aid; + u8 bssid[ETH_ALEN]; + u8 ta[ETH_ALEN]; +} __attribute__ ((packed)); + +struct wl12xx_qos_null_data_template { + struct ieee80211_header header; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct wl12xx_probe_req_template { + struct ieee80211_header header; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; +} __attribute__ ((packed)); + + +struct wl12xx_probe_resp_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __attribute__ ((packed)); + +#endif diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 1f64d6033ab5..e3e96bb2c246 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1348,6 +1348,7 @@ 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; diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 5fabd9c0f07a..4430b8d92e21 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -819,11 +819,11 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (err) { dev->stats.tx_errors++; netif_start_queue(dev); - return err; + } else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; } - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; kfree_skb(skb); return 0; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index c3a51266de20..40b07b988224 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -420,9 +420,9 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; - /* Multicast */ - if (is_multicast_ether_addr(header->addr1)) - cs->control |= ZD_CS_MULTICAST; + /* No ACK expected (multicast, etc.) */ + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + cs->control |= ZD_CS_NO_ACK; /* PS-POLL */ if (ieee80211_is_pspoll(header->frame_control)) @@ -755,52 +755,6 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed) return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); } -static int zd_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct zd_mac *mac = zd_hw_mac(hw); - int associated; - int r; - - if (mac->type == NL80211_IFTYPE_MESH_POINT || - mac->type == NL80211_IFTYPE_ADHOC) { - associated = true; - if (conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - - if (!beacon) - return -ENOMEM; - r = zd_mac_config_beacon(hw, beacon); - kfree_skb(beacon); - - if (r < 0) - return r; - } - - if (conf->changed & IEEE80211_IFCC_BEACON_ENABLED) { - u32 interval; - - if (conf->enable_beacon) - interval = BCN_MODE_IBSS | hw->conf.beacon_int; - else - interval = 0; - - r = zd_set_beacon_interval(&mac->chip, interval); - if (r < 0) - return r; - } - } else - associated = is_valid_ether_addr(conf->bssid); - - spin_lock_irq(&mac->lock); - mac->associated = associated; - spin_unlock_irq(&mac->lock); - - /* TODO: do hardware bssid filtering */ - return 0; -} - static void zd_process_intr(struct work_struct *work) { u16 int_status; @@ -923,9 +877,42 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, { struct zd_mac *mac = zd_hw_mac(hw); unsigned long flags; + int associated; dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); + if (mac->type == NL80211_IFTYPE_MESH_POINT || + mac->type == NL80211_IFTYPE_ADHOC) { + associated = true; + if (changes & BSS_CHANGED_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) { + zd_mac_config_beacon(hw, beacon); + kfree_skb(beacon); + } + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) { + u32 interval; + + if (bss_conf->enable_beacon) + interval = BCN_MODE_IBSS | + bss_conf->beacon_int; + else + interval = 0; + + zd_set_beacon_interval(&mac->chip, interval); + } + } else + associated = is_valid_ether_addr(bss_conf->bssid); + + spin_lock_irq(&mac->lock); + mac->associated = associated; + spin_unlock_irq(&mac->lock); + + /* TODO: do hardware bssid filtering */ + if (changes & BSS_CHANGED_ERP_PREAMBLE) { spin_lock_irqsave(&mac->lock, flags); mac->short_preamble = bss_conf->use_short_preamble; @@ -952,7 +939,6 @@ static const struct ieee80211_ops zd_ops = { .add_interface = zd_op_add_interface, .remove_interface = zd_op_remove_interface, .config = zd_op_config, - .config_interface = zd_op_config_interface, .configure_filter = zd_op_configure_filter, .bss_info_changed = zd_op_bss_info_changed, .get_tsf = zd_op_get_tsf, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 4c05d3ee4c37..7c2759118d13 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -87,7 +87,7 @@ struct zd_ctrlset { /* zd_ctrlset control field */ #define ZD_CS_NEED_RANDOM_BACKOFF 0x01 -#define ZD_CS_MULTICAST 0x02 +#define ZD_CS_NO_ACK 0x02 #define ZD_CS_FRAME_TYPE_MASK 0x0c #define ZD_CS_DATA_FRAME 0x00 diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 7477ffdcddb4..3c7a5053f1da 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -717,7 +717,7 @@ static void yellowfin_tx_timeout(struct net_device *dev) if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE) netif_wake_queue (dev); /* Typical path */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_errors++; } @@ -876,7 +876,6 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_start_queue (dev); /* Typical path */ else yp->tx_full = 1; - dev->trans_start = jiffies; if (yellowfin_debug > 4) { printk(KERN_DEBUG "%s: Yellowfin transmit frame #%d queued in slot %d.\n", diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 27f3b81333de..d2fa27c5c1b2 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -19,3 +19,9 @@ config OF_SPI depends on OF && (PPC_OF || MICROBLAZE) && SPI help OpenFirmware SPI accessors + +config OF_MDIO + def_tristate PHYLIB + depends on OF && PHYLIB + help + OpenFirmware MDIO bus (Ethernet PHY) accessors diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 4c3c6f8e36f5..bdfb5f5d4b06 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_OF_DEVICE) += device.o platform.o obj-$(CONFIG_OF_GPIO) += gpio.o obj-$(CONFIG_OF_I2C) += of_i2c.o obj-$(CONFIG_OF_SPI) += of_spi.o +obj-$(CONFIG_OF_MDIO) += of_mdio.o diff --git a/drivers/of/base.c b/drivers/of/base.c index 391f91c0bf55..69f85c07d17f 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -495,6 +495,30 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) } EXPORT_SYMBOL_GPL(of_modalias_node); +/** + * of_parse_phandle - Resolve a phandle property to a device_node pointer + * @np: Pointer to device node holding phandle property + * @phandle_name: Name of property holding a phandle value + * @index: For properties holding a table of phandles, this is the index into + * the table + * + * Returns the device_node pointer with refcount incremented. Use + * of_node_put() on it when done. + */ +struct device_node * +of_parse_phandle(struct device_node *np, const char *phandle_name, int index) +{ + const phandle *phandle; + int size; + + phandle = of_get_property(np, phandle_name, &size); + if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) + return NULL; + + return of_find_node_by_phandle(phandle[index]); +} +EXPORT_SYMBOL(of_parse_phandle); + /** * of_parse_phandles_with_args - Find a node pointed by phandle in a list * @np: pointer to a device tree node containing a list diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c new file mode 100644 index 000000000000..aee967d7f760 --- /dev/null +++ b/drivers/of/of_mdio.c @@ -0,0 +1,139 @@ +/* + * OF helpers for the MDIO (Ethernet PHY) API + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + * + * This file is released under the GPLv2 + * + * This file provides helper functions for extracting PHY device information + * out of the OpenFirmware device tree and using it to populate an mii_bus. + */ + +#include +#include +#include +#include + +MODULE_AUTHOR("Grant Likely "); +MODULE_LICENSE("GPL"); + +/** + * of_mdiobus_register - Register mii_bus and create PHYs from the device tree + * @mdio: pointer to mii_bus structure + * @np: pointer to device_node of MDIO bus. + * + * This function registers the mii_bus structure and registers a phy_device + * for each child node of @np. + */ +int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +{ + struct phy_device *phy; + struct device_node *child; + int rc, i; + + /* Mask out all PHYs from auto probing. Instead the PHYs listed in + * the device tree are populated after the bus has been registered */ + mdio->phy_mask = ~0; + + /* Clear all the IRQ properties */ + if (mdio->irq) + for (i=0; iirq[i] = PHY_POLL; + + /* Register the MDIO bus */ + rc = mdiobus_register(mdio); + if (rc) + return rc; + + /* Loop over the child nodes and register a phy_device for each one */ + for_each_child_of_node(np, child) { + const u32 *addr; + int len; + + /* A PHY must have a reg property in the range [0-31] */ + addr = of_get_property(child, "reg", &len); + if (!addr || len < sizeof(*addr) || *addr >= 32 || *addr < 0) { + dev_err(&mdio->dev, "%s has invalid PHY address\n", + child->full_name); + continue; + } + + if (mdio->irq) { + mdio->irq[*addr] = irq_of_parse_and_map(child, 0); + if (!mdio->irq[*addr]) + mdio->irq[*addr] = PHY_POLL; + } + + phy = get_phy_device(mdio, *addr); + if (!phy) { + dev_err(&mdio->dev, "error probing PHY at address %i\n", + *addr); + continue; + } + phy_scan_fixups(phy); + + /* Associate the OF node with the device structure so it + * can be looked up later */ + of_node_get(child); + dev_archdata_set_node(&phy->dev.archdata, child); + + /* All data is now stored in the phy struct; register it */ + rc = phy_device_register(phy); + if (rc) { + phy_device_free(phy); + of_node_put(child); + continue; + } + + dev_dbg(&mdio->dev, "registered phy %s at address %i\n", + child->name, *addr); + } + + return 0; +} +EXPORT_SYMBOL(of_mdiobus_register); + +/** + * of_phy_find_device - Give a PHY node, find the phy_device + * @phy_np: Pointer to the phy's device tree node + * + * Returns a pointer to the phy_device. + */ +struct phy_device *of_phy_find_device(struct device_node *phy_np) +{ + struct device *d; + int match(struct device *dev, void *phy_np) + { + return dev_archdata_get_node(&dev->archdata) == phy_np; + } + + if (!phy_np) + return NULL; + + d = bus_find_device(&mdio_bus_type, NULL, phy_np, match); + return d ? to_phy_device(d) : NULL; +} +EXPORT_SYMBOL(of_phy_find_device); + +/** + * of_phy_connect - Connect to the phy described in the device tree + * @dev: pointer to net_device claiming the phy + * @phy_np: Pointer to device tree node for the PHY + * @hndlr: Link state callback for the network device + * @iface: PHY data interface type + * + * Returns a pointer to the phy_device if successfull. NULL otherwise + */ +struct phy_device *of_phy_connect(struct net_device *dev, + struct device_node *phy_np, + void (*hndlr)(struct net_device *), u32 flags, + phy_interface_t iface) +{ + struct phy_device *phy = of_phy_find_device(phy_np); + + if (!phy) + return NULL; + + return phy_connect_direct(dev, phy, hndlr, flags, iface) ? NULL : phy; +} +EXPORT_SYMBOL(of_phy_connect); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 3067673d54f6..bd4253f93d5a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2461,6 +2461,8 @@ static void __devinit quirk_i82576_sriov(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); #endif /* CONFIG_PCI_IOV */ diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 284ebaca6e45..c682ac536415 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -21,7 +21,7 @@ config ACER_WMI depends on NEW_LEDS depends on BACKLIGHT_CLASS_DEVICE depends on SERIO_I8042 - depends on RFKILL + depends on RFKILL || RFKILL = n select ACPI_WMI ---help--- This is a driver for newer Acer (and Wistron) laptops. It adds @@ -60,7 +60,7 @@ config DELL_LAPTOP depends on DCDBAS depends on EXPERIMENTAL depends on BACKLIGHT_CLASS_DEVICE - depends on RFKILL + depends on RFKILL || RFKILL = n depends on POWER_SUPPLY default n ---help--- @@ -117,7 +117,7 @@ config HP_WMI tristate "HP WMI extras" depends on ACPI_WMI depends on INPUT - depends on RFKILL + depends on RFKILL || RFKILL = n help Say Y here if you want to support WMI-based hotkeys on HP laptops and to read data from WMI such as docking or ambient light sensor state. @@ -196,14 +196,13 @@ config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on ACPI depends on INPUT + depends on RFKILL || RFKILL = n select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE select HWMON select NVRAM select NEW_LEDS select LEDS_CLASS - select NET - select RFKILL ---help--- This is a driver for the IBM and Lenovo ThinkPad laptops. It adds support for Fn-Fx key combinations, Bluetooth control, video @@ -338,9 +337,9 @@ config EEEPC_LAPTOP depends on ACPI depends on INPUT depends on EXPERIMENTAL + depends on RFKILL || RFKILL = n select BACKLIGHT_CLASS_DEVICE select HWMON - select RFKILL ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. It also adds the ability to switch camera/wlan on/off. @@ -405,9 +404,8 @@ config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on ACPI depends on INPUT + depends on RFKILL || RFKILL = n select INPUT_POLLDEV - select NET - select RFKILL select BACKLIGHT_CLASS_DEVICE ---help--- This driver adds support for access to certain system settings diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 0f6e43bf4fc2..09a503e5da6a 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -958,59 +958,47 @@ static void acer_rfkill_update(struct work_struct *ignored) status = get_u32(&state, ACER_CAP_WIRELESS); if (ACPI_SUCCESS(status)) - rfkill_force_state(wireless_rfkill, state ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED); + rfkill_set_sw_state(wireless_rfkill, !!state); if (has_cap(ACER_CAP_BLUETOOTH)) { status = get_u32(&state, ACER_CAP_BLUETOOTH); if (ACPI_SUCCESS(status)) - rfkill_force_state(bluetooth_rfkill, state ? - RFKILL_STATE_UNBLOCKED : - RFKILL_STATE_SOFT_BLOCKED); + rfkill_set_sw_state(bluetooth_rfkill, !!state); } schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); } -static int acer_rfkill_set(void *data, enum rfkill_state state) +static int acer_rfkill_set(void *data, bool blocked) { acpi_status status; - u32 *cap = data; - status = set_u32((u32) (state == RFKILL_STATE_UNBLOCKED), *cap); + u32 cap = (unsigned long)data; + status = set_u32(!!blocked, cap); if (ACPI_FAILURE(status)) return -ENODEV; return 0; } -static struct rfkill * acer_rfkill_register(struct device *dev, -enum rfkill_type type, char *name, u32 cap) +static const struct rfkill_ops acer_rfkill_ops = { + .set_block = acer_rfkill_set, +}; + +static struct rfkill *acer_rfkill_register(struct device *dev, + enum rfkill_type type, + char *name, u32 cap) { int err; - u32 state; - u32 *data; struct rfkill *rfkill_dev; - rfkill_dev = rfkill_allocate(dev, type); + rfkill_dev = rfkill_alloc(name, dev, type, + &acer_rfkill_ops, + (void *)(unsigned long)cap); if (!rfkill_dev) return ERR_PTR(-ENOMEM); - rfkill_dev->name = name; - get_u32(&state, cap); - rfkill_dev->state = state ? RFKILL_STATE_UNBLOCKED : - RFKILL_STATE_SOFT_BLOCKED; - data = kzalloc(sizeof(u32), GFP_KERNEL); - if (!data) { - rfkill_free(rfkill_dev); - return ERR_PTR(-ENOMEM); - } - *data = cap; - rfkill_dev->data = data; - rfkill_dev->toggle_radio = acer_rfkill_set; - rfkill_dev->user_claim_unsupported = 1; err = rfkill_register(rfkill_dev); if (err) { - kfree(rfkill_dev->data); - rfkill_free(rfkill_dev); + rfkill_destroy(rfkill_dev); return ERR_PTR(err); } return rfkill_dev; @@ -1028,8 +1016,8 @@ static int acer_rfkill_init(struct device *dev) RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", ACER_CAP_BLUETOOTH); if (IS_ERR(bluetooth_rfkill)) { - kfree(wireless_rfkill->data); rfkill_unregister(wireless_rfkill); + rfkill_destroy(wireless_rfkill); return PTR_ERR(bluetooth_rfkill); } } @@ -1042,11 +1030,13 @@ static int acer_rfkill_init(struct device *dev) static void acer_rfkill_exit(void) { cancel_delayed_work_sync(&acer_rfkill_work); - kfree(wireless_rfkill->data); + rfkill_unregister(wireless_rfkill); + rfkill_destroy(wireless_rfkill); + if (has_cap(ACER_CAP_BLUETOOTH)) { - kfree(bluetooth_rfkill->data); rfkill_unregister(bluetooth_rfkill); + rfkill_destroy(bluetooth_rfkill); } return; } diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index af9f43021172..2faf0e14f05a 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -174,10 +174,11 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, result[3]: NVRAM format version number */ -static int dell_rfkill_set(int radio, enum rfkill_state state) +static int dell_rfkill_set(void *data, bool blocked) { struct calling_interface_buffer buffer; - int disable = (state == RFKILL_STATE_UNBLOCKED) ? 0 : 1; + int disable = blocked ? 0 : 1; + unsigned long radio = (unsigned long)data; memset(&buffer, 0, sizeof(struct calling_interface_buffer)); buffer.input[0] = (1 | (radio<<8) | (disable << 16)); @@ -186,56 +187,24 @@ static int dell_rfkill_set(int radio, enum rfkill_state state) return 0; } -static int dell_wifi_set(void *data, enum rfkill_state state) -{ - return dell_rfkill_set(1, state); -} - -static int dell_bluetooth_set(void *data, enum rfkill_state state) -{ - return dell_rfkill_set(2, state); -} - -static int dell_wwan_set(void *data, enum rfkill_state state) -{ - return dell_rfkill_set(3, state); -} - -static int dell_rfkill_get(int bit, enum rfkill_state *state) +static void dell_rfkill_query(struct rfkill *rfkill, void *data) { struct calling_interface_buffer buffer; int status; - int new_state = RFKILL_STATE_HARD_BLOCKED; + int bit = (unsigned long)data + 16; memset(&buffer, 0, sizeof(struct calling_interface_buffer)); dell_send_request(&buffer, 17, 11); status = buffer.output[1]; - if (status & (1<<16)) - new_state = RFKILL_STATE_SOFT_BLOCKED; - - if (status & (1<name = "dell-wifi"; - wifi_rfkill->toggle_radio = dell_wifi_set; - wifi_rfkill->get_state = dell_wifi_get; + } ret = rfkill_register(wifi_rfkill); if (ret) goto err_wifi; } if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { - bluetooth_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_BLUETOOTH); - if (!bluetooth_rfkill) + bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL, + RFKILL_TYPE_BLUETOOTH, + &dell_rfkill_ops, (void *) 2); + if (!bluetooth_rfkill) { + ret = -ENOMEM; goto err_bluetooth; - bluetooth_rfkill->name = "dell-bluetooth"; - bluetooth_rfkill->toggle_radio = dell_bluetooth_set; - bluetooth_rfkill->get_state = dell_bluetooth_get; + } ret = rfkill_register(bluetooth_rfkill); if (ret) goto err_bluetooth; } if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { - wwan_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WWAN); - if (!wwan_rfkill) + wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN, + &dell_rfkill_ops, (void *) 3); + if (!wwan_rfkill) { + ret = -ENOMEM; goto err_wwan; - wwan_rfkill->name = "dell-wwan"; - wwan_rfkill->toggle_radio = dell_wwan_set; - wwan_rfkill->get_state = dell_wwan_get; + } ret = rfkill_register(wwan_rfkill); if (ret) goto err_wwan; @@ -285,22 +255,15 @@ static int dell_setup_rfkill(void) return 0; err_wwan: - if (wwan_rfkill) - rfkill_free(wwan_rfkill); - if (bluetooth_rfkill) { - rfkill_unregister(bluetooth_rfkill); - bluetooth_rfkill = NULL; - } -err_bluetooth: + rfkill_destroy(wwan_rfkill); if (bluetooth_rfkill) - rfkill_free(bluetooth_rfkill); - if (wifi_rfkill) { - rfkill_unregister(wifi_rfkill); - wifi_rfkill = NULL; - } -err_wifi: + rfkill_unregister(bluetooth_rfkill); +err_bluetooth: + rfkill_destroy(bluetooth_rfkill); if (wifi_rfkill) - rfkill_free(wifi_rfkill); + rfkill_unregister(wifi_rfkill); +err_wifi: + rfkill_destroy(wifi_rfkill); return ret; } diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 353a898c3693..03bf522bd7ab 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -299,39 +299,22 @@ static int update_bl_status(struct backlight_device *bd) * Rfkill helpers */ -static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state) -{ - if (state == RFKILL_STATE_SOFT_BLOCKED) - return set_acpi(CM_ASL_WLAN, 0); - else - return set_acpi(CM_ASL_WLAN, 1); -} - -static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state) +static bool eeepc_wlan_rfkill_blocked(void) { if (get_acpi(CM_ASL_WLAN) == 1) - *state = RFKILL_STATE_UNBLOCKED; - else - *state = RFKILL_STATE_SOFT_BLOCKED; - return 0; + return false; + return true; } -static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state) +static int eeepc_rfkill_set(void *data, bool blocked) { - if (state == RFKILL_STATE_SOFT_BLOCKED) - return set_acpi(CM_ASL_BLUETOOTH, 0); - else - return set_acpi(CM_ASL_BLUETOOTH, 1); + unsigned long asl = (unsigned long)data; + return set_acpi(asl, !blocked); } -static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state) -{ - if (get_acpi(CM_ASL_BLUETOOTH) == 1) - *state = RFKILL_STATE_UNBLOCKED; - else - *state = RFKILL_STATE_SOFT_BLOCKED; - return 0; -} +static const struct rfkill_ops eeepc_rfkill_ops = { + .set_block = eeepc_rfkill_set, +}; /* * Sys helpers @@ -531,9 +514,9 @@ static int notify_brn(void) static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) { - enum rfkill_state state; struct pci_dev *dev; struct pci_bus *bus = pci_find_bus(0, 1); + bool blocked; if (event != ACPI_NOTIFY_BUS_CHECK) return; @@ -543,9 +526,8 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) return; } - eeepc_wlan_rfkill_state(ehotk->eeepc_wlan_rfkill, &state); - - if (state == RFKILL_STATE_UNBLOCKED) { + blocked = eeepc_wlan_rfkill_blocked(); + if (!blocked) { dev = pci_get_slot(bus, 0); if (dev) { /* Device already present */ @@ -566,7 +548,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) } } - rfkill_force_state(ehotk->eeepc_wlan_rfkill, state); + rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); } static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) @@ -684,26 +666,17 @@ static int eeepc_hotk_add(struct acpi_device *device) eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); if (get_acpi(CM_ASL_WLAN) != -1) { - ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev, - RFKILL_TYPE_WLAN); + ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", + &device->dev, + RFKILL_TYPE_WLAN, + &eeepc_rfkill_ops, + (void *)CM_ASL_WLAN); if (!ehotk->eeepc_wlan_rfkill) goto wlan_fail; - ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; - ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; - ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; - if (get_acpi(CM_ASL_WLAN) == 1) { - ehotk->eeepc_wlan_rfkill->state = - RFKILL_STATE_UNBLOCKED; - rfkill_set_default(RFKILL_TYPE_WLAN, - RFKILL_STATE_UNBLOCKED); - } else { - ehotk->eeepc_wlan_rfkill->state = - RFKILL_STATE_SOFT_BLOCKED; - rfkill_set_default(RFKILL_TYPE_WLAN, - RFKILL_STATE_SOFT_BLOCKED); - } + rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, + get_acpi(CM_ASL_WLAN) != 1); result = rfkill_register(ehotk->eeepc_wlan_rfkill); if (result) goto wlan_fail; @@ -711,28 +684,17 @@ static int eeepc_hotk_add(struct acpi_device *device) if (get_acpi(CM_ASL_BLUETOOTH) != -1) { ehotk->eeepc_bluetooth_rfkill = - rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); + rfkill_alloc("eeepc-bluetooth", + &device->dev, + RFKILL_TYPE_BLUETOOTH, + &eeepc_rfkill_ops, + (void *)CM_ASL_BLUETOOTH); if (!ehotk->eeepc_bluetooth_rfkill) goto bluetooth_fail; - ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; - ehotk->eeepc_bluetooth_rfkill->toggle_radio = - eeepc_bluetooth_rfkill_set; - ehotk->eeepc_bluetooth_rfkill->get_state = - eeepc_bluetooth_rfkill_state; - if (get_acpi(CM_ASL_BLUETOOTH) == 1) { - ehotk->eeepc_bluetooth_rfkill->state = - RFKILL_STATE_UNBLOCKED; - rfkill_set_default(RFKILL_TYPE_BLUETOOTH, - RFKILL_STATE_UNBLOCKED); - } else { - ehotk->eeepc_bluetooth_rfkill->state = - RFKILL_STATE_SOFT_BLOCKED; - rfkill_set_default(RFKILL_TYPE_BLUETOOTH, - RFKILL_STATE_SOFT_BLOCKED); - } - + rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, + get_acpi(CM_ASL_BLUETOOTH) != 1); result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); if (result) goto bluetooth_fail; @@ -741,13 +703,10 @@ static int eeepc_hotk_add(struct acpi_device *device) return 0; bluetooth_fail: - if (ehotk->eeepc_bluetooth_rfkill) - rfkill_free(ehotk->eeepc_bluetooth_rfkill); + rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); rfkill_unregister(ehotk->eeepc_wlan_rfkill); - ehotk->eeepc_wlan_rfkill = NULL; wlan_fail: - if (ehotk->eeepc_wlan_rfkill) - rfkill_free(ehotk->eeepc_wlan_rfkill); + rfkill_destroy(ehotk->eeepc_wlan_rfkill); eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); ehotk_fail: diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 50d9019de2be..16fffe44e333 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -154,58 +154,46 @@ static int hp_wmi_dock_state(void) return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0); } -static int hp_wmi_wifi_set(void *data, enum rfkill_state state) +static int hp_wmi_set_block(void *data, bool blocked) { - if (state) - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x101); - else - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x100); + unsigned long b = (unsigned long) data; + int query = BIT(b + 8) | ((!!blocked) << b); + + return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); } -static int hp_wmi_bluetooth_set(void *data, enum rfkill_state state) -{ - if (state) - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x202); - else - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x200); -} +static const struct rfkill_ops hp_wmi_rfkill_ops = { + .set_block = hp_wmi_set_block, +}; -static int hp_wmi_wwan_set(void *data, enum rfkill_state state) -{ - if (state) - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x404); - else - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x400); -} - -static int hp_wmi_wifi_state(void) +static bool hp_wmi_wifi_state(void) { int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); if (wireless & 0x100) - return RFKILL_STATE_UNBLOCKED; + return false; else - return RFKILL_STATE_SOFT_BLOCKED; + return true; } -static int hp_wmi_bluetooth_state(void) +static bool hp_wmi_bluetooth_state(void) { int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); if (wireless & 0x10000) - return RFKILL_STATE_UNBLOCKED; + return false; else - return RFKILL_STATE_SOFT_BLOCKED; + return true; } -static int hp_wmi_wwan_state(void) +static bool hp_wmi_wwan_state(void) { int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); if (wireless & 0x1000000) - return RFKILL_STATE_UNBLOCKED; + return false; else - return RFKILL_STATE_SOFT_BLOCKED; + return true; } static ssize_t show_display(struct device *dev, struct device_attribute *attr, @@ -347,14 +335,14 @@ static void hp_wmi_notify(u32 value, void *context) } } else if (eventcode == 0x5) { if (wifi_rfkill) - rfkill_force_state(wifi_rfkill, - hp_wmi_wifi_state()); + rfkill_set_sw_state(wifi_rfkill, + hp_wmi_wifi_state()); if (bluetooth_rfkill) - rfkill_force_state(bluetooth_rfkill, - hp_wmi_bluetooth_state()); + rfkill_set_sw_state(bluetooth_rfkill, + hp_wmi_bluetooth_state()); if (wwan_rfkill) - rfkill_force_state(wwan_rfkill, - hp_wmi_wwan_state()); + rfkill_set_sw_state(wwan_rfkill, + hp_wmi_wwan_state()); } else printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", eventcode); @@ -430,34 +418,30 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) goto add_sysfs_error; if (wireless & 0x1) { - wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); - wifi_rfkill->name = "hp-wifi"; - wifi_rfkill->state = hp_wmi_wifi_state(); - wifi_rfkill->toggle_radio = hp_wmi_wifi_set; - wifi_rfkill->user_claim_unsupported = 1; + wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, + RFKILL_TYPE_WLAN, + &hp_wmi_rfkill_ops, + (void *) 0); err = rfkill_register(wifi_rfkill); if (err) - goto add_sysfs_error; + goto register_wifi_error; } if (wireless & 0x2) { - bluetooth_rfkill = rfkill_allocate(&device->dev, - RFKILL_TYPE_BLUETOOTH); - bluetooth_rfkill->name = "hp-bluetooth"; - bluetooth_rfkill->state = hp_wmi_bluetooth_state(); - bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set; - bluetooth_rfkill->user_claim_unsupported = 1; + bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, + RFKILL_TYPE_BLUETOOTH, + &hp_wmi_rfkill_ops, + (void *) 1); err = rfkill_register(bluetooth_rfkill); if (err) goto register_bluetooth_error; } if (wireless & 0x4) { - wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); - wwan_rfkill->name = "hp-wwan"; - wwan_rfkill->state = hp_wmi_wwan_state(); - wwan_rfkill->toggle_radio = hp_wmi_wwan_set; - wwan_rfkill->user_claim_unsupported = 1; + wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, + RFKILL_TYPE_WWAN, + &hp_wmi_rfkill_ops, + (void *) 2); err = rfkill_register(wwan_rfkill); if (err) goto register_wwan_err; @@ -465,11 +449,15 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) return 0; register_wwan_err: + rfkill_destroy(wwan_rfkill); if (bluetooth_rfkill) rfkill_unregister(bluetooth_rfkill); register_bluetooth_error: + rfkill_destroy(bluetooth_rfkill); if (wifi_rfkill) rfkill_unregister(wifi_rfkill); +register_wifi_error: + rfkill_destroy(wifi_rfkill); add_sysfs_error: cleanup_sysfs(device); return err; @@ -479,12 +467,18 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) { cleanup_sysfs(device); - if (wifi_rfkill) + if (wifi_rfkill) { rfkill_unregister(wifi_rfkill); - if (bluetooth_rfkill) + rfkill_destroy(wifi_rfkill); + } + if (bluetooth_rfkill) { rfkill_unregister(bluetooth_rfkill); - if (wwan_rfkill) + rfkill_destroy(wifi_rfkill); + } + if (wwan_rfkill) { rfkill_unregister(wwan_rfkill); + rfkill_destroy(wwan_rfkill); + } return 0; } diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 552958545f94..e48d9a4506ff 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -128,11 +128,11 @@ enum sony_nc_rfkill { SONY_BLUETOOTH, SONY_WWAN, SONY_WIMAX, - SONY_RFKILL_MAX, + N_SONY_RFKILL, }; -static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; -static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; +static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; +static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; static void sony_nc_rfkill_update(void); /*********** Input Devices ***********/ @@ -1051,151 +1051,96 @@ static void sony_nc_rfkill_cleanup(void) { int i; - for (i = 0; i < SONY_RFKILL_MAX; i++) { - if (sony_rfkill_devices[i]) + for (i = 0; i < N_SONY_RFKILL; i++) { + if (sony_rfkill_devices[i]) { rfkill_unregister(sony_rfkill_devices[i]); + rfkill_destroy(sony_rfkill_devices[i]); + } } } -static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) -{ - int result; - int argument = sony_rfkill_address[(long) data]; - - sony_call_snc_handle(0x124, 0x200, &result); - if (result & 0x1) { - sony_call_snc_handle(0x124, argument, &result); - if (result & 0xf) - *state = RFKILL_STATE_UNBLOCKED; - else - *state = RFKILL_STATE_SOFT_BLOCKED; - } else { - *state = RFKILL_STATE_HARD_BLOCKED; - } - - return 0; -} - -static int sony_nc_rfkill_set(void *data, enum rfkill_state state) +static int sony_nc_rfkill_set(void *data, bool blocked) { int result; int argument = sony_rfkill_address[(long) data] + 0x100; - if (state == RFKILL_STATE_UNBLOCKED) + if (!blocked) argument |= 0xff0000; return sony_call_snc_handle(0x124, argument, &result); } -static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) +static const struct rfkill_ops sony_rfkill_ops = { + .set_block = sony_nc_rfkill_set, +}; + +static int sony_nc_setup_rfkill(struct acpi_device *device, + enum sony_nc_rfkill nc_type) { int err = 0; - struct rfkill *sony_wifi_rfkill; + struct rfkill *rfk; + enum rfkill_type type; + const char *name; - sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); - if (!sony_wifi_rfkill) - return -1; - sony_wifi_rfkill->name = "sony-wifi"; - sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set; - sony_wifi_rfkill->get_state = sony_nc_rfkill_get; - sony_wifi_rfkill->user_claim_unsupported = 1; - sony_wifi_rfkill->data = (void *)SONY_WIFI; - err = rfkill_register(sony_wifi_rfkill); - if (err) - rfkill_free(sony_wifi_rfkill); - else { - sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill; - sony_nc_rfkill_set(sony_wifi_rfkill->data, - RFKILL_STATE_UNBLOCKED); + switch (nc_type) { + case SONY_WIFI: + type = RFKILL_TYPE_WLAN; + name = "sony-wifi"; + break; + case SONY_BLUETOOTH: + type = RFKILL_TYPE_BLUETOOTH; + name = "sony-bluetooth"; + break; + case SONY_WWAN: + type = RFKILL_TYPE_WWAN; + name = "sony-wwan"; + break; + case SONY_WIMAX: + type = RFKILL_TYPE_WIMAX; + name = "sony-wimax"; + break; + default: + return -EINVAL; } - return err; -} -static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) -{ - int err = 0; - struct rfkill *sony_bluetooth_rfkill; + rfk = rfkill_alloc(name, &device->dev, type, + &sony_rfkill_ops, (void *)nc_type); + if (!rfk) + return -ENOMEM; - sony_bluetooth_rfkill = rfkill_allocate(&device->dev, - RFKILL_TYPE_BLUETOOTH); - if (!sony_bluetooth_rfkill) - return -1; - sony_bluetooth_rfkill->name = "sony-bluetooth"; - sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; - sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; - sony_bluetooth_rfkill->user_claim_unsupported = 1; - sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; - err = rfkill_register(sony_bluetooth_rfkill); - if (err) - rfkill_free(sony_bluetooth_rfkill); - else { - sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; - sony_nc_rfkill_set(sony_bluetooth_rfkill->data, - RFKILL_STATE_UNBLOCKED); - } - return err; -} - -static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) -{ - int err = 0; - struct rfkill *sony_wwan_rfkill; - - sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); - if (!sony_wwan_rfkill) - return -1; - sony_wwan_rfkill->name = "sony-wwan"; - sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set; - sony_wwan_rfkill->get_state = sony_nc_rfkill_get; - sony_wwan_rfkill->user_claim_unsupported = 1; - sony_wwan_rfkill->data = (void *)SONY_WWAN; - err = rfkill_register(sony_wwan_rfkill); - if (err) - rfkill_free(sony_wwan_rfkill); - else { - sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill; - sony_nc_rfkill_set(sony_wwan_rfkill->data, - RFKILL_STATE_UNBLOCKED); - } - return err; -} - -static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) -{ - int err = 0; - struct rfkill *sony_wimax_rfkill; - - sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); - if (!sony_wimax_rfkill) - return -1; - sony_wimax_rfkill->name = "sony-wimax"; - sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set; - sony_wimax_rfkill->get_state = sony_nc_rfkill_get; - sony_wimax_rfkill->user_claim_unsupported = 1; - sony_wimax_rfkill->data = (void *)SONY_WIMAX; - err = rfkill_register(sony_wimax_rfkill); - if (err) - rfkill_free(sony_wimax_rfkill); - else { - sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill; - sony_nc_rfkill_set(sony_wimax_rfkill->data, - RFKILL_STATE_UNBLOCKED); + err = rfkill_register(rfk); + if (err) { + rfkill_destroy(rfk); + return err; } + sony_rfkill_devices[nc_type] = rfk; return err; } static void sony_nc_rfkill_update() { - int i; - enum rfkill_state state; + enum sony_nc_rfkill i; + int result; + bool hwblock; - for (i = 0; i < SONY_RFKILL_MAX; i++) { - if (sony_rfkill_devices[i]) { - sony_rfkill_devices[i]-> - get_state(sony_rfkill_devices[i]->data, - &state); - rfkill_force_state(sony_rfkill_devices[i], state); + sony_call_snc_handle(0x124, 0x200, &result); + hwblock = !(result & 0x1); + + for (i = 0; i < N_SONY_RFKILL; i++) { + int argument = sony_rfkill_address[i]; + + if (!sony_rfkill_devices[i]) + continue; + + if (hwblock) { + if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) + sony_nc_rfkill_set((void *)i, true); + continue; } + + sony_call_snc_handle(0x124, argument, &result); + rfkill_set_states(sony_rfkill_devices[i], + !(result & 0xf), false); } } @@ -1214,13 +1159,13 @@ static int sony_nc_rfkill_setup(struct acpi_device *device) } if (result & 0x1) - sony_nc_setup_wifi_rfkill(device); + sony_nc_setup_rfkill(device, SONY_WIFI); if (result & 0x2) - sony_nc_setup_bluetooth_rfkill(device); + sony_nc_setup_rfkill(device, SONY_BLUETOOTH); if (result & 0x1c) - sony_nc_setup_wwan_rfkill(device); + sony_nc_setup_rfkill(device, SONY_WWAN); if (result & 0x20) - sony_nc_setup_wimax_rfkill(device); + sony_nc_setup_rfkill(device, SONY_WIMAX); return 0; } diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 912be65b6261..86e958539f46 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -166,13 +166,6 @@ enum { #define TPACPI_MAX_ACPI_ARGS 3 -/* rfkill switches */ -enum { - TPACPI_RFK_BLUETOOTH_SW_ID = 0, - TPACPI_RFK_WWAN_SW_ID, - TPACPI_RFK_UWB_SW_ID, -}; - /* printk headers */ #define TPACPI_LOG TPACPI_FILE ": " #define TPACPI_EMERG KERN_EMERG TPACPI_LOG @@ -1005,60 +998,6 @@ static int __init tpacpi_check_std_acpi_brightness_support(void) return 0; } -static int __init tpacpi_new_rfkill(const unsigned int id, - struct rfkill **rfk, - const enum rfkill_type rfktype, - const char *name, - const bool set_default, - int (*toggle_radio)(void *, enum rfkill_state), - int (*get_state)(void *, enum rfkill_state *)) -{ - int res; - enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED; - - res = get_state(NULL, &initial_state); - if (res < 0) { - printk(TPACPI_ERR - "failed to read initial state for %s, error %d; " - "will turn radio off\n", name, res); - } else if (set_default) { - /* try to set the initial state as the default for the rfkill - * type, since we ask the firmware to preserve it across S5 in - * NVRAM */ - if (rfkill_set_default(rfktype, - (initial_state == RFKILL_STATE_UNBLOCKED) ? - RFKILL_STATE_UNBLOCKED : - RFKILL_STATE_SOFT_BLOCKED) == -EPERM) - vdbg_printk(TPACPI_DBG_RFKILL, - "Default state for %s cannot be changed\n", - name); - } - - *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); - if (!*rfk) { - printk(TPACPI_ERR - "failed to allocate memory for rfkill class\n"); - return -ENOMEM; - } - - (*rfk)->name = name; - (*rfk)->get_state = get_state; - (*rfk)->toggle_radio = toggle_radio; - (*rfk)->state = initial_state; - - res = rfkill_register(*rfk); - if (res < 0) { - printk(TPACPI_ERR - "failed to register %s rfkill switch: %d\n", - name, res); - rfkill_free(*rfk); - *rfk = NULL; - return res; - } - - return 0; -} - static void printk_deprecated_attribute(const char * const what, const char * const details) { @@ -1068,12 +1007,339 @@ static void printk_deprecated_attribute(const char * const what, what, details); } +/************************************************************************* + * rfkill and radio control support helpers + */ + +/* + * ThinkPad-ACPI firmware handling model: + * + * WLSW (master wireless switch) is event-driven, and is common to all + * firmware-controlled radios. It cannot be controlled, just monitored, + * as expected. It overrides all radio state in firmware + * + * The kernel, a masked-off hotkey, and WLSW can change the radio state + * (TODO: verify how WLSW interacts with the returned radio state). + * + * The only time there are shadow radio state changes, is when + * masked-off hotkeys are used. + */ + +/* + * Internal driver API for radio state: + * + * int: < 0 = error, otherwise enum tpacpi_rfkill_state + * bool: true means radio blocked (off) + */ +enum tpacpi_rfkill_state { + TPACPI_RFK_RADIO_OFF = 0, + TPACPI_RFK_RADIO_ON +}; + +/* rfkill switches */ +enum tpacpi_rfk_id { + TPACPI_RFK_BLUETOOTH_SW_ID = 0, + TPACPI_RFK_WWAN_SW_ID, + TPACPI_RFK_UWB_SW_ID, + TPACPI_RFK_SW_MAX +}; + +static const char *tpacpi_rfkill_names[] = { + [TPACPI_RFK_BLUETOOTH_SW_ID] = "bluetooth", + [TPACPI_RFK_WWAN_SW_ID] = "wwan", + [TPACPI_RFK_UWB_SW_ID] = "uwb", + [TPACPI_RFK_SW_MAX] = NULL +}; + +/* ThinkPad-ACPI rfkill subdriver */ +struct tpacpi_rfk { + struct rfkill *rfkill; + enum tpacpi_rfk_id id; + const struct tpacpi_rfk_ops *ops; +}; + +struct tpacpi_rfk_ops { + /* firmware interface */ + int (*get_status)(void); + int (*set_status)(const enum tpacpi_rfkill_state); +}; + +static struct tpacpi_rfk *tpacpi_rfkill_switches[TPACPI_RFK_SW_MAX]; + +/* Query FW and update rfkill sw state for a given rfkill switch */ +static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk) +{ + int status; + + if (!tp_rfk) + return -ENODEV; + + status = (tp_rfk->ops->get_status)(); + if (status < 0) + return status; + + rfkill_set_sw_state(tp_rfk->rfkill, + (status == TPACPI_RFK_RADIO_OFF)); + + return status; +} + +/* Query FW and update rfkill sw state for all rfkill switches */ +static void tpacpi_rfk_update_swstate_all(void) +{ + unsigned int i; + + for (i = 0; i < TPACPI_RFK_SW_MAX; i++) + tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]); +} + +/* + * Sync the HW-blocking state of all rfkill switches, + * do notice it causes the rfkill core to schedule uevents + */ +static void tpacpi_rfk_update_hwblock_state(bool blocked) +{ + unsigned int i; + struct tpacpi_rfk *tp_rfk; + + for (i = 0; i < TPACPI_RFK_SW_MAX; i++) { + tp_rfk = tpacpi_rfkill_switches[i]; + if (tp_rfk) { + if (rfkill_set_hw_state(tp_rfk->rfkill, + blocked)) { + /* ignore -- we track sw block */ + } + } + } +} + +/* Call to get the WLSW state from the firmware */ +static int hotkey_get_wlsw(void); + +/* Call to query WLSW state and update all rfkill switches */ +static bool tpacpi_rfk_check_hwblock_state(void) +{ + int res = hotkey_get_wlsw(); + int hw_blocked; + + /* When unknown or unsupported, we have to assume it is unblocked */ + if (res < 0) + return false; + + hw_blocked = (res == TPACPI_RFK_RADIO_OFF); + tpacpi_rfk_update_hwblock_state(hw_blocked); + + return hw_blocked; +} + +static int tpacpi_rfk_hook_set_block(void *data, bool blocked) +{ + struct tpacpi_rfk *tp_rfk = data; + int res; + + dbg_printk(TPACPI_DBG_RFKILL, + "request to change radio state to %s\n", + blocked ? "blocked" : "unblocked"); + + /* try to set radio state */ + res = (tp_rfk->ops->set_status)(blocked ? + TPACPI_RFK_RADIO_OFF : TPACPI_RFK_RADIO_ON); + + /* and update the rfkill core with whatever the FW really did */ + tpacpi_rfk_update_swstate(tp_rfk); + + return (res < 0) ? res : 0; +} + +static const struct rfkill_ops tpacpi_rfk_rfkill_ops = { + .set_block = tpacpi_rfk_hook_set_block, +}; + +static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, + const struct tpacpi_rfk_ops *tp_rfkops, + const enum rfkill_type rfktype, + const char *name, + const bool set_default) +{ + struct tpacpi_rfk *atp_rfk; + int res; + bool initial_sw_state = false; + int initial_sw_status; + + BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); + + atp_rfk = kzalloc(sizeof(struct tpacpi_rfk), GFP_KERNEL); + if (atp_rfk) + atp_rfk->rfkill = rfkill_alloc(name, + &tpacpi_pdev->dev, + rfktype, + &tpacpi_rfk_rfkill_ops, + atp_rfk); + if (!atp_rfk || !atp_rfk->rfkill) { + printk(TPACPI_ERR + "failed to allocate memory for rfkill class\n"); + kfree(atp_rfk); + return -ENOMEM; + } + + atp_rfk->id = id; + atp_rfk->ops = tp_rfkops; + + initial_sw_status = (tp_rfkops->get_status)(); + if (initial_sw_status < 0) { + printk(TPACPI_ERR + "failed to read initial state for %s, error %d\n", + name, initial_sw_status); + } else { + initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF); + if (set_default) { + /* try to keep the initial state, since we ask the + * firmware to preserve it across S5 in NVRAM */ + rfkill_set_sw_state(atp_rfk->rfkill, initial_sw_state); + } + } + rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); + + res = rfkill_register(atp_rfk->rfkill); + if (res < 0) { + printk(TPACPI_ERR + "failed to register %s rfkill switch: %d\n", + name, res); + rfkill_destroy(atp_rfk->rfkill); + kfree(atp_rfk); + return res; + } + + tpacpi_rfkill_switches[id] = atp_rfk; + return 0; +} + +static void tpacpi_destroy_rfkill(const enum tpacpi_rfk_id id) +{ + struct tpacpi_rfk *tp_rfk; + + BUG_ON(id >= TPACPI_RFK_SW_MAX); + + tp_rfk = tpacpi_rfkill_switches[id]; + if (tp_rfk) { + rfkill_unregister(tp_rfk->rfkill); + tpacpi_rfkill_switches[id] = NULL; + kfree(tp_rfk); + } +} + static void printk_deprecated_rfkill_attribute(const char * const what) { printk_deprecated_attribute(what, "Please switch to generic rfkill before year 2010"); } +/* sysfs enable ------------------------------------------------ */ +static ssize_t tpacpi_rfk_sysfs_enable_show(const enum tpacpi_rfk_id id, + struct device_attribute *attr, + char *buf) +{ + int status; + + printk_deprecated_rfkill_attribute(attr->attr.name); + + /* This is in the ABI... */ + if (tpacpi_rfk_check_hwblock_state()) { + status = TPACPI_RFK_RADIO_OFF; + } else { + status = tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]); + if (status < 0) + return status; + } + + return snprintf(buf, PAGE_SIZE, "%d\n", + (status == TPACPI_RFK_RADIO_ON) ? 1 : 0); +} + +static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long t; + int res; + + printk_deprecated_rfkill_attribute(attr->attr.name); + + if (parse_strtoul(buf, 1, &t)) + return -EINVAL; + + tpacpi_disclose_usertask(attr->attr.name, "set to %ld\n", t); + + /* This is in the ABI... */ + if (tpacpi_rfk_check_hwblock_state() && !!t) + return -EPERM; + + res = tpacpi_rfkill_switches[id]->ops->set_status((!!t) ? + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF); + tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]); + + return (res < 0) ? res : count; +} + +/* procfs -------------------------------------------------------------- */ +static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p) +{ + int len = 0; + + if (id >= TPACPI_RFK_SW_MAX) + len += sprintf(p + len, "status:\t\tnot supported\n"); + else { + int status; + + /* This is in the ABI... */ + if (tpacpi_rfk_check_hwblock_state()) { + status = TPACPI_RFK_RADIO_OFF; + } else { + status = tpacpi_rfk_update_swstate( + tpacpi_rfkill_switches[id]); + if (status < 0) + return status; + } + + len += sprintf(p + len, "status:\t\t%s\n", + (status == TPACPI_RFK_RADIO_ON) ? + "enabled" : "disabled"); + len += sprintf(p + len, "commands:\tenable, disable\n"); + } + + return len; +} + +static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) +{ + char *cmd; + int status = -1; + int res = 0; + + if (id >= TPACPI_RFK_SW_MAX) + return -ENODEV; + + while ((cmd = next_cmd(&buf))) { + if (strlencmp(cmd, "enable") == 0) + status = TPACPI_RFK_RADIO_ON; + else if (strlencmp(cmd, "disable") == 0) + status = TPACPI_RFK_RADIO_OFF; + else + return -EINVAL; + } + + if (status != -1) { + tpacpi_disclose_usertask("procfs", "attempt to %s %s\n", + (status == TPACPI_RFK_RADIO_ON) ? + "enable" : "disable", + tpacpi_rfkill_names[id]); + res = (tpacpi_rfkill_switches[id]->ops->set_status)(status); + tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]); + } + + return res; +} + /************************************************************************* * thinkpad-acpi driver attributes */ @@ -1127,8 +1393,6 @@ static DRIVER_ATTR(version, S_IRUGO, #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES -static void tpacpi_send_radiosw_update(void); - /* wlsw_emulstate ------------------------------------------------------ */ static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv, char *buf) @@ -1144,11 +1408,10 @@ static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv, if (parse_strtoul(buf, 1, &t)) return -EINVAL; - if (tpacpi_wlsw_emulstate != t) { - tpacpi_wlsw_emulstate = !!t; - tpacpi_send_radiosw_update(); - } else + if (tpacpi_wlsw_emulstate != !!t) { tpacpi_wlsw_emulstate = !!t; + tpacpi_rfk_update_hwblock_state(!t); /* negative logic */ + } return count; } @@ -1463,17 +1726,23 @@ static struct attribute_set *hotkey_dev_attributes; /* HKEY.MHKG() return bits */ #define TP_HOTKEY_TABLET_MASK (1 << 3) -static int hotkey_get_wlsw(int *status) +static int hotkey_get_wlsw(void) { + int status; + + if (!tp_features.hotkey_wlsw) + return -ENODEV; + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES - if (dbg_wlswemul) { - *status = !!tpacpi_wlsw_emulstate; - return 0; - } + if (dbg_wlswemul) + return (tpacpi_wlsw_emulstate) ? + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; #endif - if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) + + if (!acpi_evalf(hkey_handle, &status, "WLSW", "d")) return -EIO; - return 0; + + return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; } static int hotkey_get_tablet_mode(int *status) @@ -2107,12 +2376,16 @@ static ssize_t hotkey_radio_sw_show(struct device *dev, struct device_attribute *attr, char *buf) { - int res, s; - res = hotkey_get_wlsw(&s); + int res; + res = hotkey_get_wlsw(); if (res < 0) return res; - return snprintf(buf, PAGE_SIZE, "%d\n", !!s); + /* Opportunistic update */ + tpacpi_rfk_update_hwblock_state((res == TPACPI_RFK_RADIO_OFF)); + + return snprintf(buf, PAGE_SIZE, "%d\n", + (res == TPACPI_RFK_RADIO_OFF) ? 0 : 1); } static struct device_attribute dev_attr_hotkey_radio_sw = @@ -2223,30 +2496,52 @@ static struct attribute *hotkey_mask_attributes[] __initdata = { &dev_attr_hotkey_wakeup_hotunplug_complete.attr, }; -static void bluetooth_update_rfk(void); -static void wan_update_rfk(void); -static void uwb_update_rfk(void); +/* + * Sync both the hw and sw blocking state of all switches + */ static void tpacpi_send_radiosw_update(void) { int wlsw; - /* Sync these BEFORE sending any rfkill events */ - if (tp_features.bluetooth) - bluetooth_update_rfk(); - if (tp_features.wan) - wan_update_rfk(); - if (tp_features.uwb) - uwb_update_rfk(); + /* + * We must sync all rfkill controllers *before* issuing any + * rfkill input events, or we will race the rfkill core input + * handler. + * + * tpacpi_inputdev_send_mutex works as a syncronization point + * for the above. + * + * We optimize to avoid numerous calls to hotkey_get_wlsw. + */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { + wlsw = hotkey_get_wlsw(); + + /* Sync hw blocking state first if it is hw-blocked */ + if (wlsw == TPACPI_RFK_RADIO_OFF) + tpacpi_rfk_update_hwblock_state(true); + + /* Sync sw blocking state */ + tpacpi_rfk_update_swstate_all(); + + /* Sync hw blocking state last if it is hw-unblocked */ + if (wlsw == TPACPI_RFK_RADIO_ON) + tpacpi_rfk_update_hwblock_state(false); + + /* Issue rfkill input event for WLSW switch */ + if (!(wlsw < 0)) { mutex_lock(&tpacpi_inputdev_send_mutex); input_report_switch(tpacpi_inputdev, - SW_RFKILL_ALL, !!wlsw); + SW_RFKILL_ALL, (wlsw > 0)); input_sync(tpacpi_inputdev); mutex_unlock(&tpacpi_inputdev_send_mutex); } + + /* + * this can be unconditional, as we will poll state again + * if userspace uses the notify to read data + */ hotkey_radio_sw_notify_change(); } @@ -3056,8 +3351,6 @@ enum { #define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" -static struct rfkill *tpacpi_bluetooth_rfkill; - static void bluetooth_suspend(pm_message_t state) { /* Try to make sure radio will resume powered off */ @@ -3067,83 +3360,47 @@ static void bluetooth_suspend(pm_message_t state) "bluetooth power down on resume request failed\n"); } -static int bluetooth_get_radiosw(void) +static int bluetooth_get_status(void) { int status; - if (!tp_features.bluetooth) - return -ENODEV; - - /* WLSW overrides bluetooth in firmware/hardware, reflect that */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) - return RFKILL_STATE_HARD_BLOCKED; - #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_bluetoothemul) return (tpacpi_bluetooth_emulstate) ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; #endif if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) return -EIO; return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; } -static void bluetooth_update_rfk(void) +static int bluetooth_set_status(enum tpacpi_rfkill_state state) { int status; - if (!tpacpi_bluetooth_rfkill) - return; - - status = bluetooth_get_radiosw(); - if (status < 0) - return; - rfkill_force_state(tpacpi_bluetooth_rfkill, status); - vdbg_printk(TPACPI_DBG_RFKILL, - "forced rfkill state to %d\n", - status); -} - -static int bluetooth_set_radiosw(int radio_on, int update_rfk) -{ - int status; - - if (!tp_features.bluetooth) - return -ENODEV; - - /* WLSW overrides bluetooth in firmware/hardware, but there is no - * reason to risk weird behaviour. */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status - && radio_on) - return -EPERM; - - vdbg_printk(TPACPI_DBG_RFKILL, - "will %s bluetooth\n", radio_on ? "enable" : "disable"); + "will attempt to %s bluetooth\n", + (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable"); #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_bluetoothemul) { - tpacpi_bluetooth_emulstate = !!radio_on; - if (update_rfk) - bluetooth_update_rfk(); + tpacpi_bluetooth_emulstate = (state == TPACPI_RFK_RADIO_ON); return 0; } #endif /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ - if (radio_on) + if (state == TPACPI_RFK_RADIO_ON) status = TP_ACPI_BLUETOOTH_RADIOSSW; else status = 0; + if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) return -EIO; - if (update_rfk) - bluetooth_update_rfk(); - return 0; } @@ -3152,35 +3409,16 @@ static ssize_t bluetooth_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { - int status; - - printk_deprecated_rfkill_attribute("bluetooth_enable"); - - status = bluetooth_get_radiosw(); - if (status < 0) - return status; - - return snprintf(buf, PAGE_SIZE, "%d\n", - (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0); + return tpacpi_rfk_sysfs_enable_show(TPACPI_RFK_BLUETOOTH_SW_ID, + attr, buf); } static ssize_t bluetooth_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - unsigned long t; - int res; - - printk_deprecated_rfkill_attribute("bluetooth_enable"); - - if (parse_strtoul(buf, 1, &t)) - return -EINVAL; - - tpacpi_disclose_usertask("bluetooth_enable", "set to %ld\n", t); - - res = bluetooth_set_radiosw(t, 1); - - return (res) ? res : count; + return tpacpi_rfk_sysfs_enable_store(TPACPI_RFK_BLUETOOTH_SW_ID, + attr, buf, count); } static struct device_attribute dev_attr_bluetooth_enable = @@ -3198,23 +3436,10 @@ static const struct attribute_group bluetooth_attr_group = { .attrs = bluetooth_attributes, }; -static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state) -{ - int bts = bluetooth_get_radiosw(); - - if (bts < 0) - return bts; - - *state = bts; - return 0; -} - -static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) -{ - dbg_printk(TPACPI_DBG_RFKILL, - "request to change radio state to %d\n", state); - return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); -} +static const struct tpacpi_rfk_ops bluetooth_tprfk_ops = { + .get_status = bluetooth_get_status, + .set_status = bluetooth_set_status, +}; static void bluetooth_shutdown(void) { @@ -3230,13 +3455,12 @@ static void bluetooth_shutdown(void) static void bluetooth_exit(void) { - bluetooth_shutdown(); - - if (tpacpi_bluetooth_rfkill) - rfkill_unregister(tpacpi_bluetooth_rfkill); - sysfs_remove_group(&tpacpi_pdev->dev.kobj, &bluetooth_attr_group); + + tpacpi_destroy_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID); + + bluetooth_shutdown(); } static int __init bluetooth_init(struct ibm_init_struct *iibm) @@ -3277,20 +3501,18 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) if (!tp_features.bluetooth) return 1; - res = sysfs_create_group(&tpacpi_pdev->dev.kobj, - &bluetooth_attr_group); + res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, + &bluetooth_tprfk_ops, + RFKILL_TYPE_BLUETOOTH, + TPACPI_RFK_BLUETOOTH_SW_NAME, + true); if (res) return res; - res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, - &tpacpi_bluetooth_rfkill, - RFKILL_TYPE_BLUETOOTH, - TPACPI_RFK_BLUETOOTH_SW_NAME, - true, - tpacpi_bluetooth_rfk_set, - tpacpi_bluetooth_rfk_get); + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, + &bluetooth_attr_group); if (res) { - bluetooth_exit(); + tpacpi_destroy_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID); return res; } @@ -3300,46 +3522,12 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) /* procfs -------------------------------------------------------------- */ static int bluetooth_read(char *p) { - int len = 0; - int status = bluetooth_get_radiosw(); - - if (!tp_features.bluetooth) - len += sprintf(p + len, "status:\t\tnot supported\n"); - else { - len += sprintf(p + len, "status:\t\t%s\n", - (status == RFKILL_STATE_UNBLOCKED) ? - "enabled" : "disabled"); - len += sprintf(p + len, "commands:\tenable, disable\n"); - } - - return len; + return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p); } static int bluetooth_write(char *buf) { - char *cmd; - int state = -1; - - if (!tp_features.bluetooth) - return -ENODEV; - - while ((cmd = next_cmd(&buf))) { - if (strlencmp(cmd, "enable") == 0) { - state = 1; - } else if (strlencmp(cmd, "disable") == 0) { - state = 0; - } else - return -EINVAL; - } - - if (state != -1) { - tpacpi_disclose_usertask("procfs bluetooth", - "attempt to %s\n", - state ? "enable" : "disable"); - bluetooth_set_radiosw(state, 1); - } - - return 0; + return tpacpi_rfk_procfs_write(TPACPI_RFK_BLUETOOTH_SW_ID, buf); } static struct ibm_struct bluetooth_driver_data = { @@ -3365,8 +3553,6 @@ enum { #define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" -static struct rfkill *tpacpi_wan_rfkill; - static void wan_suspend(pm_message_t state) { /* Try to make sure radio will resume powered off */ @@ -3376,83 +3562,47 @@ static void wan_suspend(pm_message_t state) "WWAN power down on resume request failed\n"); } -static int wan_get_radiosw(void) +static int wan_get_status(void) { int status; - if (!tp_features.wan) - return -ENODEV; - - /* WLSW overrides WWAN in firmware/hardware, reflect that */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) - return RFKILL_STATE_HARD_BLOCKED; - #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_wwanemul) return (tpacpi_wwan_emulstate) ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; #endif if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) return -EIO; return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; } -static void wan_update_rfk(void) +static int wan_set_status(enum tpacpi_rfkill_state state) { int status; - if (!tpacpi_wan_rfkill) - return; - - status = wan_get_radiosw(); - if (status < 0) - return; - rfkill_force_state(tpacpi_wan_rfkill, status); - vdbg_printk(TPACPI_DBG_RFKILL, - "forced rfkill state to %d\n", - status); -} - -static int wan_set_radiosw(int radio_on, int update_rfk) -{ - int status; - - if (!tp_features.wan) - return -ENODEV; - - /* WLSW overrides bluetooth in firmware/hardware, but there is no - * reason to risk weird behaviour. */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status - && radio_on) - return -EPERM; - - vdbg_printk(TPACPI_DBG_RFKILL, - "will %s WWAN\n", radio_on ? "enable" : "disable"); + "will attempt to %s wwan\n", + (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable"); #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_wwanemul) { - tpacpi_wwan_emulstate = !!radio_on; - if (update_rfk) - wan_update_rfk(); + tpacpi_wwan_emulstate = (state == TPACPI_RFK_RADIO_ON); return 0; } #endif /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ - if (radio_on) + if (state == TPACPI_RFK_RADIO_ON) status = TP_ACPI_WANCARD_RADIOSSW; else status = 0; + if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) return -EIO; - if (update_rfk) - wan_update_rfk(); - return 0; } @@ -3461,35 +3611,16 @@ static ssize_t wan_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { - int status; - - printk_deprecated_rfkill_attribute("wwan_enable"); - - status = wan_get_radiosw(); - if (status < 0) - return status; - - return snprintf(buf, PAGE_SIZE, "%d\n", - (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0); + return tpacpi_rfk_sysfs_enable_show(TPACPI_RFK_WWAN_SW_ID, + attr, buf); } static ssize_t wan_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - unsigned long t; - int res; - - printk_deprecated_rfkill_attribute("wwan_enable"); - - if (parse_strtoul(buf, 1, &t)) - return -EINVAL; - - tpacpi_disclose_usertask("wwan_enable", "set to %ld\n", t); - - res = wan_set_radiosw(t, 1); - - return (res) ? res : count; + return tpacpi_rfk_sysfs_enable_store(TPACPI_RFK_WWAN_SW_ID, + attr, buf, count); } static struct device_attribute dev_attr_wan_enable = @@ -3507,23 +3638,10 @@ static const struct attribute_group wan_attr_group = { .attrs = wan_attributes, }; -static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state) -{ - int wans = wan_get_radiosw(); - - if (wans < 0) - return wans; - - *state = wans; - return 0; -} - -static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) -{ - dbg_printk(TPACPI_DBG_RFKILL, - "request to change radio state to %d\n", state); - return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); -} +static const struct tpacpi_rfk_ops wan_tprfk_ops = { + .get_status = wan_get_status, + .set_status = wan_set_status, +}; static void wan_shutdown(void) { @@ -3539,13 +3657,12 @@ static void wan_shutdown(void) static void wan_exit(void) { - wan_shutdown(); - - if (tpacpi_wan_rfkill) - rfkill_unregister(tpacpi_wan_rfkill); - sysfs_remove_group(&tpacpi_pdev->dev.kobj, &wan_attr_group); + + tpacpi_destroy_rfkill(TPACPI_RFK_WWAN_SW_ID); + + wan_shutdown(); } static int __init wan_init(struct ibm_init_struct *iibm) @@ -3584,20 +3701,19 @@ static int __init wan_init(struct ibm_init_struct *iibm) if (!tp_features.wan) return 1; - res = sysfs_create_group(&tpacpi_pdev->dev.kobj, - &wan_attr_group); + res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, + &wan_tprfk_ops, + RFKILL_TYPE_WWAN, + TPACPI_RFK_WWAN_SW_NAME, + true); if (res) return res; - res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, - &tpacpi_wan_rfkill, - RFKILL_TYPE_WWAN, - TPACPI_RFK_WWAN_SW_NAME, - true, - tpacpi_wan_rfk_set, - tpacpi_wan_rfk_get); + res = sysfs_create_group(&tpacpi_pdev->dev.kobj, + &wan_attr_group); + if (res) { - wan_exit(); + tpacpi_destroy_rfkill(TPACPI_RFK_WWAN_SW_ID); return res; } @@ -3607,48 +3723,12 @@ static int __init wan_init(struct ibm_init_struct *iibm) /* procfs -------------------------------------------------------------- */ static int wan_read(char *p) { - int len = 0; - int status = wan_get_radiosw(); - - tpacpi_disclose_usertask("procfs wan", "read"); - - if (!tp_features.wan) - len += sprintf(p + len, "status:\t\tnot supported\n"); - else { - len += sprintf(p + len, "status:\t\t%s\n", - (status == RFKILL_STATE_UNBLOCKED) ? - "enabled" : "disabled"); - len += sprintf(p + len, "commands:\tenable, disable\n"); - } - - return len; + return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p); } static int wan_write(char *buf) { - char *cmd; - int state = -1; - - if (!tp_features.wan) - return -ENODEV; - - while ((cmd = next_cmd(&buf))) { - if (strlencmp(cmd, "enable") == 0) { - state = 1; - } else if (strlencmp(cmd, "disable") == 0) { - state = 0; - } else - return -EINVAL; - } - - if (state != -1) { - tpacpi_disclose_usertask("procfs wan", - "attempt to %s\n", - state ? "enable" : "disable"); - wan_set_radiosw(state, 1); - } - - return 0; + return tpacpi_rfk_procfs_write(TPACPI_RFK_WWAN_SW_ID, buf); } static struct ibm_struct wan_driver_data = { @@ -3672,108 +3752,59 @@ enum { #define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw" -static struct rfkill *tpacpi_uwb_rfkill; - -static int uwb_get_radiosw(void) +static int uwb_get_status(void) { int status; - if (!tp_features.uwb) - return -ENODEV; - - /* WLSW overrides UWB in firmware/hardware, reflect that */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) - return RFKILL_STATE_HARD_BLOCKED; - #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_uwbemul) return (tpacpi_uwb_emulstate) ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; #endif if (!acpi_evalf(hkey_handle, &status, "GUWB", "d")) return -EIO; return ((status & TP_ACPI_UWB_RADIOSSW) != 0) ? - RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; } -static void uwb_update_rfk(void) +static int uwb_set_status(enum tpacpi_rfkill_state state) { int status; - if (!tpacpi_uwb_rfkill) - return; - - status = uwb_get_radiosw(); - if (status < 0) - return; - rfkill_force_state(tpacpi_uwb_rfkill, status); - vdbg_printk(TPACPI_DBG_RFKILL, - "forced rfkill state to %d\n", - status); -} - -static int uwb_set_radiosw(int radio_on, int update_rfk) -{ - int status; - - if (!tp_features.uwb) - return -ENODEV; - - /* WLSW overrides UWB in firmware/hardware, but there is no - * reason to risk weird behaviour. */ - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status - && radio_on) - return -EPERM; - - vdbg_printk(TPACPI_DBG_RFKILL, - "will %s UWB\n", radio_on ? "enable" : "disable"); + "will attempt to %s UWB\n", + (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable"); #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_uwbemul) { - tpacpi_uwb_emulstate = !!radio_on; - if (update_rfk) - uwb_update_rfk(); + tpacpi_uwb_emulstate = (state == TPACPI_RFK_RADIO_ON); return 0; } #endif - status = (radio_on) ? TP_ACPI_UWB_RADIOSSW : 0; + if (state == TPACPI_RFK_RADIO_ON) + status = TP_ACPI_UWB_RADIOSSW; + else + status = 0; + if (!acpi_evalf(hkey_handle, NULL, "SUWB", "vd", status)) return -EIO; - if (update_rfk) - uwb_update_rfk(); - return 0; } /* --------------------------------------------------------------------- */ -static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state) -{ - int uwbs = uwb_get_radiosw(); - - if (uwbs < 0) - return uwbs; - - *state = uwbs; - return 0; -} - -static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state) -{ - dbg_printk(TPACPI_DBG_RFKILL, - "request to change radio state to %d\n", state); - return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); -} +static const struct tpacpi_rfk_ops uwb_tprfk_ops = { + .get_status = uwb_get_status, + .set_status = uwb_set_status, +}; static void uwb_exit(void) { - if (tpacpi_uwb_rfkill) - rfkill_unregister(tpacpi_uwb_rfkill); + tpacpi_destroy_rfkill(TPACPI_RFK_UWB_SW_ID); } static int __init uwb_init(struct ibm_init_struct *iibm) @@ -3813,13 +3844,10 @@ static int __init uwb_init(struct ibm_init_struct *iibm) return 1; res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID, - &tpacpi_uwb_rfkill, + &uwb_tprfk_ops, RFKILL_TYPE_UWB, TPACPI_RFK_UWB_SW_NAME, - false, - tpacpi_uwb_rfk_set, - tpacpi_uwb_rfk_get); - + false); return res; } diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 9f187265db8e..81d31ea507d1 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -45,7 +45,6 @@ #include #include #include -#include #include @@ -250,21 +249,15 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result) struct toshiba_acpi_dev { struct platform_device *p_dev; - struct rfkill *rfk_dev; - struct input_polled_dev *poll_dev; + struct rfkill *bt_rfk; const char *bt_name; - const char *rfk_name; - - bool last_rfk_state; struct mutex mutex; }; static struct toshiba_acpi_dev toshiba_acpi = { .bt_name = "Toshiba Bluetooth", - .rfk_name = "Toshiba RFKill Switch", - .last_rfk_state = false, }; /* Bluetooth rfkill handlers */ @@ -283,21 +276,6 @@ static u32 hci_get_bt_present(bool *present) return hci_result; } -static u32 hci_get_bt_on(bool *on) -{ - u32 hci_result; - u32 value, value2; - - value = 0; - value2 = 0x0001; - hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); - if (hci_result == HCI_SUCCESS) - *on = (value & HCI_WIRELESS_BT_POWER) && - (value & HCI_WIRELESS_BT_ATTACH); - - return hci_result; -} - static u32 hci_get_radio_state(bool *radio_state) { u32 hci_result; @@ -311,70 +289,67 @@ static u32 hci_get_radio_state(bool *radio_state) return hci_result; } -static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) +static int bt_rfkill_set_block(void *data, bool blocked) { + struct toshiba_acpi_dev *dev = data; u32 result1, result2; u32 value; + int err; bool radio_state; - struct toshiba_acpi_dev *dev = data; - value = (state == RFKILL_STATE_UNBLOCKED); - - if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) - return -EFAULT; - - switch (state) { - case RFKILL_STATE_UNBLOCKED: - if (!radio_state) - return -EPERM; - break; - case RFKILL_STATE_SOFT_BLOCKED: - break; - default: - return -EINVAL; - } + value = (blocked == false); mutex_lock(&dev->mutex); + if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) { + err = -EBUSY; + goto out; + } + + if (!radio_state) { + err = 0; + goto out; + } + hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); - mutex_unlock(&dev->mutex); if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) - return -EFAULT; - - return 0; + err = -EBUSY; + else + err = 0; + out: + mutex_unlock(&dev->mutex); + return err; } -static void bt_poll_rfkill(struct input_polled_dev *poll_dev) +static void bt_rfkill_poll(struct rfkill *rfkill, void *data) { - bool state_changed; bool new_rfk_state; bool value; u32 hci_result; - struct toshiba_acpi_dev *dev = poll_dev->private; + struct toshiba_acpi_dev *dev = data; + + mutex_lock(&dev->mutex); hci_result = hci_get_radio_state(&value); - if (hci_result != HCI_SUCCESS) - return; /* Can't do anything useful */ + if (hci_result != HCI_SUCCESS) { + /* Can't do anything useful */ + mutex_unlock(&dev->mutex); + } new_rfk_state = value; - mutex_lock(&dev->mutex); - state_changed = new_rfk_state != dev->last_rfk_state; - dev->last_rfk_state = new_rfk_state; mutex_unlock(&dev->mutex); - if (unlikely(state_changed)) { - rfkill_force_state(dev->rfk_dev, - new_rfk_state ? - RFKILL_STATE_SOFT_BLOCKED : - RFKILL_STATE_HARD_BLOCKED); - input_report_switch(poll_dev->input, SW_RFKILL_ALL, - new_rfk_state); - input_sync(poll_dev->input); - } + if (rfkill_set_hw_state(rfkill, !new_rfk_state)) + bt_rfkill_set_block(data, true); } +static const struct rfkill_ops toshiba_rfk_ops = { + .set_block = bt_rfkill_set_block, + .poll = bt_rfkill_poll, +}; + static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; static struct backlight_device *toshiba_backlight_device; static int force_fan; @@ -702,14 +677,11 @@ static struct backlight_ops toshiba_backlight_data = { static void toshiba_acpi_exit(void) { - if (toshiba_acpi.poll_dev) { - input_unregister_polled_device(toshiba_acpi.poll_dev); - input_free_polled_device(toshiba_acpi.poll_dev); + if (toshiba_acpi.bt_rfk) { + rfkill_unregister(toshiba_acpi.bt_rfk); + rfkill_destroy(toshiba_acpi.bt_rfk); } - if (toshiba_acpi.rfk_dev) - rfkill_unregister(toshiba_acpi.rfk_dev); - if (toshiba_backlight_device) backlight_device_unregister(toshiba_backlight_device); @@ -728,8 +700,6 @@ static int __init toshiba_acpi_init(void) acpi_status status = AE_OK; u32 hci_result; bool bt_present; - bool bt_on; - bool radio_on; int ret = 0; if (acpi_disabled) @@ -793,61 +763,21 @@ static int __init toshiba_acpi_init(void) /* Register rfkill switch for Bluetooth */ if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { - toshiba_acpi.rfk_dev = rfkill_allocate(&toshiba_acpi.p_dev->dev, - RFKILL_TYPE_BLUETOOTH); - if (!toshiba_acpi.rfk_dev) { + toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name, + &toshiba_acpi.p_dev->dev, + RFKILL_TYPE_BLUETOOTH, + &toshiba_rfk_ops, + &toshiba_acpi); + if (!toshiba_acpi.bt_rfk) { printk(MY_ERR "unable to allocate rfkill device\n"); toshiba_acpi_exit(); return -ENOMEM; } - toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name; - toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio; - toshiba_acpi.rfk_dev->user_claim_unsupported = 1; - toshiba_acpi.rfk_dev->data = &toshiba_acpi; - - if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) { - toshiba_acpi.rfk_dev->state = RFKILL_STATE_UNBLOCKED; - } else if (hci_get_radio_state(&radio_on) == HCI_SUCCESS && - radio_on) { - toshiba_acpi.rfk_dev->state = RFKILL_STATE_SOFT_BLOCKED; - } else { - toshiba_acpi.rfk_dev->state = RFKILL_STATE_HARD_BLOCKED; - } - - ret = rfkill_register(toshiba_acpi.rfk_dev); + ret = rfkill_register(toshiba_acpi.bt_rfk); if (ret) { printk(MY_ERR "unable to register rfkill device\n"); - toshiba_acpi_exit(); - return -ENOMEM; - } - - /* Register input device for kill switch */ - toshiba_acpi.poll_dev = input_allocate_polled_device(); - if (!toshiba_acpi.poll_dev) { - printk(MY_ERR - "unable to allocate kill-switch input device\n"); - toshiba_acpi_exit(); - return -ENOMEM; - } - toshiba_acpi.poll_dev->private = &toshiba_acpi; - toshiba_acpi.poll_dev->poll = bt_poll_rfkill; - toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ - - toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; - toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; - /* Toshiba USB ID */ - toshiba_acpi.poll_dev->input->id.vendor = 0x0930; - set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); - set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); - input_report_switch(toshiba_acpi.poll_dev->input, - SW_RFKILL_ALL, TRUE); - input_sync(toshiba_acpi.poll_dev->input); - - ret = input_register_polled_device(toshiba_acpi.poll_dev); - if (ret) { - printk(MY_ERR - "unable to register kill-switch input device\n"); + rfkill_destroy(toshiba_acpi.bt_rfk); toshiba_acpi_exit(); return ret; } diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 30a43cc79e76..7b6f46ddf3c3 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -338,12 +338,6 @@ claw_tx(struct sk_buff *skb, struct net_device *dev) CLAW_DBF_TEXT(4, trace, "claw_tx"); p_ch=&privptr->channel[WRITE]; - if (skb == NULL) { - privptr->stats.tx_dropped++; - privptr->stats.tx_errors++; - CLAW_DBF_TEXT_(2, trace, "clawtx%d", -EIO); - return -EIO; - } spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags); rc=claw_hw_tx( skb, dev, 1 ); spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags); diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 77f4033a0f4f..54c4649a493b 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1677,10 +1677,8 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev) BUG_ON(priv == NULL); CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, - "removing device %s, r/w = %s/%s, proto : %d", - priv->channel[READ]->netdev->name, - priv->channel[READ]->id, priv->channel[WRITE]->id, - priv->protocol); + "removing device %p, proto : %d", + cgdev, priv->protocol); if (cgdev->state == CCWGROUP_ONLINE) ctcm_shutdown_device(cgdev); diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index be716e45f7ac..aec9e5d3cf4b 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1315,9 +1315,9 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } dev->trans_start = jiffies; - rc = netiucv_transmit_skb(privptr->conn, skb) != 0; + rc = netiucv_transmit_skb(privptr->conn, skb); netiucv_clear_busy(dev); - return rc; + return rc ? NETDEV_TX_BUSY : NETDEV_TX_OK; } /** diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c827d69b5a91..74c49d9a8dba 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -952,6 +952,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, buf->buffer->element[i].addr = NULL; buf->buffer->element[i].flags = 0; } + buf->buffer->element[15].flags = 0; buf->next_element_to_fill = 0; atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); } @@ -1140,6 +1141,8 @@ static int qeth_setup_card(struct qeth_card *card) card->ipato.enabled = 0; card->ipato.invert4 = 0; card->ipato.invert6 = 0; + if (card->info.type == QETH_CARD_TYPE_IQD) + card->options.checksum_type = NO_CHECKSUMMING; /* init QDIO stuff */ qeth_init_qdio_info(card); return 0; @@ -2934,8 +2937,8 @@ int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) if (card->info.type == QETH_CARD_TYPE_OSN) return cast_type; - if (skb->dst && skb->dst->neighbour) { - cast_type = skb->dst->neighbour->type; + if (skb_dst(skb) && skb_dst(skb)->neighbour) { + cast_type = skb_dst(skb)->neighbour->type; if ((cast_type == RTN_BROADCAST) || (cast_type == RTN_MULTICAST) || (cast_type == RTN_ANYCAST)) diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index 06f4de1f0507..ec24901c802c 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/drivers/s390/net/qeth_core_mpc.c @@ -181,6 +181,8 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"}, {IPA_RC_L2_DUP_LAYER3_MAC, "Duplicate with layer 3 MAC"}, {IPA_RC_L2_GMAC_NOT_FOUND, "GMAC not found"}, + {IPA_RC_L2_MAC_NOT_AUTH_BY_HYP, "L2 mac not authorized by hypervisor"}, + {IPA_RC_L2_MAC_NOT_AUTH_BY_ADP, "L2 mac not authorized by adapter"}, {IPA_RC_L2_MAC_NOT_FOUND, "L2 mac address not found"}, {IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"}, {IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"}, diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 18548822e37c..eecb2ee62e85 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -168,6 +168,8 @@ enum qeth_ipa_return_codes { IPA_RC_L2_ADDR_TABLE_FULL = 0x2006, IPA_RC_L2_DUP_LAYER3_MAC = 0x200a, IPA_RC_L2_GMAC_NOT_FOUND = 0x200b, + IPA_RC_L2_MAC_NOT_AUTH_BY_HYP = 0x200c, + IPA_RC_L2_MAC_NOT_AUTH_BY_ADP = 0x200d, IPA_RC_L2_MAC_NOT_FOUND = 0x2010, IPA_RC_L2_INVALID_VLAN_ID = 0x2015, IPA_RC_L2_DUP_VLAN_ID = 0x2016, diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 172031baedc1..ecd3d06c0d5c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "qeth_core.h" @@ -130,7 +131,7 @@ static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) data; mac = &cmd->data.setdelmac.mac[0]; /* MAC already registered, needed in couple/uncouple case */ - if (cmd->hdr.return_code == 0x2005) { + if (cmd->hdr.return_code == IPA_RC_L2_DUP_MAC) { QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s \n", mac, QETH_CARD_IFNAME(card)); cmd->hdr.return_code = 0; @@ -502,6 +503,30 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, if (cmd->hdr.return_code) { QETH_DBF_TEXT_(TRACE, 2, "L2er%x", cmd->hdr.return_code); card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; + switch (cmd->hdr.return_code) { + case IPA_RC_L2_DUP_MAC: + case IPA_RC_L2_DUP_LAYER3_MAC: + dev_warn(&card->gdev->dev, + "MAC address " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + "already exists\n", + card->dev->dev_addr[0], card->dev->dev_addr[1], + card->dev->dev_addr[2], card->dev->dev_addr[3], + card->dev->dev_addr[4], card->dev->dev_addr[5]); + break; + case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: + case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: + dev_warn(&card->gdev->dev, + "MAC address " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + "is not authorized\n", + card->dev->dev_addr[0], card->dev->dev_addr[1], + card->dev->dev_addr[2], card->dev->dev_addr[3], + card->dev->dev_addr[4], card->dev->dev_addr[5]); + break; + default: + break; + } cmd->hdr.return_code = -EIO; } else { card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; @@ -616,6 +641,7 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; struct dev_addr_list *dm; + struct netdev_hw_addr *ha; if (card->info.type == QETH_CARD_TYPE_OSN) return ; @@ -629,8 +655,8 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) for (dm = dev->mc_list; dm; dm = dm->next) qeth_l2_add_mc(card, dm->da_addr, 0); - for (dm = dev->uc_list; dm; dm = dm->next) - qeth_l2_add_mc(card, dm->da_addr, 1); + list_for_each_entry(ha, &dev->uc_list, list) + qeth_l2_add_mc(card, ha->addr, 1); spin_unlock_bh(&card->mclock); if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) @@ -839,6 +865,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); + qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (cgdev->state == CCWGROUP_ONLINE) { @@ -974,8 +1001,9 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) dev_warn(&card->gdev->dev, "The LAN is offline\n"); card->lan_online = 0; + return 0; } - return rc; + goto out_remove; } else card->lan_online = 1; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 0ba3817cb6a7..6f2386e9d6e2 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1920,16 +1920,22 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); } - skb->ip_summed = card->options.checksum_type; - if (card->options.checksum_type == HW_CHECKSUMMING) { + switch (card->options.checksum_type) { + case SW_CHECKSUMMING: + skb->ip_summed = CHECKSUM_NONE; + break; + case NO_CHECKSUMMING: + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + case HW_CHECKSUMMING: if ((hdr->hdr.l3.ext_flags & - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) == - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) + (QETH_HDR_EXT_CSUM_HDR_REQ | + QETH_HDR_EXT_CSUM_TRANSP_REQ)) == + (QETH_HDR_EXT_CSUM_HDR_REQ | + QETH_HDR_EXT_CSUM_TRANSP_REQ)) skb->ip_summed = CHECKSUM_UNNECESSARY; else - skb->ip_summed = SW_CHECKSUMMING; + skb->ip_summed = CHECKSUM_NONE; } return vlan_id; @@ -2543,9 +2549,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, /* IPv4 */ hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type); memset(hdr->hdr.l3.dest_addr, 0, 12); - if ((skb->dst) && (skb->dst->neighbour)) { + if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) { *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = - *((u32 *) skb->dst->neighbour->primary_key); + *((u32 *) skb_dst(skb)->neighbour->primary_key); } else { /* fill in destination address used in ip header */ *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = @@ -2556,9 +2562,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type); if (card->info.type == QETH_CARD_TYPE_IQD) hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU; - if ((skb->dst) && (skb->dst->neighbour)) { + if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) { memcpy(hdr->hdr.l3.dest_addr, - skb->dst->neighbour->primary_key, 16); + skb_dst(skb)->neighbour->primary_key, 16); } else { /* fill in destination address used in ip header */ memcpy(hdr->hdr.l3.dest_addr, @@ -3006,6 +3012,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; + card->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; SET_NETDEV_DEV(card->dev, &card->gdev->dev); return register_netdev(card->dev); @@ -3070,6 +3077,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); + qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (cgdev->state == CCWGROUP_ONLINE) { @@ -3141,8 +3149,9 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) dev_warn(&card->gdev->dev, "The LAN is offline\n"); card->lan_online = 0; + return 0; } - return rc; + goto out_remove; } else card->lan_online = 1; qeth_set_large_send(card, card->options.large_send); diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index e606b4829d44..c15878e88157 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -134,6 +134,58 @@ static struct scsi_host_template fcoe_shost_template = { .max_sectors = 0xffff, }; +/** + * fcoe_fip_recv - handle a received FIP frame. + * @skb: the receive skb + * @dev: associated &net_device + * @ptype: the &packet_type structure which was used to register this handler. + * @orig_dev: original receive &net_device, in case @dev is a bond. + * + * Returns: 0 for success + */ +static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *ptype, + struct net_device *orig_dev) +{ + struct fcoe_softc *fc; + + fc = container_of(ptype, struct fcoe_softc, fip_packet_type); + fcoe_ctlr_recv(&fc->ctlr, skb); + return 0; +} + +/** + * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. + * @fip: FCoE controller. + * @skb: FIP Packet. + */ +static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) +{ + skb->dev = fcoe_from_ctlr(fip)->real_dev; + dev_queue_xmit(skb); +} + +/** + * fcoe_update_src_mac() - Update Ethernet MAC filters. + * @fip: FCoE controller. + * @old: Unicast MAC address to delete if the MAC is non-zero. + * @new: Unicast MAC address to add. + * + * Remove any previously-set unicast MAC filter. + * Add secondary FCoE MAC address filter for our OUI. + */ +static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) +{ + struct fcoe_softc *fc; + + fc = fcoe_from_ctlr(fip); + rtnl_lock(); + if (!is_zero_ether_addr(old)) + dev_unicast_delete(fc->real_dev, old); + dev_unicast_add(fc->real_dev, new); + rtnl_unlock(); +} + /** * fcoe_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport @@ -166,6 +218,30 @@ static int fcoe_lport_config(struct fc_lport *lp) return 0; } +/** + * fcoe_netdev_cleanup() - clean up netdev configurations + * @fc: ptr to the fcoe_softc + */ +void fcoe_netdev_cleanup(struct fcoe_softc *fc) +{ + u8 flogi_maddr[ETH_ALEN]; + + /* Don't listen for Ethernet packets anymore */ + dev_remove_pack(&fc->fcoe_packet_type); + dev_remove_pack(&fc->fip_packet_type); + + /* Delete secondary MAC addresses */ + rtnl_lock(); + memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); + dev_unicast_delete(fc->real_dev, flogi_maddr); + if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) + dev_unicast_delete(fc->real_dev, fc->ctlr.data_src_addr); + if (fc->ctlr.spma) + dev_unicast_delete(fc->real_dev, fc->ctlr.ctl_src_addr); + dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); + rtnl_unlock(); +} + /** * fcoe_queue_timer() - fcoe queue timer * @lp: the fc_lport pointer @@ -193,6 +269,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) u64 wwnn, wwpn; struct fcoe_softc *fc; u8 flogi_maddr[ETH_ALEN]; + struct netdev_hw_addr *ha; /* Setup lport private data to point to fcoe softc */ fc = lport_priv(lp); @@ -250,9 +327,23 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) fc->fcoe_pending_queue_active = 0; setup_timer(&fc->timer, fcoe_queue_timer, (unsigned long)lp); + /* look for SAN MAC address, if multiple SAN MACs exist, only + * use the first one for SPMA */ + rcu_read_lock(); + for_each_dev_addr(netdev, ha) { + if ((ha->type == NETDEV_HW_ADDR_T_SAN) && + (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) { + memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN); + fc->ctlr.spma = 1; + break; + } + } + rcu_read_unlock(); + /* setup Source Mac Address */ - memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, - fc->real_dev->addr_len); + if (!fc->ctlr.spma) + memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, + fc->real_dev->addr_len); wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); fc_set_wwnn(lp, wwnn); @@ -267,7 +358,9 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) */ rtnl_lock(); memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); - dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); + dev_unicast_add(fc->real_dev, flogi_maddr); + if (fc->ctlr.spma) + dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr); dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); rtnl_unlock(); @@ -280,6 +373,11 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) fc->fcoe_packet_type.dev = fc->real_dev; dev_add_pack(&fc->fcoe_packet_type); + fc->fip_packet_type.func = fcoe_fip_recv; + fc->fip_packet_type.type = htons(ETH_P_FIP); + fc->fip_packet_type.dev = fc->real_dev; + dev_add_pack(&fc->fip_packet_type); + return 0; } @@ -347,7 +445,6 @@ static int fcoe_if_destroy(struct net_device *netdev) { struct fc_lport *lp = NULL; struct fcoe_softc *fc; - u8 flogi_maddr[ETH_ALEN]; BUG_ON(!netdev); @@ -366,9 +463,10 @@ static int fcoe_if_destroy(struct net_device *netdev) /* Remove the instance from fcoe's list */ fcoe_hostlist_remove(lp); - /* Don't listen for Ethernet packets anymore */ - dev_remove_pack(&fc->fcoe_packet_type); - dev_remove_pack(&fc->fip_packet_type); + /* clean up netdev configurations */ + fcoe_netdev_cleanup(fc); + + /* tear-down the FCoE controller */ fcoe_ctlr_destroy(&fc->ctlr); /* Cleanup the fc_lport */ @@ -383,16 +481,6 @@ static int fcoe_if_destroy(struct net_device *netdev) if (lp->emp) fc_exch_mgr_free(lp->emp); - /* Delete secondary MAC addresses */ - rtnl_lock(); - memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); - dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN); - if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) - dev_unicast_delete(fc->real_dev, - fc->ctlr.data_src_addr, ETH_ALEN); - dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); - rtnl_unlock(); - /* Free the per-CPU receive threads */ fcoe_percpu_clean(lp); @@ -454,58 +542,6 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { .ddp_done = fcoe_ddp_done, }; -/** - * fcoe_fip_recv - handle a received FIP frame. - * @skb: the receive skb - * @dev: associated &net_device - * @ptype: the &packet_type structure which was used to register this handler. - * @orig_dev: original receive &net_device, in case @dev is a bond. - * - * Returns: 0 for success - */ -static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *ptype, - struct net_device *orig_dev) -{ - struct fcoe_softc *fc; - - fc = container_of(ptype, struct fcoe_softc, fip_packet_type); - fcoe_ctlr_recv(&fc->ctlr, skb); - return 0; -} - -/** - * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. - * @fip: FCoE controller. - * @skb: FIP Packet. - */ -static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) -{ - skb->dev = fcoe_from_ctlr(fip)->real_dev; - dev_queue_xmit(skb); -} - -/** - * fcoe_update_src_mac() - Update Ethernet MAC filters. - * @fip: FCoE controller. - * @old: Unicast MAC address to delete if the MAC is non-zero. - * @new: Unicast MAC address to add. - * - * Remove any previously-set unicast MAC filter. - * Add secondary FCoE MAC address filter for our OUI. - */ -static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) -{ - struct fcoe_softc *fc; - - fc = fcoe_from_ctlr(fip); - rtnl_lock(); - if (!is_zero_ether_addr(old)) - dev_unicast_delete(fc->real_dev, old, ETH_ALEN); - dev_unicast_add(fc->real_dev, new, ETH_ALEN); - rtnl_unlock(); -} - /** * fcoe_if_create() - this function creates the fcoe interface * @netdev: pointer the associated netdevice @@ -547,13 +583,6 @@ static int fcoe_if_create(struct net_device *netdev) goto out_host_put; } - /* configure lport network properties */ - rc = fcoe_netdev_config(lp, netdev); - if (rc) { - FC_DBG("Could not configure netdev for lport\n"); - goto out_host_put; - } - /* * Initialize FIP. */ @@ -561,23 +590,25 @@ static int fcoe_if_create(struct net_device *netdev) fc->ctlr.send = fcoe_fip_send; fc->ctlr.update_mac = fcoe_update_src_mac; - fc->fip_packet_type.func = fcoe_fip_recv; - fc->fip_packet_type.type = htons(ETH_P_FIP); - fc->fip_packet_type.dev = fc->real_dev; - dev_add_pack(&fc->fip_packet_type); + /* configure lport network properties */ + rc = fcoe_netdev_config(lp, netdev); + if (rc) { + FC_DBG("Could not configure netdev for the interface\n"); + goto out_netdev_cleanup; + } /* configure lport scsi host properties */ rc = fcoe_shost_config(lp, shost, &netdev->dev); if (rc) { FC_DBG("Could not configure shost for lport\n"); - goto out_host_put; + goto out_netdev_cleanup; } /* lport exch manager allocation */ rc = fcoe_em_config(lp); if (rc) { FC_DBG("Could not configure em for lport\n"); - goto out_host_put; + goto out_netdev_cleanup; } /* Initialize the library */ @@ -603,6 +634,8 @@ static int fcoe_if_create(struct net_device *netdev) out_lp_destroy: fc_exch_mgr_free(lp->emp); /* Free the EM */ +out_netdev_cleanup: + fcoe_netdev_cleanup(fc); out_host_put: scsi_host_put(lp->host); return rc; diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 929411880e4b..2f5bc7fd3fa9 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -198,6 +198,8 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) sol->fip.fip_subcode = FIP_SC_SOL; sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW); sol->fip.fip_flags = htons(FIP_FL_FPMA); + if (fip->spma) + sol->fip.fip_flags |= htons(FIP_FL_SPMA); sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC; sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW; @@ -350,6 +352,8 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) kal->fip.fip_dl_len = htons((sizeof(kal->mac) + ports * sizeof(*vn)) / FIP_BPW); kal->fip.fip_flags = htons(FIP_FL_FPMA); + if (fip->spma) + kal->fip.fip_flags |= htons(FIP_FL_SPMA); kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; @@ -413,6 +417,8 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, cap->fip.fip_subcode = FIP_SC_REQ; cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); cap->fip.fip_flags = htons(FIP_FL_FPMA); + if (fip->spma) + cap->fip.fip_flags |= htons(FIP_FL_SPMA); cap->encaps.fd_desc.fip_dtype = dtype; cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; @@ -421,8 +427,10 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, memset(mac, 0, sizeof(mac)); mac->fd_desc.fip_dtype = FIP_DT_MAC; mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; - if (dtype != ELS_FLOGI) + if (dtype != FIP_DT_FLOGI) memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); + else if (fip->spma) + memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); skb->protocol = htons(ETH_P_FIP); skb_reset_mac_header(skb); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 7546aa887fa7..79c9c5f5cdba 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -681,7 +681,7 @@ static int serial_config(struct pcmcia_device * link) u_char *buf; cisparse_t *parse; cistpl_cftable_entry_t *cf; - int i; + int i, last_ret, last_fn; DEBUG(0, "serial_config(0x%p)\n", link); @@ -699,6 +699,16 @@ static int serial_config(struct pcmcia_device * link) tuple->TupleDataMax = 255; tuple->Attributes = 0; + /* Get configuration register information */ + tuple->DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(link, tuple, parse); + if (last_ret != 0) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse->config.base; + link->conf.Present = parse->config.rmask[0]; + /* Is this a compliant multifunction card? */ tuple->DesiredTuple = CISTPL_LONGLINK_MFC; tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; @@ -761,7 +771,9 @@ static int serial_config(struct pcmcia_device * link) kfree(cfg_mem); return 0; - failed: +cs_failed: + cs_error(link, last_fn, last_ret); +failed: serial_remove(link); kfree(cfg_mem); return -ENODEV; @@ -863,10 +875,10 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c index 25c0ffd2faa0..43b3fe352616 100644 --- a/drivers/staging/agnx/pci.c +++ b/drivers/staging/agnx/pci.c @@ -303,14 +303,18 @@ static int agnx_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int agnx_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) +static void agnx_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed) { struct agnx_priv *priv = dev->priv; void __iomem *ctl = priv->ctl; AGNX_TRACE; + if (!(changed & BSS_CHANGED_BSSID)) + return; + spin_lock(&priv->lock); if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) { @@ -323,8 +327,7 @@ static int agnx_config_interface(struct ieee80211_hw *dev, agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1); } spin_unlock(&priv->lock); - return 0; -} /* agnx_config_interface */ +} /* agnx_bss_info_changed */ static void agnx_configure_filter(struct ieee80211_hw *dev, @@ -422,7 +425,7 @@ static struct ieee80211_ops agnx_ops = { .add_interface = agnx_add_interface, .remove_interface = agnx_remove_interface, .config = agnx_config, - .config_interface = agnx_config_interface, + .bss_info_changed = agnx_bss_info_changed, .configure_filter = agnx_configure_filter, .get_stats = agnx_get_stats, .get_tx_stats = agnx_get_tx_stats, diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c index c8af9a868d62..3f303ae97b43 100644 --- a/drivers/staging/at76_usb/at76_usb.c +++ b/drivers/staging/at76_usb/at76_usb.c @@ -3242,12 +3242,11 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev) "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n", priv->netdev->name, priv->tx_urb, priv->tx_urb->hcpriv, priv->tx_urb->complete); - } else { + } else stats->tx_bytes += skb->len; - dev_kfree_skb(skb); - } - return ret; + dev_kfree_skb(skb); + return NETDEV_TX_OK; } static void at76_tx_timeout(struct net_device *netdev) diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c index 951c73d5db20..59e99cc7786b 100644 --- a/drivers/staging/et131x/et131x_netdev.c +++ b/drivers/staging/et131x/et131x_netdev.c @@ -585,11 +585,11 @@ int et131x_tx(struct sk_buff *skb, struct net_device *netdev) * available */ netif_stop_queue(netdev); - status = 1; + status = NETDEV_TX_BUSY; } else { DBG_WARNING(et131x_dbginfo, "Misc error; drop packet\n"); - status = 0; + status = NETDEV_TX_OK; } } diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c index 33a0687252af..1294e05fcf13 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c @@ -814,7 +814,7 @@ int ieee80211_xmit(struct sk_buff *skb, spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); stats->tx_errors++; - return 1; + return NETDEV_TX_BUSY; } diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 393e4df70dfd..bc0d764d851a 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -432,21 +432,21 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, /* success and more buf */ /* avail, re: hw_txdata */ netif_wake_queue(wlandev->netdev); - result = 0; + result = NETDEV_TX_OK; } else if (txresult == 1) { /* success, no more avail */ pr_debug("txframe success, no more bufs\n"); /* netdev->tbusy = 1; don't set here, irqhdlr */ /* may have already cleared it */ - result = 0; + result = NETDEV_TX_OK; } else if (txresult == 2) { /* alloc failure, drop frame */ pr_debug("txframe returned alloc_fail\n"); - result = 1; + result = NETDEV_TX_BUSY; } else { /* buffer full or queue busy, drop frame. */ pr_debug("txframe returned full or busy\n"); - result = 1; + result = NETDEV_TX_BUSY; } failed: diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index c1abeb89b413..96fb118355b0 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -188,8 +188,7 @@ static struct usb_descriptor_header *hs_pn_function[] = { static int pn_net_open(struct net_device *dev) { - if (netif_carrier_ok(dev)) - netif_wake_queue(dev); + netif_wake_queue(dev); return 0; } @@ -219,8 +218,7 @@ static void pn_tx_complete(struct usb_ep *ep, struct usb_request *req) } dev_kfree_skb_any(skb); - if (netif_carrier_ok(dev)) - netif_wake_queue(dev); + netif_wake_queue(dev); } static int pn_net_xmit(struct sk_buff *skb, struct net_device *dev) @@ -255,7 +253,7 @@ static int pn_net_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&port->lock, flags); out: if (unlikely(skb)) { - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); dev->stats.tx_dropped++; } return 0; @@ -383,7 +381,6 @@ static void __pn_reset(struct usb_function *f) struct phonet_port *port = netdev_priv(dev); netif_carrier_off(dev); - netif_stop_queue(dev); port->usb = NULL; usb_ep_disable(fp->out_ep); @@ -427,8 +424,6 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt) fp->in_ep->driver_data = fp; netif_carrier_on(dev); - if (netif_running(dev)) - netif_wake_queue(dev); for (i = 0; i < phonet_rxq_size; i++) pn_rx_submit(fp, fp->out_reqv[i], GFP_ATOMIC); } @@ -574,9 +569,10 @@ static struct net_device *dev; int __init phonet_bind_config(struct usb_configuration *c) { struct f_phonet *fp; - int err; + int err, size; - fp = kzalloc(sizeof(*fp), GFP_KERNEL); + size = sizeof(*fp) + (phonet_rxq_size * sizeof(struct usb_request *)); + fp = kzalloc(size, GFP_KERNEL); if (!fp) return -ENOMEM; @@ -601,16 +597,13 @@ int __init gphonet_setup(struct usb_gadget *gadget) /* Create net device */ BUG_ON(dev); - dev = alloc_netdev(sizeof(*port) - + (phonet_rxq_size * sizeof(struct usb_request *)), - "upnlink%d", pn_net_setup); + dev = alloc_netdev(sizeof(*port), "upnlink%d", pn_net_setup); if (!dev) return -ENOMEM; port = netdev_priv(dev); spin_lock_init(&port->lock); netif_carrier_off(dev); - netif_stop_queue(dev); SET_NETDEV_DEV(dev, &gadget->dev); err = register_netdev(dev); diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 4007770f7ed2..016f63b39028 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -520,7 +520,7 @@ static int eth_start_xmit(struct sk_buff *skb, struct net_device *net) */ if (list_empty(&dev->tx_reqs)) { spin_unlock_irqrestore(&dev->req_lock, flags); - return 1; + return NETDEV_TX_BUSY; } req = container_of(dev->tx_reqs.next, struct usb_request, list); diff --git a/firmware/Makefile b/firmware/Makefile index 25200d106ee8..621de8e952f7 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -32,6 +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_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 \ @@ -40,13 +41,15 @@ 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.1.0.bin + cxgb3/t3fw-7.4.0.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 \ e100/d102e_ucode.bin fw-shipped-$(CONFIG_MYRI_SBUS) += myricom/lanai.bin fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis +fw-shipped-$(CONFIG_PCMCIA_3C589) += cis/3CXEM556.cis +fw-shipped-$(CONFIG_PCMCIA_3C574) += cis/3CCFEM556.cis fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ advansys/3550.bin advansys/38C0800.bin diff --git a/firmware/WHENCE b/firmware/WHENCE index 4c52984a8319..0f5649a08c0c 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -412,7 +412,7 @@ Driver: cxgb3 - Chelsio Terminator 3 1G/10G Ethernet adapter File: cxgb3/t3b_psram-1.1.0.bin.ihex File: cxgb3/t3c_psram-1.1.0.bin.ihex -file: cxgb3/t3fw-7.1.0.bin.ihex +file: cxgb3/t3fw-7.4.0.bin.ihex License: GPLv2 or OpenIB.org BSD license, no source visible @@ -586,6 +586,26 @@ Originally developed by the pcmcia-cs project -------------------------------------------------------------------------- +Driver: PCMCIA_3C589 - 3Com PCMCIA adapter + +File: cis/3CXEM556.cis + +Licence: GPL + +Originally developed by the pcmcia-cs project + +-------------------------------------------------------------------------- + +Driver: PCMCIA_3C574 - 3Com PCMCIA adapter + +File: cis/3CCFEM556.cis + +Licence: GPL + +Originally developed by the pcmcia-cs project + +-------------------------------------------------------------------------- + Driver: PCMCIA_SMC91C92 - SMC 91Cxx PCMCIA File: ositech/Xilinx7OD.bin @@ -614,6 +634,26 @@ File: myricom/lanai.bin Licence: Unknown +Found in hex form in kernel source. + +-------------------------------------------------------------------------- + +Driver: bnx2x: Broadcom Everest + +File: bnx2x-e1-4.8.53.0.fw.ihex +File: bnx2x-e1h-4.8.53.0.fw.ihex + +License: + Copyright (c) 2007-2009 Broadcom Corporation + + This file contains firmware data derived from proprietary unpublished + source code, Copyright (c) 2007-2009 Broadcom Corporation. + + 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. -------------------------------------------------------------------------- diff --git a/firmware/bnx2x-e1-4.8.53.0.fw.ihex b/firmware/bnx2x-e1-4.8.53.0.fw.ihex new file mode 100644 index 000000000000..f1edb1e7ad1b --- /dev/null +++ b/firmware/bnx2x-e1-4.8.53.0.fw.ihex @@ -0,0 +1,10364 @@ +: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-e1h-4.8.53.0.fw.ihex b/firmware/bnx2x-e1h-4.8.53.0.fw.ihex new file mode 100644 index 000000000000..48d7612907ee --- /dev/null +++ b/firmware/bnx2x-e1h-4.8.53.0.fw.ihex @@ -0,0 +1,12028 @@ +: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/cis/3CCFEM556.cis.ihex b/firmware/cis/3CCFEM556.cis.ihex new file mode 100644 index 000000000000..e4d92b173e17 --- /dev/null +++ b/firmware/cis/3CCFEM556.cis.ihex @@ -0,0 +1,13 @@ +:1000000001030000FF152D050033436F6D004D65A2 +:100010006761686572747A2033434346454D3535D0 +:1000200036004C414E202B2035366B204D6F6465D9 +:100030006D0000FF20040101560521020000060B9F +:1000400002004D000000006B000000FF001303439E +:100050004953210206001A060507001067021B0912 +:1000600087011901556430FFFFFF00130343495313 +:10007000210202001A060527001177021B09A701B9 +:090080001901552330FFFFFF00B8 +:00000001FF +# +# This card is MFC-compliant, but identifies itself as single function +# diff --git a/firmware/cis/3CXEM556.cis.ihex b/firmware/cis/3CXEM556.cis.ihex new file mode 100644 index 000000000000..895010b230ff --- /dev/null +++ b/firmware/cis/3CXEM556.cis.ihex @@ -0,0 +1,13 @@ +:1000000001030000FF152C050033436F6D004D65A3 +:100010006761686572747A20334358454D353536CB +:10002000004C414E202B2035366B204D6F64656DA2 +:100030000000FF20040101350021020000060B0230 +:10004000004C0000000069000000FF00130343495A +:1000500053210206001A0501070008631B098701E6 +:100060001901556430FFFFFF001303434953210278 +:1000700002001A0501270009631B09A70119015590 +:060080002330FFFFFF002A +:00000001FF +# +# This card is MFC-compliant, but identifies itself as single function +# diff --git a/firmware/cxgb3/t3fw-7.1.0.bin.ihex b/firmware/cxgb3/t3fw-7.1.0.bin.ihex deleted file mode 100644 index 1042f755f68f..000000000000 --- a/firmware/cxgb3/t3fw-7.1.0.bin.ihex +++ /dev/null @@ -1,1885 +0,0 @@ -:1000000060007400200380002003700000001000D6 -:1000100000002000E100028400070000E1000288E7 -:1000200000010000E0000000E00000A0010000006E -:1000300044444440E3000183200200002001E0002A -:100040002001FF101FFFD0001FFFC000E300043C91 -:1000500002000000200069881FFFC290200069D0C4 -:100060001FFFC29420006A101FFFC29820006A84FC -:100070001FFFC29C200003C0C00000E43100EA3131 -:1000800000A13100A03103020002ED306E2A05000C -:10009000ED3100020002160012FFDBC03014FFDA5F -:1000A000D30FD30FD30F03431F244C107249F0D347 -:1000B0000FD30FD30F12FFD5230A00240A00D30F4A -:1000C000D30FD30F03431F244C107249F0D30FD327 -:1000D0000FD30F14FFCE03421F14FFCB03421F1296 -:1000E000FFCCC0302D37302D37342D37382D373CED -:1000F000233D017233ED00020012FFC4C0302F37E0 -:10010000002F37102F37202F3730233D017233ED6A -:1001100000020012FFBEC0302737002737102737F4 -:1001200020273730233D017233ED03020012FFB95F -:1001300013FFBA0C0200932012FFB913FFB90C028F -:1001400000932012FFB8C0319320822012FFB71312 -:10015000FFB7932012FFB715FFB316FFB6C030D715 -:100160002005660160001B00000000000000000088 -:10017000043605000200D30FD30F05330C6E3B1479 -:100180000747140704437631E604360505330C6F40 -:100190003BED00020012FFA615FFA3230A00D720A3 -:1001A000070443043E0505330C0747146F3BF00377 -:1001B000020012FFA1C03014FFA1D30FD30FD30F41 -:1001C0009340B4447249F2D30FD30FD30F14FF9B63 -:1001D000834014FF9B834012FF9B230A0014FF9A65 -:1001E000D30FD30FD30F9340B4447249F2D30FD33C -:1001F0000FD30F14FF95834012FF95C92F832084DE -:10020000218522BC22743B0F8650B4559630B433FE -:100210007433F463FFE60000653FE1655FDE12FFC3 -:100220007C230A0028374028374428374828374C91 -:10023000233D017233ED03020000020012FF7AC079 -:1002400032032E0503020012FF7813FF819320C0B2 -:1002500011014931004831010200C00014FF7E0441 -:10026000D23115FF7D945014FF7D04D33115FF7CEE -:10027000945014FF7C04D43115FF7C24560014FFE5 -:100280007B04D53115FF7B24560010FF7A03000054 -:10029000000000000000000000000000000000005E -:1002A000000000000000000000000000000000004E -:1002B000000000000000000000000000000000003E -:1002C000000000000000000000000000000000002E -:1002D000000000000000000000000000000000001E -:1002E000000000000000000000000000000000000E -:1002F00000000000000000000000000000000000FE -:1003000000000000000000000000000000000000ED -:1003100000000000000000000000000000000000DD -:1003200000000000000000000000000000000000CD -:1003300000000000000000000000000000000000BD -:1003400000000000000000000000000000000000AD -:10035000000000000000000000000000000000009D -:10036000000000000000000000000000000000008D -:10037000000000000000000000000000000000007D -:10038000000000000000000000000000000000006D -:10039000000000000000000000000000000000005D -:1003A000000000000000000000000000000000004D -:1003B000000000000000000000000000000000003D -:1003C000000000000000000000000000000000002D -:1003D000000000000000000000000000000000001D -:1003E000000000000000000000000000000000000D -:1003F00000000000000000000000000000000000FD -:1004000000000000000000000000000000000000EC -:1004100000000000000000000000000000000000DC -:1004200063FFFC000000000000000000000000006E -:100430000000000000000000000000001FFC0000A1 -:100440001FFC0000E30005C81FFC00001FFC0000AB -:10045000E30005C81FFC00001FFC0000E30005C806 -:100460001FFFC0001FFFC000E30005C81FFFC00042 -:100470001FFFC018E30005C81FFFC0181FFFC018EA -:10048000E30005E01FFFC0181FFFC28CE30005E07A -:100490001FFFC28C1FFFC28CE30008541FFFC290D5 -:1004A0001FFFC58CE3000854200000002000016AF3 -:1004B000E3000B502000018020000180E3000CBC11 -:1004C0002000020020000203E3000CBC2000021CFC -:1004D00020000220E3000CC02000022020000226A1 -:1004E000E3000CC42000023C20000240E3000CCCDE -:1004F0002000024020000249E3000CD02000024C02 -:1005000020000250E3000CDC2000025020000259C1 -:10051000E3000CE02000025C20000260E3000CEC31 -:100520002000026020000269E3000CF02000026C51 -:1005300020000270E3000CFC200002702000027911 -:10054000E3000D002000028C2000028CE3000D0C63 -:100550002000029020000293E3000D0C200002AC6A -:10056000200002B0E3000D10200002D0200002F2B3 -:10057000E3000D14200003B0200003B0E3000D38A9 -:10058000200003B0200003B0E3000D38200003B0CA -:10059000200003B0E3000D38200003B0200003B0BA -:1005A000E3000D38200003B020006BA8E3000D38F5 -:1005B00020006BA820006BA8E3007530000000004D -:1005C00000000000000000001FFC00001FFC0000F5 -:1005D0001FFFC5901FFFC67020006BA820006BA8EE -:1005E000DEFFFE000000080CDEADBEEF1FFFC2A064 -:1005F0001FFCFE001FFFC0941FFFC5C0300000009D -:10060000003FFFFF8040000010000000080FFFFFC8 -:100610001FFFC26D000FFFFF804FFFFF8000000033 -:1006200000000880B000000560500000600000007D -:1006300040000011350000004100000010000001E2 -:1006400020000000000010007FFFFFFF40000000BE -:1006500005000000800000190400000000000800F0 -:1006600010000005806000007000000020000009FC -:10067000001FF8008000001EA0000000F80000002D -:1006800007FFFFFF080000001800000001008001C4 -:10069000420000001FFFC21D1FFFC0DC00010080E0 -:1006A000604000001A0000000C0000000000300054 -:1006B000600008008000001C000100008000001A9B -:1006C00080000018FC0000008000000100004000D5 -:1006D000030000008000040050000003FFFFBFFF84 -:1006E0001FFFC3D400000FFFFFFFF000000016D073 -:1006F0000000FFF7A50000001FFFC4B01FFFC4618A -:100700000001000800000B20202FFF801FFFC455B0 -:1007100000002C00FFFEFFF800FFFFFF1FFFC57861 -:1007200000002000FFFFDFFF0000FFEF01001100CD -:100730001FFFC3D21FFFC590FFFFEFFF0000FFFBAD -:100740001FFFC6301FFFBEA0FFFFF7FF1FFFC064E3 -:100750000000FFFD1FFFC6200001FBD01FFFC5B03A -:100760001FFFC6601FFFC591E0FFFE001FFFC5A071 -:10077000000080001FFFC53C1FFFC5B41FFFC068FD -:100780001FFFC4D01FFCFFD800010081E10006005C -:10079000000027101FFCFE301FFCFE70E10002006D -:1007A0001FFFC5381FFFC5500003D0901FFFC56451 -:1007B0002B5063802B5079802B5090802B50A6803B -:1007C0001FFFC4690100110F202FFE0020300080A0 -:1007D000202FFF000000FFFF0001FFF82B50B200A8 -:1007E0002B50B208000100102B50B1802B50B2806A -:1007F0002B50BA00000100112B50BD282B50BC809B -:100800002B50BDA020300000DFFFFE005000000292 -:1008100000C0000002000000FFFFF7F41FFFC06CE3 -:10082000000FF80004400000001000000C40000021 -:100830001C400000E00000A01FFFC5401FFD000895 -:100840001FFFC5541FFFC5681FFFC57CE100069050 -:10085000E10006EC000000000000000000000000C5 -:100860000000000001000000000000000000000087 -:100870000000000020100040201000402010004028 -:1008800020140080200C0000200C0000200C000030 -:1008900020100040201400802014008020140080CC -:1008A000201800C0201C0100201C0100201C010099 -:1008B00020200140201800C0201800C0201800C0CF -:1008C000201C0100201800C0201800C0201800C003 -:1008D000201C010020200140202001402020014058 -:1008E00020200940202009402020094020200940E4 -:1008F00020240980FFFFFFFFFFFFFFFFFFFFFFFF37 -:1009000000000000000000000000000000000000E7 -:1009100000000000200052FC200051CC200052FCBE -:10092000200052FC200051082000510820005108EE -:1009300020004F4820004F4820004F4020004EAC80 -:1009400020004D5420004B342000490800000000D6 -:1009500000000000200052CC200051982000523CA2 -:100960002000523C20004FF020004FF020004FF0BC -:1009700020004FF020004FF020004F3820004FF0B3 -:1009800020004C7420004AE4200048B4000000001D -:100990000000000020000BE0200038BC200004C054 -:1009A000200044A820000BD820003FB4200003F012 -:1009B000200044682000489020003CC420003BE018 -:1009C00020003838200036C42000343420002F9412 -:1009D00020003A3C20002BF4200028282000653419 -:1009E000200023B4200020942000204020001D2C53 -:1009F000200018402000157020000DEC20000C2471 -:100A00002000113420001320200041AC20003C784D -:100A100020000BE8200004C00000000000000000DF -:100A200000000000000000000000000000000000C6 -:100A300000000000000000000000000000000000B6 -:100A400000000000000000000000000000000000A6 -:100A50000000000000000000000000000000000096 -:100A60000000000000000000000000000000000086 -:100A70000000000000000000000000000000000076 -:100A80000000000000000000000000000000000066 -:100A900000000000000000003264000000000000C0 -:100AA0003264000064006400640064006400640058 -:100AB000640064000000000000000000000000006E -:100AC0000000000000000000000000000000000026 -:100AD0000000000000000000000000000000000016 -:100AE0000000000000000000000000000000000006 -:100AF00000000000000000000000000000001000E6 -:100B000000000000000000000000000000000000E5 -:100B100000000000000010000000000000000000C5 -:100B200000000000000000000043238000000000DF -:100B300000000000000000000000000000000000B5 -:100B400000000000000000000000000000000000A5 -:100B5000005C94015D94025E94035F940043000086 -:100B60000000000000000000000000000000000085 -:100B70000000000000000000000000000000000075 -:100B80000000000000000000000000000000000065 -:100B9000005C90015D90025E90035F900053000046 -:100BA0000000000000000000000000000000000045 -:100BB0000000000000000000000000000000000035 -:100BC0000000000000000000000000000000000025 -:100BD000009C94001D90019D94029E94039F940498 -:100BE0000894050994060A94070B9400430000003A -:100BF00000000000000000000000000000000000F5 -:100C000000000000000000000000000000000000E4 -:100C1000009C90019D90029E90071D90039F900460 -:100C20007890057990067A90077B90005300000039 -:100C300000000000000000000000000000000000B4 -:100C400000000000000000000000000000000000A4 -:100C500000DC94001D9001DD9402DE9403DF940417 -:100C60000494050594060694070794080894090956 -:100C7000940A0A940B0B940043000000000000004B -:100C80000000000000000000000000000000000064 -:100C900000DC9001DD9002DE900B1D9003DF9004DC -:100CA000B49005B59006B69007B79008B89009B90A -:100CB000900ABA900BBB90005300000063FFFC0049 -:100CC0002000696410FFFF0A00000000200069880E -:100CD00000D23110FFFE0A0000000000200069D0A1 -:100CE00000D33110FFFE0A000000000020006A104F -:100CF00000D43110FFFE0A000000000020006A84CA -:100D000000D53110FFFE0A000000000063FFFC0068 -:100D1000E00000A012FFF78220028257C82163FF83 -:100D2000FC12FFF303E83004EE3005C0309320944A -:100D300021952263FFFC00001FFFD000000400206B -:100D40001FFFC5901FFFC670200A0011FFFB13FF95 -:100D5000FB03E63101020016FFFA17FFFAD30F7703 -:100D60006B069060B4667763F85415505419E60F1B -:100D7000140063FFF90000006C1004C020D10F00C4 -:100D80006C1004C0C71AEF06D830BC2BD720857270 -:100D90000D4211837105450B957202330C237601C8 -:100DA0007B3B04233D089371A32D12EEFE19EEFE4A -:100DB000A2767D632C2E0A00088202280A01038E87 -:100DC000380E0E42C8EE29A67E6D4A050020880026 -:100DD000308C8271D10FC0F0028F387FC0EA63FF80 -:100DE000E400C0F1C050037E0CA2EE0E3D1208825A -:100DF0000203F538050542CB5729A67E2FDC100FDC -:100E00004F366DFA0500208800308CBC75C0300864 -:100E1000E208280A01058338030342C93E29A67E59 -:100E20000D480CD30F6D8A0500208800B08C8271AC -:100E3000D10FC05008F53875C0C163FFBBC0600258 -:100E4000863876C0DA63FFD46C101216EED8C1F87B -:100E5000C1E72B221E2C221DC0D07BC12F292006CA -:100E6000D7B0299CFACC57282070288CFF282470F2 -:100E700064915C2AB0000EA80C6481670FA90C6411 -:100E800092B3C1E97EA13969AC2F600036292006F2 -:100E9000D7D0299CFACC57282070288CFF282470A2 -:100EA0006491352AD0000EA80C6481640FA90C64EB -:100EB000931BC1E97EA10968AC09C020D10F0000D5 -:100EC000002D25028A32C0900A6F5065F5AD2924A5 -:100ED000670908476585A92F200C18EEB50CFE118F -:100EE000A8EE28E286B44978930260057A19EEB13B -:100EF00009F90A2992A3689007882009880C65855A -:100F00006627E28564756065558E7BC104D9B06043 -:100F10000001C0908B941CEEA80B88148CC40B0BA2 -:100F200047A8CC18EEA609BB1008CC029C7018EE9E -:100F3000A41CEEA508A8010B88020C4C021BEEA114 -:100F40009C710B880298722C90232B902204C8105D -:100F500006BB100C4C1208BB0228902107CC100CC9 -:100F600088100C88020B88021CEE998B330CBB0195 -:100F70008C340B880298739C999C748B958C399B4C -:100F80007588968B38987688979C799B7898771C8B -:100F9000EE9028E2850CFC082DC4CF08480B28E60B -:100FA0008565550B2B221E2D221D7BD9022B0A0095 -:100FB00064BF062CB00728B000DA2006880A288211 -:100FC0004CC0D10B8000DBA065AFE763FEEB0000F7 -:100FD000292070659E9C6004E42A207065AEC36081 -:100FE00004DB00002EB0032C2067D4E065C1058A25 -:100FF000328C330AFF500C4554BC5564F4E619EEAC -:1010000075882A09A90109880C64821BC0926000B6 -:10101000DD2ED0032A2067D4E065A0D88A328B3336 -:101020000AFC500B4554BC5564C4B919EE6A882AB1 -:1010300009A9017989D50BEA5064A4DD0CEE11C031 -:10104000F02F16132E16168AE78CE82A16128EE950 -:10105000DFC0AAEA7EAB01B1CF0BA85065834288FE -:1010600037DBC0AE89991E789B022BCC012B161B57 -:1010700029120E2B0A0029161A7FC3077FC9027E88 -:10108000AB01C0B165B4988B352F0A002A0A007AEB -:10109000C30564C3C72F0A0165F4842B12162B16EF -:1010A00019005104C0C100CC1A2CCCFF2C16170C0F -:1010B000FC132C16182B121A2A121BDC505818FA83 -:1010C000C0D0C0902E5CF42C12172812182F121BBF -:1010D0002A121A08FF010CAA018834074C0AAB8BAC -:1010E0002812192BC6162F86082A86092E74102955 -:1010F00024672E70038975B1EA2A7403B0990949EF -:101100000C659DB52B20672D250265B3F42B221E9F -:101110002C221D7BC901C0B064BD9E2CB00728B035 -:1011200000DA2006880A28824CC0D10B8000DBA0A0 -:1011300065AFE763FD8389BAB19965909788341CE0 -:10114000EE2698BA8F331EEE1F0F4F542FB42C8DFE -:101150002A8A320EDD020CAC017DC9660A49516F44 -:1011600092608A3375A65B2CB0130AED510DCD0148 -:101170000D0D410C0C417DC9492EB012B0EE65E356 -:10118000C2C0D08E378CB88A368FB97CA3077AC993 -:10119000027EFB01C0D1CED988350AAD020E8E0881 -:1011A00078EB022DAC0189B7DAC0AF9B79BB01B1F6 -:1011B000CADCB0C0B07DA3077AD9027CEB01C0B114 -:1011C00064B15DC091292467C020D10F00008ADA84 -:1011D000B1AA64A0BC2E20672D250265E30B1FED8C -:1011E000F98A3218EDFE0FAF0108FF0C65F2860A8E -:1011F00048516F820260027DC090292467090A4726 -:1012000065A2F27BC901C0B064BCAE2CB00728B0A7 -:1012100000DA2006880A28824CC0D10B8000DBA0AF -:1012200065AFE763FC9300000CE9506492EB0CEFB0 -:1012300011C080281611AFBF2F16198EF88BF7DA60 -:10124000E08FF92B1610ABFB7FBB01B1EA0CA85065 -:101250006580D68837DCE0AF89991C789B022CEC3E -:10126000012C161B29120C2C0A0029161A7AE307E6 -:101270007AE9027FBB01C0C165C2A48B352C0A008C -:101280002A0A007AE30564E1CA2C0A0164CE1160DF -:10129000028D88341BEDD198DA8F331EEDCA0F4FC3 -:1012A000542FD42C8C2A8A320ECC020BAB010CBBEF -:1012B0000C65BF0E0A49516E920263FF058A330A1C -:1012C000AB5064BEFD2CD0130AEE510ECE010E0EB3 -:1012D000410C0C410ECC0C65CEE82FD012B0FF654E -:1012E000F26EC0B08E378CD88A362FD2097CA30715 -:1012F0007AC9027EFB01C0B165BEC78835DBA0AEEE -:101300008E78EB01B1AB89D7DAC0AF9D79DB01B143 -:10131000CAC0C07BA3077AB9027DEB01C0C165CE0C -:10132000A1C090292467C020D10F88378C3698142B -:101330000CE90C29161408F80C981D78FB072812E4 -:1013400014B088281614891D9F159B16C0F02B1207 -:101350001429161A2B161B8B147AE30B7AE90688CC -:10136000158E1678EB01C0F165F1B929121A2F120A -:10137000118A352E121B9A1AAFEE2F1210C0A0AF91 -:101380009F79FB01B1EE9F11881AC0F098107AE3A3 -:101390000A7EA9052A12017A8B01C0F164F08160EE -:1013A000018289368B3799170BE80C981F09C90CF5 -:1013B00029161578EB07281215B088281615D9C0FC -:1013C0009A199E188A1F2E12152A161A2E161BDA23 -:1013D000C0C0E08C177F930B7FA90688188F1978FF -:1013E000FB01C0E165E13D29121A2F12138A352E47 -:1013F000121B9A1BAFEE2F1212C0A0AF9F79FB01F8 -:10140000B1EE9F13881BC0F098127AE30A7EA905FB -:101410002A12037A8B01C0F165F1092E12162E16DD -:10142000192A121B005104C0E100EE1AB0EE2E166C -:10143000170EFF132F16180FCC01ACAA2F121A0E7D -:10144000BC01ACFC7FCB01B1AA2A161B2C161A6377 -:10145000FC6200007FB30263FE3163FE2B7EB302A9 -:1014600063FC3463FC2E00006450C0DA20DBF058CB -:1014700015DEC020D10FC09163FD7E00C09163FADC -:101480004CDA20DB70C0D12E0A80C09A2924682C47 -:1014900070075814CED2A0D10F034C0B18ED51DBBE -:1014A000C0A82878C3022BCDF8D9B063FA65000034 -:1014B0002A2C74DB40580E5063FAE80000002D25FA -:1014C000027BC901C0B064B0172CB00728B000DAA5 -:1014D0002006880A28824CC0D10B8000DBA065AFB3 -:1014E000E7C020D10FC09163FC04022A02580250C9 -:1014F0000AA202060000022A0258024D0AA20206AF -:101500000000DB70DA20C0D12E0A80C09E2924683A -:101510002C70075814AEC020D10FC09463FBCF00CD -:10152000C09663FBC9C09663FBC400002A2C74DB21 -:1015300030DC405BFE13DBA0C2A02AB4002F200CDD -:1015400063FF27008D358CB77DCB0263FDD263FC32 -:10155000718F358ED77FEB0263FDC563FC6400009D -:101560006C1004C020D10F006C1004C020D10F00FB -:101570006C10042B221E28221DC0A0C09429240612 -:101580002A25027B8901DBA0C9B913ED08DA2028DE -:10159000B0002CB00703880A28824CC0D10B800011 -:1015A000DBA065AFE7C020D10F0000006C1004295C -:1015B00020062A2102689805289CF965811A0A0AE2 -:1015C0004C65A0F016ECFB2B629E1AECF86FB8028B -:1015D0006000F12AA22668A0078B200ABB0C65B028 -:1015E000E32A629D64A0DD2B200C0CBC11A6CC2D3F -:1015F000C2866FD9026000D71DECEF0DBD0A2DD257 -:10160000A368D0078E200DEE0C65E0C327C285C00D -:10161000E06470BB1DECF468434D1CECF38A2B0CAA -:10162000AA029A7089200899110D99029971882A45 -:1016300098748F329F75282104088811987718ECC8 -:10164000E40CBF11A6FF2DF285A8B82E84CF2DDCA7 -:10165000282DF685C85A2A2C74DB40580DE7D2A0F5 -:10166000D10FC020D10F00002C9CF964C08D2C201C -:10167000668931B1CC0C0C472C24666FC669709E0C -:101680006618ECDA89308F2B0989400B991009FF15 -:101690000208FF029F708C2008CC110DCC029C71B7 -:1016A0008A339A7389329972882A98748F349F7515 -:1016B00063FF820000CC57DA20DB30DC405814B8DE -:1016C000C020D10F00DA20C0B658154763FFE500EF -:1016D000DA2058154563FFDC00DA20DB30DC40DD22 -:1016E000505815C7D2A0D10F2B21045813DA1DEC86 -:1016F000BD2B200CC0E02E246663FF842F2123C065 -:10170000C87FC30263FF792C20662B2104B1CC0C67 -:101710000C472C24665813CF1DECB32B200CC0E0D3 -:101720002E246663FF5A00006C1004C0B7C0A116D7 -:10173000ECB015ECA2D720D840B822C04005350245 -:101740009671957002A438040442C94B1AEC95199D -:10175000EC9629A67EC140D30F6D4A050080880013 -:10176000208C220A88A272D10FC05008A53875B00B -:10177000E363FFD76C100893149412292006655276 -:1017800088C0716898052A9CF965A29816EC892989 -:1017900021028A1409094C6590C78AA00A6A512A55 -:1017A000ACFD65A0BCCC5FDB30DA208C1258147C19 -:1017B000C0519A14C7BF9BA98E142EE20968E0603D -:1017C0002F629E1DEC7A6FF8026000812DD2266890 -:1017D000D0052F22007DF9752C629DC79064C06DE5 -:1017E0009C118A142B200C2AA0200CBD11A6DD0A06 -:1017F0004F14BFA809880129D286AF88288C09799F -:101800008B551FEC6C0FBF0A2FF2A368F00528223E -:10181000007F894329D285D49065907760003D0090 -:10182000002B200C1FEC640CBD11A6DD29D2860F05 -:10183000BF0A6E96102FF2A368F00488207F8905F6 -:1018400029D285659165DA205814E7600013DA2003 -:10185000C0B65814E5600009C09063FFB9DA20589B -:1018600014E28914899109FE506551E48C128D149B -:10187000DA20DBD08DD09E100D6D515813549A1480 -:1018800064A208C75F8FA195A9C0510F0F479F128F -:1018900063FEFB00C091C0F12820062C2066288C36 -:1018A000F9A7CC0C0C472C24666FC6088D148DD17B -:1018B00070DE01C090DD90648159C9D32A12012BDA -:1018C00021045813648A14C0B02B24668EA92AA060 -:1018D000200E28141CEC438D1415EC37C1700A77C8 -:1018E0003685562DDC28AC2C9C13DED0A8557CD335 -:1018F000022EDDF8D3E0DA40055B02DC305BFF8AC4 -:10190000D4A028200CB455C0D02B0A882F0A800CF4 -:101910008C11A6CC29C285AF3FAB9929C6851CEC9A -:101920002CDEF0AC882D84CF28120329120478F322 -:10193000022EFDF8289020D3E007880CC17008081B -:1019400047289420087736657FAB891413EC2A89E1 -:1019500090C0F47797491BEC28C1CA28210485144C -:10196000099E4006EE11875304881185520E8802A5 -:101970000C88029BA09FA18F2B9DA598A497A7954B -:10198000A603FF029FA22C200C1EEC11AECE0CCCA5 -:101990001106CC082BC2852DE4CF2BBC202BC6858D -:1019A0002A2C748B12580D14D2A0D10F28203DC0C0 -:1019B000E07C877F2E24670E0A4765A07B1AEC0F18 -:1019C00088201EEBFD8F148EE48FF40888110A889E -:1019D000020F8F14AFEE1FEC0A98910FEE029E904B -:1019E0001EEC09C0801AEBFA2CD285AABAB8CC2812 -:1019F000A4CF2CD6852C21022F20700ECC02B1FF53 -:101A00002F24702C2502C020D10F87148770070760 -:101A10004763FD6E282123C099798B0263FE9ADD0E -:101A2000F063FE9500DA20DB308C12DD505814F4A0 -:101A3000D2A0D10FC0E163FF7A8B148C12DD50C0AD -:101A4000AA2E0A802A2468DA20581360D2A0D10F67 -:101A5000007096552B629E6EB8531DEBD42DD22686 -:101A600068D0048E207DE9452A629DCBAF2B2104EE -:101A70002C20665812F8C090292466821418EBE2D4 -:101A80008F2108FF019F21C020D10F008B10C9B802 -:101A90008CA00C6C51CCCC8E241FEBD08DE19E140D -:101AA0000FDD029DE18810658FA9C020D10FDA20DB -:101AB000C0B658144DC020D10F0000006C1006298C -:101AC0002102C0D07597102A32047FA70A8B357F78 -:101AD000BF052D25020DD902090C4C65C18216EBFC -:101AE000B41EEBB228629EC0FA78F3026001882926 -:101AF000E2266890078A2009AA0C65A17A2A629DCD -:101B0000DFA064A1772B200C0CBC11A6CC29C286C7 -:101B1000C08C79830260015719EBA709B90A299291 -:101B2000A3689007882009880C65814327C2851C1B -:101B3000EBA964713A8931098B140CBB016FB11D9B -:101B40002C20669F10B1CC0C0C472C24666EC6026C -:101B500060014009FF5065F13A8A102AAC188934B7 -:101B6000C0C47F973C18EBAA1BEBA98F359C719BD7 -:101B7000708B209D7408BB029B72C08298751BEB12 -:101B8000A50F08409B730F881198777FF70B2F21C3 -:101B900002284A0008FF022F2502C0B4600004009A -:101BA0000000C0B07E97048F362F25227D970488D1 -:101BB000372825217C9736C0F1C0900AF9382F3C90 -:101BC0002009094264908619EB7618EB7728967EF7 -:101BD00000F08800A08C00F08800A08C00F0880045 -:101BE000A08C2A629D2DE4A22AAC182A669D893019 -:101BF0007797388F338A3218EB8007BE0B2C21047D -:101C0000B4BB04CC1198E0C08498E1882B9DE59A80 -:101C1000E69FE71AEB78099F4006FF110FCC020AF6 -:101C2000880298E2C1FC0FCC022CE604C9B82C2033 -:101C30000C1EEB670CCA11AECC06AA0829A2852D92 -:101C4000C4CF09B90B29A685CF5CC020D10FC081B4 -:101C5000C0900F8938C08779880263FF7263FF667E -:101C600000CC57DA20DB30DC4058134DC020D10FB8 -:101C7000DA205813DD63FFE8C0A063FE82DA20C0DB -:101C8000B65813D963FFD900DB402A2C74580C5A7C -:101C9000D2A0D10F8A102B210458126E1EEB44C023 -:101CA000D02D246663FEB1006C1006D62019EB3FE0 -:101CB0001EEB4128610217EB3E08084C65805F8AE5 -:101CC000300A6A5169A3572B729E6EB83F2A92263A -:101CD00068A0048C607AC9342A729D2C4CFECAAB71 -:101CE0002B600CB64F0CBD11A7DD28D2860EBE0AA4 -:101CF00078FB269C112EE2A32C160068E0052F62CB -:101D0000007EF91522D285CF2560000D00DA60C073 -:101D1000B65813B5C85A60010F00DA605813B2659F -:101D20005106DC40DB308D30DA600D6D51581227E2 -:101D3000D3A064A0F384A1C05104044763FF6D00E5 -:101D4000C0B02C60668931B1CC0C0C472C64666F36 -:101D5000C60270960A2B610458123EC0B02B64660E -:101D60006550B42A3C10C0E7DC20C0D1C0F002DFCF -:101D7000380F0F4264F09019EB0A18EB0B28967E8F -:101D80008D106DDA0500A08800C08CC0A089301DC0 -:101D9000EB1A77975388328C108F3302CE0BC02406 -:101DA00092E12261049DE00422118D6B9BE59FE787 -:101DB00098E61FEB100998400688110822020FDDF3 -:101DC00002C18D9DE208220292E4B4C22E600C1F73 -:101DD000EB000CE811A7882C8285AFEE0C220B2BB0 -:101DE000E4CF228685D2A0D10F28600CD2A08C111E -:101DF00019EAF80C8D11A988A7DD2ED2852B84CF86 -:101E00000ECC0B2CD685D10FC0F00ADF387FE8024C -:101E100063FF6C63FF6000002A6C74C0B2DC20DDDD -:101E20004058121CC0B063FF63C020D10F000000F7 -:101E30006C10042C221D2A221EC049D320293006F2 -:101E4000243468C0407AC105DDA060000200C0D023 -:101E50006E9738C08F2E0A802B3014C09629340616 -:101E60000EBB022E31022B34147E8004243502DE98 -:101E7000407AC10EC8ABDBD0DA302C0A00580A76A3 -:101E80002E31020E0F4CC8FEC020D10F6895F828E5 -:101E9000310208084C658FEF1AEAC61CEAC42BA26F -:101EA0009EC09A7B9B462BC22668B0048D307BD99E -:101EB0003B29A29DC0E3CB9394901BEAD72D31041C -:101EC0009B9608DD110EDD029D979D9112EAD4C00C -:101ED000E524C4A22E34062F310228A29D02FF025F -:101EE000288C3028A69D2F3502C020D10FDA30C0B3 -:101EF000B658133DC020D10F6C10062920066898F3 -:101F000005289CF965825D29210209094C6592101A -:101F1000CD51DB30DA20044C025812A1C051D3A0BD -:101F2000C7AF2A360AC0E019EAA31DEAA91FEAA230 -:101F30008A3A16EA9FB1AC64C13528629E6F880266 -:101F40006001F129DC332992266890078B2009BBB8 -:101F50000C65B1E027629DC08E6471D82B200C0CFB -:101F6000BC11A6CC29C2867983026001D219EA91FC -:101F700009B90A2992A397106890082822000988B5 -:101F80000C6581BB27C2856471B5292006299CF99F -:101F90006491EC2C20668931B1CC0C0C472C246662 -:101FA0006EC6026001A109F85065819B883689F4EC -:101FB000088C14AC991CEA810C99022C21049970AC -:101FC00019EA980808479971892A0988100899021E -:101FD00018EA95089902997228301329301204885A -:101FE0001006991008990228302C9A740C88100851 -:101FF000C802098802987389379975883898768A53 -:1020000039C0819A771AEA888935987B9978098945 -:10201000140A9902997A8A30893277A73618EA76B3 -:102020008F33987CC084987D882B2E761129761268 -:102030002F761319EA700A9F4006FF1104CA11098E -:1020400088020FAA02987EC1F90FAA022A7610C050 -:10205000AA600001C0A6ADBF0CBC11A6CC29C285E8 -:102060002EF4CF09A90B29C685655107C020D10FD1 -:102070002B200C0CBC1106CC0828C28609B90A6FAB -:10208000890260012E2992A36890082A220009AAD9 -:102090000C65A11F2AC28564A11928203D0828408B -:1020A00064808C843504841464408485F574537F83 -:1020B0008436048414644077745374293013C08CBC -:1020C00079886CC0902924670908476580ED8820CD -:1020D00089F484351FEA4B048414A4940F440294B9 -:1020E000A014EA4608881104880298A1843698A3AF -:1020F000048414A4990F990299A219EA42ADB42854 -:10210000C2852E44CF288C1028C6852821022F2076 -:1021100070098802B2FF2F2470282502C020D10F39 -:1021200000CC57DA20DB30DC4058121DC020D10F24 -:10213000C09163FF8FDA20C0B65812AB63FFE10095 -:10214000DA205812A963FFD88A102B2104581141B4 -:102150001DEA201FEA192B200CC0E02E24668A3AC3 -:1021600063FE480000DA20DB30DC40DD50581324E9 -:10217000D2A0D10F2A2C74DB40580B1FD2A0D10F54 -:10218000292123C08879830263FE202A12002C2093 -:10219000662B21042CCC010C0C472C246658112DE5 -:1021A0001DEA0C1FEA052B200CC0E02E24668A3A9B -:1021B00063FDF800DA2058128C63FF64DA205BFFBD -:1021C0001CD2A0D10F0000006C10089515C061C191 -:1021D000B0D9402A203DC0400BAA010A64382A2009 -:1021E0000629160668A8052CACF965C33B1DE9F263 -:1021F0006440052F120564F29C2621021EE9EE06BA -:10220000064C6562E315E9EA6440D98A3529300352 -:102210009A140A990C6490CC2C200C8B149C110CF1 -:10222000CC11A5CC9C122CC286B4BB7CB30260023C -:10223000D38F110EFE0A2EE2A368E0098620D30F89 -:102240000E660C6562BE88122882856482B6891487 -:1022500064905EDA80D9308C201EE9E81FE9E91D20 -:10226000E9D68B148DD4D4B07FB718B88A293C1026 -:10227000853608C6110E66029681058514A5D50F10 -:10228000550295800418146D8927889608CB11088B -:1022900088140EBB02A8D8299C200F88029BA19805 -:1022A000A088929BA3088814A8D80F880298A22A15 -:1022B000AC1019E9D4C0C08F141EE9C586128D1167 -:1022C000286285AEDD08FF0B2CD4CF2821022F66B3 -:1022D000858B352A2070098802ABAA2825022A247A -:1022E00070C020D10F29529E18E9B16F9802600288 -:1022F0000828822668800829220008990C6591F92F -:102300002A529DC1CA9A1364A1EF2B200C262006E5 -:102310000CB811A5882D82860EBE0A7DC30260020C -:10232000022EE2A368E0082F22000EFF0C65F1F3F5 -:10233000288285DE806481FF9810266CF96461FF35 -:102340002C20668831B1CC0C0C472C24666EC6025A -:102350006001BC08FD5065D1B617E9B419E9981AB7 -:10236000E99F2C21048B2D2830102F211D0C881063 -:102370000BFB090C88020A880209BB0264415289DE -:1023800010C04D9B90979198928D35D9E064D06C98 -:10239000D730DBD0D8307FD713273C10BCE92632AA -:1023A000168C3996E69CE78A37B4389AE80B1314F2 -:1023B0006430492A821686799A9696978C778A7D18 -:1023C0009C982B82172C7C209A9A2A9C189B998681 -:1023D0007BB03BB8896DB9218BC996A52692162A88 -:1023E000AC18B8999BA196A08BC786CD9BA22B92C7 -:1023F0001596A49BA386CB2CCC2026A605C0346BB7 -:10240000D4200D3B0C0DD8090E880A7FB705C0906B -:102410009988BC88C0900B1A126DAA069988998B6E -:10242000288C18C0D01BE9831CE98216E978B1FF1B -:102430002A211C23E6130F0F4F26E6122F251D7F9E -:10244000A906C0F0C08028251D05F6111AE9718F74 -:10245000202BE6152CE6162DE61726E6180AFA02BA -:102460002AE614292006299CF96490FF29200C8D66 -:1024700015C0801AE9570C9C11AA99A5CCDA202B1B -:10248000C2852894CF0B4B0B2BC685C0B08C165839 -:102490001114D2A0D10F8A356FA548D8308BD56DD5 -:1024A000A90C8A860A8A14CBA97AB337288C10C063 -:1024B00080282467080B4765B112DA20DB302C1224 -:1024C00006581137D3A0C0C1C0D02DA4039C1563FA -:1024D000FD26863664610C8910C04D9B90979198BB -:1024E0009263FEA4C08163FFC78A15CCA7DA20DB04 -:1024F000308C1658112BC020D10FDA20C0B65811DD -:10250000BA63FFE400DA208B115811B763FFD900DA -:102510009E178A132B210458104F8E17C0B02B24FE -:102520006663FE34C08063FE09DA20DB308C16DD82 -:1025300050581233D2A0D10FDA205811AB63FFA844 -:102540002D2123C0C87DC30263FE0D8A132B2104F5 -:102550002C20669817B1CC0C0C472C246658103DE3 -:102560008E17C0D02D246663FDEE0000262123B017 -:102570006606064F262523656EF128206A7F8705AB -:102580000829416490A5C0D01BE91C19E92B26201D -:102590000723E61BB16609FA022BE61A28200A2D4A -:1025A000E61D2AE61E09880228E61C88260606473C -:1025B00028E6202B220826E53E2BE6212D24072C99 -:1025C00020062A206468C347B44463FE9EDB30DAE9 -:1025D000208D15C0CE2E0A802C24688C1658107BB6 -:1025E000D2A0D10F8E102A321616E8F30A2A1486CA -:1025F000662BE61297E127E61328E614AA66096619 -:102600000296E02EEC4869ED50C14663FD7A000069 -:1026100064AFB419E8E928201689920A880C009161 -:102620000400881AA8B8982963FF9C002B21046E27 -:10263000B81E2C2066B8CC0C0C472C2466C9C09E52 -:10264000178A135810048E17C0348F20C0D02D2441 -:1026500066C06826240663FF2C008D35C08064D0D8 -:102660004AD9E0DC30DBE0DF301AE8F4B188B4FFAF -:1026700017E8F486C9249DFF8DC82CCC102D463058 -:102680000767012D46320A66011DE8EE264631AD88 -:102690006D2D463326F21597B796B684C3BCBB940E -:1026A000B58D35299C107D83C22F211DC14663FD48 -:1026B0004B0000006C1006292006289CF86582C398 -:1026C0002921022B200C09094C6590E116E8B90C70 -:1026D000BA11A6AA2DA2862C0A127DC3026002900E -:1026E00019E8B509B90A2992A36890078C2009CC8A -:1026F0000C65C27C29A2856492762D629E1AE8AB95 -:102700006FD8026002722AA22629160168A0082B3F -:1027100022000ABB0C65B26029629DC18C6492588C -:102720002A21200A806099102C203CC7EF000F3E20 -:10273000010B3EB1BD0FDB390BBB098F260DBD115F -:102740002DDC1C0D0D410EDD038E27B1DD0D0D417D -:102750000FEE0C0DBB0B2BBC1C0BB7027EC71C2C49 -:1027600021257BCB162D1AFC0CBA0C0DA16000099B -:102770003E01073EB1780987390B770A77EB026093 -:10278000020A2C2123282121B1CC0C0C4F2C25230B -:102790007C8B29B0CD2D2523C855DA20DB30580F8E -:1027A000FA292102CC96C0E80E9E022E2502CC57B3 -:1027B000DA20DB30DC4058107AC020D10F2C2066A4 -:1027C0008931B1CC0C0C472C24666EC6026001D353 -:1027D00009FD5065D1CD2F0A012E30112922146434 -:1027E000E01128221B090C4400C10400FA1A0A88CF -:1027F0000228261B2E3010C0A0C0B088301CE86E06 -:1028000094129513C04125203C2CC022088D1477CA -:1028100087052F0A010CFA38C0F2C0840858010F4E -:102820005F010F4B3805354007BB10C0F0084F382B -:1028300008FF100FBB0228ECFEC0F0084F38842BB5 -:102840000BA8100AFF102A21200F88020B8802080B -:10285000440218E87D8F110844022821250A2A1411 -:102860000828140488110A88022A210494F08B2075 -:1028700004E41008BB1104BB02C04A04BB029BF174 -:10288000842A08AB110BEB0294F40A54110B440296 -:102890000555100D1B4094F707BB100B550208554A -:1028A00002C08195F68433C05094F3B1948B329575 -:1028B000F898F99BF2C080C1BC24261498FB9BF5C4 -:1028C00099FA853895FC843A94FD8B3B9BFE8839B8 -:1028D00098FF853525F6108436851324F6118B373D -:1028E00084122BF612C0B064C08189307797468D70 -:1028F0003288332E30108F111CE840099940069918 -:10290000112CF614C0C42CF6158C2B2DF61A28F6B3 -:102910001B2BF61904A81109880208EE0219E835E4 -:10292000C18008EE0209C90229F6162EF618C09ECB -:10293000600004000000C09A2F200C18E8250CFE4F -:1029400011A8FFA6EE2DE2852BF4CF0D9D0B2DE6F1 -:1029500085C87F8A268929A7AA9A260A990C090977 -:102960004829252565504CC020D10F00C09A63FF2F -:10297000C6DA2058109D63FE34DA20C0B658109A8B -:1029800063FE2A00689738C020D10F0000DA20DBF0 -:1029900070581057C0B0C0C10ACA390ACB3865BDDB -:1029A000E063FE098A102B2104580F2AC0B02B24A3 -:1029B0006663FE21DB402A2C7458090FD2A0D10F88 -:1029C000DA20580F2F63FCF76C1004C020D10F00E1 -:1029D0006C1004290A801EE81D1FE81D1CE7F50C79 -:1029E0002B11ACBB2C2CFC2DB2850FCC029ED19CA4 -:1029F000D0C051C07013E81914E81818E8162AB2AC -:102A000085A82804240A234691A986B8AA2AB6854F -:102A1000A98827849F25649FD10F00006C100AD6D7 -:102A200030283010292006288CF964829B68980B86 -:102A30002A9CF965A1B2022A02580F1189371BE7B7 -:102A4000DEC89164520E2A21020A0C4C65C2588DD0 -:102A50003019E7D774D7052E212365E29E2F929E69 -:102A60001AE7D36FF8026002532AA22668A0082C46 -:102A700022000ACC0C65C2442A929D64A23E9A159B -:102A80001FE7CD8D67C1E664D00E2B620618E7CA3A -:102A900064B0052880217B8B422B200C18E7C50CE5 -:102AA000BC11A8CC29C28679EB450FBE0A2EE2A341 -:102AB00068E0048F207EF9372CC2859C1864C233ED -:102AC0002B212F87660B7B360B790C6F9D266ED2E0 -:102AD000462C203D7BC740CE5560001E2A200CC1ED -:102AE000B28C205810759A1864A2458D6763FFCF89 -:102AF000C0C063FFC5D7B063FFD300C0E060000271 -:102B00002E60030EDB0C6EB20EDC700CEA11AA6AAA -:102B10002AAC20580199D7A0DA20DB70C1C82D213A -:102B20002058101B8C268B279A160CBB0C7AB334BA -:102B30008F18896399F3886298F28E659EF82D60EC -:102B4000108A189D1768D729C0D09DA92C22182B50 -:102B500022139CAB9BAA97A58E667E73026000979A -:102B6000CF5860001FDA208B16580FE165A138633B -:102B7000FFBDC081C0908F18C0A29AF999FB98FA46 -:102B800097F563FFD2DB30DA20DC40580F85C05167 -:102B9000D6A0C0C02BA0102CA4039B172C12080297 -:102BA0002A02066B02DF702D60038E179D149E10A3 -:102BB0000CDD11C0E0AD6D2DDC205801188C148B9C -:102BC00016ACAC2C64038A268929ABAA0A990C9A04 -:102BD00026886609094829252507880C98662F222A -:102BE00018A7FF2F261863FE96DA20DB30DC40DDC5 -:102BF00050581083D2A0D10FC0302C20668961B10B -:102C0000CC0C0C472C24666EC6026000D2C0300982 -:102C1000FD5065D0CA8E6764E069647066DB608CC5 -:102C200018DF70DA202D60038E170CDD119E10ADB9 -:102C30006D2DDC201EE7845800F9232618DA208B3E -:102C400016DC402F2213DD50B1FF2F2613580F241E -:102C5000D2A0D10F0028203D084840658DE76F9530 -:102C60003EDA308DB56D990C8CA80C8C14CACF7CD3 -:102C7000D32D2AAC10C090292467090D4764DDC507 -:102C8000600092002C1208066B022D6C20077F0258 -:102C90008E17DA209E101EE76B58007D63FF9A00A6 -:102CA000C09163FFD1000000655081DA20DB60DC59 -:102CB00040580F3BC020C0F02FA403D10FDA20C032 -:102CC000B6580FC963FFE000006F950263FD6CDA30 -:102CD00020DB30DC40DD50C4E0580EBCD2A0D10F68 -:102CE0008A152B2104580E5B232466286010981740 -:102CF00063FF2100DA20580FBC63FFABC858DB30FC -:102D0000DA20580EA12A210265AF9CC09409A902BD -:102D100029250263FF91DB30DC40DD50C0A32E0A81 -:102D2000802A2468DA20580EA9D2A0D10FC020D161 -:102D30000FDA202B200C580FC563FF6B6C10042892 -:102D40002006C062288CF8658125C050C7DF2B2281 -:102D50001BC0E12A206B29212300A104B099292559 -:102D600023B1AA00EC1A0BC4010A0A442A246B04FA -:102D7000E4390DCC030CBB012B261B6440692920D0 -:102D80000C1BE70B0C9A110BAA082FA2861BE70954 -:102D90006FF9026000B60B9B0A2BB2A368B0082C37 -:102DA00022000BCC0C65C0A42BA2851DE72D64B0BE -:102DB0009B8C2B2421040DCC029CB08820C0C5081C -:102DC00088110C880298B1882A08441198B48F346D -:102DD00094B79FB5C0401EE6FE2DA2850E9E082525 -:102DE000E4CF2DDC282DA68529210209094C689401 -:102DF0001A689820C9402A210265A00B2A221E2B9E -:102E0000221D7AB10265A079C020D10F2C21236543 -:102E1000CFDE6000082E21212D21237EDBD52B2241 -:102E20001E2F221D2525027BF901C0B064BFC413EB -:102E3000E6DF2CB00728B000DA2003880A28824C8D -:102E4000C0D10B8000DBA065AFE763FFA62A2C741E -:102E5000C0B02C0A02580D951CE7039CA08B2008DB -:102E6000BB1106BB029BA1893499A263FF790000C4 -:102E7000262468DA20DB30DC40DD50580FE1D2A098 -:102E8000D10FDA202B200C580F58C020D10F000092 -:102E90006C1006073D14C080DC30DB40DA20C047F0 -:102EA000C02123BC30032838080842774001B1DD37 -:102EB00064815A1EE6BB19E6BC29E67ED30F6DDAA3 -:102EC0000500508800308CC0E0C02025A03C14E6EE -:102ED000BAB6D38FC0C0D00F87142440220F8940C8 -:102EE000941077F704C081048238C0F10B2810C019 -:102EF00044C02204540104FD3802520102FE380885 -:102F0000DD10821C07EE100E6E020EDD02242CFE78 -:102F1000C0E004FE380AEE100E88020D88028DAB68 -:102F20001EE6AA08D8020E880298B0C0E80428104D -:102F30000E5E0184A025A125084411084402052540 -:102F400014045511043402C0810E8E3994B18FAA35 -:102F500084109FB475660C26A11FC0F2062614606B -:102F60000009000026A120C0F20626140565020F04 -:102F7000770107873905E6100778100866020655BD -:102F80000295B625A1040AE611085811082802087E -:102F9000660296B7C060644056649053067E11C0C6 -:102FA000F489C288C30B340B96459847994618E6B6 -:102FB000919F410459110E99021FE68F020E470896 -:102FC000D80298420E99029F40C1E00E990299449E -:102FD0002FA00CB4380CF91114E67E1EE675A4FF80 -:102FE000AE992E928526F4CF0E880B289685D10FA8 -:102FF0002BA00C1FE66F1CE6760CBE11ACBBAFEE2F -:103000002DE28526B4CF0D3D0B2DE685D10FC08076 -:1030100005283878480263FEA263FE966C1006C04D -:10302000C06570F18830C030088714778712C0B04F -:10303000C0A619E661299022C030CC97C03160004B -:1030400003C0B0C0A6C0E0C091C0D4C08225203C5F -:103050000B3F109712831CC0700858010D5D0108CA -:103060009738C0800B9838077710048810086802DA -:10307000087702C0800D98382D3CFE0888100D9E00 -:10308000388D2B0AEE1008EE0207EE020CB8100F76 -:10309000DD02053B400EDD029D408920043D100805 -:1030A00099110D99022D210409A90208DD119941F8 -:1030B000872A05B9100D3D020ABB110DBB02087726 -:1030C0000297442821258712082814048811071E16 -:1030D0004007EE100E990275660926211F06261478 -:1030E000600006002621200626140868029B470976 -:1030F0008802984629200CD2C0C0800C9E111BE685 -:10310000341FE62BAB99AFEE2DE2852894CF0DADA1 -:103110000B2DE685D10FDD40C0A6C0B08E51CAE0B0 -:10312000B2AAB1BB2DDC108F500E783698100877FC -:103130000C9FD898D989538F52991199DB9FDA7EC9 -:103140008309B1CC255C10C97763FFCF88108D113E -:1031500008E70C9751AD8DD7F078DB01B1F79D539F -:1031600097528830C030088714088840648ED5652F -:10317000BEC963FEBC0000006C1004D720B03A88C2 -:1031800020C0308221CAA0742B1E2972046D080F42 -:10319000C980C9918575B133A2527A3B0B742B0853 -:1031A00063FFE900649FECD10FD240D10F00000013 -:1031B0006C1008D630C0709515DA408E3914E5FED3 -:1031C0009A1464E0026451FC2920062A9CF865A246 -:1031D0005F2A21020A0B4C65B21F2C320015E5F460 -:1031E00074C7052D212365D3242E529E1AE5F06F56 -:1031F000E80260021B2AA22668A0082B22000ABB54 -:103200000C65B20C2E529D1DE5EB64E2038B386415 -:10321000B22D9E16C8BC8D691EE5E864D0052EE06F -:10322000217BEB492E200C18E5E20CEF11A8FF29B9 -:10323000F286C186798B4A17E5DF07E70A2772A372 -:10324000687004882077893925F2856452A2272185 -:103250002E07B73607B90C6F9D01D7B089696E92FA -:103260004228203D7B873C8A15CDAF600018C1B253 -:103270008C202A200C580E90D5A064A2AC8B6863D9 -:10328000FFCBC05063FFC3C0E06000022E60030E9E -:103290009B0C6EB20EDC700CEA11AA6A2AAC285B99 -:1032A000FFB6D7A0DA20DB70C1C42D211F580E381D -:1032B0008C268B27D4A00CBB0C7AB3258A63C090D4 -:1032C0009A538862995898528F659F598E679E5B72 -:1032D0008D6697559D5A8B687B7B748B15CEB3603A -:1032E000000DDA20DB40580E0265A10D63FFCC0013 -:1032F000DA20DB308C14580DAAD6A0C0C0C0D19DF6 -:10330000152CA403DA20DB60DF70DC50C0E0256000 -:10331000039E101EE5C10C5D11AD6D2DDC285BFF19 -:103320003F8E66A5A88F67286403AF7F77FB01B146 -:10333000EE9E669F678D268C29A4DD0DCC0C9D2604 -:103340008B680C0C482C252507BB0C9B6863FEC3BF -:103350002C20668961B1CC0C0C472C24666EC60209 -:103360006000B809FD5065D0B2CBBF8E69CBEBDBF6 -:1033700060DC50DF70DA201EE5BC2D6003C0809851 -:10338000100CDD11AD6D2DDC285BFF248B15C942BF -:103390008A2629220904AA082A26060A990C09095C -:1033A0004829252565B13CC020D10F00DB602D6C7C -:1033B00028DF70DA20C0C01EE5AC9C10DC505BFE3C -:1033C000B463FFC7002D203D0D4D4065DDF96FE56D -:1033D00022DA308F456DE90C8EAA0E8E14C9E37E79 -:1033E000F3112AAC10C090292467090F4764FDD758 -:1033F00060014100C09163FFED00881565814CDAE2 -:1034000020DB608C14580D66C020C09029A403D125 -:103410000FDA20C0B6580DF463FFDE008A162B21A8 -:1034200004580C8CC0A02A24668B6863FF3A000005 -:10343000002B9CF965B0C5DA20580C9163FD910012 -:103440002B200C0CBA11A5AA2FA286C1C27FC302E1 -:103450006000FC0DB90A2992A36890078C2009CC62 -:103460000C65C0EB26A2856460E52C20668931B12D -:10347000CC0C0C472C24666FC60270960ADAE02B3F -:103480002104580C74272466893077974B18E55926 -:103490001DE55A8A328B33C0F42C2104099E400664 -:1034A000EE1104CC110ECC029F61C1E00ECC029D46 -:1034B000608F2B9A669B679C64976508FF029F62EA -:1034C0002F200C18E5430CFE11A5EE2DE285A8FF78 -:1034D00027F4CF2DDC202DE6858F1565F091C020D7 -:1034E000D10F00002A2C748B14580643D2A0D10FA0 -:1034F00000DA20DBE0580DBC63FEFE0000DA20DBC2 -:10350000308C148D15580E3ED2A0D10F00008815B6 -:10351000C888DA20DB30580C9C2A210265AEDAC05C -:103520009409A90229250263FECFDA202B200C582A -:103530000DC763FEC4272468DA20DB302C12042D6B -:1035400012052E0A80580CA163FC7C00C020D10F0C -:10355000DA20580DA58A15CDA1DA20033B022C12E2 -:1035600004580D0F27A403C020D10F00C020D10F95 -:103570002A2C748B14580620D2A0D10F6C100C2862 -:103580002102941008084C6583621FE50929F29E08 -:103590006F98026003661DE50529D2266890082A07 -:1035A000220009AA0C65A3542CF29D64C34E2B2063 -:1035B0000C0CB611AF66286286C1EC78E30260039A -:1035C0004619E4FC09B90A2992A36890078A2009E0 -:1035D000AA0C65A33224628564432CC0E12A310918 -:1035E000C07027246689359A11992A8836991298CD -:1035F0002B89379813992C883899140858149815E2 -:10360000982D89392A25042E251D29251C28302886 -:10361000C09228243C2A30290808479816098901B5 -:103620002A243D2A311599170A094109A90C299C18 -:10363000EC29251F7E87192D2A000DA06000083E69 -:10364000010A3EB1AD08DA390EAA110A990C2925F2 -:103650001F2A211F18E5060A8160C1D0941A951B04 -:1036600001083E00053EB184054839843C259CFC98 -:103670000D883629201408AA1C8D3D2726182E26D1 -:10368000132E26142E261527261B2E246B2724677F -:1036900027246808581C0909432924142932112AAF -:1036A000252E28252F27252427252527252C2725A6 -:1036B000232525202425212D2522841A2D211C8512 -:1036C0001B6FD202600209C0A099186D080AB1AA46 -:1036D00000A10400E91A7D9B0263FFEE8918C080F7 -:1036E000C0E1C070C0D29B1D951B961C9C1E16E4A9 -:1036F000D12C203D15E4E00C0B400DCC010BE7383C -:103700001DE4C30A77100CE8380B8810C0C49C4134 -:103710000877029D40B0A80988118B209C499D48DC -:10372000954B9643087702861418E4D115E4B9083E -:10373000770205BB029B4A9B429746881287110875 -:10374000DA149A4E0D88100D77110877021AE4AC3E -:1037500006D8140D6610087702974FC78F984D98BA -:103760004C9845871598440715140D55110A5502B4 -:10377000954715E4C18A262D46102D46182D462062 -:103780002C46112C46192C46212B46122B461A2862 -:1037900046142846152B46228816254624254626FB -:1037A0008B170A0C48090D4885130EDD1105CC1145 -:1037B0000839400BEB390299101EE4B00DCC020D14 -:1037C0005511082D400655022E461316E47B0FDDD9 -:1037D00011254616080840851B0188100DBB02867E -:1037E000671DE4A70988020CBB0219E4771CE4A555 -:1037F0002B46172D461BA7661BE4A4C0702C461C45 -:103800000988028C1E28461E2B4623C0908B1D293A -:10381000461D29461F18E49D29462728462529319B -:10382000162E200629246A243117962D2425238656 -:103830001CCCE1272407C0D7090E4064E0829A29F6 -:1038400009284164809164409B2D2406C098094951 -:1038500036280AA024628501C404A844282104242F -:1038600066850888118E3F8A3E2D32100EA41800FE -:10387000C4040EAE1800EE110ACA530EDD02C0E3F6 -:103880000E880298C11EE48209084E9EC08E2094C4 -:10389000C398C59DC418E44E1DE47F05EE110EAA21 -:1038A000020DAA02A8B82784CF9AC21EE44024F2CF -:1038B0009D27E4A2244C1824F69D655052C020D1C7 -:1038C0000F2D2406C0A0C09809493604A93863FF0B -:1038D0007FC0A063FE070000654F6DC098C0A82A96 -:1038E000240663FF6B2D2406C09063FF63CC57DA78 -:1038F00020DB308C10580C2AC020D10F00DA20C0F9 -:10390000B6580CB963FFE500DA20580CB763FFDC4A -:103910002A2C748B10580538D2A0D10F6C100628B1 -:1039200020068A336F8202600161C05013E42029AF -:10393000210216E41F699204252502D9502C201576 -:103940009A2814E41D8F2627200B0AFE0C04770901 -:103950002B711C64E1398E428D436FBC0260016F94 -:1039600000E104B0C800881A08A80808D8029827FF -:103970002B200668B32ECE972B221E2C221D011160 -:10398000027BC901C0B064B0172CB00728B000DAC0 -:103990002003880A28824CC0D10B8000DBA065AFD1 -:1039A000E7C020D10F2D206464DFCA8B29C0F10B42 -:1039B000AB0C66BFC02B200C0CBC11A6CC28C28659 -:1039C0002E0A0878EB611EE3FB0EBE0A2EE2A36806 -:1039D000E0052822007E894F29C2851EE4076490F5 -:1039E000461FE4159E90C084989128200A95930F55 -:1039F000880298928E200FEE029E942F2007882630 -:103A00002F950A98969A972E200625240768E34357 -:103A10002921022AC2851DE3EE2AAC20ADBD25D4A2 -:103A2000CF2AC68563FF4E002E2065CBEDC08228CD -:103A30002465C9F605E4310002002A62821BE3F71F -:103A40002941020BAA022A668209E4312921026374 -:103A5000FF23000064DFB88F422E201600F1040D12 -:103A6000EE0C00EE1AAEAE9E2963FFA38A202B3225 -:103A700021B1AA9AB0293221283223B499293621BA -:103A80007989A92B32222B362163FFA0C020D10FC8 -:103A90009F27252415ACB828751C2B2006C0C12EE5 -:103AA000BCFE64E0AB68B7772DBCFD65DEC72D209A -:103AB00064C0F064D0868E290EAE0C66E089C0F139 -:103AC00028205A288CFE08CF3865FEE863FF58008E -:103AD00000E0049310C0810AF30C038339C78F08F8 -:103AE000D80308A80108F80C080819A83303C80C63 -:103AF000A8B828751C030B472B24158310CBB700DF -:103B0000E104B0BC00CC1AACAC0CDC029C27659E76 -:103B10005EC0B20B990209094F29250263FE5000CD -:103B20002D206A0D2D4165DF7EDA20C0B0580C755E -:103B300064AF18C0F163FEEF9F2763FFD02E221FF2 -:103B400065EE3263FF79000028221F658E2763FF30 -:103B50006E252406252502C09063FE196C100665AB -:103B600071332B4C18C0C7293C18C0A1C08009A8CC -:103B7000380808426481101CE38A1AE38B2AC67E47 -:103B80002A5CFDD30F6DAA0500B08800908C894097 -:103B9000C0A00988471FE3B4080B47094C50090D22 -:103BA0005304DD10B4CC04CC100D5D029D310CBB70 -:103BB000029B3088438E2098350FEE029E328D2670 -:103BC000D850A6DD9D268E40C0900E5E5064E097D2 -:103BD0001CE39A1EE389038B0BC0F49FB19EB02DAA -:103BE000200A99B30CDD029DB28F200CFF029FB416 -:103BF0008E262D20079EB68C282DB50A9CB7292429 -:103C0000072F20062B206469F339CBB61DE36B2305 -:103C100020168DD20B330C00D10400331AB48DA3BF -:103C2000C3932922200C13E36A1FE3610C2E11AF0A -:103C3000EEA3222924CF2FE285D2A00FDD0B2DE6A3 -:103C400085D10F002E200CB48C0CEB111FE3611DED -:103C5000E358AFEEADBB22B28529E4CF02C20B22FE -:103C6000B685D2A0D10F00002E200C1CE3511FE31B -:103C7000580CEB11AFEEACBB22B28529E4CF028227 -:103C80000B22B685D2A0D10FC0D00BAD387DC802B3 -:103C900063FEEC63FEE08E40272C747BEE12DA703C -:103CA000C0B32C3C18DD50580A7B8940C08063FEAD -:103CB000E3DE60DA20DB30DC40DD505800059A108E -:103CC000DB50077A0258044C881063FEF8000000AD -:103CD0006C100692121EE3428C40AE2D0C8C472EC7 -:103CE0003C1804CA0BD9A07DA30229ADF875C30204 -:103CF000600084C0B0C023C0A09D106D0844B89F70 -:103D00000EB80A8D900EB70BB8770D6D36ADAA9D23 -:103D1000800D660CD8F000808800708C879068B1A8 -:103D200024B22277D3278891C0D0CB879890279C44 -:103D30001000708800F08C9D91CB6FC08108BB0390 -:103D400075CB3663FFB4B1222EEC1863FFD4859295 -:103D50000D770C86939790A6D67D6B01B1559693FF -:103D60009592600016B3CC2D9C188810D9D078D3CA -:103D7000C729DDF863FFC100C0238A421BE3470067 -:103D8000CD322D44029B3092318942854379A10581 -:103D90001EE3430E550187121BE334897095350BE2 -:103DA0009902993288420A880C98428676A6A6968D -:103DB000768F44AFAF9F44D10F0000006C10089382 -:103DC00011D6308830C091086351080847059838EB -:103DD0009812282102293CFD08084C6581656591EF -:103DE000628A630A2B5065B18B0A6F142E0AFF7C1E -:103DF000A60A2C205ACCC42D0A022D245A7FE00298 -:103E0000600215892888261FE32609880C65820F21 -:103E10002E200B0FEE0B2DE0FE2EE0FF08DD110E25 -:103E2000DD021EE320AEDD1EE3201CE3200EDD01DB -:103E30000DCC37C180084837B88DB4889810896098 -:103E40001AE2DE7B96218B622AA0219C147BA317A9 -:103E50009D132A200C8B108C20580B978C148D13DB -:103E6000DBA0CEAC6001C4002E200C1BE2D10CEA1A -:103E7000110BAA082BA2861FE2CF7BDB3B0FEF0AB8 -:103E80002FF2A368F0052822007F892C2BA28564DD -:103E9000B0AA87628826DE700C7936097A0C6FAD7D -:103EA0001C8F279B1508FF0C77F3197E7B729D13DF -:103EB0009C149B15CF56600025C0B063FFD0D790EF -:103EC00063FFDD00009D139C14DA20DB70580B08A3 -:103ED0008B158C148D1365A06A8E6263FFCC00DA9B -:103EE000208B11DC40580AAED6A08B15C051DE7075 -:103EF000DA20DC60DD405BFF768D138C14D9A02EB8 -:103F0000200C1BE2AB1FE2B20CEA11AFEFC0E0AB3A -:103F1000AA2BA2852EF4CF0B990B29A68563FF1D32 -:103F200000DA20DC60DD40DE708912282007DF50D7 -:103F3000A9882824075BFF09D2A0D10F00DBE0DAB3 -:103F400020580B296550EF2A20140A3A4065A0EB4F -:103F5000DB60DC40DD30022A0258099CD6A064A058 -:103F6000D584A183A0040447030547951203635138 -:103F7000C05163FE5C2C2006D30F28CCFD6480A5C5 -:103F800068C704C0932924062C2006C0B18D641F85 -:103F9000E28A9D279D289D298FF29D2600F104002D -:103FA000BB1A00F004B0BE0EDD01C0F0ADBB8D65E4 -:103FB0002F24070D0E5E01EE11AEBB2E0AFEB0BB24 -:103FC0000B0B190EBB36C0E20B0B470EBB372B2475 -:103FD0001618E2820A09450D0B422B240B29240AEC -:103FE000B4BE2E240C7D88572920162FCCFDB09D01 -:103FF0000A5C520DCC362C246465FDEC0C0C476435 -:10400000CDE618E26D8E2888820C9F0C008104009A -:10401000FF1AAFEE9E2963FDCF1CE29C63FE1300E6 -:104020001CE29363FE0C8D6563FFA500DA202B2054 -:104030000C580B06645F0FC020D10F00C020D10FB9 -:10404000C093292416C09363FFA000006C1004C025 -:104050006017E2561DE259C3812931012A3008292F -:10406000240A78A108C3B27BA172D260D10FC0C16B -:104070006550512625022AD0202F200B290AFB2B20 -:1040800020142E201526241509BB010DFF0928F147 -:104090001C2B2414A8EE2EF51C64A0B52B221E2880 -:1040A000221D0111027B8901DB6064B0172CB0076F -:1040B00028B000DA2007880A28824CC0D10B800083 -:1040C000DBA065AFE7DB30DC40DD50DA205800D8FC -:1040D000292102090B4CCAB2D2A0D10F00CC5A2C14 -:1040E00030087BC1372ED02064E02D022A02033B2A -:1040F00002DC40DD505800CED2A0D10F2B2014B0EE -:10410000BB2B24140B0F4164F0827CB7CAC0C10CD6 -:104110009C022C2502D2A0D10FC020D10F2E200648 -:1041200069E2C12F21020F0F4C69F1B8262406263F -:1041300025022B221E28221D2A200B2920150DAA1C -:10414000092CA11C262415AC9929A51C7B814A6049 -:104150000049B0BB2B24140B0D41CBD67CB7022CED -:1041600025022B221E2E221D7BE9022B0A0064B0A1 -:10417000172CB00728B000DA2007880A28824CC024 -:10418000D10B8000DBA065AFE7C020D10F2624064D -:10419000D2A0D10F26240663FFC7DB601DE20764AF -:1041A000BF422CB00728B000DA2007880A28824CCA -:1041B000C0D10B8000DBA065AFE71DE1FF63FF24EA -:1041C0006C1004282006C0646F8564CA5B29201423 -:1041D0007D9726DA20DB30DC40055D025800192986 -:1041E0002102090A4CC8A3C020D10F00C0B10B9B0B -:1041F000022B2502C020D10F0000022A02033B023D -:104200002C0A015800CAC9AADA20DB30DC40580960 -:10421000E429A011D3A07E97082C0AFD0C9C012C48 -:10422000A411C0512D201406DD022D241463FFA219 -:10423000DA20DB30DC40DD50C0E0580964D2A0D188 -:104240000F0000006C100616E1DA1CE1DA65513B44 -:10425000C0E117E1D62821028B2008084C65807B3D -:104260002932000969516993722A629E6EA8482A10 -:10427000722668A0027AB93F2A629DB44FCBA72B61 -:10428000200C0CBD1106DD0828D28678FB150CBF6A -:104290000A2FF2A368F00488207F89072DD285D3E6 -:1042A0000F65D0602A210419E202D30F7A9B1DDA30 -:1042B00020580864600024002C21041BE1FD7CBB15 -:1042C00013DA20C0B658085FC9536000EFDA2058EF -:1042D0000A46600006DA20C0B6580A436550DDDCA5 -:1042E00040DB308D30DA200D6D515808B8D3A06412 -:1042F000A0CA1CE1B0C05184A18EA00404470E0ED8 -:104300004763FF50002B2104C08C8931C070DF70DF -:1043100009F950098F386EB8172C2066AECC0C0CFA -:10432000472C24667CFB099D105808CA8D10272451 -:104330006694D11EE1B6B8DC9ED0655056C0D7B8A1 -:104340003AC0B1C0F00CBF380F0F42CBF119E19465 -:1043500018E19628967EB04BD30F6DBA0500A08861 -:1043600000C08C2C200CC0201DE19A0CCF11A6FFA0 -:104370002EF285ADCC27C4CF0E4E0B2EF685D10F75 -:10438000C0800AB83878D0CD63FFC1008E300E0EE1 -:104390004763FEBD2A2C742B0A01044D025808BD48 -:1043A0002F200C12E18B0CF911A699A2FF27F4CF54 -:1043B000289285D2A008480B289685D10FC020D11D -:1043C0000F0000006C1004C060CB55DB30DC4005F2 -:1043D0005D02022A025BFF9B29210209084CC88268 -:1043E000D2A0D10F2B2014B0BB2B24140B0C41CB2B -:1043F000C57DB7EBC0C10C9C022C2502D2A0D10F09 -:104400000000022A02033B02066C02C0D0C7F72E4E -:10441000201428310126250228240A0FEE012E241B -:104420001458010D63FFA300262406D2A0D10F006B -:104430006C1006282102D62008084C65809D2B2090 -:104440000C12E15B0CB811A2882A8286B5497A93D6 -:104450000260009719E15809B90A2992A3689008E7 -:104460002A620009AA0C65A0822882851CE1636487 -:1044700080799C80B887B14B9B819B10655074C03C -:10448000A7D970280A01C0D0078D380D0D42CBDEA8 -:104490001FE1441EE1452EF67ED830D30F6D4A054C -:1044A00000808800908C2E3008C0A000EE322E7460 -:1044B0000028600C19E1470C8D11A2DDA988C020ED -:1044C0002CD2852284CFD2A00CBC0B2CD685D10F48 -:1044D000C0F0038F387FA0C063FFB400CC582A6CB3 -:1044E00074DB30DC405807F1C020D10FDA60580986 -:1044F000BE63FFE7DD402A6C74C0B0DC705808650D -:104500002E30088B1000EE322E740028600C19E15A -:10451000300C8D11A2DDA988C0202CD2852284CF39 -:10452000D2A00CBC0B2CD685D10F00006C10042936 -:104530002014282006B199292414688124C0AF2CA6 -:104540000A012B21022C24067BA004C0D02D2502B9 -:10455000022A02033B02044C02C0D05800BFD2A082 -:10456000D10FC020D10F00006C1004293101C2B45A -:1045700029240A2A3011C28378A16C7BA169645076 -:10458000472C2006C0686FC562CA572D20147CD7FF -:1045900022DA20DB30DC40DD505BFFA52921020957 -:1045A0000E4CC8E2C020D10FC0F10F9F022F250290 -:1045B000C020D10FDA20DB30C0C05BFFDC28201424 -:1045C00006880228241463FFC72920151BE0FB2A54 -:1045D000200BC0C09C240BAA092BA11C2C2415ABBA -:1045E0009929A51C63FF9900C020D10FDA20DB3088 -:1045F000DC40DD50C0E0580875D2A0D10F000000AB -:104600006C1004CB5513E0F625221F0D46110655FC -:104610000CA32326221E25261F06440B24261E73C8 -:104620004B1DC852D240D10F280A80C04024261FFB -:10463000A82828261E28261DD240D10FC020D10F21 -:10464000244DF824261E63FFD80000006C100428B7 -:104650002006D6206E85026000DE17E0D51DE0DC66 -:1046600019E0D5C0C1C0202A8CFC64A1322B6102A4 -:10467000B44E0B0B4C65B0A82B600C2A62000CB832 -:10468000110788082F828609B90A7FE30260009F1C -:104690002992A368900509AA0C65A09328828564D5 -:1046A000808DB8891BE0DA94819B8065514DC0B73D -:1046B000B838C0A1C0E009AE380E0E4264E0481A16 -:1046C000E0B81FE0B92FA67EB04A6DAA0500808829 -:1046D00000908CC0A02E600C0CE811A7882F82855A -:1046E000ADEE0F4F0B2F86852B600622E4CF68B10D -:1046F0002A296015C0B2C99AD2A02D61022B640686 -:104700000CDD022D6502D10FC0E008AE387EB0B7D7 -:1047100063FFAB00226406D2A0D10F00D2A0D10F5C -:1047200000CC57DA60DB30DC4058089DC020D10F48 -:10473000DA6058092D63FFE80028221E29221D781F -:104740009902280A00C176C1C1C1D21BE0A5C124CB -:10475000AB6B6480437891402A80000CAF0C64F00E -:10476000AE0DAE0C64E0A802AF0C64F0A207AE0C74 -:1047700064E09C2FACE864F0962EACE764E0902FE8 -:10478000ACE664F08A2A800708A80B088A027B83BB -:10479000022A8DF8D8A065AFBBC0906000730000FE -:1047A0002B600C0CB811A7882E82866EE87909BAA6 -:1047B0000A2AA2A368A0048E607AE96B2A82856423 -:1047C000A0651FE08DC0E32E64069EA19FA01FE0A0 -:1047D000B92E600A92A30FEE029EA28E600FEE0227 -:1047E0009EA42F60147AFF4722A417ADBE2F8285A6 -:1047F00022E4CF2FFC182F868563FE702A6C74C0CC -:10480000B1DC90DD405807A31DE072C0C163FEC457 -:10481000D9A0DA60DB30DC40DD50C2F0C1E009FE37 -:10482000395807EAD2A0D10FDA605808EF63FEF0DA -:104830002CA4170DBE0829828522E4CF299C1829B3 -:10484000868564500C2A6C74044B0258016BD2A00C -:10485000D10FC020D10F00006C10062B221E282281 -:104860001D93107B8901C0B0C0C9C03BC1F20406D2 -:10487000401DE05BC0E2C0740747010E4E01AD2D44 -:104880009E11C0402E0A1464B06E6D084428221D8B -:104890007B81652AB0007EA13B7FA1477B51207CB4 -:1048A000A14968A91768AA1473A111C09F79A10C26 -:1048B000C18B78A107C1AE290A1E29B4007CA12BA7 -:1048C0002AB0070BAB0BDAB07DB3022ABDF8DBA030 -:1048D000CAA563FFB428B01089116987BB649FB86B -:1048E00063FFDC00647FB463FFD50000646FD0C059 -:1048F00041C1AE2AB40063FFC62B2102CEBE2A22DC -:104900001D2B221E7AB12A8C107CB1217AB901C0EC -:10491000B0C9B913E026DA2028B0002CB00703880C -:104920000A28824CC0D10B8000DBA065AFE7D240E3 -:10493000D10F8910659FD463FFF300006C1008C08D -:10494000D0C8598C302921020C0C4760000C8E30E5 -:104950000E1E5065E19E292102C0C116E015090B0B -:104960004C65B0908A300A6E5168E3026000852F72 -:10497000629E1BE00E6EF8532BB22668B0052E2205 -:10498000007BE94727629DB748CB7F97102B200C0F -:10499000B04E0CBF11A6FF29F2869E12798B4117EB -:1049A000E00507B70A2772A368700488207789306A -:1049B00029F285DF90D7906590652A210419E03CA3 -:1049C0007A9B22DA2058069F600029002C21041BC4 -:1049D000E0387CBB18DA20C0B658069AC958600186 -:1049E0004CC09063FFCCDA2058087F600006DA20C4 -:1049F000C0B658087D655135DC40DB308D30DA209B -:104A00000D6D515806F2C0D0D3A064A12029210217 -:104A1000C05184A18CA00404470C0C4763FF3E00E6 -:104A2000C09C8831DBD008F850089B3828210498B6 -:104A3000116E8823282066AC8C0C0C472C24667CD5 -:104A4000BB159F139E148A108B115807028E148F6A -:104A500013C0D02D24668A30C092C1C81BDFEC7F02 -:104A6000A6099BF099F12CF40827FC106550A4B816 -:104A70003ADF70C051C08007583808084264806728 -:104A800018DFC819DFC929867E6A420AD30F6DE98B -:104A90000500A08800F08CC0A08930B4E37F962880 -:104AA000C0F207E90B2C94089B909F912F200C12C9 -:104AB000DFC80CF811A688298285A2FF2DF4CFD279 -:104AC000A009330B238685D10F22200C891218DF11 -:104AD000C00C2B11A6BBA8222D24CF2CB285D2A0AE -:104AE0000C990B29B685D10FC087C0900A59387927 -:104AF000809663FF8ADB30DA20C0C1C0D05BFF56EE -:104B0000292102C0D02A9CFE65AE4D2D2502C09001 -:104B100063FE45009E142A2C74C0B1DC70DD405841 -:104B200006DD8E14C0D01BDFB9C1C863FF6AC02088 -:104B3000D10F00006C100628210216DF9D08084CDA -:104B400065821929629E6F980260022019DF9829F8 -:104B500092266890078A2009AA0C65A20F27629DF9 -:104B6000C0CC6472072B21048E31C0A0DDA00EFEE4 -:104B7000500ECD386EB8102C2066B1CC0C0C472CE2 -:104B800024667CDB026001EFC0C12930081BDF8A8C -:104B900064909C2F0AFFC0D3B09E64E10268921318 -:104BA0006450882A2C74044B025800930AA202060F -:104BB000000000002B200C2721040CBC11A6CC29DE -:104BC000C286280A087983026001B919DF7A09B917 -:104BD0000A2992A36890082E220009EE0C65E1A430 -:104BE0002EC28564E19E26200713DF836E7B026060 -:104BF000019A17DF7A1FDF8319DFB0C0D228200A9D -:104C000093E09DE1A9690F880298E22F90802A9491 -:104C100080B1FF07FF029FE32EC2851FDF6D0EDE0E -:104C20000BAFBF2AF4CF2EC685655F76C020D10FAB -:104C30002830102930112E301300993200ED3264E3 -:104C400080EE2A30141FDF9D00AA3278EF050F9EF8 -:104C5000092DE47F1EDF9B66A0050F98092A84803A -:104C6000B4A718DF98C76F009104AE9EDDE000AFD7 -:104C70001A00C31A6EE1052DB2000DED0C1EDF9275 -:104C800008D81C063303AE882A848B2EB02E2784C6 -:104C90008C03EE010FEE022EB42E58018F63FEFF3F -:104CA0002931082925042830142E3109B088648060 -:104CB000A32E240AC0812E30162CB4232E240BB42C -:104CC000EF2F240C8C378B36292504DEB0DFC00C87 -:104CD0008F390B8E390FEE0264EEC4089F1101C4A8 -:104CE000048D380CB81800C4040CBE1800EE110E68 -:104CF000DD02C0E30EFF021EDF669F719E701EDFA5 -:104D0000658F2098739D7405FF110BCD53C180985A -:104D1000750FDD020EDD029D721EDF242A24662F30 -:104D2000629D2AE4A22FFC182F669D63FE7100008D -:104D3000002F30121BDF6600FA3278FF050B980B4C -:104D40002A847F66D0050B9A0B2DA4802A3011008F -:104D5000AA3263FF442F240A9E2B63FF56CC57DAF6 -:104D600020DB30DC4058070EC020D10F00DA20C015 -:104D7000B658079D63FFE500DA70580636C0A02AD2 -:104D8000246663FE02DA2058079863FFCFB16928D2 -:104D9000200A8620090947991129240798107F8144 -:104DA0002693E027E50A9AE388109DE119DF428DFA -:104DB00011096F029FE42DE416098802C0D398E21E -:104DC0002A240763FE5100001DDF0B0868118F11B4 -:104DD000892B93E008FF02C08F9FE50D990299E2AD -:104DE000047F11C0D49DE108FF029FE463FFD0005F -:104DF0006C1004C020D10F006C100485210D3811F7 -:104E000014DEE98622A42408660C962205330B934F -:104E100021743B13C862D230D10FC030BC29992114 -:104E200099209322D230D10F233DF8932163FFE3E1 -:104E30006C100AD620941817DEDED930B8389819CD -:104E40009914655252C0E1D2E02E61021DDEDB0EE4 -:104E50000E4C65E1628F308E190F6F512FFCFD658E -:104E6000F1558EE129D0230E8F5077E66B8F181EF7 -:104E7000DF18B0FF0FF4110F1F146590CE18DF1567 -:104E80008C60A8CCC0B119DEC928600B09CC0B0D11 -:104E9000880929811C28811A2A0A0009880C08BA65 -:104EA000381BDF0B0CA90A2992947B9B0260008CB3 -:104EB0002B600C94160CBD11A7DD29D286B8487959 -:104EC00083026000D219DEBB09B80A2882A39817B2 -:104ED0006880026000A36000A51ADEFF84180AEE55 -:104EE00001CA981BDEB28C192BB0008CC06EB313B4 -:104EF0001DDEAF0C1C520DCC0B2DC295C0A17EDB6C -:104F0000AE6000380C0C5360000900000018DEF1A0 -:104F10008C60A8CCC0B119DEA528600B09CC0B0DA4 -:104F2000880929811C28811A2A0A0009880C08BAD4 -:104F3000380CA90A2992947E930263FF72DA60C04A -:104F4000BA58072964507360026600001ADE988C14 -:104F5000192AA0008CC06EA31A18DE940C1C5208EB -:104F6000CC0B18DEDB2BC295C0A178B30263FF3FE8 -:104F700063FFC9000C0C5363FF09896078991829F5 -:104F8000D285C9922B729E1DDE896EB8232DD22642 -:104F9000991369D00B60000DDA6058071360001791 -:104FA0000088607D890A9A1A29729D9C129915CFF2 -:104FB00095DA60C0B658070C6551F58D148C18DB76 -:104FC000D08DD0066A020D6D51580580D3A09A1479 -:104FD00064A1DD82A085A1B8AF9F19050547020233 -:104FE000479518C05163FE602B6104C08C8931C0A5 -:104FF000A009F950098A386EB81F2C6066A2CC0C43 -:105000000C472C64667CAB119F119E1B8A155805BA -:10501000918E1B8F11C0A02A64669F1164F0E12954 -:1050200012032812096DF9172F810300908DAEFE2F -:105030000080889F9200908C008088B89900908CA6 -:1050400065514E8A10851A8B301FDE6B88122960DD -:105050000708580A2C82942D61040ECC0C2C8694DF -:105060006FDB3C1CDE95AC9C29C0800B5D50A29987 -:1050700009094729C48065D0DA2E600CC0D01FDE34 -:10508000540CE811AFEEA7882282852DE4CF0242AE -:105090000B228685D2A0D10F8E300E0E4763FDA65F -:1050A000A29C0C0C472C64077AB6CD8B602E600A4C -:1050B000280AFF08E80C64810E18DE7E831682132E -:1050C000B33902330B2C34162D350AC02392319F8D -:1050D00030C020923308B20208E80292349832C0FD -:1050E000802864072B600CD2A01CDE390CBE11A7EF -:1050F000EE2DE285ACBB28B4CF0D9D0B2DE685D1FE -:105100000F8B1888138D30B88C0D8F470D4950B414 -:10511000990499100D0D5F04DD1009FF029F800DA9 -:10512000BB029B8165508D851AB83AC0F1C0800CD6 -:10513000F83808084264806B1BDE1A19DE1B29B69A -:105140007E8D18B0DD6DDA0500A08800C08CC0A08F -:1051500063FEF30082138B161DDE2B28600AC0E06D -:105160002EC4800D880202B20B99239F20C0D298D2 -:10517000229D2122600CB2BB0C2D11A7DD28D28507 -:1051800008BB0B18DE132BD685A8222E24CFD2A065 -:10519000D10F9E1B851A2A6C748B185BFF178E1B10 -:1051A00063FEA300C087C0900AF93879809263FF3C -:1051B00086C020D10F9E1B2A6C74C0B18D18580573 -:1051C000358E1B851A63FE7E886B8213891608BE96 -:1051D000110ECE0202920B9E25B4991EDE069F2070 -:1051E0000E88029822C0EF04D8110E88029824C0BD -:1051F000E49E21C080D2A02B600C2864071CDDF443 -:105200000CBE11A7EE2DE285ACBB28B4CF0D9D0BD3 -:105210002DE685D10F0000006C1004C020D10F00D6 -:105220006C10048633C071C030600001B1330031AE -:105230000400741A0462017460F1D10F6C1004024E -:105240002A02033B025BFFF61CDDDC1BDE24C79F4A -:1052500088B009A903098A019AB079801EC0F00FAD -:10526000E4311DDDD30002002BD2821EDE1D2AC1D7 -:10527000020EBB022BD6820AE431D10F28C102C133 -:105280009009880208084F28C50208E431D10F00B0 -:105290006C1004C0C00CE43112DDC81ADDC5000278 -:1052A0000029A28218DE111BDE0F2621020B9901B4 -:1052B00008660129A68226250206E43114DE0C15B3 -:1052C000DE07236A902326128550242611252613F3 -:1052D000222C40D10F0000006C1008D6102B0A645D -:1052E000291AB41ADDB20D23111CDDB30F2511B834 -:1052F0001898130E551118DDFEAC55A838AA332C9A -:1053000080FF2A80FEA933288D0129800108AA1177 -:105310002880000CAA0208881109880208AA1C2803 -:105320008C0828160458084C14DDA40AA70224414E -:10533000162A30802B120407AA28580847B1338B4D -:1053400013B4559A6004AC28B4662C56277B69E0E8 -:1053500016DDDB9412C050C0D017DD979D15D370B9 -:10536000D4102F60802E60829F169E178816728937 -:105370001A8D128C402A607F0DCC282B3A200CAA63 -:1053800028580835C0B10ABE372E35408F1772F93C -:105390001A8D128C402A60810DCC282B3A200CAA41 -:1053A0002858082DC0B10ABE372E3542B233B44456 -:1053B000B1556952B6B466C0508F15B877D370B284 -:1053C000FF9F156EF899D10F6C1004C021D10F000A -:1053D0006C1004270A001CDD761FDD871EDD8A1D88 -:1053E000DD731ADDB51BDDC3C02824B0006D2A753E -:1053F000AA48288080C09164806100410415DD6E58 -:10540000C03125502E00361A0655010595390C5627 -:10541000110C66082962966E974D0D590A2992243F -:1054200068900812DDA702420872993B2362951228 -:10543000DD6BCB349F300282020E4402C092993160 -:1054400094329233AD52246295C090244C1024665D -:105450009524B0002924A0AA42292480B177B14420 -:1054600004044224B400D10FD10FD10F6C10041AE0 -:10547000DD4F2AA00058021C5BFFD5022A02033B25 -:10548000025BFFD11BDD4DC9A12CB102C0D40DCCF4 -:10549000020C0C4F2CB5020CE431D10FC0A00AE471 -:1054A0003118DD430002002F828219DD562EB10231 -:1054B00009FF022F86820EE431D10F006C1004C068 -:1054C0002002E43114DD3D16DD3A00020022628242 -:1054D000234102732F0603E431C020D10F19DD8769 -:1054E0001ADD862841020A2A010988012A668228D3 -:1054F000450208E43115DD7D12DD8225461DD10F00 -:105500006C1004292006289CF96480A02A9CFD6563 -:10551000A0968A288D262F0A087AD9042B221FC824 -:10552000BD2C206464C0812E22090EAE0C66E0788A -:105530002B200C1EDD1F0CBC11AECC28C28619DD41 -:105540001D78F3026000AD09B90A2992A36890089A -:105550002E220009EE0C65E09B29C2851FDD276421 -:1055600090929F90C0E41FDD349E9128200AC0E0F5 -:105570009E930F8802989288200F880298942F207B -:10558000079A979D962F950A2E24072820062920F2 -:105590006468833328C28512DD0E288C20A2B22EC7 -:1055A00024CF28C685C020D10FC020D10F2A206A61 -:1055B0000111020A2A4165AF52DA20C0B05805D164 -:1055C00064AFE5C021D10F00649FC81FDCFB2D2014 -:1055D000168FF209DD0C00F10400DD1AADAD9D2936 -:1055E00012DCFC28C285A2B22E24CF288C2028C62B -:1055F00085C020D10FC021D10F0000006C100426FF -:105600000A001BDD4015DCEC28206517DCE9288C3E -:10561000FE6480940C4D110DBD082CD2F52BD2F4F4 -:105620002ED2F77CB13DB4BB2BD6F47BE9052BD24F -:10563000F62BD6F47CB92C2AD2F62AD6F52AD6F443 -:1056400006E4310002002872822AFAFF0041042990 -:105650000A012F510200991A0A9903098801287634 -:10566000820FE4312624652BD2F48E5A2CD2F5B069 -:10567000EE9E5A7BCB1629D2F62FD2F70CB80C0926 -:10568000FF0C08FF0C0F2F14C8F96000320BCA0C76 -:105690000A2A14CEA92B5102C0C20CBB020B0B4F1D -:1056A0002B55020BE431D10F00DB30DA205BFF9485 -:1056B0001BDD1564AF5D0C4D11ADBD63FFA800008F -:1056C00006E4310002002F728218DCD42E51020849 -:1056D000FF022F76820EE431D10F00006C1004C05F -:1056E0003003E43116DCB315DCB40002002462821E -:1056F00074472118DD05875A084801286682CD7352 -:1057000019DD030C2A11AA9922928329928472919D -:10571000038220CC292B51020BE431C020D10F0091 -:105720001FDCFC2E51020FEE012E55020EE431B0AB -:105730002DB17C9C5A12DCF708DD112D5619D10FC2 -:105740006C10061BDC9A1EDC9C22B0001ADCF36F86 -:1057500023721DDCDAC04818DCF21FDCF0DC10D547 -:10576000C083F000808600508A6D4A4F0F35110DBE -:1057700034092440800B560A296294B1330E55092E -:105780002251400F44110C440A874009A80C02889A -:105790003622514107883608770CA89929669497D4 -:1057A00040296295874109A80C0288360788360887 -:1057B000770CA8992966959741030342B1380808E8 -:1057C0004298F0D10F1CDCD713DCD827B00023326D -:1057D000B5647057C091C0D016DCD615DCD4C0407B -:1057E0002AC00003884328C4006D793C004104B1FD -:1057F0004400971A7780148E502FB2952DB695AF2E -:10580000EE2EED2006EE369E5060001877A009833C -:10581000509D5023B69560000223B295223D20068C -:10582000223622B695B455B8BBD10F000388432861 -:10583000C400D10F6C1004C04004E43115DCBE007C -:105840000200885013DCBDCB815BFFBD1CDCBC0CAF -:105850002D11ADCC2BC2822AC28394507BAB142E67 -:10586000C28429C2850ABD0C0E990C0D990C092918 -:10587000146000050BA90C092914993015DC4F2A76 -:1058800051020AE4312A2CFC58004B2B32000AA2A8 -:10589000022BBCFF9B30CCB6C8A4D2A0D10F000015 -:1058A00004E4311EDC430002002DE2822FBAFF2CFB -:1058B00051020FDD012DE6820CE431D10F00000012 -:1058C0006C1004D10F0000006C1004C020D10F0038 -:1058D0006C100413DC9BC0D103230923318DC0A0BD -:1058E0006F340260008D19DC321BDC3317DC940C42 -:1058F0002811A8772672832572822CFAFF765147E9 -:1059000088502E7285255C0425768275E9052572FE -:10591000842576827659292E72842E76822E76837D -:105920000AE4310002002392820021042FB1020018 -:10593000D61A0C66030633012396820FE4312672D1 -:105940008325728260000200D8A07659220AE431D1 -:1059500000020023928200210400D21A2FB1020C0F -:1059600022030232012296820FE431D280D10F004D -:10597000D280D10FC020D10F6C1004DB30862015EF -:10598000DC0B280A00282502DA2028B0002CB007FA -:1059900005880A28824C2D0A010B8000DBA065AF28 -:1059A000E61ADC040A4A0A29A2A3C7BF769101D1EC -:1059B0000F2BA6A3D10F00006C1004C0D1C7CF1BC2 -:1059C000DBFE19DBFB17DBF90C2811A87786758540 -:1059D00074C0A076516288508E77B455957475E97D -:1059E00003857695747659278F769F759F740AE4A0 -:1059F00031000200239282B42E2FB10200E1040094 -:105A0000D61A0C66030633012396820FE43186759D -:105A100083747639280AE4310002002E9282B4227F -:105A200000210424B10200DF1A0CFF030FEE012E47 -:105A3000968204E431D280D10FD8A07651D6D2809C -:105A4000D10F00006C1004290A801EDC001FDC004E -:105A50001CDBD80C2B11ACBB2C2CFC2DB2850FCC35 -:105A6000029ED19CD0C051C07013DBFC14DBFB182C -:105A7000DBF92AB285A82804240A234691A986B80E -:105A8000AA2AB685A98827849F25649FD10F000084 -:105A90006C100419DC2C0C2A11A9A98990C48479F2 -:105AA0008B761BDC1AABAC2AC2832CC2847AC16809 -:105AB0008AA02BBC30D3A064A05E0B2B0A2CB2A30F -:105AC00019DBE568C0071DDC20D30F7DC94AA92971 -:105AD000299D0129901F68913270A603D3A0CA9E08 -:105AE000689210C7AF2AB6A32A2CFC5BFFB3D23052 -:105AF000D10F000013DBC503A3018C311DDBB60CF5 -:105B00008C140DCC012CB6A363FFDC00C020D10F98 -:105B1000DA205BFFCCC020D10FC020D10F000000E5 -:105B20006C1004DB30C0D019DBA1DA202830002251 -:105B3000300708481209880A28824CDC200B8000B4 -:105B40001BDB9C0C4A11ABAA29A28409290B29A6AC -:105B500084D10F006C1004C04118DB9517DB970C43 -:105B60002611A727277030A866256286007104A336 -:105B70005500441A75414822628415DBB802320B85 -:105B8000C922882117DB940884140744017549054C -:105B9000C834C020D10FD10F0809471DDBEBC0B2BC -:105BA0008E201FDB820E0E43AFEC2BC4A00FEE0A3B -:105BB0002DE6242A6284C0200A990B296684D10F1D -:105BC000C020D10F6C1004DB30C0D018DB78DA2095 -:105BD00025300022300708580A28824CDC200B8030 -:105BE000008931709E121BDB720C4A11ABAA29A2EC -:105BF0008409290B29A684D10F09C95268532600AC -:105C0000910418DB6DC0A12F811200AA1A0AFF02AD -:105C10002F85121EDB670C4D11AEDD2CD2840C2CAF -:105C20000B2CD684D10FC0811FDB64B89A0A0A47B7 -:105C30002EF11200A10400881A08EE022EF5121DA2 -:105C4000DB5C0C4C11ADCC2BC2840B2B0B2BC68414 -:105C5000D10F00006C1004DB30C0D019DB54DA2007 -:105C600028300022300709880A28824CDC200B806B -:105C7000001CDB4F0C4B11ACBB2AB2840A2A0B2A46 -:105C8000B684D10F6C1004C04118DB4916DB4B0CF5 -:105C90002711A626266030A872252286006104A35B -:105CA0005500441A75410822228402320BD10F009C -:105CB000C020D10F6C100415DBA502491429561120 -:105CC0002452120208430F8811C073008104003669 -:105CD0001A008104C78F00771A087703074401066A -:105CE0004402245612D10F006C10066E230260008D -:105CF000AC6420A7C0A0851013DB7E16DB94C040E7 -:105D0000A6AA2BA2AE0B194164906668915D6892B9 -:105D10005268933C2AA2AA283C7F288C7F0A0A4D0D -:105D20002980012880002AACF208881109880275B0 -:105D300089462B3D0129B0002BB0010899110B9920 -:105D4000027A9934B8332A2A00B1447249B160000A -:105D50004A7FBF0715DB7F63FFB90000253AE86380 -:105D6000FFB10000253AE863FFA90000250A64633B -:105D7000FFA1C05A63FF9C0000705F082534FF0537 -:105D80008C142C34FE70AF0B0A8D142E3D012AE4C6 -:105D9000012DE400DA405BFD5063FFA7D10FD10F66 -:105DA0006C10041ADB0519DB021CDB6A1BDB6BC001 -:105DB00080C07160000D00000022A430B1AA299CAF -:105DC000107B915F26928679C2156E6262C0206D4B -:105DD000080AB12200210400741A764BDB63FFEE3F -:105DE0002292850D6311032514645FCFD650032DD5 -:105DF000436DD9039820B4220644146D492298209B -:105E000098219822982398249825982698279828AE -:105E10009829982A982B982C982D982E982F222CD8 -:105E20004063FF971EDAE327E68027E681D10F0063 -:105E3000C02063FF830000006C1004C062C04112E8 -:105E4000DADE1ADADA13DB452AA00023322D19DB59 -:105E50003F2BACFE2992AE6EA30260008E090E406D -:105E60002D1AC2C2CD0EDC392C251664B0895BFF19 -:105E70009E15DB3B1ADAE52B3AE80A3A015805761B -:105E80002B21160ABB28D3A02B560058058D8B500A -:105E90000ABB082A0A0058058C15DB322D21022C7A -:105EA0003AE80C3C2804DD022D25029C505805845C -:105EB0008B50AABBC0A15805841CDB2B2D21020CE2 -:105EC0003C2806DD0213DB292D25029C3058057C79 -:105ED0008B30AABBC0A258057C2A2102C0B40BAAF1 -:105EE000020A0A4F2A2502580590D10F242423C301 -:105EF000CC2C251663FF760018DB211CDB1D19DB7B -:105F00001E1BDB1C17DAF085202E0AFD1FDB1D2D62 -:105F1000202E24F47A24F47E24F4820EDD0124F46D -:105F2000862E0AF707552806DD02C0750EDD01052D -:105F30000506AB5BA959C0E8AC5C24C4AB0EDD021E -:105F400027C4AC2E0ADFA85527B4EC0EDD0124B41B -:105F5000EBC2E027942C0EDD0224942B2E0A800D38 -:105F60000D4627546C24546B0EDD022D242E63FE47 -:105F7000FC0000006C10042A0A302B0A035BFF4D62 -:105F800012DAF3C390292616C3A1C0B3C08A28260B -:105F9000175BFF48C03CC3B12B26161ADA872AA02C -:105FA0002023261764A079C3A2C0B15BFF42C3A21D -:105FB000C0B15BFF40C3C22C2616C2AFC0B12326BE -:105FC000175BFF3CC28F282616C0FE2F2617C2E2A1 -:105FD0002E26162A0AA1C0B1C0D82D26175BFF3580 -:105FE0002A0AA12A2616C3A6C0B3C1922926175B86 -:105FF000FF31C3C62C2616C1B32A0AA22B2617C00E -:10600000B35BFF2C290AA2292616C185282617C2B0 -:10601000FB2F2616C0E72E26171DDADA2D2610D103 -:106020000FC3A2C0B35BFF2363FF82006C10041C8C -:10603000DAA41BDA9118DAD417DAD516DAD515DA1C -:10604000D5C0E0C0D414DAA01FDA5CC0288FF06D90 -:106050002A36DAC0D9C07C5B020FC90C1CDA9A0C54 -:106060009C28A8C3A6C22A36802A2584A4C2A7CC0D -:106070002D248C2B248A2B24872E248BB1BB2E36E7 -:106080009F2C369E2C369DB1AC1CDA7B1BDAC3C02C -:10609000286D2A33DAC0D9C07C5B020FC90C1CDA28 -:1060A000890C9C28A8C3A6C22A36802B2584A4C2AA -:1060B000B1BBA7CC2D248C2E248B2A248A2E369F6C -:1060C0002C369E2C369DB1ACC07919DA791BDAB525 -:1060D00013DAB31ADAB318DAB414DA7A16DAB404C3 -:1060E000F42812DAB304660C040506A252A858AAD2 -:1060F0005AA3539B3029A50027848AC091C0A52AA2 -:10610000848C29848B17DAAC18DAABA75726361D96 -:1061100026361E2E361F16DAA913DAA9A655043321 -:106120000C2826C82E75002D54AC2E54AB2E54AA24 -:106130002326E62326E52E26E7D10F006C10061352 -:10614000DA8717DA8224723D2232937F2F0B6D0893 -:10615000052832937F8F0263FFF3C0C4C0B01ADA00 -:1061600016C051D94004593929A4206E44020BB5F8 -:1061700002C3281EDA11DDB025E422052D392DE4F5 -:1061800021C0501EDA9019DA8018DA8016DA821DE2 -:10619000DA8E94102A724517DA4C6DA94BD450B39D -:1061A000557A5B17DF50756B071FDA038FF00F5FAF -:1061B0000C12DA4402F228AE2222D681D54013DA3C -:1061C00041746B0715D9FD855005450C035328B163 -:1061D00045A73FA832A93322369D22369E24368019 -:1061E0002B369F2BF48B2CF48C14DA5C24424DC09C -:1061F00030041414C84C6D0806B133041414C8429A -:1062000063FFF20015D9EAC4400031041AD9EBC08B -:10621000D193A200DD1AC138B0DD9DA318DA502B4E -:10622000824D29824E29A51C2882537A871E2C5420 -:10623000008E106FE45D12D9E02F211D23211C2F49 -:10624000251B04330C23251C23251AD10FC06218EB -:10625000DA3F88807E87D989102654006F94191BF5 -:10626000D9D62AB11C0A1A1404AA0C2AB51C2AB5BC -:106270001D2AB51A2AB51BD10F1BD9CF2AB11C0A6A -:106280001A1403AA0C2AB51C2AB51D2AB51A2AB558 -:106290001BD10F001CD9C92BC11D2DC11C2BC51B27 -:1062A00003DD0C2DC51C2DC51AD10F006C1006196D -:1062B000D9C214DA2612DA2915DA44C73FC0E02E13 -:1062C00056A82E56A92E56AA2E56AB23262918D9E3 -:1062D000EADB101CDA3EC0D42A42452D16019C1080 -:1062E00000B0890A880C2896005BFF942B22E318E3 -:1062F000D9B20B5B149B842A22E48B84B1AA0A5A7C -:10630000140BAA0C9A852922E509591499862F2283 -:10631000CD0F5F149F875BFF455BFF1623463BC194 -:10632000B01DD9A51CDA032AD1022C463A0BAA02C9 -:106330000A0A4F2AD50258047C5BFEBF5BFE98C058 -:1063400050C0B016D99B14D9A317DA12C0C0C73EEB -:1063500093122C262DC0306000430000007F9F0F59 -:10636000B155091914659FF4C0500AA9027FA7EF1F -:1063700018D98FDA5008580A28822C2B0A000B8073 -:1063800000005104D2A0C091C7AF00991A0A990326 -:106390009912CE33642067D3202B200795138C12DB -:1063A0002A62827CA85F18D98108580A28822CDAD0 -:1063B000500B8000D2A0643FDA8A310A8A1404AA02 -:1063C00001C8298B210B8B1404BB017BA945DDA0DF -:1063D0007A7B081DD9792DD2000DAD0CDB3019D98F -:1063E000731AD9B82812030ADA28088C021DD9F5C5 -:1063F00009880A28823C0DAA080B8000652F97D3D4 -:1064000020C0B063FF97CB53B1550050040A09195F -:1064100063FF4900DAB07B7B071AD9678AA00ABA02 -:106420000C1BD9A88C310BAB280C8A141CD9E6ACF8 -:10643000BB1CD9E504AA012BC68163FF907FA7C7C7 -:1064400063FF62006C100427221EC08008E4311B29 -:10645000D9580002002AB28219D958003104C0610B -:1064600000661A2991020A6A022AB68209E43115E5 -:10647000D9B30C3811A8532832822432842A8CFCD8 -:106480007841102921022A368297A009690229251C -:1064900002D10F002B21022C32850B6B022CCCFC7D -:1064A0002C368297C02B2502D10F00006C1004C03F -:1064B000E71DD93B1CD93D0D4911D7208B228A20DD -:1064C0000B4B0BD2A007A80C9B72288CF4C8346F1E -:1064D0008E026000A21FD933A298AF7B78B334C973 -:1064E0003DC081C0F0028F380F0F42C9FA2CD67E12 -:1064F000D5206D4A0500308800508C8870089808B7 -:1065000078B16CD2A09870D10FC0F0038F387FE0C3 -:10651000DE63FFD8027B0CAFBB0B990C643046D80E -:1065200030C0F1C05002F5380505426450792CD6D0 -:106530007E0B36122F6C100F4F366DFA05008088D7 -:1065400000208C06440CC081250A0003B208237C7D -:106550000C0385380505426450592CD67E6D4A05DA -:1065600000208800308CD2A0A798BC889870D10FEA -:10657000D2A0BC799970D10FD2302BAD08C0F1C038 -:10658000500BF538050542CB552CD67E083F14C17B -:10659000600F660C064636D30F6D6A050020880032 -:1065A000B08C827063FF2D00C05003F53875E08019 -:1065B00063FF7A00C06002863876E0A063FF9A002D -:1065C000C05003F53875E0C363FFBD006C1004D6FE -:1065D0002068520F695324DA20DB30DC405800F089 -:1065E000D2A0D10FDA20DB30DC405800ED9A242411 -:1065F000240EC02122640FC020D10F00B83BB04C44 -:106600002A2C7489242D200E2E200FA4DDB1EE2E0D -:10661000240FB0DD2D240E2890072D9003A488B000 -:1066200088B1DD2D94032894075BFFA069511DC03C -:10663000E082242A600F18D9662A240329600E8F6D -:106640002029240708FF029F209E64D10FC020D17B -:106650000F0000006C1004942319D95EC0B3083AEF -:10666000110BAA02992019D8D29A2116D8D0C0505D -:1066700028929D2564A2288C1828969DD10F000091 -:106680006C1004282066C038232406B788282466A6 -:10669000D10F00006C1006035A0C0D36110D5C1161 -:1066A000D8208B2282210CBB0C06550F9B82023214 -:1066B0000B928113D8BCD920A38F6450531CD8B837 -:1066C000C0D71BD8B9A256C0E1290A0004E938098D -:1066D000094276F34A044302C99E2BC67E6DAA0581 -:1066E00000208800308C8981A95909FA0C64A079AE -:1066F00099818A82C8ADD290D10FC06002E6387607 -:10670000D0DA63FFD4C020BC89998199809282D16C -:106710000F7F2304292DF8998165BFD963FFE50018 -:10672000028F0CA3FF0F3312931003AA0CD340CB9C -:106730009E2BC67E86106D6A0500208800308CBCBA -:1067400082290A0004F308240A010349380909428E -:10675000CA982BC67E6DAA0500208800308C0F5980 -:106760000CA989BC99998163FF87BC89998163FFD2 -:1067700080C06002E63876D0BA63FFB4C0700247CA -:106780003877D0D063FFCA006C100414D895C1527A -:10679000A424CA3028221D73811B292102CD952AE9 -:1067A000300075A912DA20033B022C30072D0A02B3 -:1067B0005801C2653FDDD10F2B300703BB0BDAB0A8 -:1067C00074B3022ABDF8D3A063FFC6006C1004297D -:1067D0002006C0706E9741292102C08F2A2014C064 -:1067E000B62B240606AA022A241479800227250241 -:1067F0002A221E2C221D7AC10EC8ABDA20DB302CD7 -:106800000A00033D025BF8146450752D21020D0D42 -:106810004CC9D3C020D10F00002E9CFB64E0822F16 -:1068200021020F0F4C65F0911AD8621CD86029A282 -:106830009EC08A798B5D2BC22668B0048D207BD9DF -:106840005229A29DC0F364904A97901DD8732E21BF -:10685000049D9608EE110FEE029E979E9118D86F38 -:10686000C0E527C4A22E24062BA29D2F21022BBCFB -:106870003008FF022F25022BA69DC020D10F00005B -:10688000002F300068F938DA20DB30DC4058004453 -:1068900063FF7700022A022B0A065800D3220A005F -:1068A000D10F655010283000688924022A02033B6A -:1068B00002DC4058003BC020D10FD270D10F000045 -:1068C0002A2C74033B02044C025BFEF863FF3B007E -:1068D000DB30DC402A2C745BFEF5C020D10F0000B9 -:1068E0006C1004C83F89268829A399992609880C29 -:1068F000080848282525CC52C020D10FDB402A2C7F -:10690000745BF93DD2A0D10F6C1004D820D730822F -:10691000220D451105220C928264207407420B134C -:10692000D821D420A383732302242DF885807451A9 -:106930004CBC82C0906D081600408800708C77397E -:1069400003D720C0918680743901D420746102631A -:10695000FFE2CA98C097C0411BD8A0C0A00B8B0C07 -:106960000B4A380A0A42C9AA1DD80E1CD80F2CD6C9 -:106970007EC140D30F6D4A0500208800308C97807F -:10698000D270D10FBC8FC0E00F4E387E90E263FF13 -:10699000D6BC8292819280C0209282D10F000000EA -:1069A0006C1006C0D71CD7FE1BD8000D4911D7208C -:1069B0002E221F28221D0E4E0BD280078A0C2E7607 -:1069C0001F2AAC80C8346FAE026000CB2F0A801A39 -:1069D000D804A29EAA7A7EA33FC93FC0E1C050025C -:1069E000E538050542CA552BC67EDB20D30F6D4A1C -:1069F0000500308800B08C2E721DAE9E0EA50C6472 -:106A00005086D2802E761DC091298403D10FC050AC -:106A100003E53875D0D363FFCD15D7F1027E0CA501 -:106A2000EE643051C0A1250A0002A538033A0205E0 -:106A300005426450922BC67E0E35129510255C10CF -:106A4000054536D30F6D5A0500A08800208CC0A1E3 -:106A5000A3E2C05023FA8003730C03A538AF73057B -:106A600005426450722BC67E851005450C6D5A0593 -:106A700000208800308CD280C0A10E9B0CAB7BAF75 -:106A8000BB2B761D2A8403D10FD280C0C1AF7D2DD0 -:106A9000761D2C8403D10F00D2302E8D08C0F1C09A -:106AA000500EF538050542CB592BC67E0A3F14C15E -:106AB000600F660C064636D30F6D6A05002088000D -:106AC000E08C22721D63FF03C061C05003653875FE -:106AD000D80263FF6263FF5CC05002A53875D0879F -:106AE00063FF8100C06003F63876D0BF63FFB90052 -:106AF0006C10042A201529201614D7AF0A990CCB44 -:106B00009D2E200B04ED092BD11C8F2809BC36AC1F -:106B1000AA0CBB0C2BD51C0A0A472A2415CAAF8B1A -:106B2000438942B0A800910400881AA8FF0FBB0255 -:106B30009B278F260FB80C783B1AC020D10F00007E -:106B4000292102C0A20A9902292502C021D10F00E1 -:106B50008B2763FFDC2BD11C0CAA0C0A0A472A24C2 -:106B600015ACBB2BD51CC9AE8B438C288F42B0AD66 -:106B700000F10400DD1AADCC0CBB029B27DA20B774 -:106B8000EB580019C021D10F9F2763FFEF000000D1 -:106B90006C100428203C64304705306000073E013B -:106BA000053EB156076539054928C77FA933030655 -:106BB00041076603B166060641A6337E871E222181 -:106BC00025291AFC732B1502380C09816000063E3A -:106BD00001023EB12406423903220AD10FD230D13C -:106BE0000FC05163FFC000006C100427221EC0803C -:106BF00008E4311DD76F0002002CD2821BD76F0032 -:106C00003104C06100661A2BB1020C6C022CD682D2 -:106C10000BE43119D7F20C3A11AA932832829780EB -:106C2000253282243284B45525368275410A2921C1 -:106C300002096902292502D10F2A21022B32830A77 -:106C40006A022B36822A2502D10F00006C1004192B -:106C5000D76327221EC08009770208E4311DD7546C -:106C60000002002CD2821BD754003104C0610066A0 -:106C70001A2BB1020C6C022CD6820BE43119D7D737 -:106C80000C3A11AA932832829780253282243284CA -:106C9000B45525368275410B2A21020A6A022A253B -:106CA00002D10F002B21022C32830B6B022C368277 -:106CB0002B2502D10F0000006C10041BD73D0C2ABD -:106CC00011ABAA29A286B438798B221BD73A19D7DF -:106CD000610B2B0A2BB2A309290868B00274B90D05 -:106CE000299D0129901F6E920822A285D10FC020F4 -:106CF000D10FC892C020D10FDA205BEF35C020D170 -:106D00000F0000006C100414D72A28429E19D727C0 -:106D10006F88026000BA2992266890078A2009AA23 -:106D20000C65A0AC2A429DC0DC64A0A42B200C19E9 -:106D3000D7210CBC11A4CC2EC28609B90A7ED3027D -:106D400060009A2992A36890078D2009DD0C65D018 -:106D50008C25C2856450862D2104C0306ED80D2C40 -:106D60002066B8CC0C0C472C246665C07B1CD79CD5 -:106D700018D7281AD71E19D72F1DD724C0E49E5123 -:106D80009D508F209357935599539A569A5408FFC4 -:106D9000021AD73A9F5288269F5A9E599D58935E51 -:106DA0009C5D935C9A5B080848058811985FC0D881 -:106DB0001FD7080CB911A499289285AFBF23F4CF2F -:106DC000288C402896858E262D24069E29C020D109 -:106DD0000FCA33DA20C0B65BFF84C72FD10FC93A80 -:106DE000DA205BFF81C72FD10FDBD05BFE1A232493 -:106DF000662B200C63FF7500C72FD10FC72FD10F53 -:106E00006C1004C85B29200668941C689607C02093 -:106E1000D10FC020D10FDA20DB30DC40DD502E0A4C -:106E2000005BFE6AD2A0D10F2E200C18D6E10CEF29 -:106E300011A8FF29F286C088798B751AD6DE0AEA76 -:106E40000A2AA2A368A0048B207AB96423F285647D -:106E5000305E1CD6E82A0A802D2068292067282168 -:106E6000040B991104881109880208DD02C09428D6 -:106E70004A1008DD0218D6E0993198308B2B9A37EA -:106E80009D340CBB029B32C0C09C359C362A2C74AE -:106E9000DB40C0D318D6CF29F285A8EE299C202C40 -:106EA000E4CF29F6852D2406DD405BFDFAD2A0D182 -:106EB0000FDA20DBE05BFF4CC020D10F6C100AD64C -:106EC000302A2006941128ACF86583872B2122C034 -:106ED000F22A21246550082AAC010A0A4F2A2524E7 -:106EE0007ABB0260037F2C21020C0C4C65C3192E67 -:106EF00022158D32C0910EDD0C65D39088381ED6D8 -:106F0000AC64836B8C37C0B8C0960CB9399914B493 -:106F10009A9A120D991199138F6718D6A7C9FB2851 -:106F200080217F83168B142C22002A200C5BFF62A9 -:106F3000D4A064A3A88F6760002800002B200C89D0 -:106F4000120CBA11AEAA2CA2861DD69A7C9B3E0DBD -:106F5000BD0A2DD2A368D00488207D893024A28563 -:106F600064436427212E07F73607F90C6F9D01D77C -:106F7000F0DA20DB70C1C42D211F5BFF0589268854 -:106F800027DDA009880C7A8B179A10600006C04094 -:106F900063FFCC0000DA208B105BFED58D1065A25C -:106FA00067C0E09E488C649C498B658A669B4A9AC0 -:106FB0004B97458F677F7302600120CD529D10DA99 -:106FC00020DB302C12015BFE768D10C051D6A08FD5 -:106FD000A7C0C08A68974D9A4C8869896A984E996B -:106FE0004F8E6A8A69AE7E77EB01B1AA9E6A9A6972 -:106FF0008B60C0A00B8E1477B701C0A1C091C08474 -:1070000093159D179516C0D025203CC03008580117 -:10701000089338C082083310085B010535400B9D8A -:107020003807DD100BAB100E19402A211F079910ED -:1070300003DD020DBB020553100933020A55112965 -:1070400021250A2A140929140499110A99020933DD -:10705000028A2B2921040BAA021BD6E208991109E6 -:1070600055020855020BAA029A40892088140899F3 -:107070001109880219D6631DD6DC09880298418B54 -:107080002A9346954783150DBB0285168D179B44A1 -:107090008A658966AACAA97C77CB01B1AA07FB0CCD -:1070A0009C669A6588268E29AD87972607EE0C0E7A -:1070B0000E482E25259B672B200C87131ED63D0CD2 -:1070C000B911AE99289285A78828968517D641C010 -:1070D00090A7BB29B4CF871863FE3C008C60C0E04A -:1070E000C091C0F0C034C0B82A210428203C08AAAE -:1070F000110B8B01038301039F380B9B39C03208AE -:10710000FF10038801089E380C881407EE100FEE5C -:107110000203880108983905BF1029211F0ABB11F5 -:1071200007881008FF020BAA0218D6350929140394 -:10713000AA022B212583200B2B1404BB1108331129 -:107140000FBB020B99028B148F2A0B3302083302F8 -:107150008B2B6470868868974D984C8769886A93F2 -:10716000419946974E984FC07077C701C0719A47B2 -:1071700018D69E0B7C100CEC0208F802984418D626 -:107180009B0CBC0208CC029C402A200C295CFEC04F -:10719000801FD6071CD60F0CAE112B2124ACAAAF32 -:1071A000EEB0BB8F132CE28528A4CFAFCC2CE685A4 -:1071B0002A22152B2524B1AA2A26156490DBC9D2D0 -:1071C0008F262E22090DFF082F26060FEE0C0E0E1D -:1071D000482E25256550E4C020D10F00C070934192 -:1071E0009F4499469A4777C70A1CD5F32CC022C002 -:1071F000810C87381CD67F0B781008E80208B8028B -:107200000C8802984063FF8000CC57DA20DB608C4A -:10721000115BFDE3292102689806689403C020D120 -:107220000F2B221EC0A029221D2A25027B9901C0F6 -:10723000B064BFE813D5DE2CB00728B000DA200315 -:10724000880A28824CC0D10B8000DBA065AFE763C1 -:10725000FFCA000068A779DA20DB30DC40DD505B34 -:10726000FEE8D2A0D10FC16DC19D29252C6000047C -:1072700029252CD6902624672F2468DA20DB308C31 -:1072800011DD502E0A805BFD51D2A0D10FC168C123 -:10729000A82A252C63FFDD000000C8DF8C268B297F -:1072A000ADCC9C260CBB0C0B0B482B25252A2C7433 -:1072B000DB602C12015BFD94D2A0D10F2A2C748BC1 -:1072C000115BF6CDD2A0D10FDA205BFE4763FF3809 -:1072D00000DA20C0B15BFE8B65AF2D63FBEDDA20D9 -:1072E0002B200C5BFE5A63FF1F00000012D6428267 -:1072F00020028257C82163FFFC12D63E03E8300407 -:10730000EE3005B13093209421952263FFFC0000FC -:1073100010D63A910092019302940311D611821073 -:1073200001EA30A21101F031C04004E4160002006D -:1073300011D6338210234A00032202921011D5FD88 -:10734000C021921004E43184038302820181000091 -:10735000D23001230000000010D62A910092019340 -:1073600002940311D600821001EA30A21101F1311A -:10737000C04004E41600020011D621821013D5A7E4 -:10738000032202921004E43184038302820181000B -:1073900000D330013300000010D61B91008101653D -:1073A000104981026510448103CF1F92019302941A -:1073B0000311D5EE821001EA30A21101F231C04072 -:1073C00004E41600020011D60D821013D58E03229C -:1073D00002921004E431840383028201C0109103FD -:1073E00091029101810000D43001430012D5BDC04B -:1073F0003028374028374428374828374C233D0168 -:107400007233ED03020063FFFC00000010D5FF9112 -:107410000092019302940311D5FD8210921011D5B0 -:10742000AF8310032202921011D5FA12D5C1921027 -:10743000C04004E41600020011D5F1821013D5A853 -:10744000032202921004E43184038302820181004A -:1074500000D53001530000006C10026E322FD62090 -:10746000056F04043F04745B2A05440C00410400CA -:10747000331A220A006D490D73630403660CB122AE -:107480000F2211031314736302222C01D10FC83B86 -:10749000D10F000073630CC021D10F000000000069 -:1074A00044495630C020D10F6C10020040046B4C90 -:1074B00007032318020219D10F020319C020D10FAC -:1074C0006C100202EA30D10F6C1002CC2503F031AF -:1074D00060000F006F220503F1316000056F230586 -:1074E00003F231000200D10F6C1002CC2502F03003 -:1074F000D10F00006F220402F130D10F6F2304027C -:10750000F230D10FC020D10F6C1002220A20230AC2 -:10751000006D280E28374028374428374828374C34 -:10752000233D01030200D10F6C100202E431D10FA0 -:107530000A0000004368656C73696F204657204459 -:10754000454255473D3020284275696C7420576587 -:1075500064204F63742020382031353A35303A3575 -:1075600030205044542032303038206F6E20636C0D -:10757000656F70617472613A2F686F6D652F666513 -:107580006C69782F772F66775F372E30292C20563D -:10759000657273696F6E2054337878203030372EDF -:1075A00030312E3030202D203130303730313030F6 -:0875B000100701006F4EF8BB4B -:00000001FF diff --git a/firmware/cxgb3/t3fw-7.4.0.bin.ihex b/firmware/cxgb3/t3fw-7.4.0.bin.ihex new file mode 100644 index 000000000000..38dda94bfa6f --- /dev/null +++ b/firmware/cxgb3/t3fw-7.4.0.bin.ihex @@ -0,0 +1,1917 @@ +:1000000060007400200380002003700000001000D6 +:1000100000002000E100028400070000E1000288E7 +:1000200000010000E0000000E00000A0010000006E +:1000300044444440E3000183200200002001E0002A +:100040002001FF101FFFD0001FFFC000E300043C91 +:100050000200000020006B741FFFC29020006BBCE8 +:100060001FFFC29420006BFC1FFFC29820006C7021 +:100070001FFFC29C200003C0C00000E43100EA3131 +:1000800000A13100A03103020002ED306E2A05000C +:10009000ED3100020002160012FFDBC03014FFDA5F +:1000A000D30FD30FD30F03431F244C107249F0D347 +:1000B0000FD30FD30F12FFD5230A00240A00D30F4A +:1000C000D30FD30F03431F244C107249F0D30FD327 +:1000D0000FD30F14FFCE03421F14FFCB03421F1296 +:1000E000FFCCC0302D37302D37342D37382D373CED +:1000F000233D017233ED00020012FFC4C0302F37E0 +:10010000002F37102F37202F3730233D017233ED6A +:1001100000020012FFBEC0302737002737102737F4 +:1001200020273730233D017233ED03020012FFB95F +:1001300013FFBA0C0200932012FFB913FFB90C028F +:1001400000932012FFB8C0319320822012FFB71312 +:10015000FFB7932012FFB715FFB316FFB6C030D715 +:100160002005660160001B00000000000000000088 +:10017000043605000200D30FD30F05330C6E3B1479 +:100180000747140704437631E604360505330C6F40 +:100190003BED00020012FFA615FFA3230A00D720A3 +:1001A000070443043E0505330C0747146F3BF00377 +:1001B000020012FFA1C03014FFA1D30FD30FD30F41 +:1001C0009340B4447249F2D30FD30FD30F14FF9B63 +:1001D000834014FF9B834012FF9B230A0014FF9A65 +:1001E000D30FD30FD30F9340B4447249F2D30FD33C +:1001F0000FD30F14FF95834012FF95C92F832084DE +:10020000218522BC22743B0F8650B4559630B433FE +:100210007433F463FFE60000653FE1655FDE12FFC3 +:100220007C230A0028374028374428374828374C91 +:10023000233D017233ED03020000020012FF7AC079 +:1002400032032E0503020012FF7813FF819320C0B2 +:1002500011014931004831010200C00014FF7E0441 +:10026000D23115FF7D945014FF7D04D33115FF7CEE +:10027000945014FF7C04D43115FF7C24560014FFE5 +:100280007B04D53115FF7B24560010FF7A03000054 +:10029000000000000000000000000000000000005E +:1002A000000000000000000000000000000000004E +:1002B000000000000000000000000000000000003E +:1002C000000000000000000000000000000000002E +:1002D000000000000000000000000000000000001E +:1002E000000000000000000000000000000000000E +:1002F00000000000000000000000000000000000FE +:1003000000000000000000000000000000000000ED +:1003100000000000000000000000000000000000DD +:1003200000000000000000000000000000000000CD +:1003300000000000000000000000000000000000BD +:1003400000000000000000000000000000000000AD +:10035000000000000000000000000000000000009D +:10036000000000000000000000000000000000008D +:10037000000000000000000000000000000000007D +:10038000000000000000000000000000000000006D +:10039000000000000000000000000000000000005D +:1003A000000000000000000000000000000000004D +:1003B000000000000000000000000000000000003D +:1003C000000000000000000000000000000000002D +:1003D000000000000000000000000000000000001D +:1003E000000000000000000000000000000000000D +:1003F00000000000000000000000000000000000FD +:1004000000000000000000000000000000000000EC +:1004100000000000000000000000000000000000DC +:1004200063FFFC000000000000000000000000006E +:100430000000000000000000000000001FFC0000A1 +:100440001FFC0000E30005C81FFC00001FFC0000AB +:10045000E30005C81FFC00001FFC0000E30005C806 +:100460001FFFC0001FFFC000E30005C81FFFC00042 +:100470001FFFC018E30005C81FFFC0181FFFC018EA +:10048000E30005E01FFFC0181FFFC290E30005E076 +:100490001FFFC2901FFFC290E30008581FFFC290C9 +:1004A0001FFFC58CE3000858200000002000016AEF +:1004B000E3000B542000018020000180E3000CC009 +:1004C0002000020020000203E3000CC02000021CF8 +:1004D00020000220E3000CC420000220200002269D +:1004E000E3000CC82000023C20000240E3000CD0D6 +:1004F0002000024020000249E3000CD42000024CFE +:1005000020000250E3000CE02000025020000259BD +:10051000E3000CE42000025C20000260E3000CF029 +:100520002000026020000269E3000CF42000026C4D +:1005300020000270E3000D0020000270200002790C +:10054000E3000D042000028C2000028CE3000D105B +:100550002000029020000293E3000D10200002AC66 +:10056000200002B0E3000D14200002D0200002F2AF +:10057000E3000D18200003B0200003B0E3000D3CA1 +:10058000200003B0200003B0E3000D3C200003B0C6 +:10059000200003B0E3000D3C200003B0200003B0B6 +:1005A000E3000D3C200003B020006D94E3000D3CFF +:1005B00020006D9420006D94E3007720000000007F +:1005C00000000000000000001FFC00001FFC0000F5 +:1005D0001FFFC5901FFFC67020006D9820006D980A +:1005E000DEFFFE000000080CDEADBEEF1FFFC2A064 +:1005F0001FFCFE001FFFC0941FFFC5C0300000009D +:10060000003FFFFF8040000010000000080FFFFFC8 +:100610001FFFC26D000FFFFF804FFFFF8000000033 +:1006200000000880B000000560500000600000007D +:1006300040000011350000004100000010000001E2 +:100640002000000000001000400000000500000035 +:1006500080000019040000000000080010000005E0 +:10066000806000007000000020000009001FF800FA +:100670008000001EA0000000F800000007FFFFFF40 +:100680000800000018000000010080014200000086 +:100690001FFFC21D1FFFC0DC000100806040000082 +:1006A0001A0000000C0000001000000A00003000DA +:1006B000600008008000001C000100008000001A9B +:1006C00080000018FC0000008000000100004000D5 +:1006D000030000008000040050000003FFFFBFFF84 +:1006E0001FFFC3D400000FFFFFFFF000000016D073 +:1006F0000000FFF7A50000001FFFC4B01FFFC4618A +:100700000001000800000B20202FFF801FFFC455B0 +:1007100000002C00FFFEFFF800FFFFFF1FFFC57861 +:1007200000002000FFFFDFFF0000FFEF01001100CD +:100730001FFFC3D21FFFC590FFFFEFFF0000FFFBAD +:100740001FFFC6301FFFBEA0FFFFF7FF1FFFC064E3 +:100750000000FFFD1FFFC6200001FBD01FFFC5B03A +:100760001FFFC6601FFFC591E0FFFE001FFFC5A071 +:10077000000080001FFFC53C1FFFC5B41FFFC068FD +:100780001FFFC4D01FFCFFD8000100817FFFFFFFC7 +:10079000E1000600000027101FFCFE301FFCFE7069 +:1007A000E10002001FFFC5381FFFC5500003D090B5 +:1007B0001FFFC5642B5063802B5079802B50908095 +:1007C0002B50A6801FFFC4690100110F202FFE00CF +:1007D00020300080202FFF000000FFFF0001FFF805 +:1007E0002B50B2002B50B208000100102B50B180EA +:1007F0002B50B2802B50BA00000100112B50BD28A5 +:100800002B50BC802B50BDA020300000DFFFFE002D +:100810005000000200C0000002000000FFFFF7F4DB +:100820001FFFC06C000FF800044000000010000023 +:100830000C4000001C400000E00000A01FFFC5406D +:100840001FFD00081FFFC5541FFFC5681FFFC57CA3 +:10085000E1000690E10006EC00000000000000004E +:100860000000000000000000010000000000000087 +:100870000000000000000000201000402010004098 +:100880002010004020140080200C0000200C0000EC +:10089000200C000020100040201400802014008054 +:1008A00020140080201800C0201C0100201C010022 +:1008B000201C010020200140201800C0201800C08A +:1008C000201800C0201C0100201800C0201800C003 +:1008D000201800C0201C01002020014020200140E1 +:1008E00020200140202009402020094020200940EC +:1008F0002020094020240980FFFFFFFFFFFFFFFFAA +:10090000FFFFFFFF000000000000000000000000EB +:100910000000000000000000200054902000536000 +:1009200020005490200054902000529C2000529CA3 +:100930002000529C200050DC200050DC200050D4CD +:100940002000504020004EE820004CC820004A9C67 +:100950000000000000000000200054602000532C24 +:10096000200053D0200053D0200051842000518417 +:10097000200051842000518420005184200050CC5C +:100980002000518420004E0820004C7820004A4866 +:10099000000000000000000020000BE820003A30BA +:1009A000200004C02000463C20000BE0200041480D +:1009B000200003F0200045FC20004A2420003E5483 +:1009C00020003D70200039AC2000383C200035ACC0 +:1009D0002000310C20003BCC20002D6C2000280092 +:1009E000200067182000238C2000206C2000201895 +:1009F00020001D04200018182000154820000E2C8F +:100A000020000C2C2000110C200012F82000434084 +:100A100020003E0820000BF0200004C00000000071 +:100A200000000000000000000000000000000000C6 +:100A300000000000000000000000000000000000B6 +:100A400000000000000000000000000000000000A6 +:100A50000000000000000000000000000000000096 +:100A60000000000000000000000000000000000086 +:100A70000000000000000000000000000000000076 +:100A80000000000000000000000000000000000066 +:100A900000000000000000000000000032640000C0 +:100AA0000000000032640000640064006400640020 +:100AB00064006400640064000000000000000000A6 +:100AC0000000000000000000000000000000000026 +:100AD0000000000000000000000000000000000016 +:100AE0000000000000000000000000000000000006 +:100AF00000000000000000000000000000000000F6 +:100B000000001000000000000000000000000000D5 +:100B100000000000000000000000100000000000C5 +:100B200000000000000000000000000000432380DF +:100B300000000000000000000000000000000000B5 +:100B400000000000000000000000000000000000A5 +:100B500000000000005C94015D94025E94035F94C9 +:100B60000043000000000000000000000000000042 +:100B70000000000000000000000000000000000075 +:100B80000000000000000000000000000000000065 +:100B900000000000005C90015D90025E90035F9099 +:100BA00000530000000000000000000000000000F2 +:100BB0000000000000000000000000000000000035 +:100BC0000000000000000000000000000000000025 +:100BD00000000000009C94001D90019D94029E94D2 +:100BE000039F94040894050994060A94070B940043 +:100BF00043000000000000000000000000000000B2 +:100C000000000000000000000000000000000000E4 +:100C100000000000009C90019D90029E90071D9096 +:100C2000039F90047890057990067A90077B900056 +:100C30005300000000000000000000000000000061 +:100C400000000000000000000000000000000000A4 +:100C50000000000000DC94001D9001DD9402DE9491 +:100C600003DF94040494050594060694070794088A +:100C700008940909940A0A940B0B9400430000009D +:100C80000000000000000000000000000000000064 +:100C90000000000000DC9001DD9002DE900B1D9052 +:100CA00003DF9004B49005B59006B69007B790089E +:100CB000B89009B9900ABA900BBB9000530000009D +:100CC00063FFFC0020006B5010FFFF0A00000000D3 +:100CD00020006B7400D23110FFFE0A0000000000FB +:100CE00020006BBC00D33110FFFE0A0000000000A2 +:100CF00020006BFC00D43110FFFE0A000000000051 +:100D000020006C7000D53110FFFE0A0000000000CA +:100D100063FFFC00E00000A012FFF7822002825770 +:100D2000C82163FFFC12FFF303E83004EE3005C076 +:100D30003093209421952263FFFC00001FFFD00018 +:100D4000000400201FFFC5901FFFC670200A00117D +:100D5000FFFB13FFFB03E63101020016FFFA17FF4A +:100D6000FAD30F776B069060B4667763F85415B5C5 +:100D7000541A610F140063FFF90000006C1004C0E6 +:100D800020D10F006C1004C0C71AEF06D830BC2B5E +:100D9000D72085720D4211837105450B9572023380 +:100DA0000C2376017B3B04233D089371A32D12EEA7 +:100DB000FE19EEFEA2767D632C2E0A000882022820 +:100DC0000A01038E380E0E42C8EE29A67E6D4A0532 +:100DD00000208800308C8271D10FC0F0028F387FE4 +:100DE000C0EA63FFE400C0F1C050037E0CA2EE0E27 +:100DF0003D1208820203F538050542CB5729A67E2D +:100E00002FDC100F4F366DFA0500208800308CBCA7 +:100E100075C03008E208280A01058338030342C977 +:100E20003E29A67E0D480CD30F6D8A050020880050 +:100E3000B08C8271D10FC05008F53875C0C163FF06 +:100E4000BBC06002863876C0DA63FFD46C1012161D +:100E5000EED8C1F9C1E8C1C72B221E28221DC0D07F +:100E60007B81312920060BB702299CFA655008289E +:100E70002072288CFF28247264915C2AB0000CA890 +:100E80000C6481670EA90C6492B37FA13769AC2F03 +:100E90006000340000282006D7D0288CFACC572ACE +:100EA00020722AACFF2A24726481352AD0000CA952 +:100EB0000C6491640EAC0C64C31B7FA10768AC0783 +:100EC000C020D10F002D25028A32C0900A6E5065D5 +:100ED000E5B5292467090F4765F5B12C200C1FEEF5 +:100EE000B50CCE11AFEE29E286B4487983026005D5 +:100EF0008219EEB109C90A2992A36890078F2009C7 +:100F0000FF0C65F56E2FE28564F56865559628221D +:100F10001D7B8105D9B060000200C0908B9417EE54 +:100F2000A70B881487740B0B47A87718EEA509BB8D +:100F30001008770297F018EEA317EEA408A8010B8B +:100F400088020747021BEEA097F10B880298F22750 +:100F500090232B902204781006BB1007471208BB81 +:100F6000022890210777100C88100788020B88024E +:100F700017EE988B3307BB0187340B880298F397E1 +:100F80009997F48B9587399BF588968B3898F688D6 +:100F90009797F99BF898F717EE8F28E28507C7080F +:100FA0002D74CF08480B28E68565550F2B221E2887 +:100FB000221D7B89022B0A0064BF042CB00728B0D5 +:100FC00000DA2006880A28824CC0D10B8000DBA002 +:100FD00065AFE763FEE90000292072659E9C60040E +:100FE000E72A207265AEC36004DE00002EB0032C39 +:100FF0002067D4E065C1058A328C330AFF500C4566 +:1010000054BC5564F4EB19EE74882A09A9010988C7 +:101010000C64821FC0926000DD2ED0032A2067D4AA +:10102000E065A0D88A328B330AFC500B4554BC557E +:1010300064C4BE19EE69882A09A9017989D50BEA29 +:101040005064A4E30CEE11C0F02F16132E16168A6E +:10105000E78CE82A16128EE9DFC0AAEA7EAB01B15E +:10106000CF0BA8506583468837DBC0AE89991E78C0 +:101070009B022BCC012B161B29120E2B0A002916C2 +:101080001A7FC3077FC9027EAB01C0B165B49D8BD7 +:10109000352F0A002A0A007AC30564C3CB2F0A0140 +:1010A00065F4892B12162B1619005104C0C100CC0F +:1010B0001A2CCCFF2C16170CFC132C16182B121AFA +:1010C0002A121BDC50581974C0D0C0902E5CF42C2E +:1010D00012172812182F121B2A121A08FF010CAA25 +:1010E000018834074C0AAB8B2812192BC6162F86A1 +:1010F000082A86092E74102924672E70038975B179 +:10110000EA2A7403B09909490C659DB32B20672D19 +:10111000250265B3FA2B221E2C221D7BC901C0B00B +:1011200064BD9C2CB00728B000DA2006880A28820B +:101130004CC0D10B8000DBA065AFE763FD8189BAAD +:10114000B19965909788341CEE2598BA8F331EEEBE +:101150001E0F4F542FB42C8D2A8A320EDD020CAC98 +:10116000017DC9660A49516F92608A3375A65B2C6E +:10117000B0130AED510DCD010D0D410C0C417DC98F +:10118000492EB012B0EE65E3C6C0D08E378CB88A57 +:10119000368FB97CA3077AC9027EFB01C0D1CED9B4 +:1011A00088350AAD020E8E0878EB022DAC0189B7A6 +:1011B000DAC0AF9B79BB01B1CADCB0C0B07DA30778 +:1011C0007AD9027CEB01C0B164B161C09129246776 +:1011D000C020D10F00008ADAB1AA64A0C02C206719 +:1011E0002D250265C3111DEDF88A321EEDFD0DADF2 +:1011F000010EDD0C65D28A0A4E516FE20260028157 +:10120000C090292467090F4765F2F828221D7B89C1 +:10121000022B0A0064BCA82CB00728B000DA200614 +:10122000880A28824CC0D10B8000DBA065AFE76341 +:10123000FC8D00000CE9506492ED0CEF11C0802889 +:101240001611AFBF2F16198EF88BF7DAE08FF92B36 +:101250001610ABFB7FBB01B1EA0CA8506580D688A5 +:1012600037DCE0AF89991C789B022CEC012C161B13 +:1012700029120C2C0A0029161A7AE3077AE9027F50 +:10128000BB01C0C165C2A58B352C0A002A0A007AB1 +:10129000E30564E1CA2C0A0164CE0D60028E883435 +:1012A0001BEDCF98DA8F331EEDC80F4F542FD42C7F +:1012B0008C2A8A320ECC020BAB010CBB0C65BF0A28 +:1012C0000A49516E920263FF018A330AAB5064BE31 +:1012D000F92CD0130AEE510ECE010E0E410C0C412A +:1012E0000ECC0C65CEE42FD012B0FF65F26EC0B00C +:1012F0008E378CD88A362FD2097CA3077AC9027E12 +:10130000FB01C0B165BEC38835DBA0AE8E78EB01B2 +:10131000B1AB89D7DAC0AF9D79DB01B1CAC0C07B60 +:10132000A3077AB9027DEB01C0C165CE9DC09029AB +:101330002467C020D10F88378C3698140CE90C290B +:10134000161408F80C981D78FB07281214B088288A +:101350001614891D9F159B16C0F02B121429161AFE +:101360002B161B8B147AE30B7AE90688158E1678F8 +:10137000EB01C0F165F1BA29121A2F12118A352E2C +:10138000121B9A1AAFEE2F1210C0A0AF9F79FB016B +:10139000B1EE9F11881AC0F098107AE30A7EA90571 +:1013A0002A12017A8B01C0F164F0816001838936D1 +:1013B0008B3799170BE80C981F09C90C291615785B +:1013C000EB07281215B088281615D9C09A199E184F +:1013D0008A1F2E12152A161A2E161BDAC0C0E08C90 +:1013E000177F930B7FA90688188F1978FB01C0E13E +:1013F00065E13E29121A2F12138A352E121B9A1BF1 +:10140000AFEE2F1212C0A0AF9F79FB01B1EE9F1378 +:10141000881BC0F098127AE30A7EA9052A12037A83 +:101420008B01C0F165F10A2E12162E16192A121B15 +:10143000005104C0E100EE1AB0EE2E16170EFF1395 +:101440002F16180FCC01ACAA2F121A0EBC01ACFC3F +:101450007FCB01B1AA2A161B2C161A63FC5E000072 +:101460007FB30263FE3163FE2B7EB30263FC306305 +:10147000FC2A00006450C0DA20DBC0581648C020A7 +:10148000D10FC09163FD7A00C09163FA44DA20DB8A +:1014900070C0D12E0A80C09A2924682C7007581574 +:1014A00038D2A0D10F03470B18ED4FDB70A8287876 +:1014B00073022B7DF8D9B063FA6100002A2C74DB2B +:1014C00040580EB363FAE4000029221D2D25027B4B +:1014D0009901C0B0C9B62CB00728B000DA20068840 +:1014E0000A28824CC0D10B8000DBA065AFE7C0208A +:1014F000D10FC09163FBFF00022A025802440AA2E6 +:1015000002060000022A025802410AA20206000056 +:10151000DB70DA20C0D12E0A80C09E2924682C708E +:1015200007581517C020D10FC09463FBC9C096633C +:10153000FBC4C09663FBBF002A2C74DB30DC405B2D +:10154000FE11DBA0C2A02AB4002C200C63FF2700F0 +:101550008D358CB77DCB0263FDD263FC6D8F358EEC +:10156000D77FEB0263FDC563FC6000006C1004C014 +:1015700020D10F006C1004C020D10F006C10042B80 +:10158000221E28221DC0A0C0942924062A25027BE1 +:101590008901DBA0C9B913ED06DA2028B0002CB010 +:1015A0000703880A28824CC0D10B8000DBA065AFFE +:1015B000E7C020D10F0000006C10042C20062A2167 +:1015C0000268C80528CCF965812E0A094C6591048A +:1015D0008F30C1B80F8F147FB00528212365812774 +:1015E00016ECF529629E6F98026000F819ECF1295B +:1015F00092266890078A2009AA0C65A0E72A629DB6 +:1016000064A0E12B200C0CB911A6992D92866FD9FC +:10161000026000DB1DECE90DBD0A2DD2A368D007E6 +:101620008E200DEE0C65E0C7279285C0E06470BF88 +:101630001DECEE68434E1CECED8A2B0CAA029A704E +:1016400089200899110D99029971882A98748F320E +:101650009F75282104088811987718ECDE0CBF11BB +:10166000A6FF2DF285A8B82E84CF2DDC282DF68577 +:10167000C85A2A2C74DB40580E46D2A0D10FC02085 +:10168000D10F00000029CCF96490B12C206689317B +:10169000B1CC0C0C472C24666EC60260008509F89C +:1016A0005065807F1CECD38A2B0F08400B881008F4 +:1016B000AA020CAA029A7089200899110D99029920 +:1016C00071883398738C329C728A2A9A74893499FF +:1016D0007563FF7D00CC57DA20DB30DC4058151DE8 +:1016E000C020D10F00DA20C0B65815AC63FFE5006A +:1016F000DA205815AA63FFDC00DA20DB30DC40DD9D +:1017000050581638D2A0D10FC858DA20DB30581400 +:101710008A2A210265AFBDC09409A9022925026366 +:10172000FFB200002B21045814351DECAFC0E02E91 +:1017300024668F302B200C0F8F1463FF662921380D +:10174000C08879830263FF5B2C20662B2104B1CC17 +:101750000C0C472C24665814291DECA3C0E02E2441 +:10176000668F302B200C0F8F1463FF376C1004C072 +:10177000B7C0A116ECA015EC92D720D840B822C073 +:10178000400535029671957002A438040442C94B95 +:101790001AEC8519EC8629A67EC140D30F6D4A0547 +:1017A00000808800208C220A88A272D10FC05008C5 +:1017B000A53875B0E363FFD76C1006931394112915 +:1017C0002006655288C0716898052A9CF965A29820 +:1017D00016EC792921028A1309094C6590CD8AA05B +:1017E0000A6A512AACFD65A0C2CC5FDB30DA208CDE +:1017F000115814D8C0519A13C7BF9BA98E132EE25B +:101800000968E0602F629E1DEC6A6FF80260008438 +:101810002DD22668D0052F22007DF9782C629DC735 +:101820009064C0709C108A132B200C2AA0200CBD41 +:1018300011A6DD0A4F14BFA809880129D286AF88F6 +:10184000288C09798B591FEC5C0FBF0A2FF2A36813 +:10185000F0052822007F894729D285D490659075AC +:1018600060004300002B200C1FEC540CBD11A6DDC2 +:1018700029D2860FBF0A6E96102FF2A368F0048853 +:10188000207F890529D285659165DA20581543C9DD +:101890005C6001FF00DA20C0B658154060000C0003 +:1018A000C09063FFB50000DA2058153C6551E48D07 +:1018B000138C11DBD08DD0022A020D6D515813AD5F +:1018C0009A1364A1CEC75F8FA195A9C0510F0F478E +:1018D0009F1163FEFD00C091C0F12820062C2066F8 +:1018E000288CF9A7CC0C0C472C24666FC6098D13E5 +:1018F0008DD170DE02290A00099D02648159C9D385 +:101900008A102B21045813BD8A13C0B02B24662ED5 +:10191000A2092AA0200E28141CEC338D1315EC27E5 +:10192000C1700A773685562DDC28AC2C9C12DED08F +:10193000A8557CD3022EDDF8D3E0DA40055B02DC4B +:10194000305BFF8AD4A028200CB455C0D02B0A8865 +:101950002F0A800C8C11A6CC29C285AF3FAB9929E8 +:10196000C6851CEC1CDEF0AC882D84CF2812022921 +:10197000120378F3022EFDF8289020D3E007880C9C +:10198000C170080847289420087736657FAB891313 +:1019900013EC1A8990C0F47797491BEC18C1CA2838 +:1019A00021048513099E4006EE1187530488118592 +:1019B000520E88020C88029BA09FA18F2B9DA59898 +:1019C000A497A795A603FF029FA22C200C1EEC0152 +:1019D000AECE0CCC1106CC082BC2852DE4CF2BBC8F +:1019E000202BC6852A2C748B11580D69D2A0D10FDB +:1019F00028203DC0E07C877F2E24670E0A4765A023 +:101A00007B1AEBFF88201EEBED8F138EE48FF4081A +:101A100088110A88020F8F14AFEE1FEBFA98910F0E +:101A2000EE029E901EEBF9C0801AEBEA2CD285AA3A +:101A3000BAB8CC28A4CF2CD6852C21022F20720E28 +:101A4000CC02B1FF2F24722C2502C020D10F8713A6 +:101A5000877007074763FD6E282138C099798B028C +:101A600063FE9ADDF063FE9500DA20DB308C11DD39 +:101A70005058155CD2A0D10FC0E163FF7A8B138C54 +:101A800011DD50C0AA2E0A802A2468DA205813BC1F +:101A9000D2A0D10FC020D10F6C1006292102C0D0D6 +:101AA0007597102A32047FA70A8B357FBF052D2535 +:101AB000020DD902090C4C65C18216EBBE1EEBBCAF +:101AC00028629EC0FA78F30260018829E2266890B5 +:101AD000078A2009AA0C65A17A2A629DDFA064A169 +:101AE000772B200C0CBC11A6CC29C286C08C798324 +:101AF0000260015719EBB109B90A2992A36890074E +:101B0000882009880C65814327C2851CEBB364716A +:101B10003A8931098B140CBB016FB11D2C20669FD3 +:101B200010B1CC0C0C472C24666EC6026001400933 +:101B3000FF5065F13A8A102AAC188934C0C47F97E7 +:101B40003C18EBB31BEBB28F359C719B708B209DC7 +:101B50007408BB029B72C08298751BEBAE0F0840E5 +:101B60009B730F881198777FF70B2F2102284A006B +:101B700008FF022F2502C0B4600004000000C0B0BE +:101B80007E97048F362F25227D97048837282521BC +:101B90007C9736C0F1C0900AF9382F3C20090942E1 +:101BA00064908619EB8018EB8128967E00F08800FF +:101BB000A08C00F08800A08C00F08800A08C2A6225 +:101BC0009D2DE4A22AAC182A669D89307797388F1C +:101BD000338A3218EB8A07BE0B2C2104B4BB04CC29 +:101BE0001198E0C08498E1882B9DE59AE69FE71A5A +:101BF000EB82099F4006FF110FCC020A880298E28F +:101C0000C1FC0FCC022CE604C9B82C200C1EEB71D1 +:101C10000CCA11AECC06AA0829A2852DC4CF09B9D9 +:101C20000B29A685CF5CC020D10FC081C0900F8941 +:101C300038C08779880263FF7263FF6600CC57DA89 +:101C400020DB30DC405813C3C020D10FDA205814F9 +:101C50005363FFE8C0A063FE82DA20C0B658144F79 +:101C600063FFD900DB402A2C74580CC9D2A0D10FD5 +:101C70008A102B21045812E11EEB4EC0D02D246691 +:101C800063FEB1006C1006D62019EB491EEB4B2801 +:101C9000610217EB4808084C65805F8A300A6A5178 +:101CA00069A3572B729E6EB83F2A922668A0048CB7 +:101CB000607AC9342A729D2C4CFECAAB2B600CB6DC +:101CC0004F0CBD11A7DD28D2860EBE0A78FB269CDC +:101CD000112EE2A32C160068E0052F62007EF91594 +:101CE00022D285CF2560000D00DA60C0B658142BD3 +:101CF000C85A60010F00DA60581428655106DC40AC +:101D0000DB308D30DA600D6D5158129AD3A064A08B +:101D1000F384A1C05104044763FF6D00C0B02C6080 +:101D2000668931B1CC0C0C472C64666FC602709684 +:101D30000A2B61045812B1C0B02B64666550B42AF6 +:101D40003C10C0E7DC20C0D1C0F002DF380F0F42EA +:101D500064F09019EB1418EB1528967E8D106DDA4F +:101D60000500A08800C08CC0A089301DEB247797A7 +:101D70005388328C108F3302CE0BC02492E1226143 +:101D8000049DE00422118D6B9BE59FE798E61FEB15 +:101D90001A0998400688110822020FDD02C18D9DA4 +:101DA000E208220292E4B4C22E600C1FEB0A0CE897 +:101DB00011A7882C8285AFEE0C220B2BE4CF228654 +:101DC00085D2A0D10F28600CD2A08C1119EB020C87 +:101DD0008D11A988A7DD2ED2852B84CF0ECC0B2C9C +:101DE000D685D10FC0F00ADF387FE80263FF6C634D +:101DF000FF6000002A6C74C0B2DC20DD4058128FF6 +:101E0000C0B063FF63C020D10F0000006C10042C31 +:101E1000221D2A221EC049D320293006243468C03E +:101E2000407AC105DDA060000200C0D06E9738C0C6 +:101E30008F2E0A802B3014C0962934060EBB022E3A +:101E400031022B34147E8004243502DE407AC10E28 +:101E5000C8ABDBD0DA302C0A00580AE52E31020E6E +:101E60000F4CC8FEC020D10F6895F8283102080831 +:101E70004C658FEF1AEAD01CEACE2BA29EC09A7B4B +:101E80009B462BC22668B0048D307BD93B29A29D8E +:101E9000C0E3CB9394901BEAE02D31049B9608DDC0 +:101EA000110EDD029D979D9112EADDC0E524C4A2CA +:101EB0002E34062F310228A29D02FF02288C3028E2 +:101EC000A69D2F3502C020D10FDA30C0B65813B30B +:101ED000C020D10F6C1006292006689805289CF9AF +:101EE00065825D29210209094C659210CD51DB30D4 +:101EF000DA20044C02581317C051D3A0C7AF2A36BA +:101F00000AC0E019EAAD1DEAB31FEAAC8A3A16EA44 +:101F1000A9B1AC64C13528629E6F88026001F129C5 +:101F2000DC332992266890078B2009BB0C65B1E051 +:101F300027629DC08E6471D82B200C0CBC11A6CCDE +:101F400029C2867983026001D219EA9B09B90A295C +:101F500092A3971068900828220009880C6581BB1D +:101F600027C2856471B5292006299CF96491EC2C5F +:101F700020668931B1CC0C0C472C24666EC60260F9 +:101F800001A109F85065819B883689F4088C14AC4E +:101F9000991CEA8B0C99022C2104997019EAA1086A +:101FA00008479971892A09881008990218EA9E0839 +:101FB000990299722830132930120488100699105A +:101FC00008990228302C9A740C881008C8020988D5 +:101FD00002987389379975883898768A39C0819ABA +:101FE000771AEA918935987B99780989140A9902B8 +:101FF000997A8A30893277A73618EA808F33987CAD +:10200000C084987D882B2E76112976122F7613198D +:10201000EA7A0A9F4006FF1104CA110988020FAA32 +:1020200002987EC1F90FAA022A7610C0AA600001A8 +:10203000C0A6ADBF0CBC11A6CC29C2852EF4CF0919 +:10204000A90B29C685655107C020D10F2B200C0C88 +:10205000BC1106CC0828C28609B90A6F8902600142 +:102060002E2992A36890082A220009AA0C65A11FB4 +:102070002AC28564A11928203D08284064808C84E8 +:102080003504841464408485F574537F8436048455 +:1020900014644077745374293013C08C79886CC0F1 +:1020A000902924670908476580ED882089F48435E4 +:1020B0001FEA55048414A4940F440294A014EA5017 +:1020C00008881104880298A1843698A3048414A473 +:1020D000990F990299A219EA4CADB428C2852E44F1 +:1020E000CF288C1028C6852821022F20720988024B +:1020F000B2FF2F2472282502C020D10F00CC57DA5E +:1021000020DB30DC40581293C020D10FC09163FF18 +:102110008FDA20C0B658132163FFE100DA2058138C +:102120001F63FFD88A102B21045811B41DEA2A1FFF +:10213000EA232B200CC0E02E24668A3A63FE480076 +:1021400000DA20DB30DC40DD505813A6D2A0D10FDE +:102150002A2C74DB40580B8ED2A0D10F292138C015 +:102160008879830263FE202A12002C20662B21042A +:102170002CCC010C0C472C24665811A01DEA161F0C +:10218000EA0F2B200CC0E02E24668A3A63FDF8008B +:10219000DA2058130263FF64DA205BFF1CD2A0D15F +:1021A0000F0000006C10089515C061C1B0D9402A1D +:1021B000203DC0400BAA010A64382A2006291606D1 +:1021C00068A8052CACF965C33B1DE9FC6440052FEC +:1021D000120564F29C2621021EE9F806064C65628F +:1021E000E315E9F46440D98A352930039A140A9931 +:1021F0000C6490CC2C200C8B149C110CCC11A5CC15 +:102200009C122CC286B4BB7CB3026002D38F110E29 +:10221000FE0A2EE2A368E0098620D30F0E660C6545 +:1022200062BE88122882856482B6891464905EDA60 +:1022300080D9308C201EE9F21FE9F31DE9E08B14F0 +:102240008DD4D4B07FB718B88A293C10853608C61B +:10225000110E66029681058514A5D50F550295804D +:102260000418146D8927889608CB110888140EBBB2 +:1022700002A8D8299C200F88029BA198A088929B35 +:10228000A3088814A8D80F880298A22AAC1019E9CC +:10229000DEC0C08F141EE9CF86128D11286285AE74 +:1022A000DD08FF0B2CD4CF2821022F66858B352A21 +:1022B0002072098802ABAA2825022A2472C020D1E4 +:1022C0000F29529E18E9BB6F9802600208288226E7 +:1022D00068800829220008990C6591F92A529DC14D +:1022E000CA9A1364A1EF2B200C2620060CB811A566 +:1022F000882D82860EBE0A7DC3026002022EE2A3F2 +:1023000068E0082F22000EFF0C65F1F3288285DEBD +:10231000806481FF9810266CF96461FF2C20668828 +:1023200031B1CC0C0C472C24666EC6026001BC088F +:10233000FD5065D1B617E9BD19E9A21AE9A92C210A +:10234000048B2D2830102F211D0C88100BFB090C3D +:1023500088020A880209BB026441528910C04D9B61 +:1023600090979198928D35D9E064D06CD730DBD0BE +:10237000D8307FD713273C10BCE92632168C39960B +:10238000E69CE78A37B4389AE80B13146430492A7C +:10239000821686799A9696978C778A7D9C982B825E +:1023A000172C7C209A9A2A9C189B99867BB03BB864 +:1023B000896DB9218BC996A52692162AAC18B899B1 +:1023C0009BA196A08BC786CD9BA22B921596A49B12 +:1023D000A386CB2CCC2026A605C0346BD4200D3B85 +:1023E0000C0DD8090E880A7FB705C0909988BC8863 +:1023F000C0900B1A126DAA069988998B288C18C068 +:10240000D01BE98C1CE98B16E981B1FF2A211C2322 +:10241000E6130F0F4F26E6122F251D7FA906C0F0E9 +:10242000C08028251D05F6111AE97A8F202BE615A4 +:102430002CE6162DE61726E6180AFA022AE61429D3 +:102440002006299CF96490FF29200C8D15C0801A64 +:10245000E9610C9C11AA99A5CCDA202BC28528949D +:10246000CF0B4B0B2BC685C0B08C1658118AD2A04F +:10247000D10F8A356FA548D8308BD56DA90C8A86C7 +:102480000A8A14CBA97AB337288C10C08028246715 +:10249000080B4765B112DA20DB302C12065811AD5B +:1024A000D3A0C0C1C0D02DA4039C1563FD268636E1 +:1024B00064610C8910C04D9B909791989263FEA423 +:1024C000C08163FFC78A15CCA7DA20DB308C165891 +:1024D00011A1C020D10FDA20C0B658123063FFE43A +:1024E00000DA208B1158122D63FFD9009E178A1332 +:1024F0002B21045810C28E17C0B02B246663FE3403 +:10250000C08063FE09DA20DB308C16DD505812B52E +:10251000D2A0D10FDA2058122163FFA82D2138C094 +:10252000C87DC30263FE0D8A132B21042C206698FC +:1025300017B1CC0C0C472C24665810B08E17C0D0A5 +:102540002D246663FDEE0000262138B06606064F96 +:10255000262538656EF128206A7F870508294164A1 +:1025600090A5C0D01BE92619E93426200723E61BD5 +:10257000B16609FA022BE61A28200A2DE61D2AE682 +:102580001E09880228E61C882606064728E6202B16 +:10259000220826E53E2BE6212D24072C20062A20A2 +:1025A0006468C347B44463FE9EDB30DA208D15C0F7 +:1025B000CE2E0A802C24688C165810F1D2A0D10F90 +:1025C0008E102A321616E8FD0A2A1486662BE612A9 +:1025D00097E127E61328E614AA6609660296E02E1C +:1025E000EC4869ED50C14663FD7A000064AFB41950 +:1025F000E8F328201689920A880C00910400881AB2 +:10260000A8B8982963FF9C002B21046EB81E2C20CB +:1026100066B8CC0C0C472C2466C9C09E178A135888 +:1026200010778E17C0348F20C0D02D2466C0682646 +:10263000240663FF2C008D35C08064D04AD9E0DCCD +:1026400030DBE0DF301AE8FDB188B4FF17E8FD8623 +:10265000C9249DFF8DC82CCC102D46300767012D55 +:1026600046320A66011DE8F7264631AD6D2D463328 +:1026700026F21597B796B684C3BCBB94B58D3529A1 +:102680009C107D83C22F211DC14663FD4B000000BD +:102690006C1006292006289CF86582BF2921022B90 +:1026A000200C09094C6590E116E8C30CBA11A6AAE2 +:1026B0002DA2862C0A127DC30260028C19E8BF0984 +:1026C000B90A2992A36890078C2009CC0C65C278BE +:1026D00029A2856492722D629E1AE8B56FD80260B5 +:1026E000026E2AA22629160168A0082B22000ABB26 +:1026F0000C65B25C29629DC18C6492542A21200A27 +:10270000806099102C203CC7EF000F3E010B3EB1BA +:10271000BD0FDB390BBB098F260DBD112DDC1C0D48 +:102720000D410EDD038E27B1DD0D0D410FEE0C0DB9 +:10273000BB0B2BBC1C0BB7027EC71C2C21257BCBF3 +:10274000162D1AFC0CBA0C0DA16000093E01073EC3 +:10275000B1780987390B770A77EB0260020A2C21DE +:1027600023282121B1CC0C0C4F2C25237C8B29B0A4 +:10277000CD2D2523C855DA20DB3058106F292102D2 +:10278000CC96C0E80E9E022E2502CC57DA20DB3014 +:10279000DC405810F0C020D10F2C20668931B1CC1C +:1027A0000C0C472C24666EC6026001D309FD5065EF +:1027B000D1CD2F0A012E301129221464E0112822D4 +:1027C0001B090C4400C10400FA1A0A880228261BBF +:1027D0002E3010C0A0C0B0941295131CE878883039 +:1027E0002CC022088D14778704C0F10CFA38C04140 +:1027F000C0F225203CC0840858010F5F010F4B3800 +:1028000005354007BB10C0F0084F3808FF100FBB5C +:102810000228ECFEC0F0084F38842B0BA8100AFFEA +:10282000102A21200F88020B880208440218E8862B +:102830008F110844022821250A2A14082814048824 +:10284000110A88022A210494F08B2004E41008BBAA +:102850001104BB02C04A04BB029BF1842A08AB11DD +:102860000BEB0294F40A54110B44020555100D1B96 +:102870004094F707BB100B5502085502C08195F62E +:102880008433C05094F3B1948B3295F898F99BF24D +:10289000C080C1BC24261499FA9BF598FB85389515 +:1028A000FC843A94FD8B3B9BFE883998FF85352547 +:1028B000F6108436851324F6118B3784122BF6120A +:1028C000C0B064C07E89307797438D3288332E3014 +:1028D000108F111CE84A0999400699112CF614C072 +:1028E000C42CF6158C2B2DF61A28F61B2BF6190482 +:1028F000A81109880208EE0219E840C18008EE021A +:1029000009C90229F6162EF618C09E600001C09A69 +:102910002F200C18E8300CFE11A8FFA6EE2DE28542 +:102920002BF4CF0D9D0B2DE685C87F8A268929A71C +:10293000AA9A260A990C090948292525655050C0EC +:1029400020D10F00C09A63FFC6DA2058111463FE2D +:1029500038DA20C0B658111163FE2E0068973C2B60 +:102960009CFD64BE24C020D10FDA20DB705810CD4E +:10297000C0C0C0D10ADA390ADC3865CDE063FE098F +:102980008A102B2104580F9DC0B02B246663FE21B2 +:10299000DB402A2C7458097ED2A0D10FDA20580FC0 +:1029A000A263FCF76C1004C020D10F006C10042946 +:1029B0000A801EE8261FE8261CE7FF0C2B11ACBB83 +:1029C0002C2CFC2DB2850FCC029ED19CD0C051C0C6 +:1029D0007013E82214E82118E81F2AB285A82804F9 +:1029E000240A234691A986B8AA2AB685A9882784ED +:1029F0009F25649FD10F00006C100AD6302830103C +:102A0000292006288CF964829B68980B2A9CF9651A +:102A1000A1B2022A02580F8489371BE7E8C89164E3 +:102A2000520E2A21020A0C4C65C2588D3019E7E17A +:102A300074D7052E212365E29E2F929E1AE7DD6F43 +:102A4000F8026002532AA22668A0082C22000ACCB1 +:102A50000C65C2442A929D64A23E9A151FE7D78D49 +:102A600067C1E6C8DD2B620618E7D564B00528808B +:102A7000217B8B432B200C18E7CF0CBC11A8CC2951 +:102A8000C28679EB460FBE0A2EE2A368E0052F222C +:102A9000007EF9372CC2859C1864C2332B212F8706 +:102AA000660B7B360B790C6F9D266ED2462C203D33 +:102AB0007BC740CE5560001E2A200CC1B28C205826 +:102AC00010F79A1864A2458D6763FFCFC0C063FFFB +:102AD000C5D7B063FFD300C0E06000022E60030ED4 +:102AE000DB0C6EB20EDC700CEA11AA6A2AAC20581C +:102AF0000199D7A0DA20DB70C1C82D212058109190 +:102B00008C268B279A160CBB0C7AB3348F188963EA +:102B100099F3886298F28E659EF82D60108A189D50 +:102B20001768D729C0D09DA92C22182B22139CAB43 +:102B30009BAA97A58E667E7302600097CF586000AF +:102B40001FDA208B1658105765A13863FFBDC0816E +:102B5000C0908F18C0A29AF999FB98FA97F563FF75 +:102B6000D2DB30DA20DC40580FFBC051D6A0C0C009 +:102B70002BA0102CA4039B172C1208022A02066B10 +:102B800002DF702D60038E179D149E100CDD11C0A6 +:102B9000E0AD6D2DDC205801188C148B16ACAC2CDC +:102BA00064038A268929ABAA0A990C9A26886609A1 +:102BB000094829252507880C98662F2218A7FF2F7A +:102BC000261863FE96DA20DB30DC40DD5058110514 +:102BD000D2A0D10FC0302C20668961B1CC0C0C473B +:102BE0002C24666EC6026000D2C03009FD5065D04C +:102BF000CA8E6764E069647066DB608C18DF70DA27 +:102C0000202D60038E170CDD119E10AD6D2DDC2084 +:102C10001EE78D5800F9232618DA208B16DC402F8A +:102C20002213DD50B1FF2F2613580F9AD2A0D10FD7 +:102C30000028203D084840658DE76F953EDA308DCD +:102C4000B56D990C8CA80C8C14CACF7CD32D2AACF2 +:102C500010C090292467090D4764DDC5600092000B +:102C60002C1208066B022D6C20077F028E17DA20CB +:102C70009E101EE77458007D63FF9A00C09163FFA9 +:102C8000D1000000655081DA20DB60DC40580FB1D4 +:102C9000C020C0F02FA403D10FDA20C0B658103FD7 +:102CA00063FFE000006F950263FD6CDA20DB30DC2F +:102CB00040DD50C4E0580F32D2A0D10F8A152B212D +:102CC00004580ECE232466286010981763FF210055 +:102CD000DA2058103263FFABC858DB30DA20580FC7 +:102CE000162A210265AF9CC09409A9022925026316 +:102CF000FF91DB30DC40DD50C0A32E0A802A24681F +:102D0000DA20580F1FD2A0D10FC020D10FDA202B0C +:102D1000200C58104763FF6B6C1004282006C0621B +:102D2000288CF8658125C050C7DF2B221BC0E12A03 +:102D3000206B29212300A104B099292523B1AA00E1 +:102D4000EC1A0BC4010A0A442A246B04E4390DCCA2 +:102D5000030CBB012B261B64406929200C1BE715C3 +:102D60000C9A110BAA082FA2861BE7136FF90260B9 +:102D700000B60B9B0A2BB2A368B0082C22000BCC28 +:102D80000C65C0A42BA2851DE73664B09B8C2B2458 +:102D900021040DCC029CB08820C0C50888110C8885 +:102DA0000298B1882A08441198B48F3494B79FB51B +:102DB000C0401EE7082DA2850E9E0825E4CF2DDC1D +:102DC000282DA68529210209094C68941A689820A3 +:102DD000C9402A210265A00B2A221E2B221D7AB18E +:102DE0000265A079C020D10F2C212365CFDE6000C1 +:102DF000082E21212D21237EDBD52B221E2F221DE3 +:102E00002525027BF901C0B064BFC413E6E92CB0EC +:102E10000728B000DA2003880A28824CC0D10B8032 +:102E200000DBA065AFE763FFA62A2C74C0B02C0AB4 +:102E300002580E081CE70C9CA08B2008BB1106BB97 +:102E4000029BA1893499A263FF790000262468DAE5 +:102E500020DB30DC40DD50581063D2A0D10FDA20E7 +:102E60002B200C580FCEC020D10F00006C1006078D +:102E70003D14C080DC30DB40DA20C047C02123BCD9 +:102E800030032838080842774001B1DD64815A1EBA +:102E9000E6C519E6C629E67ED30F6DDA050050882F +:102EA00000308CC0E0C02025A03C14E6C4B6D38F0F +:102EB000C0C0D00F87142440220F8940941077F7A8 +:102EC00004C081048238C0F10B2810C044C0220421 +:102ED000540104FD3802520102FE3808DD10821C44 +:102EE00007EE100E6E020EDD02242CFEC0E004FE82 +:102EF000380AEE100E88020D88028DAB1EE6B4086B +:102F0000D8020E880298B0C0E80428100E5E018432 +:102F1000A025A125084411084402052514045511D3 +:102F2000043402C0810E8E3994B18FAA84109FB4EC +:102F300075660C26A11FC0F2062614600009000069 +:102F400026A120C0F20626140565020F7701078727 +:102F50003905E61007781008660206550295B62571 +:102F6000A1040AE61108581108280208660296B75B +:102F7000C060644056649053067E11C0F489C288D4 +:102F8000C30B340B96459847994618E69B9F41041E +:102F900059110E99021FE699020E4708D80298426D +:102FA0000E99029F40C1E00E990299442FA00CB4E3 +:102FB000380CF91114E6881EE67FA4FFAE992E9214 +:102FC0008526F4CF0E880B289685D10F2BA00C1FD9 +:102FD000E6791CE6800CBE11ACBBAFEE2DE2852677 +:102FE000B4CF0D3D0B2DE685D10FC0800528387874 +:102FF000480263FEA263FE966C1006C0C06570F1C5 +:103000008830C030088714778712C0B0C0A619E690 +:103010006B299022C030CC97C031600003C0B0C093 +:10302000A6C0E0C091C0D4C08225203C0B3F1097C1 +:1030300012831CC0700858010D5D01089738C080CC +:103040000B9838077710048810086802087702C0C8 +:10305000800D98382D3CFE0888100D9E388D2B0A67 +:10306000EE1008EE0207EE020CB8100FDD02053B71 +:10307000400EDD029D408920043D100899110D99F4 +:10308000022D210409A90208DD119941872A05B9F9 +:10309000100D3D020ABB110DBB02087702974428B0 +:1030A00021258712082814048811071E4007EE10F6 +:1030B0000E990275660926211F0626146000060077 +:1030C0002621200626140868029B47098802984694 +:1030D00029200CD2C0C0800C9E111BE63E1FE63595 +:1030E000AB99AFEE2DE2852894CF0DAD0B2DE68583 +:1030F000D10FDD40C0A6C0B08E51CAE0B2AAB1BBAC +:103100002DDC108F500E7836981008770C9FD898C9 +:10311000D989538F52991199DB9FDA7E8309B1CCFB +:10312000255C10C97763FFCF88108D1108E70C97D5 +:1031300051AD8DD7F078DB01B1F79D5397528830B0 +:10314000C030088714088840648ED565BEC963FE08 +:10315000BC0000006C1004D720B03A8820C0308238 +:1031600021CAA0742B1E2972046D080FC980C99151 +:103170008575B133A2527A3B0B742B0863FFE900CB +:10318000649FECD10FD240D10F0000006C100AD622 +:10319000302E3027D950DA4015E6092430269A150A +:1031A00029160464E0026493732920062A9CF865BA +:1031B000A3CE2A2102270A040A0B4C65B3978C3050 +:1031C00074C7052D212365D4A0C0A62B0A032C2289 +:1031D00000580F0B64A3B917E5F78E389A1664E30D +:1031E000BA2F6027285021C9F37E8311C2B08C20EA +:1031F0002A200C580F2AD7A0CDA16004A200C2B08B +:103200008C202A200C580EFED7A064A4862F212ED5 +:103210008B680FBF360FB90C6F9D54296027D5B04E +:103220006E920528203D7B8F4CDA20DB50C1C42DE7 +:10323000211F580EC48B269A189A1989272AAC3850 +:103240000B990C7A93538963C08099738F62987835 +:103250009F728E659E798D679D7B8C6695759C7A35 +:103260008E687E53026000B18B1465B050600038E8 +:10327000DBF063FFA5008A14C9A92E60030E9B0C26 +:103280006EB2A5DC500CEA11AA6A2AAC285BFFB129 +:10329000D5A063FF93C0E063FFE2DA208B18580EDD +:1032A0008165A2B163FF9E0000DA20DB308C1558E7 +:1032B0000E29D6A0C0C0C0D12D16042CA403DC70EA +:1032C000DA20DB60DF502D6003C0E09E109D171EEA +:1032D000E5D20CDD110D6D082DDC285BFF478E66F5 +:1032E0008F678817AF5FA8A828640375FB01B1EE4C +:1032F0008A189E669F6789268829AA9909880C9949 +:10330000268E6808084805EE0C28252515E5AC9E94 +:103310006865EECC63FEE6000000C9432F21232B35 +:1033200021212FFC010F0F4F2F25237FBB026003AC +:10333000142C20668961B1CC0C0C472C24666EC617 +:103340000260022809FD5065D22264E1B62E602792 +:1033500064E1B0DC70DF50DA20DB601EE5C32D6075 +:1033600003C08098100CDD11AD6D2DDC285BFF22B1 +:10337000644181C0442B0A008C202A200C580EA0E6 +:103380000AA70265A00FC0B02C22002A200C580EFC +:103390009CD7A064AFEFDA20C1BCC1C82D21208F1B +:1033A000188E268929AFEE9E260E990C0909482908 +:1033B0002525580E64C090C050C0C288609A191E5E +:1033C000E57FC0A12EE022088F14778704C0810E0C +:1033D0008938C0800B93102D203C2921200CDC0162 +:1033E00004DB010929140BA8380CA5380D3D401C3D +:1033F000E5968B2B088810075510085502053302F7 +:103400002821250F154003BB020CBB0207551005F0 +:10341000D3100828140ADD11048811098802053325 +:10342000022921040833029B70C0808A201BE58F8B +:1034300008AA110BAA029A71C0A1852A93769574E5 +:1034400008931103DD020ADD029D778C63C1DC9CC9 +:10345000738B6298789A799B72232214C0C0B1351D +:103460002526149C7B9D75937A2B621A9B7C2A627D +:103470001C9A7D28621D987E25621B957F2362170A +:103480002376102D62182D76112C62192C76126479 +:10349000E0B98E6077E73DC0FE13E5571DE558C1E2 +:1034A000818A628B630495110E9C4006CC110C55E9 +:1034B00002247615085502C0802D76148D2B2B76AC +:1034C0001B2A761A28761925761803DD022D761622 +:1034D0006000030000C0FA2E200C19E53E18E53507 +:1034E000A9E90CEE11A8EEC0802DE2852894CF0D3D +:1034F000FD0B2DE685DA208B198C158D14580D6582 +:10350000D2A0D10FDC70DF50DB602D6C28C0A01E74 +:10351000E5569A10DA205BFE5563FE53002B203DE2 +:103520000B4B4065BC826FE527DA308F556DE90C97 +:103530008EAA0E8E14C9E87EF3162AAC10C090290C +:103540002467090F4764FC6060015F00C0FA63FFF5 +:1035500085C09163FFE88814658168DA20DB608CA0 +:1035600015580D7CC020C09029A403D10F8A162BBA +:103570002104580CA2C0A02A24668E6863FDCA00EC +:10358000002B9CF965B0FDDA20580CA763FC2200E3 +:1035900000DA20C0B6580E0163FFBA002B200C0CD5 +:1035A000BE11A7EE2DE286C1C27DC30260011819CB +:1035B000E50209B90A2992A36890082A220009AAFB +:1035C0000C65A10326E2856460FD2C20668931B17B +:1035D000CC0C0C472C24666FC60270960C8A162BF6 +:1035E0002104580C86C0D02D24668E3077E74D1C00 +:1035F000E5021BE5028F328833C0A42D21040E9909 +:103600004006991104DD1109DD029A61C19009DDBE +:10361000029B60C0908B2B9D649F66986799650C98 +:10362000BB029B6228200C1AE4EBAA8A0C8811A723 +:10363000882F828529A4CF2FFC202F86858A1465A8 +:10364000A0A6C020D10FB0FC8B142C2523C8B70234 +:103650002A02066B02580CB82A210265AEF7C0D8C0 +:103660000DAD022D250263FEEC008E14C8E8DA20B1 +:10367000DB30580CB12A210265AEDA07AF022F25E4 +:103680000263FED100DA20DB308C158D14580E5504 +:10369000D2A0D10FDA202B200C580DC063FEB6004B +:1036A000DA202B200C580DE263FEAADA20DB308CE6 +:1036B000152D12042E0A80280A00282468580CB000 +:1036C00063FAE500C020D10FDA20580DB48914CD7B +:1036D00092DA20DB308C15580D1FDBA0C020C0A073 +:1036E0002AB403D10FC020D10F2A2C748B15580691 +:1036F00028D2A0D10F0000006C100C2821029410D9 +:1037000008084C6583621FE4AB29F29E6F98026043 +:1037100003661DE4A729D2266890082A220009AA78 +:103720000C65A3542CF29D64C34E2B200C0CB611D7 +:10373000AF66286286C1EC78E30260034619E49E16 +:1037400009B90A2992A36890078A2009AA0C65A3DF +:103750003224628564432CC0E12A3109C0702724D9 +:103760006689359A11992A88369912982B89379843 +:1037700013992C883899140858149815982D89395C +:103780002A25042E251D29251C283028C0922824EE +:103790003C2A302908084798160989012A243D2A1D +:1037A000311599170A094109A90C299CEC29251FF3 +:1037B0007E87192D2A000DA06000083E010A3EB147 +:1037C000AD08DA390EAA110A990C29251F2A211FE2 +:1037D00018E4A80A8160C1D0941A951B01083E0024 +:1037E000053EB184054839843C259CFC0D8836296A +:1037F000201408AA1C8D3D2726182E26132E2614C9 +:103800002E261527261B2E246B27246727246808BD +:10381000581C0909432924142932112A252E282548 +:103820002F27252427252527252C27252325252037 +:103830002425212D2522841A2D211C851B6FD202BF +:10384000600209C0A099186D080AB1AA00A104007D +:10385000E91A7D9B0263FFEE8918C080C0E1C07049 +:10386000C0D29B1D951B961C9C1E16E4722C203DFD +:1038700015E4820C0B400DCC010BE7381DE4640A03 +:1038800077100CE8380B8810C0C49C410877029D63 +:1038900040B0A80988118B209C499D48954B9643C0 +:1038A000087702861418E47315E45A08770205BBFA +:1038B000029B4A9B4297468812871108DA149A4E57 +:1038C0000D88100D77110877021AE44E06D8140DF2 +:1038D0006610087702974FC78F984D984C98458788 +:1038E0001598440715140D55110A5502954715E40E +:1038F000638A262D46102D46182D46202C46112C65 +:1039000046192C46212B46122B461A2846142846C7 +:10391000152B462288162546242546268B170A0C89 +:1039200048090D4885130EDD1105CC110839400BEF +:10393000EB390299101EE4520DCC020D5511082DE1 +:10394000400655022E461316E41D0FDD11254616BE +:10395000080840851B0188100DBB0286671DE449DD +:103960000988020CBB0219E4191CE4472B46172DE9 +:10397000461BA7661BE446C0702C461C0988028CB7 +:103980001E28461E2B4623C0908B1D29461D294606 +:103990001F18E43F2946272846252931162E2006E0 +:1039A00029246A243117962D242538861CCCE1273A +:1039B0002407C0D7090E4064E0829A29092841648F +:1039C000809164409B2D2406C098094936280AA09E +:1039D00024628501C404A84428210424668508883B +:1039E000118E3F8A3E2D32100EA41800C4040EAE74 +:1039F0001800EE110ACA530EDD02C0E30E880298C9 +:103A0000C11EE42409084E9EC08E2094C398C59D13 +:103A1000C418E3F01DE42105EE110EAA020DAA025E +:103A2000A8B82784CF9AC21EE3E224F29D27E4A21D +:103A3000244C1824F69D655052C020D10F2D240629 +:103A4000C0A0C09809493604A93863FF7FC0A063AD +:103A5000FE070000654F6DC098C0A82A240663FFCA +:103A60006B2D2406C09063FF63CC57DA20DB308CCB +:103A700010580C38C020D10F00DA20C0B6580CC73F +:103A800063FFE500DA20580CC563FFDC2A2C748B39 +:103A90001058053FD2A0D10F6C10062820068A339B +:103AA0006F8202600161C05013E3C229210216E354 +:103AB000C1699204252502D9502C20159A2814E3B7 +:103AC000BF8F2627200B0AFE0C0477092B711C647C +:103AD000E1398E428D436FBC0260016F00E104B09A +:103AE000C800881A08A80808D80298272B2006685A +:103AF000B32ECE972B221E2C221D0111027BC90151 +:103B0000C0B064B0172CB00728B000DA2003880AD0 +:103B100028824CC0D10B8000DBA065AFE7C020D16C +:103B20000F2D206464DFCA8B29C0F10BAB0C66BF7C +:103B3000C02B200C0CBC11A6CC28C2862E0A0878FB +:103B4000EB611EE39D0EBE0A2EE2A368E00528226B +:103B5000007E894F29C2851EE3A96490461FE3B603 +:103B60009E90C084989128200A95930F880298927D +:103B70008E200FEE029E942F200788262F950A98FC +:103B8000969A972E200625240768E3432921022AC6 +:103B9000C2851DE3902AAC20ADBD25D4CF2AC685B1 +:103BA00063FF4E002E2065CBEDC082282465C9F648 +:103BB00005E4310002002A62821BE3982941020BCE +:103BC000AA022A668209E43129210263FF23000048 +:103BD00064DFB88F422E201600F1040DEE0C00EECB +:103BE0001AAEAE9E2963FFA38A202B3221B1AA9A76 +:103BF000B0293221283223B4992936217989A92B79 +:103C000032222B362163FFA0C020D10F9F2725240D +:103C100015ACB828751C2B2006C0C12EBCFE64E074 +:103C2000AB68B7772DBCFD65DEC72D2064C0F0649E +:103C3000D0868E290EAE0C66E089C0F128205A2865 +:103C40008CFE08CF3865FEE863FF580000E004935F +:103C500010C0810AF30C038339C78F08D80308A862 +:103C60000108F80C080819A83303C80CA8B828756F +:103C70001C030B472B24158310CBB700E104B0BC09 +:103C800000CC1AACAC0CDC029C27659E5EC0B20B6B +:103C9000990209094F29250263FE50002D206A0D63 +:103CA0002D4165DF7EDA20C0B0580C8F64AF18C09C +:103CB000F163FEEF9F2763FFD02E221F65EE326374 +:103CC000FF79000028221F658E2763FF6E252406DA +:103CD00029210263FE1B00006C10066571332B4C1A +:103CE00018C0C7293C18C0A1C08009A838080842DC +:103CF0006481101CE32C1AE32D2AC67E2A5CFDD3B6 +:103D00000F6DAA0500B08800908C8940C0A009887A +:103D1000471FE355080B47094C50090D5304DD10AC +:103D2000B4CC04CC100D5D029D310CBB029B3088DD +:103D3000438E2098350FEE029E328D26D850A6DD98 +:103D40009D268E40C0900E5E5064E0971CE33B1EA3 +:103D5000E32B038B0BC0F49FB19EB02D200A99B3C7 +:103D60000CDD029DB28F200CFF029FB48E262D2009 +:103D7000079EB68C282DB50A9CB72924072F20064C +:103D80002B206469F339CBB61DE30D2320168DD2A9 +:103D90000B330C00D10400331AB48DA3C393292232 +:103DA000200C13E30C1FE3030C2E11AFEEA322290A +:103DB00024CF2FE285D2A00FDD0B2DE685D10F0099 +:103DC0002E200CB48C0CEB111FE3031DE2FAAFEEB6 +:103DD000ADBB22B28529E4CF02C20B22B685D2A0A8 +:103DE000D10F00002E200C1CE2F31FE2FA0CEB11A5 +:103DF000AFEEACBB22B28529E4CF02820B22B6859E +:103E0000D2A0D10FC0D00BAD387DC80263FEEC63E9 +:103E1000FEE08E40272C747BEE12DA70C0B32C3C8F +:103E200018DD50580A868940C08063FEE3066E02A2 +:103E3000022A02DB30DC40DD505800049A10DB50CF +:103E4000DA70580453881063FEF700006C10069275 +:103E5000121EE2E48C40AE2D0C8C472E3C1804CA96 +:103E60000BD9A07DA30229ADF875C302600084C000 +:103E7000B0C023C0A09D106D0844B89F0EB80A8D35 +:103E8000900EB70BB8770D6D36ADAA9D800D660C00 +:103E9000D8F000808800708C879068B124B22277B7 +:103EA000D3278891C0D0CB879890279C100070882A +:103EB00000F08C9D91CB6FC08108BB0375CB36633E +:103EC000FFB4B1222EEC1863FFD485920D770C86D7 +:103ED000939790A6D67D6B01B1559693959260000D +:103EE00016B3CC2D9C188810D9D078D3C729DDF80B +:103EF00063FFC100C0238A421BE2E900CD322D449A +:103F0000029B3092318942854379A1051EE2E50E7C +:103F1000550187121BE2D5897095350B99029932AC +:103F200088420A880C98428676A6A696768F44AF79 +:103F3000AF9F44D10F0000006C10089311D6308859 +:103F400030C0910863510808470598389812282115 +:103F500002293CFD08084C6581656591628A630A07 +:103F60002B5065B18B0A6F142E0AFF7CA60A2C20F9 +:103F70005ACCC42D0A022D245A7FE0026002158912 +:103F80002888261FE2C809880C65820F2E200B0F97 +:103F9000EE0B2DE0FE2EE0FF08DD110EDD021EE22D +:103FA000C2AEDD1EE2C21CE2C20EDD010DCC37C185 +:103FB00080084837B88DB488981089601AE2807BF1 +:103FC00096218B622AA0219C147BA3179D132A2083 +:103FD0000C8B108C20580BB18C148D13DBA0CEAC45 +:103FE0006001C4002E200C1BE2730CEA110BAA081E +:103FF0002BA2861FE2717BDB3B0FEF0A2FF2A36837 +:10400000F0052822007F892C2BA28564B0AA876244 +:104010008826DE700C7936097A0C6FAD1C8F279BD1 +:104020001508FF0C77F3197E7B729D139C149B156A +:10403000CF56600025C0B063FFD0D79063FFDD008E +:10404000009D139C14DA20DB70580B168B158C1412 +:104050008D1365A06A8E6263FFCC00DA208B11DCC1 +:1040600040580ABCD6A08B15C051DE70DA20DC6047 +:10407000DD405BFF768D138C14D9A02E200C1BE243 +:104080004D1FE2540CEA11AFEFC0E0ABAA2BA285A2 +:104090002EF4CF0B990B29A68563FF1D00DA20DCD7 +:1040A00060DD40DE708912282007DF50A9882824AF +:1040B000075BFF09D2A0D10F00DBE0DA20580B37F5 +:1040C0006550EF2A20140A3A4065A0EBDB60DC4023 +:1040D000DD30022A025809A7D6A064A0D584A183A6 +:1040E000A00404470305479512036351C05163FEC2 +:1040F0005C2C2006D30F28CCFD6480A568C704C0C3 +:10410000932924062C2006C0B18D641FE22C9D2724 +:104110009D289D298FF29D2600F10400BB1A00F016 +:1041200004B0BE0EDD01C0F0ADBB8D652F24070DC0 +:104130000E5E01EE11AEBB2E0AFEB0BB0B0B190ECC +:10414000BB36C0E20B0B470EBB372B241618E224FC +:104150000A09450D0B422B240B29240AB4BE2E2438 +:104160000C7D88572920162FCCFDB09D0A5C520D7E +:10417000CC362C246465FDEC0C0C4764CDE618E2CB +:104180000F8E2888820C9F0C00810400FF1AAFEE6E +:104190009E2963FDCF1CE23E63FE13001CE23563E3 +:1041A000FE0C8D6563FFA500DA202B200C580B2038 +:1041B000645F0FC020D10F00C020D10FC09329240D +:1041C00016C09363FFA000006C1004C06017E1F8F4 +:1041D0001DE1FBC3812931012A300829240A78A175 +:1041E00008C3B27BA172D260D10FC0C16550512605 +:1041F00025022AD0202F200B290AFB2B20142E2049 +:104200001526241509BB010DFF0928F11C2B2414C8 +:10421000A8EE2EF51C64A0A92B221E28221D011138 +:10422000027B8901DB6064B0172CB00728B000DA8C +:104230002007880A28824CC0D10B8000DBA065AF24 +:10424000E7DB30DC40DD50DA205800DE29210209AE +:104250000B4CCAB2D2A0D10F00CC5A2C30087BC173 +:10426000372ED02064E02D022A02033B02DC40DD21 +:10427000505800D4D2A0D10F2B2014B0BB2B241443 +:104280000B0F4164F0797CB7CAC0C10C9C022C258D +:1042900002D2A0D10FC020D10F2E200669E2C12684 +:1042A00024062B221E2F221D29200B2820150D99B4 +:1042B000092A911C262415AA8828951C7BF149609F +:1042C0000048B0BB2B24140B0A4164A0627CB702E7 +:1042D0002C25022B221E2C221DD30F7BC901C0B01E +:1042E000C9B62CB00728B000DA2007880A28824C0B +:1042F000C0D10B8000DBA065AFE7C020D10F00006C +:10430000262406D2A0D10F0000DB601DE1AC64BF03 +:104310004F2CB00728B000DA2007880A28824CC04A +:10432000D10B8000DBA065AFE71DE1A463FF310086 +:1043300026240663FF9C00006C1004282006260A31 +:10434000046F856364502A2920147D9724022A0271 +:10435000DB30DC40DD50580019292102090A4CC825 +:10436000A2C020D10FC0B10B9B022B2502C020D1CF +:104370000F00022A02033B022C0A015800D1C9AAED +:10438000DA20DB30DC405809F329A011D3A07E9756 +:10439000082C0AFD0C9C012CA411C0512D201406E0 +:1043A000DD022D241463FFA4DA20DB30DC40DD5075 +:1043B000C0E0580973D2A0D10F0000006C1006169F +:1043C000E17D1CE17D655157C0E117E179282102AB +:1043D0002D220008084C6580932B32000B6951296F +:1043E0009CFD6590872A629E6EA84C2A722668A062 +:1043F000027AD9432A629DCBAD7CBE502B200C0C97 +:10440000BD11A6DD28D2862F4C0478FB160CBF0AFE +:104410002FF2A368F0052822007F89072DD285D3CB +:104420000F65D0742A210419E1A3D30F7A9B2EDAE9 +:104430002058086E600035002D21041BE19E7DBBD5 +:1044400024DA20C0B6580869CA546001030B2B5007 +:104450002B240BB4BB0B0B472B240C63FFA0DA20DF +:10446000580A4E600006DA20C0B6580A4C6550E083 +:10447000DC40DB302D3200022A020D6D515808BDA0 +:104480001CE14ED3A064A0C8C05184A18EA0040436 +:10449000470E0E4763FF3500002B2104C08C893185 +:1044A000C070DF7009F950098F386EB8172C20667C +:1044B000AECC0C0C472C24667CFB099D105808CF11 +:1044C0008D1027246694D11EE151B8DC9ED0655032 +:1044D00056C0D7B83AC0B1C0F00CBF380F0F42CBAE +:1044E000F119E13018E13228967EB04BD30F6DBA46 +:1044F0000500A08800C08C2C200CC0201DE1360CCB +:10450000CF11A6FF2EF285ADCC27C4CF0E4E0B2EB9 +:10451000F685D10FC0800AB83878D0CD63FFC100CE +:104520008E300E0E4763FEA12A2C742B0A01044D17 +:10453000025808C22F200C12E1270CF911A699A2EB +:10454000FF27F4CF289285D2A008480B289685D162 +:104550000FC020D10F0000006C1004C060CB55DBF1 +:1045600030DC40055D02022A025BFF94292102092A +:10457000084CC882D2A0D10F2B2014B0BB2B24141E +:104580000B0C41CBC57DB7EBC0C10C9C022C2502A6 +:10459000D2A0D10F0000022A02033B02066C02C027 +:1045A000D0C7F72E201428310126250228240A0F0F +:1045B000EE012E241458010E63FFA300262406D218 +:1045C000A0D10F006C1006282102D62008084C65E7 +:1045D000809D2B200C12E0F70CB811A2882A82864D +:1045E000B5497A930260009719E0F409B90A299253 +:1045F000A36890082A620009AA0C65A08228828517 +:104600001CE0FF6480799C80B887B14B9B819B1034 +:10461000655074C0A7D970280A01C0D0078D380D25 +:104620000D42CBDE1FE0E01EE0E12EF67ED830D357 +:104630000F6D4A0500808800908C2E3008C0A000C5 +:10464000EE322E740028600C19E0E30C8D11A2DD0F +:10465000A988C0202CD2852284CFD2A00CBC0B2CE0 +:10466000D685D10FC0F0038F387FA0C063FFB400A0 +:10467000CC582A6C74DB30DC405807F6C020D10FD0 +:10468000DA605809C663FFE7DD402A6C74C0B0DC0D +:104690007058086A2E30088B1000EE322E740028F5 +:1046A000600C19E0CC0C8D11A2DDA988C0202CD2A1 +:1046B000852284CFD2A00CBC0B2CD685D10F000054 +:1046C0006C1004292014282006B19929241468812B +:1046D00024C0AF2C0A012B21022C24067BA004C08D +:1046E000D02D2502022A02033B02044C02C0D058FE +:1046F00000C0D2A0D10FC020D10F00006C1004293F +:104700003101C2B429240A2A3011C28378A16C7BFA +:10471000A1696450472C2006C0686FC562CA572D36 +:1047200020147CD722DA20DB30DC40DD505BFFA593 +:10473000292102090E4CC8E2C020D10FC0F10F9F01 +:10474000022F2502C020D10FDA20DB30C0C05BFF72 +:10475000DC28201406880228241463FFC7292015AA +:104760001BE0972A200BC0C09C240BAA092BA11C7C +:104770002C2415AB9929A51C63FF9900C020D10FEB +:10478000DA20DB30DC40DD50C0E058087DD2A0D11B +:104790000F0000006C1004CB5513E09225221F0D72 +:1047A000461106550CA32326221E25261F06440B60 +:1047B00024261E734B1DC852D240D10F280A80C038 +:1047C0004024261FA82828261E28261DD240D10FA7 +:1047D000C020D10F244DF824261E63FFD80000000E +:1047E0006C1004D620282006C0706E85026000D4AC +:1047F0001DE07919E07112E06F2A8CFC64A1302B66 +:104800006102B44C0B0B4C65B0A22B600C8A600C9F +:10481000B8110288082E828609B90A7EC302600098 +:104820009A2992A368900509AA0C65A08E28828512 +:10483000648088B8891BE07594819B80655155C060 +:10484000B7B8382A0A01C0C009AC380C0C4264C0A1 +:10485000421FE0541EE0562EF67EB04AD30F6DAADA +:104860000500808800908CC0A029600C0C9C11A2CF +:10487000CC2BC285AD990B4B0B2BC6852860062728 +:1048800094CF6881222D6015D2A0C9D2C0E22E64D7 +:1048900006D10F00C0F008AF387FB0BD63FFB10094 +:1048A000276406D2A0D10F00D2A0D10F00CC57DAD6 +:1048B00060DB30DC405808A7C020D10FDA6058090F +:1048C0003763FFE80028221E29221DD30F789901A3 +:1048D000C080C1D6C1C11BE043C122AB6B64804222 +:1048E00078913F2A80000CAE0C64E0BB02AF0C64F0 +:1048F000F0B52EACEC64E0AF0DAF0C64F0A92EACBB +:10490000E864E0A32FACE764F09D2EACE664E0978A +:104910002F800708F80BDA807B83022A8DF8D8A055 +:1049200065AFBC28612308D739D97060007B0000CF +:104930002B600C0CB811A2882C82862A0A087CAB4A +:104940007E09BA0A2AA2A368A0052C62007AC96F60 +:104950002A828564A0691FE029276504C0E3C0C4DA +:104960002E64069CA11CE0549FA02E600A97A30C05 +:10497000EE029EA28F600CFF029FA42E60147AEFBD +:104980004627A417ADBC2F828527C4CF2FFC202F2C +:10499000868563FE692A6C74C0B1DC90DD405807DF +:1049A000A71DE00C63FEC100D9A0DA60DB30C2D0E5 +:1049B000C1E0DC4009DE39DD505807F1D2A0D10F4B +:1049C000DA605808F663FEE4290A0129A4170DBF2E +:1049D000082E828527F4CF2EEC202E868564500B7E +:1049E0002A6C74DB4058016AD2A0D10FC020D10FCD +:1049F0006C10062B221E28221D93107B8901C0B04B +:104A0000C0C9C03BC1F20406401DDFF6C0E2C0745D +:104A10000747010E4E01AD2D9E11C0402E0A1464B1 +:104A2000B06E6D084428221D7B81652AB0007EA1EE +:104A30003B7FA1477B51207CA14968A91768AA1434 +:104A400073A111C09F79A10CC18B78A107C1AE29B8 +:104A50000A1E29B4007CA12B2AB0070BAB0BDAB0DD +:104A60007DB3022ABDF8DBA0CAA563FFB428B0104D +:104A700089116987BB649FB863FFDC00647FB463FE +:104A8000FFD50000646FD0C041C1AE2AB40063FFFF +:104A9000C62B2102CEBE2A221D2B221E7AB12A8CC1 +:104AA000107CB1217AB901C0B0C9B913DFC1DA20D5 +:104AB00028B0002CB00703880A28824CC0D10B8094 +:104AC00000DBA065AFE7D240D10F8910659FD463AA +:104AD000FFF300006C1008C0D0C8598C30292102A7 +:104AE0000C0C4760000C8E300E1E5065E19E292193 +:104AF00002C0C116DFB0090B4C65B0908A300A6E57 +:104B00005168E3026000852F629E1BDFA96EF85397 +:104B10002BB22668B0052E22007BE94727629DB79D +:104B200048CB7F97102B200CB04E0CBF11A6FF294D +:104B3000F2869E12798B4117DFA007B70A2772A36E +:104B4000687004882077893029F285DF90D79065D6 +:104B500090652A210419DFD77A9B22DA205806A310 +:104B6000600029002C21041BDFD37CBB18DA20C095 +:104B7000B658069EC95860014CC09063FFCCDA203D +:104B8000580886600006DA20C0B65808846551359A +:104B9000DC40DB308D30DA200D6D515806F6C0D088 +:104BA000D3A064A120292102C05184A18CA00404B7 +:104BB000470C0C4763FF3E00C09C8831DBD008F8EF +:104BC00050089B3828210498116E8823282066AC51 +:104BD0008C0C0C472C24667CBB159F139E148A10EA +:104BE0008B115807068E148F13C0D02D24668A307F +:104BF000C092C1C81BDF867FA6099BF099F12CF4F7 +:104C00000827FC106550A4B83ADF70C051C0800777 +:104C1000583808084264806718DF6319DF64298602 +:104C20007E6A420AD30F6DE90500A08800F08CC0AF +:104C3000A08930B4E37F9628C0F207E90B2C9408D2 +:104C40009B909F912F200C12DF630CF811A68829EE +:104C50008285A2FF2DF4CFD2A009330B238685D104 +:104C60000F22200C891218DF5B0C2B11A6BBA82287 +:104C70002D24CF2CB285D2A00C990B29B685D10F4B +:104C8000C087C0900A593879809663FF8ADB30DA92 +:104C900020C0C1C0D05BFF56292102C0D02A9CFE93 +:104CA00065AE4D2D2502C09063FE45009E142A2C52 +:104CB00074C0B1DC70DD405806E18E14C0D01BDF3B +:104CC00053C1C863FF6AC020D10F00006C100628D2 +:104CD000210216DF3808084C65821929629E6F98F8 +:104CE0000260022019DF332992266890078A200982 +:104CF000AA0C65A20F27629DC0CC6472072B210409 +:104D00008E31C0A0DDA00EFE500ECD386EB8102C36 +:104D10002066B1CC0C0C472C24667CDB026001EFD2 +:104D2000C0C12930081BDF2564909C2F0AFFC0D327 +:104D3000B09E64E1026892136450882A2C74044B7C +:104D4000025800930AA20206000000002B200C2744 +:104D500021040CBC11A6CC29C286280A087983023A +:104D60006001B919DF1509B90A2992A36890082EC4 +:104D7000220009EE0C65E1A42EC28564E19E262086 +:104D80000713DF1E6E7B0260019A17DF151FDF1EFF +:104D900019DF4BC0D228200A93E09DE1A9690F8852 +:104DA0000298E22F90802A9480B1FF07FF029FE3D0 +:104DB0002EC2851FDF080EDE0BAFBF2AF4CF2EC632 +:104DC00085655F76C020D10F2830102930112E3034 +:104DD0001300993200ED326480EE2A30141FDF3860 +:104DE00000AA3278EF050F9E092DE47F1EDF36669C +:104DF000A0050F98092A8480B4A718DF33C76F0075 +:104E00009104AE9EDDE000AF1A00C31A6EE1052DDD +:104E1000B2000DED0C1EDF2D08D81C063303AE8842 +:104E20002A848B2EB02E27848C03EE010FEE022EE7 +:104E3000B42E58018F63FEFF29310829250428303C +:104E4000142E3109B0886480A32E240AC0812E302C +:104E5000162CB4232E240BB4EF2F240C8C378B3656 +:104E6000292504DEB0DFC00C8F390B8E390FEE021E +:104E700064EEC4089F1101C4048D380CB81800C436 +:104E8000040CBE1800EE110EDD02C0E30EFF021E80 +:104E9000DF019F719E701EDF008F2098739D740547 +:104EA000FF110BCD53C18098750FDD020EDD029D01 +:104EB000721EDEBF2A24662F629D2AE4A22FFC18F0 +:104EC0002F669D63FE710000002F30121BDF010072 +:104ED000FA3278FF050B980B2A847F66D0050B9A6F +:104EE0000B2DA4802A301100AA3263FF442F240A1C +:104EF0009E2B63FF56CC57DA20DB30DC4058071579 +:104F0000C020D10F00DA20C0B65807A463FFE50027 +:104F1000DA7058063AC0A02A246663FE02DA2058E6 +:104F2000079F63FFCFB16928200A862009094799A6 +:104F30001129240798107F812693E027E50A9AE338 +:104F400088109DE119DEDD8D11096F029FE42DE4CB +:104F500016098802C0D398E22A240763FE51000094 +:104F60001DDEA60868118F11892B93E008FF02C08F +:104F70008F9FE50D990299E2047F11C0D49DE1084D +:104F8000FF029FE463FFD0006C1004C020D10F002B +:104F90006C100485210D381114DE848622A42408A7 +:104FA000660C962205330B9321743B13C862D230F2 +:104FB000D10FC030BC29992199209322D230D10F32 +:104FC000233DF8932163FFE36C100AD62094181751 +:104FD000DE79D930B83898199914655252C0E1D2A7 +:104FE000E02E61021DDE760E0E4C65E1628F308E82 +:104FF000190F6F512FFCFD65F1558EE129D0230E5D +:105000008F5077E66B8F181EDEB3B0FF0FF4110FD1 +:105010001F146590CE18DEB08C60A8CCC0B119DE2C +:105020006428600B09CC0B0D880929811C28811A82 +:105030002A0A0009880C08BA381BDEA60CA90A291E +:1050400092947B9B0260008C2B600C94160CBD111B +:10505000A7DD29D286B8487983026000D219DE56CE +:1050600009B80A2882A398176880026000A360002C +:10507000A51ADE9A84180AEE01CA981BDE4D8C1917 +:105080002BB0008CC06EB3131DDE4A0C1C520DCC2D +:105090000B2DC295C0A17EDBAE6000380C0C5360B6 +:1050A000000900000018DE8C8C60A8CCC0B119DEAD +:1050B0004028600B09CC0B0D880929811C28811A16 +:1050C0002A0A0009880C08BA380CA90A2992947E89 +:1050D000930263FF72DA60C0BA580730645073609D +:1050E000026600001ADE338C192AA0008CC06EA361 +:1050F0001A18DE2F0C1C5208CC0B18DE762BC2952A +:10510000C0A178B30263FF3F63FFC9000C0C536377 +:10511000FF09896078991829D285C9922B729E1D42 +:10512000DE246EB8232DD226991369D00B60000DB2 +:10513000DA6058071A6000170088607D890A9A1A99 +:1051400029729D9C129915CF95DA60C0B658071345 +:105150006551F58D148C18DBD08DD0066A020D6D6B +:1051600051580584D3A09A1464A1DD82A085A1B80A +:10517000AF9F190505470202479518C05163FE60AD +:105180002B6104C08C8931C0A009F950098A386E9E +:10519000B81F2C6066A2CC0C0C472C64667CAB114B +:1051A0009F119E1B8A155805958E1B8F11C0A02A32 +:1051B00064669F1164F0E12912032812096DF91742 +:1051C0002F810300908DAEFE0080889F9200908C0E +:1051D000008088B89900908C65514E8A10851A8B92 +:1051E000301FDE06881229600708580A2C82942D89 +:1051F00061040ECC0C2C86946FDB3C1CDE30AC9C26 +:1052000029C0800B5D50A29909094729C48065D047 +:10521000DA2E600CC0D01FDDEF0CE811AFEEA788CE +:105220002282852DE4CF02420B228685D2A0D10FA7 +:105230008E300E0E4763FDA6A29C0C0C472C640713 +:105240007AB6CD8B602E600A280AFF08E80C6481CC +:105250000E18DE1983168213B33902330B2C341661 +:105260002D350AC02392319F30C020923308B202FC +:1052700008E80292349832C0802864072B600CD270 +:10528000A01CDDD40CBE11A7EE2DE285ACBB28B46A +:10529000CF0D9D0B2DE685D10F8B1888138D30B85F +:1052A0008C0D8F470D4950B4990499100D0D5F0472 +:1052B000DD1009FF029F800DBB029B8165508D852B +:1052C0001AB83AC0F1C0800CF83808084264806B04 +:1052D0001BDDB519DDB629B67E8D18B0DD6DDA059A +:1052E00000A08800C08CC0A063FEF30082138B1660 +:1052F0001DDDC628600AC0E02EC4800D880202B2FF +:105300000B99239F20C0D298229D2122600CB2BB12 +:105310000C2D11A7DD28D28508BB0B18DDAE2BD6CE +:1053200085A8222E24CFD2A0D10F9E1B851A2A6CCD +:10533000748B185BFF178E1B63FEA300C087C090A1 +:105340000AF93879809263FF86C020D10F9E1B2A0C +:105350006C74C0B18D185805398E1B851A63FE7E9A +:10536000886B8213891608BE110ECE0202920B9E24 +:1053700025B4991EDDA19F200E88029822C0EF045B +:10538000D8110E88029824C0E49E21C080D2A02BA0 +:10539000600C2864071CDD8F0CBE11A7EE2DE28582 +:1053A000ACBB28B4CF0D9D0B2DE685D10F000000BE +:1053B0006C1004C020D10F006C10048633C071C083 +:1053C00030600001B13300310400741A04620174CA +:1053D00060F1D10F6C1004022A02033B025BFFF65E +:1053E0001CDD771BDDBFC79F88B009A903098A01AF +:1053F0009AB079801EC0F00FE4311DDD6E0002000E +:105400002BD2821EDDB82AC1020EBB022BD6820A25 +:10541000E431D10F28C102C19009880208084F2841 +:10542000C50208E431D10F006C1004C0C00CE43197 +:1054300012DD631ADD6000020029A28218DDAC1BB8 +:10544000DDAA2621020B990108660129A6822625DC +:105450000206E43114DDA715DDA2236A902326128B +:105460008550242611252613222C40D10F00000040 +:105470006C1008D6102B0A64291AB41ADD4D0D23BE +:10548000111CDD4E0F2511B81898130E551118DD9B +:1054900099AC55A838AA332C80FF2A80FEA933285E +:1054A0008D0129800108AA112880000CAA02088811 +:1054B0001109880208AA1C288C08281604580862BA +:1054C00014DD3F0AA7022441162A30802B1204075C +:1054D000AA2858085DB1338B13B4559A6004AC28E0 +:1054E000B4662C56277B69E016DD769412C050C056 +:1054F000D017DD329D15D370D4102F60802E6082BE +:105500009F169E17881672891A8D128C402A607F0A +:105510000DCC282B3A200CAA2858084BC0B10ABE43 +:10552000372E35408F1772F91A8D128C402A608100 +:105530000DCC282B3A200CAA28580843C0B10ABE2B +:10554000372E3542B233B444B1556952B6B466C051 +:10555000508F15B877D370B2FF9F156EF899D10FA1 +:105560006C1004C021D10F006C1004270A001CDD50 +:10557000111FDD221EDD251DDD0E1ADD501BDD5E37 +:10558000C02824B0006D2A75AA48288080C0916484 +:10559000806100410415DD09C03125502E00361A06 +:1055A0000655010595390C56110C66082962966E50 +:1055B000974D0D590A29922468900812DD42024243 +:1055C0000872993B23629512DD06CB349F3002822C +:1055D000020E4402C092993194329233AD52246249 +:1055E00095C090244C1024669524B0002924A0AACC +:1055F00042292480B177B14404044224B400D10F7D +:10560000D10FD10F6C10041ADCEA2AA00058021C3A +:105610005BFFD5022A02033B025BFFD11BDCE8C91A +:10562000A12CB102C0D40DCC020C0C4F2CB5020C35 +:10563000E431D10FC0A00AE43118DCDE0002002FF3 +:10564000828219DCF12EB10209FF022F86820EE45C +:1056500031D10F006C1004C02002E43114DCD816E4 +:10566000DCD5000200226282234102732F0603E48C +:1056700031C020D10F19DD221ADD212841020A2A6A +:10568000010988012A668228450208E43115DD18DF +:1056900012DD1D25461DD10F6C1004292006289C03 +:1056A000F96480A02A9CFD65A0968A288D262F0A81 +:1056B000087AD9042B221FC8BD2C206464C0812E17 +:1056C00022090EAE0C66E0782B200C1EDCBA0CBC56 +:1056D00011AECC28C28619DCB878F3026000AD099F +:1056E000B90A2992A36890082E220009EE0C65E001 +:1056F0009B29C2851FDCC26490929F90C0E41FDC8E +:10570000CE9E9128200AC0E09E930F88029892882E +:10571000200F880298942F20079A979D962F950A1C +:105720002E240728200629206468833328C2851286 +:10573000DCA9288C20A2B22E24CF28C685C020D177 +:105740000FC020D10F2A206A0111020A2A4165AF39 +:1057500052DA20C0B05805E464AFE5C021D10F0093 +:10576000649FC81FDC962D20168FF209DD0C00F116 +:105770000400DD1AADAD9D2912DC9728C285A2B2C6 +:105780002E24CF288C2028C685C020D10FC021D13F +:105790000F0000006C1004260A001BDCDB15DC8700 +:1057A00028206517DC84288CFE6480940C4D110D34 +:1057B000BD082CD2F52BD2F42ED2F77CB13DB4BB70 +:1057C0002BD6F47BE9052BD2F62BD6F47CB92C2A08 +:1057D000D2F62AD6F52AD6F406E431000200287261 +:1057E000822AFAFF004104290A012F510200991A66 +:1057F0000A99030988012876820FE4312624652B53 +:10580000D2F48E5A2CD2F5B0EE9E5A7BCB1629D20A +:10581000F62FD2F70CB80C09FF0C08FF0C0F2F1451 +:10582000C8F96000320BCA0C0A2A14CEA92B510207 +:10583000C0C20CBB020B0B4F2B55020BE431D10F36 +:1058400000DB30DA205BFF941BDCB064AF5D0C4DF5 +:1058500011ADBD63FFA8000006E4310002002F7205 +:105860008218DC6E2E510208FF022F76820EE43180 +:10587000D10F00006C1004C03003E43116DC4E156B +:10588000DC4F00020024628274472118DCA0875A92 +:10589000084801286682CD7319DC9E0C2A11AA994A +:1058A0002292832992847291038220CC292B510267 +:1058B0000BE431C020D10F001FDC972E51020FEEF8 +:1058C000012E55020EE431B02DB17C9C5A12DC92AF +:1058D00008DD112D5619D10F6C10061BDC351EDCAE +:1058E0003722B0001ADC8E6F23721DDC75C0481899 +:1058F000DC8D1FDC8BDC10D5C083F000808600506F +:105900008A6D4A4F0F35110D34092440800B560A19 +:10591000296294B1330E55092251400F44110C44B1 +:105920000A874009A80C02883622514107883608A8 +:10593000770CA8992966949740296295874109A810 +:105940000C02883607883608770CA899296695973F +:1059500041030342B13808084298F0D10F1CDC72B1 +:1059600013DC7327B0002332B5647057C091C0D0E8 +:1059700016DC7115DC6FC0402AC00003884328C4C0 +:10598000006D793C004104B14400971A7780148E71 +:10599000502FB2952DB695AFEE2EED2006EE369E29 +:1059A0005060001877A00983509D5023B695600081 +:1059B0000223B295223D2006223622B695B455B870 +:1059C000BBD10F0003884328C400D10F6C1004C062 +:1059D0004004E43115DC59000200885013DC58CB38 +:1059E000815BFFBD1CDC570C2D11ADCC2BC2822A74 +:1059F000C28394507BAB142EC28429C2850ABD0C8D +:105A00000E990C0D990C0929146000050BA90C09BD +:105A10002914993015DBEA2A51020AE4312A2CFCB8 +:105A200058004B2B32000AA2022BBCFF9B30CCB695 +:105A3000C8A4D2A0D10F000004E4311EDBDE0002B6 +:105A4000002DE2822FBAFF2C51020FDD012DE682DC +:105A50000CE431D10F0000006C1004D10F000000E5 +:105A60006C1004C020D10F006C100413DC36C0D1C0 +:105A700003230923318DC0A06F340260008D19DB30 +:105A8000CD1BDBCE17DC2F0C2811A87726728325BF +:105A900072822CFAFF76514788502E7285255C045D +:105AA00025768275E9052572842576827659292E18 +:105AB00072842E76822E76830AE4310002002392CD +:105AC000820021042FB10200D61A0C6603063301AE +:105AD0002396820FE43126728325728260000200D1 +:105AE000D8A07659220AE4310002002392820021D4 +:105AF0000400D21A2FB1020C220302320122968234 +:105B00000FE431D280D10F00D280D10FC020D10F4D +:105B10006C1004DB30862015DBA6280A002825023D +:105B2000DA2028B0002CB00705880A28824C2D0AFC +:105B3000010B8000DBA065AFE61ADB9F0A4A0A2949 +:105B4000A2A3C7BF769101D10F2BA6A3D10F00004E +:105B50006C1004C0D1C7CF1BDB9919DB9617DB94FF +:105B60000C2811A87786758574C0A076516288507C +:105B70008E77B455957475E90385769574765927B3 +:105B80008F769F759F740AE431000200239282B4DD +:105B90002E2FB10200E10400D61A0C660306330171 +:105BA0002396820FE431867583747639280AE431AE +:105BB0000002002E9282B42200210424B10200DFF0 +:105BC0001A0CFF030FEE012E968204E431D280D12D +:105BD0000FD8A07651D6D280D10F00006C100429C6 +:105BE0000A801EDB9A1FDB9A1CDB730C2B11ACBBEB +:105BF0002C2CFC2DB2850FCC029ED19CD0C051C064 +:105C00007013DB9614DB9518DB932AB285A8280461 +:105C1000240A234691A986B8AA2AB685A98827848A +:105C20009F25649FD10F00006C100419DBC70C2A5C +:105C300011A9A98990C484798B761BDBB5ABAC2AFA +:105C4000C2832CC2847AC1688AA02BBC30D3A064E2 +:105C5000A05E0B2B0A2CB2A319DB7F68C0071DDBEB +:105C6000BBD30F7DC94AA929299D0129901F68919D +:105C70003270A603D3A0CA9E689210C7AF2AB6A3FB +:105C80002A2CFC5BFFB3D230D10F000013DBB10331 +:105C9000A3018C311DDB510C8C140DCC012CB6A34F +:105CA00063FFDC00C020D10FDA205BFFCCC020D125 +:105CB0000FC020D10F0000006C1004DB30C0D019E1 +:105CC000DB3CDA2028300022300708481209880A15 +:105CD00028824CDC200B80001BDB370C4A11ABAA5E +:105CE00029A28409290B29A684D10F006C1004C0B5 +:105CF0004118DB3017DB320C2611A727277030A89C +:105D000066256286007104A35500441A7541482235 +:105D1000628415DB5202320BC922882117DB2F085F +:105D20008414074401754905C834C020D10FD10F30 +:105D30000809471DDB86C0B28E201FDB1D0E0E43F7 +:105D4000AFEC2BC4A00FEE0A2DE6242A6284C020FB +:105D50000A990B296684D10FC020D10F6C1004DB87 +:105D600030C0D018DB13DA20253000223007085865 +:105D70000A28824CDC200B80008931709E121BDBCC +:105D80000D0C4A11ABAA29A28409290B29A684D19A +:105D90000F09C95268532600910418DB08C0A12FCF +:105DA000811200AA1A0AFF022F85121EDB020C4D77 +:105DB00011AEDD2CD2840C2C0B2CD684D10FC081DB +:105DC0001FDAFFB89A0A0A472EF11200A1040088D0 +:105DD0001A08EE022EF5121DDAF70C4C11ADCC2B81 +:105DE000C2840B2B0B2BC684D10F00006C1004DB7C +:105DF00030C0D019DAEFDA202830002230070988C5 +:105E00000A28824CDC200B80001CDAEA0C4B11AC17 +:105E1000BB2AB2840A2A0B2AB684D10F6C1004C0A4 +:105E20004118DAE416DAE60C2711A626266030A817 +:105E300072252286006104A35500441A7541082288 +:105E4000228402320BD10F00C020D10F6C10041538 +:105E5000DB410249142956112452120208430F88CB +:105E600011C07300810400361A008104C78F0077C7 +:105E70001A087703074401064402245612D10F0082 +:105E80006C10066E23026000AC6420A7C0A08510D1 +:105E900013DB1916DB30C040A6AA2BA2AE0B1941AA +:105EA00064906668915D68925268933C2AA2AA2821 +:105EB0003C7F288C7F0A0A4D2980012880002AAC6B +:105EC000F20888110988027589462B3D0129B00026 +:105ED0002BB0010899110B99027A9934B8332A2A08 +:105EE00000B1447249B160004A7FBF0715DB1B63F4 +:105EF000FFB90000253AE863FFB10000253AE863E6 +:105F0000FFA90000250A6463FFA1C05A63FF9C003B +:105F100000705F082534FF058C142C34FE70AF0B25 +:105F20000A8D142E3D012AE4012DE400DA405BFDC8 +:105F30005063FFA7D10FD10F6C10041ADAA019DA41 +:105F40009D1CDB061BDB07C080C07160000D0000DC +:105F50000022A430B1AA299C107B915F26928679F9 +:105F6000C2156E6262C0206D080AB12200210400D1 +:105F7000741A764BDB63FFEE2292850D63110325C5 +:105F800014645FCFD650032D436DD9039820B422FB +:105F90000644146D49229820982198229823982429 +:105FA00098259826982798289829982A982B982CED +:105FB000982D982E982F222C4063FF971EDA7E276B +:105FC000E68027E681D10F00C02063FF8300000038 +:105FD0006C1004C062C04112DA791ADA7513DAE182 +:105FE0002AA00023322D19DADB2BACFE2992AE6EEB +:105FF000A30260008E090E402D1AC2C2CD0EDC39FC +:106000002C251664B0895BFF9E15DAD71ADAD12BDE +:106010003AE80A3A0158058C2B21160ABB28D3A06E +:106020009B505805A32B52000ABB082A0A005805AA +:10603000A215DACE2D21022C3AE80C3C2804DD0210 +:106040002D25029C5058059A8B50AABBC0A158051B +:106050009A1CDAC72D21020C3C2806DD0213DAC592 +:106060002D25029C305805928B30AABBC0A2580542 +:10607000922A2102C0B40BAA020A0A4F2A2502580A +:1060800005A6D10F242423C3CC2C251663FF76004C +:1060900018DABD1CDAB919DABA1BDAB817DA8B8547 +:1060A000202E0AFD1FDAB92D202E24F47A24F47E46 +:1060B00024F4820EDD0124F4862E0AF70755280603 +:1060C000DD02C0750EDD01050506AB5BA959C0E810 +:1060D000AC5C24C4AB0EDD0227C4AC2E0ADFA8558D +:1060E00027B4EC0EDD0124B4EBC2E027942C0EDDC6 +:1060F0000224942B2E0A800D0D4627546C24546BD9 +:106100000EDD022D242E63FEFC0000006C10042A1C +:106110000A302B0A035BFF4D12DA8FC39029261633 +:10612000C3A1C0B3C08A2826175BFF48C03CC3B1D7 +:106130002B26161ADA222AA02023261764A079C358 +:10614000A2C0B15BFF42C3A2C0B15BFF40C3C22C7F +:106150002616C2AFC0B12326175BFF3CC28F28268C +:1061600016C0FE2F2617C2E22E26162A0AA1C0B19B +:10617000C0D82D26175BFF352A0AA12A2616C3A6EA +:10618000C0B3C1922926175BFF31C3C62C2616C1A6 +:10619000B32A0AA22B2617C0B35BFF2C290AA22917 +:1061A0002616C185282617C2FB2F2616C0E72E26E5 +:1061B000171DDA762D2610D10FC3A2C0B35BFF23C3 +:1061C00063FF82006C10041CDA3F1BDA2C18DA70B3 +:1061D00017DA7116DA7115DA71C0E0C0D414DA3B3F +:1061E0001FD9F7C0288FF06D2A36DAC0D9C07C5B82 +:1061F000020FC90C1CDA350C9C28A8C3A6C22A368B +:10620000802A2584A4C2A7CC2D248C2B248A2B245D +:10621000872E248BB1BB2E369F2C369E2C369DB1FB +:10622000AC1CDA161BDA5FC0286D2A33DAC0D9C07D +:106230007C5B020FC90C1CDA240C9C28A8C3A6C2E4 +:106240002A36802B2584A4C2B1BBA7CC2D248C2E4A +:10625000248B2A248A2E369F2C369E2C369DB1AC58 +:10626000C07919DA141BDA5113DA4F1ADA4F18DA37 +:106270005014DA1516DA5004F42812DA4F04660CBA +:10628000040506A252A858AA5AA3539B3029A50078 +:1062900027848AC091C0A52A848C29848B17DA4868 +:1062A00018DA47A75726361D26361E2E361F16DA51 +:1062B0004513DA45A65504330C2826C82E75002D43 +:1062C00054AC2E54AB2E54AA2326E62326E52E26C4 +:1062D000E7D10F006C100613DA2317DA1E24723D83 +:1062E0002232937F2F0B6D08052832937F8F026334 +:1062F000FFF3C0C4C0B01AD9B1C051D94004593954 +:1063000029A4206E44020BB502C3281ED9ACDDB00F +:1063100025E422052D392DE421C0501EDA2C19DA8E +:106320001C18DA1C16DA1E1DDA2A94102A72451778 +:10633000D9E76DA94BD450B3557A5B17DF50756B15 +:10634000071FD99E8FF00F5F0C12D9DF02F228AE23 +:106350002222D681D54013D9DC746B0715D99885D4 +:106360005005450C035328B145A73FA832A9332255 +:10637000369D22369E2436802B369F2BF48B2CF4B0 +:106380008C14D9F824424DC030041414C84C6D0844 +:1063900006B133041414C84263FFF20015D985C452 +:1063A000400031041AD986C0D193A200DD1AC13849 +:1063B000B0DD9DA318D9EC2B824D29824E29A51C56 +:1063C0002882537A871E2C54008E106FE45D12D9F8 +:1063D0007B2F211D23211C2F251B04330C23251C5F +:1063E00023251AD10FC06218D9DB88807E87D9890E +:1063F000102654006F94191BD9712AB11C0A1A1463 +:1064000004AA0C2AB51C2AB51D2AB51A2AB51BD117 +:106410000F1BD96A2AB11C0A1A1403AA0C2AB51C2C +:106420002AB51D2AB51A2AB51BD10F001CD9642B19 +:10643000C11D2DC11C2BC51B03DD0C2DC51C2DC57D +:106440001AD10F006C100619D95D14D9C212D9C522 +:1064500015D9E0C73FC0E02E56A82E56A92E56AA41 +:106460002E56AB23262918D985DB101CD9DAC0D4C7 +:106470002A42452D16019C1000B0890A880C2896E6 +:10648000005BFF942B22E318D94D0B5B149B842AED +:1064900022E48B84B1AA0A5A140BAA0C9A852922E9 +:1064A000E509591499862F22CD0F5F149F875BFF52 +:1064B000455BFF1623463BC1B01DD9401CD99E2A1F +:1064C000D1022C463A0BAA020A0A4F2AD5025804D6 +:1064D000925BFEBF5BFE98C050C0B016D93614D98F +:1064E0003E17D9AEC0C0C73E93122C262DC03060D7 +:1064F00000440000007F9F0FB155091914659FF4F7 +:10650000C0500AA9027FA7EF18D92ADA5008580A02 +:1065100028822C2B0A000B8000005104D2A0C091CD +:10652000C7AF00991A0A99039912CE3864206BD329 +:10653000202B20072516032C12022A62827CA863D6 +:1065400018D91C01110208580A28822CDA500B8035 +:1065500000D2A0643FD58A310A8A1404AA01C82A4D +:106560002B22010B8B1404BB017BA945DDA07A7B98 +:10657000081DD9122DD2000DAD0CDB3019D90D1A22 +:10658000D95288130ADA28DC801DD99009880A2894 +:10659000823C0DAA080B8000652F93D320C0B06306 +:1065A000FF9400007FAF34B1550050040A0919630D +:1065B000FF42DAB07B7B081AD9012AA2000ABA0C82 +:1065C0001BD9428C310BAB280C8A141CD980ACBB74 +:1065D0001CD98004AA012BC68163FF8F645F60C051 +:1065E00050C0B0C7CE9C1263FF5500006C1004274A +:1065F000221EC08008E4311BD8EF0002002AB282BC +:1066000019D8EF003104C06100661A2991020A6AA4 +:10661000022AB68209E43115D94A0C3811A8532848 +:1066200032822432842A8CFC7841102921022A36B5 +:106630008297A0096902292502D10F002B21022C83 +:1066400032850B6B022CCCFC2C368297C02B25029A +:10665000D10F00006C1004C0E71DD8D21CD8D40D97 +:106660004911D7208B228A200B4B0BD2A007A80CF4 +:106670009B72288CF4C8346F8E026000A31FD8CAA6 +:10668000A298AF7B78B334C93DC081C0F0028F3887 +:106690000F0F42C9FA2CD67ED5206D4A05003088EE +:1066A00000508C887008980878B16DD2A09870D18D +:1066B0000FC0F0038F387FE0DE63FFD8027B0CAFA2 +:1066C000BB0B990C643047D830C0F1C05002F5388C +:1066D0000505426450792CD67E0B36122F6C100FB4 +:1066E0004F366DFA0500808800208C06440CC0816E +:1066F000C05003B208237C0C038538050542645062 +:106700005A2CD67ED30F6D4A0500208800308CD2DB +:10671000A0A798BC889870D10FD2A0BC799970D1ED +:106720000FD2302BAD08C0F1C0500BF53805054233 +:10673000CB542CD67E083F14260A100F660C064652 +:10674000366D6A0500208800B08C827063FF2D00D2 +:10675000C05003F53875E08063FF7A00C0600286A0 +:106760003876E09F63FF9900C05003F53875E0C4A8 +:1067700063FFBE006C1004D62068520F695324DA00 +:1067800020DB30DC405800F3D2A0D10FDA20DB3020 +:10679000DC405800F09A2424240EC02122640FC04B +:1067A00020D10F00B83BB04C2A2C7489242D200E28 +:1067B0002E200FA4DDB1EE2E240FB0DD2D240E28E7 +:1067C00090072D9003A488B088B1DD2D9403289400 +:1067D000075BFFA069511DC0E082242A600F18D812 +:1067E000FE2A240329600E8F2029240708FF029F18 +:1067F000209E64D10FC020D10F0000006C100494C3 +:106800002319D8F6C0B3083A110BAA02992019D857 +:10681000699A2116D867C05028929D2564A2288CB9 +:106820001828969DD10F00006C1004282066C038EF +:10683000232406B788282466D10F00006C100603B5 +:106840005A0C0D36110D5C11D8208B2282210CBB05 +:106850000C06550F9B8202320B928113D853D9201C +:10686000A38F6450561CD84FC0D71BD850A256C017 +:10687000E1C09004E93809094276F34F044302CAA3 +:10688000912BC67ED30F6DAA0500208800308C891D +:1068900081A95909FA0C64A07D99818A8264A00FAC +:1068A000D290D10FC06002E63876D0D763FFD10016 +:1068B000C020BC89998199809282D10F7F230429BD +:1068C0002DF8998165BFD863FFE50000028F0CA306 +:1068D000FF0F3312931003AA0CD3406490402BC6D1 +:1068E0007E8610D30F6D6A0500208800308CBC8234 +:1068F000C090A4F3C041034938090942CA9B2BC682 +:106900007E6DAA0500208800308C0F590CA989BC27 +:1069100099998163FF8400BC89998163FF7C00C0E1 +:106920006002E63876D0B963FFB300C07002473822 +:1069300077D0CD63FFC700006C100414D82AC15271 +:10694000A424CA3128221D73811C292102659016B6 +:106950002A300075A912022A02033B022C3007C01C +:10696000D25801D0653FDCD10F2B300703BB0B0B96 +:10697000BA0274B3022ABDF8D3A063FFC4000000BA +:106980006C1004292006C0706E9741292102C08F27 +:106990002A2014C0B62B240606AA022A24147980C1 +:1069A000022725022A221E2C221D7AC10EC8ABDA2C +:1069B00020DB302C0A00033D025BF80D6450742D7F +:1069C00021020D0D4CC9D3C020D10F00002E9CFB1D +:1069D00064E0822F21020F0F4C65F0911AD7F61C4C +:1069E000D7F429A29EC08A798B5D2BC22668B00499 +:1069F0008D207BD95229A29DC0F364904A97901DA7 +:106A0000D8062E21049D9608EE110FEE029E979E49 +:106A10009118D802C0E527C4A22E24062BA29D2FD0 +:106A200021022BBC3008FF022F25022BA69DC0207F +:106A3000D10F00002F300068F939DA20DB30044C28 +:106A40000258004463FF7700022A022B0A0658000E +:106A5000D3220A00D10F6550102830006889240223 +:106A60002A02033B02DC4058003BC020D10FD27009 +:106A7000D10F00002A2C74033B02044C025BFEF58C +:106A800063FF3B00DB30DC402A2C745BFEF2C0204D +:106A9000D10F00006C1004C83F89268829A399995A +:106AA0002609880C080848282525CC52C020D10F7B +:106AB000DB402A2C745BF936D2A0D10F6C1004D8BD +:106AC00020D73082220D451105220C928264207459 +:106AD00007420B13D7B5D420A383732302242DF8C8 +:106AE000858074514CBC82C0906D081600408800AF +:106AF000708C773903D720C0918680743901D420F7 +:106B000074610263FFE2CA98C097C0411BD835C0C8 +:106B1000A00B8B0C0B4A380A0A42C9AA1DD7A21C2B +:106B2000D7A32CD67EC140D30F6D4A050020880024 +:106B3000308C9780D270D10FBC8FC0E00F4E387E62 +:106B400090E263FFD6BC8292819280C0209282D173 +:106B50000F0000006C1006C0D71CD7921BD7940DF5 +:106B60004911D7202E221F28221D0E4E0BD280073E +:106B70008A0C2E761F2AAC80C8346FAE026000CB20 +:106B80002F0A801AD798A29EAA7A7EA33FC93FC037 +:106B9000E1C05002E538050542CA552BC67EDB2010 +:106BA000D30F6D4A0500308800B08C2E721DAE9E4A +:106BB0000EA50C645086D2802E761DC091298403C8 +:106BC000D10FC05003E53875D0D363FFCD15D785FD +:106BD000027E0CA5EE643051C0A1250A0002A53842 +:106BE000033A020505426450922BC67E0E3512957B +:106BF00010255C10054536D30F6D5A0500A088009E +:106C0000208CC0A1A3E2C05023FA8003730C03A51B +:106C100038AF730505426450722BC67E851005455A +:106C20000C6D5A0500208800308CD280C0A10E9BCC +:106C30000CAB7BAFBB2B761D2A8403D10FD280C057 +:106C4000C1AF7D2D761D2C8403D10F00D2302E8D47 +:106C500008C0F1C0500EF538050542CB592BC67E51 +:106C60000A3F14C1600F660C064636D30F6D6A05E5 +:106C700000208800E08C22721D63FF03C061C050B9 +:106C800003653875D80263FF6263FF5CC05002A5DC +:106C90003875D08763FF8100C06003F63876D0BFB7 +:106CA00063FFB9006C10042A201529201614D7435D +:106CB0000A990CCB9D2E200B04ED092BD11C8F289B +:106CC00009BC36ACAA0CBB0C2BD51C0A0A472A24DB +:106CD00015CAAF8B438942B0A800910400881AA856 +:106CE000FF0FBB029B278F260FB80C783B1AC020E2 +:106CF000D10F0000292102C0A20A9902292502C051 +:106D000021D10F008B2763FFDC2BD11C0CAA0C0AAE +:106D10000A472A2415ACBB2BD51CC9AE8B438C2843 +:106D20008F42B0AD00F10400DD1AADCC0CBB029B6C +:106D300027DA20B7EB580019C021D10F9F2763FF36 +:106D4000EF0000006C100428203C643047053060E0 +:106D500000073E01053EB156076539054928C77F42 +:106D6000A933030641076603B166060641A6337ED2 +:106D7000871E222125291AFC732B1502380C098144 +:106D80006000063E01023EB12406423903220AD1C8 +:106D90000FD230D10FC05163FFC000006C10042728 +:106DA000221EC08008E4311DD7030002002CD282CD +:106DB0001BD703003104C06100661A2BB1020C6CB2 +:106DC000022CD6820BE43119D7870C3A11AA9328EA +:106DD00032829780253282243284B45525368275DA +:106DE000410A292102096902292502D10F2A21021B +:106DF0002B32830A6A022B36822A2502D10F000029 +:106E00006C100418D6EC0C2711087708267286251A +:106E10003C04765B1315D6E805220A2222A36820DB +:106E200002742904227285D10FC020D10F00000006 +:106E30006C100419D6EB27221EC08009770208E4E3 +:106E4000311DD6DC0002002CD2821BD6DC003104BE +:106E5000C06100661A2BB1020C6C022CD6820BE4C6 +:106E60003119D7600C3A11AA9328328297802532C3 +:106E700082243284B45525368275410B2A21020AB8 +:106E80006A022A2502D10F002B21022C32830B6BC0 +:106E9000022C36822B2502D10F0000006C10041B3F +:106EA000D6C50C2A11ABAA29A286B438798B221B2D +:106EB000D6C219D6E80B2B0A2BB2A309290868B051 +:106EC0000274B90D299D0129901F6E920822A28596 +:106ED000D10FC020D10FC892C020D10FDA205BEEB5 +:106EE000B3C020D10F0000006C100414D6B22842A9 +:106EF0009E19D6AF6F88026000BA29922668900763 +:106F00008A2009AA0C65A0AC2A429DC0DC64A0A41A +:106F10002B200C19D6A90CBC11A4CC2EC28609B901 +:106F20000A7ED30260009A2992A36890078D2009F7 +:106F3000DD0C65D08C25C2856450862D2104C030BF +:106F40006ED80D2C2066B8CC0C0C472C246665C07E +:106F50007B1CD72518D6AF1AD6A619D6B61DD6AB28 +:106F6000C0E49E519D508F209357935599539A5644 +:106F70009A5408FF021AD6C29F5288269F5A9E59D9 +:106F80009D58935E9C5D935C9A5B08084805881148 +:106F9000985FC0D81FD6900CB911A499289285AFDC +:106FA000BF23F4CF288C402896858E262D24069E5C +:106FB00029C020D10FCA33DA20C0B65BFF78C72FB3 +:106FC000D10FC93ADA205BFF75C72FD10FDBD05B39 +:106FD000FE0B2324662B200C63FF7500C72FD10FF7 +:106FE000C72FD10F6C1004C85B29200668941C6859 +:106FF0009607C020D10FC020D10FDA20DB30DC4053 +:10700000DD502E0A005BFE5ED2A0D10F2E200C18A0 +:10701000D6690CEF11A8FF29F286C088798B791AFE +:10702000D6660AEA0A2AA2A368A0048B207AB96865 +:1070300023F2856430621BD670290A802C206828D0 +:1070400020672D21040B881104DD1108DD020DCC11 +:1070500002C0842D4A100DCC021DD66898319D3097 +:107060008A2B99379C340BAA02C0C09C359C369A57 +:10707000322A2C74DB4028F285C0D3288C2028F6D5 +:10708000852C25042D24061FD653DD40AFEE2CE4BD +:10709000CF5BFDEAD2A0D10F00DA20DBE05BFF3F3F +:1070A000C020D10F6C100AD6302A200624160128E1 +:1070B000ACF86583862B2122C0F22A2124CC572AE2 +:1070C000AC010A0A4F2A25247ABB0260037F2C21D7 +:1070D000020C0C4C65C3192E22158D32C0910EDDA9 +:1070E0000C65D39088381ED63364836B8C37C0B858 +:1070F000C0960CB9399914B49A9A120D9911991332 +:107100008F6718D62EC9FB2880217F83168B142CFD +:1071100022002A200C5BFF61D4A064A3B38F6760B8 +:10712000002800002B200C89120CBA11AEAA2CA248 +:10713000861DD6217C9B3E0DBD0A2DD2A368D004AE +:1071400088207D893024A28564436427212E07F797 +:107150003607F90C6F9D01D7F0DA20DB70C1C42D22 +:10716000211F5BFEF889268827DDA009880C7A8B11 +:10717000179A10600006C04063FFCC0000DA208B35 +:10718000105BFEC88D1065A267C0E09E488C649CB1 +:10719000498B658A669B4A9A4B97458F677F730236 +:1071A000600120CD529D10DA20DB302C12015BFEF5 +:1071B000698D10C051D6A08FA7C0C08A68974D9A1C +:1071C0004C8869896A984E994F8E6A8A69AE7E7733 +:1071D000EB01B1AA9E6A9A698B60C0A00B8E1477EE +:1071E000B701C0A1C091C08493159D179516C0D05A +:1071F00025203CC030085801089338C0820833105D +:10720000085B010535400B9D3807DD100BAB100EF8 +:1072100019402A211F07991003DD020DBB020553F7 +:10722000100933020A55112921250A2A14092914A3 +:107230000499110A99020933028A2B2921040BAA05 +:10724000021BD66A0899110955020855020BAA02B9 +:107250009A408920881408991109880219D5EA1DD5 +:10726000D66409880298418B2A9346954783150D69 +:10727000BB0285168D179B448A658966AACAA97CBC +:1072800077CB01B1AA07FB0C9C669A6588268E29EC +:10729000AD87972607EE0C0E0E482E25259B672BF3 +:1072A000200C87131ED5C40CB911AE99289285A75E +:1072B0008828968517D5C8C090A7BB29B4CF871852 +:1072C00063FE3C008C60C0E0C091C0F0C034C0B828 +:1072D0002A210428203C08AA110B8B0103830103F7 +:1072E0009F380B9B39C03208FF10038801089E3875 +:1072F0000C881407EE100FEE020388010898390578 +:10730000BF1029211F0ABB1107881008FF020BAA12 +:107310000218D5BC09291403AA022B212583200BAE +:107320002B1404BB110833110FBB020B99028B14F1 +:107330008F2A0B33020833028B2B64708688689780 +:107340004D984C8769886A93419946974E984FC0EB +:107350007077C701C0719A4718D6260B7C100CECC9 +:107360000208F802984418D6230CBC0208CC029CF0 +:10737000402A200C295CFEC0801FD58E1CD5960C9F +:10738000AE112B2124ACAAAFEEB0BB8F132CE2853B +:1073900028A4CFAFCC2CE6852A22152B2524B1AA10 +:1073A0002A26156490DBC9D28F262E22090DFF08EC +:1073B0002F26060FEE0C0E0E482E25256550E4C034 +:1073C00020D10F00C07093419F4499469A4777C7D8 +:1073D0000A1CD57A2CC022C0810C87381CD6070B1A +:1073E000781008E80208B8020C8802984063FF8011 +:1073F00000CC57DA20DB608C115BFDD629210268B6 +:107400009806689403C020D10F2B221EC0A0292209 +:107410001D2A25027B9901C0B064BFE813D5652CF5 +:10742000B00728B000DA2003880A28824CC0D10BAC +:107430008000DBA065AFE763FFCA000068A779DAC8 +:1074400020DB30DC40DD505BFEE7D2A0D10FC16D08 +:10745000C19D29252C60000429252CD6902624675F +:107460002F2468DA20DB308C11DD502E0A805BFD82 +:1074700044D2A0D10FC168C1A82A252C63FFDD002A +:107480000000C8DF8C268B29ADCC9C260CBB0C0BD6 +:107490000B482B25252A2C74DB602C12015BFD8701 +:1074A000D2A0D10F2A2C748B115BF6B9D2A0D10FC8 +:1074B000DA205BFE3A63FF3800DA20C0B15BFE8A57 +:1074C00064ABF1655F352D2124B1DD2D252463FFEB +:1074D0001FDA202B200C5BFE5663FF1412D5C882E6 +:1074E00020028257C82163FFFC12D5C403E8300490 +:1074F000EE3005B13093209421952263FFFC00000B +:1075000010D5C0910092019302940311D597821077 +:1075100001EA30A21101F031C04004E4160002007B +:1075200011D5B98210234A00032202921011D5828C +:10753000C021921004E4318403830282018100009F +:10754000D23001230000000010D5B09100920193C9 +:1075500002940311D586821001EA30A21101F131A3 +:10756000C04004E41600020011D5A7821013D52BE9 +:10757000032202921004E431840383028201810019 +:1075800000D330013300000010D5A19100810165C6 +:10759000104981026510448103CF1F920193029428 +:1075A0000311D574821001EA30A21101F231C040FA +:1075B00004E41600020011D593821013D5130322A0 +:1075C00002921004E431840383028201C01091030B +:1075D00091029101810000D43001430012D542C0D4 +:1075E0003028374028374428374828374C233D0176 +:1075F0007233ED03020063FFFC00000010D585919B +:107600000092019302940311D5838210921011D538 +:10761000348310032202921011D58012D5469210A5 +:10762000C04004E41600020011D577821013D52D56 +:10763000032202921004E431840383028201810058 +:1076400000D53001530000006C10026E322FD6209E +:10765000056F04043F04745B2A05440C00410400D8 +:10766000331A220A006D490D73630403660CB122BC +:107670000F2211031314736302222C01D10FC83B94 +:10768000D10F000073630CC021D10F000000000077 +:1076900044495630C020D10F6C10020040046B4C9E +:1076A00007032318020219D10F020319C020D10FBA +:1076B0006C100202EA30D10F6C1002CC2503F031BD +:1076C00060000F006F220503F1316000056F230594 +:1076D00003F231000200D10F6C1002CC2502F03011 +:1076E000D10F00006F220402F130D10F6F2304028A +:1076F000F230D10FC020D10F6C1002220A20230AD1 +:10770000006D280E28374028374428374828374C42 +:10771000233D01030200D10F6C100202E431D10FAE +:107720000A004368656C73696F20465720444542E0 +:1077300055473D3020284275696C74204672692097 +:107740004D61792020382031363A30373A333620AF +:107750005044542032303039206F6E20636C656F96 +:1077600070617472612E6173696364657369676EB9 +:107770006572732E636F6D3A2F686F6D652F666546 +:107780006C69782F772F66775F372E31292C20563A +:10779000657273696F6E2054337878203030372EDD +:1077A00030342E3030202D203130303730343030EE +:0877B000100704000071489469 +:00000001FF diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h index e8852c092fea..28cc03bf19e6 100644 --- a/include/asm-generic/errno.h +++ b/include/asm-generic/errno.h @@ -106,4 +106,6 @@ #define EOWNERDEAD 130 /* Owner died */ #define ENOTRECOVERABLE 131 /* State not recoverable */ +#define ERFKILL 132 /* Operation not possible due to RF-kill */ + #endif diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b3afd2219ad2..a2df7030d49d 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -311,6 +311,7 @@ unifdef-y += ppp-comp.h unifdef-y += ptrace.h unifdef-y += quota.h unifdef-y += random.h +unifdef-y += rfkill.h unifdef-y += irqnr.h unifdef-y += reboot.h unifdef-y += reiserfs_fs.h diff --git a/include/linux/can/Kbuild b/include/linux/can/Kbuild index eff898aac02b..8cb05aae661c 100644 --- a/include/linux/can/Kbuild +++ b/include/linux/can/Kbuild @@ -1,3 +1,4 @@ header-y += raw.h header-y += bcm.h header-y += error.h +header-y += netlink.h diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h new file mode 100644 index 000000000000..4a37a56f6cdd --- /dev/null +++ b/include/linux/can/dev.h @@ -0,0 +1,70 @@ +/* + * linux/can/dev.h + * + * Definitions for the CAN network device driver interface + * + * Copyright (C) 2006 Andrey Volkov + * Varma Electronics Oy + * + * Copyright (C) 2008 Wolfgang Grandegger + * + * Send feedback to + */ + +#ifndef CAN_DEV_H +#define CAN_DEV_H + +#include +#include + +/* + * CAN mode + */ +enum can_mode { + CAN_MODE_STOP = 0, + CAN_MODE_START, + CAN_MODE_SLEEP +}; + +/* + * CAN common private data + */ +#define CAN_ECHO_SKB_MAX 4 + +struct can_priv { + struct can_device_stats can_stats; + + struct can_bittiming bittiming; + struct can_bittiming_const *bittiming_const; + struct can_clock clock; + + enum can_state state; + u32 ctrlmode; + + int restart_ms; + struct timer_list restart_timer; + + struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX]; + + int (*do_set_bittiming)(struct net_device *dev); + int (*do_set_mode)(struct net_device *dev, enum can_mode mode); + int (*do_get_state)(const struct net_device *dev, + enum can_state *state); +}; + +struct net_device *alloc_candev(int sizeof_priv); +void free_candev(struct net_device *dev); + +int open_candev(struct net_device *dev); +void close_candev(struct net_device *dev); + +int register_candev(struct net_device *dev); +void unregister_candev(struct net_device *dev); + +int can_restart_now(struct net_device *dev); +void can_bus_off(struct net_device *dev); + +void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx); +void can_get_echo_skb(struct net_device *dev, int idx); + +#endif /* CAN_DEV_H */ diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h new file mode 100644 index 000000000000..9ecbb7871c0e --- /dev/null +++ b/include/linux/can/netlink.h @@ -0,0 +1,113 @@ +/* + * linux/can/netlink.h + * + * Definitions for the CAN netlink interface + * + * Copyright (c) 2009 Wolfgang Grandegger + * + * Send feedback to + * + */ + +#ifndef CAN_NETLINK_H +#define CAN_NETLINK_H + +#include + +/* + * CAN bit-timing parameters + * + * For futher information, please read chapter "8 BIT TIMING + * REQUIREMENTS" of the "Bosch CAN Specification version 2.0" + * at http://www.semiconductors.bosch.de/pdf/can2spec.pdf. + */ +struct can_bittiming { + __u32 bitrate; /* Bit-rate in bits/second */ + __u32 sample_point; /* Sample point in one-tenth of a percent */ + __u32 tq; /* Time quanta (TQ) in nanoseconds */ + __u32 prop_seg; /* Propagation segment in TQs */ + __u32 phase_seg1; /* Phase buffer segment 1 in TQs */ + __u32 phase_seg2; /* Phase buffer segment 2 in TQs */ + __u32 sjw; /* Synchronisation jump width in TQs */ + __u32 brp; /* Bit-rate prescaler */ +}; + +/* + * CAN harware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ +struct can_bittiming_const { + char name[16]; /* Name of the CAN controller hardware */ + __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_max; + __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ + __u32 tseg2_max; + __u32 sjw_max; /* Synchronisation jump width */ + __u32 brp_min; /* Bit-rate prescaler */ + __u32 brp_max; + __u32 brp_inc; +}; + +/* + * CAN clock parameters + */ +struct can_clock { + __u32 freq; /* CAN system clock frequency in Hz */ +}; + +/* + * CAN operational and error states + */ +enum can_state { + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ + CAN_STATE_STOPPED, /* Device is stopped */ + CAN_STATE_SLEEPING, /* Device is sleeping */ + CAN_STATE_MAX +}; + +/* + * CAN controller mode + */ +struct can_ctrlmode { + __u32 mask; + __u32 flags; +}; + +#define CAN_CTRLMODE_LOOPBACK 0x1 /* Loopback mode */ +#define CAN_CTRLMODE_LISTENONLY 0x2 /* Listen-only mode */ +#define CAN_CTRLMODE_3_SAMPLES 0x4 /* Triple sampling mode */ + +/* + * CAN device statistics + */ +struct can_device_stats { + __u32 bus_error; /* Bus errors */ + __u32 error_warning; /* Changes to error warning state */ + __u32 error_passive; /* Changes to error passive state */ + __u32 bus_off; /* Changes to bus off state */ + __u32 arbitration_lost; /* Arbitration lost errors */ + __u32 restarts; /* CAN controller re-starts */ +}; + +/* + * CAN netlink interface + */ +enum { + IFLA_CAN_UNSPEC, + IFLA_CAN_BITTIMING, + IFLA_CAN_BITTIMING_CONST, + IFLA_CAN_CLOCK, + IFLA_CAN_STATE, + IFLA_CAN_CTRLMODE, + IFLA_CAN_RESTART_MS, + IFLA_CAN_RESTART, + __IFLA_CAN_MAX +}; + +#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) + +#endif /* CAN_NETLINK_H */ diff --git a/include/linux/can/platform/sja1000.h b/include/linux/can/platform/sja1000.h new file mode 100644 index 000000000000..01ee2aeb048d --- /dev/null +++ b/include/linux/can/platform/sja1000.h @@ -0,0 +1,35 @@ +#ifndef _CAN_PLATFORM_SJA1000_H_ +#define _CAN_PLATFORM_SJA1000_H_ + +/* clock divider register */ +#define CDR_CLKOUT_MASK 0x07 +#define CDR_CLK_OFF 0x08 /* Clock off (CLKOUT pin) */ +#define CDR_RXINPEN 0x20 /* TX1 output is RX irq output */ +#define CDR_CBP 0x40 /* CAN input comparator bypass */ +#define CDR_PELICAN 0x80 /* PeliCAN mode */ + +/* output control register */ +#define OCR_MODE_BIPHASE 0x00 +#define OCR_MODE_TEST 0x01 +#define OCR_MODE_NORMAL 0x02 +#define OCR_MODE_CLOCK 0x03 +#define OCR_MODE_MASK 0x07 +#define OCR_TX0_INVERT 0x04 +#define OCR_TX0_PULLDOWN 0x08 +#define OCR_TX0_PULLUP 0x10 +#define OCR_TX0_PUSHPULL 0x18 +#define OCR_TX1_INVERT 0x20 +#define OCR_TX1_PULLDOWN 0x40 +#define OCR_TX1_PULLUP 0x80 +#define OCR_TX1_PUSHPULL 0xc0 +#define OCR_TX_MASK 0xfc +#define OCR_TX_SHIFT 2 + +struct sja1000_platform_data { + u32 clock; /* CAN bus oscillator frequency in Hz */ + + u8 ocr; /* output control register */ + u8 cdr; /* clock divider register */ +}; + +#endif /* !_CAN_PLATFORM_SJA1000_H_ */ diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index a1f17abba7dc..3d7a6687d247 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -182,6 +182,33 @@ static inline unsigned compare_ether_addr_64bits(const u8 addr1[6+2], return compare_ether_addr(addr1, addr2); #endif } + +/** + * is_etherdev_addr - Tell if given Ethernet address belongs to the device. + * @dev: Pointer to a device structure + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Compare passed address with all addresses of the device. Return true if the + * address if one of the device addresses. + * + * Note that this function calls compare_ether_addr_64bits() so take care of + * the right padding. + */ +static inline bool is_etherdev_addr(const struct net_device *dev, + const u8 addr[6 + 2]) +{ + struct netdev_hw_addr *ha; + int res = 1; + + rcu_read_lock(); + for_each_dev_addr(dev, ha) { + res = compare_ether_addr_64bits(addr, ha->addr); + if (!res) + break; + } + rcu_read_unlock(); + return !res; +} #endif /* __KERNEL__ */ /** diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 131b127b70f8..9b660bd2e2b3 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -26,11 +26,14 @@ struct ethtool_cmd { __u8 phy_address; __u8 transceiver; /* Which transceiver to use */ __u8 autoneg; /* Enable or disable autonegotiation */ + __u8 mdio_support; __u32 maxtxpkt; /* Tx pkts before generating tx int */ __u32 maxrxpkt; /* Rx pkts before generating rx int */ __u16 speed_hi; - __u16 reserved2; - __u32 reserved[3]; + __u8 eth_tp_mdix; + __u8 reserved2; + __u32 lp_advertising; /* Features the link partner advertises */ + __u32 reserved[2]; }; static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, @@ -563,6 +566,11 @@ struct ethtool_ops { #define SUPPORTED_Pause (1 << 13) #define SUPPORTED_Asym_Pause (1 << 14) #define SUPPORTED_2500baseX_Full (1 << 15) +#define SUPPORTED_Backplane (1 << 16) +#define SUPPORTED_1000baseKX_Full (1 << 17) +#define SUPPORTED_10000baseKX4_Full (1 << 18) +#define SUPPORTED_10000baseKR_Full (1 << 19) +#define SUPPORTED_10000baseR_FEC (1 << 20) /* Indicates what features are advertised by the interface. */ #define ADVERTISED_10baseT_Half (1 << 0) @@ -581,6 +589,11 @@ struct ethtool_ops { #define ADVERTISED_Pause (1 << 13) #define ADVERTISED_Asym_Pause (1 << 14) #define ADVERTISED_2500baseX_Full (1 << 15) +#define ADVERTISED_Backplane (1 << 16) +#define ADVERTISED_1000baseKX_Full (1 << 17) +#define ADVERTISED_10000baseKX4_Full (1 << 18) +#define ADVERTISED_10000baseKR_Full (1 << 19) +#define ADVERTISED_10000baseR_FEC (1 << 20) /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the @@ -605,6 +618,7 @@ struct ethtool_ops { #define PORT_MII 0x02 #define PORT_FIBRE 0x03 #define PORT_BNC 0x04 +#define PORT_OTHER 0xff /* Which transceiver to use. */ #define XCVR_INTERNAL 0x00 @@ -619,6 +633,11 @@ struct ethtool_ops { #define AUTONEG_DISABLE 0x00 #define AUTONEG_ENABLE 0x01 +/* Mode MDI or MDI-X */ +#define ETH_TP_MDI_INVALID 0x00 +#define ETH_TP_MDI 0x01 +#define ETH_TP_MDI_X 0x02 + /* Wake-On-Lan options. */ #define WAKE_PHY (1 << 0) #define WAKE_UCAST (1 << 1) diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h index 8300cab30f9a..51b793466ff3 100644 --- a/include/linux/fs_enet_pd.h +++ b/include/linux/fs_enet_pd.h @@ -17,6 +17,7 @@ #define FS_ENET_PD_H #include +#include #include #define FS_ENET_NAME "fs_enet" @@ -130,10 +131,7 @@ struct fs_platform_info { u32 device_flags; - int phy_addr; /* the phy address (-1 no phy) */ - char bus_id[16]; - int phy_irq; /* the phy irq (if it exists) */ - + struct device_node *phy_node; const struct fs_mii_bus_info *bus_info; int rx_ring, tx_ring; /* number of buffers on rx */ diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 4b501b48ce86..a9173d5434d1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -493,6 +493,7 @@ struct ieee80211s_hdr { /* Mesh flags */ #define MESH_FLAGS_AE_A4 0x1 #define MESH_FLAGS_AE_A5_A6 0x2 +#define MESH_FLAGS_AE 0x3 #define MESH_FLAGS_PS_DEEP 0x4 /** @@ -540,10 +541,10 @@ struct ieee80211_tim_ie { u8 dtim_period; u8 bitmap_ctrl; /* variable size: 1 - 251 bytes */ - u8 virtual_map[0]; + u8 virtual_map[1]; } __attribute__ ((packed)); -#define WLAN_SA_QUERY_TR_ID_LEN 16 +#define WLAN_SA_QUERY_TR_ID_LEN 2 struct ieee80211_mgmt { __le16 frame_control; @@ -1068,8 +1069,12 @@ enum ieee80211_category { WLAN_CATEGORY_DLS = 2, WLAN_CATEGORY_BACK = 3, WLAN_CATEGORY_PUBLIC = 4, + WLAN_CATEGORY_HT = 7, WLAN_CATEGORY_SA_QUERY = 8, + WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, WLAN_CATEGORY_WMM = 17, + WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, + WLAN_CATEGORY_VENDOR_SPECIFIC = 127, }; /* SPECTRUM_MGMT action code */ @@ -1081,6 +1086,15 @@ enum ieee80211_spectrum_mgmt_actioncode { WLAN_ACTION_SPCT_CHL_SWITCH = 4, }; +/* Security key length */ +enum ieee80211_key_len { + WLAN_KEY_LEN_WEP40 = 5, + WLAN_KEY_LEN_WEP104 = 13, + WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_TKIP = 32, + WLAN_KEY_LEN_AES_CMAC = 16, +}; + /* * IEEE 802.11-2007 7.3.2.9 Country information element * @@ -1261,7 +1275,9 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) if (ieee80211_has_protected(hdr->frame_control)) return true; category = ((u8 *) hdr) + 24; - return *category != WLAN_CATEGORY_PUBLIC; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; } return false; @@ -1383,4 +1399,43 @@ static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) return -1; } +/** + * ieee80211_tu_to_usec - convert time units (TU) to microseconds + * @tu: the TUs + */ +static inline unsigned long ieee80211_tu_to_usec(unsigned long tu) +{ + return 1024 * tu; +} + +/** + * ieee80211_check_tim - check if AID bit is set in TIM + * @tim: the TIM IE + * @tim_len: length of the TIM IE + * @aid: the AID to look for + */ +static inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, + u8 tim_len, u16 aid) +{ + u8 mask; + u8 index, indexn1, indexn2; + + if (unlikely(!tim || tim_len < sizeof(*tim))) + return false; + + aid &= 0x3fff; + index = aid / 8; + mask = 1 << (aid & 7); + + indexn1 = tim->bitmap_ctrl & 0xfe; + indexn2 = tim_len + indexn1 - 4; + + if (index < indexn1 || index > indexn2) + return false; + + index -= indexn1; + + return !!(tim->virtual_map[index] & mask); +} + #endif /* LINUX_IEEE80211_H */ diff --git a/include/linux/if.h b/include/linux/if.h index 1108f3e099e3..b9a6229f3be7 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -67,6 +67,9 @@ #define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */ #define IFF_MASTER_ARPMON 0x100 /* bonding master, ARP mon in use */ #define IFF_WAN_HDLC 0x200 /* WAN HDLC device */ +#define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to + * release skb->dst + */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h index 5ff89809a581..b554300ef8bf 100644 --- a/include/linux/if_arp.h +++ b/include/linux/if_arp.h @@ -86,6 +86,8 @@ #define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ #define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */ #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ +#define ARPHRD_IEEE802154 804 +#define ARPHRD_IEEE802154_PHY 805 #define ARPHRD_PHONET 820 /* PhoNet media type */ #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 60e8934d10b5..ae3a1871413d 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -107,6 +107,7 @@ #define ETH_P_DSA 0x001B /* Distributed Switch Arch. */ #define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ #define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ +#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ /* * This is an Ethernet frame header. diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index 18db0668065a..dea7d6b7cf98 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -46,6 +46,8 @@ struct sockaddr_ll #define PACKET_VERSION 10 #define PACKET_HDRLEN 11 #define PACKET_RESERVE 12 +#define PACKET_TX_RING 13 +#define PACKET_LOSS 14 struct tpacket_stats { @@ -63,14 +65,22 @@ struct tpacket_auxdata __u16 tp_vlan_tci; }; +/* Rx ring - header status */ +#define TP_STATUS_KERNEL 0x0 +#define TP_STATUS_USER 0x1 +#define TP_STATUS_COPY 0x2 +#define TP_STATUS_LOSING 0x4 +#define TP_STATUS_CSUMNOTREADY 0x8 + +/* Tx ring - header status */ +#define TP_STATUS_AVAILABLE 0x0 +#define TP_STATUS_SEND_REQUEST 0x1 +#define TP_STATUS_SENDING 0x2 +#define TP_STATUS_WRONG_FORMAT 0x4 + struct tpacket_hdr { unsigned long tp_status; -#define TP_STATUS_KERNEL 0 -#define TP_STATUS_USER 1 -#define TP_STATUS_COPY 2 -#define TP_STATUS_LOSING 4 -#define TP_STATUS_CSUMNOTREADY 8 unsigned int tp_len; unsigned int tp_snaplen; unsigned short tp_mac; @@ -135,5 +145,6 @@ struct packet_mreq #define PACKET_MR_MULTICAST 0 #define PACKET_MR_PROMISC 1 #define PACKET_MR_ALLMULTI 2 +#define PACKET_MR_UNICAST 3 #endif diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 049d6c9428db..915ba5789f0e 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -55,6 +55,7 @@ #define IFF_NO_PI 0x1000 #define IFF_ONE_QUEUE 0x2000 #define IFF_VNET_HDR 0x4000 +#define IFF_TUN_EXCL 0x8000 /* Features for GSO (TUNSETOFFLOAD). */ #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index 5a9aae4adb44..5eb9b0f857e0 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -44,7 +44,7 @@ struct ip_tunnel_prl { __u16 flags; __u16 __reserved; __u32 datalen; - __u32 __reserved2; + __u32 rs_delay; /* data follows */ }; diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index e1ff5b14310e..7ff9af1d0f05 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -118,8 +118,7 @@ extern int vlan_hwaccel_do_receive(struct sk_buff *skb); extern int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb); extern int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, - unsigned int vlan_tci, - struct napi_gro_fraginfo *info); + unsigned int vlan_tci); #else static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) @@ -154,8 +153,7 @@ static inline int vlan_gro_receive(struct napi_struct *napi, } static inline int vlan_gro_frags(struct napi_struct *napi, - struct vlan_group *grp, unsigned int vlan_tci, - struct napi_gro_fraginfo *info) + struct vlan_group *grp, unsigned int vlan_tci) { return NET_RX_DROP; } diff --git a/include/linux/in.h b/include/linux/in.h index d60122a3a088..cf196da04ec9 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -107,6 +107,7 @@ struct in_addr { #define MCAST_JOIN_SOURCE_GROUP 46 #define MCAST_LEAVE_SOURCE_GROUP 47 #define MCAST_MSFILTER 48 +#define IP_MULTICAST_ALL 49 #define MCAST_EXCLUDE 0 #define MCAST_INCLUDE 1 diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 476d9464ac82..c662efa68289 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -169,6 +169,12 @@ struct ipv6_devconf { __s32 accept_dad; void *sysctl; }; + +struct ipv6_params { + __s32 disable_ipv6; + __s32 autoconf; +}; +extern struct ipv6_params ipv6_defaults; #endif /* index values for the variables in ipv6_devconf */ diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index 35e9b0fd014b..7acb87a44872 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -79,7 +79,7 @@ int attach_capi_ctr(struct capi_ctr *); int detach_capi_ctr(struct capi_ctr *); void capi_ctr_ready(struct capi_ctr * card); -void capi_ctr_reseted(struct capi_ctr * card); +void capi_ctr_down(struct capi_ctr * card); void capi_ctr_suspend_output(struct capi_ctr * card); void capi_ctr_resume_output(struct capi_ctr * card); void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb); diff --git a/include/linux/list_nulls.h b/include/linux/list_nulls.h index 93150ecf3ea4..5d10ae364b5e 100644 --- a/include/linux/list_nulls.h +++ b/include/linux/list_nulls.h @@ -56,6 +56,18 @@ static inline int hlist_nulls_empty(const struct hlist_nulls_head *h) return is_a_nulls(h->first); } +static inline void hlist_nulls_add_head(struct hlist_nulls_node *n, + struct hlist_nulls_head *h) +{ + struct hlist_nulls_node *first = h->first; + + n->next = first; + n->pprev = &h->first; + h->first = n; + if (!is_a_nulls(first)) + first->pprev = &n->next; +} + static inline void __hlist_nulls_del(struct hlist_nulls_node *n) { struct hlist_nulls_node *next = n->next; @@ -65,6 +77,12 @@ static inline void __hlist_nulls_del(struct hlist_nulls_node *n) next->pprev = pprev; } +static inline void hlist_nulls_del(struct hlist_nulls_node *n) +{ + __hlist_nulls_del(n); + n->pprev = LIST_POISON2; +} + /** * hlist_nulls_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop cursor. diff --git a/include/linux/mISDNdsp.h b/include/linux/mISDNdsp.h index 6b71d2dce508..41d1eeb9b3bd 100644 --- a/include/linux/mISDNdsp.h +++ b/include/linux/mISDNdsp.h @@ -12,7 +12,8 @@ struct mISDN_dsp_element { void *(*new)(const char *arg); void (*free)(void *p); void (*process_tx)(void *p, unsigned char *data, int len); - void (*process_rx)(void *p, unsigned char *data, int len); + void (*process_rx)(void *p, unsigned char *data, int len, + unsigned int txlen); int num_args; struct mISDN_dsp_element_arg *args; @@ -24,6 +25,7 @@ extern void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem); struct dsp_features { int hfc_id; /* unique id to identify the chip (or -1) */ int hfc_dtmf; /* set if HFCmulti card supports dtmf */ + int hfc_conf; /* set if HFCmulti card supports conferences */ int hfc_loops; /* set if card supports tone loops */ int hfc_echocanhw; /* set if card supports echocancelation*/ int pcm_id; /* unique id to identify the pcm bus (or -1) */ diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h index 97ffdc1d3442..7f9831da847f 100644 --- a/include/linux/mISDNhw.h +++ b/include/linux/mISDNhw.h @@ -89,11 +89,6 @@ struct dchannel { void (*phfunc) (struct dchannel *); u_int state; void *l1; - /* HW access */ - u_char (*read_reg) (void *, u_char); - void (*write_reg) (void *, u_char, u_char); - void (*read_fifo) (void *, u_char *, int); - void (*write_fifo) (void *, u_char *, int); void *hw; int slot; /* multiport card channel slot */ struct timer_list timer; @@ -151,11 +146,6 @@ struct bchannel { u_long Flags; struct work_struct workq; u_int state; - /* HW access */ - u_char (*read_reg) (void *, u_char); - void (*write_reg) (void *, u_char, u_char); - void (*read_fifo) (void *, u_char *, int); - void (*write_fifo) (void *, u_char *, int); void *hw; int slot; /* multiport card channel slot */ struct timer_list timer; @@ -185,7 +175,7 @@ extern int dchannel_senddata(struct dchannel *, struct sk_buff *); extern int bchannel_senddata(struct bchannel *, struct sk_buff *); extern void recv_Dchannel(struct dchannel *); extern void recv_Echannel(struct dchannel *, struct dchannel *); -extern void recv_Bchannel(struct bchannel *); +extern void recv_Bchannel(struct bchannel *, unsigned int id); extern void recv_Dchannel_skb(struct dchannel *, struct sk_buff *); extern void recv_Bchannel_skb(struct bchannel *, struct sk_buff *); extern void confirm_Bsend(struct bchannel *bch); diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h index 5da3d95b27f1..45100b39a7cf 100644 --- a/include/linux/mISDNif.h +++ b/include/linux/mISDNif.h @@ -229,6 +229,7 @@ #define OPTION_L2_PTP 2 #define OPTION_L2_FIXEDTEI 3 #define OPTION_L2_CLEANUP 4 +#define OPTION_L1_HOLD 5 /* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */ #define MISDN_MAX_IDLEN 20 @@ -291,19 +292,19 @@ struct mISDN_devrename { /* MPH_INFORMATION_REQ payload */ struct ph_info_ch { - __u32 protocol; - __u64 Flags; + __u32 protocol; + __u64 Flags; }; struct ph_info_dch { - struct ph_info_ch ch; - __u16 state; - __u16 num_bch; + struct ph_info_ch ch; + __u16 state; + __u16 num_bch; }; struct ph_info { - struct ph_info_dch dch; - struct ph_info_ch bch[]; + struct ph_info_dch dch; + struct ph_info_ch bch[]; }; /* timer device ioctl */ @@ -317,6 +318,7 @@ struct ph_info { #define IMCTRLREQ _IOR('I', 69, int) #define IMCLEAR_L2 _IOR('I', 70, int) #define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename) +#define IMHOLD_L1 _IOR('I', 72, int) static inline int test_channelmap(u_int nr, u_char *map) @@ -362,7 +364,8 @@ clear_channelmap(u_int nr, u_char *map) #define MISDN_CTRL_HFC_RECEIVE_ON 0x4006 #define MISDN_CTRL_HFC_ECHOCAN_ON 0x4007 #define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008 - +#define MISDN_CTRL_HFC_WD_INIT 0x4009 +#define MISDN_CTRL_HFC_WD_RESET 0x400A /* socket options */ #define MISDN_TIME_STAMP 0x0001 diff --git a/include/linux/mdio.h b/include/linux/mdio.h new file mode 100644 index 000000000000..cfdf1df2875e --- /dev/null +++ b/include/linux/mdio.h @@ -0,0 +1,356 @@ +/* + * linux/mdio.h: definitions for MDIO (clause 45) transceivers + * Copyright 2006-2009 Solarflare Communications 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, incorporated herein by reference. + */ + +#ifndef __LINUX_MDIO_H__ +#define __LINUX_MDIO_H__ + +#include + +/* MDIO Manageable Devices (MMDs). */ +#define MDIO_MMD_PMAPMD 1 /* Physical Medium Attachment/ + * Physical Medium Dependent */ +#define MDIO_MMD_WIS 2 /* WAN Interface Sublayer */ +#define MDIO_MMD_PCS 3 /* Physical Coding Sublayer */ +#define MDIO_MMD_PHYXS 4 /* PHY Extender Sublayer */ +#define MDIO_MMD_DTEXS 5 /* DTE Extender Sublayer */ +#define MDIO_MMD_TC 6 /* Transmission Convergence */ +#define MDIO_MMD_AN 7 /* Auto-Negotiation */ +#define MDIO_MMD_C22EXT 29 /* Clause 22 extension */ +#define MDIO_MMD_VEND1 30 /* Vendor specific 1 */ +#define MDIO_MMD_VEND2 31 /* Vendor specific 2 */ + +/* Generic MDIO registers. */ +#define MDIO_CTRL1 MII_BMCR +#define MDIO_STAT1 MII_BMSR +#define MDIO_DEVID1 MII_PHYSID1 +#define MDIO_DEVID2 MII_PHYSID2 +#define MDIO_SPEED 4 /* Speed ability */ +#define MDIO_DEVS1 5 /* Devices in package */ +#define MDIO_DEVS2 6 +#define MDIO_CTRL2 7 /* 10G control 2 */ +#define MDIO_STAT2 8 /* 10G status 2 */ +#define MDIO_PMA_TXDIS 9 /* 10G PMA/PMD transmit disable */ +#define MDIO_PMA_RXDET 10 /* 10G PMA/PMD receive signal detect */ +#define MDIO_PMA_EXTABLE 11 /* 10G PMA/PMD extended ability */ +#define MDIO_PKGID1 14 /* Package identifier */ +#define MDIO_PKGID2 15 +#define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ +#define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ +#define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ + +/* Media-dependent registers. */ +#define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */ +#define MDIO_PMA_10GBT_TXPWR 131 /* 10GBASE-T TX power control */ +#define MDIO_PMA_10GBT_SNR 133 /* 10GBASE-T SNR margin, lane A. + * Lanes B-D are numbered 134-136. */ +#define MDIO_PMA_10GBR_FECABLE 170 /* 10GBASE-R FEC ability */ +#define MDIO_PCS_10GBX_STAT1 24 /* 10GBASE-X PCS status 1 */ +#define MDIO_PCS_10GBRT_STAT1 32 /* 10GBASE-R/-T PCS status 1 */ +#define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */ +#define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */ +#define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */ + +/* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */ +#define MDIO_PMA_LASI_RXCTRL 0x9000 /* RX_ALARM control */ +#define MDIO_PMA_LASI_TXCTRL 0x9001 /* TX_ALARM control */ +#define MDIO_PMA_LASI_CTRL 0x9002 /* LASI control */ +#define MDIO_PMA_LASI_RXSTAT 0x9003 /* RX_ALARM status */ +#define MDIO_PMA_LASI_TXSTAT 0x9004 /* TX_ALARM status */ +#define MDIO_PMA_LASI_STAT 0x9005 /* LASI status */ + +/* Control register 1. */ +/* Enable extended speed selection */ +#define MDIO_CTRL1_SPEEDSELEXT (BMCR_SPEED1000 | BMCR_SPEED100) +/* All speed selection bits */ +#define MDIO_CTRL1_SPEEDSEL (MDIO_CTRL1_SPEEDSELEXT | 0x003c) +#define MDIO_CTRL1_FULLDPLX BMCR_FULLDPLX +#define MDIO_CTRL1_LPOWER BMCR_PDOWN +#define MDIO_CTRL1_RESET BMCR_RESET +#define MDIO_PMA_CTRL1_LOOPBACK 0x0001 +#define MDIO_PMA_CTRL1_SPEED1000 BMCR_SPEED1000 +#define MDIO_PMA_CTRL1_SPEED100 BMCR_SPEED100 +#define MDIO_PCS_CTRL1_LOOPBACK BMCR_LOOPBACK +#define MDIO_PHYXS_CTRL1_LOOPBACK BMCR_LOOPBACK +#define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART +#define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE +#define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */ + +/* 10 Gb/s */ +#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00) +/* 10PASS-TS/2BASE-TL */ +#define MDIO_CTRL1_SPEED10P2B (MDIO_CTRL1_SPEEDSELEXT | 0x04) + +/* Status register 1. */ +#define MDIO_STAT1_LPOWERABLE 0x0002 /* Low-power ability */ +#define MDIO_STAT1_LSTATUS BMSR_LSTATUS +#define MDIO_STAT1_FAULT 0x0080 /* Fault */ +#define MDIO_AN_STAT1_LPABLE 0x0001 /* Link partner AN ability */ +#define MDIO_AN_STAT1_ABLE BMSR_ANEGCAPABLE +#define MDIO_AN_STAT1_RFAULT BMSR_RFAULT +#define MDIO_AN_STAT1_COMPLETE BMSR_ANEGCOMPLETE +#define MDIO_AN_STAT1_PAGE 0x0040 /* Page received */ +#define MDIO_AN_STAT1_XNP 0x0080 /* Extended next page status */ + +/* Speed register. */ +#define MDIO_SPEED_10G 0x0001 /* 10G capable */ +#define MDIO_PMA_SPEED_2B 0x0002 /* 2BASE-TL capable */ +#define MDIO_PMA_SPEED_10P 0x0004 /* 10PASS-TS capable */ +#define MDIO_PMA_SPEED_1000 0x0010 /* 1000M capable */ +#define MDIO_PMA_SPEED_100 0x0020 /* 100M capable */ +#define MDIO_PMA_SPEED_10 0x0040 /* 10M capable */ +#define MDIO_PCS_SPEED_10P2B 0x0002 /* 10PASS-TS/2BASE-TL capable */ + +/* Device present registers. */ +#define MDIO_DEVS_PRESENT(devad) (1 << (devad)) +#define MDIO_DEVS_PMAPMD MDIO_DEVS_PRESENT(MDIO_MMD_PMAPMD) +#define MDIO_DEVS_WIS MDIO_DEVS_PRESENT(MDIO_MMD_WIS) +#define MDIO_DEVS_PCS MDIO_DEVS_PRESENT(MDIO_MMD_PCS) +#define MDIO_DEVS_PHYXS MDIO_DEVS_PRESENT(MDIO_MMD_PHYXS) +#define MDIO_DEVS_DTEXS MDIO_DEVS_PRESENT(MDIO_MMD_DTEXS) +#define MDIO_DEVS_TC MDIO_DEVS_PRESENT(MDIO_MMD_TC) +#define MDIO_DEVS_AN MDIO_DEVS_PRESENT(MDIO_MMD_AN) +#define MDIO_DEVS_C22EXT MDIO_DEVS_PRESENT(MDIO_MMD_C22EXT) + +/* Control register 2. */ +#define MDIO_PMA_CTRL2_TYPE 0x000f /* PMA/PMD type selection */ +#define MDIO_PMA_CTRL2_10GBCX4 0x0000 /* 10GBASE-CX4 type */ +#define MDIO_PMA_CTRL2_10GBEW 0x0001 /* 10GBASE-EW type */ +#define MDIO_PMA_CTRL2_10GBLW 0x0002 /* 10GBASE-LW type */ +#define MDIO_PMA_CTRL2_10GBSW 0x0003 /* 10GBASE-SW type */ +#define MDIO_PMA_CTRL2_10GBLX4 0x0004 /* 10GBASE-LX4 type */ +#define MDIO_PMA_CTRL2_10GBER 0x0005 /* 10GBASE-ER type */ +#define MDIO_PMA_CTRL2_10GBLR 0x0006 /* 10GBASE-LR type */ +#define MDIO_PMA_CTRL2_10GBSR 0x0007 /* 10GBASE-SR type */ +#define MDIO_PMA_CTRL2_10GBLRM 0x0008 /* 10GBASE-LRM type */ +#define MDIO_PMA_CTRL2_10GBT 0x0009 /* 10GBASE-T type */ +#define MDIO_PMA_CTRL2_10GBKX4 0x000a /* 10GBASE-KX4 type */ +#define MDIO_PMA_CTRL2_10GBKR 0x000b /* 10GBASE-KR type */ +#define MDIO_PMA_CTRL2_1000BT 0x000c /* 1000BASE-T type */ +#define MDIO_PMA_CTRL2_1000BKX 0x000d /* 1000BASE-KX type */ +#define MDIO_PMA_CTRL2_100BTX 0x000e /* 100BASE-TX type */ +#define MDIO_PMA_CTRL2_10BT 0x000f /* 10BASE-T type */ +#define MDIO_PCS_CTRL2_TYPE 0x0003 /* PCS type selection */ +#define MDIO_PCS_CTRL2_10GBR 0x0000 /* 10GBASE-R type */ +#define MDIO_PCS_CTRL2_10GBX 0x0001 /* 10GBASE-X type */ +#define MDIO_PCS_CTRL2_10GBW 0x0002 /* 10GBASE-W type */ +#define MDIO_PCS_CTRL2_10GBT 0x0003 /* 10GBASE-T type */ + +/* Status register 2. */ +#define MDIO_STAT2_RXFAULT 0x0400 /* Receive fault */ +#define MDIO_STAT2_TXFAULT 0x0800 /* Transmit fault */ +#define MDIO_STAT2_DEVPRST 0xc000 /* Device present */ +#define MDIO_STAT2_DEVPRST_VAL 0x8000 /* Device present value */ +#define MDIO_PMA_STAT2_LBABLE 0x0001 /* PMA loopback ability */ +#define MDIO_PMA_STAT2_10GBEW 0x0002 /* 10GBASE-EW ability */ +#define MDIO_PMA_STAT2_10GBLW 0x0004 /* 10GBASE-LW ability */ +#define MDIO_PMA_STAT2_10GBSW 0x0008 /* 10GBASE-SW ability */ +#define MDIO_PMA_STAT2_10GBLX4 0x0010 /* 10GBASE-LX4 ability */ +#define MDIO_PMA_STAT2_10GBER 0x0020 /* 10GBASE-ER ability */ +#define MDIO_PMA_STAT2_10GBLR 0x0040 /* 10GBASE-LR ability */ +#define MDIO_PMA_STAT2_10GBSR 0x0080 /* 10GBASE-SR ability */ +#define MDIO_PMD_STAT2_TXDISAB 0x0100 /* PMD TX disable ability */ +#define MDIO_PMA_STAT2_EXTABLE 0x0200 /* Extended abilities */ +#define MDIO_PMA_STAT2_RXFLTABLE 0x1000 /* Receive fault ability */ +#define MDIO_PMA_STAT2_TXFLTABLE 0x2000 /* Transmit fault ability */ +#define MDIO_PCS_STAT2_10GBR 0x0001 /* 10GBASE-R capable */ +#define MDIO_PCS_STAT2_10GBX 0x0002 /* 10GBASE-X capable */ +#define MDIO_PCS_STAT2_10GBW 0x0004 /* 10GBASE-W capable */ +#define MDIO_PCS_STAT2_RXFLTABLE 0x1000 /* Receive fault ability */ +#define MDIO_PCS_STAT2_TXFLTABLE 0x2000 /* Transmit fault ability */ + +/* Transmit disable register. */ +#define MDIO_PMD_TXDIS_GLOBAL 0x0001 /* Global PMD TX disable */ +#define MDIO_PMD_TXDIS_0 0x0002 /* PMD TX disable 0 */ +#define MDIO_PMD_TXDIS_1 0x0004 /* PMD TX disable 1 */ +#define MDIO_PMD_TXDIS_2 0x0008 /* PMD TX disable 2 */ +#define MDIO_PMD_TXDIS_3 0x0010 /* PMD TX disable 3 */ + +/* Receive signal detect register. */ +#define MDIO_PMD_RXDET_GLOBAL 0x0001 /* Global PMD RX signal detect */ +#define MDIO_PMD_RXDET_0 0x0002 /* PMD RX signal detect 0 */ +#define MDIO_PMD_RXDET_1 0x0004 /* PMD RX signal detect 1 */ +#define MDIO_PMD_RXDET_2 0x0008 /* PMD RX signal detect 2 */ +#define MDIO_PMD_RXDET_3 0x0010 /* PMD RX signal detect 3 */ + +/* Extended abilities register. */ +#define MDIO_PMA_EXTABLE_10GCX4 0x0001 /* 10GBASE-CX4 ability */ +#define MDIO_PMA_EXTABLE_10GBLRM 0x0002 /* 10GBASE-LRM ability */ +#define MDIO_PMA_EXTABLE_10GBT 0x0004 /* 10GBASE-T ability */ +#define MDIO_PMA_EXTABLE_10GBKX4 0x0008 /* 10GBASE-KX4 ability */ +#define MDIO_PMA_EXTABLE_10GBKR 0x0010 /* 10GBASE-KR ability */ +#define MDIO_PMA_EXTABLE_1000BT 0x0020 /* 1000BASE-T ability */ +#define MDIO_PMA_EXTABLE_1000BKX 0x0040 /* 1000BASE-KX ability */ +#define MDIO_PMA_EXTABLE_100BTX 0x0080 /* 100BASE-TX ability */ +#define MDIO_PMA_EXTABLE_10BT 0x0100 /* 10BASE-T ability */ + +/* PHY XGXS lane state register. */ +#define MDIO_PHYXS_LNSTAT_SYNC0 0x0001 +#define MDIO_PHYXS_LNSTAT_SYNC1 0x0002 +#define MDIO_PHYXS_LNSTAT_SYNC2 0x0004 +#define MDIO_PHYXS_LNSTAT_SYNC3 0x0008 +#define MDIO_PHYXS_LNSTAT_ALIGN 0x1000 + +/* PMA 10GBASE-T pair swap & polarity */ +#define MDIO_PMA_10GBT_SWAPPOL_ABNX 0x0001 /* Pair A/B uncrossed */ +#define MDIO_PMA_10GBT_SWAPPOL_CDNX 0x0002 /* Pair C/D uncrossed */ +#define MDIO_PMA_10GBT_SWAPPOL_AREV 0x0100 /* Pair A polarity reversed */ +#define MDIO_PMA_10GBT_SWAPPOL_BREV 0x0200 /* Pair B polarity reversed */ +#define MDIO_PMA_10GBT_SWAPPOL_CREV 0x0400 /* Pair C polarity reversed */ +#define MDIO_PMA_10GBT_SWAPPOL_DREV 0x0800 /* Pair D polarity reversed */ + +/* PMA 10GBASE-T TX power register. */ +#define MDIO_PMA_10GBT_TXPWR_SHORT 0x0001 /* Short-reach mode */ + +/* PMA 10GBASE-T SNR registers. */ +/* Value is SNR margin in dB, clamped to range [-127, 127], plus 0x8000. */ +#define MDIO_PMA_10GBT_SNR_BIAS 0x8000 +#define MDIO_PMA_10GBT_SNR_MAX 127 + +/* PMA 10GBASE-R FEC ability register. */ +#define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */ +#define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */ + +/* PCS 10GBASE-R/-T status register 1. */ +#define MDIO_PCS_10GBRT_STAT1_BLKLK 0x0001 /* Block lock attained */ + +/* PCS 10GBASE-R/-T status register 2. */ +#define MDIO_PCS_10GBRT_STAT2_ERR 0x00ff +#define MDIO_PCS_10GBRT_STAT2_BER 0x3f00 + +/* AN 10GBASE-T control register. */ +#define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */ + +/* AN 10GBASE-T status register. */ +#define MDIO_AN_10GBT_STAT_LPTRR 0x0200 /* LP training reset req. */ +#define MDIO_AN_10GBT_STAT_LPLTABLE 0x0400 /* LP loop timing ability */ +#define MDIO_AN_10GBT_STAT_LP10G 0x0800 /* LP is 10GBT capable */ +#define MDIO_AN_10GBT_STAT_REMOK 0x1000 /* Remote OK */ +#define MDIO_AN_10GBT_STAT_LOCOK 0x2000 /* Local OK */ +#define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */ +#define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */ + +/* LASI RX_ALARM control/status registers. */ +#define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */ +#define MDIO_PMA_LASI_RX_PCSLFLT 0x0008 /* PCS RX local fault */ +#define MDIO_PMA_LASI_RX_PMALFLT 0x0010 /* PMA/PMD RX local fault */ +#define MDIO_PMA_LASI_RX_OPTICPOWERFLT 0x0020 /* RX optical power fault */ +#define MDIO_PMA_LASI_RX_WISLFLT 0x0200 /* WIS local fault */ + +/* LASI TX_ALARM control/status registers. */ +#define MDIO_PMA_LASI_TX_PHYXSLFLT 0x0001 /* PHY XS TX local fault */ +#define MDIO_PMA_LASI_TX_PCSLFLT 0x0008 /* PCS TX local fault */ +#define MDIO_PMA_LASI_TX_PMALFLT 0x0010 /* PMA/PMD TX local fault */ +#define MDIO_PMA_LASI_TX_LASERPOWERFLT 0x0080 /* Laser output power fault */ +#define MDIO_PMA_LASI_TX_LASERTEMPFLT 0x0100 /* Laser temperature fault */ +#define MDIO_PMA_LASI_TX_LASERBICURRFLT 0x0200 /* Laser bias current fault */ + +/* LASI control/status registers. */ +#define MDIO_PMA_LASI_LSALARM 0x0001 /* LS_ALARM enable/status */ +#define MDIO_PMA_LASI_TXALARM 0x0002 /* TX_ALARM enable/status */ +#define MDIO_PMA_LASI_RXALARM 0x0004 /* RX_ALARM enable/status */ + +/* Mapping between MDIO PRTAD/DEVAD and mii_ioctl_data::phy_id */ + +#define MDIO_PHY_ID_C45 0x8000 +#define MDIO_PHY_ID_PRTAD 0x03e0 +#define MDIO_PHY_ID_DEVAD 0x001f +#define MDIO_PHY_ID_C45_MASK \ + (MDIO_PHY_ID_C45 | MDIO_PHY_ID_PRTAD | MDIO_PHY_ID_DEVAD) + +static inline __u16 mdio_phy_id_c45(int prtad, int devad) +{ + return MDIO_PHY_ID_C45 | (prtad << 5) | devad; +} + +static inline bool mdio_phy_id_is_c45(int phy_id) +{ + return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK); +} + +static inline __u16 mdio_phy_id_prtad(int phy_id) +{ + return (phy_id & MDIO_PHY_ID_PRTAD) >> 5; +} + +static inline __u16 mdio_phy_id_devad(int phy_id) +{ + return phy_id & MDIO_PHY_ID_DEVAD; +} + +#define MDIO_SUPPORTS_C22 1 +#define MDIO_SUPPORTS_C45 2 + +#ifdef __KERNEL__ + +/** + * struct mdio_if_info - Ethernet controller MDIO interface + * @prtad: PRTAD of the PHY (%MDIO_PRTAD_NONE if not present/unknown) + * @mmds: Mask of MMDs expected to be present in the PHY. This must be + * non-zero unless @prtad = %MDIO_PRTAD_NONE. + * @mode_support: MDIO modes supported. If %MDIO_SUPPORTS_C22 is set then + * MII register access will be passed through with @devad = + * %MDIO_DEVAD_NONE. If %MDIO_EMULATE_C22 is set then access to + * commonly used clause 22 registers will be translated into + * clause 45 registers. + * @dev: Net device structure + * @mdio_read: Register read function; returns value or negative error code + * @mdio_write: Register write function; returns 0 or negative error code + */ +struct mdio_if_info { + int prtad; + u32 __bitwise mmds; + unsigned mode_support; + + struct net_device *dev; + int (*mdio_read)(struct net_device *dev, int prtad, int devad, + u16 addr); + int (*mdio_write)(struct net_device *dev, int prtad, int devad, + u16 addr, u16 val); +}; + +#define MDIO_PRTAD_NONE (-1) +#define MDIO_DEVAD_NONE (-1) +#define MDIO_EMULATE_C22 4 + +struct ethtool_cmd; +struct ethtool_pauseparam; +extern int mdio45_probe(struct mdio_if_info *mdio, int prtad); +extern int mdio_set_flag(const struct mdio_if_info *mdio, + int prtad, int devad, u16 addr, int mask, + bool sense); +extern int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmds); +extern int mdio45_nway_restart(const struct mdio_if_info *mdio); +extern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, + struct ethtool_cmd *ecmd, + u32 npage_adv, u32 npage_lpa); +extern void +mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio, + const struct ethtool_pauseparam *ecmd); + +/** + * mdio45_ethtool_gset - get settings for ETHTOOL_GSET + * @mdio: MDIO interface + * @ecmd: Ethtool request structure + * + * Since the CSRs for auto-negotiation using next pages are not fully + * standardised, this function does not attempt to decode them. Use + * mdio45_ethtool_gset_npage() to specify advertisement bits from next + * pages. + */ +static inline void mdio45_ethtool_gset(const struct mdio_if_info *mdio, + struct ethtool_cmd *ecmd) +{ + mdio45_ethtool_gset_npage(mdio, ecmd, 0, 0); +} + +extern int mdio_mii_ioctl(const struct mdio_if_info *mdio, + struct mii_ioctl_data *mii_data, int cmd); + +#endif /* __KERNEL__ */ +#endif /* __LINUX_MDIO_H__ */ diff --git a/include/linux/mii.h b/include/linux/mii.h index ad748588faf1..359fba880274 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -239,6 +239,22 @@ static inline unsigned int mii_duplex (unsigned int duplex_lock, return 0; } +/** + * mii_advertise_flowctrl - get flow control advertisement flags + * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both) + */ +static inline u16 mii_advertise_flowctrl(int cap) +{ + u16 adv = 0; + + if (cap & FLOW_CTRL_RX) + adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + if (cap & FLOW_CTRL_TX) + adv ^= ADVERTISE_PAUSE_ASYM; + + return adv; +} + /** * mii_resolve_flowctrl_fdx * @lcladv: value of MII ADVERTISE register @@ -250,18 +266,12 @@ static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv) { u8 cap = 0; - if (lcladv & ADVERTISE_PAUSE_CAP) { - if (lcladv & ADVERTISE_PAUSE_ASYM) { - if (rmtadv & LPA_PAUSE_CAP) - cap = FLOW_CTRL_TX | FLOW_CTRL_RX; - else if (rmtadv & LPA_PAUSE_ASYM) - cap = FLOW_CTRL_RX; - } else { - if (rmtadv & LPA_PAUSE_CAP) - cap = FLOW_CTRL_TX | FLOW_CTRL_RX; - } - } else if (lcladv & ADVERTISE_PAUSE_ASYM) { - if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) + if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) { + cap = FLOW_CTRL_TX | FLOW_CTRL_RX; + } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) { + if (lcladv & ADVERTISE_PAUSE_CAP) + cap = FLOW_CTRL_RX; + else if (rmtadv & ADVERTISE_PAUSE_CAP) cap = FLOW_CTRL_TX; } diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index ea1bf5ba092f..c7211ab6dd4b 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -25,5 +25,7 @@ #define SDIO_VENDOR_ID_MARVELL 0x02df #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103 +#define SDIO_DEVICE_ID_MARVELL_8688WLAN 0x9104 +#define SDIO_DEVICE_ID_MARVELL_8688BT 0x9105 #endif diff --git a/include/linux/net_dropmon.h b/include/linux/net_dropmon.h index 0e2e100c44a2..3ceb0cc1bc78 100644 --- a/include/linux/net_dropmon.h +++ b/include/linux/net_dropmon.h @@ -3,12 +3,20 @@ #include #include +#include struct net_dm_drop_point { __u8 pc[8]; __u32 count; }; +#define is_drop_point_hw(x) do {\ + int ____i, ____j;\ + for (____i = 0; ____i < 8; i ____i++)\ + ____j |= x[____i];\ + ____j;\ +} while (0) + #define NET_DM_CFG_VERSION 0 #define NET_DM_CFG_ALERT_COUNT 1 #define NET_DM_CFG_ALERT_DELAY 2 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5a96a1a406e9..9ea8d6dfe540 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -39,9 +39,11 @@ #include #include +#include #include #include +#include #include #include #ifdef CONFIG_DCB @@ -49,7 +51,6 @@ #endif struct vlan_group; -struct ethtool_ops; struct netpoll_info; /* 802.11 specific */ struct wireless_dev; @@ -210,6 +211,19 @@ struct dev_addr_list #define dmi_users da_users #define dmi_gusers da_gusers +struct netdev_hw_addr { + struct list_head list; + unsigned char addr[MAX_ADDR_LEN]; + unsigned char type; +#define NETDEV_HW_ADDR_T_LAN 1 +#define NETDEV_HW_ADDR_T_SAN 2 +#define NETDEV_HW_ADDR_T_SLAVE 3 +#define NETDEV_HW_ADDR_T_UNICAST 4 + int refcount; + bool synced; + struct rcu_head rcu_head; +}; + struct hh_cache { struct hh_cache *hh_next; /* Next entry */ @@ -447,12 +461,25 @@ enum netdev_queue_state_t }; struct netdev_queue { +/* + * read mostly part + */ struct net_device *dev; struct Qdisc *qdisc; unsigned long state; - spinlock_t _xmit_lock; - int xmit_lock_owner; struct Qdisc *qdisc_sleeping; +/* + * write mostly part + */ + spinlock_t _xmit_lock ____cacheline_aligned_in_smp; + int xmit_lock_owner; + /* + * please use this field instead of dev->trans_start + */ + unsigned long trans_start; + unsigned long tx_bytes; + unsigned long tx_packets; + unsigned long tx_dropped; } ____cacheline_aligned_in_smp; @@ -670,7 +697,9 @@ struct net_device #define NETIF_F_GRO 16384 /* Generic receive offload */ #define NETIF_F_LRO 32768 /* large receive offload */ +/* the GSO_MASK reserves bits 16 through 23 */ #define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */ +#define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 @@ -747,10 +776,11 @@ struct net_device unsigned char addr_len; /* hardware address length */ unsigned short dev_id; /* for shared network cards */ - spinlock_t addr_list_lock; - struct dev_addr_list *uc_list; /* Secondary unicast mac addresses */ + struct list_head uc_list; /* Secondary unicast mac + addresses */ int uc_count; /* Number of installed ucasts */ int uc_promisc; + spinlock_t addr_list_lock; struct dev_addr_list *mc_list; /* Multicast mac addresses */ int mc_count; /* Number of installed mcasts */ unsigned int promiscuity; @@ -776,8 +806,11 @@ struct net_device */ unsigned long last_rx; /* Time of last Rx */ /* Interface address info used in eth_type_trans() */ - unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast - because most packets are unicast) */ + unsigned char *dev_addr; /* hw address, (before bcast + because most packets are + unicast) */ + + struct list_head dev_addr_list; /* list of device hw addresses */ unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ @@ -797,6 +830,11 @@ struct net_device * One part is mostly used on xmit path (device) */ /* These may be needed for future network-power-down code. */ + + /* + * trans_start here is expensive for high speed devices on SMP, + * please use netdev_queue->trans_start instead. + */ unsigned long trans_start; /* Time (in jiffies) of last Tx */ int watchdog_timeo; /* used by dev_watchdog() */ @@ -867,49 +905,10 @@ struct net_device /* max exchange id for FCoE LRO by ddp */ unsigned int fcoe_ddp_xid; #endif - -#ifdef CONFIG_COMPAT_NET_DEV_OPS - struct { - int (*init)(struct net_device *dev); - void (*uninit)(struct net_device *dev); - int (*open)(struct net_device *dev); - int (*stop)(struct net_device *dev); - int (*hard_start_xmit) (struct sk_buff *skb, - struct net_device *dev); - u16 (*select_queue)(struct net_device *dev, - struct sk_buff *skb); - void (*change_rx_flags)(struct net_device *dev, - int flags); - void (*set_rx_mode)(struct net_device *dev); - void (*set_multicast_list)(struct net_device *dev); - int (*set_mac_address)(struct net_device *dev, - void *addr); - int (*validate_addr)(struct net_device *dev); - int (*do_ioctl)(struct net_device *dev, - struct ifreq *ifr, int cmd); - int (*set_config)(struct net_device *dev, - struct ifmap *map); - int (*change_mtu)(struct net_device *dev, int new_mtu); - int (*neigh_setup)(struct net_device *dev, - struct neigh_parms *); - void (*tx_timeout) (struct net_device *dev); - struct net_device_stats* (*get_stats)(struct net_device *dev); - void (*vlan_rx_register)(struct net_device *dev, - struct vlan_group *grp); - void (*vlan_rx_add_vid)(struct net_device *dev, - unsigned short vid); - void (*vlan_rx_kill_vid)(struct net_device *dev, - unsigned short vid); -#ifdef CONFIG_NET_POLL_CONTROLLER - void (*poll_controller)(struct net_device *dev); -#endif - }; -#endif }; #define to_net_dev(d) container_of(d, struct net_device, dev) #define NETDEV_ALIGN 32 -#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) static inline struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev, @@ -980,9 +979,7 @@ static inline bool netdev_uses_trailer_tags(struct net_device *dev) */ static inline void *netdev_priv(const struct net_device *dev) { - return (char *)dev + ((sizeof(struct net_device) - + NETDEV_ALIGN_CONST) - & ~NETDEV_ALIGN_CONST); + return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); } /* Set the sysfs physical device reference for the network logical device @@ -1012,6 +1009,12 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, void netif_napi_del(struct napi_struct *napi); struct napi_gro_cb { + /* Virtual address of skb_shinfo(skb)->frags[0].page + offset. */ + void *frag0; + + /* Length of frag0. */ + unsigned int frag0_len; + /* This indicates where we are processing relative to skb->data. */ int data_offset; @@ -1047,14 +1050,6 @@ struct packet_type { struct list_head list; }; -struct napi_gro_fraginfo { - skb_frag_t frags[MAX_SKB_FRAGS]; - unsigned int nr_frags; - unsigned int ip_summed; - unsigned int len; - __wsum csum; -}; - #include #include @@ -1119,9 +1114,9 @@ extern int dev_restart(struct net_device *dev); #ifdef CONFIG_NETPOLL_TRAP extern int netpoll_trap(void); #endif -extern void *skb_gro_header(struct sk_buff *skb, unsigned int hlen); extern int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb); +extern void skb_gro_reset_offset(struct sk_buff *skb); static inline unsigned int skb_gro_offset(const struct sk_buff *skb) { @@ -1138,16 +1133,34 @@ static inline void skb_gro_pull(struct sk_buff *skb, unsigned int len) NAPI_GRO_CB(skb)->data_offset += len; } -static inline void skb_gro_reset_offset(struct sk_buff *skb) +static inline void *skb_gro_header_fast(struct sk_buff *skb, + unsigned int offset) { - NAPI_GRO_CB(skb)->data_offset = 0; + return NAPI_GRO_CB(skb)->frag0 + offset; +} + +static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen) +{ + return NAPI_GRO_CB(skb)->frag0_len < hlen; +} + +static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, + unsigned int offset) +{ + NAPI_GRO_CB(skb)->frag0 = NULL; + NAPI_GRO_CB(skb)->frag0_len = 0; + return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; } static inline void *skb_gro_mac_header(struct sk_buff *skb) { - return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) : - page_address(skb_shinfo(skb)->frags[0].page) + - skb_shinfo(skb)->frags[0].page_offset; + return NAPI_GRO_CB(skb)->frag0 ?: skb_mac_header(skb); +} + +static inline void *skb_gro_network_header(struct sk_buff *skb) +{ + return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) + + skb_network_offset(skb); } static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, @@ -1442,12 +1455,18 @@ extern int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); extern void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb); -extern struct sk_buff * napi_fraginfo_skb(struct napi_struct *napi, - struct napi_gro_fraginfo *info); +extern struct sk_buff * napi_get_frags(struct napi_struct *napi); extern int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret); -extern int napi_gro_frags(struct napi_struct *napi, - struct napi_gro_fraginfo *info); +extern struct sk_buff * napi_frags_skb(struct napi_struct *napi); +extern int napi_gro_frags(struct napi_struct *napi); + +static inline void napi_free_frags(struct napi_struct *napi) +{ + kfree_skb(napi->skb); + napi->skb = NULL; +} + extern void netif_nit_deliver(struct sk_buff *skb); extern int dev_valid_name(const char *name); extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); @@ -1514,6 +1533,8 @@ static inline int netif_carrier_ok(const struct net_device *dev) return !test_bit(__LINK_STATE_NOCARRIER, &dev->state); } +extern unsigned long dev_trans_start(struct net_device *dev); + extern void __netdev_watchdog_up(struct net_device *dev); extern void netif_carrier_on(struct net_device *dev); @@ -1671,6 +1692,12 @@ static inline void __netif_tx_unlock_bh(struct netdev_queue *txq) spin_unlock_bh(&txq->_xmit_lock); } +static inline void txq_trans_update(struct netdev_queue *txq) +{ + if (txq->xmit_lock_owner != -1) + txq->trans_start = jiffies; +} + /** * netif_tx_lock - grab network device transmit lock * @dev: network device @@ -1778,6 +1805,13 @@ static inline void netif_addr_unlock_bh(struct net_device *dev) spin_unlock_bh(&dev->addr_list_lock); } +/* + * dev_addr_list walker. Should be used only for read access. Call with + * rcu_read_lock held. + */ +#define for_each_dev_addr(dev, ha) \ + list_for_each_entry_rcu(ha, &dev->dev_addr_list, list) + /* These functions live elsewhere (drivers/net/net_init.c, but related) */ extern void ether_setup(struct net_device *dev); @@ -1790,11 +1824,24 @@ extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, alloc_netdev_mq(sizeof_priv, name, setup, 1) extern int register_netdev(struct net_device *dev); extern void unregister_netdev(struct net_device *dev); + +/* Functions used for device addresses handling */ +extern int dev_addr_add(struct net_device *dev, unsigned char *addr, + unsigned char addr_type); +extern int dev_addr_del(struct net_device *dev, unsigned char *addr, + unsigned char addr_type); +extern int dev_addr_add_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type); +extern int dev_addr_del_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type); + /* Functions used for secondary unicast and multicast support */ extern void dev_set_rx_mode(struct net_device *dev); extern void __dev_set_rx_mode(struct net_device *dev); -extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen); -extern int dev_unicast_add(struct net_device *dev, void *addr, int alen); +extern int dev_unicast_delete(struct net_device *dev, void *addr); +extern int dev_unicast_add(struct net_device *dev, void *addr); extern int dev_unicast_sync(struct net_device *to, struct net_device *from); extern void dev_unicast_unsync(struct net_device *to, struct net_device *from); extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); @@ -1856,15 +1903,14 @@ static inline int net_gso_ok(int features, int gso_type) static inline int skb_gso_ok(struct sk_buff *skb, int features) { - return net_gso_ok(features, skb_shinfo(skb)->gso_type); + return net_gso_ok(features, skb_shinfo(skb)->gso_type) && + (!skb_has_frags(skb) || (features & NETIF_F_FRAGLIST)); } static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) { return skb_is_gso(skb) && (!skb_gso_ok(skb, dev->features) || - (skb_shinfo(skb)->frag_list && - !(dev->features & NETIF_F_FRAGLIST)) || unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); } @@ -1874,6 +1920,16 @@ static inline void netif_set_gso_max_size(struct net_device *dev, dev->gso_max_size = size; } +static inline void skb_bond_set_mac_by_master(struct sk_buff *skb, + struct net_device *master) +{ + if (skb->pkt_type == PACKET_HOST) { + u16 *dest = (u16 *) eth_hdr(skb)->h_dest; + + memcpy(dest, master->dev_addr, ETH_ALEN); + } +} + /* On bonding slaves other than the currently active slave, suppress * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and * ARP on active-backup slaves with arp_validate enabled. @@ -1887,6 +1943,14 @@ static inline int skb_bond_should_drop(struct sk_buff *skb) if (master->priv_flags & IFF_MASTER_ARPMON) dev->last_rx = jiffies; + if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) { + /* Do address unmangle. The local destination address + * will be always the one master has. Provides the right + * functionality in a bridge. + */ + skb_bond_set_mac_by_master(skb, master); + } + if (dev->priv_flags & IFF_SLAVE_INACTIVE) { if ((dev->priv_flags & IFF_SLAVE_NEEDARP) && skb->protocol == __cpu_to_be16(ETH_P_ARP)) @@ -1908,6 +1972,28 @@ static inline int skb_bond_should_drop(struct sk_buff *skb) } extern struct pernet_operations __net_initdata loopback_net_ops; + +static inline int dev_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) + return -EOPNOTSUPP; + return dev->ethtool_ops->get_settings(dev, cmd); +} + +static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_rx_csum) + return 0; + return dev->ethtool_ops->get_rx_csum(dev); +} + +static inline u32 dev_ethtool_get_flags(struct net_device *dev) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_flags) + return 0; + return dev->ethtool_ops->get_flags(dev); +} #endif /* __KERNEL__ */ -#endif /* _LINUX_DEV_H */ +#endif /* _LINUX_NETDEVICE_H */ diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index af9d2fb97212..2aea50399c0b 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -33,6 +33,7 @@ header-y += xt_limit.h header-y += xt_mac.h header-y += xt_mark.h header-y += xt_multiport.h +header-y += xt_osf.h header-y += xt_owner.h header-y += xt_pkttype.h header-y += xt_quota.h diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 885cbe282260..a8248ee422b7 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -75,75 +75,6 @@ enum ip_conntrack_status { IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), }; -/* Connection tracking event bits */ -enum ip_conntrack_events -{ - /* New conntrack */ - IPCT_NEW_BIT = 0, - IPCT_NEW = (1 << IPCT_NEW_BIT), - - /* Expected connection */ - IPCT_RELATED_BIT = 1, - IPCT_RELATED = (1 << IPCT_RELATED_BIT), - - /* Destroyed conntrack */ - IPCT_DESTROY_BIT = 2, - IPCT_DESTROY = (1 << IPCT_DESTROY_BIT), - - /* Timer has been refreshed */ - IPCT_REFRESH_BIT = 3, - IPCT_REFRESH = (1 << IPCT_REFRESH_BIT), - - /* Status has changed */ - IPCT_STATUS_BIT = 4, - IPCT_STATUS = (1 << IPCT_STATUS_BIT), - - /* Update of protocol info */ - IPCT_PROTOINFO_BIT = 5, - IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT), - - /* Volatile protocol info */ - IPCT_PROTOINFO_VOLATILE_BIT = 6, - IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT), - - /* New helper for conntrack */ - IPCT_HELPER_BIT = 7, - IPCT_HELPER = (1 << IPCT_HELPER_BIT), - - /* Update of helper info */ - IPCT_HELPINFO_BIT = 8, - IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT), - - /* Volatile helper info */ - IPCT_HELPINFO_VOLATILE_BIT = 9, - IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT), - - /* NAT info */ - IPCT_NATINFO_BIT = 10, - IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), - - /* Counter highest bit has been set, unused */ - IPCT_COUNTER_FILLING_BIT = 11, - IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), - - /* Mark is set */ - IPCT_MARK_BIT = 12, - IPCT_MARK = (1 << IPCT_MARK_BIT), - - /* NAT sequence adjustment */ - IPCT_NATSEQADJ_BIT = 13, - IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT), - - /* Secmark is set */ - IPCT_SECMARK_BIT = 14, - IPCT_SECMARK = (1 << IPCT_SECMARK_BIT), -}; - -enum ip_conntrack_expect_events { - IPEXP_NEW_BIT = 0, - IPEXP_NEW = (1 << IPEXP_NEW_BIT), -}; - #ifdef __KERNEL__ struct ip_conntrack_stat { diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h index b2f384d42611..4352feed2377 100644 --- a/include/linux/netfilter/nf_conntrack_tcp.h +++ b/include/linux/netfilter/nf_conntrack_tcp.h @@ -15,7 +15,8 @@ enum tcp_conntrack { TCP_CONNTRACK_LAST_ACK, TCP_CONNTRACK_TIME_WAIT, TCP_CONNTRACK_CLOSE, - TCP_CONNTRACK_LISTEN, + TCP_CONNTRACK_LISTEN, /* obsolete */ +#define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN TCP_CONNTRACK_MAX, TCP_CONNTRACK_IGNORE }; diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index c600083cbdf5..bff4d5741d98 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -46,7 +46,8 @@ struct nfgenmsg { #define NFNL_SUBSYS_CTNETLINK_EXP 2 #define NFNL_SUBSYS_QUEUE 3 #define NFNL_SUBSYS_ULOG 4 -#define NFNL_SUBSYS_COUNT 5 +#define NFNL_SUBSYS_OSF 5 +#define NFNL_SUBSYS_COUNT 6 #ifdef __KERNEL__ @@ -75,7 +76,7 @@ extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); extern int nfnetlink_has_listeners(unsigned int group); extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, - int echo); + int echo, gfp_t flags); extern void nfnetlink_set_err(u32 pid, u32 group, int error); extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index 1a865e48b8eb..ed4ef8d0b11b 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -101,6 +101,7 @@ enum ctattr_protoinfo_dccp { CTA_PROTOINFO_DCCP_UNSPEC, CTA_PROTOINFO_DCCP_STATE, CTA_PROTOINFO_DCCP_ROLE, + CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, __CTA_PROTOINFO_DCCP_MAX, }; #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index c9efe039dc57..1030b7593898 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -184,9 +184,10 @@ struct xt_counters_info * @matchinfo: per-match data * @fragoff: packet is a fragment, this is the data offset * @thoff: position of transport header relative to skb->data - * @hotdrop: drop packet if we had inspection problems + * @hook: hook number given packet came from * @family: Actual NFPROTO_* through which the function is invoked * (helpful when match->family == NFPROTO_UNSPEC) + * @hotdrop: drop packet if we had inspection problems */ struct xt_match_param { const struct net_device *in, *out; @@ -194,8 +195,9 @@ struct xt_match_param { const void *matchinfo; int fragoff; unsigned int thoff; - bool *hotdrop; + unsigned int hooknum; u_int8_t family; + bool *hotdrop; }; /** diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h index 982a89f78272..2584f4a777de 100644 --- a/include/linux/netfilter/xt_NFQUEUE.h +++ b/include/linux/netfilter/xt_NFQUEUE.h @@ -15,4 +15,9 @@ struct xt_NFQ_info { __u16 queuenum; }; +struct xt_NFQ_info_v1 { + __u16 queuenum; + __u16 queues_total; +}; + #endif /* _XT_NFQ_TARGET_H */ diff --git a/include/linux/netfilter/xt_osf.h b/include/linux/netfilter/xt_osf.h new file mode 100644 index 000000000000..fd2272e0959a --- /dev/null +++ b/include/linux/netfilter/xt_osf.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003+ Evgeniy Polyakov + * + * + * 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 + */ + +#ifndef _XT_OSF_H +#define _XT_OSF_H + +#define MAXGENRELEN 32 + +#define XT_OSF_GENRE (1<<0) +#define XT_OSF_TTL (1<<1) +#define XT_OSF_LOG (1<<2) +#define XT_OSF_INVERT (1<<3) + +#define XT_OSF_LOGLEVEL_ALL 0 /* log all matched fingerprints */ +#define XT_OSF_LOGLEVEL_FIRST 1 /* log only the first matced fingerprint */ +#define XT_OSF_LOGLEVEL_ALL_KNOWN 2 /* do not log unknown packets */ + +#define XT_OSF_TTL_TRUE 0 /* True ip and fingerprint TTL comparison */ +#define XT_OSF_TTL_LESS 1 /* Check if ip TTL is less than fingerprint one */ +#define XT_OSF_TTL_NOCHECK 2 /* Do not compare ip and fingerprint TTL at all */ + +struct xt_osf_info { + char genre[MAXGENRELEN]; + __u32 len; + __u32 flags; + __u32 loglevel; + __u32 ttl; +}; + +/* + * Wildcard MSS (kind of). + * It is used to implement a state machine for the different wildcard values + * of the MSS and window sizes. + */ +struct xt_osf_wc { + __u32 wc; + __u32 val; +}; + +/* + * This struct represents IANA options + * http://www.iana.org/assignments/tcp-parameters + */ +struct xt_osf_opt { + __u16 kind, length; + struct xt_osf_wc wc; +}; + +struct xt_osf_user_finger { + struct xt_osf_wc wss; + + __u8 ttl, df; + __u16 ss, mss; + __u16 opt_num; + + char genre[MAXGENRELEN]; + char version[MAXGENRELEN]; + char subtype[MAXGENRELEN]; + + /* MAX_IPOPTLEN is maximum if all options are NOPs or EOLs */ + struct xt_osf_opt opt[MAX_IPOPTLEN]; +}; + +struct xt_osf_nlmsg { + struct xt_osf_user_finger f; + struct iphdr ip; + struct tcphdr tcp; +}; + +/* Defines for IANA option kinds */ + +enum iana_options { + OSFOPT_EOL = 0, /* End of options */ + OSFOPT_NOP, /* NOP */ + OSFOPT_MSS, /* Maximum segment size */ + OSFOPT_WSO, /* Window scale option */ + OSFOPT_SACKP, /* SACK permitted */ + OSFOPT_SACK, /* SACK */ + OSFOPT_ECHO, + OSFOPT_ECHOREPLY, + OSFOPT_TS, /* Timestamp option */ + OSFOPT_POCP, /* Partial Order Connection Permitted */ + OSFOPT_POSP, /* Partial Order Service Profile */ + + /* Others are not used in the current OSF */ + OSFOPT_EMPTY = 255, +}; + +/* + * Initial window size option state machine: multiple of mss, mtu or + * plain numeric value. Can also be made as plain numeric value which + * is not a multiple of specified value. + */ +enum xt_osf_window_size_options { + OSF_WSS_PLAIN = 0, + OSF_WSS_MSS, + OSF_WSS_MTU, + OSF_WSS_MODULO, + OSF_WSS_MAX, +}; + +/* + * Add/remove fingerprint from the kernel. + */ +enum xt_osf_msg_types { + OSF_MSG_ADD, + OSF_MSG_REMOVE, + OSF_MSG_MAX, +}; + +enum xt_osf_attr_type { + OSF_ATTR_UNSPEC, + OSF_ATTR_FINGER, + OSF_ATTR_MAX, +}; + +#endif /* _XT_OSF_H */ diff --git a/include/linux/netfilter/xt_socket.h b/include/linux/netfilter/xt_socket.h new file mode 100644 index 000000000000..6f475b8ff34b --- /dev/null +++ b/include/linux/netfilter/xt_socket.h @@ -0,0 +1,12 @@ +#ifndef _XT_SOCKET_H +#define _XT_SOCKET_H + +enum { + XT_SOCKET_TRANSPARENT = 1 << 0, +}; + +struct xt_socket_mtinfo1 { + __u8 flags; +}; + +#endif /* _XT_SOCKET_H */ diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index cbe8ce3bf486..dbea93b694e5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -7,7 +7,7 @@ * Copyright 2008 Michael Wu * Copyright 2008 Luis Carlos Cobo * Copyright 2008 Michael Buesch - * Copyright 2008 Luis R. Rodriguez + * Copyright 2008, 2009 Luis R. Rodriguez * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe * @@ -25,6 +25,8 @@ * */ +#include + /** * DOC: Station handling * @@ -46,8 +48,10 @@ * to get a list of all present wiphys. * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or - * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, + * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request * or rename notification. Has attributes %NL80211_ATTR_WIPHY and * %NL80211_ATTR_WIPHY_NAME. @@ -75,8 +79,8 @@ * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, - * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER - * attributes. + * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, + * and %NL80211_ATTR_KEY_SEQ attributes. * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX * or %NL80211_ATTR_MAC. * @@ -166,6 +170,22 @@ * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on * to (%NL80211_ATTR_REG_ALPHA2). + * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon + * has been found while world roaming thus enabling active scan or + * any mode of operation that initiates TX (beacons) on a channel + * where we would not have been able to do either before. As an example + * if you are world roaming (regulatory domain set to world or if your + * driver is using a custom world roaming regulatory domain) and while + * doing a passive scan on the 5 GHz band you find an AP there (if not + * on a DFS channel) you will now be able to actively scan for that AP + * or use AP mode on your card on that same channel. Note that this will + * never be used for channels 1-11 on the 2 GHz band as they are always + * enabled world wide. This beacon hint is only sent if your device had + * either disabled active scanning or beaconing on a channel. We send to + * userspace the wiphy on which we removed a restriction from + * (%NL80211_ATTR_WIPHY) and the channel on which this occurred + * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) + * the beacon hint was processed. * * @NL80211_CMD_AUTHENTICATE: authentication request and notification. * This command is used both as a command (request to authenticate) and @@ -185,8 +205,12 @@ * frame, i.e., it was for the local STA and was received in correct * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the * MLME SAP interface (kernel providing MLME, userspace SME). The - * included NL80211_ATTR_FRAME attribute contains the management frame - * (including both the header and frame body, but not FCS). + * included %NL80211_ATTR_FRAME attribute contains the management frame + * (including both the header and frame body, but not FCS). This event is + * also used to indicate if the authentication attempt timed out. In that + * case the %NL80211_ATTR_FRAME attribute is replaced with a + * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which + * pending authentication timed out). * @NL80211_CMD_ASSOCIATE: association request and notification; like * NL80211_CMD_AUTHENTICATE but for Association and Reassociation * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, @@ -199,6 +223,25 @@ * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). * + * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael + * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the + * event includes %NL80211_ATTR_MAC to describe the source MAC address of + * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key + * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and + * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this + * event matches with MLME-MICHAELMICFAILURE.indication() primitive + * + * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a + * FREQ attribute (for the initial frequency if no peer can be found) + * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those + * should be fixed rather than automatically determined. Can only be + * executed on a network interface that is UP, and fixed BSSID/FREQ + * may be rejected. Another optional parameter is the beacon interval, + * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not + * given defaults to 100 TU (102.4ms). + * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is + * determined by the network interface. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -260,6 +303,13 @@ enum nl80211_commands { NL80211_CMD_DEAUTHENTICATE, NL80211_CMD_DISASSOCIATE, + NL80211_CMD_MICHAEL_MIC_FAILURE, + + NL80211_CMD_REG_BEACON_HINT, + + NL80211_CMD_JOIN_IBSS, + NL80211_CMD_LEAVE_IBSS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -278,6 +328,7 @@ enum nl80211_commands { #define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE #define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE +#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT /** * enum nl80211_attrs - nl80211 netlink attributes @@ -296,6 +347,18 @@ enum nl80211_commands { * NL80211_CHAN_HT20 = HT20 only * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel + * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is + * less than or equal to the RTS threshold; allowed range: 1..255; + * dot11ShortRetryLimit; u8 + * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is + * greater than the RTS threshold; allowed range: 1..255; + * dot11ShortLongLimit; u8 + * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum + * length in octets for frames; allowed range: 256..8000, disable + * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 + * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length + * larger than or equal to this use RTS/CTS handshake); allowed range: + * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 * * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on * @NL80211_ATTR_IFNAME: network interface name @@ -319,7 +382,7 @@ enum nl80211_commands { * * @NL80211_ATTR_STA_AID: Association ID for the station (u16) * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_sta_flags. + * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by * IEEE 802.11 7.3.1.6 (u16). * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported @@ -380,6 +443,8 @@ enum nl80211_commands { * * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements + * that can be added to a scan request * * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive @@ -408,6 +473,44 @@ enum nl80211_commands { * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and * %NL80211_CMD_DISASSOCIATE, u16 * + * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as + * a u32 + * + * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _before_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _after_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * + * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported + * cipher suites + * + * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look + * for other networks on different channels + * + * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this + * is used, e.g., with %NL80211_CMD_AUTHENTICATE event + * + * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is + * used for the association (&enum nl80211_mfp, represented as a u32); + * this attribute can be used + * with %NL80211_CMD_ASSOCIATE request + * + * @NL80211_ATTR_STA_FLAGS2: Attribute containing a + * &struct nl80211_sta_flag_update. + * + * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls + * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in + * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE + * request, the driver will assume that the port is unauthorized until + * authorized by user space. Otherwise, port is marked authorized by + * default in station mode. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -492,6 +595,30 @@ enum nl80211_attrs { NL80211_ATTR_AUTH_TYPE, NL80211_ATTR_REASON_CODE, + NL80211_ATTR_KEY_TYPE, + + NL80211_ATTR_MAX_SCAN_IE_LEN, + NL80211_ATTR_CIPHER_SUITES, + + NL80211_ATTR_FREQ_BEFORE, + NL80211_ATTR_FREQ_AFTER, + + NL80211_ATTR_FREQ_FIXED, + + + NL80211_ATTR_WIPHY_RETRY_SHORT, + NL80211_ATTR_WIPHY_RETRY_LONG, + NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + NL80211_ATTR_WIPHY_RTS_THRESHOLD, + + NL80211_ATTR_TIMED_OUT, + + NL80211_ATTR_USE_MFP, + + NL80211_ATTR_STA_FLAGS2, + + NL80211_ATTR_CONTROL_PORT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -580,6 +707,18 @@ enum nl80211_sta_flags { NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 }; +/** + * struct nl80211_sta_flag_update - station flags mask/set + * @mask: mask of station flags to set + * @set: which values to set them to + * + * Both mask and set contain bits as per &enum nl80211_sta_flags. + */ +struct nl80211_sta_flag_update { + __u32 mask; + __u32 set; +} __attribute__((packed)); + /** * enum nl80211_rate_info - bitrate information * @@ -1062,4 +1201,27 @@ enum nl80211_auth_type { NL80211_AUTHTYPE_FT, NL80211_AUTHTYPE_NETWORK_EAP, }; + +/** + * enum nl80211_key_type - Key Type + * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key + * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key + * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) + */ +enum nl80211_key_type { + NL80211_KEYTYPE_GROUP, + NL80211_KEYTYPE_PAIRWISE, + NL80211_KEYTYPE_PEERKEY, +}; + +/** + * enum nl80211_mfp - Management frame protection state + * @NL80211_MFP_NO: Management frame protection not used + * @NL80211_MFP_REQUIRED: Management frame protection required + */ +enum nl80211_mfp { + NL80211_MFP_NO, + NL80211_MFP_REQUIRED, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h new file mode 100644 index 000000000000..2cda00ccfcca --- /dev/null +++ b/include/linux/nl802154.h @@ -0,0 +1,119 @@ +/* + * 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 NL802154_H +#define NL802154_H + +#define IEEE802154_NL_NAME "802.15.4 MAC" +#define IEEE802154_MCAST_COORD_NAME "coordinator" +#define IEEE802154_MCAST_BEACON_NAME "beacon" + +enum { + __IEEE802154_ATTR_INVALID, + + IEEE802154_ATTR_DEV_NAME, + IEEE802154_ATTR_DEV_INDEX, + + IEEE802154_ATTR_STATUS, + + IEEE802154_ATTR_SHORT_ADDR, + IEEE802154_ATTR_HW_ADDR, + IEEE802154_ATTR_PAN_ID, + + IEEE802154_ATTR_CHANNEL, + + IEEE802154_ATTR_COORD_SHORT_ADDR, + IEEE802154_ATTR_COORD_HW_ADDR, + IEEE802154_ATTR_COORD_PAN_ID, + + IEEE802154_ATTR_SRC_SHORT_ADDR, + IEEE802154_ATTR_SRC_HW_ADDR, + IEEE802154_ATTR_SRC_PAN_ID, + + IEEE802154_ATTR_DEST_SHORT_ADDR, + IEEE802154_ATTR_DEST_HW_ADDR, + IEEE802154_ATTR_DEST_PAN_ID, + + IEEE802154_ATTR_CAPABILITY, + IEEE802154_ATTR_REASON, + IEEE802154_ATTR_SCAN_TYPE, + IEEE802154_ATTR_CHANNELS, + IEEE802154_ATTR_DURATION, + IEEE802154_ATTR_ED_LIST, + IEEE802154_ATTR_BCN_ORD, + IEEE802154_ATTR_SF_ORD, + IEEE802154_ATTR_PAN_COORD, + IEEE802154_ATTR_BAT_EXT, + IEEE802154_ATTR_COORD_REALIGN, + IEEE802154_ATTR_SEC, + + __IEEE802154_ATTR_MAX, +}; + +#define IEEE802154_ATTR_MAX (__IEEE802154_ATTR_MAX - 1) + +extern struct nla_policy ieee802154_policy[]; + +/* commands */ +/* REQ should be responded with CONF + * and INDIC with RESP + */ +enum { + __IEEE802154_COMMAND_INVALID, + + IEEE802154_ASSOCIATE_REQ, + IEEE802154_ASSOCIATE_CONF, + IEEE802154_DISASSOCIATE_REQ, + IEEE802154_DISASSOCIATE_CONF, + IEEE802154_GET_REQ, + IEEE802154_GET_CONF, + IEEE802154_RESET_REQ, + IEEE802154_RESET_CONF, + IEEE802154_SCAN_REQ, + IEEE802154_SCAN_CONF, + IEEE802154_SET_REQ, + IEEE802154_SET_CONF, + IEEE802154_START_REQ, + IEEE802154_START_CONF, + IEEE802154_SYNC_REQ, + IEEE802154_POLL_REQ, + IEEE802154_POLL_CONF, + + IEEE802154_ASSOCIATE_INDIC, + IEEE802154_ASSOCIATE_RESP, + IEEE802154_DISASSOCIATE_INDIC, + IEEE802154_BEACON_NOTIFY_INDIC, + IEEE802154_ORPHAN_INDIC, + IEEE802154_ORPHAN_RESP, + IEEE802154_COMM_STATUS_INDIC, + IEEE802154_SYNC_LOSS_INDIC, + + IEEE802154_GTS_REQ, /* Not supported yet */ + IEEE802154_GTS_INDIC, /* Not supported yet */ + IEEE802154_GTS_CONF, /* Not supported yet */ + IEEE802154_RX_ENABLE_REQ, /* Not supported yet */ + IEEE802154_RX_ENABLE_CONF, /* Not supported yet */ + + __IEEE802154_CMD_MAX, +}; + +#define IEEE802154_CMD_MAX (__IEEE802154_CMD_MAX - 1) + +#endif diff --git a/include/linux/notifier.h b/include/linux/notifier.h index b86fa2ffca0c..81bc252dc8ac 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -198,6 +198,7 @@ static inline int notifier_to_errno(int ret) #define NETDEV_CHANGENAME 0x000A #define NETDEV_FEAT_CHANGE 0x000B #define NETDEV_BONDING_FAILOVER 0x000C +#define NETDEV_PRE_UP 0x000D #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN diff --git a/include/linux/of.h b/include/linux/of.h index 6a7efa242f5e..7be2d1043c16 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -77,6 +77,9 @@ extern int of_n_size_cells(struct device_node *np); extern const struct of_device_id *of_match_node( const struct of_device_id *matches, const struct device_node *node); extern int of_modalias_node(struct device_node *node, char *modalias, int len); +extern struct device_node *of_parse_phandle(struct device_node *np, + const char *phandle_name, + int index); extern int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const char *cells_name, int index, struct device_node **out_node, const void **out_args); diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h new file mode 100644 index 000000000000..c9663c690303 --- /dev/null +++ b/include/linux/of_mdio.h @@ -0,0 +1,22 @@ +/* + * OF helpers for the MDIO (Ethernet PHY) API + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + * + * This file is released under the GPLv2 + */ + +#ifndef __LINUX_OF_MDIO_H +#define __LINUX_OF_MDIO_H + +#include +#include + +extern int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np); +extern struct phy_device *of_phy_find_device(struct device_node *phy_np); +extern struct phy_device *of_phy_connect(struct net_device *dev, + struct device_node *phy_np, + void (*hndlr)(struct net_device *), + u32 flags, phy_interface_t iface); + +#endif /* __LINUX_OF_MDIO_H */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a3df4a2bba63..aa01d38c9971 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1067,8 +1067,6 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE 0x0035 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036 -#define PCI_DEVICE_ID_NVIDIA_NVENET_10 0x0037 -#define PCI_DEVICE_ID_NVIDIA_NVENET_11 0x0038 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2 0x003e #define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800 0x0041 @@ -1079,21 +1077,16 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE 0x0053 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2 0x0055 -#define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 -#define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 #define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 #define PCI_DEVICE_ID_NVIDIA_CK804_PCIE 0x005d #define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 -#define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 #define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085 -#define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086 #define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089 #define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a -#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e #define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT 0x0090 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX 0x0091 @@ -1109,15 +1102,12 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5 -#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6 #define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da -#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df #define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5 -#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6 #define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0 @@ -1177,7 +1167,6 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4 #define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc #define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM 0x01c1 -#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3 #define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201 @@ -1200,8 +1189,6 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2 0x037F -#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268 -#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282 @@ -1248,46 +1235,21 @@ #define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E -#define PCI_DEVICE_ID_NVIDIA_NVENET_14 0x0372 #define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 -#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5 -#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS 0x03EB #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC -#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE -#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS 0x0446 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448 -#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450 -#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 -#define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 -#define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS 0x0542 -#define PCI_DEVICE_ID_NVIDIA_NVENET_24 0x054C -#define PCI_DEVICE_ID_NVIDIA_NVENET_25 0x054D -#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E -#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F -#define PCI_DEVICE_ID_NVIDIA_NVENET_28 0x07DC -#define PCI_DEVICE_ID_NVIDIA_NVENET_29 0x07DD -#define PCI_DEVICE_ID_NVIDIA_NVENET_30 0x07DE -#define PCI_DEVICE_ID_NVIDIA_NVENET_31 0x07DF #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS 0x0752 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 -#define PCI_DEVICE_ID_NVIDIA_NVENET_32 0x0760 -#define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761 -#define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762 -#define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2 -#define PCI_DEVICE_ID_NVIDIA_NVENET_36 0x0AB0 -#define PCI_DEVICE_ID_NVIDIA_NVENET_37 0x0AB1 -#define PCI_DEVICE_ID_NVIDIA_NVENET_38 0x0AB2 -#define PCI_DEVICE_ID_NVIDIA_NVENET_39 0x0AB3 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_TT128 0x9128 @@ -1926,6 +1888,8 @@ #define PCI_SUBDEVICE_ID_CCD_SWYX4S 0xB540 #define PCI_SUBDEVICE_ID_CCD_JH4S20 0xB550 #define PCI_SUBDEVICE_ID_CCD_IOB8ST_1 0xB552 +#define PCI_SUBDEVICE_ID_CCD_JHSE1 0xB553 +#define PCI_SUBDEVICE_ID_CCD_JH8S 0xB55B #define PCI_SUBDEVICE_ID_CCD_BN4S 0xB560 #define PCI_SUBDEVICE_ID_CCD_BN8S 0xB562 #define PCI_SUBDEVICE_ID_CCD_BNE1 0xB563 @@ -2332,6 +2296,8 @@ #define PCI_VENDOR_ID_QMI 0x1a32 +#define PCI_VENDOR_ID_AZWAVE 0x1a3b + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 diff --git a/include/linux/phy.h b/include/linux/phy.h index 97e40cb6b588..b1368b8f6572 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -79,7 +79,7 @@ typedef enum { * Need to be a little smaller than phydev->dev.bus_id to leave room * for the ":%02x" */ -#define MII_BUS_ID_SIZE (BUS_ID_SIZE - 3) +#define MII_BUS_ID_SIZE (20 - 3) /* * The Bus class for PHYs. Devices which provide access to @@ -407,7 +407,7 @@ struct phy_driver { /* A Structure for boards to register fixups with the PHY Lib */ struct phy_fixup { struct list_head list; - char bus_id[BUS_ID_SIZE]; + char bus_id[20]; u32 phy_uid; u32 phy_uid_mask; int (*run)(struct phy_device *phydev); @@ -444,10 +444,16 @@ static inline int phy_write(struct phy_device *phydev, u16 regnum, u16 val) int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); struct phy_device* get_phy_device(struct mii_bus *bus, int addr); +int phy_device_register(struct phy_device *phy); int phy_clear_interrupt(struct phy_device *phydev); int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); +int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface); struct phy_device * phy_attach(struct net_device *dev, const char *bus_id, u32 flags, phy_interface_t interface); +int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, + void (*handler)(struct net_device *), u32 flags, + phy_interface_t interface); struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device *), u32 flags, phy_interface_t interface); diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 164332cbb77c..16e39c7a67fc 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -4,6 +4,7 @@ /* * Copyright (C) 2006 - 2007 Ivo van Doorn * Copyright (C) 2007 Dmitry Torokhov + * Copyright 2009 Johannes Berg * * 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 @@ -21,132 +22,332 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include + +/* define userspace visible states */ +#define RFKILL_STATE_SOFT_BLOCKED 0 +#define RFKILL_STATE_UNBLOCKED 1 +#define RFKILL_STATE_HARD_BLOCKED 2 + +/** + * enum rfkill_type - type of rfkill switch. + * + * @RFKILL_TYPE_ALL: toggles all switches (userspace only) + * @RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. + * @RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. + * @RFKILL_TYPE_UWB: switch is on a ultra wideband device. + * @RFKILL_TYPE_WIMAX: switch is on a WiMAX device. + * @RFKILL_TYPE_WWAN: switch is on a wireless WAN device. + * @NUM_RFKILL_TYPES: number of defined rfkill types + */ +enum rfkill_type { + RFKILL_TYPE_ALL = 0, + RFKILL_TYPE_WLAN, + RFKILL_TYPE_BLUETOOTH, + RFKILL_TYPE_UWB, + RFKILL_TYPE_WIMAX, + RFKILL_TYPE_WWAN, + NUM_RFKILL_TYPES, +}; + +/** + * enum rfkill_operation - operation types + * @RFKILL_OP_ADD: a device was added + * @RFKILL_OP_DEL: a device was removed + * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device + * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all) + */ +enum rfkill_operation { + RFKILL_OP_ADD = 0, + RFKILL_OP_DEL, + RFKILL_OP_CHANGE, + RFKILL_OP_CHANGE_ALL, +}; + +/** + * struct rfkill_event - events for userspace on /dev/rfkill + * @idx: index of dev rfkill + * @type: type of the rfkill struct + * @op: operation code + * @hard: hard state (0/1) + * @soft: soft state (0/1) + * + * Structure used for userspace communication on /dev/rfkill, + * used for events from the kernel and control to the kernel. + */ +struct rfkill_event { + __u32 idx; + __u8 type; + __u8 op; + __u8 soft, hard; +} __packed; + +/* ioctl for turning off rfkill-input (if present) */ +#define RFKILL_IOC_MAGIC 'R' +#define RFKILL_IOC_NOINPUT 1 +#define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT) + +/* and that's all userspace gets */ +#ifdef __KERNEL__ +/* don't allow anyone to use these in the kernel */ +enum rfkill_user_states { + RFKILL_USER_STATE_SOFT_BLOCKED = RFKILL_STATE_SOFT_BLOCKED, + RFKILL_USER_STATE_UNBLOCKED = RFKILL_STATE_UNBLOCKED, + RFKILL_USER_STATE_HARD_BLOCKED = RFKILL_STATE_HARD_BLOCKED, +}; +#undef RFKILL_STATE_SOFT_BLOCKED +#undef RFKILL_STATE_UNBLOCKED +#undef RFKILL_STATE_HARD_BLOCKED + #include #include #include #include #include #include +#include + +/* this is opaque */ +struct rfkill; /** - * enum rfkill_type - type of rfkill switch. - * RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. - * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. - * RFKILL_TYPE_UWB: switch is on a ultra wideband device. - * RFKILL_TYPE_WIMAX: switch is on a WiMAX device. - * RFKILL_TYPE_WWAN: switch is on a wireless WAN device. - */ -enum rfkill_type { - RFKILL_TYPE_WLAN , - RFKILL_TYPE_BLUETOOTH, - RFKILL_TYPE_UWB, - RFKILL_TYPE_WIMAX, - RFKILL_TYPE_WWAN, - RFKILL_TYPE_MAX, -}; - -enum rfkill_state { - RFKILL_STATE_SOFT_BLOCKED = 0, /* Radio output blocked */ - RFKILL_STATE_UNBLOCKED = 1, /* Radio output allowed */ - RFKILL_STATE_HARD_BLOCKED = 2, /* Output blocked, non-overrideable */ - RFKILL_STATE_MAX, /* marker for last valid state */ -}; - -/* - * These are DEPRECATED, drivers using them should be verified to - * comply with the rfkill usage guidelines in Documentation/rfkill.txt - * and then converted to use the new names for rfkill_state - */ -#define RFKILL_STATE_OFF RFKILL_STATE_SOFT_BLOCKED -#define RFKILL_STATE_ON RFKILL_STATE_UNBLOCKED - -/** - * struct rfkill - rfkill control structure. - * @name: Name of the switch. - * @type: Radio type which the button controls, the value stored - * here should be a value from enum rfkill_type. - * @state: State of the switch, "UNBLOCKED" means radio can operate. - * @user_claim_unsupported: Whether the hardware supports exclusive - * RF-kill control by userspace. Set this before registering. - * @user_claim: Set when the switch is controlled exlusively by userspace. - * @mutex: Guards switch state transitions. It serializes callbacks - * and also protects the state. - * @data: Pointer to the RF button drivers private data which will be - * passed along when toggling radio state. - * @toggle_radio(): Mandatory handler to control state of the radio. - * only RFKILL_STATE_SOFT_BLOCKED and RFKILL_STATE_UNBLOCKED are - * valid parameters. - * @get_state(): handler to read current radio state from hardware, - * may be called from atomic context, should return 0 on success. - * Either this handler OR judicious use of rfkill_force_state() is - * MANDATORY for any driver capable of RFKILL_STATE_HARD_BLOCKED. - * @led_trigger: A LED trigger for this button's LED. - * @dev: Device structure integrating the switch into device tree. - * @node: Used to place switch into list of all switches known to the - * the system. + * struct rfkill_ops - rfkill driver methods * - * This structure represents a RF switch located on a network device. + * @poll: poll the rfkill block state(s) -- only assign this method + * when you need polling. When called, simply call one of the + * rfkill_set{,_hw,_sw}_state family of functions. If the hw + * is getting unblocked you need to take into account the return + * value of those functions to make sure the software block is + * properly used. + * @query: query the rfkill block state(s) and call exactly one of the + * rfkill_set{,_hw,_sw}_state family of functions. Assign this + * method if input events can cause hardware state changes to make + * the rfkill core query your driver before setting a requested + * block. + * @set_block: turn the transmitter on (blocked == false) or off + * (blocked == true) -- ignore and return 0 when hard blocked. + * This callback must be assigned. */ -struct rfkill { - const char *name; - enum rfkill_type type; - - bool user_claim_unsupported; - bool user_claim; - - /* the mutex serializes callbacks and also protects - * the state */ - struct mutex mutex; - enum rfkill_state state; - void *data; - int (*toggle_radio)(void *data, enum rfkill_state state); - int (*get_state)(void *data, enum rfkill_state *state); - -#ifdef CONFIG_RFKILL_LEDS - struct led_trigger led_trigger; -#endif - - struct device dev; - struct list_head node; - enum rfkill_state state_for_resume; +struct rfkill_ops { + void (*poll)(struct rfkill *rfkill, void *data); + void (*query)(struct rfkill *rfkill, void *data); + int (*set_block)(void *data, bool blocked); }; -#define to_rfkill(d) container_of(d, struct rfkill, dev) -struct rfkill * __must_check rfkill_allocate(struct device *parent, - enum rfkill_type type); -void rfkill_free(struct rfkill *rfkill); +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) +/** + * rfkill_alloc - allocate rfkill structure + * @name: name of the struct -- the string is not copied internally + * @parent: device that has rf switch on it + * @type: type of the switch (RFKILL_TYPE_*) + * @ops: rfkill methods + * @ops_data: data passed to each method + * + * This function should be called by the transmitter driver to allocate an + * rfkill structure. Returns %NULL on failure. + */ +struct rfkill * __must_check rfkill_alloc(const char *name, + struct device *parent, + const enum rfkill_type type, + const struct rfkill_ops *ops, + void *ops_data); + +/** + * rfkill_register - Register a rfkill structure. + * @rfkill: rfkill structure to be registered + * + * This function should be called by the transmitter driver to register + * the rfkill structure. Before calling this function the driver needs + * to be ready to service method calls from rfkill. + * + * If the software blocked state is not set before registration, + * set_block will be called to initialize it to a default value. + * + * If the hardware blocked state is not set before registration, + * it is assumed to be unblocked. + */ int __must_check rfkill_register(struct rfkill *rfkill); + +/** + * rfkill_pause_polling(struct rfkill *rfkill) + * + * Pause polling -- say transmitter is off for other reasons. + * NOTE: not necessary for suspend/resume -- in that case the + * core stops polling anyway + */ +void rfkill_pause_polling(struct rfkill *rfkill); + +/** + * rfkill_resume_polling(struct rfkill *rfkill) + * + * Pause polling -- say transmitter is off for other reasons. + * NOTE: not necessary for suspend/resume -- in that case the + * core stops polling anyway + */ +void rfkill_resume_polling(struct rfkill *rfkill); + + +/** + * rfkill_unregister - Unregister a rfkill structure. + * @rfkill: rfkill structure to be unregistered + * + * This function should be called by the network driver during device + * teardown to destroy rfkill structure. Until it returns, the driver + * needs to be able to service method calls. + */ void rfkill_unregister(struct rfkill *rfkill); -int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state); -int rfkill_set_default(enum rfkill_type type, enum rfkill_state state); - /** - * rfkill_state_complement - return complementar state - * @state: state to return the complement of + * rfkill_destroy - free rfkill structure + * @rfkill: rfkill structure to be destroyed * - * Returns RFKILL_STATE_SOFT_BLOCKED if @state is RFKILL_STATE_UNBLOCKED, - * returns RFKILL_STATE_UNBLOCKED otherwise. + * Destroys the rfkill structure. */ -static inline enum rfkill_state rfkill_state_complement(enum rfkill_state state) -{ - return (state == RFKILL_STATE_UNBLOCKED) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; -} +void rfkill_destroy(struct rfkill *rfkill); /** - * rfkill_get_led_name - Get the LED trigger name for the button's LED. - * This function might return a NULL pointer if registering of the - * LED trigger failed. - * Use this as "default_trigger" for the LED. + * rfkill_set_hw_state - Set the internal rfkill hardware block state + * @rfkill: pointer to the rfkill class to modify. + * @state: the current hardware block state to set + * + * rfkill drivers that get events when the hard-blocked state changes + * use this function to notify the rfkill core (and through that also + * userspace) of the current state. They should also use this after + * resume if the state could have changed. + * + * You need not (but may) call this function if poll_state is assigned. + * + * This function can be called in any context, even from within rfkill + * callbacks. + * + * The function returns the combined block state (true if transmitter + * should be blocked) so that drivers need not keep track of the soft + * block state -- which they might not be able to. */ -static inline char *rfkill_get_led_name(struct rfkill *rfkill) +bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); + +/** + * rfkill_set_sw_state - Set the internal rfkill software block state + * @rfkill: pointer to the rfkill class to modify. + * @state: the current software block state to set + * + * rfkill drivers that get events when the soft-blocked state changes + * (yes, some platforms directly act on input but allow changing again) + * use this function to notify the rfkill core (and through that also + * userspace) of the current state. It is not necessary to notify on + * resume; since hibernation can always change the soft-blocked state, + * the rfkill core will unconditionally restore the previous state. + * + * This function can be called in any context, even from within rfkill + * callbacks. + * + * The function returns the combined block state (true if transmitter + * should be blocked). + */ +bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); + +/** + * rfkill_set_states - Set the internal rfkill block states + * @rfkill: pointer to the rfkill class to modify. + * @sw: the current software block state to set + * @hw: the current hardware block state to set + * + * This function can be called in any context, even from within rfkill + * callbacks. + */ +void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw); + +/** + * rfkill_blocked - query rfkill block + * + * @rfkill: rfkill struct to query + */ +bool rfkill_blocked(struct rfkill *rfkill); +#else /* !RFKILL */ +static inline struct rfkill * __must_check +rfkill_alloc(const char *name, + struct device *parent, + const enum rfkill_type type, + const struct rfkill_ops *ops, + void *ops_data) { -#ifdef CONFIG_RFKILL_LEDS - return (char *)(rfkill->led_trigger.name); -#else - return NULL; -#endif + return ERR_PTR(-ENODEV); } +static inline int __must_check rfkill_register(struct rfkill *rfkill) +{ + if (rfkill == ERR_PTR(-ENODEV)) + return 0; + return -EINVAL; +} + +static inline void rfkill_pause_polling(struct rfkill *rfkill) +{ +} + +static inline void rfkill_resume_polling(struct rfkill *rfkill) +{ +} + +static inline void rfkill_unregister(struct rfkill *rfkill) +{ +} + +static inline void rfkill_destroy(struct rfkill *rfkill) +{ +} + +static inline bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked) +{ + return blocked; +} + +static inline bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) +{ + return blocked; +} + +static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) +{ +} + +static inline bool rfkill_blocked(struct rfkill *rfkill) +{ + return false; +} +#endif /* RFKILL || RFKILL_MODULE */ + + +#ifdef CONFIG_RFKILL_LEDS +/** + * rfkill_get_led_trigger_name - Get the LED trigger name for the button's LED. + * This function might return a NULL pointer if registering of the + * LED trigger failed. Use this as "default_trigger" for the LED. + */ +const char *rfkill_get_led_trigger_name(struct rfkill *rfkill); + +/** + * rfkill_set_led_trigger_name -- set the LED trigger name + * @rfkill: rfkill struct + * @name: LED trigger name + * + * This function sets the LED trigger name of the radio LED + * trigger that rfkill creates. It is optional, but if called + * must be called before rfkill_register() to be effective. + */ +void rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name); +#else +static inline const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) +{ + return NULL; +} + +static inline void +rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name) +{ +} +#endif + +#endif /* __KERNEL__ */ + #endif /* RFKILL_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 4896fdfec913..fea9d188dbff 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2212,6 +2212,12 @@ static inline int test_tsk_need_resched(struct task_struct *tsk) return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED)); } +static inline int restart_syscall(void) +{ + set_tsk_thread_flag(current, TIF_SIGPENDING); + return -ERESTARTNOINTR; +} + static inline int signal_pending(struct task_struct *p) { return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING)); diff --git a/include/linux/sctp.h b/include/linux/sctp.h index c2731bfe04d8..b464b9d3d242 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -487,17 +487,17 @@ typedef enum { * * Value Cause Code * --------- ---------------- - * 0x0100 Request to Delete Last Remaining IP Address. - * 0x0101 Operation Refused Due to Resource Shortage. - * 0x0102 Request to Delete Source IP Address. - * 0x0103 Association Aborted due to illegal ASCONF-ACK - * 0x0104 Request refused - no authorization. + * 0x00A0 Request to Delete Last Remaining IP Address. + * 0x00A1 Operation Refused Due to Resource Shortage. + * 0x00A2 Request to Delete Source IP Address. + * 0x00A3 Association Aborted due to illegal ASCONF-ACK + * 0x00A4 Request refused - no authorization. */ - SCTP_ERROR_DEL_LAST_IP = cpu_to_be16(0x0100), - SCTP_ERROR_RSRC_LOW = cpu_to_be16(0x0101), - SCTP_ERROR_DEL_SRC_IP = cpu_to_be16(0x0102), - SCTP_ERROR_ASCONF_ACK = cpu_to_be16(0x0103), - SCTP_ERROR_REQ_REFUSED = cpu_to_be16(0x0104), + SCTP_ERROR_DEL_LAST_IP = cpu_to_be16(0x00A0), + SCTP_ERROR_RSRC_LOW = cpu_to_be16(0x00A1), + SCTP_ERROR_DEL_SRC_IP = cpu_to_be16(0x00A2), + SCTP_ERROR_ASCONF_ACK = cpu_to_be16(0x00A3), + SCTP_ERROR_REQ_REFUSED = cpu_to_be16(0x00A4), /* AUTH Section 4. New Error Cause * diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 5fd389162f01..fa51293f2708 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -189,20 +189,23 @@ struct skb_shared_info { atomic_t dataref; unsigned short nr_frags; unsigned short gso_size; +#ifdef CONFIG_HAS_DMA + dma_addr_t dma_head; +#endif /* Warning: this field is not always filled in (UFO)! */ unsigned short gso_segs; unsigned short gso_type; __be32 ip6_frag_id; union skb_shared_tx tx_flags; -#ifdef CONFIG_HAS_DMA - unsigned int num_dma_maps; -#endif struct sk_buff *frag_list; struct skb_shared_hwtstamps hwtstamps; skb_frag_t frags[MAX_SKB_FRAGS]; #ifdef CONFIG_HAS_DMA - dma_addr_t dma_maps[MAX_SKB_FRAGS + 1]; + dma_addr_t dma_maps[MAX_SKB_FRAGS]; #endif + /* Intermediate layers must ensure that destructor_arg + * remains valid until skb destructor */ + void * destructor_arg; }; /* We divide dataref into two halves. The higher 16 bits hold references @@ -301,9 +304,6 @@ typedef unsigned char *sk_buff_data_t; * @tc_verd: traffic control verdict * @ndisc_nodetype: router type (from link layer) * @do_not_encrypt: set to prevent encryption of this frame - * @requeue: set to indicate that the wireless core should attempt - * a software retry on this frame if we failed to - * receive an ACK for it * @dma_cookie: a cookie to one of several possible DMA operations * done by skb DMA functions * @secmark: security marking @@ -319,10 +319,7 @@ struct sk_buff { ktime_t tstamp; struct net_device *dev; - union { - struct dst_entry *dst; - struct rtable *rtable; - }; + unsigned long _skb_dst; #ifdef CONFIG_XFRM struct sec_path *sp; #endif @@ -380,7 +377,6 @@ struct sk_buff { #endif #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) __u8 do_not_encrypt:1; - __u8 requeue:1; #endif /* 0/13/14 bit hole */ @@ -423,6 +419,21 @@ extern void skb_dma_unmap(struct device *dev, struct sk_buff *skb, enum dma_data_direction dir); #endif +static inline struct dst_entry *skb_dst(const struct sk_buff *skb) +{ + return (struct dst_entry *)skb->_skb_dst; +} + +static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst) +{ + skb->_skb_dst = (unsigned long)dst; +} + +static inline struct rtable *skb_rtable(const struct sk_buff *skb) +{ + return (struct rtable *)skb_dst(skb); +} + extern void kfree_skb(struct sk_buff *skb); extern void consume_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb); @@ -1062,7 +1073,7 @@ extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, int size); #define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags) -#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_shinfo(skb)->frag_list) +#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frags(skb)) #define SKB_LINEAR_ASSERT(skb) BUG_ON(skb_is_nonlinear(skb)) #ifdef NET_SKBUFF_DATA_USES_OFFSET @@ -1701,6 +1712,25 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) skb = skb->prev) +static inline bool skb_has_frags(const struct sk_buff *skb) +{ + return skb_shinfo(skb)->frag_list != NULL; +} + +static inline void skb_frag_list_init(struct sk_buff *skb) +{ + skb_shinfo(skb)->frag_list = NULL; +} + +static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag) +{ + frag->next = skb_shinfo(skb)->frag_list; + skb_shinfo(skb)->frag_list = frag; +} + +#define skb_walk_frags(skb, iter) \ + for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next) + extern struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, int *peeked, int *err); extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, @@ -1715,8 +1745,14 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, struct iovec *iov); extern int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, - struct iovec *from, + const struct iovec *from, + int from_offset, int len); +extern int skb_copy_datagram_const_iovec(const struct sk_buff *from, + int offset, + const struct iovec *to, + int to_offset, + int size); extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index b32725075d71..5241e4fb4eca 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -47,4 +47,14 @@ struct smsc911x_platform_config { #define SMSC911X_FORCE_EXTERNAL_PHY (BIT(3)) #define SMSC911X_SAVE_MAC_ADDRESS (BIT(4)) +/* + * SMSC911X_SWAP_FIFO: + * Enables software byte swap for fifo data. Should only be used as a + * "last resort" in the case of big endian mode on boards with incorrectly + * routed data bus to older devices such as LAN9118. Newer devices such as + * LAN9221 can handle this in hardware, there are registers to control + * this swapping but the driver doesn't currently use them. + */ +#define SMSC911X_SWAP_FIFO (BIT(5)) + #endif /* __LINUX_SMSC911X_H__ */ diff --git a/include/linux/snmp.h b/include/linux/snmp.h index aee3f1e1d1ce..0f953fe40413 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -18,7 +18,7 @@ enum { IPSTATS_MIB_NUM = 0, - IPSTATS_MIB_INRECEIVES, /* InReceives */ + IPSTATS_MIB_INPKTS, /* InReceives */ IPSTATS_MIB_INHDRERRORS, /* InHdrErrors */ IPSTATS_MIB_INTOOBIGERRORS, /* InTooBigErrors */ IPSTATS_MIB_INNOROUTES, /* InNoRoutes */ @@ -28,7 +28,7 @@ enum IPSTATS_MIB_INDISCARDS, /* InDiscards */ IPSTATS_MIB_INDELIVERS, /* InDelivers */ IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */ - IPSTATS_MIB_OUTREQUESTS, /* OutRequests */ + IPSTATS_MIB_OUTPKTS, /* OutRequests */ IPSTATS_MIB_OUTDISCARDS, /* OutDiscards */ IPSTATS_MIB_OUTNOROUTES, /* OutNoRoutes */ IPSTATS_MIB_REASMTIMEOUT, /* ReasmTimeout */ @@ -42,6 +42,12 @@ enum IPSTATS_MIB_OUTMCASTPKTS, /* OutMcastPkts */ IPSTATS_MIB_INBCASTPKTS, /* InBcastPkts */ IPSTATS_MIB_OUTBCASTPKTS, /* OutBcastPkts */ + IPSTATS_MIB_INOCTETS, /* InOctets */ + IPSTATS_MIB_OUTOCTETS, /* OutOctets */ + IPSTATS_MIB_INMCASTOCTETS, /* InMcastOctets */ + IPSTATS_MIB_OUTMCASTOCTETS, /* OutMcastOctets */ + IPSTATS_MIB_INBCASTOCTETS, /* InBcastOctets */ + IPSTATS_MIB_OUTBCASTOCTETS, /* OutBcastOctets */ __IPSTATS_MIB_MAX }; diff --git a/include/linux/socket.h b/include/linux/socket.h index 421afb4d29b0..3b461dffe244 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -194,7 +194,8 @@ struct ucred { #define AF_RXRPC 33 /* RxRPC sockets */ #define AF_ISDN 34 /* mISDN sockets */ #define AF_PHONET 35 /* Phonet sockets */ -#define AF_MAX 36 /* For now.. */ +#define AF_IEEE802154 36 /* IEEE802154 sockets */ +#define AF_MAX 37 /* For now.. */ /* Protocol families, same as address families. */ #define PF_UNSPEC AF_UNSPEC @@ -233,6 +234,7 @@ struct ucred { #define PF_RXRPC AF_RXRPC #define PF_ISDN AF_ISDN #define PF_PHONET AF_PHONET +#define PF_IEEE802154 AF_IEEE802154 #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ @@ -303,14 +305,15 @@ struct ucred { #define SOL_BLUETOOTH 274 #define SOL_PNPIPE 275 #define SOL_RDS 276 +#define SOL_IUCV 277 /* IPX options */ #define IPX_TYPE 1 #ifdef __KERNEL__ extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); -extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, - int offset, int len); +extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len); extern int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, @@ -318,6 +321,8 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata, extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode); extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); +extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, + int offset, int len); extern int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, int __user *ulen); extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr); extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h index 79506f5f9e67..1b5d5384fcd3 100644 --- a/include/linux/spi/libertas_spi.h +++ b/include/linux/spi/libertas_spi.h @@ -22,9 +22,6 @@ struct libertas_spi_platform_data { * speed, you may want to use 0 here. */ u16 use_dummy_writes; - /* GPIO number to use as chip select */ - u16 gpio_cs; - /* Board specific setup/teardown */ int (*setup)(struct spi_device *spi); int (*teardown)(struct spi_device *spi); diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h new file mode 100644 index 000000000000..11430cab2aad --- /dev/null +++ b/include/linux/spi/wl12xx.h @@ -0,0 +1,31 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * 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 _LINUX_SPI_WL12XX_H +#define _LINUX_SPI_WL12XX_H + +struct wl12xx_platform_data { + void (*set_power)(bool enable); +}; + +#endif diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 9d5078bd23a3..8afac76cd748 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -377,7 +377,7 @@ struct tcp_sock { unsigned int keepalive_time; /* time before keep alive takes place */ unsigned int keepalive_intvl; /* time interval between keep alive probes */ - unsigned long last_synq_overflow; + int linger2; /* Receiver side RTT estimation */ struct { @@ -406,8 +406,6 @@ struct tcp_sock { /* TCP MD5 Signagure Option information */ struct tcp_md5sig_info *md5sig_info; #endif - - int linger2; }; static inline struct tcp_sock *tcp_sk(const struct sock *sk) diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 36fabb95c7d3..5d44059f6d63 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -183,6 +183,7 @@ extern void usbnet_tx_timeout (struct net_device *net); extern int usbnet_change_mtu (struct net_device *net, int new_mtu); extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *); +extern int usbnet_get_ethernet_addr(struct usbnet *, int); 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 *); diff --git a/include/linux/wimax.h b/include/linux/wimax.h index c89de7f4e5b9..4fdcc5635518 100644 --- a/include/linux/wimax.h +++ b/include/linux/wimax.h @@ -59,7 +59,7 @@ enum { * M - Major: change if removing or modifying an existing call. * m - minor: change when adding a new call */ - WIMAX_GNL_VERSION = 00, + WIMAX_GNL_VERSION = 01, /* Generic NetLink attributes */ WIMAX_GNL_ATTR_INVALID = 0x00, WIMAX_GNL_ATTR_MAX = 10, @@ -78,6 +78,7 @@ enum { WIMAX_GNL_OP_RFKILL, /* Run wimax_rfkill() */ WIMAX_GNL_OP_RESET, /* Run wimax_rfkill() */ WIMAX_GNL_RE_STATE_CHANGE, /* Report: status change */ + WIMAX_GNL_OP_STATE_GET, /* Request for current state */ }; @@ -113,6 +114,10 @@ enum { WIMAX_GNL_RESET_IFIDX = 1, }; +/* Atributes for wimax_state_get() */ +enum { + WIMAX_GNL_STGET_IFIDX = 1, +}; /* * Attributes for the Report State Change diff --git a/include/linux/wimax/i2400m.h b/include/linux/wimax/i2400m.h index d5148a7889a6..433693ef2bb0 100644 --- a/include/linux/wimax/i2400m.h +++ b/include/linux/wimax/i2400m.h @@ -266,7 +266,7 @@ enum i2400m_ro_type { /* Misc constants */ enum { - I2400M_PL_PAD = 16, /* Payload data size alignment */ + I2400M_PL_ALIGN = 16, /* Payload data size alignment */ I2400M_PL_SIZE_MAX = 0x3EFF, I2400M_MAX_PLS_IN_MSG = 60, /* protocol barkers: sync sequences; for notifications they diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 3ad5390a4dd5..968166a45f86 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -81,12 +81,6 @@ enum { BT_CLOSED }; -/* Endianness conversions */ -#define htobs(a) __cpu_to_le16(a) -#define htobl(a) __cpu_to_le32(a) -#define btohs(a) __le16_to_cpu(a) -#define btohl(a) __le32_to_cpu(a) - /* BD Address */ typedef struct { __u8 b[6]; @@ -171,15 +165,6 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long l return skb; } -static inline int skb_frags_no(struct sk_buff *skb) -{ - register struct sk_buff *frag = skb_shinfo(skb)->frag_list; - register int n = 1; - - for (; frag; frag=frag->next, n++); - return n; -} - int bt_err(__u16 code); extern int hci_sock_init(void); diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 73aead222b32..c4ca4228b083 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -137,6 +137,8 @@ struct hci_dev { struct device *parent; struct device dev; + struct rfkill *rfkill; + struct module *owner; int (*open)(struct hci_dev *hdev); diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f566aa1f0a4c..e919fca1072a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -26,8 +26,13 @@ #define __L2CAP_H /* L2CAP defaults */ -#define L2CAP_DEFAULT_MTU 672 -#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF +#define L2CAP_DEFAULT_MTU 672 +#define L2CAP_DEFAULT_FLUSH_TO 0xffff +#define L2CAP_DEFAULT_RX_WINDOW 1 +#define L2CAP_DEFAULT_MAX_RECEIVE 1 +#define L2CAP_DEFAULT_RETRANS_TO 300 /* 300 milliseconds */ +#define L2CAP_DEFAULT_MONITOR_TO 1000 /* 1 second */ +#define L2CAP_DEFAULT_MAX_RX_APDU 0xfff7 #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ #define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ @@ -64,17 +69,29 @@ struct l2cap_conninfo { #define L2CAP_LM_SECURE 0x0020 /* L2CAP command codes */ -#define L2CAP_COMMAND_REJ 0x01 -#define L2CAP_CONN_REQ 0x02 -#define L2CAP_CONN_RSP 0x03 -#define L2CAP_CONF_REQ 0x04 -#define L2CAP_CONF_RSP 0x05 -#define L2CAP_DISCONN_REQ 0x06 -#define L2CAP_DISCONN_RSP 0x07 -#define L2CAP_ECHO_REQ 0x08 -#define L2CAP_ECHO_RSP 0x09 -#define L2CAP_INFO_REQ 0x0a -#define L2CAP_INFO_RSP 0x0b +#define L2CAP_COMMAND_REJ 0x01 +#define L2CAP_CONN_REQ 0x02 +#define L2CAP_CONN_RSP 0x03 +#define L2CAP_CONF_REQ 0x04 +#define L2CAP_CONF_RSP 0x05 +#define L2CAP_DISCONN_REQ 0x06 +#define L2CAP_DISCONN_RSP 0x07 +#define L2CAP_ECHO_REQ 0x08 +#define L2CAP_ECHO_RSP 0x09 +#define L2CAP_INFO_REQ 0x0a +#define L2CAP_INFO_RSP 0x0b + +/* L2CAP feature mask */ +#define L2CAP_FEAT_FLOWCTL 0x00000001 +#define L2CAP_FEAT_RETRANS 0x00000002 +#define L2CAP_FEAT_ERTM 0x00000008 +#define L2CAP_FEAT_STREAMING 0x00000010 +#define L2CAP_FEAT_FCS 0x00000020 +#define L2CAP_FEAT_FIXED_CHAN 0x00000080 + +/* L2CAP checksum option */ +#define L2CAP_FCS_NONE 0x00 +#define L2CAP_FCS_CRC16 0x01 /* L2CAP structures */ struct l2cap_hdr { @@ -106,17 +123,23 @@ struct l2cap_conn_rsp { __le16 status; } __attribute__ ((packed)); +/* channel indentifier */ +#define L2CAP_CID_SIGNALING 0x0001 +#define L2CAP_CID_CONN_LESS 0x0002 +#define L2CAP_CID_DYN_START 0x0040 +#define L2CAP_CID_DYN_END 0xffff + /* connect result */ -#define L2CAP_CR_SUCCESS 0x0000 -#define L2CAP_CR_PEND 0x0001 -#define L2CAP_CR_BAD_PSM 0x0002 -#define L2CAP_CR_SEC_BLOCK 0x0003 -#define L2CAP_CR_NO_MEM 0x0004 +#define L2CAP_CR_SUCCESS 0x0000 +#define L2CAP_CR_PEND 0x0001 +#define L2CAP_CR_BAD_PSM 0x0002 +#define L2CAP_CR_SEC_BLOCK 0x0003 +#define L2CAP_CR_NO_MEM 0x0004 /* connect status */ -#define L2CAP_CS_NO_INFO 0x0000 -#define L2CAP_CS_AUTHEN_PEND 0x0001 -#define L2CAP_CS_AUTHOR_PEND 0x0002 +#define L2CAP_CS_NO_INFO 0x0000 +#define L2CAP_CS_AUTHEN_PEND 0x0001 +#define L2CAP_CS_AUTHOR_PEND 0x0002 struct l2cap_conf_req { __le16 dcid; @@ -143,10 +166,14 @@ struct l2cap_conf_opt { } __attribute__ ((packed)); #define L2CAP_CONF_OPT_SIZE 2 +#define L2CAP_CONF_HINT 0x80 +#define L2CAP_CONF_MASK 0x7f + #define L2CAP_CONF_MTU 0x01 #define L2CAP_CONF_FLUSH_TO 0x02 #define L2CAP_CONF_QOS 0x03 #define L2CAP_CONF_RFC 0x04 +#define L2CAP_CONF_FCS 0x05 #define L2CAP_CONF_MAX_SIZE 22 @@ -162,6 +189,8 @@ struct l2cap_conf_rfc { #define L2CAP_MODE_BASIC 0x00 #define L2CAP_MODE_RETRANS 0x01 #define L2CAP_MODE_FLOWCTL 0x02 +#define L2CAP_MODE_ERTM 0x03 +#define L2CAP_MODE_STREAM 0x04 struct l2cap_disconn_req { __le16 dcid; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5389afdc1297..1a21895b732b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1,21 +1,207 @@ #ifndef __NET_CFG80211_H #define __NET_CFG80211_H +/* + * 802.11 device and configuration interface + * + * Copyright 2006-2009 Johannes Berg + * + * 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 +#include +#include #include #include #include #include #include -#include -#include -#include +#include + /* remove once we remove the wext stuff */ #include +#include + /* - * 802.11 configuration in-kernel interface + * wireless hardware capability structures + */ + +/** + * enum ieee80211_band - supported frequency bands * - * Copyright 2006, 2007 Johannes Berg + * The bands are assigned this way because the supported + * bitrates differ in these bands. + * + * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band + * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) + */ +enum ieee80211_band { + IEEE80211_BAND_2GHZ, + IEEE80211_BAND_5GHZ, + + /* keep last */ + IEEE80211_NUM_BANDS +}; + +/** + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted + * on this channel. + * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel + * is not permitted. + */ +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, + IEEE80211_CHAN_NO_IBSS = 1<<2, + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, +}; + +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) + +/** + * struct ieee80211_channel - channel definition + * + * This structure describes a single channel for use + * 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 + * code to support devices with additional restrictions + * @band: band this channel belongs to. + * @max_antenna_gain: maximum antenna gain in dBi + * @max_power: maximum transmission power (in dBm) + * @beacon_found: helper to regulatory code to indicate when a beacon + * has been found on this channel. Use regulatory_hint_found_beacon() + * to enable this, this is is useful only on 5 GHz band. + * @orig_mag: internal use + * @orig_mpwr: internal use + */ +struct ieee80211_channel { + enum ieee80211_band band; + u16 center_freq; + u8 max_bandwidth; + u16 hw_value; + u32 flags; + int max_antenna_gain; + int max_power; + bool beacon_found; + u32 orig_flags; + int orig_mag, orig_mpwr; +}; + +/** + * enum ieee80211_rate_flags - rate flags + * + * Hardware/specification flags for rates. These are structured + * in a way that allows using the same bitrate structure for + * different bands/PHY modes. + * + * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short + * preamble on this bitrate; only relevant in 2.4GHz band and + * with CCK rates. + * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate + * when used with 802.11a (on the 5 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate + * when used with 802.11b (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate + * when used with 802.11g (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. + */ +enum ieee80211_rate_flags { + IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, + IEEE80211_RATE_MANDATORY_A = 1<<1, + IEEE80211_RATE_MANDATORY_B = 1<<2, + IEEE80211_RATE_MANDATORY_G = 1<<3, + IEEE80211_RATE_ERP_G = 1<<4, +}; + +/** + * struct ieee80211_rate - bitrate definition + * + * This structure describes a bitrate that an 802.11 PHY can + * operate with. The two values @hw_value and @hw_value_short + * are only for driver use when pointers to this structure are + * passed around. + * + * @flags: rate-specific flags + * @bitrate: bitrate in units of 100 Kbps + * @hw_value: driver/hardware value for this rate + * @hw_value_short: driver/hardware value for this rate when + * short preamble is used + */ +struct ieee80211_rate { + u32 flags; + u16 bitrate; + u16 hw_value, hw_value_short; +}; + +/** + * struct ieee80211_sta_ht_cap - STA's HT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11n HT capabilities for an STA. + * + * @ht_supported: is HT supported by the STA + * @cap: HT capabilities map as described in 802.11n spec + * @ampdu_factor: Maximum A-MPDU length factor + * @ampdu_density: Minimum A-MPDU spacing + * @mcs: Supported MCS rates + */ +struct ieee80211_sta_ht_cap { + u16 cap; /* use IEEE80211_HT_CAP_ */ + bool ht_supported; + u8 ampdu_factor; + u8 ampdu_density; + struct ieee80211_mcs_info mcs; +}; + +/** + * struct ieee80211_supported_band - frequency band definition + * + * This structure describes a frequency band a wiphy + * is able to operate in. + * + * @channels: Array of channels the hardware can operate in + * in this band. + * @band: the band this structure represents + * @n_channels: Number of channels in @channels + * @bitrates: Array of bitrates the hardware can operate with + * in this band. Must be sorted to give a valid "supported + * rates" IE, i.e. CCK rates first, then OFDM. + * @n_bitrates: Number of bitrates in @bitrates + */ +struct ieee80211_supported_band { + struct ieee80211_channel *channels; + struct ieee80211_rate *bitrates; + enum ieee80211_band band; + int n_channels; + int n_bitrates; + struct ieee80211_sta_ht_cap ht_cap; +}; + +/* + * Wireless hardware/device configuration structures and methods */ /** @@ -28,44 +214,7 @@ struct vif_params { int mesh_id_len; }; -/* Radiotap header iteration - * implemented in net/wireless/radiotap.c - * docs in Documentation/networking/radiotap-headers.txt - */ /** - * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args - * @rtheader: pointer to the radiotap header we are walking through - * @max_length: length of radiotap header in cpu byte ordering - * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg - * @this_arg: pointer to current radiotap arg - * @arg_index: internal next argument index - * @arg: internal next argument pointer - * @next_bitmap: internal pointer to next present u32 - * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present - */ - -struct ieee80211_radiotap_iterator { - struct ieee80211_radiotap_header *rtheader; - int max_length; - int this_arg_index; - u8 *this_arg; - - int arg_index; - u8 *arg; - __le32 *next_bitmap; - u32 bitmap_shifter; -}; - -extern int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length); - -extern int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator); - - - /** * struct key_params - key information * * Information about a key @@ -105,27 +254,6 @@ struct beacon_parameters { int head_len, tail_len; }; -/** - * enum station_flags - station flags - * - * Station capability flags. Note that these must be the bits - * according to the nl80211 flags. - * - * @STATION_FLAG_CHANGED: station flags were changed - * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X) - * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames - * with short preambles - * @STATION_FLAG_WME: station is WME/QoS capable - * @STATION_FLAG_MFP: station uses management frame protection - */ -enum station_flags { - STATION_FLAG_CHANGED = 1<<0, - STATION_FLAG_AUTHORIZED = 1<retry_short has changed + * WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed + * WIPHY_PARAM_FRAG_THRESHOLD: wiphy->frag_threshold has changed + * WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed + */ +enum wiphy_params_flags { + WIPHY_PARAM_RETRY_SHORT = 1 << 0, + WIPHY_PARAM_RETRY_LONG = 1 << 1, + WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2, + WIPHY_PARAM_RTS_THRESHOLD = 1 << 3, +}; + +/** + * enum tx_power_setting - TX power adjustment + * + * @TX_POWER_AUTOMATIC: the dbm parameter is ignored + * @TX_POWER_LIMITED: limit TX power by the dbm parameter + * @TX_POWER_FIXED: fix TX power to the dbm parameter + */ +enum tx_power_setting { + TX_POWER_AUTOMATIC, + TX_POWER_LIMITED, + TX_POWER_FIXED, +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -688,10 +794,11 @@ struct cfg80211_disassoc_request { * @get_key: get information about the key with the given parameters. * @mac_addr will be %NULL when requesting information for a group * key. All pointers given to the @callback function need not be valid - * after it returns. + * after it returns. This function should return an error if it is + * not possible to retrieve the key, -ENOENT if it doesn't exist. * * @del_key: remove a key given the @mac_addr (%NULL for a group key) - * and @key_index + * and @key_index, return -ENOENT if the key doesn't exist. * * @set_default_key: set the default key on an interface * @@ -733,6 +840,23 @@ struct cfg80211_disassoc_request { * @assoc: Request to (re)associate with the specified peer * @deauth: Request to deauthenticate from the specified peer * @disassoc: Request to disassociate from the specified peer + * + * @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. + * @leave_ibss: Leave the IBSS. + * + * @set_wiphy_params: Notify that wiphy parameters have changed; + * @changed bitfield (see &enum wiphy_params_flags) describes which values + * have changed. The actual parameter values are available in + * struct wiphy. If returning an error, no value should be changed. + * + * @set_tx_power: set the transmit power according to the parameters + * @get_tx_power: store the current TX power into the dbm variable; + * return 0 if successful + * + * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting + * functions to adjust rfkill hw state */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy); @@ -747,13 +871,13 @@ struct cfg80211_ops { struct vif_params *params); int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, u8 *mac_addr, + u8 key_index, const u8 *mac_addr, struct key_params *params); int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, u8 *mac_addr, void *cookie, + u8 key_index, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*)); int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, u8 *mac_addr); + u8 key_index, const u8 *mac_addr); int (*set_default_key)(struct wiphy *wiphy, struct net_device *netdev, u8 key_index); @@ -818,9 +942,473 @@ struct cfg80211_ops { struct cfg80211_deauth_request *req); int (*disassoc)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); + + int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params); + int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); + + int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); + + int (*set_tx_power)(struct wiphy *wiphy, + enum tx_power_setting type, int dbm); + int (*get_tx_power)(struct wiphy *wiphy, int *dbm); + + void (*rfkill_poll)(struct wiphy *wiphy); }; -/* temporary wext handlers */ +/* + * wireless hardware and networking interfaces structures + * and registration/helper functions + */ + +/** + * struct wiphy - wireless hardware description + * @idx: the wiphy index assigned to this item + * @class_dev: the class device representing /sys/class/ieee80211/ + * @custom_regulatory: tells us the driver for this device + * has its own custom regulatory domain and cannot identify the + * ISO / IEC 3166 alpha2 it belongs to. When this is enabled + * we will disregard the first regulatory hint (when the + * initiator is %REGDOM_SET_BY_CORE). + * @strict_regulatory: tells us the driver for this device will ignore + * regulatory domain settings until it gets its own regulatory domain + * via its regulatory_hint(). After its gets its own regulatory domain + * it will only allow further regulatory domain settings to further + * enhance compliance. For example if channel 13 and 14 are disabled + * by this regulatory domain no user regulatory domain can enable these + * channels at a later time. This can be used for devices which do not + * have calibration information gauranteed for frequencies or settings + * outside of its regulatory domain. + * @reg_notifier: the driver's regulatory notification callback + * @regd: the driver's regulatory domain, if one was requested via + * the regulatory_hint() API. This can be used by the driver + * on the reg_notifier() if it chooses to ignore future + * regulatory domain changes caused by other drivers. + * @signal_type: signal type reported in &struct cfg80211_bss. + * @cipher_suites: supported cipher suites + * @n_cipher_suites: number of supported cipher suites + * @retry_short: Retry limit for short frames (dot11ShortRetryLimit) + * @retry_long: Retry limit for long frames (dot11LongRetryLimit) + * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold); + * -1 = fragmentation disabled, only odd values >= 256 used + * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled + */ +struct wiphy { + /* assign these fields before you register the wiphy */ + + /* permanent MAC address */ + u8 perm_addr[ETH_ALEN]; + + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ + u16 interface_modes; + + bool custom_regulatory; + bool strict_regulatory; + + enum cfg80211_signal_type signal_type; + + int bss_priv_size; + u8 max_scan_ssids; + u16 max_scan_ie_len; + + int n_cipher_suites; + const u32 *cipher_suites; + + u8 retry_short; + u8 retry_long; + u32 frag_threshold; + u32 rts_threshold; + + /* If multiple wiphys are registered and you're handed e.g. + * a regular netdev with assigned ieee80211_ptr, you won't + * know whether it points to a wiphy your driver has registered + * or not. Assign this to something global to your driver to + * help determine whether you own this wiphy or not. */ + const void *privid; + + struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; + + /* Lets us get back the wiphy on the callback */ + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request); + + /* fields below are read-only, assigned by cfg80211 */ + + const struct ieee80211_regdomain *regd; + + /* the item in /sys/class/ieee80211/ points to this, + * you need use set_wiphy_dev() (see below) */ + struct device dev; + + /* dir in debugfs: ieee80211/ */ + struct dentry *debugfsdir; + + char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); +}; + +/** + * wiphy_priv - return priv from wiphy + * + * @wiphy: the wiphy whose priv pointer to return + */ +static inline void *wiphy_priv(struct wiphy *wiphy) +{ + BUG_ON(!wiphy); + return &wiphy->priv; +} + +/** + * set_wiphy_dev - set device pointer for wiphy + * + * @wiphy: The wiphy whose device to bind + * @dev: The device to parent it to + */ +static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev) +{ + wiphy->dev.parent = dev; +} + +/** + * wiphy_dev - get wiphy dev pointer + * + * @wiphy: The wiphy whose device struct to look up + */ +static inline struct device *wiphy_dev(struct wiphy *wiphy) +{ + return wiphy->dev.parent; +} + +/** + * wiphy_name - get wiphy name + * + * @wiphy: The wiphy whose name to return + */ +static inline const char *wiphy_name(struct wiphy *wiphy) +{ + return dev_name(&wiphy->dev); +} + +/** + * wiphy_new - create a new wiphy for use with cfg80211 + * + * @ops: The configuration operations for this device + * @sizeof_priv: The size of the private area to allocate + * + * Create a new wiphy and associate the given operations with it. + * @sizeof_priv bytes are allocated for private use. + * + * The returned pointer must be assigned to each netdev's + * ieee80211_ptr for proper operation. + */ +struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv); + +/** + * wiphy_register - register a wiphy with cfg80211 + * + * @wiphy: The wiphy to register. + * + * Returns a non-negative wiphy index or a negative error code. + */ +extern int wiphy_register(struct wiphy *wiphy); + +/** + * wiphy_unregister - deregister a wiphy from cfg80211 + * + * @wiphy: The wiphy to unregister. + * + * After this call, no more requests can be made with this priv + * pointer, but the call may sleep to wait for an outstanding + * request that is being handled. + */ +extern void wiphy_unregister(struct wiphy *wiphy); + +/** + * wiphy_free - free wiphy + * + * @wiphy: The wiphy to free + */ +extern void wiphy_free(struct wiphy *wiphy); + +/** + * struct wireless_dev - wireless per-netdev state + * + * This structure must be allocated by the driver/stack + * that uses the ieee80211_ptr field in struct net_device + * (this is intentional so it can be allocated along with + * the netdev.) + * + * @wiphy: pointer to hardware description + * @iftype: interface type + * @list: (private) Used to collect the interfaces + * @netdev: (private) Used to reference back to the netdev + * @current_bss: (private) Used by the internal configuration code + * @bssid: (private) Used by the internal configuration code + * @ssid: (private) Used by the internal configuration code + * @ssid_len: (private) Used by the internal configuration code + * @wext: (private) Used by the internal wireless extensions compat code + * @wext_bssid: (private) Used by the internal wireless extensions compat code + */ +struct wireless_dev { + struct wiphy *wiphy; + enum nl80211_iftype iftype; + + /* private to the generic wireless code */ + 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]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + +#ifdef CONFIG_WIRELESS_EXT + /* wext data */ + struct { + struct cfg80211_ibss_params ibss; + u8 bssid[ETH_ALEN]; + s8 default_key, default_mgmt_key; + } wext; +#endif +}; + +/** + * wdev_priv - return wiphy priv from wireless_dev + * + * @wdev: The wireless device whose wiphy's priv pointer to return + */ +static inline void *wdev_priv(struct wireless_dev *wdev) +{ + BUG_ON(!wdev); + return wiphy_priv(wdev->wiphy); +} + +/* + * Utility functions + */ + +/** + * ieee80211_channel_to_frequency - convert channel number to frequency + */ +extern int ieee80211_channel_to_frequency(int chan); + +/** + * ieee80211_frequency_to_channel - convert frequency to channel number + */ +extern int ieee80211_frequency_to_channel(int freq); + +/* + * Name indirection necessary because the ieee80211 code also has + * a function named "ieee80211_get_channel", so if you include + * cfg80211's header file you get cfg80211's version, if you try + * to include both header files you'll (rightfully!) get a symbol + * clash. + */ +extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, + int freq); +/** + * ieee80211_get_channel - get channel struct from wiphy for specified frequency + */ +static inline struct ieee80211_channel * +ieee80211_get_channel(struct wiphy *wiphy, int freq) +{ + return __ieee80211_get_channel(wiphy, freq); +} + +/** + * ieee80211_get_response_rate - get basic rate for a given rate + * + * @sband: the band to look for rates in + * @basic_rates: bitmap of basic rates + * @bitrate: the bitrate for which to find the basic rate + * + * This function returns the basic rate corresponding to a given + * bitrate, that is the next lower bitrate contained in the basic + * rate map, which is, for this function, given as a bitmap of + * indices of rates in the band's bitrate table. + */ +struct ieee80211_rate * +ieee80211_get_response_rate(struct ieee80211_supported_band *sband, + u32 basic_rates, int bitrate); + +/* + * Radiotap parsing functions -- for controlled injection support + * + * Implemented in net/wireless/radiotap.c + * Documentation in Documentation/networking/radiotap-headers.txt + */ + +/** + * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args + * @rtheader: pointer to the radiotap header we are walking through + * @max_length: length of radiotap header in cpu byte ordering + * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg + * @this_arg: pointer to current radiotap arg + * @arg_index: internal next argument index + * @arg: internal next argument pointer + * @next_bitmap: internal pointer to next present u32 + * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + */ + +struct ieee80211_radiotap_iterator { + struct ieee80211_radiotap_header *rtheader; + int max_length; + int this_arg_index; + u8 *this_arg; + + int arg_index; + u8 *arg; + __le32 *next_bitmap; + u32 bitmap_shifter; +}; + +extern int ieee80211_radiotap_iterator_init( + struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, + int max_length); + +extern int ieee80211_radiotap_iterator_next( + struct ieee80211_radiotap_iterator *iterator); + +extern const unsigned char rfc1042_header[6]; +extern const unsigned char bridge_tunnel_header[6]; + +/** + * ieee80211_get_hdrlen_from_skb - get header length from data + * + * Given an skb with a raw 802.11 header at the data pointer this function + * returns the 802.11 header length in bytes (not including encryption + * headers). If the data in the sk_buff is too short to contain a valid 802.11 + * header the function returns 0. + * + * @skb: the frame + */ +unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); + +/** + * ieee80211_hdrlen - get header length in bytes from frame control + * @fc: frame control field in little-endian format + */ +unsigned int ieee80211_hdrlen(__le16 fc); + +/** + * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 + * @skb: the 802.11 data frame + * @addr: the device MAC address + * @iftype: the virtual interface type + */ +int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, + enum nl80211_iftype iftype); + +/** + * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11 + * @skb: the 802.3 frame + * @addr: the device MAC address + * @iftype: the virtual interface type + * @bssid: the network bssid (used only for iftype STATION and ADHOC) + * @qos: build 802.11 QoS data frame + */ +int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, + enum nl80211_iftype iftype, u8 *bssid, bool qos); + +/** + * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame + * @skb: the data frame + */ +unsigned int cfg80211_classify8021d(struct sk_buff *skb); + +/* + * Regulatory helper functions for wiphys + */ + +/** + * regulatory_hint - driver hint to the wireless core a regulatory domain + * @wiphy: the wireless device giving the hint (used only for reporting + * conflicts) + * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain + * should be in. If @rd is set this should be NULL. Note that if you + * set this to NULL you should still set rd->alpha2 to some accepted + * alpha2. + * + * Wireless drivers can use this function to hint to the wireless core + * what it believes should be the current regulatory domain by + * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory + * domain should be in or by providing a completely build regulatory domain. + * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried + * for a regulatory domain structure for the respective country. + * + * The wiphy must have been registered to cfg80211 prior to this call. + * For cfg80211 drivers this means you must first use wiphy_register(), + * for mac80211 drivers you must first use ieee80211_register_hw(). + * + * Drivers should check the return value, its possible you can get + * an -ENOMEM. + */ +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 + * + * Drivers can sometimes have custom regulatory domains which do not apply + * to a specific country. Drivers can use this to apply such custom regulatory + * domains. This routine must be called prior to wiphy registration. The + * custom regulatory domain will be trusted completely and as such previous + * default channel settings will be disregarded. If no rule is found for a + * channel on the regulatory domain the channel will be disabled. + */ +extern void wiphy_apply_custom_regulatory( + struct wiphy *wiphy, + const struct ieee80211_regdomain *regd); + +/** + * freq_reg_info - get regulatory information for the given frequency + * @wiphy: the wiphy for which we want to process this rule for + * @center_freq: Frequency in KHz for which we want regulatory information for + * @desired_bw_khz: the desired max bandwidth you want to use per + * channel. Note that this is still 20 MHz if you want to use HT40 + * as HT40 makes use of two channels for its 40 MHz width bandwidth. + * If set to 0 we'll assume you want the standard 20 MHz. + * @reg_rule: the regulatory rule which we have for this frequency + * + * Use this function to get the regulatory rule for a specific frequency on + * a given wireless device. If the device has a specific regulatory domain + * it wants to follow we respect that unless a country IE has been received + * and processed already. + * + * Returns 0 if it was able to find a valid regulatory rule which does + * apply to the given center_freq otherwise it returns non-zero. It will + * also return -ERANGE if we determine the given center_freq does not even have + * a regulatory rule for a frequency range in the center_freq's band. See + * freq_in_rule_band() for our current definition of a band -- this is purely + * subjective and right now its 802.11 specific. + */ +extern int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, + const struct ieee80211_reg_rule **reg_rule); + +/* + * Temporary wext handlers & helper functions + * + * In the future cfg80211 will simply assign the entire wext handler + * structure to netdevs it manages, but we're not there yet. + */ int cfg80211_wext_giwname(struct net_device *dev, struct iw_request_info *info, char *name, char *extra); @@ -834,9 +1422,72 @@ int cfg80211_wext_siwscan(struct net_device *dev, int cfg80211_wext_giwscan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); +int cfg80211_wext_siwmlme(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra); 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); + +struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, + struct iw_freq *freq); + +int cfg80211_wext_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra); +int cfg80211_wext_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra); +int cfg80211_wext_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra); +int cfg80211_wext_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra); +int cfg80211_wext_siwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra); +int cfg80211_wext_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra); +int cfg80211_wext_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *extra); +int cfg80211_wext_siwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *keybuf); +int cfg80211_wext_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *keybuf); +int cfg80211_wext_siwtxpower(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *keybuf); +int cfg80211_wext_giwtxpower(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *keybuf); + +/* + * callbacks for asynchronous cfg80211 methods, notification + * functions and BSS handling helpers + */ /** * cfg80211_scan_done - notify that scan finished @@ -864,6 +1515,14 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, struct ieee80211_mgmt *mgmt, size_t len, s32 signal, gfp_t gfp); +struct cfg80211_bss* +cfg80211_inform_bss(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *bssid, + u64 timestamp, u16 capability, u16 beacon_interval, + const u8 *ie, size_t ielen, + s32 signal, gfp_t gfp); + struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, struct ieee80211_channel *channel, const u8 *bssid, @@ -883,6 +1542,7 @@ struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, const u8 *meshid, size_t meshidlen, const u8 *meshcfg); void cfg80211_put_bss(struct cfg80211_bss *bss); + /** * cfg80211_unlink_bss - unlink BSS from internal data structures * @wiphy: the wiphy @@ -902,10 +1562,19 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); * @len: length of the frame data * * This function is called whenever an authentication has been processed in - * station mode. + * 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. */ 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 + */ +void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); + /** * cfg80211_send_rx_assoc - notification of processed association * @dev: network device @@ -913,33 +1582,42 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); * @len: length of the frame data * * This function is called whenever a (re)association response has been - * processed in station mode. + * 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. */ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len); /** - * cfg80211_send_rx_deauth - notification of processed deauthentication + * 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 + */ +void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); + +/** + * cfg80211_send_deauth - notification of processed deauthentication * @dev: network device * @buf: deauthentication frame (header + body) * @len: length of the frame data * * This function is called whenever deauthentication has been processed in - * station mode. + * station mode. This includes both received deauthentication frames and + * locally generated ones. */ -void cfg80211_send_rx_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); /** - * cfg80211_send_rx_disassoc - notification of processed disassociation + * cfg80211_send_disassoc - notification of processed disassociation * @dev: network device * @buf: disassociation response frame (header + body) * @len: length of the frame data * * This function is called whenever disassociation has been processed in - * station mode. + * station mode. This includes both received disassociation frames and locally + * generated ones. */ -void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, - size_t len); +void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len); /** * cfg80211_hold_bss - exclude bss from expiration @@ -958,4 +1636,55 @@ void cfg80211_hold_bss(struct cfg80211_bss *bss); */ void cfg80211_unhold_bss(struct cfg80211_bss *bss); +/** + * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP) + * @dev: network device + * @addr: The source MAC address of the frame + * @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) + * + * This function is called whenever the local MAC detects a MIC failure in a + * received frame. This matches with MLME-MICHAELMICFAILURE.indication() + * primitive. + */ +void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, + enum nl80211_key_type key_type, int key_id, + const u8 *tsc); + +/** + * cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS + * + * @dev: network device + * @bssid: the BSSID of the IBSS joined + * @gfp: allocation flags + * + * This function notifies cfg80211 that the device joined an IBSS or + * switched to a different BSSID. Before this function can be called, + * either a beacon has to have been received from the IBSS, or one of + * the cfg80211_inform_bss{,_frame} functions must have been called + * with the locally generated beacon -- this guarantees that there is + * always a scan result for this IBSS. cfg80211 will handle the rest. + */ +void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); + +/** + * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state + * @wiphy: the wiphy + * @blocked: block status + */ +void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked); + +/** + * wiphy_rfkill_start_polling - start polling rfkill + * @wiphy: the wiphy + */ +void wiphy_rfkill_start_polling(struct wiphy *wiphy); + +/** + * wiphy_rfkill_stop_polling - stop polling rfkill + * @wiphy: the wiphy + */ +void wiphy_rfkill_stop_polling(struct wiphy *wiphy); + #endif /* __NET_CFG80211_H */ diff --git a/include/net/dst.h b/include/net/dst.h index 6be3b082a070..7fc409c19b37 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -195,6 +195,12 @@ struct dst_entry * dst_clone(struct dst_entry * dst) } extern void dst_release(struct dst_entry *dst); +static inline void skb_dst_drop(struct sk_buff *skb) +{ + if (skb->_skb_dst) + dst_release(skb_dst(skb)); + skb->_skb_dst = 0UL; +} /* Children define the path of the packet through the * Linux networking. Thus, destinations are stackable. @@ -246,7 +252,7 @@ static inline void dst_negative_advice(struct dst_entry **dst_p) static inline void dst_link_failure(struct sk_buff *skb) { - struct dst_entry * dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); if (dst && dst->ops && dst->ops->link_failure) dst->ops->link_failure(skb); } @@ -265,13 +271,13 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout) /* Output packet to network from transport. */ static inline int dst_output(struct sk_buff *skb) { - return skb->dst->output(skb); + return skb_dst(skb)->output(skb); } /* Input packet from network to transport. */ static inline int dst_input(struct sk_buff *skb) { - return skb->dst->input(skb); + return skb_dst(skb)->input(skb); } static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index c2bb5cae6515..ca4b2e840078 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -48,14 +48,12 @@ struct fib_rules_ops struct flowi *, int); int (*configure)(struct fib_rule *, struct sk_buff *, - struct nlmsghdr *, struct fib_rule_hdr *, struct nlattr **); int (*compare)(struct fib_rule *, struct fib_rule_hdr *, struct nlattr **); int (*fill)(struct fib_rule *, struct sk_buff *, - struct nlmsghdr *, struct fib_rule_hdr *); u32 (*default_pref)(struct fib_rules_ops *ops); size_t (*nlmsg_payload)(struct fib_rule *); diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 747c255d1df0..1b0e3ee4ddd8 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -88,6 +88,8 @@ struct genl_ops }; extern int genl_register_family(struct genl_family *family); +extern int genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops); extern int genl_unregister_family(struct genl_family *family); extern int genl_register_ops(struct genl_family *, struct genl_ops *ops); extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops); diff --git a/include/net/ieee802154/af_ieee802154.h b/include/net/ieee802154/af_ieee802154.h new file mode 100644 index 000000000000..0d78605fb1a6 --- /dev/null +++ b/include/net/ieee802154/af_ieee802154.h @@ -0,0 +1,60 @@ +/* + * IEEE 802.15.4 inteface for userspace + * + * Copyright 2007, 2008 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. + * + * Written by: + * Sergey Lapin + * Dmitry Eremin-Solenikov + */ + +#ifndef _AF_IEEE802154_H +#define _AF_IEEE802154_H + +#include /* for sa_family_t */ + +enum { + IEEE802154_ADDR_NONE = 0x0, + /* RESERVED = 0x01, */ + IEEE802154_ADDR_SHORT = 0x2, /* 16-bit address + PANid */ + IEEE802154_ADDR_LONG = 0x3, /* 64-bit address + PANid */ +}; + +/* address length, octets */ +#define IEEE802154_ADDR_LEN 8 + +struct ieee802154_addr { + int addr_type; + u16 pan_id; + union { + u8 hwaddr[IEEE802154_ADDR_LEN]; + u16 short_addr; + }; +}; + +#define IEEE802154_PANID_BROADCAST 0xffff +#define IEEE802154_ADDR_BROADCAST 0xffff +#define IEEE802154_ADDR_UNDEF 0xfffe + +struct sockaddr_ieee802154 { + sa_family_t family; /* AF_IEEE802154 */ + struct ieee802154_addr addr; +}; + +/* master device */ +#define IEEE802154_SIOC_ADD_SLAVE (SIOCDEVPRIVATE + 0) + +#endif diff --git a/include/net/ieee802154/mac_def.h b/include/net/ieee802154/mac_def.h new file mode 100644 index 000000000000..8cb684635650 --- /dev/null +++ b/include/net/ieee802154/mac_def.h @@ -0,0 +1,160 @@ +/* + * IEEE802.15.4-2003 specification + * + * Copyright (C) 2007, 2008 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. + * + * Written by: + * Pavel Smolenskiy + * Maxim Gorbachyov + * Maxim Osipov + * Dmitry Eremin-Solenikov + */ + +#ifndef IEEE802154_MAC_DEF_H +#define IEEE802154_MAC_DEF_H + +#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */ +#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */ +#define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */ +#define IEEE802154_FC_TYPE_MAC_CMD 0x3 /* Frame is MAC command */ + +#define IEEE802154_FC_TYPE_SHIFT 0 +#define IEEE802154_FC_TYPE_MASK ((1 << 3) - 1) +#define IEEE802154_FC_TYPE(x) ((x & IEEE802154_FC_TYPE_MASK) >> IEEE802154_FC_TYPE_SHIFT) +#define IEEE802154_FC_SET_TYPE(v, x) do { \ + v = (((v) & ~IEEE802154_FC_TYPE_MASK) | \ + (((x) << IEEE802154_FC_TYPE_SHIFT) & IEEE802154_FC_TYPE_MASK)); \ + } while (0) + +#define IEEE802154_FC_SECEN (1 << 3) +#define IEEE802154_FC_FRPEND (1 << 4) +#define IEEE802154_FC_ACK_REQ (1 << 5) +#define IEEE802154_FC_INTRA_PAN (1 << 6) + +#define IEEE802154_FC_SAMODE_SHIFT 14 +#define IEEE802154_FC_SAMODE_MASK (3 << IEEE802154_FC_SAMODE_SHIFT) +#define IEEE802154_FC_DAMODE_SHIFT 10 +#define IEEE802154_FC_DAMODE_MASK (3 << IEEE802154_FC_DAMODE_SHIFT) + +#define IEEE802154_FC_SAMODE(x) \ + (((x) & IEEE802154_FC_SAMODE_MASK) >> IEEE802154_FC_SAMODE_SHIFT) + +#define IEEE802154_FC_DAMODE(x) \ + (((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT) + + +/* MAC's Command Frames Identifiers */ +#define IEEE802154_CMD_ASSOCIATION_REQ 0x01 +#define IEEE802154_CMD_ASSOCIATION_RESP 0x02 +#define IEEE802154_CMD_DISASSOCIATION_NOTIFY 0x03 +#define IEEE802154_CMD_DATA_REQ 0x04 +#define IEEE802154_CMD_PANID_CONFLICT_NOTIFY 0x05 +#define IEEE802154_CMD_ORPHAN_NOTIFY 0x06 +#define IEEE802154_CMD_BEACON_REQ 0x07 +#define IEEE802154_CMD_COORD_REALIGN_NOTIFY 0x08 +#define IEEE802154_CMD_GTS_REQ 0x09 + +/* + * The return values of MAC operations + */ +enum { + /* + * The requested operation was completed successfully. + * For a transmission request, this value indicates + * a successful transmission. + */ + IEEE802154_SUCCESS = 0x0, + + /* The beacon was lost following a synchronization request. */ + IEEE802154_BEACON_LOSS = 0xe0, + /* + * A transmission could not take place due to activity on the + * channel, i.e., the CSMA-CA mechanism has failed. + */ + IEEE802154_CHNL_ACCESS_FAIL = 0xe1, + /* The GTS request has been denied by the PAN coordinator. */ + IEEE802154_DENINED = 0xe2, + /* The attempt to disable the transceiver has failed. */ + IEEE802154_DISABLE_TRX_FAIL = 0xe3, + /* + * The received frame induces a failed security check according to + * the security suite. + */ + IEEE802154_FAILED_SECURITY_CHECK = 0xe4, + /* + * The frame resulting from secure processing has a length that is + * greater than aMACMaxFrameSize. + */ + IEEE802154_FRAME_TOO_LONG = 0xe5, + /* + * The requested GTS transmission failed because the specified GTS + * either did not have a transmit GTS direction or was not defined. + */ + IEEE802154_INVALID_GTS = 0xe6, + /* + * A request to purge an MSDU from the transaction queue was made using + * an MSDU handle that was not found in the transaction table. + */ + IEEE802154_INVALID_HANDLE = 0xe7, + /* A parameter in the primitive is out of the valid range.*/ + IEEE802154_INVALID_PARAMETER = 0xe8, + /* No acknowledgment was received after aMaxFrameRetries. */ + IEEE802154_NO_ACK = 0xe9, + /* A scan operation failed to find any network beacons.*/ + IEEE802154_NO_BEACON = 0xea, + /* No response data were available following a request. */ + IEEE802154_NO_DATA = 0xeb, + /* The operation failed because a short address was not allocated. */ + IEEE802154_NO_SHORT_ADDRESS = 0xec, + /* + * A receiver enable request was unsuccessful because it could not be + * completed within the CAP. + */ + IEEE802154_OUT_OF_CAP = 0xed, + /* + * A PAN identifier conflict has been detected and communicated to the + * PAN coordinator. + */ + IEEE802154_PANID_CONFLICT = 0xee, + /* A coordinator realignment command has been received. */ + IEEE802154_REALIGMENT = 0xef, + /* The transaction has expired and its information discarded. */ + IEEE802154_TRANSACTION_EXPIRED = 0xf0, + /* There is no capacity to store the transaction. */ + IEEE802154_TRANSACTION_OVERFLOW = 0xf1, + /* + * The transceiver was in the transmitter enabled state when the + * receiver was requested to be enabled. + */ + IEEE802154_TX_ACTIVE = 0xf2, + /* The appropriate key is not available in the ACL. */ + IEEE802154_UNAVAILABLE_KEY = 0xf3, + /* + * A SET/GET request was issued with the identifier of a PIB attribute + * that is not supported. + */ + IEEE802154_UNSUPPORTED_ATTR = 0xf4, + /* + * A request to perform a scan operation failed because the MLME was + * in the process of performing a previously initiated scan operation. + */ + IEEE802154_SCAN_IN_PROGRESS = 0xfc, +}; + + +#endif + + diff --git a/include/net/ieee802154/netdevice.h b/include/net/ieee802154/netdevice.h new file mode 100644 index 000000000000..e2506af3e7c8 --- /dev/null +++ b/include/net/ieee802154/netdevice.h @@ -0,0 +1,115 @@ +/* + * An interface between IEEE802.15.4 device and rest of the kernel. + * + * 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. + * + * Written by: + * Pavel Smolenskiy + * Maxim Gorbachyov + * Maxim Osipov + * Dmitry Eremin-Solenikov + */ + +#ifndef IEEE802154_NETDEVICE_H +#define IEEE802154_NETDEVICE_H + +/* + * A control block of skb passed between the ARPHRD_IEEE802154 device + * and other stack parts. + */ +struct ieee802154_mac_cb { + u8 lqi; + struct ieee802154_addr sa; + struct ieee802154_addr da; + u8 flags; + u8 seq; +}; + +static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb) +{ + return (struct ieee802154_mac_cb *)skb->cb; +} + +#define MAC_CB_FLAG_TYPEMASK ((1 << 3) - 1) + +#define MAC_CB_FLAG_ACKREQ (1 << 3) +#define MAC_CB_FLAG_SECEN (1 << 4) +#define MAC_CB_FLAG_INTRAPAN (1 << 5) + +static inline int mac_cb_is_ackreq(struct sk_buff *skb) +{ + return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ; +} + +static inline int mac_cb_is_secen(struct sk_buff *skb) +{ + return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN; +} + +static inline int mac_cb_is_intrapan(struct sk_buff *skb) +{ + return mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN; +} + +static inline int mac_cb_type(struct sk_buff *skb) +{ + return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK; +} + +#define IEEE802154_MAC_SCAN_ED 0 +#define IEEE802154_MAC_SCAN_ACTIVE 1 +#define IEEE802154_MAC_SCAN_PASSIVE 2 +#define IEEE802154_MAC_SCAN_ORPHAN 3 + +/* + * This should be located at net_device->ml_priv + */ +struct ieee802154_mlme_ops { + int (*assoc_req)(struct net_device *dev, + struct ieee802154_addr *addr, + u8 channel, u8 cap); + int (*assoc_resp)(struct net_device *dev, + struct ieee802154_addr *addr, + u16 short_addr, u8 status); + int (*disassoc_req)(struct net_device *dev, + struct ieee802154_addr *addr, + u8 reason); + int (*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); + int (*scan_req)(struct net_device *dev, + u8 type, u32 channels, u8 duration); + + /* + * FIXME: these should become the part of PIB/MIB interface. + * However we still don't have IB interface of any kind + */ + u16 (*get_pan_id)(struct net_device *dev); + u16 (*get_short_addr)(struct net_device *dev); + u8 (*get_dsn)(struct net_device *dev); + u8 (*get_bsn)(struct net_device *dev); +}; + +static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops( + struct net_device *dev) +{ + return dev->ml_priv; +} + +#endif + + diff --git a/include/net/ieee802154/nl802154.h b/include/net/ieee802154/nl802154.h new file mode 100644 index 000000000000..78efcdf52b59 --- /dev/null +++ b/include/net/ieee802154/nl802154.h @@ -0,0 +1,41 @@ +/* + * 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/inet6_hashtables.h b/include/net/inet6_hashtables.h index f74665d7bea8..22c73a77cd99 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -100,7 +100,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, if (unlikely(sk = skb_steal_sock(skb))) return sk; - else return __inet6_lookup(dev_net(skb->dst->dev), hashinfo, + else return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, &ipv6_hdr(skb)->saddr, sport, &ipv6_hdr(skb)->daddr, ntohs(dport), inet6_iif(skb)); diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index a44e2248b2ef..d522dcf3031a 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -385,7 +385,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, if (unlikely(sk = skb_steal_sock(skb))) return sk; else - return __inet_lookup(dev_net(skb->dst->dev), hashinfo, + return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, iph->saddr, sport, iph->daddr, dport, inet_iif(skb)); } diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index de0ecc71cf03..20a6957af870 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -130,7 +130,8 @@ struct inet_sock { freebind:1, hdrincl:1, mc_loop:1, - transparent:1; + transparent:1, + mc_all:1; int mc_index; __be32 mc_addr; struct ip_mc_socklist *mc_list; diff --git a/include/net/ip.h b/include/net/ip.h index 4ac7577f98d0..72c36926c26d 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -168,7 +168,10 @@ struct ipv4_config extern struct ipv4_config ipv4_config; #define IP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.ip_statistics, field) #define IP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.ip_statistics, field) +#define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.ip_statistics, field, val) #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val) +#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS((net)->mib.ip_statistics, field, val) +#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS_BH((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) #define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) #define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 5f53db7e4e57..0e1b8aebaff8 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -142,7 +142,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, static inline int ipv6_unicast_destination(struct sk_buff *skb) { - struct rt6_info *rt = (struct rt6_info *) skb->dst; + struct rt6_info *rt = (struct rt6_info *) skb_dst(skb); return rt->rt6i_flags & RTF_LOCAL; } diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 8b12667f7a2b..ef91fe924ba4 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -124,14 +124,12 @@ struct fib_result_nl { #ifdef CONFIG_IP_ROUTE_MULTIPATH #define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel]) -#define FIB_RES_RESET(res) ((res).nh_sel = 0) #define FIB_TABLE_HASHSZ 2 #else /* CONFIG_IP_ROUTE_MULTIPATH */ #define FIB_RES_NH(res) ((res).fi->fib_nh[0]) -#define FIB_RES_RESET(res) #define FIB_TABLE_HASHSZ 256 @@ -145,7 +143,6 @@ struct fib_result_nl { struct fib_table { struct hlist_node tb_hlist; u32 tb_id; - unsigned tb_stamp; int tb_default; int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res); int (*tb_insert)(struct fib_table *, struct fib_config *); diff --git a/include/net/ipip.h b/include/net/ipip.h index fdf9bd743705..5d3036fa1511 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -28,11 +28,18 @@ struct ip_tunnel unsigned int prl_count; /* # of entries in PRL */ }; +/* ISATAP: default interval between RS in secondy */ +#define IPTUNNEL_RS_DEFAULT_DELAY (900) + struct ip_tunnel_prl_entry { struct ip_tunnel_prl_entry *next; __be32 addr; u16 flags; + unsigned long rs_delay; + struct timer_list rs_timer; + struct ip_tunnel *tunnel; + spinlock_t lock; }; #define IPTUNNEL_XMIT() do { \ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index c1f16fc49ade..f27fd83d67d8 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -126,15 +126,28 @@ extern struct ctl_path net_ipv6_ctl_path[]; SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\ }) +#define _DEVUPD(net, statname, modifier, idev, field, val) \ +({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \ + SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\ +}) + /* MIBs */ #define IP6_INC_STATS(net, idev,field) \ _DEVINC(net, ipv6, , idev, field) #define IP6_INC_STATS_BH(net, idev,field) \ _DEVINC(net, ipv6, _BH, idev, field) +#define IP6_ADD_STATS(net, idev,field,val) \ + _DEVADD(net, ipv6, , idev, field, val) #define IP6_ADD_STATS_BH(net, idev,field,val) \ _DEVADD(net, ipv6, _BH, idev, field, val) - +#define IP6_UPD_PO_STATS(net, idev,field,val) \ + _DEVUPD(net, ipv6, , idev, field, val) +#define IP6_UPD_PO_STATS_BH(net, idev,field,val) \ + _DEVUPD(net, ipv6, _BH, idev, field, val) #define ICMP6_INC_STATS(net, idev, field) \ _DEVINC(net, icmpv6, , idev, field) #define ICMP6_INC_STATS_BH(net, idev, field) \ diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index 85f80eadfa35..21ee49ffcbaf 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -73,8 +73,17 @@ struct iucv_sock { struct sk_buff_head backlog_skb_q; struct sock_msg_q message_q; unsigned int send_tag; + u8 flags; + u16 msglimit; }; +/* iucv socket options (SOL_IUCV) */ +#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */ +#define SO_MSGLIMIT 0x1000 /* get/set IUCV MSGLIMIT */ + +/* iucv related control messages (scm) */ +#define SCM_IUCV_TRGCLS 0x0001 /* target class control message */ + struct iucv_sock_list { struct hlist_head head; rwlock_t lock; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3b83a80e3fe0..c06104476973 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -19,7 +19,6 @@ #include #include #include -#include #include /** @@ -73,22 +72,6 @@ * not do so then mac80211 may add this under certain circumstances. */ -/** - * struct ieee80211_ht_bss_info - describing BSS's HT characteristics - * - * This structure describes most essential parameters needed - * to describe 802.11n HT characteristics in a BSS. - * - * @primary_channel: channel number of primery channel - * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) - * @bss_op_mode: 802.11n's BSS operation modes (e.g. HT protection) - */ -struct ieee80211_ht_bss_info { - u8 primary_channel; - u8 bss_cap; /* use IEEE80211_HT_IE_CHA_ */ - u8 bss_op_mode; /* use IEEE80211_HT_IE_ */ -}; - /** * enum ieee80211_max_queues - maximum number of queues * @@ -150,6 +133,13 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_ERP_SLOT: slot timing changed * @BSS_CHANGED_HT: 802.11n parameters changed * @BSS_CHANGED_BASIC_RATES: Basic rateset changed + * @BSS_CHANGED_BEACON_INT: Beacon interval changed + * @BSS_CHANGED_BSSID: BSSID changed, for whatever + * reason (IBSS and managed mode) + * @BSS_CHANGED_BEACON: Beacon data changed, retrieve + * new beacon (beaconing modes) + * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be + * enabled/disabled (beaconing modes) */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -158,14 +148,10 @@ enum ieee80211_bss_change { BSS_CHANGED_ERP_SLOT = 1<<3, BSS_CHANGED_HT = 1<<4, BSS_CHANGED_BASIC_RATES = 1<<5, -}; - -/** - * struct ieee80211_bss_ht_conf - BSS's changing HT configuration - * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) - */ -struct ieee80211_bss_ht_conf { - u16 operation_mode; + BSS_CHANGED_BEACON_INT = 1<<6, + BSS_CHANGED_BSSID = 1<<7, + BSS_CHANGED_BEACON = 1<<8, + BSS_CHANGED_BEACON_ENABLED = 1<<9, }; /** @@ -187,12 +173,16 @@ struct ieee80211_bss_ht_conf { * @timestamp: beacon timestamp * @beacon_int: beacon interval * @assoc_capability: capabilities taken from assoc resp - * @ht: BSS's HT configuration * @basic_rates: bitmap of basic rates, each bit stands for an * index into the rate table configured by the driver in * the current band. + * @bssid: The BSSID for this BSS + * @enable_beacon: whether beaconing should be enabled or not + * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). + * This field is only valid when the channel type is one of the HT types. */ struct ieee80211_bss_conf { + const u8 *bssid; /* association related data */ bool assoc; u16 aid; @@ -200,12 +190,13 @@ struct ieee80211_bss_conf { bool use_cts_prot; bool use_short_preamble; bool use_short_slot; + bool enable_beacon; u8 dtim_period; u16 beacon_int; u16 assoc_capability; u64 timestamp; u32 basic_rates; - struct ieee80211_bss_ht_conf ht; + u16 ht_operation_mode; }; /** @@ -248,6 +239,8 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, * used to indicate that a pending frame requires TX processing before * 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 */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -265,6 +258,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), IEEE80211_TX_INTFL_RCALGO = BIT(13), IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), + IEEE80211_TX_INTFL_RETRIED = BIT(15), }; /** @@ -518,52 +512,76 @@ struct ieee80211_rx_status { * Flags to define PHY configuration options * * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) - * @IEEE80211_CONF_PS: Enable 802.11 power save mode + * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only) + * @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set + * the driver should be prepared to handle configuration requests but + * may turn the device off as much as possible. Typically, this flag will + * be set when an interface is set UP but not associated or scanning, but + * it can also be unset in that case when monitor interfaces are active. */ enum ieee80211_conf_flags { IEEE80211_CONF_RADIOTAP = (1<<0), IEEE80211_CONF_PS = (1<<1), + IEEE80211_CONF_IDLE = (1<<2), }; /** * enum ieee80211_conf_changed - denotes which configuration changed * - * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed - * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed + * @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed - * @IEEE80211_CONF_CHANGE_PS: the PS flag changed - * @IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT: the dynamic PS timeout changed + * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed * @IEEE80211_CONF_CHANGE_POWER: the TX power changed * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed + * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed */ enum ieee80211_conf_changed { - IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), - IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), + _IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), IEEE80211_CONF_CHANGE_PS = BIT(4), - IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT = BIT(5), - IEEE80211_CONF_CHANGE_POWER = BIT(6), - IEEE80211_CONF_CHANGE_CHANNEL = BIT(7), - IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(8), + IEEE80211_CONF_CHANGE_POWER = BIT(5), + IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), + IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), + IEEE80211_CONF_CHANGE_IDLE = BIT(8), }; +static inline __deprecated enum ieee80211_conf_changed +__IEEE80211_CONF_CHANGE_RADIO_ENABLED(void) +{ + return _IEEE80211_CONF_CHANGE_RADIO_ENABLED; +} +#define IEEE80211_CONF_CHANGE_RADIO_ENABLED \ + __IEEE80211_CONF_CHANGE_RADIO_ENABLED() + /** * struct ieee80211_conf - configuration of the device * * This struct indicates how the driver shall configure the hardware. * - * @radio_enabled: when zero, driver is required to switch off the radio. - * @beacon_int: beacon interval (TODO make interface config) - * @listen_interval: listen interval in units of beacon interval * @flags: configuration flags defined above + * + * @radio_enabled: when zero, driver is required to switch off the radio. + * @beacon_int: DEPRECATED, DO NOT USE + * + * @listen_interval: listen interval in units of beacon interval + * @max_sleep_period: the maximum number of beacon intervals to sleep for + * before checking the beacon for a TIM bit (managed mode only); this + * value will be only achievable between DTIM frames, the hardware + * needs to check for the multicast traffic bit in DTIM beacons. + * This variable is valid only when the CONF_PS flag is set. + * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the + * powersave documentation below. This variable is valid only when + * the CONF_PS flag is set. + * * @power_level: requested transmit power (in dBm) - * @dynamic_ps_timeout: dynamic powersave timeout (in ms) + * * @channel: the channel to tune to * @channel_type: the channel (HT) type + * * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, * but actually means the number of transmissions not the number of retries @@ -572,12 +590,13 @@ enum ieee80211_conf_changed { * number of transmissions not the number of retries */ struct ieee80211_conf { - int beacon_int; + int __deprecated beacon_int; u32 flags; int power_level, dynamic_ps_timeout; + int max_sleep_period; u16 listen_interval; - bool radio_enabled; + bool __deprecated radio_enabled; u8 long_frame_max_tx_count, short_frame_max_tx_count; @@ -639,37 +658,6 @@ struct ieee80211_if_init_conf { void *mac_addr; }; -/** - * enum ieee80211_if_conf_change - interface config change flags - * - * @IEEE80211_IFCC_BSSID: The BSSID changed. - * @IEEE80211_IFCC_BEACON: The beacon for this interface changed - * (currently AP and MESH only), use ieee80211_beacon_get(). - * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed. - */ -enum ieee80211_if_conf_change { - IEEE80211_IFCC_BSSID = BIT(0), - IEEE80211_IFCC_BEACON = BIT(1), - IEEE80211_IFCC_BEACON_ENABLED = BIT(2), -}; - -/** - * struct ieee80211_if_conf - configuration of an interface - * - * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. - * @bssid: BSSID of the network we are associated to/creating. - * @enable_beacon: Indicates whether beacons can be sent. - * This is valid only for AP/IBSS/MESH modes. - * - * This structure is passed to the config_interface() callback of - * &struct ieee80211_hw. - */ -struct ieee80211_if_conf { - u32 changed; - const u8 *bssid; - bool enable_beacon; -}; - /** * enum ieee80211_key_alg - key algorithm * @ALG_WEP: WEP40 or WEP104 @@ -684,16 +672,6 @@ enum ieee80211_key_alg { ALG_AES_CMAC, }; -/** - * enum ieee80211_key_len - key length - * @LEN_WEP40: WEP 5-byte long key - * @LEN_WEP104: WEP 13-byte long key - */ -enum ieee80211_key_len { - LEN_WEP40 = 5, - LEN_WEP104 = 13, -}; - /** * enum ieee80211_key_flags - key flags * @@ -1109,11 +1087,9 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * need software support for parsing the TIM bitmap. This is also supported * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still - * required to pass up beacons. Additionally, in this case, mac80211 will - * wake up the hardware when multicast traffic is announced in the beacon. - * - * FIXME: I don't think we can be fast enough in software when we want to - * receive multicast traffic? + * required to pass up beacons. The hardware is still required to handle + * waking up for multicast traffic; if it cannot the driver must handle that + * as best as it can, mac80211 is too slow. * * Dynamic powersave mode is an extension to normal powersave mode in which * the hardware stays awake for a user-specified period of time after sending @@ -1134,11 +1110,53 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * way the host will only receive beacons where some relevant information * (for example ERP protection or WMM settings) have changed. * - * Beacon filter support is informed with %IEEE80211_HW_BEACON_FILTER flag. - * The driver needs to enable beacon filter support whenever power save is - * enabled, that is %IEEE80211_CONF_PS is set. When power save is enabled, - * the stack will not check for beacon miss at all and the driver needs to - * notify about complete loss of beacons with ieee80211_beacon_loss(). + * Beacon filter support is advertised with the %IEEE80211_HW_BEACON_FILTER + * hardware capability. The driver needs to enable beacon filter support + * whenever power save is enabled, that is %IEEE80211_CONF_PS is set. When + * power save is enabled, the stack will not check for beacon loss and the + * driver needs to notify about loss of beacons with ieee80211_beacon_loss(). + * + * The time (or number of beacons missed) until the firmware notifies the + * driver of a beacon loss event (which in turn causes the driver to call + * ieee80211_beacon_loss()) should be configurable and will be controlled + * by mac80211 and the roaming algorithm in the future. + * + * Since there may be constantly changing information elements that nothing + * in the software stack cares about, we will, in the future, have mac80211 + * tell the driver which information elements are interesting in the sense + * that we want to see changes in them. This will include + * - a list of information element IDs + * - a list of OUIs for the vendor information element + * + * Ideally, the hardware would filter out any beacons without changes in the + * requested elements, but if it cannot support that it may, at the expense + * of some efficiency, filter out only a subset. For example, if the device + * doesn't support checking for OUIs it should pass up all changes in all + * vendor information elements. + * + * Note that change, for the sake of simplification, also includes information + * elements appearing or disappearing from the beacon. + * + * Some hardware supports an "ignore list" instead, just make sure nothing + * that was requested is on the ignore list, and include commonly changing + * information element IDs in the ignore list, for example 11 (BSS load) and + * the various vendor-assigned IEs with unknown contents (128, 129, 133-136, + * 149, 150, 155, 156, 173, 176, 178, 179, 219); for forward compatibility + * it could also include some currently unused IDs. + * + * + * In addition to these capabilities, hardware should support notifying the + * host of changes in the beacon RSSI. This is relevant to implement roaming + * when no traffic is flowing (when traffic is flowing we see the RSSI of + * the received data packets). This can consist in notifying the host when + * the RSSI changes significantly or when it drops below or rises above + * configurable thresholds. In the future these thresholds will also be + * configured by mac80211 (which gets them from userspace) to implement + * them as the roaming algorithm requires. + * + * If the hardware cannot implement this, the driver should ask it to + * periodically pass beacon frames to the host so that software can do the + * signal strength threshold checking. */ /** @@ -1298,10 +1316,6 @@ enum ieee80211_ampdu_mlme_action { * This function should never fail but returns a negative error code * if it does. * - * @config_interface: Handler for configuration requests related to interfaces - * (e.g. BSSID changes.) - * Returns a negative error code which will be seen in userspace. - * * @bss_info_changed: Handler for configuration requests related to BSS * parameters that may vary during BSS's lifespan, and may affect low * level driver (e.g. assoc/disassoc status, erp parameters). @@ -1330,11 +1344,14 @@ enum ieee80211_ampdu_mlme_action { * the scan state machine in stack. The scan must honour the channel * configuration done by the regulatory agent in the wiphy's * registered bands. The hardware (or the driver) needs to make sure - * that power save is disabled. When the scan finishes, - * ieee80211_scan_completed() must be called; note that it also must - * be called when the scan cannot finish because the hardware is - * turned off! Anything else is a bug! Returns a negative error code - * which will be seen in userspace. + * that power save is disabled. + * The @req ie/ie_len members are rewritten by mac80211 to contain the + * entire IEs after the SSID, so that drivers need not look at these + * at all but just send them after the SSID -- mac80211 includes the + * (extended) supported rates and HT information (where applicable). + * When the scan finishes, ieee80211_scan_completed() must be called; + * note that it also must be called when the scan cannot finish due to + * any error unless this callback returned a negative error code. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. @@ -1390,6 +1407,10 @@ enum ieee80211_ampdu_mlme_action { * is the first frame we expect to perform the action on. Notice * that TX/RX_STOP can pass NULL for this parameter. * Returns a negative error code on failure. + * + * @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. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1400,9 +1421,6 @@ struct ieee80211_ops { void (*remove_interface)(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int (*config)(struct ieee80211_hw *hw, u32 changed); - int (*config_interface)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); void (*bss_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -1441,6 +1459,8 @@ struct ieee80211_ops { int (*ampdu_action)(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn); + + void (*rfkill_poll)(struct ieee80211_hw *hw); }; /** @@ -1572,6 +1592,20 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw); */ void ieee80211_free_hw(struct ieee80211_hw *hw); +/** + * ieee80211_restart_hw - restart hardware completely + * + * Call this function when the hardware was restarted for some reason + * (hardware error, ...) and the driver is unable to restore its state + * by itself. mac80211 assumes that at this point the driver/hardware + * is completely uninitialised and stopped, it starts the process by + * calling the ->start() operation. The driver will need to reset all + * internal state that it has prior to calling this function. + * + * @hw: the hardware to restart + */ +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); @@ -1774,24 +1808,6 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct sk_buff * ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -/** - * ieee80211_get_hdrlen_from_skb - get header length from data - * - * Given an skb with a raw 802.11 header at the data pointer this function - * returns the 802.11 header length in bytes (not including encryption - * headers). If the data in the sk_buff is too short to contain a valid 802.11 - * header the function returns 0. - * - * @skb: the frame - */ -unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); - -/** - * ieee80211_hdrlen - get header length in bytes from frame control - * @fc: frame control field in little-endian format - */ -unsigned int ieee80211_hdrlen(__le16 fc); - /** * ieee80211_get_tkip_key - get a TKIP rc4 for skb * diff --git a/include/net/netfilter/ipv4/nf_conntrack_icmp.h b/include/net/netfilter/ipv4/nf_conntrack_icmp.h deleted file mode 100644 index 3dd22cff23ec..000000000000 --- a/include/net/netfilter/ipv4/nf_conntrack_icmp.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _NF_CONNTRACK_ICMP_H -#define _NF_CONNTRACK_ICMP_H -/* ICMP tracking. */ -#include - -struct ip_ct_icmp -{ - /* Optimization: when number in == number out, forget immediately. */ - atomic_t count; -}; -#endif /* _NF_CONNTRACK_ICMP_H */ diff --git a/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h b/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h index 86591afda29c..67edd50a398a 100644 --- a/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h +++ b/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h @@ -9,7 +9,6 @@ #ifndef _NF_CONNTRACK_ICMPV6_H #define _NF_CONNTRACK_ICMPV6_H -#include #ifndef ICMPV6_NI_QUERY #define ICMPV6_NI_QUERY 139 @@ -18,10 +17,4 @@ #define ICMPV6_NI_REPLY 140 #endif -struct nf_ct_icmpv6 -{ - /* Optimization: when number in == number out, forget immediately. */ - atomic_t count; -}; - #endif /* _NF_CONNTRACK_ICMPV6_H */ diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 6c3f964de9e1..a632689b61b4 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -34,8 +33,6 @@ union nf_conntrack_proto { struct nf_ct_dccp dccp; struct ip_ct_sctp sctp; struct ip_ct_tcp tcp; - struct ip_ct_icmp icmp; - struct nf_ct_icmpv6 icmpv6; struct nf_ct_gre gre; }; @@ -96,6 +93,8 @@ struct nf_conn { plus 1 for any connection(s) we are `master' for */ struct nf_conntrack ct_general; + spinlock_t lock; + /* XXX should I move this to the tail ? - Y.K */ /* These are my tuples; original and reply */ struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; @@ -144,6 +143,8 @@ static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct) return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; } +#define nf_ct_tuple(ct, dir) (&(ct)->tuplehash[dir].tuple) + /* get master conntrack via master expectation */ #define master_ct(conntr) (conntr->master) @@ -200,8 +201,10 @@ extern struct nf_conntrack_tuple_hash * __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); extern void nf_conntrack_hash_insert(struct nf_conn *ct); +extern void nf_ct_delete_from_lists(struct nf_conn *ct); +extern void nf_ct_insert_dying_list(struct nf_conn *ct); -extern void nf_conntrack_flush(struct net *net, u32 pid, int report); +extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); extern bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, u_int16_t l3num, diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 0ff0dc69ca4a..4f20d58e2ab7 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -6,17 +6,54 @@ #define _NF_CONNTRACK_ECACHE_H #include -#include -#include #include #include +#include +#include +#include -#ifdef CONFIG_NF_CONNTRACK_EVENTS -struct nf_conntrack_ecache { - struct nf_conn *ct; - unsigned int events; +/* Connection tracking event types */ +enum ip_conntrack_events +{ + IPCT_NEW = 0, /* new conntrack */ + IPCT_RELATED = 1, /* related conntrack */ + IPCT_DESTROY = 2, /* destroyed conntrack */ + IPCT_STATUS = 3, /* status has changed */ + IPCT_PROTOINFO = 4, /* protocol information has changed */ + IPCT_HELPER = 5, /* new helper has been set */ + IPCT_MARK = 6, /* new mark has been set */ + IPCT_NATSEQADJ = 7, /* NAT is doing sequence adjustment */ + IPCT_SECMARK = 8, /* new security mark has been set */ }; +enum ip_conntrack_expect_events { + IPEXP_NEW = 0, /* new expectation */ +}; + +struct nf_conntrack_ecache { + unsigned long cache; /* bitops want long */ + unsigned long missed; /* missed events */ + u32 pid; /* netlink pid of destroyer */ +}; + +static inline struct nf_conntrack_ecache * +nf_ct_ecache_find(const struct nf_conn *ct) +{ + return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE); +} + +static inline struct nf_conntrack_ecache * +nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp) +{ + struct net *net = nf_ct_net(ct); + + if (!net->ct.sysctl_events) + return NULL; + + return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp); +}; + +#ifdef CONFIG_NF_CONNTRACK_EVENTS /* This structure is passed to event handler */ struct nf_ct_event { struct nf_conn *ct; @@ -24,47 +61,96 @@ struct nf_ct_event { int report; }; -extern struct atomic_notifier_head nf_conntrack_chain; -extern int nf_conntrack_register_notifier(struct notifier_block *nb); -extern int nf_conntrack_unregister_notifier(struct notifier_block *nb); +struct nf_ct_event_notifier { + int (*fcn)(unsigned int events, struct nf_ct_event *item); +}; -extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); -extern void __nf_ct_event_cache_init(struct nf_conn *ct); -extern void nf_ct_event_cache_flush(struct net *net); +extern struct nf_ct_event_notifier *nf_conntrack_event_cb; +extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); +extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); + +extern void nf_ct_deliver_cached_events(struct nf_conn *ct); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) { - struct net *net = nf_ct_net(ct); - struct nf_conntrack_ecache *ecache; + struct nf_conntrack_ecache *e; - local_bh_disable(); - ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id()); - if (ct != ecache->ct) - __nf_ct_event_cache_init(ct); - ecache->events |= event; - local_bh_enable(); + if (nf_conntrack_event_cb == NULL) + return; + + e = nf_ct_ecache_find(ct); + if (e == NULL) + return; + + set_bit(event, &e->cache); } -static inline void -nf_conntrack_event_report(enum ip_conntrack_events event, - struct nf_conn *ct, - u32 pid, - int report) +static inline int +nf_conntrack_eventmask_report(unsigned int eventmask, + struct nf_conn *ct, + u32 pid, + int report) { - struct nf_ct_event item = { - .ct = ct, - .pid = pid, - .report = report - }; - if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) - atomic_notifier_call_chain(&nf_conntrack_chain, event, &item); + int ret = 0; + struct net *net = nf_ct_net(ct); + struct nf_ct_event_notifier *notify; + struct nf_conntrack_ecache *e; + + rcu_read_lock(); + notify = rcu_dereference(nf_conntrack_event_cb); + if (notify == NULL) + goto out_unlock; + + if (!net->ct.sysctl_events) + goto out_unlock; + + e = nf_ct_ecache_find(ct); + if (e == NULL) + goto out_unlock; + + if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { + struct nf_ct_event item = { + .ct = ct, + .pid = e->pid ? e->pid : pid, + .report = report + }; + /* This is a resent of a destroy event? If so, skip missed */ + unsigned long missed = e->pid ? 0 : e->missed; + + ret = notify->fcn(eventmask | missed, &item); + if (unlikely(ret < 0 || missed)) { + spin_lock_bh(&ct->lock); + if (ret < 0) { + /* This is a destroy event that has been + * triggered by a process, we store the PID + * to include it in the retransmission. */ + if (eventmask & (1 << IPCT_DESTROY) && + e->pid == 0 && pid != 0) + e->pid = pid; + else + e->missed |= eventmask; + } else + e->missed &= ~missed; + spin_unlock_bh(&ct->lock); + } + } +out_unlock: + rcu_read_unlock(); + return ret; } -static inline void +static inline int +nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, + u32 pid, int report) +{ + return nf_conntrack_eventmask_report(1 << event, ct, pid, report); +} + +static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { - nf_conntrack_event_report(event, ct, 0, 0); + return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); } struct nf_exp_event { @@ -73,9 +159,13 @@ struct nf_exp_event { int report; }; -extern struct atomic_notifier_head nf_ct_expect_chain; -extern int nf_ct_expect_register_notifier(struct notifier_block *nb); -extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); +struct nf_exp_event_notifier { + int (*fcn)(unsigned int events, struct nf_exp_event *item); +}; + +extern struct nf_exp_event_notifier *nf_expect_event_cb; +extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb); +extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb); static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, @@ -83,12 +173,27 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, u32 pid, int report) { - struct nf_exp_event item = { - .exp = exp, - .pid = pid, - .report = report - }; - atomic_notifier_call_chain(&nf_ct_expect_chain, event, &item); + struct net *net = nf_ct_exp_net(exp); + struct nf_exp_event_notifier *notify; + + rcu_read_lock(); + notify = rcu_dereference(nf_expect_event_cb); + if (notify == NULL) + goto out_unlock; + + if (!net->ct.sysctl_events) + goto out_unlock; + + { + struct nf_exp_event item = { + .exp = exp, + .pid = pid, + .report = report + }; + notify->fcn(1 << event, &item); + } +out_unlock: + rcu_read_unlock(); } static inline void @@ -105,12 +210,16 @@ extern void nf_conntrack_ecache_fini(struct net *net); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) {} -static inline void nf_conntrack_event(enum ip_conntrack_events event, - struct nf_conn *ct) {} -static inline void nf_conntrack_event_report(enum ip_conntrack_events event, - struct nf_conn *ct, - u32 pid, - int report) {} +static inline int nf_conntrack_eventmask_report(unsigned int eventmask, + struct nf_conn *ct, + u32 pid, + int report) { return 0; } +static inline int nf_conntrack_event(enum ip_conntrack_events event, + struct nf_conn *ct) { return 0; } +static inline int nf_conntrack_event_report(enum ip_conntrack_events event, + struct nf_conn *ct, + u32 pid, + int report) { return 0; } static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event, struct nf_conntrack_expect *exp) {} @@ -118,7 +227,6 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, struct nf_conntrack_expect *exp, u32 pid, int report) {} -static inline void nf_ct_event_cache_flush(struct net *net) {} static inline int nf_conntrack_ecache_init(struct net *net) { diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index da8ee52613a5..7f8fc5d123c5 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -8,12 +8,14 @@ enum nf_ct_ext_id NF_CT_EXT_HELPER, NF_CT_EXT_NAT, NF_CT_EXT_ACCT, + NF_CT_EXT_ECACHE, NF_CT_EXT_NUM, }; #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter +#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index ee2a4b369a04..1b7068000927 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -50,6 +50,8 @@ extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); extern int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags); +extern void nf_ct_helper_destroy(struct nf_conn *ct); + static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) { return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index ba32ed7bdabe..3767fb41e541 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -59,11 +59,11 @@ struct nf_conntrack_l4proto const struct nf_conntrack_tuple *); /* Print out the private part of the conntrack. */ - int (*print_conntrack)(struct seq_file *s, const struct nf_conn *); + int (*print_conntrack)(struct seq_file *s, struct nf_conn *); /* convert protoinfo to nfnetink attributes */ int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, - const struct nf_conn *ct); + struct nf_conn *ct); /* Calculate protoinfo nlattr size */ int (*nlattr_size)(void); diff --git a/include/net/netlink.h b/include/net/netlink.h index eddb50289d6d..007bdb07dabb 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -939,6 +939,15 @@ static inline u64 nla_get_u64(const struct nlattr *nla) return tmp; } +/** + * nla_get_be64 - return payload of __be64 attribute + * @nla: __be64 netlink attribute + */ +static inline __be64 nla_get_be64(const struct nlattr *nla) +{ + return *(__be64 *) nla_data(nla); +} + /** * nla_get_flag - return payload of flag attribute * @nla: flag netlink attribute diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 9dc58402bc09..ba1ba0c5efd1 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -14,16 +14,17 @@ struct netns_ct { struct hlist_nulls_head *hash; struct hlist_head *expect_hash; struct hlist_nulls_head unconfirmed; + struct hlist_nulls_head dying; struct ip_conntrack_stat *stat; -#ifdef CONFIG_NF_CONNTRACK_EVENTS - struct nf_conntrack_ecache *ecache; -#endif + int sysctl_events; + unsigned int sysctl_events_retry_timeout; int sysctl_acct; int sysctl_checksum; unsigned int sysctl_log_invalid; /* Log invalid packets */ #ifdef CONFIG_SYSCTL struct ctl_table_header *sysctl_header; struct ctl_table_header *acct_sysctl_header; + struct ctl_table_header *event_sysctl_header; #endif int hash_vmalloc; int expect_vmalloc; diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index e37fe3129c17..82a3191375f5 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -41,16 +41,17 @@ static inline void *qdisc_priv(struct Qdisc *q) typedef u64 psched_time_t; typedef long psched_tdiff_t; -/* Avoid doing 64 bit divide by 1000 */ -#define PSCHED_US2NS(x) ((s64)(x) << 10) -#define PSCHED_NS2US(x) ((x) >> 10) +/* Avoid doing 64 bit divide */ +#define PSCHED_SHIFT 6 +#define PSCHED_TICKS2NS(x) ((s64)(x) << PSCHED_SHIFT) +#define PSCHED_NS2TICKS(x) ((x) >> PSCHED_SHIFT) -#define PSCHED_TICKS_PER_SEC PSCHED_NS2US(NSEC_PER_SEC) +#define PSCHED_TICKS_PER_SEC PSCHED_NS2TICKS(NSEC_PER_SEC) #define PSCHED_PASTPERFECT 0 static inline psched_time_t psched_get_time(void) { - return PSCHED_NS2US(ktime_to_ns(ktime_get())); + return PSCHED_NS2TICKS(ktime_to_ns(ktime_get())); } static inline psched_tdiff_t diff --git a/include/net/regulatory.h b/include/net/regulatory.h new file mode 100644 index 000000000000..47995b81c5d7 --- /dev/null +++ b/include/net/regulatory.h @@ -0,0 +1,101 @@ +#ifndef __NET_REGULATORY_H +#define __NET_REGULATORY_H +/* + * regulatory support structures + * + * Copyright 2008-2009 Luis R. Rodriguez + * + * 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. + */ + + +/** + * enum environment_cap - Environment parsed from country IE + * @ENVIRON_ANY: indicates country IE applies to both indoor and + * outdoor operation. + * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation + * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation + */ +enum environment_cap { + ENVIRON_ANY, + ENVIRON_INDOOR, + ENVIRON_OUTDOOR, +}; + +/** + * struct regulatory_request - used to keep track of regulatory requests + * + * @wiphy_idx: this is set if this request's initiator is + * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This + * can be used by the wireless core to deal with conflicts + * and potentially inform users of which devices specifically + * cased the conflicts. + * @initiator: indicates who sent this request, could be any of + * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) + * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested + * regulatory domain. We have a few special codes: + * 00 - World regulatory domain + * 99 - built by driver but a specific alpha2 cannot be determined + * 98 - result of an intersection between two regulatory domains + * @intersect: indicates whether the wireless core should intersect + * the requested regulatory domain with the presently set regulatory + * domain. + * @country_ie_checksum: checksum of the last processed and accepted + * country IE + * @country_ie_env: lets us know if the AP is telling us we are outdoor, + * indoor, or if it doesn't matter + * @list: used to insert into the reg_requests_list linked list + */ +struct regulatory_request { + int wiphy_idx; + enum nl80211_reg_initiator initiator; + char alpha2[2]; + bool intersect; + u32 country_ie_checksum; + enum environment_cap country_ie_env; + struct list_head list; +}; + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 flags; +}; + +struct ieee80211_regdomain { + u32 n_reg_rules; + char alpha2[2]; + struct ieee80211_reg_rule reg_rules[]; +}; + +#define MHZ_TO_KHZ(freq) ((freq) * 1000) +#define KHZ_TO_MHZ(freq) ((freq) / 1000) +#define DBI_TO_MBI(gain) ((gain) * 100) +#define MBI_TO_DBI(gain) ((gain) / 100) +#define DBM_TO_MBM(gain) ((gain) * 100) +#define MBM_TO_DBM(gain) ((gain) / 100) + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ +} + +#endif diff --git a/include/net/route.h b/include/net/route.h index 4e8cae0e5841..40f6346ef496 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -210,7 +210,7 @@ static inline struct inet_peer *rt_get_peer(struct rtable *rt) static inline int inet_iif(const struct sk_buff *skb) { - return skb->rtable->rt_iif; + return skb_rtable(skb)->rt_iif; } #endif /* _ROUTE_H */ diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 23f08fe1d50a..edfcacf3250e 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1939,10 +1939,8 @@ void sctp_association_free(struct sctp_association *); void sctp_association_put(struct sctp_association *); void sctp_association_hold(struct sctp_association *); -struct sctp_transport *sctp_assoc_choose_init_transport( - struct sctp_association *); -struct sctp_transport *sctp_assoc_choose_shutdown_transport( - struct sctp_association *); +struct sctp_transport *sctp_assoc_choose_alter_transport( + struct sctp_association *, struct sctp_transport *); void sctp_assoc_update_retran_path(struct sctp_association *); struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, const union sctp_addr *); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index b259fc5798fb..1580c04f68bc 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -147,6 +147,8 @@ enum sctp_optname { #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX + SCTP_SOCKOPT_CONNECTX3, /* CONNECTX requests. (new implementation) */ +#define SCTP_SOCKOPT_CONNECTX3 SCTP_SOCKOPT_CONNECTX3 }; /* diff --git a/include/net/snmp.h b/include/net/snmp.h index 57c93628695f..8c842e06bec8 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -153,6 +153,11 @@ struct linux_xfrm_mib { per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \ put_cpu(); \ } while (0) +#define SNMP_ADD_STATS(mib, field, addend) \ + do { \ + per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \ + put_cpu(); \ + } while (0) #define SNMP_ADD_STATS_BH(mib, field, addend) \ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend) #define SNMP_ADD_STATS_USER(mib, field, addend) \ @@ -160,5 +165,17 @@ struct linux_xfrm_mib { per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \ put_cpu(); \ } while (0) - +#define SNMP_UPD_PO_STATS(mib, basefield, addend) \ + do { \ + __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\ + ptr->mibs[basefield##PKTS]++; \ + ptr->mibs[basefield##OCTETS] += addend;\ + put_cpu(); \ + } while (0) +#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ + do { \ + __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\ + ptr->mibs[basefield##PKTS]++; \ + ptr->mibs[basefield##OCTETS] += addend;\ + } while (0) #endif diff --git a/include/net/sock.h b/include/net/sock.h index 4bb1ff9fd15b..010e14a93c92 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1217,9 +1217,13 @@ static inline int skb_copy_to_page(struct sock *sk, char __user *from, static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) { - sock_hold(sk); skb->sk = sk; skb->destructor = sock_wfree; + /* + * We used to take a refcount on sk, but following operation + * is enough to guarantee sk_free() wont free this sock until + * all in-flight packets are completed + */ atomic_add(skb->truesize, &sk->sk_wmem_alloc); } diff --git a/include/net/tcp.h b/include/net/tcp.h index 646dbe3962ea..19f4150f4d4d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -266,6 +266,19 @@ static inline int tcp_too_many_orphans(struct sock *sk, int num) atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]); } +/* syncookies: remember time of last synqueue overflow */ +static inline void tcp_synq_overflow(struct sock *sk) +{ + tcp_sk(sk)->rx_opt.ts_recent_stamp = jiffies; +} + +/* syncookies: no recent synqueue overflow on this listening socket? */ +static inline int tcp_synq_no_recent_overflow(const struct sock *sk) +{ + unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + return time_after(jiffies, last_overflow + TCP_TIMEOUT_INIT); +} + extern struct proto tcp_prot; #define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field) @@ -889,30 +902,32 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); - if (!sysctl_tcp_low_latency && tp->ucopy.task) { - __skb_queue_tail(&tp->ucopy.prequeue, skb); - tp->ucopy.memory += skb->truesize; - if (tp->ucopy.memory > sk->sk_rcvbuf) { - struct sk_buff *skb1; + if (sysctl_tcp_low_latency || !tp->ucopy.task) + return 0; - BUG_ON(sock_owned_by_user(sk)); + __skb_queue_tail(&tp->ucopy.prequeue, skb); + tp->ucopy.memory += skb->truesize; + if (tp->ucopy.memory > sk->sk_rcvbuf) { + struct sk_buff *skb1; - while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) { - sk_backlog_rcv(sk, skb1); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPREQUEUEDROPPED); - } + BUG_ON(sock_owned_by_user(sk)); - tp->ucopy.memory = 0; - } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) { - wake_up_interruptible(sk->sk_sleep); - if (!inet_csk_ack_scheduled(sk)) - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - (3 * tcp_rto_min(sk)) / 4, - TCP_RTO_MAX); + while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) { + sk_backlog_rcv(sk, skb1); + NET_INC_STATS_BH(sock_net(sk), + LINUX_MIB_TCPPREQUEUEDROPPED); } - return 1; + + tp->ucopy.memory = 0; + } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) { + wake_up_interruptible_poll(sk->sk_sleep, + POLLIN | POLLRDNORM | POLLRDBAND); + if (!inet_csk_ack_scheduled(sk)) + inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, + (3 * tcp_rto_min(sk)) / 4, + TCP_RTO_MAX); } - return 0; + return 1; } diff --git a/include/net/wimax.h b/include/net/wimax.h index 6b3824edb39e..2af7bf839f23 100644 --- a/include/net/wimax.h +++ b/include/net/wimax.h @@ -253,7 +253,6 @@ struct net_device; struct genl_info; struct wimax_dev; -struct input_dev; /** * struct wimax_dev - Generic WiMAX device @@ -293,8 +292,8 @@ struct input_dev; * See wimax_reset()'s documentation. * * @name: [fill] A way to identify this device. We need to register a - * name with many subsystems (input for RFKILL, workqueue - * creation, etc). We can't use the network device name as that + * name with many subsystems (rfkill, workqueue creation, etc). + * We can't use the network device name as that * might change and in some instances we don't know it yet (until * we don't call register_netdev()). So we generate an unique one * using the driver name and device bus id, place it here and use @@ -316,9 +315,6 @@ struct input_dev; * * @rfkill: [private] integration into the RF-Kill infrastructure. * - * @rfkill_input: [private] virtual input device to process the - * hardware RF Kill switches. - * * @rf_sw: [private] State of the software radio switch (OFF/ON) * * @rf_hw: [private] State of the hardware radio switch (OFF/ON) diff --git a/include/net/wireless.h b/include/net/wireless.h deleted file mode 100644 index 64a76208580c..000000000000 --- a/include/net/wireless.h +++ /dev/null @@ -1,472 +0,0 @@ -#ifndef __NET_WIRELESS_H -#define __NET_WIRELESS_H - -/* - * 802.11 device management - * - * Copyright 2007 Johannes Berg - */ - -#include -#include -#include -#include -#include - -/** - * enum ieee80211_band - supported frequency bands - * - * The bands are assigned this way because the supported - * bitrates differ in these bands. - * - * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band - * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) - */ -enum ieee80211_band { - IEEE80211_BAND_2GHZ, - IEEE80211_BAND_5GHZ, - - /* keep last */ - IEEE80211_NUM_BANDS -}; - -/** - * enum ieee80211_channel_flags - channel flags - * - * Channel flags set by the regulatory control code. - * - * @IEEE80211_CHAN_DISABLED: This channel is disabled. - * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted - * on this channel. - * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. - * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. - * @IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel - * is not permitted. - * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel - * is not permitted. - */ -enum ieee80211_channel_flags { - IEEE80211_CHAN_DISABLED = 1<<0, - IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, - IEEE80211_CHAN_NO_IBSS = 1<<2, - IEEE80211_CHAN_RADAR = 1<<3, - IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, - IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, -}; - -/** - * struct ieee80211_channel - channel definition - * - * This structure describes a single channel for use - * 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 - * code to support devices with additional restrictions - * @band: band this channel belongs to. - * @max_antenna_gain: maximum antenna gain in dBi - * @max_power: maximum transmission power (in dBm) - * @beacon_found: helper to regulatory code to indicate when a beacon - * has been found on this channel. Use regulatory_hint_found_beacon() - * to enable this, this is is useful only on 5 GHz band. - * @orig_mag: internal use - * @orig_mpwr: internal use - */ -struct ieee80211_channel { - enum ieee80211_band band; - u16 center_freq; - u8 max_bandwidth; - u16 hw_value; - u32 flags; - int max_antenna_gain; - int max_power; - bool beacon_found; - u32 orig_flags; - int orig_mag, orig_mpwr; -}; - -/** - * enum ieee80211_rate_flags - rate flags - * - * Hardware/specification flags for rates. These are structured - * in a way that allows using the same bitrate structure for - * different bands/PHY modes. - * - * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short - * preamble on this bitrate; only relevant in 2.4GHz band and - * with CCK rates. - * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate - * when used with 802.11a (on the 5 GHz band); filled by the - * core code when registering the wiphy. - * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate - * when used with 802.11b (on the 2.4 GHz band); filled by the - * core code when registering the wiphy. - * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate - * when used with 802.11g (on the 2.4 GHz band); filled by the - * core code when registering the wiphy. - * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. - */ -enum ieee80211_rate_flags { - IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, - IEEE80211_RATE_MANDATORY_A = 1<<1, - IEEE80211_RATE_MANDATORY_B = 1<<2, - IEEE80211_RATE_MANDATORY_G = 1<<3, - IEEE80211_RATE_ERP_G = 1<<4, -}; - -/** - * struct ieee80211_rate - bitrate definition - * - * This structure describes a bitrate that an 802.11 PHY can - * operate with. The two values @hw_value and @hw_value_short - * are only for driver use when pointers to this structure are - * passed around. - * - * @flags: rate-specific flags - * @bitrate: bitrate in units of 100 Kbps - * @hw_value: driver/hardware value for this rate - * @hw_value_short: driver/hardware value for this rate when - * short preamble is used - */ -struct ieee80211_rate { - u32 flags; - u16 bitrate; - u16 hw_value, hw_value_short; -}; - -/** - * struct ieee80211_sta_ht_cap - STA's HT capabilities - * - * This structure describes most essential parameters needed - * to describe 802.11n HT capabilities for an STA. - * - * @ht_supported: is HT supported by the STA - * @cap: HT capabilities map as described in 802.11n spec - * @ampdu_factor: Maximum A-MPDU length factor - * @ampdu_density: Minimum A-MPDU spacing - * @mcs: Supported MCS rates - */ -struct ieee80211_sta_ht_cap { - u16 cap; /* use IEEE80211_HT_CAP_ */ - bool ht_supported; - u8 ampdu_factor; - u8 ampdu_density; - struct ieee80211_mcs_info mcs; -}; - -/** - * struct ieee80211_supported_band - frequency band definition - * - * This structure describes a frequency band a wiphy - * is able to operate in. - * - * @channels: Array of channels the hardware can operate in - * in this band. - * @band: the band this structure represents - * @n_channels: Number of channels in @channels - * @bitrates: Array of bitrates the hardware can operate with - * in this band. Must be sorted to give a valid "supported - * rates" IE, i.e. CCK rates first, then OFDM. - * @n_bitrates: Number of bitrates in @bitrates - */ -struct ieee80211_supported_band { - struct ieee80211_channel *channels; - struct ieee80211_rate *bitrates; - enum ieee80211_band band; - int n_channels; - int n_bitrates; - struct ieee80211_sta_ht_cap ht_cap; -}; - -/** - * struct wiphy - wireless hardware description - * @idx: the wiphy index assigned to this item - * @class_dev: the class device representing /sys/class/ieee80211/ - * @custom_regulatory: tells us the driver for this device - * has its own custom regulatory domain and cannot identify the - * ISO / IEC 3166 alpha2 it belongs to. When this is enabled - * we will disregard the first regulatory hint (when the - * initiator is %REGDOM_SET_BY_CORE). - * @strict_regulatory: tells us the driver for this device will ignore - * regulatory domain settings until it gets its own regulatory domain - * via its regulatory_hint(). After its gets its own regulatory domain - * it will only allow further regulatory domain settings to further - * enhance compliance. For example if channel 13 and 14 are disabled - * by this regulatory domain no user regulatory domain can enable these - * channels at a later time. This can be used for devices which do not - * have calibration information gauranteed for frequencies or settings - * outside of its regulatory domain. - * @reg_notifier: the driver's regulatory notification callback - * @regd: the driver's regulatory domain, if one was requested via - * the regulatory_hint() API. This can be used by the driver - * on the reg_notifier() if it chooses to ignore future - * regulatory domain changes caused by other drivers. - * @signal_type: signal type reported in &struct cfg80211_bss. - */ -struct wiphy { - /* assign these fields before you register the wiphy */ - - /* permanent MAC address */ - u8 perm_addr[ETH_ALEN]; - - /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ - u16 interface_modes; - - bool custom_regulatory; - bool strict_regulatory; - - enum cfg80211_signal_type signal_type; - - int bss_priv_size; - u8 max_scan_ssids; - - /* If multiple wiphys are registered and you're handed e.g. - * a regular netdev with assigned ieee80211_ptr, you won't - * know whether it points to a wiphy your driver has registered - * or not. Assign this to something global to your driver to - * help determine whether you own this wiphy or not. */ - void *privid; - - struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; - - /* Lets us get back the wiphy on the callback */ - int (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request); - - /* fields below are read-only, assigned by cfg80211 */ - - const struct ieee80211_regdomain *regd; - - /* the item in /sys/class/ieee80211/ points to this, - * you need use set_wiphy_dev() (see below) */ - struct device dev; - - /* dir in debugfs: ieee80211/ */ - struct dentry *debugfsdir; - - char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); -}; - -/** struct wireless_dev - wireless per-netdev state - * - * This structure must be allocated by the driver/stack - * that uses the ieee80211_ptr field in struct net_device - * (this is intentional so it can be allocated along with - * the netdev.) - * - * @wiphy: pointer to hardware description - * @iftype: interface type - */ -struct wireless_dev { - struct wiphy *wiphy; - enum nl80211_iftype iftype; - - /* private to the generic wireless code */ - struct list_head list; - struct net_device *netdev; -}; - -/** - * wiphy_priv - return priv from wiphy - */ -static inline void *wiphy_priv(struct wiphy *wiphy) -{ - BUG_ON(!wiphy); - return &wiphy->priv; -} - -/** - * set_wiphy_dev - set device pointer for wiphy - */ -static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev) -{ - wiphy->dev.parent = dev; -} - -/** - * wiphy_dev - get wiphy dev pointer - */ -static inline struct device *wiphy_dev(struct wiphy *wiphy) -{ - return wiphy->dev.parent; -} - -/** - * wiphy_name - get wiphy name - */ -static inline const char *wiphy_name(struct wiphy *wiphy) -{ - return dev_name(&wiphy->dev); -} - -/** - * wdev_priv - return wiphy priv from wireless_dev - */ -static inline void *wdev_priv(struct wireless_dev *wdev) -{ - BUG_ON(!wdev); - return wiphy_priv(wdev->wiphy); -} - -/** - * wiphy_new - create a new wiphy for use with cfg80211 - * - * create a new wiphy and associate the given operations with it. - * @sizeof_priv bytes are allocated for private use. - * - * the returned pointer must be assigned to each netdev's - * ieee80211_ptr for proper operation. - */ -struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv); - -/** - * wiphy_register - register a wiphy with cfg80211 - * - * register the given wiphy - * - * Returns a non-negative wiphy index or a negative error code. - */ -extern int wiphy_register(struct wiphy *wiphy); - -/** - * wiphy_unregister - deregister a wiphy from cfg80211 - * - * unregister a device with the given priv pointer. - * After this call, no more requests can be made with this priv - * pointer, but the call may sleep to wait for an outstanding - * request that is being handled. - */ -extern void wiphy_unregister(struct wiphy *wiphy); - -/** - * wiphy_free - free wiphy - */ -extern void wiphy_free(struct wiphy *wiphy); - -/** - * ieee80211_channel_to_frequency - convert channel number to frequency - */ -extern int ieee80211_channel_to_frequency(int chan); - -/** - * ieee80211_frequency_to_channel - convert frequency to channel number - */ -extern int ieee80211_frequency_to_channel(int freq); - -/* - * Name indirection necessary because the ieee80211 code also has - * a function named "ieee80211_get_channel", so if you include - * cfg80211's header file you get cfg80211's version, if you try - * to include both header files you'll (rightfully!) get a symbol - * clash. - */ -extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, - int freq); -/** - * ieee80211_get_channel - get channel struct from wiphy for specified frequency - */ -static inline struct ieee80211_channel * -ieee80211_get_channel(struct wiphy *wiphy, int freq) -{ - return __ieee80211_get_channel(wiphy, freq); -} - -/** - * ieee80211_get_response_rate - get basic rate for a given rate - * - * @sband: the band to look for rates in - * @basic_rates: bitmap of basic rates - * @bitrate: the bitrate for which to find the basic rate - * - * This function returns the basic rate corresponding to a given - * bitrate, that is the next lower bitrate contained in the basic - * rate map, which is, for this function, given as a bitmap of - * indices of rates in the band's bitrate table. - */ -struct ieee80211_rate * -ieee80211_get_response_rate(struct ieee80211_supported_band *sband, - u32 basic_rates, int bitrate); - -/** - * regulatory_hint - driver hint to the wireless core a regulatory domain - * @wiphy: the wireless device giving the hint (used only for reporting - * conflicts) - * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain - * should be in. If @rd is set this should be NULL. Note that if you - * set this to NULL you should still set rd->alpha2 to some accepted - * alpha2. - * - * Wireless drivers can use this function to hint to the wireless core - * what it believes should be the current regulatory domain by - * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory - * domain should be in or by providing a completely build regulatory domain. - * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried - * for a regulatory domain structure for the respective country. - * - * The wiphy must have been registered to cfg80211 prior to this call. - * For cfg80211 drivers this means you must first use wiphy_register(), - * for mac80211 drivers you must first use ieee80211_register_hw(). - * - * Drivers should check the return value, its possible you can get - * an -ENOMEM. - */ -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 - * - * Drivers can sometimes have custom regulatory domains which do not apply - * to a specific country. Drivers can use this to apply such custom regulatory - * domains. This routine must be called prior to wiphy registration. The - * custom regulatory domain will be trusted completely and as such previous - * default channel settings will be disregarded. If no rule is found for a - * channel on the regulatory domain the channel will be disabled. - */ -extern void wiphy_apply_custom_regulatory( - struct wiphy *wiphy, - const struct ieee80211_regdomain *regd); - -/** - * freq_reg_info - get regulatory information for the given frequency - * @wiphy: the wiphy for which we want to process this rule for - * @center_freq: Frequency in KHz for which we want regulatory information for - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. - * @reg_rule: the regulatory rule which we have for this frequency - * - * Use this function to get the regulatory rule for a specific frequency on - * a given wireless device. If the device has a specific regulatory domain - * it wants to follow we respect that unless a country IE has been received - * and processed already. - * - * Returns 0 if it was able to find a valid regulatory rule which does - * apply to the given center_freq otherwise it returns non-zero. It will - * also return -ERANGE if we determine the given center_freq does not even have - * a regulatory rule for a frequency range in the center_freq's band. See - * freq_in_rule_band() for our current definition of a band -- this is purely - * subjective and right now its 802.11 specific. - */ -extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule); - -#endif /* __NET_WIRELESS_H */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 2e9f5c0018ae..736bca450886 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -994,7 +994,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir, return __xfrm_policy_check(sk, ndir, skb, family); return (!net->xfrm.policy_count[dir] && !skb->sp) || - (skb->dst->flags & DST_NOPOLICY) || + (skb_dst(skb)->flags & DST_NOPOLICY) || __xfrm_policy_check(sk, ndir, skb, family); } @@ -1048,7 +1048,7 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) struct net *net = dev_net(skb->dev); return !net->xfrm.policy_count[XFRM_POLICY_OUT] || - (skb->dst->flags & DST_NOXFRM) || + (skb_dst(skb)->flags & DST_NOXFRM) || __xfrm_route_forward(skb, family); } diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 666cc131732e..b2410605b740 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -73,6 +73,7 @@ enum fip_state { * @link: current link status for libfc. * @last_link: last link state reported to libfc. * @map_dest: use the FC_MAP mode for destination MAC addresses. + * @spma: supports SPMA server-provided MACs mode * @dest_addr: MAC address of the selected FC forwarder. * @ctl_src_addr: the native MAC address of our local port. * @data_src_addr: the assigned MAC address for the local port after FLOGI. @@ -104,6 +105,7 @@ struct fcoe_ctlr { u8 link; u8 last_link; u8 map_dest; + u8 spma; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; u8 data_src_addr[ETH_ALEN]; diff --git a/include/trace/events/napi.h b/include/trace/events/napi.h new file mode 100644 index 000000000000..a8989c4547e7 --- /dev/null +++ b/include/trace/events/napi.h @@ -0,0 +1,11 @@ +#ifndef _TRACE_NAPI_H_ +#define _TRACE_NAPI_H_ + +#include +#include + +DECLARE_TRACE(napi_poll, + TP_PROTO(struct napi_struct *napi), + TP_ARGS(napi)); + +#endif diff --git a/net/802/fddi.c b/net/802/fddi.c index 539e6064e6d4..3ef0ab0a543a 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c @@ -185,10 +185,6 @@ static const struct header_ops fddi_header_ops = { static void fddi_setup(struct net_device *dev) { dev->header_ops = &fddi_header_ops; -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev->change_mtu = fddi_change_mtu, -#endif - dev->type = ARPHRD_FDDI; dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ diff --git a/net/802/hippi.c b/net/802/hippi.c index 313b9ebf92ee..cd3e8e929529 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c @@ -193,11 +193,6 @@ static const struct header_ops hippi_header_ops = { static void hippi_setup(struct net_device *dev) { -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev->change_mtu = hippi_change_mtu; - dev->set_mac_address = hippi_mac_addr; - dev->neigh_setup = hippi_neigh_setup_dev; -#endif dev->header_ops = &hippi_header_ops; /* diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index d1e10546eb85..fe649081fbdc 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -378,13 +378,13 @@ static void vlan_sync_address(struct net_device *dev, * the new address */ if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && !compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) - dev_unicast_delete(dev, vlandev->dev_addr, ETH_ALEN); + dev_unicast_delete(dev, vlandev->dev_addr); /* vlan address was equal to the old address and is different from * the new address */ if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) - dev_unicast_add(dev, vlandev->dev_addr, ETH_ALEN); + dev_unicast_add(dev, vlandev->dev_addr); memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); } @@ -758,7 +758,7 @@ static void __exit vlan_cleanup_module(void) BUG_ON(!hlist_empty(&vlan_group_hash[i])); unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops); - synchronize_net(); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ vlan_gvrp_uninit(); } diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index c67fe6f75653..7f7de1a04de6 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -114,9 +114,9 @@ int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, EXPORT_SYMBOL(vlan_gro_receive); int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, - unsigned int vlan_tci, struct napi_gro_fraginfo *info) + unsigned int vlan_tci) { - struct sk_buff *skb = napi_fraginfo_skb(napi, info); + struct sk_buff *skb = napi_frags_skb(napi); if (!skb) return NET_RX_DROP; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b4b9068e55a7..96bad8f233e2 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -290,7 +290,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = &dev->stats; + struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); /* Handle non-VLAN frames if they are sent to us, for example by DHCP. @@ -309,7 +309,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_put_tag(skb, vlan_tci); if (!skb) { - stats->tx_dropped++; + txq->tx_dropped++; return NETDEV_TX_OK; } @@ -317,8 +317,8 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_dev_info(dev)->cnt_inc_headroom_on_tx++; } - stats->tx_packets++; - stats->tx_bytes += skb->len; + txq->tx_packets++; + txq->tx_bytes += skb->len; skb->dev = vlan_dev_info(dev)->real_dev; dev_queue_xmit(skb); @@ -328,15 +328,15 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = &dev->stats; + struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); u16 vlan_tci; vlan_tci = vlan_dev_info(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, vlan_tci); - stats->tx_packets++; - stats->tx_bytes += skb->len; + txq->tx_packets++; + txq->tx_bytes += skb->len; skb->dev = vlan_dev_info(dev)->real_dev; dev_queue_xmit(skb); @@ -441,7 +441,7 @@ static int vlan_dev_open(struct net_device *dev) return -ENETDOWN; if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { - err = dev_unicast_add(real_dev, dev->dev_addr, ETH_ALEN); + err = dev_unicast_add(real_dev, dev->dev_addr); if (err < 0) goto out; } @@ -470,7 +470,7 @@ static int vlan_dev_open(struct net_device *dev) dev_set_allmulti(real_dev, -1); del_unicast: if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) - dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(real_dev, dev->dev_addr); out: netif_carrier_off(dev); return err; @@ -492,7 +492,7 @@ static int vlan_dev_stop(struct net_device *dev) dev_set_promiscuity(real_dev, -1); if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) - dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); + dev_unicast_delete(real_dev, dev->dev_addr); netif_carrier_off(dev); return 0; @@ -511,13 +511,13 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p) goto out; if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) { - err = dev_unicast_add(real_dev, addr->sa_data, ETH_ALEN); + err = dev_unicast_add(real_dev, addr->sa_data); if (err < 0) return err; } if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) - dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(real_dev, dev->dev_addr); out: memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -644,7 +644,6 @@ static int vlan_dev_init(struct net_device *dev) dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; dev->netdev_ops = &vlan_netdev_ops; } - netdev_resync_ops(dev); if (is_vlan_dev(real_dev)) subclass = 1; @@ -671,13 +670,7 @@ static int vlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - struct net_device *real_dev = vlan->real_dev; - - if (!real_dev->ethtool_ops || - !real_dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - - return real_dev->ethtool_ops->get_settings(real_dev, cmd); + return dev_ethtool_get_settings(vlan->real_dev, cmd); } static void vlan_ethtool_get_drvinfo(struct net_device *dev, @@ -691,24 +684,13 @@ static void vlan_ethtool_get_drvinfo(struct net_device *dev, static u32 vlan_ethtool_get_rx_csum(struct net_device *dev) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - struct net_device *real_dev = vlan->real_dev; - - if (real_dev->ethtool_ops == NULL || - real_dev->ethtool_ops->get_rx_csum == NULL) - return 0; - return real_dev->ethtool_ops->get_rx_csum(real_dev); + return dev_ethtool_get_rx_csum(vlan->real_dev); } static u32 vlan_ethtool_get_flags(struct net_device *dev) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - struct net_device *real_dev = vlan->real_dev; - - if (!(real_dev->features & NETIF_F_HW_VLAN_RX) || - real_dev->ethtool_ops == NULL || - real_dev->ethtool_ops->get_flags == NULL) - return 0; - return real_dev->ethtool_ops->get_flags(real_dev); + return dev_ethtool_get_flags(vlan->real_dev); } static const struct ethtool_ops vlan_ethtool_ops = { @@ -756,6 +738,7 @@ void vlan_setup(struct net_device *dev) ether_setup(dev); dev->priv_flags |= IFF_802_1Q_VLAN; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; dev->tx_queue_len = 0; dev->netdev_ops = &vlan_netdev_ops; diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index 3628e0a81b40..b55a091a33df 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -279,13 +279,14 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) { struct net_device *vlandev = (struct net_device *) seq->private; const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); - struct net_device_stats *stats = &vlandev->stats; + const struct net_device_stats *stats; static const char fmt[] = "%30s %12lu\n"; int i; if (!is_vlan_dev(vlandev)) return 0; + stats = dev_get_stats(vlandev); seq_printf(seq, "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", vlandev->name, dev_info->vlan_id, diff --git a/net/Kconfig b/net/Kconfig index c19f549c8e74..7051b9710675 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -179,6 +179,7 @@ source "net/lapb/Kconfig" source "net/econet/Kconfig" source "net/wanrouter/Kconfig" source "net/phonet/Kconfig" +source "net/ieee802154/Kconfig" source "net/sched/Kconfig" source "net/dcb/Kconfig" diff --git a/net/Makefile b/net/Makefile index 9e00a55a901b..ba324aefda73 100644 --- a/net/Makefile +++ b/net/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_NET_9P) += 9p/ ifneq ($(CONFIG_DCB),) obj-y += dcb/ endif +obj-y += ieee802154/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index d6a9243641af..b603cbacdc58 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -939,6 +939,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, int len, unsigned long sum) { int start = skb_headlen(skb); + struct sk_buff *frag_iter; int i, copy; /* checksum stuff in header space */ @@ -977,26 +978,22 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - sum = atalk_sum_skb(list, offset - start, - copy, sum); - if ((len -= copy) == 0) - return sum; - offset += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + sum = atalk_sum_skb(frag_iter, offset - start, + copy, sum); + if ((len -= copy) == 0) + return sum; + offset += copy; } + start = end; } BUG_ON(len > 0); diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c index 72277d70c980..6c8016f61866 100644 --- a/net/appletalk/dev.c +++ b/net/appletalk/dev.c @@ -9,21 +9,10 @@ #include #include -#ifdef CONFIG_COMPAT_NET_DEV_OPS -static int ltalk_change_mtu(struct net_device *dev, int mtu) -{ - return -EINVAL; -} -#endif - static void ltalk_setup(struct net_device *dev) { /* Fill in the fields of the device structure with localtalk-generic values. */ -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev->change_mtu = ltalk_change_mtu; -#endif - dev->type = ARPHRD_LOCALTLK; dev->hard_header_len = LTALK_HLEN; dev->mtu = LTALK_MTU; diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 3100a8940afc..2912665fc58c 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -228,7 +228,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) struct br2684_dev *brdev = BRPRIV(dev); struct br2684_vcc *brvcc; - pr_debug("br2684_start_xmit, skb->dst=%p\n", skb->dst); + pr_debug("br2684_start_xmit, skb_dst(skb)=%p\n", skb_dst(skb)); read_lock(&devs_lock); brvcc = pick_outgoing_vcc(skb, brdev); if (brvcc == NULL) { @@ -445,9 +445,10 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) */ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) { + struct sk_buff_head queue; int err; struct br2684_vcc *brvcc; - struct sk_buff *skb; + struct sk_buff *skb, *tmp; struct sk_buff_head *rq; struct br2684_dev *brdev; struct net_device *net_dev; @@ -505,29 +506,20 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) barrier(); atmvcc->push = br2684_push; + __skb_queue_head_init(&queue); rq = &sk_atm(atmvcc)->sk_receive_queue; spin_lock_irqsave(&rq->lock, flags); - if (skb_queue_empty(rq)) { - skb = NULL; - } else { - /* NULL terminate the list. */ - rq->prev->next = NULL; - skb = rq->next; - } - rq->prev = rq->next = (struct sk_buff *)rq; - rq->qlen = 0; + skb_queue_splice_init(rq, &queue); spin_unlock_irqrestore(&rq->lock, flags); - while (skb) { - struct sk_buff *next = skb->next; + skb_queue_walk_safe(&queue, skb, tmp) { + struct net_device *dev = skb->dev; + + dev->stats.rx_bytes -= skb->len; + dev->stats.rx_packets--; - skb->next = skb->prev = NULL; br2684_push(atmvcc, skb); - skb->dev->stats.rx_bytes -= skb->len; - skb->dev->stats.rx_packets--; - - skb = next; } __module_get(THIS_MODULE); return 0; diff --git a/net/atm/clip.c b/net/atm/clip.c index 3dc0a3a42a57..e65a3b1477f8 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -369,16 +369,16 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; pr_debug("clip_start_xmit (skb %p)\n", skb); - if (!skb->dst) { - printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); + if (!skb_dst(skb)) { + printk(KERN_ERR "clip_start_xmit: skb_dst(skb) == NULL\n"); dev_kfree_skb(skb); dev->stats.tx_dropped++; return 0; } - if (!skb->dst->neighbour) { + if (!skb_dst(skb)->neighbour) { #if 0 - skb->dst->neighbour = clip_find_neighbour(skb->dst, 1); - if (!skb->dst->neighbour) { + skb_dst(skb)->neighbour = clip_find_neighbour(skb_dst(skb), 1); + if (!skb_dst(skb)->neighbour) { dev_kfree_skb(skb); /* lost that one */ dev->stats.tx_dropped++; return 0; @@ -389,7 +389,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_dropped++; return 0; } - entry = NEIGH2ENTRY(skb->dst->neighbour); + entry = NEIGH2ENTRY(skb_dst(skb)->neighbour); if (!entry->vccs) { if (time_after(jiffies, entry->expires)) { /* should be resolved */ @@ -406,7 +406,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) } pr_debug("neigh %p, vccs %p\n", entry, entry->vccs); ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc; - pr_debug("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc); + pr_debug("using neighbour %p, vcc %p\n", skb_dst(skb)->neighbour, vcc); if (entry->vccs->encap) { void *here; @@ -445,9 +445,9 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) static int clip_mkip(struct atm_vcc *vcc, int timeout) { + struct sk_buff_head *rq, queue; struct clip_vcc *clip_vcc; - struct sk_buff *skb; - struct sk_buff_head *rq; + struct sk_buff *skb, *tmp; unsigned long flags; if (!vcc->push) @@ -469,39 +469,28 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) vcc->push = clip_push; vcc->pop = clip_pop; + __skb_queue_head_init(&queue); rq = &sk_atm(vcc)->sk_receive_queue; spin_lock_irqsave(&rq->lock, flags); - if (skb_queue_empty(rq)) { - skb = NULL; - } else { - /* NULL terminate the list. */ - rq->prev->next = NULL; - skb = rq->next; - } - rq->prev = rq->next = (struct sk_buff *)rq; - rq->qlen = 0; + skb_queue_splice_init(rq, &queue); spin_unlock_irqrestore(&rq->lock, flags); /* re-process everything received between connection setup and MKIP */ - while (skb) { - struct sk_buff *next = skb->next; - - skb->next = skb->prev = NULL; + skb_queue_walk_safe(&queue, skb, tmp) { if (!clip_devs) { atm_return(vcc, skb->truesize); kfree_skb(skb); } else { + struct net_device *dev = skb->dev; unsigned int len = skb->len; skb_get(skb); clip_push(vcc, skb); - skb->dev->stats.rx_packets--; - skb->dev->stats.rx_bytes -= len; + dev->stats.rx_packets--; + dev->stats.rx_bytes -= len; kfree_skb(skb); } - - skb = next; } return 0; } @@ -568,6 +557,7 @@ static void clip_setup(struct net_device *dev) /* without any more elaborate queuing. 100 is a reasonable */ /* compromise between decent burst-tolerance and protection */ /* against memory hogs. */ + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } static int clip_create(int number) diff --git a/net/atm/lec.c b/net/atm/lec.c index 199b6bb79f42..ff2e594dca9b 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -34,7 +34,6 @@ /* Proxy LEC knows about bridging */ #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -#include #include "../bridge/br_private.h" static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; @@ -271,7 +270,8 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) printk("%s:No lecd attached\n", dev->name); dev->stats.tx_errors++; netif_stop_queue(dev); - return -EUNATCH; + kfree_skb(skb); + return NETDEV_TX_OK; } pr_debug("skbuff head:%lx data:%lx tail:%lx end:%lx\n", @@ -518,18 +518,14 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) case l_should_bridge: #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) { - struct net_bridge_fdb_entry *f; - pr_debug("%s: bridge zeppelin asks about %pM\n", dev->name, mesg->content.proxy.mac_addr); - if (br_fdb_get_hook == NULL || dev->br_port == NULL) + if (br_fdb_test_addr_hook == NULL) break; - f = br_fdb_get_hook(dev->br_port->br, - mesg->content.proxy.mac_addr); - if (f != NULL && f->dst->dev != dev - && f->dst->state == BR_STATE_FORWARDING) { + if (br_fdb_test_addr_hook(dev, + mesg->content.proxy.mac_addr)) { /* hit from bridge table, send LE_ARP_RESPONSE */ struct sk_buff *skb2; struct sock *sk; @@ -540,10 +536,8 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); - if (skb2 == NULL) { - br_fdb_put_hook(f); + if (skb2 == NULL) break; - } skb2->len = sizeof(struct atmlec_msg); skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); @@ -552,8 +546,6 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) skb_queue_tail(&sk->sk_receive_queue, skb2); sk->sk_data_ready(sk, skb2->len); } - if (f != NULL) - br_fdb_put_hook(f); } #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ break; diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 7725da95a767..59fdb1d2e8ed 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -3,8 +3,9 @@ # menuconfig BT - depends on NET && !S390 tristate "Bluetooth subsystem support" + depends on NET && !S390 + depends on RFKILL || !RFKILL help Bluetooth is low-cost, low-power, short-range wireless technology. It was designed as a replacement for cables and other short-range diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 78958c0f9a40..97f8d68d574d 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c @@ -382,7 +382,7 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl) BT_DBG("ctrl %p", ctrl); - capi_ctr_reseted(ctrl); + capi_ctr_down(ctrl); atomic_inc(&session->terminate); cmtp_schedule(session); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cd061510b6bd..406ad07cdea1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -476,6 +477,11 @@ int hci_dev_open(__u16 dev) hci_req_lock(hdev); + if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { + ret = -ERFKILL; + goto done; + } + if (test_bit(HCI_UP, &hdev->flags)) { ret = -EALREADY; goto done; @@ -813,6 +819,24 @@ int hci_get_dev_info(void __user *arg) /* ---- Interface to HCI drivers ---- */ +static int hci_rfkill_set_block(void *data, bool blocked) +{ + struct hci_dev *hdev = data; + + BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); + + if (!blocked) + return 0; + + hci_dev_do_close(hdev); + + return 0; +} + +static const struct rfkill_ops hci_rfkill_ops = { + .set_block = hci_rfkill_set_block, +}; + /* Alloc HCI device */ struct hci_dev *hci_alloc_dev(void) { @@ -844,7 +868,8 @@ int hci_register_dev(struct hci_dev *hdev) struct list_head *head = &hci_dev_list, *p; int i, id = 0; - BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); + BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, + hdev->type, hdev->owner); if (!hdev->open || !hdev->close || !hdev->destruct) return -EINVAL; @@ -900,6 +925,15 @@ int hci_register_dev(struct hci_dev *hdev) hci_register_sysfs(hdev); + hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, + RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev); + if (hdev->rfkill) { + if (rfkill_register(hdev->rfkill) < 0) { + rfkill_destroy(hdev->rfkill); + hdev->rfkill = NULL; + } + } + hci_notify(hdev, HCI_DEV_REG); return id; @@ -924,6 +958,11 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_notify(hdev, HCI_DEV_UNREG); + if (hdev->rfkill) { + rfkill_unregister(hdev->rfkill); + rfkill_destroy(hdev->rfkill); + } + hci_unregister_sysfs(hdev); __hci_dev_put(hdev); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index ca4d3b40d5ce..bd0a4c1bced0 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -40,10 +40,10 @@ #include #include #include +#include #include #include -#include #include #include @@ -52,7 +52,7 @@ #define VERSION "2.13" -static u32 l2cap_feat_mask = 0x0080; +static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; static u8 l2cap_fixed_chan[8] = { 0x02, }; static const struct proto_ops l2cap_sock_ops; @@ -134,7 +134,8 @@ static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 struct sock *s; read_lock(&l->lock); s = __l2cap_get_chan_by_scid(l, cid); - if (s) bh_lock_sock(s); + if (s) + bh_lock_sock(s); read_unlock(&l->lock); return s; } @@ -154,17 +155,18 @@ static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 struct sock *s; read_lock(&l->lock); s = __l2cap_get_chan_by_ident(l, ident); - if (s) bh_lock_sock(s); + if (s) + bh_lock_sock(s); read_unlock(&l->lock); return s; } static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) { - u16 cid = 0x0040; + u16 cid = L2CAP_CID_DYN_START; - for (; cid < 0xffff; cid++) { - if(!__l2cap_get_chan_by_scid(l, cid)) + for (; cid < L2CAP_CID_DYN_END; cid++) { + if (!__l2cap_get_chan_by_scid(l, cid)) return cid; } @@ -204,7 +206,8 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so { struct l2cap_chan_list *l = &conn->chan_list; - BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); + BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, + l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); conn->disc_reason = 0x13; @@ -215,13 +218,13 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so l2cap_pi(sk)->scid = l2cap_alloc_cid(l); } else if (sk->sk_type == SOCK_DGRAM) { /* Connectionless socket */ - l2cap_pi(sk)->scid = 0x0002; - l2cap_pi(sk)->dcid = 0x0002; + l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS; + l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS; l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; } else { /* Raw socket can send/recv signalling messages only */ - l2cap_pi(sk)->scid = 0x0001; - l2cap_pi(sk)->dcid = 0x0001; + l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING; + l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING; l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; } @@ -272,7 +275,7 @@ static inline int l2cap_check_security(struct sock *sk) if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) auth_type = HCI_AT_NO_BONDING_MITM; else - auth_type = HCI_AT_NO_BONDING; + auth_type = HCI_AT_NO_BONDING; if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; @@ -588,7 +591,8 @@ static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t struct sock *s; read_lock(&l2cap_sk_list.lock); s = __l2cap_get_sock_by_psm(state, psm, src); - if (s) bh_lock_sock(s); + if (s) + bh_lock_sock(s); read_unlock(&l2cap_sk_list.lock); return s; } @@ -808,7 +812,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) goto done; } - if (la.l2_psm && btohs(la.l2_psm) < 0x1001 && + if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) { err = -EACCES; goto done; @@ -825,7 +829,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) l2cap_pi(sk)->sport = la.l2_psm; sk->sk_state = BT_BOUND; - if (btohs(la.l2_psm) == 0x0001 || btohs(la.l2_psm) == 0x0003) + if (__le16_to_cpu(la.l2_psm) == 0x0001 || + __le16_to_cpu(la.l2_psm) == 0x0003) l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; } @@ -844,12 +849,13 @@ static int l2cap_do_connect(struct sock *sk) struct hci_conn *hcon; struct hci_dev *hdev; __u8 auth_type; - int err = 0; + int err; BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); - if (!(hdev = hci_get_route(dst, src))) + hdev = hci_get_route(dst, src); + if (!hdev) return -EHOSTUNREACH; hci_dev_lock_bh(hdev); @@ -950,7 +956,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al goto done; } - switch(sk->sk_state) { + switch (sk->sk_state) { case BT_CONNECT: case BT_CONNECT2: case BT_CONFIG: @@ -975,7 +981,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); l2cap_pi(sk)->psm = la.l2_psm; - if ((err = l2cap_do_connect(sk))) + err = l2cap_do_connect(sk); + if (err) goto done; wait: @@ -1009,9 +1016,9 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) write_lock_bh(&l2cap_sk_list.lock); for (psm = 0x1001; psm < 0x1100; psm += 2) - if (!__l2cap_get_sock_by_addr(htobs(psm), src)) { - l2cap_pi(sk)->psm = htobs(psm); - l2cap_pi(sk)->sport = htobs(psm); + if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { + l2cap_pi(sk)->psm = cpu_to_le16(psm); + l2cap_pi(sk)->sport = cpu_to_le16(psm); err = 0; break; } @@ -1100,11 +1107,11 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l if (peer) { la->l2_psm = l2cap_pi(sk)->psm; bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); - la->l2_cid = htobs(l2cap_pi(sk)->dcid); + la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid); } else { la->l2_psm = l2cap_pi(sk)->sport; bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); - la->l2_cid = htobs(l2cap_pi(sk)->scid); + la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid); } return 0; @@ -1114,7 +1121,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb, **frag; - int err, hlen, count, sent=0; + int err, hlen, count, sent = 0; struct l2cap_hdr *lh; BT_DBG("sk %p len %d", sk, len); @@ -1167,8 +1174,8 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len) frag = &(*frag)->next; } - - if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0) + err = hci_send_acl(conn->hcon, skb, 0); + if (err < 0) goto fail; return sent; @@ -1556,7 +1563,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) { struct l2cap_chan_list *l = &conn->chan_list; struct sk_buff *nskb; - struct sock * sk; + struct sock *sk; BT_DBG("conn %p", conn); @@ -1568,8 +1575,8 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) /* Don't send frame to the socket it came from */ if (skb->sk == sk) continue; - - if (!(nskb = skb_clone(skb, GFP_ATOMIC))) + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) continue; if (sock_queue_rcv_skb(sk, nskb)) @@ -1587,7 +1594,8 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, struct l2cap_hdr *lh; int len, count; - BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", conn, code, ident, dlen); + BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", + conn, code, ident, dlen); len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; count = min_t(unsigned int, conn->mtu, len); @@ -1598,7 +1606,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); - lh->cid = cpu_to_le16(0x0001); + lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); cmd->code = code; @@ -1739,8 +1747,8 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&req, &type, &olen, &val); - hint = type & 0x80; - type &= 0x7f; + hint = type & L2CAP_CONF_HINT; + type &= L2CAP_CONF_MASK; switch (type) { case L2CAP_CONF_MTU: @@ -1966,10 +1974,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); if (scid) { - if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) + sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!sk) return 0; } else { - if (!(sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident))) + sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); + if (!sk) return 0; } @@ -2012,7 +2022,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); - if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) + sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + if (!sk) return -ENOENT; if (sk->sk_state == BT_DISCONN) @@ -2079,9 +2090,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr flags = __le16_to_cpu(rsp->flags); result = __le16_to_cpu(rsp->result); - BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result); + BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", + scid, flags, result); - if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) + sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!sk) return 0; switch (result) { @@ -2142,7 +2155,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); - if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) + sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + if (!sk) return 0; rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); @@ -2169,7 +2183,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); - if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) + sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!sk) return 0; l2cap_chan_del(sk, 0); @@ -2230,7 +2245,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm if (type == L2CAP_IT_FEAT_MASK) { conn->feat_mask = get_unaligned_le32(rsp->data); - if (conn->feat_mask & 0x0080) { + if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { struct l2cap_info_req req; req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); @@ -2403,7 +2418,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str kfree_skb(skb); done: - if (sk) bh_unlock_sock(sk); + if (sk) + bh_unlock_sock(sk); return 0; } @@ -2420,11 +2436,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) BT_DBG("len %d, cid 0x%4.4x", len, cid); switch (cid) { - case 0x0001: + case L2CAP_CID_SIGNALING: l2cap_sig_channel(conn, skb); break; - case 0x0002: + case L2CAP_CID_CONN_LESS: psm = get_unaligned((__le16 *) skb->data); skb_pull(skb, 2); l2cap_conless_channel(conn, psm, skb); @@ -2650,7 +2666,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl } /* Allocate skb for the complete frame (with header) */ - if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC))) + conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); + if (!conn->rx_skb) goto drop; skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), @@ -2704,13 +2721,13 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid, - pi->imtu, pi->omtu, pi->sec_level); + sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, + pi->dcid, pi->imtu, pi->omtu, pi->sec_level); } read_unlock_bh(&l2cap_sk_list.lock); - return (str - buf); + return str - buf; } static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 374536e050aa..e50566ebf9f9 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -679,7 +679,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst bacpy(&addr.l2_bdaddr, dst); addr.l2_family = AF_BLUETOOTH; - addr.l2_psm = htobs(RFCOMM_PSM); + addr.l2_psm = cpu_to_le16(RFCOMM_PSM); addr.l2_cid = 0; *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); if (*err == 0 || *err == -EINPROGRESS) @@ -852,9 +852,9 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d } if (cr && channel_mtu >= 0) - pn->mtu = htobs(channel_mtu); + pn->mtu = cpu_to_le16(channel_mtu); else - pn->mtu = htobs(d->mtu); + pn->mtu = cpu_to_le16(d->mtu); *ptr = __fcs(buf); ptr++; @@ -1056,7 +1056,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) if (len > 127) { hdr = (void *) skb_push(skb, 4); - put_unaligned(htobs(__len16(len)), (__le16 *) &hdr->len); + put_unaligned(cpu_to_le16(__len16(len)), (__le16 *) &hdr->len); } else { hdr = (void *) skb_push(skb, 3); hdr->len = __len8(len); @@ -1289,7 +1289,7 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) d->priority = pn->priority; - d->mtu = btohs(pn->mtu); + d->mtu = __le16_to_cpu(pn->mtu); if (cr && d->mtu > s->mtu) d->mtu = s->mtu; @@ -1922,7 +1922,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) /* Bind socket */ bacpy(&addr.l2_bdaddr, ba); addr.l2_family = AF_BLUETOOTH; - addr.l2_psm = htobs(RFCOMM_PSM); + addr.l2_psm = cpu_to_le16(RFCOMM_PSM); addr.l2_cid = 0; err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { diff --git a/net/bridge/br.c b/net/bridge/br.c index 4d2c1f1cb524..9aac5213105a 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -65,8 +65,9 @@ static int __init br_init(void) brioctl_set(br_ioctl_deviceless_stub); br_handle_frame_hook = br_handle_frame; - br_fdb_get_hook = br_fdb_get; - br_fdb_put_hook = br_fdb_put; +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + br_fdb_test_addr_hook = br_fdb_test_addr; +#endif return 0; err_out4: @@ -95,8 +96,9 @@ static void __exit br_deinit(void) synchronize_net(); br_netfilter_fini(); - br_fdb_get_hook = NULL; - br_fdb_put_hook = NULL; +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + br_fdb_test_addr_hook = NULL; +#endif br_handle_frame_hook = NULL; br_fdb_fini(); diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index a48f5efdb6bf..57bf05c353bc 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -71,10 +71,17 @@ static inline int br_mac_hash(const unsigned char *mac) return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1); } +static void fdb_rcu_free(struct rcu_head *head) +{ + struct net_bridge_fdb_entry *ent + = container_of(head, struct net_bridge_fdb_entry, rcu); + kmem_cache_free(br_fdb_cache, ent); +} + static inline void fdb_delete(struct net_bridge_fdb_entry *f) { hlist_del_rcu(&f->hlist); - br_fdb_put(f); + call_rcu(&f->rcu, fdb_rcu_free); } void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) @@ -226,33 +233,26 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, return NULL; } -/* Interface used by ATM hook that keeps a ref count */ -struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, - unsigned char *addr) +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +/* Interface used by ATM LANE hook to test + * if an addr is on some other bridge port */ +int br_fdb_test_addr(struct net_device *dev, unsigned char *addr) { struct net_bridge_fdb_entry *fdb; + int ret; + + if (!dev->br_port) + return 0; rcu_read_lock(); - fdb = __br_fdb_get(br, addr); - if (fdb && !atomic_inc_not_zero(&fdb->use_count)) - fdb = NULL; + fdb = __br_fdb_get(dev->br_port->br, addr); + ret = fdb && fdb->dst->dev != dev && + fdb->dst->state == BR_STATE_FORWARDING; rcu_read_unlock(); - return fdb; -} -static void fdb_rcu_free(struct rcu_head *head) -{ - struct net_bridge_fdb_entry *ent - = container_of(head, struct net_bridge_fdb_entry, rcu); - kmem_cache_free(br_fdb_cache, ent); -} - -/* Set entry up for deletion with RCU */ -void br_fdb_put(struct net_bridge_fdb_entry *ent) -{ - if (atomic_dec_and_test(&ent->use_count)) - call_rcu(&ent->rcu, fdb_rcu_free); + return ret; } +#endif /* CONFIG_ATM_LANE */ /* * Fill buffer with forwarding table records in @@ -326,7 +326,6 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); if (fdb) { memcpy(fdb->addr.addr, addr, ETH_ALEN); - atomic_set(&fdb->use_count, 1); hlist_add_head_rcu(&fdb->hlist, head); fdb->dst = source; @@ -398,7 +397,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, if (unlikely(fdb->is_local)) { if (net_ratelimit()) printk(KERN_WARNING "%s: received packet with " - " own address as source address\n", + "own address as source address\n", source->dev->name); } else { /* fastpath: update of existing entry */ diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e4a418fcb35b..d22f611e4004 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -228,6 +228,7 @@ int nf_bridge_copy_header(struct sk_buff *skb) static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = skb->nf_bridge; + struct rtable *rt; if (nf_bridge->mask & BRNF_PKT_TYPE) { skb->pkt_type = PACKET_OTHERHOST; @@ -235,12 +236,13 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) } nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; - skb->rtable = bridge_parent_rtable(nf_bridge->physindev); - if (!skb->rtable) { + rt = bridge_parent_rtable(nf_bridge->physindev); + if (!rt) { kfree_skb(skb); return 0; } - dst_hold(&skb->rtable->u.dst); + dst_hold(&rt->u.dst); + skb_dst_set(skb, &rt->u.dst); skb->dev = nf_bridge->physindev; nf_bridge_push_encap_header(skb); @@ -320,7 +322,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) skb->dev = bridge_parent(skb->dev); if (skb->dev) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); nf_bridge_pull_encap_header(skb); @@ -338,6 +340,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) struct net_device *dev = skb->dev; struct iphdr *iph = ip_hdr(skb); struct nf_bridge_info *nf_bridge = skb->nf_bridge; + struct rtable *rt; int err; if (nf_bridge->mask & BRNF_PKT_TYPE) { @@ -347,7 +350,6 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; if (dnat_took_place(skb)) { if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { - struct rtable *rt; struct flowi fl = { .nl_u = { .ip4_u = { @@ -373,7 +375,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) /* - Bridged-and-DNAT'ed traffic doesn't * require ip_forwarding. */ if (((struct dst_entry *)rt)->dev == dev) { - skb->dst = (struct dst_entry *)rt; + skb_dst_set(skb, (struct dst_entry *)rt); goto bridged_dnat; } /* we are sure that forwarding is disabled, so printing @@ -387,7 +389,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) kfree_skb(skb); return 0; } else { - if (skb->dst->dev == dev) { + if (skb_dst(skb)->dev == dev) { bridged_dnat: /* Tell br_nf_local_out this is a * bridged frame */ @@ -404,12 +406,13 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) skb->pkt_type = PACKET_HOST; } } else { - skb->rtable = bridge_parent_rtable(nf_bridge->physindev); - if (!skb->rtable) { + rt = bridge_parent_rtable(nf_bridge->physindev); + if (!rt) { kfree_skb(skb); return 0; } - dst_hold(&skb->rtable->u.dst); + dst_hold(&rt->u.dst); + skb_dst_set(skb, &rt->u.dst); } skb->dev = nf_bridge->physindev; @@ -628,10 +631,10 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (skb->rtable && skb->rtable == bridge_parent_rtable(in)) { - dst_release(&skb->rtable->u.dst); - skb->rtable = NULL; - } + struct rtable *rt = skb_rtable(skb); + + if (rt && rt == bridge_parent_rtable(in)) + skb_dst_drop(skb); return NF_ACCEPT; } @@ -846,7 +849,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, return NF_ACCEPT; #ifdef CONFIG_NETFILTER_DEBUG - if (skb->dst == NULL) { + if (skb_dst(skb) == NULL) { printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n"); goto print_error; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b6c3b71974dc..d5b5537272b4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -51,7 +51,6 @@ struct net_bridge_fdb_entry struct net_bridge_port *dst; struct rcu_head rcu; - atomic_t use_count; unsigned long ageing_timer; mac_addr addr; unsigned char is_local; @@ -154,9 +153,7 @@ extern void br_fdb_delete_by_port(struct net_bridge *br, const struct net_bridge_port *p, int do_all); extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, const unsigned char *addr); -extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, - unsigned char *addr); -extern void br_fdb_put(struct net_bridge_fdb_entry *ent); +extern int br_fdb_test_addr(struct net_device *dev, unsigned char *addr); extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count, unsigned long off); extern int br_fdb_insert(struct net_bridge *br, @@ -242,10 +239,9 @@ extern void br_stp_port_timer_init(struct net_bridge_port *p); extern unsigned long br_timer_value(const struct timer_list *timer); /* br.c */ -extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, - unsigned char *addr); -extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); - +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); +#endif /* br_netlink.c */ extern int br_netlink_init(void); diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 603d89248e71..ee4820aa1843 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -172,7 +172,8 @@ static ssize_t store_stp_state(struct device *d, if (endp == buf) return -EINVAL; - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); br_stp_set_enabled(br, val); rtnl_unlock(); diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 02b2d50cce4d..4a3cdf8f3813 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -189,7 +189,8 @@ static ssize_t brport_store(struct kobject * kobj, val = simple_strtoul(buf, &endp, 0); if (endp != buf) { - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); if (p->dev && p->br && brport_attr->store) { spin_lock_bh(&p->br->lock); ret = brport_attr->store(p, val); diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 820252aee81f..37928d5f2840 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -142,6 +142,12 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, return 0; } +static inline __pure +struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry) +{ + return (void *)entry + entry->next_offset; +} + /* Do some firewalling */ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, @@ -164,7 +170,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, mtpar.in = tgpar.in = in; mtpar.out = tgpar.out = out; mtpar.hotdrop = &hotdrop; - tgpar.hooknum = hook; + mtpar.hooknum = tgpar.hooknum = hook; read_lock_bh(&table->lock); private = table->private; @@ -249,8 +255,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, /* jump to a udc */ cs[sp].n = i + 1; cs[sp].chaininfo = chaininfo; - cs[sp].e = (struct ebt_entry *) - (((char *)point) + point->next_offset); + cs[sp].e = ebt_next_entry(point); i = 0; chaininfo = (struct ebt_entries *) (base + verdict); #ifdef CONFIG_NETFILTER_DEBUG @@ -266,8 +271,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, sp++; continue; letscontinue: - point = (struct ebt_entry *) - (((char *)point) + point->next_offset); + point = ebt_next_entry(point); i++; } @@ -787,7 +791,7 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s /* this can't be 0, so the loop test is correct */ cl_s[i].cs.n = pos + 1; pos = 0; - cl_s[i].cs.e = ((void *)e + e->next_offset); + cl_s[i].cs.e = ebt_next_entry(e); e = (struct ebt_entry *)(hlp2->data); nentries = hlp2->nentries; cl_s[i].from = chain_nr; @@ -797,7 +801,7 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s continue; } letscontinue: - e = (void *)e + e->next_offset; + e = ebt_next_entry(e); pos++; } return 0; diff --git a/net/can/af_can.c b/net/can/af_can.c index 10f0528c3bf5..e733725b11d4 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -903,6 +903,8 @@ static __exit void can_exit(void) } spin_unlock(&can_rcvlists_lock); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ + kmem_cache_destroy(rcv_cache); } diff --git a/net/core/datagram.c b/net/core/datagram.c index b01a76abe1d2..58abee1f1df1 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -260,7 +260,9 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) spin_unlock_bh(&sk->sk_receive_queue.lock); } - skb_free_datagram(sk, skb); + kfree_skb(skb); + sk_mem_reclaim_partial(sk); + return err; } @@ -280,6 +282,7 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, { int start = skb_headlen(skb); int i, copy = start - offset; + struct sk_buff *frag_iter; /* Copy header. */ if (copy > 0) { @@ -320,28 +323,24 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - if (skb_copy_datagram_iovec(list, - offset - start, - to, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_datagram_iovec(frag_iter, + offset - start, + to, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; } + start = end; } if (!len) return 0; @@ -351,30 +350,34 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, } /** - * skb_copy_datagram_from_iovec - Copy a datagram from an iovec. + * skb_copy_datagram_const_iovec - Copy a datagram to an iovec. * @skb: buffer to copy - * @offset: offset in the buffer to start copying to - * @from: io vector to copy to - * @len: amount of data to copy to buffer from iovec + * @offset: offset in the buffer to start copying from + * @to: io vector to copy to + * @to_offset: offset in the io vector to start copying to + * @len: amount of data to copy from buffer to iovec * * Returns 0 or -EFAULT. - * Note: the iovec is modified during the copy. + * Note: the iovec is not modified during the copy. */ -int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, - struct iovec *from, int len) +int skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset, + const struct iovec *to, int to_offset, + int len) { int start = skb_headlen(skb); int i, copy = start - offset; + struct sk_buff *frag_iter; /* Copy header. */ if (copy > 0) { if (copy > len) copy = len; - if (memcpy_fromiovec(skb->data + offset, from, copy)) + if (memcpy_toiovecend(to, skb->data + offset, to_offset, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; + to_offset += copy; } /* Copy paged appendix. Hmm... why does this look so complicated? */ @@ -393,8 +396,99 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap(page); - err = memcpy_fromiovec(vaddr + frag->page_offset + - offset - start, from, copy); + err = memcpy_toiovecend(to, vaddr + frag->page_offset + + offset - start, to_offset, copy); + kunmap(page); + if (err) + goto fault; + if (!(len -= copy)) + return 0; + offset += copy; + to_offset += copy; + } + start = end; + } + + skb_walk_frags(skb, frag_iter) { + int end; + + WARN_ON(start > offset + len); + + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_datagram_const_iovec(frag_iter, + offset - start, + to, to_offset, + copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + to_offset += copy; + } + start = end; + } + if (!len) + return 0; + +fault: + return -EFAULT; +} +EXPORT_SYMBOL(skb_copy_datagram_const_iovec); + +/** + * skb_copy_datagram_from_iovec - Copy a datagram from an iovec. + * @skb: buffer to copy + * @offset: offset in the buffer to start copying to + * @from: io vector to copy to + * @from_offset: offset in the io vector to start copying from + * @len: amount of data to copy to buffer from iovec + * + * Returns 0 or -EFAULT. + * Note: the iovec is not modified during the copy. + */ +int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, + const struct iovec *from, int from_offset, + int len) +{ + int start = skb_headlen(skb); + int i, copy = start - offset; + struct sk_buff *frag_iter; + + /* Copy header. */ + if (copy > 0) { + if (copy > len) + copy = len; + if (memcpy_fromiovecend(skb->data + offset, from, from_offset, + copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + from_offset += copy; + } + + /* Copy paged appendix. Hmm... why does this look so complicated? */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + WARN_ON(start > offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + int err; + u8 *vaddr; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; + + if (copy > len) + copy = len; + vaddr = kmap(page); + err = memcpy_fromiovecend(vaddr + frag->page_offset + + offset - start, + from, from_offset, copy); kunmap(page); if (err) goto fault; @@ -402,32 +496,32 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, if (!(len -= copy)) return 0; offset += copy; + from_offset += copy; } start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - if (skb_copy_datagram_from_iovec(list, - offset - start, - from, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_datagram_from_iovec(frag_iter, + offset - start, + from, + from_offset, + copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + from_offset += copy; } + start = end; } if (!len) return 0; @@ -442,8 +536,9 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, __wsum *csump) { int start = skb_headlen(skb); - int pos = 0; int i, copy = start - offset; + struct sk_buff *frag_iter; + int pos = 0; /* Copy header. */ if (copy > 0) { @@ -494,33 +589,29 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list=list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - __wsum csum2 = 0; - if (copy > len) - copy = len; - if (skb_copy_and_csum_datagram(list, - offset - start, - to, copy, - &csum2)) - goto fault; - *csump = csum_block_add(*csump, csum2, pos); - if ((len -= copy) == 0) - return 0; - offset += copy; - to += copy; - pos += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + __wsum csum2 = 0; + if (copy > len) + copy = len; + if (skb_copy_and_csum_datagram(frag_iter, + offset - start, + to, copy, + &csum2)) + goto fault; + *csump = csum_block_add(*csump, csum2, pos); + if ((len -= copy) == 0) + return 0; + offset += copy; + to += copy; + pos += copy; } + start = end; } if (!len) return 0; diff --git a/net/core/dev.c b/net/core/dev.c index e2e9e4af3ace..576a61574a93 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -126,6 +126,7 @@ #include #include #include +#include #include "net-sysfs.h" @@ -268,7 +269,8 @@ static const unsigned short netdev_lock_type[] = ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, ARPHRD_FCFABRIC, ARPHRD_IEEE802_TR, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, - ARPHRD_PHONET_PIPE, ARPHRD_VOID, ARPHRD_NONE}; + ARPHRD_PHONET_PIPE, ARPHRD_IEEE802154, ARPHRD_IEEE802154_PHY, + ARPHRD_VOID, ARPHRD_NONE}; static const char *netdev_lock_name[] = {"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", @@ -285,7 +287,8 @@ static const char *netdev_lock_name[] = "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", "_xmit_FCFABRIC", "_xmit_IEEE802_TR", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", - "_xmit_PHONET_PIPE", "_xmit_VOID", "_xmit_NONE"}; + "_xmit_PHONET_PIPE", "_xmit_IEEE802154", "_xmit_IEEE802154_PHY", + "_xmit_VOID", "_xmit_NONE"}; static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)]; @@ -1047,7 +1050,7 @@ void dev_load(struct net *net, const char *name) int dev_open(struct net_device *dev) { const struct net_device_ops *ops = dev->netdev_ops; - int ret = 0; + int ret; ASSERT_RTNL(); @@ -1064,6 +1067,11 @@ int dev_open(struct net_device *dev) if (!netif_device_present(dev)) return -ENODEV; + ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev); + ret = notifier_to_errno(ret); + if (ret) + return ret; + /* * Call device private open method */ @@ -1688,7 +1696,16 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, goto gso; } + /* + * If device doesnt need skb->dst, release it right now while + * its hot in this cpu cache + */ + if (dev->priv_flags & IFF_XMIT_DST_RELEASE) + skb_dst_drop(skb); + rc = ops->ndo_start_xmit(skb, dev); + if (rc == 0) + txq_trans_update(txq); /* * TODO: if skb_orphan() was called by * dev->hard_start_xmit() (for example, the unmodified @@ -1718,6 +1735,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, skb->next = nskb; return rc; } + txq_trans_update(txq); if (unlikely(netif_tx_queue_stopped(txq) && skb->next)) return NETDEV_TX_BUSY; } while (skb->next); @@ -1735,8 +1753,12 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) { u32 hash; - if (skb_rx_queue_recorded(skb)) - return skb_get_rx_queue(skb) % dev->real_num_tx_queues; + if (skb_rx_queue_recorded(skb)) { + hash = skb_get_rx_queue(skb); + while (unlikely (hash >= dev->real_num_tx_queues)) + hash -= dev->real_num_tx_queues; + return hash; + } if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; @@ -1800,7 +1822,7 @@ int dev_queue_xmit(struct sk_buff *skb) if (netif_needs_gso(dev, skb)) goto gso; - if (skb_shinfo(skb)->frag_list && + if (skb_has_frags(skb) && !(dev->features & NETIF_F_FRAGLIST) && __skb_linearize(skb)) goto out_kfree_skb; @@ -2049,11 +2071,13 @@ static inline int deliver_skb(struct sk_buff *skb, } #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) -/* These hooks defined here for ATM */ -struct net_bridge; -struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, - unsigned char *addr); -void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly; + +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +/* This hook is defined here for ATM LANE */ +int (*br_fdb_test_addr_hook)(struct net_device *dev, + unsigned char *addr) __read_mostly; +EXPORT_SYMBOL(br_fdb_test_addr_hook); +#endif /* * If bridge module is loaded call bridging hook. @@ -2061,6 +2085,8 @@ void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly; */ struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff *skb) __read_mostly; +EXPORT_SYMBOL(br_handle_frame_hook); + static inline struct sk_buff *handle_bridge(struct sk_buff *skb, struct packet_type **pt_prev, int *ret, struct net_device *orig_dev) @@ -2374,26 +2400,6 @@ void napi_gro_flush(struct napi_struct *napi) } EXPORT_SYMBOL(napi_gro_flush); -void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) -{ - unsigned int offset = skb_gro_offset(skb); - - hlen += offset; - if (hlen <= skb_headlen(skb)) - return skb->data + offset; - - if (unlikely(!skb_shinfo(skb)->nr_frags || - skb_shinfo(skb)->frags[0].size <= - hlen - skb_headlen(skb) || - PageHighMem(skb_shinfo(skb)->frags[0].page))) - return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; - - return page_address(skb_shinfo(skb)->frags[0].page) + - skb_shinfo(skb)->frags[0].page_offset + - offset - skb_headlen(skb); -} -EXPORT_SYMBOL(skb_gro_header); - int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff **pp = NULL; @@ -2407,7 +2413,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) if (!(skb->dev->features & NETIF_F_GRO)) goto normal; - if (skb_is_gso(skb) || skb_shinfo(skb)->frag_list) + if (skb_is_gso(skb) || skb_has_frags(skb)) goto normal; rcu_read_lock(); @@ -2456,10 +2462,25 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) ret = GRO_HELD; pull: - if (unlikely(!pskb_may_pull(skb, skb_gro_offset(skb)))) { - if (napi->gro_list == skb) - napi->gro_list = skb->next; - ret = GRO_DROP; + if (skb_headlen(skb) < skb_gro_offset(skb)) { + int grow = skb_gro_offset(skb) - skb_headlen(skb); + + BUG_ON(skb->end - skb->tail < grow); + + memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow); + + skb->tail += grow; + skb->data_len -= grow; + + skb_shinfo(skb)->frags[0].page_offset += grow; + skb_shinfo(skb)->frags[0].size -= grow; + + if (unlikely(!skb_shinfo(skb)->frags[0].size)) { + put_page(skb_shinfo(skb)->frags[0].page); + memmove(skb_shinfo(skb)->frags, + skb_shinfo(skb)->frags + 1, + --skb_shinfo(skb)->nr_frags); + } } ok: @@ -2509,6 +2530,22 @@ int napi_skb_finish(int ret, struct sk_buff *skb) } EXPORT_SYMBOL(napi_skb_finish); +void skb_gro_reset_offset(struct sk_buff *skb) +{ + NAPI_GRO_CB(skb)->data_offset = 0; + NAPI_GRO_CB(skb)->frag0 = NULL; + NAPI_GRO_CB(skb)->frag0_len = 0; + + if (skb->mac_header == skb->tail && + !PageHighMem(skb_shinfo(skb)->frags[0].page)) { + NAPI_GRO_CB(skb)->frag0 = + page_address(skb_shinfo(skb)->frags[0].page) + + skb_shinfo(skb)->frags[0].page_offset; + NAPI_GRO_CB(skb)->frag0_len = skb_shinfo(skb)->frags[0].size; + } +} +EXPORT_SYMBOL(skb_gro_reset_offset); + int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { skb_gro_reset_offset(skb); @@ -2526,16 +2563,10 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) } EXPORT_SYMBOL(napi_reuse_skb); -struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, - struct napi_gro_fraginfo *info) +struct sk_buff *napi_get_frags(struct napi_struct *napi) { struct net_device *dev = napi->dev; struct sk_buff *skb = napi->skb; - struct ethhdr *eth; - skb_frag_t *frag; - int i; - - napi->skb = NULL; if (!skb) { skb = netdev_alloc_skb(dev, GRO_MAX_HEAD + NET_IP_ALIGN); @@ -2543,47 +2574,14 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, goto out; skb_reserve(skb, NET_IP_ALIGN); + + napi->skb = skb; } - BUG_ON(info->nr_frags > MAX_SKB_FRAGS); - frag = info->frags; - - for (i = 0; i < info->nr_frags; i++) { - skb_fill_page_desc(skb, i, frag->page, frag->page_offset, - frag->size); - frag++; - } - skb_shinfo(skb)->nr_frags = info->nr_frags; - - skb->data_len = info->len; - skb->len += info->len; - skb->truesize += info->len; - - skb_reset_mac_header(skb); - skb_gro_reset_offset(skb); - - eth = skb_gro_header(skb, sizeof(*eth)); - if (!eth) { - napi_reuse_skb(napi, skb); - skb = NULL; - goto out; - } - - skb_gro_pull(skb, sizeof(*eth)); - - /* - * This works because the only protocols we care about don't require - * special handling. We'll fix it up properly at the end. - */ - skb->protocol = eth->h_proto; - - skb->ip_summed = info->ip_summed; - skb->csum = info->csum; - out: return skb; } -EXPORT_SYMBOL(napi_fraginfo_skb); +EXPORT_SYMBOL(napi_get_frags); int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) { @@ -2613,9 +2611,46 @@ int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) } EXPORT_SYMBOL(napi_frags_finish); -int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) +struct sk_buff *napi_frags_skb(struct napi_struct *napi) { - struct sk_buff *skb = napi_fraginfo_skb(napi, info); + struct sk_buff *skb = napi->skb; + struct ethhdr *eth; + unsigned int hlen; + unsigned int off; + + napi->skb = NULL; + + skb_reset_mac_header(skb); + skb_gro_reset_offset(skb); + + off = skb_gro_offset(skb); + hlen = off + sizeof(*eth); + eth = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, hlen)) { + eth = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!eth)) { + napi_reuse_skb(napi, skb); + skb = NULL; + goto out; + } + } + + skb_gro_pull(skb, sizeof(*eth)); + + /* + * This works because the only protocols we care about don't require + * special handling. We'll fix it up properly at the end. + */ + skb->protocol = eth->h_proto; + +out: + return skb; +} +EXPORT_SYMBOL(napi_frags_skb); + +int napi_gro_frags(struct napi_struct *napi) +{ + struct sk_buff *skb = napi_frags_skb(napi); if (!skb) return NET_RX_DROP; @@ -2719,7 +2754,7 @@ void netif_napi_del(struct napi_struct *napi) struct sk_buff *skb, *next; list_del_init(&napi->dev_list); - kfree_skb(napi->skb); + napi_free_frags(napi); for (skb = napi->gro_list; skb; skb = next) { next = skb->next; @@ -2773,8 +2808,10 @@ static void net_rx_action(struct softirq_action *h) * accidently calling ->poll() when NAPI is not scheduled. */ work = 0; - if (test_bit(NAPI_STATE_SCHED, &n->state)) + if (test_bit(NAPI_STATE_SCHED, &n->state)) { work = n->poll(n, weight); + trace_napi_poll(n); + } WARN_ON_ONCE(work > weight); @@ -3444,6 +3481,319 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } +/* hw addresses list handling functions */ + +static int __hw_addr_add(struct list_head *list, int *delta, + unsigned char *addr, int addr_len, + unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + int alloc_size; + + if (addr_len > MAX_ADDR_LEN) + return -EINVAL; + + list_for_each_entry(ha, list, list) { + if (!memcmp(ha->addr, addr, addr_len) && + ha->type == addr_type) { + ha->refcount++; + return 0; + } + } + + + alloc_size = sizeof(*ha); + if (alloc_size < L1_CACHE_BYTES) + alloc_size = L1_CACHE_BYTES; + ha = kmalloc(alloc_size, GFP_ATOMIC); + if (!ha) + return -ENOMEM; + memcpy(ha->addr, addr, addr_len); + ha->type = addr_type; + ha->refcount = 1; + ha->synced = false; + list_add_tail_rcu(&ha->list, list); + if (delta) + (*delta)++; + return 0; +} + +static void ha_rcu_free(struct rcu_head *head) +{ + struct netdev_hw_addr *ha; + + ha = container_of(head, struct netdev_hw_addr, rcu_head); + kfree(ha); +} + +static int __hw_addr_del(struct list_head *list, int *delta, + unsigned char *addr, int addr_len, + unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + + list_for_each_entry(ha, list, list) { + if (!memcmp(ha->addr, addr, addr_len) && + (ha->type == addr_type || !addr_type)) { + if (--ha->refcount) + return 0; + list_del_rcu(&ha->list); + call_rcu(&ha->rcu_head, ha_rcu_free); + if (delta) + (*delta)--; + return 0; + } + } + return -ENOENT; +} + +static int __hw_addr_add_multiple(struct list_head *to_list, int *to_delta, + struct list_head *from_list, int addr_len, + unsigned char addr_type) +{ + int err; + struct netdev_hw_addr *ha, *ha2; + unsigned char type; + + list_for_each_entry(ha, from_list, list) { + type = addr_type ? addr_type : ha->type; + err = __hw_addr_add(to_list, to_delta, ha->addr, + addr_len, type); + if (err) + goto unroll; + } + return 0; + +unroll: + list_for_each_entry(ha2, from_list, list) { + if (ha2 == ha) + break; + type = addr_type ? addr_type : ha2->type; + __hw_addr_del(to_list, to_delta, ha2->addr, + addr_len, type); + } + return err; +} + +static void __hw_addr_del_multiple(struct list_head *to_list, int *to_delta, + struct list_head *from_list, int addr_len, + unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + unsigned char type; + + list_for_each_entry(ha, from_list, list) { + type = addr_type ? addr_type : ha->type; + __hw_addr_del(to_list, to_delta, ha->addr, + addr_len, addr_type); + } +} + +static int __hw_addr_sync(struct list_head *to_list, int *to_delta, + struct list_head *from_list, int *from_delta, + int addr_len) +{ + int err = 0; + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, from_list, list) { + if (!ha->synced) { + err = __hw_addr_add(to_list, to_delta, ha->addr, + addr_len, ha->type); + if (err) + break; + ha->synced = true; + ha->refcount++; + } else if (ha->refcount == 1) { + __hw_addr_del(to_list, to_delta, ha->addr, + addr_len, ha->type); + __hw_addr_del(from_list, from_delta, ha->addr, + addr_len, ha->type); + } + } + return err; +} + +static void __hw_addr_unsync(struct list_head *to_list, int *to_delta, + struct list_head *from_list, int *from_delta, + int addr_len) +{ + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, from_list, list) { + if (ha->synced) { + __hw_addr_del(to_list, to_delta, ha->addr, + addr_len, ha->type); + ha->synced = false; + __hw_addr_del(from_list, from_delta, ha->addr, + addr_len, ha->type); + } + } +} + + +static void __hw_addr_flush(struct list_head *list) +{ + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, list, list) { + list_del_rcu(&ha->list); + call_rcu(&ha->rcu_head, ha_rcu_free); + } +} + +/* Device addresses handling functions */ + +static void dev_addr_flush(struct net_device *dev) +{ + /* rtnl_mutex must be held here */ + + __hw_addr_flush(&dev->dev_addr_list); + dev->dev_addr = NULL; +} + +static int dev_addr_init(struct net_device *dev) +{ + unsigned char addr[MAX_ADDR_LEN]; + struct netdev_hw_addr *ha; + int err; + + /* rtnl_mutex must be held here */ + + INIT_LIST_HEAD(&dev->dev_addr_list); + memset(addr, 0, sizeof(addr)); + err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(addr), + NETDEV_HW_ADDR_T_LAN); + if (!err) { + /* + * Get the first (previously created) address from the list + * and set dev_addr pointer to this location. + */ + ha = list_first_entry(&dev->dev_addr_list, + struct netdev_hw_addr, list); + dev->dev_addr = ha->addr; + } + return err; +} + +/** + * dev_addr_add - Add a device address + * @dev: device + * @addr: address to add + * @addr_type: address type + * + * Add a device address to the device or increase the reference count if + * it already exists. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_add(struct net_device *dev, unsigned char *addr, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, dev->addr_len, + addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + return err; +} +EXPORT_SYMBOL(dev_addr_add); + +/** + * dev_addr_del - Release a device address. + * @dev: device + * @addr: address to delete + * @addr_type: address type + * + * Release reference to a device address and remove it from the device + * if the reference count drops to zero. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_del(struct net_device *dev, unsigned char *addr, + unsigned char addr_type) +{ + int err; + struct netdev_hw_addr *ha; + + ASSERT_RTNL(); + + /* + * We can not remove the first address from the list because + * dev->dev_addr points to that. + */ + ha = list_first_entry(&dev->dev_addr_list, struct netdev_hw_addr, list); + if (ha->addr == dev->dev_addr && ha->refcount == 1) + return -ENOENT; + + err = __hw_addr_del(&dev->dev_addr_list, NULL, addr, dev->addr_len, + addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + return err; +} +EXPORT_SYMBOL(dev_addr_del); + +/** + * dev_addr_add_multiple - Add device addresses from another device + * @to_dev: device to which addresses will be added + * @from_dev: device from which addresses will be added + * @addr_type: address type - 0 means type will be used from from_dev + * + * Add device addresses of the one device to another. + ** + * The caller must hold the rtnl_mutex. + */ +int dev_addr_add_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + if (from_dev->addr_len != to_dev->addr_len) + return -EINVAL; + err = __hw_addr_add_multiple(&to_dev->dev_addr_list, NULL, + &from_dev->dev_addr_list, + to_dev->addr_len, addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); + return err; +} +EXPORT_SYMBOL(dev_addr_add_multiple); + +/** + * dev_addr_del_multiple - Delete device addresses by another device + * @to_dev: device where the addresses will be deleted + * @from_dev: device by which addresses the addresses will be deleted + * @addr_type: address type - 0 means type will used from from_dev + * + * Deletes addresses in to device by the list of addresses in from device. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_del_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type) +{ + ASSERT_RTNL(); + + if (from_dev->addr_len != to_dev->addr_len) + return -EINVAL; + __hw_addr_del_multiple(&to_dev->dev_addr_list, NULL, + &from_dev->dev_addr_list, + to_dev->addr_len, addr_type); + call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); + return 0; +} +EXPORT_SYMBOL(dev_addr_del_multiple); + +/* unicast and multicast addresses handling functions */ + int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int glbl) { @@ -3506,24 +3856,22 @@ int __dev_addr_add(struct dev_addr_list **list, int *count, * dev_unicast_delete - Release secondary unicast address. * @dev: device * @addr: address to delete - * @alen: length of @addr * * Release reference to a secondary unicast address and remove it * from the device if the reference count drops to zero. * * The caller must hold the rtnl_mutex. */ -int dev_unicast_delete(struct net_device *dev, void *addr, int alen) +int dev_unicast_delete(struct net_device *dev, void *addr) { int err; ASSERT_RTNL(); - netif_addr_lock_bh(dev); - err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0); + err = __hw_addr_del(&dev->uc_list, &dev->uc_count, addr, + dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); - netif_addr_unlock_bh(dev); return err; } EXPORT_SYMBOL(dev_unicast_delete); @@ -3532,24 +3880,22 @@ EXPORT_SYMBOL(dev_unicast_delete); * dev_unicast_add - add a secondary unicast address * @dev: device * @addr: address to add - * @alen: length of @addr * * Add a secondary unicast address to the device or increase * the reference count if it already exists. * * The caller must hold the rtnl_mutex. */ -int dev_unicast_add(struct net_device *dev, void *addr, int alen) +int dev_unicast_add(struct net_device *dev, void *addr) { int err; ASSERT_RTNL(); - netif_addr_lock_bh(dev); - err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0); + err = __hw_addr_add(&dev->uc_list, &dev->uc_count, addr, + dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); - netif_addr_unlock_bh(dev); return err; } EXPORT_SYMBOL(dev_unicast_add); @@ -3606,8 +3952,7 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, * @from: source device * * Add newly added addresses to the destination device and release - * addresses that have no users left. The source device must be - * locked by netif_tx_lock_bh. + * addresses that have no users left. * * This function is intended to be called from the dev->set_rx_mode * function of layered software devices. @@ -3616,12 +3961,15 @@ int dev_unicast_sync(struct net_device *to, struct net_device *from) { int err = 0; - netif_addr_lock_bh(to); - err = __dev_addr_sync(&to->uc_list, &to->uc_count, - &from->uc_list, &from->uc_count); + ASSERT_RTNL(); + + if (to->addr_len != from->addr_len) + return -EINVAL; + + err = __hw_addr_sync(&to->uc_list, &to->uc_count, + &from->uc_list, &from->uc_count, to->addr_len); if (!err) __dev_set_rx_mode(to); - netif_addr_unlock_bh(to); return err; } EXPORT_SYMBOL(dev_unicast_sync); @@ -3637,18 +3985,33 @@ EXPORT_SYMBOL(dev_unicast_sync); */ void dev_unicast_unsync(struct net_device *to, struct net_device *from) { - netif_addr_lock_bh(from); - netif_addr_lock(to); + ASSERT_RTNL(); - __dev_addr_unsync(&to->uc_list, &to->uc_count, - &from->uc_list, &from->uc_count); + if (to->addr_len != from->addr_len) + return; + + __hw_addr_unsync(&to->uc_list, &to->uc_count, + &from->uc_list, &from->uc_count, to->addr_len); __dev_set_rx_mode(to); - - netif_addr_unlock(to); - netif_addr_unlock_bh(from); } EXPORT_SYMBOL(dev_unicast_unsync); +static void dev_unicast_flush(struct net_device *dev) +{ + /* rtnl_mutex must be held here */ + + __hw_addr_flush(&dev->uc_list); + dev->uc_count = 0; +} + +static void dev_unicast_init(struct net_device *dev) +{ + /* rtnl_mutex must be held here */ + + INIT_LIST_HEAD(&dev->uc_list); +} + + static void __dev_addr_discard(struct dev_addr_list **list) { struct dev_addr_list *tmp; @@ -3667,9 +4030,6 @@ static void dev_addr_discard(struct net_device *dev) { netif_addr_lock_bh(dev); - __dev_addr_discard(&dev->uc_list); - dev->uc_count = 0; - __dev_addr_discard(&dev->mc_list); dev->mc_count = 0; @@ -3853,7 +4213,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm switch (cmd) { case SIOCGIFFLAGS: /* Get interface flags */ - ifr->ifr_flags = dev_get_flags(dev); + ifr->ifr_flags = (short) dev_get_flags(dev); return 0; case SIOCGIFMETRIC: /* Get the metric on the interface @@ -4262,6 +4622,7 @@ static void rollback_registered(struct net_device *dev) /* * Flush the unicast and multicast chains */ + dev_unicast_flush(dev); dev_addr_discard(dev); if (dev->netdev_ops->ndo_uninit) @@ -4333,39 +4694,6 @@ unsigned long netdev_fix_features(unsigned long features, const char *name) } EXPORT_SYMBOL(netdev_fix_features); -/* Some devices need to (re-)set their netdev_ops inside - * ->init() or similar. If that happens, we have to setup - * the compat pointers again. - */ -void netdev_resync_ops(struct net_device *dev) -{ -#ifdef CONFIG_COMPAT_NET_DEV_OPS - const struct net_device_ops *ops = dev->netdev_ops; - - dev->init = ops->ndo_init; - dev->uninit = ops->ndo_uninit; - dev->open = ops->ndo_open; - dev->change_rx_flags = ops->ndo_change_rx_flags; - dev->set_rx_mode = ops->ndo_set_rx_mode; - dev->set_multicast_list = ops->ndo_set_multicast_list; - dev->set_mac_address = ops->ndo_set_mac_address; - dev->validate_addr = ops->ndo_validate_addr; - dev->do_ioctl = ops->ndo_do_ioctl; - dev->set_config = ops->ndo_set_config; - dev->change_mtu = ops->ndo_change_mtu; - dev->neigh_setup = ops->ndo_neigh_setup; - dev->tx_timeout = ops->ndo_tx_timeout; - dev->get_stats = ops->ndo_get_stats; - dev->vlan_rx_register = ops->ndo_vlan_rx_register; - dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid; - dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ops->ndo_poll_controller; -#endif -#endif -} -EXPORT_SYMBOL(netdev_resync_ops); - /** * register_netdevice - register a network device * @dev: device to register @@ -4405,23 +4733,6 @@ int register_netdevice(struct net_device *dev) dev->iflink = -1; -#ifdef CONFIG_COMPAT_NET_DEV_OPS - /* Netdevice_ops API compatibility support. - * This is temporary until all network devices are converted. - */ - if (dev->netdev_ops) { - netdev_resync_ops(dev); - } else { - char drivername[64]; - pr_info("%s (%s): not using net_device_ops yet\n", - dev->name, netdev_drivername(dev, drivername, 64)); - - /* This works only because net_device_ops and the - compatibility structure are the same. */ - dev->netdev_ops = (void *) &(dev->init); - } -#endif - /* Init, if this function is available */ if (dev->netdev_ops->ndo_init) { ret = dev->netdev_ops->ndo_init(dev); @@ -4707,13 +5018,30 @@ void netdev_run_todo(void) * the internal statistics structure is used. */ const struct net_device_stats *dev_get_stats(struct net_device *dev) - { +{ const struct net_device_ops *ops = dev->netdev_ops; if (ops->ndo_get_stats) return ops->ndo_get_stats(dev); - else - return &dev->stats; + else { + unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0; + struct net_device_stats *stats = &dev->stats; + unsigned int i; + struct netdev_queue *txq; + + for (i = 0; i < dev->num_tx_queues; i++) { + txq = netdev_get_tx_queue(dev, i); + tx_bytes += txq->tx_bytes; + tx_packets += txq->tx_packets; + tx_dropped += txq->tx_dropped; + } + if (tx_bytes || tx_packets || tx_dropped) { + stats->tx_bytes = tx_bytes; + stats->tx_packets = tx_packets; + stats->tx_dropped = tx_dropped; + } + return stats; + } } EXPORT_SYMBOL(dev_get_stats); @@ -4748,18 +5076,18 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, struct netdev_queue *tx; struct net_device *dev; size_t alloc_size; - void *p; + struct net_device *p; BUG_ON(strlen(name) >= sizeof(dev->name)); alloc_size = sizeof(struct net_device); if (sizeof_priv) { /* ensure 32-byte alignment of private area */ - alloc_size = (alloc_size + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; + alloc_size = ALIGN(alloc_size, NETDEV_ALIGN); alloc_size += sizeof_priv; } /* ensure 32-byte alignment of whole construct */ - alloc_size += NETDEV_ALIGN_CONST; + alloc_size += NETDEV_ALIGN - 1; p = kzalloc(alloc_size, GFP_KERNEL); if (!p) { @@ -4771,13 +5099,17 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, if (!tx) { printk(KERN_ERR "alloc_netdev: Unable to allocate " "tx qdiscs.\n"); - kfree(p); - return NULL; + goto free_p; } - dev = (struct net_device *) - (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); + dev = PTR_ALIGN(p, NETDEV_ALIGN); dev->padded = (char *)dev - (char *)p; + + if (dev_addr_init(dev)) + goto free_tx; + + dev_unicast_init(dev); + dev_net_set(dev, &init_net); dev->_tx = tx; @@ -4789,9 +5121,17 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, netdev_init_queues(dev); INIT_LIST_HEAD(&dev->napi_list); + dev->priv_flags = IFF_XMIT_DST_RELEASE; setup(dev); strcpy(dev->name, name); return dev; + +free_tx: + kfree(tx); + +free_p: + kfree(p); + return NULL; } EXPORT_SYMBOL(alloc_netdev_mq); @@ -4811,6 +5151,9 @@ void free_netdev(struct net_device *dev) kfree(dev->_tx); + /* Flush device addresses */ + dev_addr_flush(dev); + list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) netif_napi_del(p); @@ -4970,6 +5313,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* * Flush the unicast and multicast chains */ + dev_unicast_flush(dev); dev_addr_discard(dev); netdev_unregister_kobject(dev); @@ -5325,12 +5669,6 @@ EXPORT_SYMBOL(net_enable_timestamp); EXPORT_SYMBOL(net_disable_timestamp); EXPORT_SYMBOL(dev_get_flags); -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -EXPORT_SYMBOL(br_handle_frame_hook); -EXPORT_SYMBOL(br_fdb_get_hook); -EXPORT_SYMBOL(br_fdb_put_hook); -#endif - EXPORT_SYMBOL(dev_load); EXPORT_PER_CPU_SYMBOL(softnet_data); diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index b75b6cea49da..9d66fa953ab7 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -22,8 +22,10 @@ #include #include #include +#include #include +#include #include @@ -38,7 +40,8 @@ static void send_dm_alert(struct work_struct *unused); * and the work handle that will send up * netlink alerts */ -struct sock *dm_sock; +static int trace_state = TRACE_OFF; +static spinlock_t trace_state_lock = SPIN_LOCK_UNLOCKED; struct per_cpu_dm_data { struct work_struct dm_alert_work; @@ -47,11 +50,18 @@ struct per_cpu_dm_data { struct timer_list send_timer; }; +struct dm_hw_stat_delta { + struct net_device *dev; + struct list_head list; + struct rcu_head rcu; + unsigned long last_drop_val; +}; + static struct genl_family net_drop_monitor_family = { .id = GENL_ID_GENERATE, .hdrsize = 0, .name = "NET_DM", - .version = 1, + .version = 2, .maxattr = NET_DM_CMD_MAX, }; @@ -59,19 +69,24 @@ static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); static int dm_hit_limit = 64; static int dm_delay = 1; - +static unsigned long dm_hw_check_delta = 2*HZ; +static LIST_HEAD(hw_stats_list); static void reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; struct net_dm_alert_msg *msg; + struct nlattr *nla; al = sizeof(struct net_dm_alert_msg); al += dm_hit_limit * sizeof(struct net_dm_drop_point); + al += sizeof(struct nlattr); + data->skb = genlmsg_new(al, GFP_KERNEL); genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family, 0, NET_DM_CMD_ALERT); - msg = __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_alert_msg)); + nla = nla_reserve(data->skb, NLA_UNSPEC, sizeof(struct net_dm_alert_msg)); + msg = nla_data(nla); memset(msg, 0, al); atomic_set(&data->dm_hit_count, dm_hit_limit); } @@ -111,10 +126,11 @@ static void sched_send_work(unsigned long unused) schedule_work(&data->dm_alert_work); } -static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) +static void trace_drop_common(struct sk_buff *skb, void *location) { struct net_dm_alert_msg *msg; struct nlmsghdr *nlh; + struct nlattr *nla; int i; struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data); @@ -127,7 +143,8 @@ static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) } nlh = (struct nlmsghdr *)data->skb->data; - msg = genlmsg_data(nlmsg_data(nlh)); + nla = genlmsg_data(nlmsg_data(nlh)); + msg = nla_data(nla); for (i = 0; i < msg->entries; i++) { if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { msg->points[i].count++; @@ -139,6 +156,7 @@ static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) * We need to create a new entry */ __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point)); + nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point)); memcpy(msg->points[msg->entries].pc, &location, sizeof(void *)); msg->points[msg->entries].count = 1; msg->entries++; @@ -152,24 +170,80 @@ static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) return; } +static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) +{ + trace_drop_common(skb, location); +} + +static void trace_napi_poll_hit(struct napi_struct *napi) +{ + struct dm_hw_stat_delta *new_stat; + + /* + * Ratelimit our check time to dm_hw_check_delta jiffies + */ + if (!time_after(jiffies, napi->dev->last_rx + dm_hw_check_delta)) + return; + + rcu_read_lock(); + list_for_each_entry_rcu(new_stat, &hw_stats_list, list) { + if ((new_stat->dev == napi->dev) && + (napi->dev->stats.rx_dropped != new_stat->last_drop_val)) { + trace_drop_common(NULL, NULL); + new_stat->last_drop_val = napi->dev->stats.rx_dropped; + break; + } + } + rcu_read_unlock(); +} + + +static void free_dm_hw_stat(struct rcu_head *head) +{ + struct dm_hw_stat_delta *n; + n = container_of(head, struct dm_hw_stat_delta, rcu); + kfree(n); +} + static int set_all_monitor_traces(int state) { int rc = 0; + struct dm_hw_stat_delta *new_stat = NULL; + struct dm_hw_stat_delta *temp; + + spin_lock(&trace_state_lock); switch (state) { case TRACE_ON: rc |= register_trace_kfree_skb(trace_kfree_skb_hit); + rc |= register_trace_napi_poll(trace_napi_poll_hit); break; case TRACE_OFF: rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit); + rc |= unregister_trace_napi_poll(trace_napi_poll_hit); tracepoint_synchronize_unregister(); + + /* + * Clean the device list + */ + list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { + if (new_stat->dev == NULL) { + list_del_rcu(&new_stat->list); + call_rcu(&new_stat->rcu, free_dm_hw_stat); + } + } break; default: rc = 1; break; } + if (!rc) + trace_state = state; + + spin_unlock(&trace_state_lock); + if (rc) return -EINPROGRESS; return rc; @@ -197,6 +271,44 @@ static int net_dm_cmd_trace(struct sk_buff *skb, return -ENOTSUPP; } +static int dropmon_net_event(struct notifier_block *ev_block, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + struct dm_hw_stat_delta *new_stat = NULL; + struct dm_hw_stat_delta *tmp; + + switch (event) { + case NETDEV_REGISTER: + new_stat = kzalloc(sizeof(struct dm_hw_stat_delta), GFP_KERNEL); + + if (!new_stat) + goto out; + + new_stat->dev = dev; + INIT_RCU_HEAD(&new_stat->rcu); + spin_lock(&trace_state_lock); + list_add_rcu(&new_stat->list, &hw_stats_list); + spin_unlock(&trace_state_lock); + break; + case NETDEV_UNREGISTER: + spin_lock(&trace_state_lock); + list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) { + if (new_stat->dev == dev) { + new_stat->dev = NULL; + if (trace_state == TRACE_OFF) { + list_del_rcu(&new_stat->list); + call_rcu(&new_stat->rcu, free_dm_hw_stat); + break; + } + } + } + spin_unlock(&trace_state_lock); + break; + } +out: + return NOTIFY_DONE; +} static struct genl_ops dropmon_ops[] = { { @@ -213,6 +325,10 @@ static struct genl_ops dropmon_ops[] = { }, }; +static struct notifier_block dropmon_net_notifier = { + .notifier_call = dropmon_net_event +}; + static int __init init_net_drop_monitor(void) { int cpu; @@ -236,12 +352,18 @@ static int __init init_net_drop_monitor(void) ret = genl_register_ops(&net_drop_monitor_family, &dropmon_ops[i]); if (ret) { - printk(KERN_CRIT "failed to register operation %d\n", + printk(KERN_CRIT "Failed to register operation %d\n", dropmon_ops[i].cmd); goto out_unreg; } } + rc = register_netdevice_notifier(&dropmon_net_notifier); + if (rc < 0) { + printk(KERN_CRIT "Failed to register netdevice notifier\n"); + goto out_unreg; + } + rc = 0; for_each_present_cpu(cpu) { @@ -252,6 +374,7 @@ static int __init init_net_drop_monitor(void) data->send_timer.data = cpu; data->send_timer.function = sched_send_work; } + goto out; out_unreg: diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 98691e1466b8..bd309384f8b8 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -299,7 +299,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) } else if (rule->action == FR_ACT_GOTO) goto errout_free; - err = ops->configure(rule, skb, nlh, frh, tb); + err = ops->configure(rule, skb, frh, tb); if (err < 0) goto errout_free; @@ -500,7 +500,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, if (rule->target) NLA_PUT_U32(skb, FRA_GOTO, rule->target); - if (ops->fill(rule, skb, nlh, frh) < 0) + if (ops->fill(rule, skb, frh) < 0) goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 6d62d4618cfc..78e5bfc454ae 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -128,12 +128,12 @@ static void est_timer(unsigned long arg) npackets = e->bstats->packets; brate = (nbytes - e->last_bytes)<<(7 - idx); e->last_bytes = nbytes; - e->avbps += ((s64)(brate - e->avbps)) >> e->ewma_log; + e->avbps += (brate >> e->ewma_log) - (e->avbps >> e->ewma_log); e->rate_est->bps = (e->avbps+0xF)>>5; rate = (npackets - e->last_packets)<<(12 - idx); e->last_packets = npackets; - e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log; + e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log); e->rate_est->pps = (e->avpps+0x1FF)>>10; skip: read_unlock(&est_lock); diff --git a/net/core/iovec.c b/net/core/iovec.c index 4c9c0121c9da..16ad45d4882b 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -97,6 +97,31 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) return 0; } +/* + * Copy kernel to iovec. Returns -EFAULT on error. + */ + +int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, + int offset, int len) +{ + int copy; + for (; len > 0; ++iov) { + /* Skip over the finished iovecs */ + if (unlikely(offset >= iov->iov_len)) { + offset -= iov->iov_len; + continue; + } + copy = min_t(unsigned int, iov->iov_len - offset, len); + if (copy_to_user(iov->iov_base + offset, kdata, copy)) + return -EFAULT; + offset = 0; + kdata += copy; + len -= copy; + } + + return 0; +} + /* * Copy iovec to kernel. Returns -EFAULT on error. * @@ -122,10 +147,11 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len) } /* - * For use with ip_build_xmit + * Copy iovec from kernel. Returns -EFAULT on error. */ -int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, - int len) + +int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len) { /* Skip over the finished iovecs */ while (offset >= iov->iov_len) { @@ -236,3 +262,4 @@ EXPORT_SYMBOL(csum_partial_copy_fromiovecend); EXPORT_SYMBOL(memcpy_fromiovec); EXPORT_SYMBOL(memcpy_fromiovecend); EXPORT_SYMBOL(memcpy_toiovec); +EXPORT_SYMBOL(memcpy_toiovecend); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index a1cbce7fdae5..163b4f5b0365 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -771,6 +771,28 @@ static __inline__ int neigh_max_probes(struct neighbour *n) p->ucast_probes + p->app_probes + p->mcast_probes); } +static void neigh_invalidate(struct neighbour *neigh) +{ + struct sk_buff *skb; + + NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed); + NEIGH_PRINTK2("neigh %p is failed.\n", neigh); + neigh->updated = jiffies; + + /* It is very thin place. report_unreachable is very complicated + routine. Particularly, it can hit the same neighbour entry! + + So that, we try to be accurate and avoid dead loop. --ANK + */ + while (neigh->nud_state == NUD_FAILED && + (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) { + write_unlock(&neigh->lock); + neigh->ops->error_report(neigh, skb); + write_lock(&neigh->lock); + } + skb_queue_purge(&neigh->arp_queue); +} + /* Called when a timer expires for a neighbour entry. */ static void neigh_timer_handler(unsigned long arg) @@ -835,26 +857,9 @@ static void neigh_timer_handler(unsigned long arg) if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) && atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) { - struct sk_buff *skb; - neigh->nud_state = NUD_FAILED; - neigh->updated = jiffies; notify = 1; - NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed); - NEIGH_PRINTK2("neigh %p is failed.\n", neigh); - - /* It is very thin place. report_unreachable is very complicated - routine. Particularly, it can hit the same neighbour entry! - - So that, we try to be accurate and avoid dead loop. --ANK - */ - while (neigh->nud_state == NUD_FAILED && - (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) { - write_unlock(&neigh->lock); - neigh->ops->error_report(neigh, skb); - write_lock(&neigh->lock); - } - skb_queue_purge(&neigh->arp_queue); + neigh_invalidate(neigh); } if (neigh->nud_state & NUD_IN_TIMER) { @@ -1001,6 +1006,11 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, neigh->nud_state = new; err = 0; notify = old & NUD_VALID; + if ((old & (NUD_INCOMPLETE | NUD_PROBE)) && + (new & NUD_FAILED)) { + neigh_invalidate(neigh); + notify = 1; + } goto out; } @@ -1088,8 +1098,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, struct neighbour *n1 = neigh; write_unlock_bh(&neigh->lock); /* On shaper/eql skb->dst->neighbour != neigh :( */ - if (skb->dst && skb->dst->neighbour) - n1 = skb->dst->neighbour; + if (skb_dst(skb) && skb_dst(skb)->neighbour) + n1 = skb_dst(skb)->neighbour; n1->output(skb); write_lock_bh(&neigh->lock); } @@ -1182,7 +1192,7 @@ EXPORT_SYMBOL(neigh_compat_output); int neigh_resolve_output(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct neighbour *neigh; int rc = 0; @@ -1229,7 +1239,7 @@ EXPORT_SYMBOL(neigh_resolve_output); int neigh_connected_output(struct sk_buff *skb) { int err; - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct neighbour *neigh = dst->neighbour; struct net_device *dev = neigh->dev; @@ -1298,8 +1308,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, if (time_before(tbl->proxy_timer.expires, sched_next)) sched_next = tbl->proxy_timer.expires; } - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); dev_hold(skb->dev); __skb_queue_tail(&tbl->proxy_queue, skb); mod_timer(&tbl->proxy_timer, sched_next); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 2da59a0ac4ac..3994680c08b9 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -78,7 +78,7 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, goto err; if (!rtnl_trylock()) - return -ERESTARTSYS; + return restart_syscall(); if (dev_isalive(net)) { if ((ret = (*set)(net, new)) == 0) @@ -225,7 +225,8 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, if (len > 0 && buf[len - 1] == '\n') --count; - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); ret = dev_set_alias(netdev, buf, count); rtnl_unlock(); @@ -238,7 +239,8 @@ static ssize_t show_ifalias(struct device *dev, const struct net_device *netdev = to_net_dev(dev); ssize_t ret = 0; - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); if (netdev->ifalias) ret = sprintf(buf, "%s\n", netdev->ifalias); rtnl_unlock(); @@ -497,7 +499,6 @@ int netdev_register_kobject(struct net_device *net) dev->platform_data = net; dev->groups = groups; - BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ); dev_set_name(dev, "%s", net->name); #ifdef CONFIG_SYSFS diff --git a/net/core/net-traces.c b/net/core/net-traces.c index 499a67eaf3ae..f1e982c508bb 100644 --- a/net/core/net-traces.c +++ b/net/core/net-traces.c @@ -25,5 +25,8 @@ #define CREATE_TRACE_POINTS #include +#include EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); + +EXPORT_TRACEPOINT_SYMBOL_GPL(napi_poll); diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index e3bebd36f053..b7292a2719dc 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -115,41 +115,34 @@ static void net_free(struct net *net) kmem_cache_free(net_cachep, net); } -struct net *copy_net_ns(unsigned long flags, struct net *old_net) +static struct net *net_create(void) { - struct net *new_net = NULL; - int err; - - get_net(old_net); - - if (!(flags & CLONE_NEWNET)) - return old_net; - - err = -ENOMEM; - new_net = net_alloc(); - if (!new_net) - goto out_err; + struct net *net; + int rv; + net = net_alloc(); + if (!net) + return ERR_PTR(-ENOMEM); mutex_lock(&net_mutex); - err = setup_net(new_net); - if (!err) { + rv = setup_net(net); + if (rv == 0) { rtnl_lock(); - list_add_tail(&new_net->list, &net_namespace_list); + list_add_tail(&net->list, &net_namespace_list); rtnl_unlock(); } mutex_unlock(&net_mutex); + if (rv < 0) { + net_free(net); + return ERR_PTR(rv); + } + return net; +} - if (err) - goto out_free; -out: - put_net(old_net); - return new_net; - -out_free: - net_free(new_net); -out_err: - new_net = ERR_PTR(err); - goto out; +struct net *copy_net_ns(unsigned long flags, struct net *old_net) +{ + if (!(flags & CLONE_NEWNET)) + return get_net(old_net); + return net_create(); } static void cleanup_net(struct work_struct *work) @@ -203,9 +196,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) static int __init net_ns_init(void) { struct net_generic *ng; - int err; - printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net)); #ifdef CONFIG_NET_NS net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), SMP_CACHE_BYTES, @@ -224,15 +215,14 @@ static int __init net_ns_init(void) rcu_assign_pointer(init_net.gen, ng); mutex_lock(&net_mutex); - err = setup_net(&init_net); + if (setup_net(&init_net)) + panic("Could not setup the initial network namespace"); rtnl_lock(); list_add_tail(&init_net.list, &net_namespace_list); rtnl_unlock(); mutex_unlock(&net_mutex); - if (err) - panic("Could not setup the initial network namespace"); return 0; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 64f51eec6576..9675f312830d 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * We maintain a small pool of fully-sized skbs, to make sure the @@ -137,6 +138,7 @@ static int poll_one_napi(struct netpoll_info *npinfo, set_bit(NAPI_STATE_NPSVC, &napi->state); work = napi->poll(napi, budget); + trace_napi_poll(napi); clear_bit(NAPI_STATE_NPSVC, &napi->state); atomic_dec(&trapped); @@ -300,8 +302,11 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { if (__netif_tx_trylock(txq)) { - if (!netif_tx_queue_stopped(txq)) + if (!netif_tx_queue_stopped(txq)) { status = ops->ndo_start_xmit(skb, dev); + if (status == NETDEV_TX_OK) + txq_trans_update(txq); + } __netif_tx_unlock(txq); if (status == NETDEV_TX_OK) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 0666a827bc62..19b8c20e98a4 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3438,6 +3438,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) retry_now: ret = (*xmit)(pkt_dev->skb, odev); if (likely(ret == NETDEV_TX_OK)) { + txq_trans_update(txq); pkt_dev->last_ok = 1; pkt_dev->sofar++; pkt_dev->seq_num++; @@ -3690,8 +3691,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) #ifdef CONFIG_XFRM free_SAs(pkt_dev); #endif - if (pkt_dev->flows) - vfree(pkt_dev->flows); + vfree(pkt_dev->flows); kfree(pkt_dev); return err; } @@ -3790,8 +3790,7 @@ static int pktgen_remove_device(struct pktgen_thread *t, #ifdef CONFIG_XFRM free_SAs(pkt_dev); #endif - if (pkt_dev->flows) - vfree(pkt_dev->flows); + vfree(pkt_dev->flows); kfree(pkt_dev); return 0; } diff --git a/net/core/skb_dma_map.c b/net/core/skb_dma_map.c index 86234923a3b7..79687dfd6957 100644 --- a/net/core/skb_dma_map.c +++ b/net/core/skb_dma_map.c @@ -20,7 +20,7 @@ int skb_dma_map(struct device *dev, struct sk_buff *skb, if (dma_mapping_error(dev, map)) goto out_err; - sp->dma_maps[0] = map; + sp->dma_head = map; for (i = 0; i < sp->nr_frags; i++) { skb_frag_t *fp = &sp->frags[i]; @@ -28,9 +28,8 @@ int skb_dma_map(struct device *dev, struct sk_buff *skb, fp->size, dir); if (dma_mapping_error(dev, map)) goto unwind; - sp->dma_maps[i + 1] = map; + sp->dma_maps[i] = map; } - sp->num_dma_maps = i + 1; return 0; @@ -38,10 +37,10 @@ int skb_dma_map(struct device *dev, struct sk_buff *skb, while (--i >= 0) { skb_frag_t *fp = &sp->frags[i]; - dma_unmap_page(dev, sp->dma_maps[i + 1], + dma_unmap_page(dev, sp->dma_maps[i], fp->size, dir); } - dma_unmap_single(dev, sp->dma_maps[0], + dma_unmap_single(dev, sp->dma_head, skb_headlen(skb), dir); out_err: return -ENOMEM; @@ -54,12 +53,12 @@ void skb_dma_unmap(struct device *dev, struct sk_buff *skb, struct skb_shared_info *sp = skb_shinfo(skb); int i; - dma_unmap_single(dev, sp->dma_maps[0], + dma_unmap_single(dev, sp->dma_head, skb_headlen(skb), dir); for (i = 0; i < sp->nr_frags; i++) { skb_frag_t *fp = &sp->frags[i]; - dma_unmap_page(dev, sp->dma_maps[i + 1], + dma_unmap_page(dev, sp->dma_maps[i], fp->size, dir); } } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c2e4fb8f3546..1a94a3037370 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -210,7 +210,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; shinfo->tx_flags.flags = 0; - shinfo->frag_list = NULL; + skb_frag_list_init(skb); memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); if (fclone) { @@ -323,7 +323,7 @@ static void skb_clone_fraglist(struct sk_buff *skb) { struct sk_buff *list; - for (list = skb_shinfo(skb)->frag_list; list; list = list->next) + skb_walk_frags(skb, list) skb_get(list); } @@ -338,7 +338,7 @@ static void skb_release_data(struct sk_buff *skb) put_page(skb_shinfo(skb)->frags[i].page); } - if (skb_shinfo(skb)->frag_list) + if (skb_has_frags(skb)) skb_drop_fraglist(skb); kfree(skb->head); @@ -381,7 +381,7 @@ static void kfree_skbmem(struct sk_buff *skb) static void skb_release_head_state(struct sk_buff *skb) { - dst_release(skb->dst); + skb_dst_drop(skb); #ifdef CONFIG_XFRM secpath_put(skb->sp); #endif @@ -503,7 +503,7 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size) shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; shinfo->tx_flags.flags = 0; - shinfo->frag_list = NULL; + skb_frag_list_init(skb); memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); memset(skb, 0, offsetof(struct sk_buff, tail)); @@ -521,13 +521,12 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->transport_header = old->transport_header; new->network_header = old->network_header; new->mac_header = old->mac_header; - new->dst = dst_clone(old->dst); + skb_dst_set(new, dst_clone(skb_dst(old))); #ifdef CONFIG_XFRM new->sp = secpath_get(old->sp); #endif memcpy(new->cb, old->cb, sizeof(old->cb)); - new->csum_start = old->csum_start; - new->csum_offset = old->csum_offset; + new->csum = old->csum; new->local_df = old->local_df; new->pkt_type = old->pkt_type; new->ip_summed = old->ip_summed; @@ -538,6 +537,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) #endif new->protocol = old->protocol; new->mark = old->mark; + new->iif = old->iif; __nf_copy(new, old); #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) @@ -550,10 +550,17 @@ 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); } +/* + * You should not add any new code to this function. Add it to + * __copy_skb_header above instead. + */ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) { #define C(x) n->x = skb->x @@ -569,16 +576,11 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) n->cloned = 1; n->nohdr = 0; n->destructor = NULL; - C(iif); C(tail); C(end); C(head); C(data); C(truesize); -#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) - C(do_not_encrypt); - C(requeue); -#endif atomic_set(&n->users, 1); atomic_inc(&(skb_shinfo(skb)->dataref)); @@ -755,7 +757,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) skb_shinfo(n)->nr_frags = i; } - if (skb_shinfo(skb)->frag_list) { + if (skb_has_frags(skb)) { skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list; skb_clone_fraglist(n); } @@ -818,7 +820,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) get_page(skb_shinfo(skb)->frags[i].page); - if (skb_shinfo(skb)->frag_list) + if (skb_has_frags(skb)) skb_clone_fraglist(skb); skb_release_data(skb); @@ -1090,7 +1092,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) for (; i < nfrags; i++) put_page(skb_shinfo(skb)->frags[i].page); - if (skb_shinfo(skb)->frag_list) + if (skb_has_frags(skb)) skb_drop_fraglist(skb); goto done; } @@ -1185,7 +1187,7 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta) /* Optimization: no fragments, no reasons to preestimate * size of pulled pages. Superb. */ - if (!skb_shinfo(skb)->frag_list) + if (!skb_has_frags(skb)) goto pull_pages; /* Estimate size of pulled pages. */ @@ -1282,8 +1284,9 @@ EXPORT_SYMBOL(__pskb_pull_tail); int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) { - int i, copy; int start = skb_headlen(skb); + struct sk_buff *frag_iter; + int i, copy; if (offset > (int)skb->len - len) goto fault; @@ -1325,28 +1328,23 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - if (skb_copy_bits(list, offset - start, - to, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - to += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_bits(frag_iter, offset - start, to, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + to += copy; } + start = end; } if (!len) return 0; @@ -1531,6 +1529,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, .ops = &sock_pipe_buf_ops, .spd_release = sock_spd_release, }; + struct sk_buff *frag_iter; struct sock *sk = skb->sk; /* @@ -1545,13 +1544,11 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, /* * now see if we have a frag_list to map */ - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list && tlen; list = list->next) { - if (__skb_splice_bits(list, &offset, &tlen, &spd, sk)) - break; - } + skb_walk_frags(skb, frag_iter) { + if (!tlen) + break; + if (__skb_splice_bits(frag_iter, &offset, &tlen, &spd, sk)) + break; } done: @@ -1590,8 +1587,9 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) { - int i, copy; int start = skb_headlen(skb); + struct sk_buff *frag_iter; + int i, copy; if (offset > (int)skb->len - len) goto fault; @@ -1632,28 +1630,24 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - if (skb_store_bits(list, offset - start, - from, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - from += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_store_bits(frag_iter, offset - start, + from, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + from += copy; } + start = end; } if (!len) return 0; @@ -1670,6 +1664,7 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, { int start = skb_headlen(skb); int i, copy = start - offset; + struct sk_buff *frag_iter; int pos = 0; /* Checksum header. */ @@ -1709,29 +1704,25 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - __wsum csum2; - if (copy > len) - copy = len; - csum2 = skb_checksum(list, offset - start, - copy, 0); - csum = csum_block_add(csum, csum2, pos); - if ((len -= copy) == 0) - return csum; - offset += copy; - pos += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + __wsum csum2; + if (copy > len) + copy = len; + csum2 = skb_checksum(frag_iter, offset - start, + copy, 0); + csum = csum_block_add(csum, csum2, pos); + if ((len -= copy) == 0) + return csum; + offset += copy; + pos += copy; } + start = end; } BUG_ON(len); @@ -1746,6 +1737,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, { int start = skb_headlen(skb); int i, copy = start - offset; + struct sk_buff *frag_iter; int pos = 0; /* Copy header. */ @@ -1790,31 +1782,27 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + __wsum csum2; + int end; - for (; list; list = list->next) { - __wsum csum2; - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - csum2 = skb_copy_and_csum_bits(list, - offset - start, - to, copy, 0); - csum = csum_block_add(csum, csum2, pos); - if ((len -= copy) == 0) - return csum; - offset += copy; - to += copy; - pos += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + csum2 = skb_copy_and_csum_bits(frag_iter, + offset - start, + to, copy, 0); + csum = csum_block_add(csum, csum2, pos); + if ((len -= copy) == 0) + return csum; + offset += copy; + to += copy; + pos += copy; } + start = end; } BUG_ON(len); return csum; @@ -2324,8 +2312,7 @@ unsigned int skb_seq_read(unsigned int consumed, const u8 **data, st->frag_data = NULL; } - if (st->root_skb == st->cur_skb && - skb_shinfo(st->root_skb)->frag_list) { + if (st->root_skb == st->cur_skb && skb_has_frags(st->root_skb)) { st->cur_skb = skb_shinfo(st->root_skb)->frag_list; st->frag_idx = 0; goto next_skb; @@ -2636,7 +2623,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) } else skb_get(fskb2); - BUG_ON(skb_shinfo(nskb)->frag_list); + SKB_FRAG_ASSERT(nskb); skb_shinfo(nskb)->frag_list = fskb2; } @@ -2661,30 +2648,40 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) { struct sk_buff *p = *head; struct sk_buff *nskb; + struct skb_shared_info *skbinfo = skb_shinfo(skb); + struct skb_shared_info *pinfo = skb_shinfo(p); unsigned int headroom; unsigned int len = skb_gro_len(skb); + unsigned int offset = skb_gro_offset(skb); + unsigned int headlen = skb_headlen(skb); if (p->len + len >= 65536) return -E2BIG; - if (skb_shinfo(p)->frag_list) + if (pinfo->frag_list) goto merge; - else if (skb_headlen(skb) <= skb_gro_offset(skb)) { - if (skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags > - MAX_SKB_FRAGS) + else if (headlen <= offset) { + skb_frag_t *frag; + skb_frag_t *frag2; + int i = skbinfo->nr_frags; + int nr_frags = pinfo->nr_frags + i; + + offset -= headlen; + + if (nr_frags > MAX_SKB_FRAGS) return -E2BIG; - skb_shinfo(skb)->frags[0].page_offset += - skb_gro_offset(skb) - skb_headlen(skb); - skb_shinfo(skb)->frags[0].size -= - skb_gro_offset(skb) - skb_headlen(skb); + pinfo->nr_frags = nr_frags; + skbinfo->nr_frags = 0; - memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags, - skb_shinfo(skb)->frags, - skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); + frag = pinfo->frags + nr_frags; + frag2 = skbinfo->frags + i; + do { + *--frag = *--frag2; + } while (--i); - skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags; - skb_shinfo(skb)->nr_frags = 0; + frag->page_offset += offset; + frag->size -= offset; skb->truesize -= skb->data_len; skb->len -= skb->data_len; @@ -2715,7 +2712,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p); skb_shinfo(nskb)->frag_list = p; - skb_shinfo(nskb)->gso_size = skb_shinfo(p)->gso_size; + skb_shinfo(nskb)->gso_size = pinfo->gso_size; skb_header_release(p); nskb->prev = p; @@ -2730,16 +2727,13 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) p = nskb; merge: - if (skb_gro_offset(skb) > skb_headlen(skb)) { - skb_shinfo(skb)->frags[0].page_offset += - skb_gro_offset(skb) - skb_headlen(skb); - skb_shinfo(skb)->frags[0].size -= - skb_gro_offset(skb) - skb_headlen(skb); - skb_gro_reset_offset(skb); - skb_gro_pull(skb, skb_headlen(skb)); + if (offset > headlen) { + skbinfo->frags[0].page_offset += offset - headlen; + skbinfo->frags[0].size -= offset - headlen; + offset = headlen; } - __skb_pull(skb, skb_gro_offset(skb)); + __skb_pull(skb, offset); p->prev->next = skb; p->prev = skb; @@ -2786,6 +2780,7 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) { int start = skb_headlen(skb); int i, copy = start - offset; + struct sk_buff *frag_iter; int elt = 0; if (copy > 0) { @@ -2819,26 +2814,22 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - elt += __skb_to_sgvec(list, sg+elt, offset - start, - copy); - if ((len -= copy) == 0) - return elt; - offset += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + elt += __skb_to_sgvec(frag_iter, sg+elt, offset - start, + copy); + if ((len -= copy) == 0) + return elt; + offset += copy; } + start = end; } BUG_ON(len); return elt; @@ -2886,7 +2877,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) return -ENOMEM; /* Easy case. Most of packets will go this way. */ - if (!skb_shinfo(skb)->frag_list) { + if (!skb_has_frags(skb)) { /* A little of trouble, not enough of space for trailer. * This should not happen, when stack is tuned to generate * good frames. OK, on miss we reallocate and reserve even more @@ -2921,7 +2912,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) if (skb1->next == NULL && tailbits) { if (skb_shinfo(skb1)->nr_frags || - skb_shinfo(skb1)->frag_list || + skb_has_frags(skb1) || skb_tailroom(skb1) < tailbits) ntail = tailbits + 128; } @@ -2930,7 +2921,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) skb_cloned(skb1) || ntail || skb_shinfo(skb1)->nr_frags || - skb_shinfo(skb1)->frag_list) { + skb_has_frags(skb1)) { struct sk_buff *skb2; /* Fuck, we are miserable poor guys... */ @@ -3016,12 +3007,12 @@ EXPORT_SYMBOL_GPL(skb_tstamp_tx); */ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off) { - if (unlikely(start > skb->len - 2) || - unlikely((int)start + off > skb->len - 2)) { + if (unlikely(start > skb_headlen(skb)) || + unlikely((int)start + off > skb_headlen(skb) - 2)) { if (net_ratelimit()) printk(KERN_WARNING "bad partial csum: csum=%u/%u len=%u\n", - start, off, skb->len); + start, off, skb_headlen(skb)); return false; } skb->ip_summed = CHECKSUM_PARTIAL; diff --git a/net/core/sock.c b/net/core/sock.c index 7dbf3ffb35cc..06e26b77ad9e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -155,6 +155,7 @@ static const char *af_family_key_strings[AF_MAX+1] = { "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , + "sk_lock-AF_IEEE802154", "sk_lock-AF_MAX" }; static const char *af_family_slock_key_strings[AF_MAX+1] = { @@ -170,6 +171,7 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = { "slock-27" , "slock-28" , "slock-AF_CAN" , "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , + "slock-AF_IEEE802154", "slock-AF_MAX" }; static const char *af_family_clock_key_strings[AF_MAX+1] = { @@ -185,6 +187,7 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = { "clock-27" , "clock-28" , "clock-AF_CAN" , "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , + "clock-AF_IEEE802154", "clock-AF_MAX" }; @@ -212,6 +215,7 @@ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; /* Maximal space eaten by iovec or ancilliary data plus some space */ int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); +EXPORT_SYMBOL(sysctl_optmem_max); static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) { @@ -444,7 +448,7 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) int sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) { - struct sock *sk=sock->sk; + struct sock *sk = sock->sk; int val; int valbool; struct linger ling; @@ -463,15 +467,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname, if (get_user(val, (int __user *)optval)) return -EFAULT; - valbool = val?1:0; + valbool = val ? 1 : 0; lock_sock(sk); - switch(optname) { + switch (optname) { case SO_DEBUG: - if (val && !capable(CAP_NET_ADMIN)) { + if (val && !capable(CAP_NET_ADMIN)) ret = -EACCES; - } else + else sock_valbool_flag(sk, SOCK_DBG, valbool); break; case SO_REUSEADDR: @@ -582,7 +586,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ret = -EINVAL; /* 1003.1g */ break; } - if (copy_from_user(&ling,optval,sizeof(ling))) { + if (copy_from_user(&ling, optval, sizeof(ling))) { ret = -EFAULT; break; } @@ -690,9 +694,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_MARK: if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else { + else sk->sk_mark = val; - } break; /* We implement the SO_SNDLOWAT etc to @@ -704,6 +707,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, release_sock(sk); return ret; } +EXPORT_SYMBOL(sock_setsockopt); int sock_getsockopt(struct socket *sock, int level, int optname, @@ -727,7 +731,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, memset(&v, 0, sizeof(v)); - switch(optname) { + switch (optname) { case SO_DEBUG: v.val = sock_flag(sk, SOCK_DBG); break; @@ -762,7 +766,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, case SO_ERROR: v.val = -sock_error(sk); - if (v.val==0) + if (v.val == 0) v.val = xchg(&sk->sk_err_soft, 0); break; @@ -816,7 +820,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_RCVTIMEO: - lv=sizeof(struct timeval); + lv = sizeof(struct timeval); if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) { v.tm.tv_sec = 0; v.tm.tv_usec = 0; @@ -827,7 +831,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_SNDTIMEO: - lv=sizeof(struct timeval); + lv = sizeof(struct timeval); if (sk->sk_sndtimeo == MAX_SCHEDULE_TIMEOUT) { v.tm.tv_sec = 0; v.tm.tv_usec = 0; @@ -842,7 +846,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_SNDLOWAT: - v.val=1; + v.val = 1; break; case SO_PASSCRED: @@ -1002,8 +1006,9 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, return sk; } +EXPORT_SYMBOL(sk_alloc); -void sk_free(struct sock *sk) +static void __sk_free(struct sock *sk) { struct sk_filter *filter; @@ -1027,6 +1032,18 @@ void sk_free(struct sock *sk) sk_prot_free(sk->sk_prot_creator, sk); } +void sk_free(struct sock *sk) +{ + /* + * We substract one from sk_wmem_alloc and can know if + * some packets are still in some tx queue. + * If not null, sock_wfree() will call __sk_free(sk) later + */ + if (atomic_dec_and_test(&sk->sk_wmem_alloc)) + __sk_free(sk); +} +EXPORT_SYMBOL(sk_free); + /* * Last sock_put should drop referrence to sk->sk_net. It has already * been dropped in sk_change_net. Taking referrence to stopping namespace @@ -1065,7 +1082,10 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; atomic_set(&newsk->sk_rmem_alloc, 0); - atomic_set(&newsk->sk_wmem_alloc, 0); + /* + * sk_wmem_alloc set to one (see sk_free() and sock_wfree()) + */ + atomic_set(&newsk->sk_wmem_alloc, 1); atomic_set(&newsk->sk_omem_alloc, 0); skb_queue_head_init(&newsk->sk_receive_queue); skb_queue_head_init(&newsk->sk_write_queue); @@ -1126,7 +1146,6 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) out: return newsk; } - EXPORT_SYMBOL_GPL(sk_clone); void sk_setup_caps(struct sock *sk, struct dst_entry *dst) @@ -1170,13 +1189,20 @@ void __init sk_init(void) void sock_wfree(struct sk_buff *skb) { struct sock *sk = skb->sk; + int res; /* In case it might be waiting for more memory. */ - atomic_sub(skb->truesize, &sk->sk_wmem_alloc); + res = atomic_sub_return(skb->truesize, &sk->sk_wmem_alloc); if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) sk->sk_write_space(sk); - sock_put(sk); + /* + * if sk_wmem_alloc reached 0, we are last user and should + * free this sock, as sk_free() call could not do it. + */ + if (res == 0) + __sk_free(sk); } +EXPORT_SYMBOL(sock_wfree); /* * Read buffer destructor automatically called from kfree_skb. @@ -1188,6 +1214,7 @@ void sock_rfree(struct sk_buff *skb) atomic_sub(skb->truesize, &sk->sk_rmem_alloc); sk_mem_uncharge(skb->sk, skb->truesize); } +EXPORT_SYMBOL(sock_rfree); int sock_i_uid(struct sock *sk) @@ -1199,6 +1226,7 @@ int sock_i_uid(struct sock *sk) read_unlock(&sk->sk_callback_lock); return uid; } +EXPORT_SYMBOL(sock_i_uid); unsigned long sock_i_ino(struct sock *sk) { @@ -1209,6 +1237,7 @@ unsigned long sock_i_ino(struct sock *sk) read_unlock(&sk->sk_callback_lock); return ino; } +EXPORT_SYMBOL(sock_i_ino); /* * Allocate a skb from the socket's send buffer. @@ -1217,7 +1246,7 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, gfp_t priority) { if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { - struct sk_buff * skb = alloc_skb(size, priority); + struct sk_buff *skb = alloc_skb(size, priority); if (skb) { skb_set_owner_w(skb, sk); return skb; @@ -1225,6 +1254,7 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, } return NULL; } +EXPORT_SYMBOL(sock_wmalloc); /* * Allocate a skb from the socket's receive buffer. @@ -1261,6 +1291,7 @@ void *sock_kmalloc(struct sock *sk, int size, gfp_t priority) } return NULL; } +EXPORT_SYMBOL(sock_kmalloc); /* * Free an option memory block. @@ -1270,11 +1301,12 @@ void sock_kfree_s(struct sock *sk, void *mem, int size) kfree(mem); atomic_sub(size, &sk->sk_omem_alloc); } +EXPORT_SYMBOL(sock_kfree_s); /* It is almost wait_for_tcp_memory minus release_sock/lock_sock. I think, these locks should be removed for datagram sockets. */ -static long sock_wait_for_wmem(struct sock * sk, long timeo) +static long sock_wait_for_wmem(struct sock *sk, long timeo) { DEFINE_WAIT(wait); @@ -1392,6 +1424,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, { return sock_alloc_send_pskb(sk, size, 0, noblock, errcode); } +EXPORT_SYMBOL(sock_alloc_send_skb); static void __lock_sock(struct sock *sk) { @@ -1460,7 +1493,6 @@ int sk_wait_data(struct sock *sk, long *timeo) finish_wait(sk->sk_sleep, &wait); return rc; } - EXPORT_SYMBOL(sk_wait_data); /** @@ -1541,7 +1573,6 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) atomic_sub(amt, prot->memory_allocated); return 0; } - EXPORT_SYMBOL(__sk_mem_schedule); /** @@ -1560,7 +1591,6 @@ void __sk_mem_reclaim(struct sock *sk) (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0])) *prot->memory_pressure = 0; } - EXPORT_SYMBOL(__sk_mem_reclaim); @@ -1575,78 +1605,92 @@ int sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_bind); int sock_no_connect(struct socket *sock, struct sockaddr *saddr, int len, int flags) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_connect); int sock_no_socketpair(struct socket *sock1, struct socket *sock2) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_socketpair); int sock_no_accept(struct socket *sock, struct socket *newsock, int flags) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_accept); int sock_no_getname(struct socket *sock, struct sockaddr *saddr, int *len, int peer) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_getname); -unsigned int sock_no_poll(struct file * file, struct socket *sock, poll_table *pt) +unsigned int sock_no_poll(struct file *file, struct socket *sock, poll_table *pt) { return 0; } +EXPORT_SYMBOL(sock_no_poll); int sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_ioctl); int sock_no_listen(struct socket *sock, int backlog) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_listen); int sock_no_shutdown(struct socket *sock, int how) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_shutdown); int sock_no_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_setsockopt); int sock_no_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_getsockopt); int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_sendmsg); int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags) { return -EOPNOTSUPP; } +EXPORT_SYMBOL(sock_no_recvmsg); int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma) { /* Mirror missing mmap method error code */ return -ENODEV; } +EXPORT_SYMBOL(sock_no_mmap); ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { @@ -1660,6 +1704,7 @@ ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, siz kunmap(page); return res; } +EXPORT_SYMBOL(sock_no_sendpage); /* * Default Socket Callbacks @@ -1723,6 +1768,7 @@ void sk_send_sigurg(struct sock *sk) if (send_sigurg(&sk->sk_socket->file->f_owner)) sk_wake_async(sk, SOCK_WAKE_URG, POLL_PRI); } +EXPORT_SYMBOL(sk_send_sigurg); void sk_reset_timer(struct sock *sk, struct timer_list* timer, unsigned long expires) @@ -1730,7 +1776,6 @@ void sk_reset_timer(struct sock *sk, struct timer_list* timer, if (!mod_timer(timer, expires)) sock_hold(sk); } - EXPORT_SYMBOL(sk_reset_timer); void sk_stop_timer(struct sock *sk, struct timer_list* timer) @@ -1738,7 +1783,6 @@ void sk_stop_timer(struct sock *sk, struct timer_list* timer) if (timer_pending(timer) && del_timer(timer)) __sock_put(sk); } - EXPORT_SYMBOL(sk_stop_timer); void sock_init_data(struct socket *sock, struct sock *sk) @@ -1795,8 +1839,10 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_stamp = ktime_set(-1L, 0); atomic_set(&sk->sk_refcnt, 1); + atomic_set(&sk->sk_wmem_alloc, 1); atomic_set(&sk->sk_drops, 0); } +EXPORT_SYMBOL(sock_init_data); void lock_sock_nested(struct sock *sk, int subclass) { @@ -1812,7 +1858,6 @@ void lock_sock_nested(struct sock *sk, int subclass) mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); local_bh_enable(); } - EXPORT_SYMBOL(lock_sock_nested); void release_sock(struct sock *sk) @@ -1895,7 +1940,6 @@ int sock_common_getsockopt(struct socket *sock, int level, int optname, return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen); } - EXPORT_SYMBOL(sock_common_getsockopt); #ifdef CONFIG_COMPAT @@ -1925,7 +1969,6 @@ int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = addr_len; return err; } - EXPORT_SYMBOL(sock_common_recvmsg); /* @@ -1938,7 +1981,6 @@ int sock_common_setsockopt(struct socket *sock, int level, int optname, return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen); } - EXPORT_SYMBOL(sock_common_setsockopt); #ifdef CONFIG_COMPAT @@ -1989,7 +2031,6 @@ void sk_common_release(struct sock *sk) sk_refcnt_debug_release(sk); sock_put(sk); } - EXPORT_SYMBOL(sk_common_release); static DEFINE_RWLOCK(proto_list_lock); @@ -2171,7 +2212,6 @@ int proto_register(struct proto *prot, int alloc_slab) out: return -ENOBUFS; } - EXPORT_SYMBOL(proto_register); void proto_unregister(struct proto *prot) @@ -2198,7 +2238,6 @@ void proto_unregister(struct proto *prot) prot->twsk_prot->twsk_slab = NULL; } } - EXPORT_SYMBOL(proto_unregister); #ifdef CONFIG_PROC_FS @@ -2324,33 +2363,3 @@ static int __init proto_init(void) subsys_initcall(proto_init); #endif /* PROC_FS */ - -EXPORT_SYMBOL(sk_alloc); -EXPORT_SYMBOL(sk_free); -EXPORT_SYMBOL(sk_send_sigurg); -EXPORT_SYMBOL(sock_alloc_send_skb); -EXPORT_SYMBOL(sock_init_data); -EXPORT_SYMBOL(sock_kfree_s); -EXPORT_SYMBOL(sock_kmalloc); -EXPORT_SYMBOL(sock_no_accept); -EXPORT_SYMBOL(sock_no_bind); -EXPORT_SYMBOL(sock_no_connect); -EXPORT_SYMBOL(sock_no_getname); -EXPORT_SYMBOL(sock_no_getsockopt); -EXPORT_SYMBOL(sock_no_ioctl); -EXPORT_SYMBOL(sock_no_listen); -EXPORT_SYMBOL(sock_no_mmap); -EXPORT_SYMBOL(sock_no_poll); -EXPORT_SYMBOL(sock_no_recvmsg); -EXPORT_SYMBOL(sock_no_sendmsg); -EXPORT_SYMBOL(sock_no_sendpage); -EXPORT_SYMBOL(sock_no_setsockopt); -EXPORT_SYMBOL(sock_no_shutdown); -EXPORT_SYMBOL(sock_no_socketpair); -EXPORT_SYMBOL(sock_rfree); -EXPORT_SYMBOL(sock_setsockopt); -EXPORT_SYMBOL(sock_wfree); -EXPORT_SYMBOL(sock_wmalloc); -EXPORT_SYMBOL(sock_i_uid); -EXPORT_SYMBOL(sock_i_ino); -EXPORT_SYMBOL(sysctl_optmem_max); diff --git a/net/core/stream.c b/net/core/stream.c index 8727cead64ad..a37debfeb1b2 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -33,7 +33,8 @@ void sk_stream_write_space(struct sock *sk) clear_bit(SOCK_NOSPACE, &sock->flags); if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible(sk->sk_sleep); + wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | + POLLWRNORM | POLLWRBAND); if (sock->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT); } diff --git a/net/core/user_dma.c b/net/core/user_dma.c index 164b090d5ac3..25d717ebc92e 100644 --- a/net/core/user_dma.c +++ b/net/core/user_dma.c @@ -51,6 +51,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, { int start = skb_headlen(skb); int i, copy = start - offset; + struct sk_buff *frag_iter; dma_cookie_t cookie = 0; /* Copy header. */ @@ -94,31 +95,28 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - copy = end - offset; - if (copy > 0) { - if (copy > len) - copy = len; - cookie = dma_skb_copy_datagram_iovec(chan, list, - offset - start, to, copy, - pinned_list); - if (cookie < 0) - goto fault; - len -= copy; - if (len == 0) - goto end; - offset += copy; - } - start = end; + end = start + frag_iter->len; + copy = end - offset; + if (copy > 0) { + if (copy > len) + copy = len; + cookie = dma_skb_copy_datagram_iovec(chan, frag_iter, + offset - start, + to, copy, + pinned_list); + if (cookie < 0) + goto fault; + len -= copy; + if (len == 0) + goto end; + offset += copy; } + start = end; } end: diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index d1dd95289b89..a0a36c9e6cce 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -452,7 +452,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, struct sk_buff *skb) { struct rtable *rt; - struct flowi fl = { .oif = skb->rtable->rt_iif, + struct flowi fl = { .oif = skb_rtable(skb)->rt_iif, .nl_u = { .ip4_u = { .daddr = ip_hdr(skb)->saddr, .saddr = ip_hdr(skb)->daddr, @@ -507,14 +507,14 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) const struct iphdr *rxiph; struct sk_buff *skb; struct dst_entry *dst; - struct net *net = dev_net(rxskb->dst->dev); + struct net *net = dev_net(skb_dst(rxskb)->dev); struct sock *ctl_sk = net->dccp.v4_ctl_sk; /* Never send a reset in response to a reset. */ if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) return; - if (rxskb->rtable->rt_type != RTN_LOCAL) + if (skb_rtable(rxskb)->rt_type != RTN_LOCAL) return; dst = dccp_v4_route_skb(net, ctl_sk, rxskb); @@ -528,7 +528,7 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) rxiph = ip_hdr(rxskb); dccp_hdr(skb)->dccph_checksum = dccp_v4_csum_finish(skb, rxiph->saddr, rxiph->daddr); - skb->dst = dst_clone(dst); + skb_dst_set(skb, dst_clone(dst)); bh_lock_sock(ctl_sk); err = ip_build_and_send_pkt(skb, ctl_sk, @@ -567,7 +567,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ - if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) + if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) return 0; /* discard, don't send a reset here */ if (dccp_bad_service_code(sk, service)) { diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index b963f35c65f6..05ea7440d9e5 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -314,8 +314,9 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) struct ipv6hdr *rxip6h; struct sk_buff *skb; struct flowi fl; - struct net *net = dev_net(rxskb->dst->dev); + struct net *net = dev_net(skb_dst(rxskb)->dev); struct sock *ctl_sk = net->dccp.v6_ctl_sk; + struct dst_entry *dst; if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET) return; @@ -342,8 +343,9 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) security_skb_classify_flow(rxskb, &fl); /* sk = NULL, but it is safe for now. RST socket required. */ - if (!ip6_dst_lookup(ctl_sk, &skb->dst, &fl)) { - if (xfrm_lookup(net, &skb->dst, &fl, NULL, 0) >= 0) { + if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { + if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { + skb_dst_set(skb, dst); ip6_xmit(ctl_sk, skb, &fl, NULL, 0); DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); diff --git a/net/dccp/output.c b/net/dccp/output.c index 36bcc00654d3..c0e88c16d088 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -350,7 +350,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, /* Reserve space for headers. */ skb_reserve(skb, sk->sk_prot->max_header); - skb->dst = dst_clone(dst); + skb_dst_set(skb, dst_clone(dst)); dreq = dccp_rsk(req); if (inet_rsk(req)->acked) /* increase ISS upon retransmission */ diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 9647d911f916..a5e3a593e472 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1075,6 +1075,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) int err = 0; unsigned char type; long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); + struct dst_entry *dst; lock_sock(sk); @@ -1102,8 +1103,9 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) } release_sock(sk); - dst_release(xchg(&newsk->sk_dst_cache, skb->dst)); - skb->dst = NULL; + dst = skb_dst(skb); + dst_release(xchg(&newsk->sk_dst_cache, dst)); + skb_dst_set(skb, NULL); DN_SK(newsk)->state = DN_CR; DN_SK(newsk)->addrrem = cb->src_port; @@ -1250,14 +1252,8 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (skb) { amount = skb->len; } else { - skb = sk->sk_receive_queue.next; - for (;;) { - if (skb == - (struct sk_buff *)&sk->sk_receive_queue) - break; + skb_queue_walk(&sk->sk_receive_queue, skb) amount += skb->len; - skb = skb->next; - } } release_sock(sk); err = put_user(amount, (int __user *)arg); @@ -1644,13 +1640,13 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int target) { - struct sk_buff *skb = q->next; + struct sk_buff *skb; int len = 0; if (flags & MSG_OOB) return !skb_queue_empty(q) ? 1 : 0; - while(skb != (struct sk_buff *)q) { + skb_queue_walk(q, skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); len += skb->len; @@ -1666,8 +1662,6 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int /* minimum data length for read exceeded */ if (len >= target) return 1; - - skb = skb->next; } return 0; @@ -1683,7 +1677,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, size_t target = size > 1 ? 1 : 0; size_t copied = 0; int rv = 0; - struct sk_buff *skb, *nskb; + struct sk_buff *skb, *n; struct dn_skb_cb *cb = NULL; unsigned char eor = 0; long timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); @@ -1758,7 +1752,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, finish_wait(sk->sk_sleep, &wait); } - for(skb = queue->next; skb != (struct sk_buff *)queue; skb = nskb) { + skb_queue_walk_safe(queue, skb, n) { unsigned int chunk = skb->len; cb = DN_SKB_CB(skb); @@ -1775,7 +1769,6 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, skb_pull(skb, chunk); eor = cb->nsp_flags & 0x40; - nskb = skb->next; if (skb->len == 0) { skb_unlink(skb, queue); diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 05b5aa05e50e..923786bd6d01 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -204,7 +204,7 @@ static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb) static int dn_neigh_output_packet(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct dn_route *rt = (struct dn_route *)dst; struct neighbour *neigh = dst->neighbour; struct net_device *dev = neigh->dev; @@ -224,7 +224,7 @@ static int dn_neigh_output_packet(struct sk_buff *skb) static int dn_long_output(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct neighbour *neigh = dst->neighbour; struct net_device *dev = neigh->dev; int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; @@ -270,7 +270,7 @@ static int dn_long_output(struct sk_buff *skb) static int dn_short_output(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct neighbour *neigh = dst->neighbour; struct net_device *dev = neigh->dev; int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; @@ -313,7 +313,7 @@ static int dn_short_output(struct sk_buff *skb) */ static int dn_phase3_output(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct neighbour *neigh = dst->neighbour; struct net_device *dev = neigh->dev; int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 5d8a2a56fd39..932408dca86d 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -578,6 +578,7 @@ static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb) static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue) { int err; + int skb_len; /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces number of warnings when compiling with -W --ANK @@ -592,22 +593,12 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig if (err) goto out; + skb_len = skb->len; skb_set_owner_r(skb, sk); skb_queue_tail(queue, skb); - /* This code only runs from BH or BH protected context. - * Therefore the plain read_lock is ok here. -DaveM - */ - read_lock(&sk->sk_callback_lock); - if (!sock_flag(sk, SOCK_DEAD)) { - struct socket *sock = sk->sk_socket; - wake_up_interruptible(sk->sk_sleep); - if (sock && sock->fasync_list && - !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) - __kill_fasync(sock->fasync_list, sig, - (sig == SIGURG) ? POLL_PRI : POLL_IN); - } - read_unlock(&sk->sk_callback_lock); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, skb_len); out: return err; } diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index 2013c25b7f5a..a65e929ce76c 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -85,7 +85,7 @@ static void dn_nsp_send(struct sk_buff *skb) dst = sk_dst_check(sk, 0); if (dst) { try_again: - skb->dst = dst; + skb_dst_set(skb, dst); dst_output(skb); return; } @@ -382,7 +382,7 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dn_scp *scp = DN_SK(sk); - struct sk_buff *skb2, *list, *ack = NULL; + struct sk_buff *skb2, *n, *ack = NULL; int wakeup = 0; int try_retrans = 0; unsigned long reftime = cb->stamp; @@ -390,9 +390,7 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff unsigned short xmit_count; unsigned short segnum; - skb2 = q->next; - list = (struct sk_buff *)q; - while(list != skb2) { + skb_queue_walk_safe(q, skb2, n) { struct dn_skb_cb *cb2 = DN_SKB_CB(skb2); if (dn_before_or_equal(cb2->segnum, acknum)) @@ -400,8 +398,6 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff /* printk(KERN_DEBUG "ack: %s %04x %04x\n", ack ? "ACK" : "SKIP", (int)cb2->segnum, (int)acknum); */ - skb2 = skb2->next; - if (ack == NULL) continue; @@ -586,7 +582,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, * to be able to send disc packets out which have no socket * associations. */ - skb->dst = dst_clone(dst); + skb_dst_set(skb, dst_clone(dst)); dst_output(skb); } @@ -615,7 +611,7 @@ void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, int ddl = 0; gfp_t gfp = GFP_ATOMIC; - dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb->dst, ddl, + dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb_dst(skb), ddl, NULL, cb->src_port, cb->dst_port); } diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 0cc4394117df..1d6ca8a98dc6 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -678,7 +678,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type static int dn_output(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct dn_route *rt = (struct dn_route *)dst; struct net_device *dev = dst->dev; struct dn_skb_cb *cb = DN_SKB_CB(skb); @@ -717,7 +717,7 @@ static int dn_output(struct sk_buff *skb) static int dn_forward(struct sk_buff *skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct dn_dev *dn_db = dst->dev->dn_ptr; struct dn_route *rt; struct neighbour *neigh = dst->neighbour; @@ -730,7 +730,7 @@ static int dn_forward(struct sk_buff *skb) goto drop; /* Ensure that we have enough space for headers */ - rt = (struct dn_route *)skb->dst; + rt = (struct dn_route *)skb_dst(skb); header_len = dn_db->use_long ? 21 : 6; if (skb_cow(skb, LL_RESERVED_SPACE(rt->u.dst.dev)+header_len)) goto drop; @@ -1392,7 +1392,8 @@ static int dn_route_input_slow(struct sk_buff *skb) goto e_neighbour; hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst); - dn_insert_route(rt, hash, (struct dn_route **)&skb->dst); + dn_insert_route(rt, hash, &rt); + skb_dst_set(skb, &rt->u.dst); done: if (neigh) @@ -1424,7 +1425,7 @@ static int dn_route_input(struct sk_buff *skb) struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned hash = dn_hash(cb->src, cb->dst); - if (skb->dst) + if (skb_dst(skb)) return 0; rcu_read_lock(); @@ -1437,7 +1438,7 @@ static int dn_route_input(struct sk_buff *skb) (rt->fl.iif == cb->iif)) { dst_use(&rt->u.dst, jiffies); rcu_read_unlock(); - skb->dst = (struct dst_entry *)rt; + skb_dst_set(skb, (struct dst_entry *)rt); return 0; } } @@ -1449,7 +1450,7 @@ static int dn_route_input(struct sk_buff *skb) static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait, unsigned int flags) { - struct dn_route *rt = (struct dn_route *)skb->dst; + struct dn_route *rt = (struct dn_route *)skb_dst(skb); struct rtmsg *r; struct nlmsghdr *nlh; unsigned char *b = skb_tail_pointer(skb); @@ -1554,7 +1555,7 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void err = dn_route_input(skb); local_bh_enable(); memset(cb, 0, sizeof(struct dn_skb_cb)); - rt = (struct dn_route *)skb->dst; + rt = (struct dn_route *)skb_dst(skb); if (!err && -rt->u.dst.error) err = rt->u.dst.error; } else { @@ -1570,7 +1571,7 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void skb->dev = NULL; if (err) goto out_free; - skb->dst = &rt->u.dst; + skb_dst_set(skb, &rt->u.dst); if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; @@ -1622,15 +1623,15 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb) rt = rcu_dereference(rt->u.dst.dn_next), idx++) { if (idx < s_idx) continue; - skb->dst = dst_clone(&rt->u.dst); + skb_dst_set(skb, dst_clone(&rt->u.dst)); if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1, NLM_F_MULTI) <= 0) { - dst_release(xchg(&skb->dst, NULL)); + skb_dst_drop(skb); rcu_read_unlock_bh(); goto done; } - dst_release(xchg(&skb->dst, NULL)); + skb_dst_drop(skb); } rcu_read_unlock_bh(); } diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 14fbca55e908..72495f25269f 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -115,7 +115,7 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) } static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, + struct fib_rule_hdr *frh, struct nlattr **tb) { int err = -EINVAL; @@ -192,7 +192,7 @@ unsigned dnet_addr_type(__le16 addr) } static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh) + struct fib_rule_hdr *frh) { struct dn_fib_rule *r = (struct dn_fib_rule *)rule; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index ed131181215d..2175e6d5cc8d 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -67,7 +67,7 @@ static int dsa_slave_open(struct net_device *dev) return -ENETDOWN; if (compare_ether_addr(dev->dev_addr, master->dev_addr)) { - err = dev_unicast_add(master, dev->dev_addr, ETH_ALEN); + err = dev_unicast_add(master, dev->dev_addr); if (err < 0) goto out; } @@ -90,7 +90,7 @@ static int dsa_slave_open(struct net_device *dev) dev_set_allmulti(master, -1); del_unicast: if (compare_ether_addr(dev->dev_addr, master->dev_addr)) - dev_unicast_delete(master, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(master, dev->dev_addr); out: return err; } @@ -108,7 +108,7 @@ static int dsa_slave_close(struct net_device *dev) dev_set_promiscuity(master, -1); if (compare_ether_addr(dev->dev_addr, master->dev_addr)) - dev_unicast_delete(master, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(master, dev->dev_addr); return 0; } @@ -147,13 +147,13 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a) goto out; if (compare_ether_addr(addr->sa_data, master->dev_addr)) { - err = dev_unicast_add(master, addr->sa_data, ETH_ALEN); + err = dev_unicast_add(master, addr->sa_data); if (err < 0) return err; } if (compare_ether_addr(dev->dev_addr, master->dev_addr)) - dev_unicast_delete(master, dev->dev_addr, ETH_ALEN); + dev_unicast_delete(master, dev->dev_addr); out: memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 6f479fa522c3..8121bf0029e3 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -901,15 +901,10 @@ static void aun_tx_ack(unsigned long seq, int result) struct ec_cb *eb; spin_lock_irqsave(&aun_queue_lock, flags); - skb = skb_peek(&aun_queue); - while (skb && skb != (struct sk_buff *)&aun_queue) - { - struct sk_buff *newskb = skb->next; + skb_queue_walk(&aun_queue, skb) { eb = (struct ec_cb *)&skb->cb; if (eb->seq == seq) goto foundit; - - skb = newskb; } spin_unlock_irqrestore(&aun_queue_lock, flags); printk(KERN_DEBUG "AUN: unknown sequence %ld\n", seq); @@ -982,23 +977,18 @@ static void aun_data_available(struct sock *sk, int slen) static void ab_cleanup(unsigned long h) { - struct sk_buff *skb; + struct sk_buff *skb, *n; unsigned long flags; spin_lock_irqsave(&aun_queue_lock, flags); - skb = skb_peek(&aun_queue); - while (skb && skb != (struct sk_buff *)&aun_queue) - { - struct sk_buff *newskb = skb->next; + skb_queue_walk_safe(&aun_queue, skb, n) { struct ec_cb *eb = (struct ec_cb *)&skb->cb; - if ((jiffies - eb->start) > eb->timeout) - { + if ((jiffies - eb->start) > eb->timeout) { tx_result(skb->sk, eb->cookie, ECTYPE_TRANSMIT_NOT_PRESENT); skb_unlink(skb, &aun_queue); kfree_skb(skb); } - skb = newskb; } spin_unlock_irqrestore(&aun_queue_lock, flags); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 280352aba403..5a883affecd3 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -337,11 +337,6 @@ const struct header_ops eth_header_ops ____cacheline_aligned = { void ether_setup(struct net_device *dev) { dev->header_ops = ð_header_ops; -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev->change_mtu = eth_change_mtu; - dev->set_mac_address = eth_mac_addr; - dev->validate_addr = eth_validate_addr; -#endif dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->mtu = ETH_DATA_LEN; diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig new file mode 100644 index 000000000000..1c1de97d264a --- /dev/null +++ b/net/ieee802154/Kconfig @@ -0,0 +1,12 @@ +config IEEE802154 + tristate "IEEE Std 802.15.4 Low-Rate Wireless Personal Area Networks support (EXPERIMENTAL)" + depends on EXPERIMENTAL + ---help--- + IEEE Std 802.15.4 defines a low data rate, low power and low + complexity short range wireless personal area networks. It was + designed to organise networks of sensors, switches, etc automation + devices. Maximum allowed data rate is 250 kb/s and typical personal + operating space around 10m. + + Say Y here to compile LR-WPAN support into the kernel or say M to + compile it as modules. diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile new file mode 100644 index 000000000000..f99338a26100 --- /dev/null +++ b/net/ieee802154/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_IEEE802154) += nl802154.o af_802154.o +nl802154-y := netlink.o nl_policy.o +af_802154-y := af_ieee802154.o raw.o dgram.o + +ccflags-y += -Wall -DDEBUG diff --git a/net/ieee802154/af802154.h b/net/ieee802154/af802154.h new file mode 100644 index 000000000000..b1ec52537522 --- /dev/null +++ b/net/ieee802154/af802154.h @@ -0,0 +1,36 @@ +/* + * Internal interfaces for ieee 802.15.4 address family. + * + * Copyright 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. + * + * Written by: + * Sergey Lapin + * Dmitry Eremin-Solenikov + */ + +#ifndef AF802154_H +#define AF802154_H + +struct sk_buff; +struct net_devce; +extern struct proto ieee802154_raw_prot; +extern struct proto ieee802154_dgram_prot; +void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb); +int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb); +struct net_device *ieee802154_get_dev(struct net *net, + struct ieee802154_addr *addr); + +#endif diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c new file mode 100644 index 000000000000..882a927cefae --- /dev/null +++ b/net/ieee802154/af_ieee802154.c @@ -0,0 +1,372 @@ +/* + * IEEE802154.4 socket interface + * + * Copyright 2007, 2008 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. + * + * Written by: + * Sergey Lapin + * Maxim Gorbachyov + */ + +#include +#include +#include +#include +#include +#include /* For TIOCOUTQ/INQ */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "af802154.h" + +#define DBG_DUMP(data, len) { \ + int i; \ + pr_debug("function: %s: data: len %d:\n", __func__, len); \ + for (i = 0; i < len; i++) {\ + pr_debug("%02x: %02x\n", i, (data)[i]); \ + } \ +} + +/* + * Utility function for families + */ +struct net_device *ieee802154_get_dev(struct net *net, + struct ieee802154_addr *addr) +{ + struct net_device *dev = NULL; + struct net_device *tmp; + u16 pan_id, short_addr; + + switch (addr->addr_type) { + case IEEE802154_ADDR_LONG: + rtnl_lock(); + dev = dev_getbyhwaddr(net, ARPHRD_IEEE802154, addr->hwaddr); + if (dev) + dev_hold(dev); + rtnl_unlock(); + break; + case IEEE802154_ADDR_SHORT: + if (addr->pan_id == 0xffff || + addr->short_addr == IEEE802154_ADDR_UNDEF || + addr->short_addr == 0xffff) + break; + + rtnl_lock(); + + for_each_netdev(net, tmp) { + if (tmp->type != ARPHRD_IEEE802154) + continue; + + pan_id = ieee802154_mlme_ops(tmp)->get_pan_id(tmp); + short_addr = + ieee802154_mlme_ops(tmp)->get_short_addr(tmp); + + if (pan_id == addr->pan_id && + short_addr == addr->short_addr) { + dev = tmp; + dev_hold(dev); + break; + } + } + + rtnl_unlock(); + break; + default: + pr_warning("Unsupported ieee802154 address type: %d\n", + addr->addr_type); + break; + } + + return dev; +} + +static int ieee802154_sock_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (sk) { + sock->sk = NULL; + sk->sk_prot->close(sk, 0); + } + return 0; +} +static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t len) +{ + struct sock *sk = sock->sk; + + return sk->sk_prot->sendmsg(iocb, sk, msg, len); +} + +static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, + int addr_len) +{ + struct sock *sk = sock->sk; + + if (sk->sk_prot->bind) + return sk->sk_prot->bind(sk, uaddr, addr_len); + + return sock_no_bind(sock, uaddr, addr_len); +} + +static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) +{ + struct sock *sk = sock->sk; + + if (uaddr->sa_family == AF_UNSPEC) + return sk->sk_prot->disconnect(sk, flags); + + return sk->sk_prot->connect(sk, uaddr, addr_len); +} + +static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, + unsigned int cmd) +{ + struct ifreq ifr; + int ret = -EINVAL; + struct net_device *dev; + + if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) + return -EFAULT; + + ifr.ifr_name[IFNAMSIZ-1] = 0; + + dev_load(sock_net(sk), ifr.ifr_name); + dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); + if (dev->type == ARPHRD_IEEE802154 || + dev->type == ARPHRD_IEEE802154_PHY) + ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); + + if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) + ret = -EFAULT; + dev_put(dev); + + return ret; +} + +static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + struct sock *sk = sock->sk; + + switch (cmd) { + case SIOCGSTAMP: + return sock_get_timestamp(sk, (struct timeval __user *)arg); + case SIOCGSTAMPNS: + return sock_get_timestampns(sk, (struct timespec __user *)arg); + case SIOCGIFADDR: + case SIOCSIFADDR: + return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, + cmd); + default: + if (!sk->sk_prot->ioctl) + return -ENOIOCTLCMD; + return sk->sk_prot->ioctl(sk, cmd, arg); + } +} + +static const struct proto_ops ieee802154_raw_ops = { + .family = PF_IEEE802154, + .owner = THIS_MODULE, + .release = ieee802154_sock_release, + .bind = ieee802154_sock_bind, + .connect = ieee802154_sock_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = sock_no_getname, + .poll = datagram_poll, + .ioctl = ieee802154_sock_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = ieee802154_sock_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif +}; + +static const struct proto_ops ieee802154_dgram_ops = { + .family = PF_IEEE802154, + .owner = THIS_MODULE, + .release = ieee802154_sock_release, + .bind = ieee802154_sock_bind, + .connect = ieee802154_sock_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = sock_no_getname, + .poll = datagram_poll, + .ioctl = ieee802154_sock_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = ieee802154_sock_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif +}; + + +/* + * Create a socket. Initialise the socket, blank the addresses + * set the state. + */ +static int ieee802154_create(struct net *net, struct socket *sock, + int protocol) +{ + struct sock *sk; + int rc; + struct proto *proto; + const struct proto_ops *ops; + + if (net != &init_net) + return -EAFNOSUPPORT; + + switch (sock->type) { + case SOCK_RAW: + proto = &ieee802154_raw_prot; + ops = &ieee802154_raw_ops; + break; + case SOCK_DGRAM: + proto = &ieee802154_dgram_prot; + ops = &ieee802154_dgram_ops; + break; + default: + rc = -ESOCKTNOSUPPORT; + goto out; + } + + rc = -ENOMEM; + sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto); + if (!sk) + goto out; + rc = 0; + + sock->ops = ops; + + sock_init_data(sock, sk); + /* FIXME: sk->sk_destruct */ + sk->sk_family = PF_IEEE802154; + + /* Checksums on by default */ + sock_set_flag(sk, SOCK_ZAPPED); + + if (sk->sk_prot->hash) + sk->sk_prot->hash(sk); + + if (sk->sk_prot->init) { + rc = sk->sk_prot->init(sk); + if (rc) + sk_common_release(sk); + } +out: + return rc; +} + +static struct net_proto_family ieee802154_family_ops = { + .family = PF_IEEE802154, + .create = ieee802154_create, + .owner = THIS_MODULE, +}; + +static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) +{ + DBG_DUMP(skb->data, skb->len); + if (!netif_running(dev)) + return -ENODEV; + pr_debug("got frame, type %d, dev %p\n", dev->type, dev); + + if (!net_eq(dev_net(dev), &init_net)) + goto drop; + + ieee802154_raw_deliver(dev, skb); + + if (dev->type != ARPHRD_IEEE802154) + goto drop; + + if (skb->pkt_type != PACKET_OTHERHOST) + return ieee802154_dgram_deliver(dev, skb); + +drop: + kfree_skb(skb); + return NET_RX_DROP; +} + + +static struct packet_type ieee802154_packet_type = { + .type = __constant_htons(ETH_P_IEEE802154), + .func = ieee802154_rcv, +}; + +static int __init af_ieee802154_init(void) +{ + int rc = -EINVAL; + + rc = proto_register(&ieee802154_raw_prot, 1); + if (rc) + goto out; + + rc = proto_register(&ieee802154_dgram_prot, 1); + if (rc) + goto err_dgram; + + /* Tell SOCKET that we are alive */ + rc = sock_register(&ieee802154_family_ops); + if (rc) + goto err_sock; + dev_add_pack(&ieee802154_packet_type); + + rc = 0; + goto out; + +err_sock: + proto_unregister(&ieee802154_dgram_prot); +err_dgram: + proto_unregister(&ieee802154_raw_prot); +out: + return rc; +} +static void __exit af_ieee802154_remove(void) +{ + dev_remove_pack(&ieee802154_packet_type); + sock_unregister(PF_IEEE802154); + proto_unregister(&ieee802154_dgram_prot); + proto_unregister(&ieee802154_raw_prot); +} + +module_init(af_ieee802154_init); +module_exit(af_ieee802154_remove); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETPROTO(PF_IEEE802154); diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c new file mode 100644 index 000000000000..1779677aed46 --- /dev/null +++ b/net/ieee802154/dgram.c @@ -0,0 +1,394 @@ +/* + * ZigBee socket interface + * + * Copyright 2007, 2008 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. + * + * Written by: + * Sergey Lapin + * Dmitry Eremin-Solenikov + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "af802154.h" + +static HLIST_HEAD(dgram_head); +static DEFINE_RWLOCK(dgram_lock); + +struct dgram_sock { + struct sock sk; + + int bound; + struct ieee802154_addr src_addr; + struct ieee802154_addr dst_addr; +}; + +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); + sk_add_node(sk, &dgram_head); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + write_unlock_bh(&dgram_lock); +} + +static void dgram_unhash(struct sock *sk) +{ + write_lock_bh(&dgram_lock); + if (sk_del_node_init(sk)) + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + write_unlock_bh(&dgram_lock); +} + +static int dgram_init(struct sock *sk) +{ + struct dgram_sock *ro = dgram_sk(sk); + + ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; + ro->dst_addr.pan_id = 0xffff; + memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); + return 0; +} + +static void dgram_close(struct sock *sk, long timeout) +{ + sk_common_release(sk); +} + +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; + struct net_device *dev; + + ro->bound = 0; + + if (len < sizeof(*addr)) + return -EINVAL; + + if (addr->family != AF_IEEE802154) + return -EINVAL; + + lock_sock(sk); + + dev = ieee802154_get_dev(sock_net(sk), &addr->addr); + if (!dev) { + err = -ENODEV; + goto out; + } + + if (dev->type != ARPHRD_IEEE802154) { + err = -ENODEV; + goto out_put; + } + + memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee802154_addr)); + + ro->bound = 1; +out_put: + dev_put(dev); +out: + release_sock(sk); + + return err; +} + +static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) +{ + switch (cmd) { + case SIOCOUTQ: + { + int amount = atomic_read(&sk->sk_wmem_alloc); + return put_user(amount, (int __user *)arg); + } + + case SIOCINQ: + { + struct sk_buff *skb; + unsigned long amount; + + amount = 0; + spin_lock_bh(&sk->sk_receive_queue.lock); + skb = skb_peek(&sk->sk_receive_queue); + if (skb != NULL) { + /* + * We will only return the amount + * of this packet since that is all + * that will be read. + */ + /* FIXME: parse the header for more correct value */ + amount = skb->len - (3+8+8); + } + spin_unlock_bh(&sk->sk_receive_queue.lock); + return put_user(amount, (int __user *)arg); + } + + } + return -ENOIOCTLCMD; +} + +/* FIXME: autobind */ +static int dgram_connect(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; + + if (len < sizeof(*addr)) + return -EINVAL; + + if (addr->family != AF_IEEE802154) + return -EINVAL; + + lock_sock(sk); + + if (!ro->bound) { + err = -ENETUNREACH; + goto out; + } + + memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee802154_addr)); + +out: + release_sock(sk); + return err; +} + +static int dgram_disconnect(struct sock *sk, int flags) +{ + struct dgram_sock *ro = dgram_sk(sk); + + lock_sock(sk); + + ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; + memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); + + release_sock(sk); + + return 0; +} + +static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t size) +{ + struct net_device *dev; + unsigned mtu; + struct sk_buff *skb; + struct dgram_sock *ro = dgram_sk(sk); + int err; + + if (msg->msg_flags & MSG_OOB) { + pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags); + return -EOPNOTSUPP; + } + + if (!ro->bound) + dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); + else + dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr); + + if (!dev) { + pr_debug("no dev\n"); + err = -ENXIO; + goto out; + } + mtu = dev->mtu; + pr_debug("name = %s, mtu = %u\n", dev->name, mtu); + + skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + size, + msg->msg_flags & MSG_DONTWAIT, + &err); + if (!skb) + goto out_dev; + + skb_reserve(skb, LL_RESERVED_SPACE(dev)); + + skb_reset_network_header(skb); + + mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA | 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); + if (err < 0) + goto out_skb; + + skb_reset_mac_header(skb); + + err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); + if (err < 0) + goto out_skb; + + if (size > mtu) { + pr_debug("size = %Zu, mtu = %u\n", size, mtu); + err = -EINVAL; + goto out_skb; + } + + skb->dev = dev; + skb->sk = sk; + skb->protocol = htons(ETH_P_IEEE802154); + + dev_put(dev); + + err = dev_queue_xmit(skb); + if (err > 0) + err = net_xmit_errno(err); + + return err ?: size; + +out_skb: + kfree_skb(skb); +out_dev: + dev_put(dev); +out: + return err; +} + +static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len, int noblock, int flags, + int *addr_len) +{ + size_t copied = 0; + int err = -EOPNOTSUPP; + struct sk_buff *skb; + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto out; + + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + + /* FIXME: skip headers if necessary ?! */ + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (err) + goto done; + + sock_recv_timestamp(msg, sk, skb); + + if (flags & MSG_TRUNC) + copied = skb->len; +done: + skb_free_datagram(sk, skb); +out: + if (err) + return err; + return copied; +} + +static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) +{ + if (sock_queue_rcv_skb(sk, skb) < 0) { + atomic_inc(&sk->sk_drops); + kfree_skb(skb); + return NET_RX_DROP; + } + + return NET_RX_SUCCESS; +} + +static inline int ieee802154_match_sock(u8 *hw_addr, u16 pan_id, + u16 short_addr, struct dgram_sock *ro) +{ + if (!ro->bound) + return 1; + + if (ro->src_addr.addr_type == IEEE802154_ADDR_LONG && + !memcmp(ro->src_addr.hwaddr, hw_addr, IEEE802154_ADDR_LEN)) + return 1; + + if (ro->src_addr.addr_type == IEEE802154_ADDR_SHORT && + pan_id == ro->src_addr.pan_id && + short_addr == ro->src_addr.short_addr) + return 1; + + return 0; +} + +int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) +{ + struct sock *sk, *prev = NULL; + struct hlist_node *node; + int ret = NET_RX_SUCCESS; + u16 pan_id, short_addr; + + /* Data frame processing */ + BUG_ON(dev->type != ARPHRD_IEEE802154); + + pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); + short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev); + + read_lock(&dgram_lock); + sk_for_each(sk, node, &dgram_head) { + if (ieee802154_match_sock(dev->dev_addr, pan_id, short_addr, + dgram_sk(sk))) { + if (prev) { + struct sk_buff *clone; + clone = skb_clone(skb, GFP_ATOMIC); + if (clone) + dgram_rcv_skb(prev, clone); + } + + prev = sk; + } + } + + if (prev) + dgram_rcv_skb(prev, skb); + else { + kfree_skb(skb); + ret = NET_RX_DROP; + } + read_unlock(&dgram_lock); + + return ret; +} + +struct proto ieee802154_dgram_prot = { + .name = "IEEE-802.15.4-MAC", + .owner = THIS_MODULE, + .obj_size = sizeof(struct dgram_sock), + .init = dgram_init, + .close = dgram_close, + .bind = dgram_bind, + .sendmsg = dgram_sendmsg, + .recvmsg = dgram_recvmsg, + .hash = dgram_hash, + .unhash = dgram_unhash, + .connect = dgram_connect, + .disconnect = dgram_disconnect, + .ioctl = dgram_ioctl, +}; + diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c new file mode 100644 index 000000000000..105ad10876af --- /dev/null +++ b/net/ieee802154/netlink.c @@ -0,0 +1,523 @@ +/* + * Netlink inteface for IEEE 802.15.4 stack + * + * Copyright 2007, 2008 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. + * + * Written by: + * Sergey Lapin + * Dmitry Eremin-Solenikov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int ieee802154_seq_num; + +static struct genl_family ieee802154_coordinator_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = IEEE802154_NL_NAME, + .version = 1, + .maxattr = IEEE802154_ATTR_MAX, +}; + +static struct genl_multicast_group ieee802154_coord_mcgrp = { + .name = IEEE802154_MCAST_COORD_NAME, +}; + +static struct genl_multicast_group ieee802154_beacon_mcgrp = { + .name = IEEE802154_MCAST_BEACON_NAME, +}; + +/* Requests to userspace */ +static struct sk_buff *ieee802154_nl_create(int flags, u8 req) +{ + void *hdr; + struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + + if (!msg) + return NULL; + + hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, + &ieee802154_coordinator_family, flags, req); + if (!hdr) { + nlmsg_free(msg); + return NULL; + } + + return msg; +} + +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)) + goto out; + + return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id, + GFP_ATOMIC); +out: + nlmsg_free(msg); + return -ENOBUFS; +} + +int ieee802154_nl_assoc_indic(struct net_device *dev, + struct ieee802154_addr *addr, u8 cap) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + if (addr->addr_type != IEEE802154_ADDR_LONG) { + pr_err("%s: received non-long source address!\n", __func__); + return -EINVAL; + } + + msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC); + 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(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, + addr->hwaddr); + + NLA_PUT_U8(msg, IEEE802154_ATTR_CAPABILITY, cap); + + return ieee802154_nl_finish(msg); + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(ieee802154_nl_assoc_indic); + +int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, + u8 status) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_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_U16(msg, IEEE802154_ATTR_SHORT_ADDR, short_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_assoc_confirm); + +int ieee802154_nl_disassoc_indic(struct net_device *dev, + struct ieee802154_addr *addr, u8 reason) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC); + 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); + + if (addr->addr_type == IEEE802154_ADDR_LONG) + NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, + addr->hwaddr); + else + NLA_PUT_U16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, + addr->short_addr); + + NLA_PUT_U8(msg, IEEE802154_ATTR_REASON, reason); + + return ieee802154_nl_finish(msg); + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(ieee802154_nl_disassoc_indic); + +int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_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_disassoc_confirm); + +int ieee802154_nl_beacon_indic(struct net_device *dev, + u16 panid, u16 coord_addr) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC); + 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_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr); + NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid); + + return ieee802154_nl_finish(msg); + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(ieee802154_nl_beacon_indic); + +int ieee802154_nl_scan_confirm(struct net_device *dev, + u8 status, u8 scan_type, u32 unscanned, + u8 *edl/* , struct list_head *pan_desc_list */) +{ + struct sk_buff *msg; + + pr_debug("%s\n", __func__); + + msg = ieee802154_nl_create(0, IEEE802154_SCAN_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); + NLA_PUT_U8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type); + NLA_PUT_U32(msg, IEEE802154_ATTR_CHANNELS, unscanned); + + if (edl) + NLA_PUT(msg, IEEE802154_ATTR_ED_LIST, 27, edl); + + return ieee802154_nl_finish(msg); + +nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(ieee802154_nl_scan_confirm); + +/* Requests from userspace */ +static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) +{ + struct net_device *dev; + + if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { + char name[IFNAMSIZ + 1]; + nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME], + sizeof(name)); + 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])); + else + return NULL; + + if (dev->type != ARPHRD_IEEE802154) { + dev_put(dev); + return NULL; + } + + return dev; +} + +static int ieee802154_associate_req(struct sk_buff *skb, + struct genl_info *info) +{ + struct net_device *dev; + struct ieee802154_addr addr; + int ret = -EINVAL; + + if (!info->attrs[IEEE802154_ATTR_CHANNEL] || + !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || + (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] && + !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) || + !info->attrs[IEEE802154_ATTR_CAPABILITY]) + return -EINVAL; + + dev = ieee802154_nl_get_dev(info); + if (!dev) + return -ENODEV; + + if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { + addr.addr_type = IEEE802154_ADDR_LONG; + nla_memcpy(addr.hwaddr, + info->attrs[IEEE802154_ATTR_COORD_HW_ADDR], + IEEE802154_ADDR_LEN); + } else { + addr.addr_type = IEEE802154_ADDR_SHORT; + addr.short_addr = nla_get_u16( + info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); + } + addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); + + ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr, + nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]), + nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); + + dev_put(dev); + return ret; +} + +static int ieee802154_associate_resp(struct sk_buff *skb, + struct genl_info *info) +{ + struct net_device *dev; + struct ieee802154_addr addr; + int ret = -EINVAL; + + if (!info->attrs[IEEE802154_ATTR_STATUS] || + !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] || + !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) + return -EINVAL; + + dev = ieee802154_nl_get_dev(info); + if (!dev) + return -ENODEV; + + addr.addr_type = IEEE802154_ADDR_LONG; + nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], + IEEE802154_ADDR_LEN); + addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); + + + ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, + nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), + nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); + + dev_put(dev); + return ret; +} + +static int ieee802154_disassociate_req(struct sk_buff *skb, + struct genl_info *info) +{ + struct net_device *dev; + struct ieee802154_addr addr; + int ret = -EINVAL; + + if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && + !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || + !info->attrs[IEEE802154_ATTR_REASON]) + return -EINVAL; + + dev = ieee802154_nl_get_dev(info); + if (!dev) + return -ENODEV; + + if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { + addr.addr_type = IEEE802154_ADDR_LONG; + nla_memcpy(addr.hwaddr, + info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], + IEEE802154_ADDR_LEN); + } else { + addr.addr_type = IEEE802154_ADDR_SHORT; + addr.short_addr = nla_get_u16( + info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); + } + addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); + + ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, + nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); + + dev_put(dev); + return ret; +} + +/* + * PANid, channel, beacon_order = 15, superframe_order = 15, + * PAN_coordinator, battery_life_extension = 0, + * coord_realignment = 0, security_enable = 0 +*/ +static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device *dev; + struct ieee802154_addr addr; + + u8 channel, bcn_ord, sf_ord; + int pan_coord, blx, coord_realign; + int ret; + + if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || + !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || + !info->attrs[IEEE802154_ATTR_CHANNEL] || + !info->attrs[IEEE802154_ATTR_BCN_ORD] || + !info->attrs[IEEE802154_ATTR_SF_ORD] || + !info->attrs[IEEE802154_ATTR_PAN_COORD] || + !info->attrs[IEEE802154_ATTR_BAT_EXT] || + !info->attrs[IEEE802154_ATTR_COORD_REALIGN] + ) + return -EINVAL; + + dev = ieee802154_nl_get_dev(info); + if (!dev) + return -ENODEV; + + addr.addr_type = IEEE802154_ADDR_SHORT; + addr.short_addr = nla_get_u16( + info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); + addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); + + channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); + bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); + sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]); + pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]); + blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]); + coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]); + + ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, + bcn_ord, sf_ord, pan_coord, blx, coord_realign); + + dev_put(dev); + return ret; +} + +static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device *dev; + int ret; + u8 type; + u32 channels; + u8 duration; + + if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] || + !info->attrs[IEEE802154_ATTR_CHANNELS] || + !info->attrs[IEEE802154_ATTR_DURATION]) + return -EINVAL; + + dev = ieee802154_nl_get_dev(info); + if (!dev) + return -ENODEV; + + type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); + channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); + duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]); + + ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, + duration); + + dev_put(dev); + return ret; +} + +#define IEEE802154_OP(_cmd, _func) \ + { \ + .cmd = _cmd, \ + .policy = ieee802154_policy, \ + .doit = _func, \ + .dumpit = NULL, \ + .flags = GENL_ADMIN_PERM, \ + } + +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), +}; + +static int __init ieee802154_nl_init(void) +{ + int rc; + int i; + + rc = genl_register_family(&ieee802154_coordinator_family); + if (rc) + goto fail; + + rc = genl_register_mc_group(&ieee802154_coordinator_family, + &ieee802154_coord_mcgrp); + if (rc) + goto fail; + + rc = genl_register_mc_group(&ieee802154_coordinator_family, + &ieee802154_beacon_mcgrp); + if (rc) + goto fail; + + + for (i = 0; i < ARRAY_SIZE(ieee802154_coordinator_ops); i++) { + rc = genl_register_ops(&ieee802154_coordinator_family, + &ieee802154_coordinator_ops[i]); + if (rc) + goto fail; + } + + return 0; + +fail: + genl_unregister_family(&ieee802154_coordinator_family); + return rc; +} +module_init(ieee802154_nl_init); + +static void __exit ieee802154_nl_exit(void) +{ + genl_unregister_family(&ieee802154_coordinator_family); +} +module_exit(ieee802154_nl_exit); + diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c new file mode 100644 index 000000000000..c7d71d1adcac --- /dev/null +++ b/net/ieee802154/nl_policy.c @@ -0,0 +1,52 @@ +/* + * nl802154.h + * + * Copyright (C) 2007, 2008 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. + * + */ + +#include +#include +#include + +#define NLA_HW_ADDR NLA_U64 + +struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { + [IEEE802154_ATTR_DEV_NAME] = { .type = NLA_STRING, }, + [IEEE802154_ATTR_DEV_INDEX] = { .type = NLA_U32, }, + + [IEEE802154_ATTR_STATUS] = { .type = NLA_U8, }, + [IEEE802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, }, + [IEEE802154_ATTR_HW_ADDR] = { .type = NLA_HW_ADDR, }, + [IEEE802154_ATTR_PAN_ID] = { .type = NLA_U16, }, + [IEEE802154_ATTR_CHANNEL] = { .type = NLA_U8, }, + [IEEE802154_ATTR_COORD_SHORT_ADDR] = { .type = NLA_U16, }, + [IEEE802154_ATTR_COORD_HW_ADDR] = { .type = NLA_HW_ADDR, }, + [IEEE802154_ATTR_COORD_PAN_ID] = { .type = NLA_U16, }, + [IEEE802154_ATTR_SRC_SHORT_ADDR] = { .type = NLA_U16, }, + [IEEE802154_ATTR_SRC_HW_ADDR] = { .type = NLA_HW_ADDR, }, + [IEEE802154_ATTR_SRC_PAN_ID] = { .type = NLA_U16, }, + [IEEE802154_ATTR_DEST_SHORT_ADDR] = { .type = NLA_U16, }, + [IEEE802154_ATTR_DEST_HW_ADDR] = { .type = NLA_HW_ADDR, }, + [IEEE802154_ATTR_DEST_PAN_ID] = { .type = NLA_U16, }, + + [IEEE802154_ATTR_CAPABILITY] = { .type = NLA_U8, }, + [IEEE802154_ATTR_REASON] = { .type = NLA_U8, }, + [IEEE802154_ATTR_SCAN_TYPE] = { .type = NLA_U8, }, + [IEEE802154_ATTR_CHANNELS] = { .type = NLA_U32, }, + [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, + [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, +}; diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c new file mode 100644 index 000000000000..fca44d59f97e --- /dev/null +++ b/net/ieee802154/raw.c @@ -0,0 +1,254 @@ +/* + * Raw IEEE 802.15.4 sockets + * + * Copyright 2007, 2008 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. + * + * Written by: + * Sergey Lapin + * Dmitry Eremin-Solenikov + */ + +#include +#include +#include +#include +#include +#include + +#include "af802154.h" + +static HLIST_HEAD(raw_head); +static DEFINE_RWLOCK(raw_lock); + +static void raw_hash(struct sock *sk) +{ + write_lock_bh(&raw_lock); + sk_add_node(sk, &raw_head); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + write_unlock_bh(&raw_lock); +} + +static void raw_unhash(struct sock *sk) +{ + write_lock_bh(&raw_lock); + if (sk_del_node_init(sk)) + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + write_unlock_bh(&raw_lock); +} + +static void raw_close(struct sock *sk, long timeout) +{ + sk_common_release(sk); +} + +static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int len) +{ + struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; + int err = 0; + struct net_device *dev = NULL; + + if (len < sizeof(*addr)) + return -EINVAL; + + if (addr->family != AF_IEEE802154) + return -EINVAL; + + lock_sock(sk); + + dev = ieee802154_get_dev(sock_net(sk), &addr->addr); + if (!dev) { + err = -ENODEV; + goto out; + } + + if (dev->type != ARPHRD_IEEE802154_PHY && + dev->type != ARPHRD_IEEE802154) { + err = -ENODEV; + goto out_put; + } + + sk->sk_bound_dev_if = dev->ifindex; + sk_dst_reset(sk); + +out_put: + dev_put(dev); +out: + release_sock(sk); + + return err; +} + +static int raw_connect(struct sock *sk, struct sockaddr *uaddr, + int addr_len) +{ + return -ENOTSUPP; +} + +static int raw_disconnect(struct sock *sk, int flags) +{ + return 0; +} + +static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t size) +{ + struct net_device *dev; + unsigned mtu; + struct sk_buff *skb; + int err; + + if (msg->msg_flags & MSG_OOB) { + pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags); + return -EOPNOTSUPP; + } + + lock_sock(sk); + if (!sk->sk_bound_dev_if) + dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); + else + dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); + release_sock(sk); + + if (!dev) { + pr_debug("no dev\n"); + err = -ENXIO; + goto out; + } + + mtu = dev->mtu; + pr_debug("name = %s, mtu = %u\n", dev->name, mtu); + + if (size > mtu) { + pr_debug("size = %Zu, mtu = %u\n", size, mtu); + err = -EINVAL; + goto out_dev; + } + + skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + size, + msg->msg_flags & MSG_DONTWAIT, &err); + if (!skb) + goto out_dev; + + skb_reserve(skb, LL_RESERVED_SPACE(dev)); + + skb_reset_mac_header(skb); + skb_reset_network_header(skb); + + err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); + if (err < 0) + goto out_skb; + + skb->dev = dev; + skb->sk = sk; + skb->protocol = htons(ETH_P_IEEE802154); + + dev_put(dev); + + err = dev_queue_xmit(skb); + if (err > 0) + err = net_xmit_errno(err); + + return err ?: size; + +out_skb: + kfree_skb(skb); +out_dev: + dev_put(dev); +out: + return err; +} + +static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) +{ + size_t copied = 0; + int err = -EOPNOTSUPP; + struct sk_buff *skb; + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto out; + + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (err) + goto done; + + sock_recv_timestamp(msg, sk, skb); + + if (flags & MSG_TRUNC) + copied = skb->len; +done: + skb_free_datagram(sk, skb); +out: + if (err) + return err; + return copied; +} + +static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) +{ + if (sock_queue_rcv_skb(sk, skb) < 0) { + atomic_inc(&sk->sk_drops); + kfree_skb(skb); + return NET_RX_DROP; + } + + return NET_RX_SUCCESS; +} + + +void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) +{ + struct sock *sk; + struct hlist_node *node; + + read_lock(&raw_lock); + sk_for_each(sk, node, &raw_head) { + bh_lock_sock(sk); + if (!sk->sk_bound_dev_if || + sk->sk_bound_dev_if == dev->ifindex) { + + struct sk_buff *clone; + + clone = skb_clone(skb, GFP_ATOMIC); + if (clone) + raw_rcv_skb(sk, clone); + } + bh_unlock_sock(sk); + } + read_unlock(&raw_lock); +} + +struct proto ieee802154_raw_prot = { + .name = "IEEE-802.15.4-RAW", + .owner = THIS_MODULE, + .obj_size = sizeof(struct sock), + .close = raw_close, + .bind = raw_bind, + .sendmsg = raw_sendmsg, + .recvmsg = raw_recvmsg, + .hash = raw_hash, + .unhash = raw_unhash, + .connect = raw_connect, + .disconnect = raw_disconnect, +}; + diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 5b919f7b45db..70491d9035eb 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -273,29 +273,20 @@ config IP_PIMSM_V2 you want to play with it. config ARPD - bool "IP: ARP daemon support (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "IP: ARP daemon support" ---help--- - Normally, the kernel maintains an internal cache which maps IP - addresses to hardware addresses on the local network, so that - Ethernet/Token Ring/ etc. frames are sent to the proper address on - the physical networking layer. For small networks having a few - hundred directly connected hosts or less, keeping this address - resolution (ARP) cache inside the kernel works well. However, - maintaining an internal ARP cache does not work well for very large - switched networks, and will use a lot of kernel memory if TCP/IP - connections are made to many machines on the network. + The kernel maintains an internal cache which maps IP addresses to + hardware addresses on the local network, so that Ethernet/Token Ring/ + etc. frames are sent to the proper address on the physical networking + layer. Normally, kernel uses the ARP protocol to resolve these + mappings. - If you say Y here, the kernel's internal ARP cache will never grow - to more than 256 entries (the oldest entries are expired in a LIFO - manner) and communication will be attempted with the user space ARP - daemon arpd. Arpd then answers the address resolution request either - from its own cache or by asking the net. + Saying Y here adds support to have an user space daemon to do this + resolution instead. This is useful for implementing an alternate + address resolution protocol (e.g. NHRP on mGRE tunnels) and also for + testing purposes. - This code is experimental and also obsolete. If you want to use it, - you need to find a version of the daemon arpd on the net somewhere, - and you should also say Y to "Kernel/User network link driver", - below. If unsure, say N. + If unsure, say N. config SYN_COOKIES bool "IP: TCP syncookie support (disabled per default)" diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 7f03373b8c07..566ea6c4321d 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -116,7 +116,6 @@ #include #endif -extern void ip_mc_drop_socket(struct sock *sk); /* The inetsw table contains everything that inet_create needs to * build a new socket. @@ -375,6 +374,7 @@ static int inet_create(struct net *net, struct socket *sock, int protocol) inet->uc_ttl = -1; inet->mc_loop = 1; inet->mc_ttl = 1; + inet->mc_all = 1; inet->mc_index = 0; inet->mc_list = NULL; @@ -1003,8 +1003,6 @@ void inet_register_protosw(struct inet_protosw *p) out: spin_unlock_bh(&inetsw_lock); - synchronize_net(); - return; out_permanent: @@ -1248,13 +1246,20 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff **pp = NULL; struct sk_buff *p; struct iphdr *iph; + unsigned int hlen; + unsigned int off; + unsigned int id; int flush = 1; int proto; - int id; - iph = skb_gro_header(skb, sizeof(*iph)); - if (unlikely(!iph)) - goto out; + off = skb_gro_offset(skb); + hlen = off + sizeof(*iph); + iph = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, hlen)) { + iph = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!iph)) + goto out; + } proto = iph->protocol & (MAX_INET_PROTOS - 1); @@ -1269,9 +1274,9 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto out_unlock; - flush = ntohs(iph->tot_len) != skb_gro_len(skb) || - iph->frag_off != htons(IP_DF); - id = ntohs(iph->id); + id = ntohl(*(u32 *)&iph->id); + flush = (u16)((ntohl(*(u32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); + id >>= 16; for (p = *head; p; p = p->next) { struct iphdr *iph2; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index f11931c18381..8a3881e28aca 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -468,13 +468,13 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb) __be32 paddr; struct neighbour *n; - if (!skb->dst) { + if (!skb_dst(skb)) { printk(KERN_DEBUG "arp_find is called with dst==NULL\n"); kfree_skb(skb); return 1; } - paddr = skb->rtable->rt_gateway; + paddr = skb_rtable(skb)->rt_gateway; if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, paddr, dev)) return 0; @@ -817,7 +817,7 @@ static int arp_process(struct sk_buff *skb) if (arp->ar_op == htons(ARPOP_REQUEST) && ip_route_input(skb, tip, sip, 0, dev) == 0) { - rt = skb->rtable; + rt = skb_rtable(skb); addr_type = rt->rt_type; if (addr_type == RTN_LOCAL) { diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 126bb911880f..3863c3a4223f 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1347,7 +1347,8 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, struct net *net = ctl->extra2; if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) { - rtnl_lock(); + if (!rtnl_trylock()) + return restart_syscall(); if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) { inet_forward_change(net); } else if (*valp) { diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index cafcc49d0993..e2f950592566 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index ded8c44fb848..ecd39454235c 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -263,7 +263,6 @@ fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result err = fib_semantic_match(&f->fn_alias, flp, res, - f->fn_key, fz->fz_mask, fz->fz_order); if (err <= 0) goto out; diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h index 2c1623d2768b..637b133973bd 100644 --- a/net/ipv4/fib_lookup.h +++ b/net/ipv4/fib_lookup.h @@ -22,8 +22,7 @@ struct fib_alias { /* Exported by fib_semantics.c */ extern int fib_semantic_match(struct list_head *head, const struct flowi *flp, - struct fib_result *res, __be32 zone, __be32 mask, - int prefixlen); + struct fib_result *res, int prefixlen); extern void fib_release_info(struct fib_info *); extern struct fib_info *fib_create_info(struct fib_config *cfg); extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 6080d7120821..92d9d97ec5e3 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -134,7 +134,7 @@ static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = { }; static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, + struct fib_rule_hdr *frh, struct nlattr **tb) { struct net *net = sock_net(skb->sk); @@ -209,7 +209,7 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, } static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh) + struct fib_rule_hdr *frh) { struct fib4_rule *rule4 = (struct fib4_rule *) rule; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index f831df500907..9b096d6ff3f2 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -866,8 +866,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) /* Note! fib_semantic_match intentionally uses RCU list functions. */ int fib_semantic_match(struct list_head *head, const struct flowi *flp, - struct fib_result *res, __be32 zone, __be32 mask, - int prefixlen) + struct fib_result *res, int prefixlen) { struct fib_alias *fa; int nh_sel = 0; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 33c7c85dfe40..d1a39b1277d6 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -123,6 +123,7 @@ struct tnode { union { struct rcu_head rcu; struct work_struct work; + struct tnode *tnode_free; }; struct node *child[0]; }; @@ -161,6 +162,8 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, static struct node *resize(struct trie *t, struct tnode *tn); 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 struct kmem_cache *fn_alias_kmem __read_mostly; static struct kmem_cache *trie_leaf_kmem __read_mostly; @@ -385,6 +388,29 @@ static inline void tnode_free(struct tnode *tn) call_rcu(&tn->rcu, __tnode_free_rcu); } +static void tnode_free_safe(struct tnode *tn) +{ + BUG_ON(IS_LEAF(tn)); + + if (node_parent((struct node *) tn)) { + tn->tnode_free = tnode_free_head; + tnode_free_head = tn; + } else { + tnode_free(tn); + } +} + +static void tnode_free_flush(void) +{ + struct tnode *tn; + + while ((tn = tnode_free_head)) { + tnode_free_head = tn->tnode_free; + tn->tnode_free = NULL; + tnode_free(tn); + } +} + static struct leaf *leaf_new(void) { struct leaf *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL); @@ -495,7 +521,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) /* No children */ if (tn->empty_children == tnode_child_length(tn)) { - tnode_free(tn); + tnode_free_safe(tn); return NULL; } /* One child */ @@ -509,7 +535,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) /* compress one level */ node_set_parent(n, NULL); - tnode_free(tn); + tnode_free_safe(tn); return n; } /* @@ -670,7 +696,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) /* compress one level */ node_set_parent(n, NULL); - tnode_free(tn); + tnode_free_safe(tn); return n; } @@ -756,7 +782,7 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) put_child(t, tn, 2*i, inode->child[0]); put_child(t, tn, 2*i+1, inode->child[1]); - tnode_free(inode); + tnode_free_safe(inode); continue; } @@ -801,9 +827,9 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) put_child(t, tn, 2*i, resize(t, left)); put_child(t, tn, 2*i+1, resize(t, right)); - tnode_free(inode); + tnode_free_safe(inode); } - tnode_free(oldtnode); + tnode_free_safe(oldtnode); return tn; nomem: { @@ -885,7 +911,7 @@ static struct tnode *halve(struct trie *t, struct tnode *tn) put_child(t, newBinNode, 1, right); put_child(t, tn, i/2, resize(t, newBinNode)); } - tnode_free(oldtnode); + tnode_free_safe(oldtnode); return tn; nomem: { @@ -989,7 +1015,6 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn) t_key cindex, key; struct tnode *tp; - preempt_disable(); key = tn->key; while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) { @@ -1001,16 +1026,18 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn) (struct node *)tn, wasfull); tp = node_parent((struct node *) tn); + tnode_free_flush(); if (!tp) break; tn = tp; } /* Handle last (top) tnode */ - if (IS_TNODE(tn)) + if (IS_TNODE(tn)) { tn = (struct tnode *)resize(t, (struct tnode *)tn); + tnode_free_flush(); + } - preempt_enable(); return (struct node *)tn; } @@ -1351,8 +1378,7 @@ static int check_leaf(struct trie *t, struct leaf *l, if (l->key != (key & ntohl(mask))) continue; - err = fib_semantic_match(&li->falh, flp, res, - htonl(l->key), mask, plen); + err = fib_semantic_match(&li->falh, flp, res, plen); #ifdef CONFIG_IP_FIB_TRIE_STATS if (err <= 0) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3f50807237e0..97c410e84388 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -356,7 +356,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) { struct ipcm_cookie ipc; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct net *net = dev_net(rt->u.dst.dev); struct sock *sk; struct inet_sock *inet; @@ -416,7 +416,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) struct iphdr *iph; int room; struct icmp_bxm icmp_param; - struct rtable *rt = skb_in->rtable; + struct rtable *rt = skb_rtable(skb_in); struct ipcm_cookie ipc; __be32 saddr; u8 tos; @@ -591,13 +591,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) goto relookup_failed; /* Ugh! */ - odst = skb_in->dst; + odst = skb_dst(skb_in); err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src, RT_TOS(tos), rt2->u.dst.dev); dst_release(&rt2->u.dst); - rt2 = skb_in->rtable; - skb_in->dst = odst; + rt2 = skb_rtable(skb_in); + skb_dst_set(skb_in, odst); } if (err) @@ -659,7 +659,7 @@ static void icmp_unreach(struct sk_buff *skb) u32 info = 0; struct net *net; - net = dev_net(skb->dst->dev); + net = dev_net(skb_dst(skb)->dev); /* * Incomplete header ? @@ -822,7 +822,7 @@ static void icmp_echo(struct sk_buff *skb) { struct net *net; - net = dev_net(skb->dst->dev); + net = dev_net(skb_dst(skb)->dev); if (!net->ipv4.sysctl_icmp_echo_ignore_all) { struct icmp_bxm icmp_param; @@ -873,7 +873,7 @@ static void icmp_timestamp(struct sk_buff *skb) out: return; out_err: - ICMP_INC_STATS_BH(dev_net(skb->dst->dev), ICMP_MIB_INERRORS); + ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); goto out; } @@ -926,7 +926,7 @@ static void icmp_address(struct sk_buff *skb) static void icmp_address_reply(struct sk_buff *skb) { - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct net_device *dev = skb->dev; struct in_device *in_dev; struct in_ifaddr *ifa; @@ -970,7 +970,7 @@ static void icmp_discard(struct sk_buff *skb) int icmp_rcv(struct sk_buff *skb) { struct icmphdr *icmph; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct net *net = dev_net(rt->u.dst.dev); if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 9eb6219af615..01b4284ed694 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -311,7 +311,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) return NULL; } - skb->dst = &rt->u.dst; + skb_dst_set(skb, &rt->u.dst); skb->dev = dev; skb_reserve(skb, LL_RESERVED_SPACE(dev)); @@ -659,7 +659,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, return -1; } - skb->dst = &rt->u.dst; + skb_dst_set(skb, &rt->u.dst); skb_reserve(skb, LL_RESERVED_SPACE(dev)); @@ -948,7 +948,7 @@ int igmp_rcv(struct sk_buff *skb) case IGMPV2_HOST_MEMBERSHIP_REPORT: case IGMPV3_HOST_MEMBERSHIP_REPORT: /* Is it our report looped back? */ - if (skb->rtable->fl.iif == 0) + if (skb_rtable(skb)->fl.iif == 0) break; /* don't rely on MC router hearing unicast reports */ if (skb->pkt_type == PACKET_MULTICAST || @@ -2196,7 +2196,7 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif) break; } if (!pmc) - return 1; + return inet->mc_all; psl = pmc->sflist; if (!psl) return pmc->sfmode == MCAST_EXCLUDE; diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 588a7796e3e3..b0b273503e2a 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -198,8 +198,6 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, tmo = 0; r->idiag_family = tw->tw_family; - r->idiag_state = tw->tw_state; - r->idiag_timer = 0; r->idiag_retrans = 0; r->id.idiag_if = tw->tw_bound_dev_if; r->id.idiag_cookie[0] = (u32)(unsigned long)tw; diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 8554d0ea1719..68a8d892c711 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -49,19 +49,22 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw, inet_twsk_put(tw); } +static noinline void inet_twsk_free(struct inet_timewait_sock *tw) +{ + struct module *owner = tw->tw_prot->owner; + twsk_destructor((struct sock *)tw); +#ifdef SOCK_REFCNT_DEBUG + pr_debug("%s timewait_sock %p released\n", tw->tw_prot->name, tw); +#endif + release_net(twsk_net(tw)); + kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw); + module_put(owner); +} + void inet_twsk_put(struct inet_timewait_sock *tw) { - if (atomic_dec_and_test(&tw->tw_refcnt)) { - struct module *owner = tw->tw_prot->owner; - twsk_destructor((struct sock *)tw); -#ifdef SOCK_REFCNT_DEBUG - printk(KERN_DEBUG "%s timewait_sock %p released\n", - tw->tw_prot->name, tw); -#endif - release_net(twsk_net(tw)); - kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw); - module_put(owner); - } + if (atomic_dec_and_test(&tw->tw_refcnt)) + inet_twsk_free(tw); } EXPORT_SYMBOL_GPL(inet_twsk_put); diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index df3fe50bbf0d..a2991bc8e32e 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -42,7 +42,7 @@ static int ip_forward_finish(struct sk_buff *skb) { struct ip_options * opt = &(IPCB(skb)->opt); - IP_INC_STATS_BH(dev_net(skb->dst->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); if (unlikely(opt->optlen)) ip_forward_options(skb); @@ -81,7 +81,7 @@ int ip_forward(struct sk_buff *skb) if (!xfrm4_route_forward(skb)) goto drop; - rt = skb->rtable; + rt = skb_rtable(skb); if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway) goto sr_failed; @@ -123,7 +123,7 @@ int ip_forward(struct sk_buff *skb) too_many_hops: /* Tell the sender its packet died... */ - IP_INC_STATS_BH(dev_net(skb->dst->dev), IPSTATS_MIB_INHDRERRORS); + IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_INHDRERRORS); icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); drop: kfree_skb(skb); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 7985346653bd..575f9bd51ccd 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -507,7 +507,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ - if (skb_shinfo(head)->frag_list) { + if (skb_has_frags(head)) { struct sk_buff *clone; int i, plen = 0; @@ -516,7 +516,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, clone->next = head->next; head->next = clone; skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; - skb_shinfo(head)->frag_list = NULL; + skb_frag_list_init(head); for (i=0; inr_frags; i++) plen += skb_shinfo(head)->frags[i].size; clone->len = clone->data_len = head->data_len - plen; @@ -573,7 +573,7 @@ int ip_defrag(struct sk_buff *skb, u32 user) struct ipq *qp; struct net *net; - net = skb->dev ? dev_net(skb->dev) : dev_net(skb->dst->dev); + net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev); IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); /* Start by cleaning up the memory. */ diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index e62510d5ea5a..44e2a3d2359a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -602,7 +602,7 @@ static int ipgre_rcv(struct sk_buff *skb) #ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast(iph->daddr)) { /* Looped back packet, drop it! */ - if (skb->rtable->fl.iif == 0) + if (skb_rtable(skb)->fl.iif == 0) goto drop; stats->multicast++; skb->pkt_type = PACKET_BROADCAST; @@ -643,8 +643,7 @@ static int ipgre_rcv(struct sk_buff *skb) stats->rx_packets++; stats->rx_bytes += len; skb->dev = tunnel->dev; - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); nf_reset(skb); skb_reset_network_header(skb); @@ -698,13 +697,13 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if ((dst = tiph->daddr) == 0) { /* NBMA tunnel */ - if (skb->dst == NULL) { + if (skb_dst(skb) == NULL) { stats->tx_fifo_errors++; goto tx_error; } if (skb->protocol == htons(ETH_P_IP)) { - rt = skb->rtable; + rt = skb_rtable(skb); if ((dst = rt->rt_gateway) == 0) goto tx_error_icmp; } @@ -712,7 +711,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) else if (skb->protocol == htons(ETH_P_IPV6)) { struct in6_addr *addr6; int addr_type; - struct neighbour *neigh = skb->dst->neighbour; + struct neighbour *neigh = skb_dst(skb)->neighbour; if (neigh == NULL) goto tx_error; @@ -766,10 +765,10 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (df) mtu = dst_mtu(&rt->u.dst) - dev->hard_header_len - tunnel->hlen; else - mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; - if (skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->protocol == htons(ETH_P_IP)) { df |= (old_iph->frag_off&htons(IP_DF)); @@ -783,14 +782,14 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } #ifdef CONFIG_IPV6 else if (skb->protocol == htons(ETH_P_IPV6)) { - struct rt6_info *rt6 = (struct rt6_info *)skb->dst; + struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); - if (rt6 && mtu < dst_mtu(skb->dst) && mtu >= IPV6_MIN_MTU) { + if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) { if ((tunnel->parms.iph.daddr && !ipv4_is_multicast(tunnel->parms.iph.daddr)) || rt6->rt6i_dst.plen == 128) { rt6->rt6i_flags |= RTF_MODIFIED; - skb->dst->metrics[RTAX_MTU-1] = mtu; + skb_dst(skb)->metrics[RTAX_MTU-1] = mtu; } } @@ -837,8 +836,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* * Push down and install the IPIP header. @@ -1238,6 +1237,7 @@ static void ipgre_tunnel_setup(struct net_device *dev) dev->iflink = 0; dev->addr_len = 4; dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } static int ipgre_tunnel_init(struct net_device *dev) diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 1a58a6fa1dc0..490ce20faf38 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -329,7 +329,7 @@ static int ip_rcv_finish(struct sk_buff *skb) * Initialise the virtual path cache for the packet. It describes * how the packet travels inside Linux networking. */ - if (skb->dst == NULL) { + if (skb_dst(skb) == NULL) { int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, skb->dev); if (unlikely(err)) { @@ -344,9 +344,9 @@ static int ip_rcv_finish(struct sk_buff *skb) } #ifdef CONFIG_NET_CLS_ROUTE - if (unlikely(skb->dst->tclassid)) { + if (unlikely(skb_dst(skb)->tclassid)) { struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id()); - u32 idx = skb->dst->tclassid; + u32 idx = skb_dst(skb)->tclassid; st[idx&0xFF].o_packets++; st[idx&0xFF].o_bytes += skb->len; st[(idx>>16)&0xFF].i_packets++; @@ -357,11 +357,13 @@ static int ip_rcv_finish(struct sk_buff *skb) if (iph->ihl > 5 && ip_rcv_options(skb)) goto drop; - rt = skb->rtable; - if (rt->rt_type == RTN_MULTICAST) - IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS); - else if (rt->rt_type == RTN_BROADCAST) - IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS); + rt = skb_rtable(skb); + if (rt->rt_type == RTN_MULTICAST) { + IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST, + skb->len); + } else if (rt->rt_type == RTN_BROADCAST) + IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST, + skb->len); return dst_input(skb); @@ -384,7 +386,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, if (skb->pkt_type == PACKET_OTHERHOST) goto drop; - IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES); + + IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 2c88da6e7862..94bf105ef3c9 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -102,7 +102,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) sptr = skb_network_header(skb); dptr = dopt->__data; - daddr = skb->rtable->rt_spec_dst; + daddr = skb_rtable(skb)->rt_spec_dst; if (sopt->rr) { optlen = sptr[sopt->rr+1]; @@ -143,7 +143,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) __be32 addr; memcpy(&addr, sptr+soffset-1, 4); - if (inet_addr_type(dev_net(skb->dst->dev), addr) != RTN_LOCAL) { + if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) { dopt->ts_needtime = 1; soffset += 8; } @@ -257,7 +257,7 @@ int ip_options_compile(struct net *net, struct rtable *rt = NULL; if (skb != NULL) { - rt = skb->rtable; + rt = skb_rtable(skb); optptr = (unsigned char *)&(ip_hdr(skb)[1]); } else optptr = opt->__data; @@ -550,7 +550,7 @@ void ip_forward_options(struct sk_buff *skb) { struct ip_options * opt = &(IPCB(skb)->opt); unsigned char * optptr; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); unsigned char *raw = skb_network_header(skb); if (opt->rr_needaddr) { @@ -598,7 +598,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) __be32 nexthop; struct iphdr *iph = ip_hdr(skb); unsigned char *optptr = skb_network_header(skb) + opt->srr; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct rtable *rt2; int err; @@ -623,13 +623,13 @@ int ip_options_rcv_srr(struct sk_buff *skb) } memcpy(&nexthop, &optptr[srrptr-1], 4); - rt = skb->rtable; - skb->rtable = NULL; + rt = skb_rtable(skb); + skb_dst_set(skb, NULL); err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev); - rt2 = skb->rtable; + rt2 = skb_rtable(skb); if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { ip_rt_put(rt2); - skb->rtable = rt; + skb_dst_set(skb, &rt->u.dst); return -EINVAL; } ip_rt_put(rt); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3e7e910c7c0f..247026282669 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -95,7 +95,7 @@ int __ip_local_out(struct sk_buff *skb) iph->tot_len = htons(skb->len); ip_send_check(iph); - return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev, + return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, dst_output); } @@ -118,7 +118,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb) __skb_pull(newskb, skb_network_offset(newskb)); newskb->pkt_type = PACKET_LOOPBACK; newskb->ip_summed = CHECKSUM_UNNECESSARY; - WARN_ON(!newskb->dst); + WARN_ON(!skb_dst(newskb)); netif_rx(newskb); return 0; } @@ -140,7 +140,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, __be32 saddr, __be32 daddr, struct ip_options *opt) { struct inet_sock *inet = inet_sk(sk); - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct iphdr *iph; /* Build the IP header. */ @@ -176,15 +176,15 @@ EXPORT_SYMBOL_GPL(ip_build_and_send_pkt); static inline int ip_finish_output2(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct rtable *rt = (struct rtable *)dst; struct net_device *dev = dst->dev; unsigned int hh_len = LL_RESERVED_SPACE(dev); - if (rt->rt_type == RTN_MULTICAST) - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS); - else if (rt->rt_type == RTN_BROADCAST) - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS); + if (rt->rt_type == RTN_MULTICAST) { + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len); + } else if (rt->rt_type == RTN_BROADCAST) + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len); /* Be paranoid, rather than too clever. */ if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { @@ -217,14 +217,14 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb) struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL; return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ? - skb->dst->dev->mtu : dst_mtu(skb->dst); + skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); } static int ip_finish_output(struct sk_buff *skb) { #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) /* Policy lookup after SNAT yielded a new policy */ - if (skb->dst->xfrm != NULL) { + if (skb_dst(skb)->xfrm != NULL) { IPCB(skb)->flags |= IPSKB_REROUTED; return dst_output(skb); } @@ -238,13 +238,13 @@ static int ip_finish_output(struct sk_buff *skb) int ip_mc_output(struct sk_buff *skb) { struct sock *sk = skb->sk; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct net_device *dev = rt->u.dst.dev; /* * If the indicated interface is up and running, send the packet. */ - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS); + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); skb->dev = dev; skb->protocol = htons(ETH_P_IP); @@ -296,9 +296,9 @@ int ip_mc_output(struct sk_buff *skb) int ip_output(struct sk_buff *skb) { - struct net_device *dev = skb->dst->dev; + struct net_device *dev = skb_dst(skb)->dev; - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS); + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); skb->dev = dev; skb->protocol = htons(ETH_P_IP); @@ -319,7 +319,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) /* Skip all of this if the packet is already routed, * f.e. by something like SCTP. */ - rt = skb->rtable; + rt = skb_rtable(skb); if (rt != NULL) goto packet_routed; @@ -355,7 +355,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) } sk_setup_caps(sk, &rt->u.dst); } - skb->dst = dst_clone(&rt->u.dst); + skb_dst_set(skb, dst_clone(&rt->u.dst)); packet_routed: if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) @@ -401,8 +401,8 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->pkt_type = from->pkt_type; to->priority = from->priority; to->protocol = from->protocol; - dst_release(to->dst); - to->dst = dst_clone(from->dst); + skb_dst_drop(to); + skb_dst_set(to, dst_clone(skb_dst(from))); to->dev = from->dev; to->mark = from->mark; @@ -440,7 +440,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) unsigned int mtu, hlen, left, len, ll_rs, pad; int offset; __be16 not_last_frag; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); int err = 0; dev = rt->u.dst.dev; @@ -474,7 +474,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) * LATER: this step can be merged to real generation of fragments, * we can switch to copy when see the first bad fragment. */ - if (skb_shinfo(skb)->frag_list) { + if (skb_has_frags(skb)) { struct sk_buff *frag; int first_len = skb_pagelen(skb); int truesizes = 0; @@ -485,7 +485,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb_cloned(skb)) goto slow_path; - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + skb_walk_frags(skb, frag) { /* Correct geometry. */ if (frag->len > mtu || ((frag->len & 7) && frag->next) || @@ -498,7 +498,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) BUG_ON(frag->sk); if (skb->sk) { - sock_hold(skb->sk); frag->sk = skb->sk; frag->destructor = sock_wfree; truesizes += frag->truesize; @@ -510,7 +509,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) err = 0; offset = 0; frag = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; + skb_frag_list_init(skb); skb->data_len = first_len - skb_headlen(skb); skb->truesize -= truesizes; skb->len = first_len; @@ -1294,7 +1293,7 @@ int ip_push_pending_frames(struct sock *sk) * on dst refcount */ inet->cork.dst = NULL; - skb->dst = &rt->u.dst; + skb_dst_set(skb, &rt->u.dst); if (iph->protocol == IPPROTO_ICMP) icmp_out_count(net, ((struct icmphdr *) @@ -1362,7 +1361,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar } replyopts; struct ipcm_cookie ipc; __be32 daddr; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); if (ip_options_echo(&replyopts.opt, skb)) return; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 43c05854d752..fc7993e9061f 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -57,7 +57,7 @@ static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) { struct in_pktinfo info; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); info.ipi_addr.s_addr = ip_hdr(skb)->daddr; if (rt) { @@ -157,38 +157,39 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) /* Ordered by supposed usage frequency */ if (flags & 1) ip_cmsg_recv_pktinfo(msg, skb); - if ((flags>>=1) == 0) + if ((flags >>= 1) == 0) return; if (flags & 1) ip_cmsg_recv_ttl(msg, skb); - if ((flags>>=1) == 0) + if ((flags >>= 1) == 0) return; if (flags & 1) ip_cmsg_recv_tos(msg, skb); - if ((flags>>=1) == 0) + if ((flags >>= 1) == 0) return; if (flags & 1) ip_cmsg_recv_opts(msg, skb); - if ((flags>>=1) == 0) + if ((flags >>= 1) == 0) return; if (flags & 1) ip_cmsg_recv_retopts(msg, skb); - if ((flags>>=1) == 0) + if ((flags >>= 1) == 0) return; if (flags & 1) ip_cmsg_recv_security(msg, skb); - if ((flags>>=1) == 0) + if ((flags >>= 1) == 0) return; if (flags & 1) ip_cmsg_recv_dstaddr(msg, skb); } +EXPORT_SYMBOL(ip_cmsg_recv); int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) { @@ -203,7 +204,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) switch (cmsg->cmsg_type) { case IP_RETOPTS: err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); - err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); + err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg), + err < 40 ? err : 40); if (err) return err; break; @@ -238,7 +240,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) struct ip_ra_chain *ip_ra_chain; DEFINE_RWLOCK(ip_ra_lock); -int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)) +int ip_ra_control(struct sock *sk, unsigned char on, + void (*destructor)(struct sock *)) { struct ip_ra_chain *ra, *new_ra, **rap; @@ -248,7 +251,7 @@ int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct s new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; write_lock_bh(&ip_ra_lock); - for (rap = &ip_ra_chain; (ra=*rap) != NULL; rap = &ra->next) { + for (rap = &ip_ra_chain; (ra = *rap) != NULL; rap = &ra->next) { if (ra->sk == sk) { if (on) { write_unlock_bh(&ip_ra_lock); @@ -416,7 +419,8 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) /* Reset and regenerate socket error */ spin_lock_bh(&sk->sk_error_queue.lock); sk->sk_err = 0; - if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) { + skb2 = skb_peek(&sk->sk_error_queue); + if (skb2 != NULL) { sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno; spin_unlock_bh(&sk->sk_error_queue.lock); sk->sk_error_report(sk); @@ -431,8 +435,8 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) /* - * Socket option code for IP. This is the end of the line after any TCP,UDP etc options on - * an IP socket. + * Socket option code for IP. This is the end of the line after any + * TCP,UDP etc options on an IP socket. */ static int do_ip_setsockopt(struct sock *sk, int level, @@ -449,6 +453,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, (1<= sizeof(int)) { @@ -474,7 +479,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, switch (optname) { case IP_OPTIONS: { - struct ip_options * opt = NULL; + struct ip_options *opt = NULL; if (optlen > 40 || optlen < 0) goto e_inval; err = ip_options_get_from_user(sock_net(sk), &opt, @@ -556,9 +561,9 @@ static int do_ip_setsockopt(struct sock *sk, int level, } break; case IP_TTL: - if (optlen<1) + if (optlen < 1) goto e_inval; - if (val != -1 && (val < 1 || val>255)) + if (val != -1 && (val < 0 || val > 255)) goto e_inval; inet->uc_ttl = val; break; @@ -570,7 +575,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, inet->hdrincl = val ? 1 : 0; break; case IP_MTU_DISCOVER: - if (val<0 || val>3) + if (val < 0 || val > 3) goto e_inval; inet->pmtudisc = val; break; @@ -582,7 +587,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, case IP_MULTICAST_TTL: if (sk->sk_type == SOCK_STREAM) goto e_inval; - if (optlen<1) + if (optlen < 1) goto e_inval; if (val == -1) val = 1; @@ -591,7 +596,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, inet->mc_ttl = val; break; case IP_MULTICAST_LOOP: - if (optlen<1) + if (optlen < 1) goto e_inval; inet->mc_loop = !!val; break; @@ -613,7 +618,8 @@ static int do_ip_setsockopt(struct sock *sk, int level, } else { memset(&mreq, 0, sizeof(mreq)); if (optlen >= sizeof(struct in_addr) && - copy_from_user(&mreq.imr_address, optval, sizeof(struct in_addr))) + copy_from_user(&mreq.imr_address, optval, + sizeof(struct in_addr))) break; } @@ -677,7 +683,6 @@ static int do_ip_setsockopt(struct sock *sk, int level, } case IP_MSFILTER: { - extern int sysctl_igmp_max_msf; struct ip_msfilter *msf; if (optlen < IP_MSFILTER_SIZE(0)) @@ -831,7 +836,6 @@ static int do_ip_setsockopt(struct sock *sk, int level, } case MCAST_MSFILTER: { - extern int sysctl_igmp_max_msf; struct sockaddr_in *psin; struct ip_msfilter *msf = NULL; struct group_filter *gsf = NULL; @@ -849,9 +853,9 @@ static int do_ip_setsockopt(struct sock *sk, int level, break; } err = -EFAULT; - if (copy_from_user(gsf, optval, optlen)) { + if (copy_from_user(gsf, optval, optlen)) goto mc_msf_out; - } + /* numsrc >= (4G-140)/128 overflow in 32 bits */ if (gsf->gf_numsrc >= 0x1ffffff || gsf->gf_numsrc > sysctl_igmp_max_msf) { @@ -879,7 +883,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, msf->imsf_fmode = gsf->gf_fmode; msf->imsf_numsrc = gsf->gf_numsrc; err = -EADDRNOTAVAIL; - for (i=0; igf_numsrc; ++i) { + for (i = 0; i < gsf->gf_numsrc; ++i) { psin = (struct sockaddr_in *)&gsf->gf_slist[i]; if (psin->sin_family != AF_INET) @@ -890,17 +894,24 @@ static int do_ip_setsockopt(struct sock *sk, int level, gsf = NULL; err = ip_mc_msfilter(sk, msf, ifindex); - mc_msf_out: +mc_msf_out: kfree(msf); kfree(gsf); break; } + case IP_MULTICAST_ALL: + if (optlen < 1) + goto e_inval; + if (val != 0 && val != 1) + goto e_inval; + inet->mc_all = val; + break; case IP_ROUTER_ALERT: err = ip_ra_control(sk, val ? 1 : 0, NULL); break; case IP_FREEBIND: - if (optlen<1) + if (optlen < 1) goto e_inval; inet->freebind = !!val; break; @@ -957,6 +968,7 @@ int ip_setsockopt(struct sock *sk, int level, #endif return err; } +EXPORT_SYMBOL(ip_setsockopt); #ifdef CONFIG_COMPAT int compat_ip_setsockopt(struct sock *sk, int level, int optname, @@ -986,13 +998,12 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname, #endif return err; } - EXPORT_SYMBOL(compat_ip_setsockopt); #endif /* - * Get the options. Note for future reference. The GET of IP options gets the - * _received_ ones. The set sets the _sent_ ones. + * Get the options. Note for future reference. The GET of IP options gets + * the _received_ ones. The set sets the _sent_ ones. */ static int do_ip_getsockopt(struct sock *sk, int level, int optname, @@ -1143,10 +1154,14 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, return -EFAULT; } err = ip_mc_gsfget(sk, &gsf, - (struct group_filter __user *)optval, optlen); + (struct group_filter __user *)optval, + optlen); release_sock(sk); return err; } + case IP_MULTICAST_ALL: + val = inet->mc_all; + break; case IP_PKTOPTIONS: { struct msghdr msg; @@ -1187,7 +1202,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, } release_sock(sk); - if (len < sizeof(int) && len > 0 && val>=0 && val<=255) { + if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) { unsigned char ucval = (unsigned char)val; len = 1; if (put_user(len, optlen)) @@ -1230,6 +1245,7 @@ int ip_getsockopt(struct sock *sk, int level, #endif return err; } +EXPORT_SYMBOL(ip_getsockopt); #ifdef CONFIG_COMPAT int compat_ip_getsockopt(struct sock *sk, int level, int optname, @@ -1262,11 +1278,5 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname, #endif return err; } - EXPORT_SYMBOL(compat_ip_getsockopt); #endif - -EXPORT_SYMBOL(ip_cmsg_recv); - -EXPORT_SYMBOL(ip_getsockopt); -EXPORT_SYMBOL(ip_setsockopt); diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 88bf051d0cbb..f8d04c256454 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -160,6 +160,9 @@ static char user_dev_name[IFNAMSIZ] __initdata = { 0, }; /* Protocols supported by available interfaces */ static int ic_proto_have_if __initdata = 0; +/* MTU for boot device */ +static int ic_dev_mtu __initdata = 0; + #ifdef IPCONFIG_DYNAMIC static DEFINE_SPINLOCK(ic_recv_lock); static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */ @@ -286,7 +289,7 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port) sin->sin_port = port; } -static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) +static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg) { int res; @@ -297,6 +300,17 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) return res; } +static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) +{ + int res; + + mm_segment_t oldfs = get_fs(); + set_fs(get_ds()); + res = dev_ioctl(&init_net, cmd, (struct ifreq __user *) arg); + set_fs(oldfs); + return res; +} + static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg) { int res; @@ -321,20 +335,31 @@ static int __init ic_setup_if(void) memset(&ir, 0, sizeof(ir)); strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); set_sockaddr(sin, ic_myaddr, 0); - if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) { + if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) { printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err); return -1; } set_sockaddr(sin, ic_netmask, 0); - if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) { + if ((err = ic_devinet_ioctl(SIOCSIFNETMASK, &ir)) < 0) { printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err); return -1; } set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); - if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { + if ((err = ic_devinet_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err); return -1; } + /* Handle the case where we need non-standard MTU on the boot link (a network + * using jumbo frames, for instance). If we can't set the mtu, don't error + * out, we'll try to muddle along. + */ + if (ic_dev_mtu != 0) { + strcpy(ir.ifr_name, ic_dev->name); + ir.ifr_mtu = ic_dev_mtu; + if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0) + printk(KERN_ERR "IP-Config: Unable to set interface mtu to %d (%d).\n", + ic_dev_mtu, err); + } return 0; } @@ -623,6 +648,7 @@ ic_dhcp_init_options(u8 *options) 12, /* Host name */ 15, /* Domain name */ 17, /* Boot path */ + 26, /* MTU */ 40, /* NIS domain name */ }; @@ -798,6 +824,7 @@ static void __init ic_do_bootp_ext(u8 *ext) { u8 servers; int i; + u16 mtu; #ifdef IPCONFIG_DEBUG u8 *c; @@ -837,6 +864,10 @@ static void __init ic_do_bootp_ext(u8 *ext) if (!root_server_path[0]) ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path)); break; + case 26: /* Interface MTU */ + memcpy(&mtu, ext+1, sizeof(mtu)); + ic_dev_mtu = ntohs(mtu); + break; case 40: /* NIS Domain name (_not_ DNS) */ ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN); break; @@ -1403,6 +1434,8 @@ static int __init ip_auto_config(void) printk(",\n bootserver=%pI4", &ic_servaddr); printk(", rootserver=%pI4", &root_server_addr); printk(", rootpath=%s", root_server_path); + if (ic_dev_mtu) + printk(", mtu=%d", ic_dev_mtu); printk("\n"); #endif /* !SILENT */ diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 9054139795af..93e2b787da20 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -370,8 +370,7 @@ static int ipip_rcv(struct sk_buff *skb) tunnel->dev->stats.rx_packets++; tunnel->dev->stats.rx_bytes += skb->len; skb->dev = tunnel->dev; - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); nf_reset(skb); ipip_ecn_decapsulate(iph, skb); netif_rx(skb); @@ -416,7 +415,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (!dst) { /* NBMA tunnel */ - if ((rt = skb->rtable) == NULL) { + if ((rt = skb_rtable(skb)) == NULL) { stats->tx_fifo_errors++; goto tx_error; } @@ -447,15 +446,15 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (tiph->frag_off) mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); else - mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; if (mtu < 68) { stats->collisions++; ip_rt_put(rt); goto tx_error; } - if (skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); df |= (old_iph->frag_off&htons(IP_DF)); @@ -502,8 +501,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* * Push down and install the IPIP header. @@ -713,6 +712,7 @@ static void ipip_tunnel_setup(struct net_device *dev) dev->iflink = 0; dev->addr_len = 4; dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } static void ipip_tunnel_init(struct net_device *dev) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 13e9dd3012b3..9a8da5ed92b7 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -226,9 +226,10 @@ static void reg_vif_setup(struct net_device *dev) dev->flags = IFF_NOARP; dev->netdev_ops = ®_vif_netdev_ops, dev->destructor = free_netdev; + dev->features |= NETIF_F_NETNS_LOCAL; } -static struct net_device *ipmr_reg_vif(void) +static struct net_device *ipmr_reg_vif(struct net *net) { struct net_device *dev; struct in_device *in_dev; @@ -238,6 +239,8 @@ static struct net_device *ipmr_reg_vif(void) if (dev == NULL) return NULL; + dev_net_set(dev, net); + if (register_netdevice(dev)) { free_netdev(dev); return NULL; @@ -448,7 +451,7 @@ static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) */ if (net->ipv4.mroute_reg_vif_num >= 0) return -EADDRINUSE; - dev = ipmr_reg_vif(); + dev = ipmr_reg_vif(net); if (!dev) return -ENOBUFS; err = dev_set_allmulti(dev, 1); @@ -651,7 +654,7 @@ static int ipmr_cache_report(struct net *net, ip_hdr(skb)->protocol = 0; /* Flag to the kernel this is a route add */ msg = (struct igmpmsg *)skb_network_header(skb); msg->im_vif = vifi; - skb->dst = dst_clone(pkt->dst); + skb_dst_set(skb, dst_clone(skb_dst(pkt))); /* * Add our header @@ -1031,16 +1034,6 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int if (v != net->ipv4.mroute_do_pim) { net->ipv4.mroute_do_pim = v; net->ipv4.mroute_do_assert = v; -#ifdef CONFIG_IP_PIMSM_V2 - if (net->ipv4.mroute_do_pim) - ret = inet_add_protocol(&pim_protocol, - IPPROTO_PIM); - else - ret = inet_del_protocol(&pim_protocol, - IPPROTO_PIM); - if (ret < 0) - ret = -EAGAIN; -#endif } rtnl_unlock(); return ret; @@ -1201,7 +1194,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) iph->protocol = IPPROTO_IPIP; iph->ihl = 5; iph->tot_len = htons(skb->len); - ip_select_ident(iph, skb->dst, NULL); + ip_select_ident(iph, skb_dst(skb), NULL); ip_send_check(iph); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); @@ -1212,7 +1205,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) { struct ip_options * opt = &(IPCB(skb)->opt); - IP_INC_STATS_BH(dev_net(skb->dst->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); + IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); if (unlikely(opt->optlen)) ip_forward_options(skb); @@ -1290,8 +1283,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) vif->pkt_out++; vif->bytes_out += skb->len; - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); ip_decrease_ttl(ip_hdr(skb)); /* FIXME: forward and output firewalls used to be called here. @@ -1354,7 +1347,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local if (net->ipv4.vif_table[vif].dev != skb->dev) { int true_vifi; - if (skb->rtable->fl.iif == 0) { + if (skb_rtable(skb)->fl.iif == 0) { /* It is our own packet, looped back. Very complicated situation... @@ -1430,7 +1423,7 @@ int ip_mr_input(struct sk_buff *skb) { struct mfc_cache *cache; struct net *net = dev_net(skb->dev); - int local = skb->rtable->rt_flags&RTCF_LOCAL; + int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; /* Packet is looped back after forward, it should not be forwarded second time, but still can be delivered locally. @@ -1543,8 +1536,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) skb->protocol = htons(ETH_P_IP); skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); reg_dev->stats.rx_bytes += skb->len; reg_dev->stats.rx_packets++; nf_reset(skb); @@ -1646,7 +1638,7 @@ int ipmr_get_route(struct net *net, { int err; struct mfc_cache *cache; - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); read_lock(&mrt_lock); cache = ipmr_cache_find(net, rt->rt_src, rt->rt_dst); @@ -1955,6 +1947,7 @@ static const struct file_operations ipmr_mfc_fops = { #ifdef CONFIG_IP_PIMSM_V2 static struct net_protocol pim_protocol = { .handler = pim_rcv, + .netns_ok = 1, }; #endif @@ -2041,8 +2034,19 @@ int __init ip_mr_init(void) err = register_netdevice_notifier(&ip_mr_notifier); if (err) goto reg_notif_fail; +#ifdef CONFIG_IP_PIMSM_V2 + if (inet_add_protocol(&pim_protocol, IPPROTO_PIM) < 0) { + printk(KERN_ERR "ip_mr_init: can't add PIM protocol\n"); + err = -EAGAIN; + goto add_proto_fail; + } +#endif return 0; +#ifdef CONFIG_IP_PIMSM_V2 +add_proto_fail: + unregister_netdevice_notifier(&ip_mr_notifier); +#endif reg_notif_fail: del_timer(&ipmr_expire_timer); unregister_pernet_subsys(&ipmr_net_ops); diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index fdf6811c31a2..1725dc0ef688 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -12,7 +12,7 @@ /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) { - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); const struct iphdr *iph = ip_hdr(skb); struct rtable *rt; struct flowi fl = {}; @@ -41,8 +41,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) return -1; /* Drop old route. */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); } else { /* non-local src, find valid iif to satisfy * rp-filter when calling ip_route_input. */ @@ -50,7 +50,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) if (ip_route_output_key(net, &rt, &fl) != 0) return -1; - odst = skb->dst; + odst = skb_dst(skb); if (ip_route_input(skb, iph->daddr, iph->saddr, RT_TOS(iph->tos), rt->u.dst.dev) != 0) { dst_release(&rt->u.dst); @@ -60,18 +60,22 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) dst_release(odst); } - if (skb->dst->error) + if (skb_dst(skb)->error) return -1; #ifdef CONFIG_XFRM if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && - xfrm_decode_session(skb, &fl, AF_INET) == 0) - if (xfrm_lookup(net, &skb->dst, &fl, skb->sk, 0)) + xfrm_decode_session(skb, &fl, AF_INET) == 0) { + struct dst_entry *dst = skb_dst(skb); + skb_dst_set(skb, NULL); + if (xfrm_lookup(net, &dst, &fl, skb->sk, 0)) return -1; + skb_dst_set(skb, dst); + } #endif /* Change in oif may mean change in hh_len. */ - hh_len = skb->dst->dev->hard_header_len; + hh_len = skb_dst(skb)->dev->hard_header_len; if (skb_headroom(skb) < hh_len && pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) return -1; @@ -92,7 +96,7 @@ int ip_xfrm_me_harder(struct sk_buff *skb) if (xfrm_decode_session(skb, &fl, AF_INET) < 0) return -1; - dst = skb->dst; + dst = skb_dst(skb); if (dst->xfrm) dst = ((struct xfrm_dst *)dst)->route; dst_hold(dst); @@ -100,11 +104,11 @@ int ip_xfrm_me_harder(struct sk_buff *skb) if (xfrm_lookup(dev_net(dst->dev), &dst, &fl, skb->sk, 0) < 0) return -1; - dst_release(skb->dst); - skb->dst = dst; + skb_dst_drop(skb); + skb_dst_set(skb, dst); /* Change in oif may mean change in hh_len. */ - hh_len = skb->dst->dev->hard_header_len; + hh_len = skb_dst(skb)->dev->hard_header_len; if (skb_headroom(skb) < hh_len && pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) return -1; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 831fe1879dc0..7505dff4ffdf 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -231,6 +231,12 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset) return (struct arpt_entry *)(base + offset); } +static inline __pure +struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry) +{ + return (void *)entry + entry->next_offset; +} + unsigned int arpt_do_table(struct sk_buff *skb, unsigned int hook, const struct net_device *in, @@ -267,67 +273,64 @@ unsigned int arpt_do_table(struct sk_buff *skb, arp = arp_hdr(skb); do { - if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { - struct arpt_entry_target *t; - int hdr_len; + struct arpt_entry_target *t; + int hdr_len; - hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + - (2 * skb->dev->addr_len); - - ADD_COUNTER(e->counters, hdr_len, 1); - - t = arpt_get_target(e); - - /* Standard target? */ - if (!t->u.kernel.target->target) { - int v; - - v = ((struct arpt_standard_target *)t)->verdict; - if (v < 0) { - /* Pop from stack? */ - if (v != ARPT_RETURN) { - verdict = (unsigned)(-v) - 1; - break; - } - e = back; - back = get_entry(table_base, - back->comefrom); - continue; - } - if (table_base + v - != (void *)e + e->next_offset) { - /* Save old back ptr in next entry */ - struct arpt_entry *next - = (void *)e + e->next_offset; - next->comefrom = - (void *)back - table_base; - - /* set back pointer to next entry */ - back = next; - } - - e = get_entry(table_base, v); - } else { - /* Targets which reenter must return - * abs. verdicts - */ - tgpar.target = t->u.kernel.target; - tgpar.targinfo = t->data; - verdict = t->u.kernel.target->target(skb, - &tgpar); - - /* Target might have changed stuff. */ - arp = arp_hdr(skb); - - if (verdict == ARPT_CONTINUE) - e = (void *)e + e->next_offset; - else - /* Verdict */ - break; - } - } else { - e = (void *)e + e->next_offset; + if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { + e = arpt_next_entry(e); + continue; } + + hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + + (2 * skb->dev->addr_len); + ADD_COUNTER(e->counters, hdr_len, 1); + + t = arpt_get_target(e); + + /* Standard target? */ + if (!t->u.kernel.target->target) { + int v; + + v = ((struct arpt_standard_target *)t)->verdict; + if (v < 0) { + /* Pop from stack? */ + if (v != ARPT_RETURN) { + verdict = (unsigned)(-v) - 1; + break; + } + e = back; + back = get_entry(table_base, back->comefrom); + continue; + } + if (table_base + v + != arpt_next_entry(e)) { + /* Save old back ptr in next entry */ + struct arpt_entry *next = arpt_next_entry(e); + next->comefrom = (void *)back - table_base; + + /* set back pointer to next entry */ + back = next; + } + + e = get_entry(table_base, v); + continue; + } + + /* Targets which reenter must return + * abs. verdicts + */ + tgpar.target = t->u.kernel.target; + tgpar.targinfo = t->data; + verdict = t->u.kernel.target->target(skb, &tgpar); + + /* Target might have changed stuff. */ + arp = arp_hdr(skb); + + if (verdict == ARPT_CONTINUE) + e = arpt_next_entry(e); + else + /* Verdict */ + break; } while (!hotdrop); xt_info_rdunlock_bh(); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 5f22c91c6e15..c156db215987 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -596,7 +596,7 @@ static int __init ip_queue_init(void) #ifdef CONFIG_SYSCTL ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); #endif - status = nf_register_queue_handler(PF_INET, &nfqh); + status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh); if (status < 0) { printk(KERN_ERR "ip_queue: failed to register queue handler\n"); goto cleanup_sysctl; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2ec8d7290c40..fdefae6b5dfc 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -238,8 +238,8 @@ static struct nf_loginfo trace_loginfo = { /* Mildly perf critical (only if packet tracing is on) */ static inline int get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, - char *hookname, char **chainname, - char **comment, unsigned int *rulenum) + const char *hookname, const char **chainname, + const char **comment, unsigned int *rulenum) { struct ipt_standard_target *t = (void *)ipt_get_target(s); @@ -257,8 +257,8 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, && unconditional(&s->ip)) { /* Tail of chains: STANDARD target (return/policy) */ *comment = *chainname == hookname - ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY] - : (char *)comments[NF_IP_TRACE_COMMENT_RETURN]; + ? comments[NF_IP_TRACE_COMMENT_POLICY] + : comments[NF_IP_TRACE_COMMENT_RETURN]; } return 1; } else @@ -277,14 +277,14 @@ static void trace_packet(struct sk_buff *skb, { void *table_base; const struct ipt_entry *root; - char *hookname, *chainname, *comment; + const char *hookname, *chainname, *comment; unsigned int rulenum = 0; - table_base = (void *)private->entries[smp_processor_id()]; + table_base = private->entries[smp_processor_id()]; root = get_entry(table_base, private->hook_entry[hook]); - hookname = chainname = (char *)hooknames[hook]; - comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE]; + hookname = chainname = hooknames[hook]; + comment = comments[NF_IP_TRACE_COMMENT_RULE]; IPT_ENTRY_ITERATE(root, private->size - private->hook_entry[hook], @@ -297,6 +297,12 @@ static void trace_packet(struct sk_buff *skb, } #endif +static inline __pure +struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry) +{ + return (void *)entry + entry->next_offset; +} + /* Returns one of the generic firewall policies, like NF_ACCEPT. */ unsigned int ipt_do_table(struct sk_buff *skb, @@ -305,6 +311,8 @@ ipt_do_table(struct sk_buff *skb, const struct net_device *out, struct xt_table *table) { +#define tb_comefrom ((struct ipt_entry *)table_base)->comefrom + static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); const struct iphdr *ip; u_int16_t datalen; @@ -335,7 +343,7 @@ ipt_do_table(struct sk_buff *skb, mtpar.in = tgpar.in = in; mtpar.out = tgpar.out = out; mtpar.family = tgpar.family = NFPROTO_IPV4; - tgpar.hooknum = hook; + mtpar.hooknum = tgpar.hooknum = hook; IP_NF_ASSERT(table->valid_hooks & (1 << hook)); xt_info_rdlock_bh(); @@ -348,92 +356,84 @@ ipt_do_table(struct sk_buff *skb, back = get_entry(table_base, private->underflow[hook]); do { + struct ipt_entry_target *t; + IP_NF_ASSERT(e); IP_NF_ASSERT(back); - if (ip_packet_match(ip, indev, outdev, - &e->ip, mtpar.fragoff)) { - struct ipt_entry_target *t; + if (!ip_packet_match(ip, indev, outdev, + &e->ip, mtpar.fragoff) || + IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { + e = ipt_next_entry(e); + continue; + } - if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) - goto no_match; + ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); - ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); - - t = ipt_get_target(e); - IP_NF_ASSERT(t->u.kernel.target); + t = ipt_get_target(e); + IP_NF_ASSERT(t->u.kernel.target); #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) - /* The packet is traced: log it */ - if (unlikely(skb->nf_trace)) - trace_packet(skb, hook, in, out, - table->name, private, e); + /* The packet is traced: log it */ + if (unlikely(skb->nf_trace)) + trace_packet(skb, hook, in, out, + table->name, private, e); #endif - /* Standard target? */ - if (!t->u.kernel.target->target) { - int v; + /* Standard target? */ + if (!t->u.kernel.target->target) { + int v; - v = ((struct ipt_standard_target *)t)->verdict; - if (v < 0) { - /* Pop from stack? */ - if (v != IPT_RETURN) { - verdict = (unsigned)(-v) - 1; - break; - } - e = back; - back = get_entry(table_base, - back->comefrom); - continue; - } - if (table_base + v != (void *)e + e->next_offset - && !(e->ip.flags & IPT_F_GOTO)) { - /* Save old back ptr in next entry */ - struct ipt_entry *next - = (void *)e + e->next_offset; - next->comefrom - = (void *)back - table_base; - /* set back pointer to next entry */ - back = next; - } - - e = get_entry(table_base, v); - } else { - /* Targets which reenter must return - abs. verdicts */ - tgpar.target = t->u.kernel.target; - tgpar.targinfo = t->data; -#ifdef CONFIG_NETFILTER_DEBUG - ((struct ipt_entry *)table_base)->comefrom - = 0xeeeeeeec; -#endif - verdict = t->u.kernel.target->target(skb, - &tgpar); -#ifdef CONFIG_NETFILTER_DEBUG - if (((struct ipt_entry *)table_base)->comefrom - != 0xeeeeeeec - && verdict == IPT_CONTINUE) { - printk("Target %s reentered!\n", - t->u.kernel.target->name); - verdict = NF_DROP; - } - ((struct ipt_entry *)table_base)->comefrom - = 0x57acc001; -#endif - /* Target might have changed stuff. */ - ip = ip_hdr(skb); - datalen = skb->len - ip->ihl * 4; - - if (verdict == IPT_CONTINUE) - e = (void *)e + e->next_offset; - else - /* Verdict */ + v = ((struct ipt_standard_target *)t)->verdict; + if (v < 0) { + /* Pop from stack? */ + if (v != IPT_RETURN) { + verdict = (unsigned)(-v) - 1; break; + } + e = back; + back = get_entry(table_base, back->comefrom); + continue; + } + if (table_base + v != ipt_next_entry(e) + && !(e->ip.flags & IPT_F_GOTO)) { + /* Save old back ptr in next entry */ + struct ipt_entry *next = ipt_next_entry(e); + next->comefrom = (void *)back - table_base; + /* set back pointer to next entry */ + back = next; } - } else { - no_match: - e = (void *)e + e->next_offset; + e = get_entry(table_base, v); + continue; } + + /* Targets which reenter must return + abs. verdicts */ + tgpar.target = t->u.kernel.target; + tgpar.targinfo = t->data; + + +#ifdef CONFIG_NETFILTER_DEBUG + tb_comefrom = 0xeeeeeeec; +#endif + verdict = t->u.kernel.target->target(skb, &tgpar); +#ifdef CONFIG_NETFILTER_DEBUG + if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) { + printk("Target %s reentered!\n", + t->u.kernel.target->name); + verdict = NF_DROP; + } + tb_comefrom = 0x57acc001; +#endif + /* Target might have changed stuff. */ + ip = ip_hdr(skb); + datalen = skb->len - ip->ihl * 4; + + if (verdict == IPT_CONTINUE) + e = ipt_next_entry(e); + else + /* Verdict */ + break; } while (!hotdrop); xt_info_rdunlock_bh(); @@ -444,6 +444,8 @@ ipt_do_table(struct sk_buff *skb, return NF_DROP; else return verdict; #endif + +#undef tb_comefrom } /* Figures out from what hook each rule can be called: returns 0 if @@ -2158,7 +2160,7 @@ static bool icmp_checkentry(const struct xt_mtchk_param *par) static struct xt_target ipt_standard_target __read_mostly = { .name = IPT_STANDARD_TARGET, .targetsize = sizeof(int), - .family = AF_INET, + .family = NFPROTO_IPV4, #ifdef CONFIG_COMPAT .compatsize = sizeof(compat_int_t), .compat_from_user = compat_standard_from_user, @@ -2170,7 +2172,7 @@ static struct xt_target ipt_error_target __read_mostly = { .name = IPT_ERROR_TARGET, .target = ipt_error, .targetsize = IPT_FUNCTION_MAXNAMELEN, - .family = AF_INET, + .family = NFPROTO_IPV4, }; static struct nf_sockopt_ops ipt_sockopts = { @@ -2196,17 +2198,17 @@ static struct xt_match icmp_matchstruct __read_mostly = { .matchsize = sizeof(struct ipt_icmp), .checkentry = icmp_checkentry, .proto = IPPROTO_ICMP, - .family = AF_INET, + .family = NFPROTO_IPV4, }; static int __net_init ip_tables_net_init(struct net *net) { - return xt_proto_init(net, AF_INET); + return xt_proto_init(net, NFPROTO_IPV4); } static void __net_exit ip_tables_net_exit(struct net *net) { - xt_proto_fini(net, AF_INET); + xt_proto_fini(net, NFPROTO_IPV4); } static struct pernet_operations ip_tables_net_ops = { diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index f389f60cb105..dada0863946d 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -27,9 +27,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); -/* Lock protects masq region inside conntrack */ -static DEFINE_RWLOCK(masq_lock); - /* FIXME: Multiple targets. --RR */ static bool masquerade_tg_check(const struct xt_tgchk_param *par) { @@ -72,16 +69,14 @@ masquerade_tg(struct sk_buff *skb, const struct xt_target_param *par) return NF_ACCEPT; mr = par->targinfo; - rt = skb->rtable; + rt = skb_rtable(skb); newsrc = inet_select_addr(par->out, rt->rt_gateway, RT_SCOPE_UNIVERSE); if (!newsrc) { printk("MASQUERADE: %s ate my IP address\n", par->out->name); return NF_DROP; } - write_lock_bh(&masq_lock); nat->masq_index = par->out->ifindex; - write_unlock_bh(&masq_lock); /* Transfer from original range. */ newrange = ((struct nf_nat_range) @@ -97,16 +92,11 @@ static int device_cmp(struct nf_conn *i, void *ifindex) { const struct nf_conn_nat *nat = nfct_nat(i); - int ret; if (!nat) return 0; - read_lock_bh(&masq_lock); - ret = (nat->masq_index == (int)(long)ifindex); - read_unlock_bh(&masq_lock); - - return ret; + return nat->masq_index == (int)(long)ifindex; } static int masq_device_event(struct notifier_block *this, diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 0b4b6e0ff2b9..c93ae44bff2a 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -108,17 +108,16 @@ static void send_reset(struct sk_buff *oldskb, int hook) addr_type = RTN_LOCAL; /* ip_route_me_harder expects skb->dst to be set */ - dst_hold(oldskb->dst); - nskb->dst = oldskb->dst; + skb_dst_set(nskb, dst_clone(skb_dst(oldskb))); if (ip_route_me_harder(nskb, addr_type)) goto free_nskb; - niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); + niph->ttl = dst_metric(skb_dst(nskb), RTAX_HOPLIMIT); nskb->ip_summed = CHECKSUM_NONE; /* "Never happens" */ - if (nskb->len > dst_mtu(nskb->dst)) + if (nskb->len > dst_mtu(skb_dst(nskb))) goto free_nskb; nf_ct_attach(nskb, oldskb); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 23b2c2ee869a..d71ba7677344 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -82,18 +82,10 @@ static int icmp_packet(struct nf_conn *ct, u_int8_t pf, unsigned int hooknum) { - /* Try to delete connection immediately after all replies: - won't actually vanish as we still have skb, and del_timer - means this will only run once even if count hits zero twice - (theoretically possible with SMP) */ - if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { - if (atomic_dec_and_test(&ct->proto.icmp.count)) - nf_ct_kill_acct(ct, ctinfo, skb); - } else { - atomic_inc(&ct->proto.icmp.count); - nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct); - nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); - } + /* Do not immediately delete the connection after the first + successful reply to avoid excessive conntrackd traffic + and also to handle correctly ICMP echo reply duplicates. */ + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); return NF_ACCEPT; } @@ -117,7 +109,6 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple); return false; } - atomic_set(&ct->proto.icmp.count, 0); return true; } diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index cf7a42bf9820..155c008626c8 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -140,7 +140,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, const char *rep_buffer, unsigned int rep_len) { - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct iphdr *iph; struct tcphdr *tcph; int oldlen, datalen; @@ -218,7 +218,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, const char *rep_buffer, unsigned int rep_len) { - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct iphdr *iph; struct udphdr *udph; int datalen, oldlen; diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/ipv4/netfilter/nf_nat_proto_sctp.c index 65e470bc6123..3fc598eeeb1a 100644 --- a/net/ipv4/netfilter/nf_nat_proto_sctp.c +++ b/net/ipv4/netfilter/nf_nat_proto_sctp.c @@ -33,6 +33,7 @@ sctp_manip_pkt(struct sk_buff *skb, enum nf_nat_manip_type maniptype) { const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); + struct sk_buff *frag; sctp_sctphdr_t *hdr; unsigned int hdroff = iphdroff + iph->ihl*4; __be32 oldip, newip; @@ -57,8 +58,8 @@ sctp_manip_pkt(struct sk_buff *skb, } crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff); - for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) - crc32 = sctp_update_cksum((u8 *)skb->data, skb_headlen(skb), + skb_walk_frags(skb, frag) + crc32 = sctp_update_cksum((u8 *)frag->data, skb_headlen(frag), crc32); crc32 = sctp_end_cksum(crc32); hdr->checksum = crc32; diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index b7dd695691a0..5567bd0d0750 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -167,10 +167,9 @@ nf_nat_in(unsigned int hooknum, ret = nf_nat_fn(hooknum, skb, in, out, okfn); if (ret != NF_DROP && ret != NF_STOLEN && - daddr != ip_hdr(skb)->daddr) { - dst_release(skb->dst); - skb->dst = NULL; - } + daddr != ip_hdr(skb)->daddr) + skb_dst_drop(skb); + return ret; } diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index cf0cdeeb1db0..f25542c48b7d 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -90,14 +90,14 @@ static const struct file_operations sockstat_seq_fops = { /* snmp items */ static const struct snmp_mib snmp4_ipstats_list[] = { - SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES), + SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INPKTS), SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS), SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS), SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS), SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS), SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS), SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS), - SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS), + SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS), SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS), SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES), SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT), @@ -118,6 +118,12 @@ static const struct snmp_mib snmp4_ipextstats_list[] = { SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS), SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS), SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS), + SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS), + SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS), + SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS), + SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), + SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), + SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), SNMP_MIB_SENTINEL }; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index f774651f0a47..3dc9171a272f 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -343,7 +343,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - skb->dst = dst_clone(&rt->u.dst); + skb_dst_set(skb, dst_clone(&rt->u.dst)); skb_reset_network_header(skb); iph = ip_hdr(skb); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 28205e5bfa9b..cd76b3cb7092 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -131,8 +131,8 @@ static int ip_rt_min_advmss __read_mostly = 256; static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ; static int rt_chain_length_max __read_mostly = 20; -static void rt_worker_func(struct work_struct *work); -static DECLARE_DELAYED_WORK(expires_work, rt_worker_func); +static struct delayed_work expires_work; +static unsigned long expires_ljiffies; /* * Interface to generic destination cache. @@ -787,9 +787,12 @@ static void rt_check_expire(void) struct rtable *rth, *aux, **rthp; unsigned long samples = 0; unsigned long sum = 0, sum2 = 0; + unsigned long delta; u64 mult; - mult = ((u64)ip_rt_gc_interval) << rt_hash_log; + delta = jiffies - expires_ljiffies; + expires_ljiffies = jiffies; + mult = ((u64)delta) << rt_hash_log; if (ip_rt_gc_timeout > 1) do_div(mult, ip_rt_gc_timeout); goal = (unsigned int)mult; @@ -1064,7 +1067,8 @@ static int rt_garbage_collect(struct dst_ops *ops) out: return 0; } -static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) +static int rt_intern_hash(unsigned hash, struct rtable *rt, + struct rtable **rp, struct sk_buff *skb) { struct rtable *rth, **rthp; unsigned long now; @@ -1114,7 +1118,10 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) spin_unlock_bh(rt_hash_lock_addr(hash)); rt_drop(rt); - *rp = rth; + if (rp) + *rp = rth; + else + skb_dst_set(skb, &rth->u.dst); return 0; } @@ -1210,7 +1217,10 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) rcu_assign_pointer(rt_hash_table[hash].chain, rt); spin_unlock_bh(rt_hash_lock_addr(hash)); - *rp = rt; + if (rp) + *rp = rt; + else + skb_dst_set(skb, &rt->u.dst); return 0; } @@ -1407,7 +1417,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, &netevent); rt_del(hash, rth); - if (!rt_intern_hash(hash, rt, &rt)) + if (!rt_intern_hash(hash, rt, &rt, NULL)) ip_rt_put(rt); goto do_next; } @@ -1473,7 +1483,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) void ip_rt_send_redirect(struct sk_buff *skb) { - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct in_device *in_dev = in_dev_get(rt->u.dst.dev); if (!in_dev) @@ -1521,7 +1531,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) static int ip_error(struct sk_buff *skb) { - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); unsigned long now; int code; @@ -1698,7 +1708,7 @@ static void ipv4_link_failure(struct sk_buff *skb) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); - rt = skb->rtable; + rt = skb_rtable(skb); if (rt) dst_set_expires(&rt->u.dst, 0); } @@ -1858,7 +1868,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, in_dev_put(in_dev); hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); - return rt_intern_hash(hash, rth, &skb->rtable); + return rt_intern_hash(hash, rth, NULL, skb); e_nobufs: in_dev_put(in_dev); @@ -2019,7 +2029,7 @@ static int ip_mkroute_input(struct sk_buff *skb, /* put it into the cache */ hash = rt_hash(daddr, saddr, fl->iif, rt_genid(dev_net(rth->u.dst.dev))); - return rt_intern_hash(hash, rth, &skb->rtable); + return rt_intern_hash(hash, rth, NULL, skb); } /* @@ -2175,7 +2185,7 @@ out: return err; } rth->rt_type = res.type; hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); - err = rt_intern_hash(hash, rth, &skb->rtable); + err = rt_intern_hash(hash, rth, NULL, skb); goto done; no_route: @@ -2244,7 +2254,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(in_hit); rcu_read_unlock(); - skb->rtable = rth; + skb_dst_set(skb, &rth->u.dst); return 0; } RT_CACHE_STAT_INC(in_hlist_search); @@ -2420,7 +2430,7 @@ static int ip_mkroute_output(struct rtable **rp, if (err == 0) { hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, rt_genid(dev_net(dev_out))); - err = rt_intern_hash(hash, rth, rp); + err = rt_intern_hash(hash, rth, rp, NULL); } return err; @@ -2763,7 +2773,7 @@ static int rt_fill_info(struct net *net, struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait, unsigned int flags) { - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct rtmsg *r; struct nlmsghdr *nlh; long expires; @@ -2907,7 +2917,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); local_bh_enable(); - rt = skb->rtable; + rt = skb_rtable(skb); if (err == 0 && rt->u.dst.error) err = -rt->u.dst.error; } else { @@ -2927,7 +2937,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void if (err) goto errout_free; - skb->rtable = rt; + skb_dst_set(skb, &rt->u.dst); if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; @@ -2968,15 +2978,15 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) continue; if (rt_is_expired(rt)) continue; - skb->dst = dst_clone(&rt->u.dst); + skb_dst_set(skb, dst_clone(&rt->u.dst)); if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1, NLM_F_MULTI) <= 0) { - dst_release(xchg(&skb->dst, NULL)); + skb_dst_drop(skb); rcu_read_unlock_bh(); goto done; } - dst_release(xchg(&skb->dst, NULL)); + skb_dst_drop(skb); } rcu_read_unlock_bh(); } @@ -3390,6 +3400,8 @@ int __init ip_rt_init(void) /* All the timers, started at system startup tend to synchronize. Perturb it a bit. */ + INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); + expires_ljiffies = jiffies; schedule_delayed_work(&expires_work, net_random() % ip_rt_gc_interval + ip_rt_gc_interval); diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index b35a950d2e06..cd2b97f1b6e1 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -161,13 +161,12 @@ static __u16 const msstab[] = { */ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) { - struct tcp_sock *tp = tcp_sk(sk); const struct iphdr *iph = ip_hdr(skb); const struct tcphdr *th = tcp_hdr(skb); int mssind; const __u16 mss = *mssp; - tp->last_synq_overflow = jiffies; + tcp_synq_overflow(sk); /* XXX sort msstab[] by probability? Binary search? */ for (mssind = 0; mss > msstab[mssind + 1]; mssind++) @@ -268,7 +267,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, if (!sysctl_tcp_syncookies || !th->ack) goto out; - if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || + if (tcp_synq_no_recent_overflow(sk) || (mss = cookie_check(skb, cookie)) == 0) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); goto out; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7a0f0b27bf1f..17b89c523f9d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -439,12 +439,14 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { + struct sk_buff *skb; + answ = tp->rcv_nxt - tp->copied_seq; /* Subtract 1, if FIN is in queue. */ - if (answ && !skb_queue_empty(&sk->sk_receive_queue)) - answ -= - tcp_hdr((struct sk_buff *)sk->sk_receive_queue.prev)->fin; + skb = skb_peek_tail(&sk->sk_receive_queue); + if (answ && skb) + answ -= tcp_hdr(skb)->fin; } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); @@ -1382,11 +1384,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* Next get a buffer. */ - skb = skb_peek(&sk->sk_receive_queue); - do { - if (!skb) - break; - + skb_queue_walk(&sk->sk_receive_queue, skb) { /* Now that we have two receive queues this * shouldn't happen. */ @@ -1403,8 +1401,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (tcp_hdr(skb)->fin) goto found_fin_ok; WARN_ON(!(flags & MSG_PEEK)); - skb = skb->next; - } while (skb != (struct sk_buff *)&sk->sk_receive_queue); + } /* Well, if we have backlog, try to process it now yet. */ @@ -2518,20 +2515,30 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) unsigned int thlen; unsigned int flags; unsigned int mss = 1; + unsigned int hlen; + unsigned int off; int flush = 1; int i; - th = skb_gro_header(skb, sizeof(*th)); - if (unlikely(!th)) - goto out; + off = skb_gro_offset(skb); + hlen = off + sizeof(*th); + th = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, hlen)) { + th = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!th)) + goto out; + } thlen = th->doff * 4; if (thlen < sizeof(*th)) goto out; - th = skb_gro_header(skb, thlen); - if (unlikely(!th)) - goto out; + hlen = off + thlen; + if (skb_gro_header_hard(skb, hlen)) { + th = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!th)) + goto out; + } skb_gro_pull(skb, thlen); @@ -2544,7 +2551,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) th2 = tcp_hdr(p); - if ((th->source ^ th2->source) | (th->dest ^ th2->dest)) { + if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { NAPI_GRO_CB(p)->same_flow = 0; continue; } @@ -2559,14 +2566,14 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) flush |= flags & TCP_FLAG_CWR; flush |= (flags ^ tcp_flag_word(th2)) & ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); - flush |= (th->ack_seq ^ th2->ack_seq) | (th->window ^ th2->window); - for (i = sizeof(*th); !flush && i < thlen; i += 4) + flush |= th->ack_seq ^ th2->ack_seq; + for (i = sizeof(*th); i < thlen; i += 4) flush |= *(u32 *)((u8 *)th + i) ^ *(u32 *)((u8 *)th2 + i); mss = skb_shinfo(p)->gso_size; - flush |= (len > mss) | !len; + flush |= (len - 1) >= mss; flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); if (flush || skb_gro_receive(head, skb)) { diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index eec3e6f9956c..2bdb0da237e6 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -77,7 +77,7 @@ int sysctl_tcp_window_scaling __read_mostly = 1; int sysctl_tcp_sack __read_mostly = 1; int sysctl_tcp_fack __read_mostly = 1; int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH; -int sysctl_tcp_ecn __read_mostly; +int sysctl_tcp_ecn __read_mostly = 2; int sysctl_tcp_dsack __read_mostly = 1; int sysctl_tcp_app_win __read_mostly = 31; int sysctl_tcp_adv_win_scale __read_mostly = 2; @@ -4426,7 +4426,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) } __skb_queue_head(&tp->out_of_order_queue, skb); } else { - struct sk_buff *skb1 = tp->out_of_order_queue.prev; + struct sk_buff *skb1 = skb_peek_tail(&tp->out_of_order_queue); u32 seq = TCP_SKB_CB(skb)->seq; u32 end_seq = TCP_SKB_CB(skb)->end_seq; @@ -4443,15 +4443,18 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) } /* Find place to insert this segment. */ - do { + while (1) { if (!after(TCP_SKB_CB(skb1)->seq, seq)) break; - } while ((skb1 = skb1->prev) != - (struct sk_buff *)&tp->out_of_order_queue); + if (skb_queue_is_first(&tp->out_of_order_queue, skb1)) { + skb1 = NULL; + break; + } + skb1 = skb_queue_prev(&tp->out_of_order_queue, skb1); + } /* Do skb overlap to previous one? */ - if (skb1 != (struct sk_buff *)&tp->out_of_order_queue && - before(seq, TCP_SKB_CB(skb1)->end_seq)) { + if (skb1 && before(seq, TCP_SKB_CB(skb1)->end_seq)) { if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) { /* All the bits are present. Drop. */ __kfree_skb(skb); @@ -4463,15 +4466,26 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) tcp_dsack_set(sk, seq, TCP_SKB_CB(skb1)->end_seq); } else { - skb1 = skb1->prev; + if (skb_queue_is_first(&tp->out_of_order_queue, + skb1)) + skb1 = NULL; + else + skb1 = skb_queue_prev( + &tp->out_of_order_queue, + skb1); } } - __skb_queue_after(&tp->out_of_order_queue, skb1, skb); + if (!skb1) + __skb_queue_head(&tp->out_of_order_queue, skb); + else + __skb_queue_after(&tp->out_of_order_queue, skb1, skb); /* And clean segments covered by new one as whole. */ - while ((skb1 = skb->next) != - (struct sk_buff *)&tp->out_of_order_queue && - after(end_seq, TCP_SKB_CB(skb1)->seq)) { + while (!skb_queue_is_last(&tp->out_of_order_queue, skb)) { + skb1 = skb_queue_next(&tp->out_of_order_queue, skb); + + if (!after(end_seq, TCP_SKB_CB(skb1)->seq)) + break; if (before(end_seq, TCP_SKB_CB(skb1)->end_seq)) { tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq, end_seq); @@ -4492,7 +4506,10 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) static struct sk_buff *tcp_collapse_one(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *list) { - struct sk_buff *next = skb->next; + struct sk_buff *next = NULL; + + if (!skb_queue_is_last(list, skb)) + next = skb_queue_next(list, skb); __skb_unlink(skb, list); __kfree_skb(skb); @@ -4503,6 +4520,9 @@ static struct sk_buff *tcp_collapse_one(struct sock *sk, struct sk_buff *skb, /* Collapse contiguous sequence of skbs head..tail with * sequence numbers start..end. + * + * If tail is NULL, this means until the end of the list. + * * Segments with FIN/SYN are not collapsed (only because this * simplifies code) */ @@ -4511,15 +4531,23 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, struct sk_buff *head, struct sk_buff *tail, u32 start, u32 end) { - struct sk_buff *skb; + struct sk_buff *skb, *n; + bool end_of_skbs; /* First, check that queue is collapsible and find * the point where collapsing can be useful. */ - for (skb = head; skb != tail;) { + skb = head; +restart: + end_of_skbs = true; + skb_queue_walk_from_safe(list, skb, n) { + if (skb == tail) + break; /* No new bits? It is possible on ofo queue. */ if (!before(start, TCP_SKB_CB(skb)->end_seq)) { skb = tcp_collapse_one(sk, skb, list); - continue; + if (!skb) + break; + goto restart; } /* The first skb to collapse is: @@ -4529,16 +4557,24 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, */ if (!tcp_hdr(skb)->syn && !tcp_hdr(skb)->fin && (tcp_win_from_space(skb->truesize) > skb->len || - before(TCP_SKB_CB(skb)->seq, start) || - (skb->next != tail && - TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb->next)->seq))) + before(TCP_SKB_CB(skb)->seq, start))) { + end_of_skbs = false; break; + } + + if (!skb_queue_is_last(list, skb)) { + struct sk_buff *next = skb_queue_next(list, skb); + if (next != tail && + TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(next)->seq) { + end_of_skbs = false; + break; + } + } /* Decided to skip this, advance start seq. */ start = TCP_SKB_CB(skb)->end_seq; - skb = skb->next; } - if (skb == tail || tcp_hdr(skb)->syn || tcp_hdr(skb)->fin) + if (end_of_skbs || tcp_hdr(skb)->syn || tcp_hdr(skb)->fin) return; while (before(start, end)) { @@ -4583,7 +4619,8 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, } if (!before(start, TCP_SKB_CB(skb)->end_seq)) { skb = tcp_collapse_one(sk, skb, list); - if (skb == tail || + if (!skb || + skb == tail || tcp_hdr(skb)->syn || tcp_hdr(skb)->fin) return; @@ -4610,17 +4647,21 @@ static void tcp_collapse_ofo_queue(struct sock *sk) head = skb; for (;;) { - skb = skb->next; + struct sk_buff *next = NULL; + + if (!skb_queue_is_last(&tp->out_of_order_queue, skb)) + next = skb_queue_next(&tp->out_of_order_queue, skb); + skb = next; /* Segment is terminated when we see gap or when * we are at the end of all the queue. */ - if (skb == (struct sk_buff *)&tp->out_of_order_queue || + if (!skb || after(TCP_SKB_CB(skb)->seq, end) || before(TCP_SKB_CB(skb)->end_seq, start)) { tcp_collapse(sk, &tp->out_of_order_queue, head, skb, start, end); head = skb; - if (skb == (struct sk_buff *)&tp->out_of_order_queue) + if (!skb) break; /* Start new segment */ start = TCP_SKB_CB(skb)->seq; @@ -4681,10 +4722,11 @@ static int tcp_prune_queue(struct sock *sk) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); tcp_collapse_ofo_queue(sk); - tcp_collapse(sk, &sk->sk_receive_queue, - sk->sk_receive_queue.next, - (struct sk_buff *)&sk->sk_receive_queue, - tp->copied_seq, tp->rcv_nxt); + if (!skb_queue_empty(&sk->sk_receive_queue)) + tcp_collapse(sk, &sk->sk_receive_queue, + skb_peek(&sk->sk_receive_queue), + NULL, + tp->copied_seq, tp->rcv_nxt); sk_mem_reclaim(sk); if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5d427f86b414..5a1ca2698c88 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -546,7 +546,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) if (th->rst) return; - if (skb->rtable->rt_type != RTN_LOCAL) + if (skb_rtable(skb)->rt_type != RTN_LOCAL) return; /* Swap the send and the receive. */ @@ -590,7 +590,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; - net = dev_net(skb->dst->dev); + net = dev_net(skb_dst(skb)->dev); ip_send_reply(net->ipv4.tcp_sock, skb, &arg, arg.iov[0].iov_len); @@ -617,7 +617,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, ]; } rep; struct ip_reply_arg arg; - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&arg, 0, sizeof(arg)); @@ -1185,7 +1185,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) #endif /* Never answer to SYNs send to broadcast or multicast */ - if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) + if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) goto drop; /* TW buckets are converted to open requests without @@ -1593,7 +1593,7 @@ int tcp_v4_rcv(struct sk_buff *skb) #endif { if (!tcp_prequeue(sk, skb)) - ret = tcp_v4_do_rcv(sk, skb); + ret = tcp_v4_do_rcv(sk, skb); } } else sk_add_backlog(sk, skb); @@ -2343,7 +2343,7 @@ void tcp4_proc_exit(void) struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct iphdr *iph = ip_hdr(skb); + struct iphdr *iph = skb_gro_network_header(skb); switch (skb->ip_summed) { case CHECKSUM_COMPLETE: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 59aec609cec6..416fc4c2e7eb 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -288,7 +288,7 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); tp->ecn_flags = 0; - if (sysctl_tcp_ecn) { + if (sysctl_tcp_ecn == 1) { TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE | TCPCB_FLAG_CWR; tp->ecn_flags = TCP_ECN_OK; } @@ -2202,7 +2202,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, /* Reserve space for headers. */ skb_reserve(skb, MAX_TCP_HEADER); - skb->dst = dst_clone(dst); + skb_dst_set(skb, dst_clone(dst)); mss = dst_metric(dst, RTAX_ADVMSS); if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7a1d1ce22e66..8f4158d7c9a6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -328,7 +328,7 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, if (unlikely(sk = skb_steal_sock(skb))) return sk; else - return __udp4_lib_lookup(dev_net(skb->dst->dev), iph->saddr, sport, + return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport, iph->daddr, dport, inet_iif(skb), udptable); } @@ -1237,7 +1237,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, struct sock *sk; struct udphdr *uh; unsigned short ulen; - struct rtable *rt = (struct rtable*)skb->dst; + struct rtable *rt = skb_rtable(skb); __be32 saddr, daddr; struct net *net = dev_net(skb->dev); diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 4ec2162a437e..f9f922a0ba88 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -23,7 +23,7 @@ int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb) static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) { - if (skb->dst == NULL) { + if (skb_dst(skb) == NULL) { const struct iphdr *iph = ip_hdr(skb); if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 7135279f3f84..3444f3b34eca 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -28,7 +28,7 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb) */ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct iphdr *top_iph; int flags; @@ -41,7 +41,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) top_iph->ihl = 5; top_iph->version = 4; - top_iph->protocol = xfrm_af2proto(skb->dst->ops->family); + top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family); /* DS disclosed */ top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos, diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 8c3180adddbf..c908bd99bcba 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -29,7 +29,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df) goto out; - dst = skb->dst; + dst = skb_dst(skb); mtu = dst_mtu(dst); if (skb->len > mtu) { icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); @@ -72,7 +72,7 @@ EXPORT_SYMBOL(xfrm4_prepare_output); static int xfrm4_output_finish(struct sk_buff *skb) { #ifdef CONFIG_NETFILTER - if (!skb->dst->xfrm) { + if (!skb_dst(skb)->xfrm) { IPCB(skb)->flags |= IPSKB_REROUTED; return dst_output(skb); } @@ -87,6 +87,6 @@ static int xfrm4_output_finish(struct sk_buff *skb) int xfrm4_output(struct sk_buff *skb) { return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, - NULL, skb->dst->dev, xfrm4_output_finish, + NULL, skb_dst(skb)->dev, xfrm4_output_finish, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 597487ae6ce8..8c1e86afbbf5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -503,7 +503,7 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) return 0; if (!rtnl_trylock()) - return -ERESTARTSYS; + return restart_syscall(); if (p == &net->ipv6.devconf_all->forwarding) { __s32 newf = net->ipv6.devconf_all->forwarding; @@ -591,7 +591,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, { struct inet6_ifaddr *ifa = NULL; struct rt6_info *rt; - struct net *net = dev_net(idev->dev); int hash; int err = 0; int addr_type = ipv6_addr_type(addr); @@ -608,7 +607,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, goto out2; } - if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) { + if (idev->cnf.disable_ipv6) { err = -EACCES; goto out2; } @@ -1520,6 +1519,8 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev) int __ipv6_isatap_ifid(u8 *eui, __be32 addr) { + if (addr == 0) + return -1; eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || @@ -1750,6 +1751,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) __u32 prefered_lft; int addr_type; struct inet6_dev *in6_dev; + struct net *net = dev_net(dev); pinfo = (struct prefix_info *) opt; @@ -1807,7 +1809,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) if (addrconf_finite_timeout(rt_expires)) rt_expires *= HZ; - rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, + rt = rt6_lookup(net, &pinfo->prefix, NULL, dev->ifindex, 1); if (rt && addrconf_is_prefix_route(rt)) { @@ -1844,7 +1846,6 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) struct inet6_ifaddr * ifp; struct in6_addr addr; int create = 0, update_lft = 0; - struct net *net = dev_net(dev); if (pinfo->prefix_len == 64) { memcpy(&addr, &pinfo->prefix, 8); @@ -3986,6 +3987,75 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table, return addrconf_fixup_forwarding(table, valp, val); } +static void dev_disable_change(struct inet6_dev *idev) +{ + if (!idev || !idev->dev) + return; + + if (idev->cnf.disable_ipv6) + addrconf_notify(NULL, NETDEV_DOWN, idev->dev); + else + addrconf_notify(NULL, NETDEV_UP, idev->dev); +} + +static void addrconf_disable_change(struct net *net, __s32 newf) +{ + struct net_device *dev; + struct inet6_dev *idev; + + read_lock(&dev_base_lock); + for_each_netdev(net, dev) { + rcu_read_lock(); + idev = __in6_dev_get(dev); + if (idev) { + int changed = (!idev->cnf.disable_ipv6) ^ (!newf); + idev->cnf.disable_ipv6 = newf; + if (changed) + dev_disable_change(idev); + } + rcu_read_unlock(); + } + read_unlock(&dev_base_lock); +} + +static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) +{ + struct net *net; + + net = (struct net *)table->extra2; + + if (p == &net->ipv6.devconf_dflt->disable_ipv6) + return 0; + + if (!rtnl_trylock()) + return restart_syscall(); + + if (p == &net->ipv6.devconf_all->disable_ipv6) { + __s32 newf = net->ipv6.devconf_all->disable_ipv6; + net->ipv6.devconf_dflt->disable_ipv6 = newf; + addrconf_disable_change(net, newf); + } else if ((!*p) ^ (!old)) + dev_disable_change((struct inet6_dev *)table->extra1); + + rtnl_unlock(); + return 0; +} + +static +int addrconf_sysctl_disable(ctl_table *ctl, int write, struct file * filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int *valp = ctl->data; + int val = *valp; + int ret; + + ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); + + if (write) + ret = addrconf_disable_ipv6(ctl, valp, val); + return ret; +} + static struct addrconf_sysctl_table { struct ctl_table_header *sysctl_header; @@ -4223,7 +4293,8 @@ static struct addrconf_sysctl_table .data = &ipv6_devconf.disable_ipv6, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = addrconf_sysctl_disable, + .strategy = sysctl_intvec, }, { .ctl_name = CTL_UNNUMBERED, @@ -4344,6 +4415,10 @@ static int addrconf_init_net(struct net *net) dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); if (dflt == NULL) goto err_alloc_dflt; + } else { + /* these will be inherited by all namespaces */ + dflt->autoconf = ipv6_defaults.autoconf; + dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; } net->ipv6.devconf_all = all; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 61f55386a236..85b3d0036afd 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -72,9 +72,21 @@ MODULE_LICENSE("GPL"); static struct list_head inetsw6[SOCK_MAX]; static DEFINE_SPINLOCK(inetsw6_lock); -static int disable_ipv6 = 0; -module_param_named(disable, disable_ipv6, int, 0); -MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional"); +struct ipv6_params ipv6_defaults = { + .disable_ipv6 = 0, + .autoconf = 1, +}; + +static int disable_ipv6_mod = 0; + +module_param_named(disable, disable_ipv6_mod, int, 0444); +MODULE_PARM_DESC(disable, "Disable IPv6 module such that it is non-functional"); + +module_param_named(disable_ipv6, ipv6_defaults.disable_ipv6, int, 0444); +MODULE_PARM_DESC(disable_ipv6, "Disable IPv6 on all interfaces"); + +module_param_named(autoconf, ipv6_defaults.autoconf, int, 0444); +MODULE_PARM_DESC(autoconf, "Enable IPv6 address autoconfiguration on all interfaces"); static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) { @@ -817,13 +829,20 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, struct sk_buff *p; struct ipv6hdr *iph; unsigned int nlen; + unsigned int hlen; + unsigned int off; int flush = 1; int proto; __wsum csum; - iph = skb_gro_header(skb, sizeof(*iph)); - if (unlikely(!iph)) - goto out; + off = skb_gro_offset(skb); + hlen = off + sizeof(*iph); + iph = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, hlen)) { + iph = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!iph)) + goto out; + } skb_gro_pull(skb, sizeof(*iph)); skb_set_transport_header(skb, skb_gro_offset(skb)); @@ -1031,7 +1050,7 @@ static int __init inet6_init(void) for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) INIT_LIST_HEAD(r); - if (disable_ipv6) { + if (disable_ipv6_mod) { printk(KERN_INFO "IPv6: Loaded, but administratively disabled, " "reboot required to enable\n"); @@ -1220,7 +1239,7 @@ module_init(inet6_init); static void __exit inet6_exit(void) { - if (disable_ipv6) + if (disable_ipv6_mod) return; /* First of all disallow new sockets creation. */ diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 1c7f400a3cfe..4aae658e5501 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -277,7 +277,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || !pskb_may_pull(skb, (skb_transport_offset(skb) + ((skb_transport_header(skb)[1] + 1) << 3)))) { - IP6_INC_STATS_BH(dev_net(skb->dst->dev), ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; @@ -288,7 +288,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) dstbuf = opt->dst1; #endif - dst = dst_clone(skb->dst); + dst = dst_clone(skb_dst(skb)); if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { dst_release(dst); skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; @@ -333,7 +333,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || !pskb_may_pull(skb, (skb_transport_offset(skb) + ((skb_transport_header(skb)[1] + 1) << 3)))) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; @@ -343,7 +343,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || skb->pkt_type != PACKET_HOST) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; @@ -358,7 +358,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) * processed by own */ if (!addr) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; @@ -384,7 +384,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) goto unknown_rh; /* Silently discard invalid RTH type 2 */ if (hdr->hdrlen != 2 || hdr->segments_left != 1) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -1; @@ -403,7 +403,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) n = hdr->hdrlen >> 1; if (hdr->segments_left > n) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, ((&hdr->segments_left) - @@ -417,7 +417,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (skb_cloned(skb)) { /* the copy is a forwarded packet */ if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return -1; @@ -440,13 +440,13 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, (xfrm_address_t *)&ipv6_hdr(skb)->saddr, IPPROTO_ROUTING) < 0) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; } - if (!ipv6_chk_home_addr(dev_net(skb->dst->dev), addr)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) { + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; @@ -458,7 +458,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) } if (ipv6_addr_is_multicast(addr)) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); return -1; @@ -468,17 +468,17 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr); ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr); - dst_release(xchg(&skb->dst, NULL)); + skb_dst_drop(skb); ip6_route_input(skb); - if (skb->dst->error) { + if (skb_dst(skb)->error) { skb_push(skb, skb->data - skb_network_header(skb)); dst_input(skb); return -1; } - if (skb->dst->dev->flags&IFF_LOOPBACK) { + if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) { if (ipv6_hdr(skb)->hop_limit <= 1) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); @@ -494,7 +494,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) return -1; unknown_rh: - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb_network_header(skb)); return -1; @@ -552,11 +552,11 @@ void ipv6_exthdrs_exit(void) **********************************/ /* - * Note: we cannot rely on skb->dst before we assign it in ip6_route_input(). + * Note: we cannot rely on skb_dst(skb) before we assign it in ip6_route_input(). */ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) { - return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev); + return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev); } /* Router Alert as of RFC 2711 */ @@ -581,7 +581,7 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) { const unsigned char *nh = skb_network_header(skb); u32 pkt_len; - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index f5de3f9dc692..00a7a5e4ac97 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -151,7 +151,7 @@ static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = { }; static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, + struct fib_rule_hdr *frh, struct nlattr **tb) { int err = -EINVAL; @@ -211,7 +211,7 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, } static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh) + struct fib_rule_hdr *frh) { struct fib6_rule *rule6 = (struct fib6_rule *) rule; diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 3c3732d50c1a..cc4797dd8325 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -228,7 +228,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) __inet6_csk_dst_store(sk, dst, NULL, NULL); } - skb->dst = dst_clone(dst); + skb_dst_set(skb, dst_clone(dst)); /* Restore final destination back after routing done */ ipv6_addr_copy(&fl.fl6_dst, &np->daddr); diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 8f04bd9da274..c3a07d75b5f5 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -48,7 +48,7 @@ inline int ip6_rcv_finish( struct sk_buff *skb) { - if (skb->dst == NULL) + if (skb_dst(skb) == NULL) ip6_route_input(skb); return dst_input(skb); @@ -70,7 +70,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt idev = __in6_dev_get(skb->dev); - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES); + IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || !idev || unlikely(idev->cnf.disable_ipv6)) { @@ -91,7 +91,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt * arrived via the sending interface (ethX), because of the * nature of scoping architecture. --yoshfuji */ - IP6CB(skb)->iif = skb->dst ? ip6_dst_idev(skb->dst)->dev->ifindex : dev->ifindex; + IP6CB(skb)->iif = skb_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex; if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) goto err; @@ -161,7 +161,7 @@ static int ip6_input_finish(struct sk_buff *skb) int nexthdr, raw; u8 hash; struct inet6_dev *idev; - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); /* * Parse extension headers @@ -169,7 +169,7 @@ static int ip6_input_finish(struct sk_buff *skb) rcu_read_lock(); resubmit: - idev = ip6_dst_idev(skb->dst); + idev = ip6_dst_idev(skb_dst(skb)); if (!pskb_pull(skb, skb_transport_offset(skb))) goto discard; nhoff = IP6CB(skb)->nhoff; @@ -242,8 +242,9 @@ int ip6_mc_input(struct sk_buff *skb) struct ipv6hdr *hdr; int deliver; - IP6_INC_STATS_BH(dev_net(skb->dst->dev), - ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); + IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev), + ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INMCAST, + skb->len); hdr = ipv6_hdr(skb); deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9fb49c3b518a..7c76e3d18215 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -78,7 +78,7 @@ int __ip6_local_out(struct sk_buff *skb) len = 0; ipv6_hdr(skb)->payload_len = htons(len); - return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev, + return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, dst_output); } @@ -96,7 +96,7 @@ EXPORT_SYMBOL_GPL(ip6_local_out); static int ip6_output_finish(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); if (dst->hh) return neigh_hh_output(dst->hh, skb); @@ -117,7 +117,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) __skb_pull(newskb, skb_network_offset(newskb)); newskb->pkt_type = PACKET_LOOPBACK; newskb->ip_summed = CHECKSUM_UNNECESSARY; - WARN_ON(!newskb->dst); + WARN_ON(!skb_dst(newskb)); netif_rx(newskb); return 0; @@ -126,7 +126,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) static int ip6_output2(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct net_device *dev = dst->dev; skb->protocol = htons(ETH_P_IPV6); @@ -134,7 +134,7 @@ static int ip6_output2(struct sk_buff *skb) if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; - struct inet6_dev *idev = ip6_dst_idev(skb->dst); + struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && ((mroute6_socket(dev_net(dev)) && @@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb) } } - IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS); + IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST, + skb->len); } return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, @@ -171,21 +172,21 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? - skb->dst->dev->mtu : dst_mtu(skb->dst); + skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); } int ip6_output(struct sk_buff *skb) { - struct inet6_dev *idev = ip6_dst_idev(skb->dst); + struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); if (unlikely(idev->cnf.disable_ipv6)) { - IP6_INC_STATS(dev_net(skb->dst->dev), idev, + IP6_INC_STATS(dev_net(skb_dst(skb)->dev), idev, IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return 0; } if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || - dst_allfrag(skb->dst)) + dst_allfrag(skb_dst(skb))) return ip6_fragment(skb, ip6_output2); else return ip6_output2(skb); @@ -201,7 +202,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, struct net *net = sock_net(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct in6_addr *first_hop = &fl->fl6_dst; - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct ipv6hdr *hdr; u8 proto = fl->proto; int seg_len = skb->len; @@ -221,7 +222,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (skb_headroom(skb) < head_room) { struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); if (skb2 == NULL) { - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return -ENOBUFS; @@ -275,8 +276,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, mtu = dst_mtu(dst); if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), - IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), + IPSTATS_MIB_OUT, skb->len); return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, dst_output); } @@ -285,7 +286,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; } @@ -415,7 +416,7 @@ static inline int ip6_forward_finish(struct sk_buff *skb) int ip6_forward(struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct ipv6hdr *hdr = ipv6_hdr(skb); struct inet6_skb_parm *opt = IP6CB(skb); struct net *net = dev_net(dst->dev); @@ -484,7 +485,7 @@ int ip6_forward(struct sk_buff *skb) IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); goto drop; } - dst = skb->dst; + dst = skb_dst(skb); /* IPv6 specs say nothing about it, but it is clear that we cannot send redirects to source routed frames. @@ -565,8 +566,8 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->pkt_type = from->pkt_type; to->priority = from->priority; to->protocol = from->protocol; - dst_release(to->dst); - to->dst = dst_clone(from->dst); + skb_dst_drop(to); + skb_dst_set(to, dst_clone(skb_dst(from))); to->dev = from->dev; to->mark = from->mark; @@ -623,7 +624,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) { struct sk_buff *frag; - struct rt6_info *rt = (struct rt6_info*)skb->dst; + struct rt6_info *rt = (struct rt6_info*)skb_dst(skb); struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; struct ipv6hdr *tmp_hdr; struct frag_hdr *fh; @@ -631,7 +632,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) __be32 frag_id = 0; int ptr, offset = 0, err=0; u8 *prevhdr, nexthdr = 0; - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); hlen = ip6_find_1stfragopt(skb, &prevhdr); nexthdr = *prevhdr; @@ -643,9 +644,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) * check should be redundant, but it's free.) */ if (!skb->local_df) { - skb->dev = skb->dst->dev; + skb->dev = skb_dst(skb)->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; @@ -657,7 +658,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) } mtu -= hlen + sizeof(struct frag_hdr); - if (skb_shinfo(skb)->frag_list) { + if (skb_has_frags(skb)) { int first_len = skb_pagelen(skb); int truesizes = 0; @@ -666,7 +667,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb_cloned(skb)) goto slow_path; - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + skb_walk_frags(skb, frag) { /* Correct geometry. */ if (frag->len > mtu || ((frag->len & 7) && frag->next) || @@ -679,7 +680,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) BUG_ON(frag->sk); if (skb->sk) { - sock_hold(skb->sk); frag->sk = skb->sk; frag->destructor = sock_wfree; truesizes += frag->truesize; @@ -689,13 +689,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) err = 0; offset = 0; frag = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; + skb_frag_list_init(skb); /* BUILD HEADER */ *prevhdr = NEXTHDR_FRAGMENT; tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); if (!tmp_hdr) { - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); return -ENOMEM; } @@ -808,7 +808,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); err = -ENOMEM; goto fail; @@ -872,16 +872,16 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (err) goto fail; - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGCREATES); } - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGOKS); kfree_skb(skb); return err; fail: - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return err; @@ -1515,10 +1515,10 @@ int ip6_push_pending_frames(struct sock *sk) skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - skb->dst = dst_clone(&rt->u.dst); - IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); + skb_dst_set(skb, dst_clone(&rt->u.dst)); + IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); if (proto == IPPROTO_ICMPV6) { - struct inet6_dev *idev = ip6_dst_idev(skb->dst); + struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type); ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); @@ -1544,8 +1544,8 @@ void ip6_flush_pending_frames(struct sock *sk) struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { - if (skb->dst) - IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb->dst), + if (skb_dst(skb)) + IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index d994c55a5b16..404d16a97d5c 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -532,8 +532,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (!skb2) return 0; - dst_release(skb2->dst); - skb2->dst = NULL; + skb_dst_drop(skb2); + skb_pull(skb2, offset); skb_reset_network_header(skb2); eiph = ip_hdr(skb2); @@ -560,21 +560,21 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ip_rt_put(rt); goto out; } - skb2->dst = (struct dst_entry *)rt; + skb_dst_set(skb2, (struct dst_entry *)rt); } else { ip_rt_put(rt); if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || - skb2->dst->dev->type != ARPHRD_TUNNEL) + skb_dst(skb2)->dev->type != ARPHRD_TUNNEL) goto out; } /* change mtu on this route */ if (rel_type == ICMP_DEST_UNREACH && rel_code == ICMP_FRAG_NEEDED) { - if (rel_info > dst_mtu(skb2->dst)) + if (rel_info > dst_mtu(skb_dst(skb2))) goto out; - skb2->dst->ops->update_pmtu(skb2->dst, rel_info); + skb_dst(skb2)->ops->update_pmtu(skb_dst(skb2), rel_info); } icmp_send(skb2, rel_type, rel_code, htonl(rel_info)); @@ -606,8 +606,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (!skb2) return 0; - dst_release(skb2->dst); - skb2->dst = NULL; + skb_dst_drop(skb2); skb_pull(skb2, offset); skb_reset_network_header(skb2); @@ -720,8 +719,7 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, skb->pkt_type = PACKET_HOST; memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); skb->dev = t->dev; - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); nf_reset(skb); dscp_ecn_decapsulate(t, ipv6h, skb); @@ -885,8 +883,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, } if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; - if (skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->len > mtu) { *pmtu = mtu; err = -EMSGSIZE; @@ -910,8 +908,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, kfree_skb(skb); skb = new_skb; } - dst_release(skb->dst); - skb->dst = dst_clone(dst); + skb_dst_drop(skb); + skb_dst_set(skb, dst_clone(dst)); skb->transport_header = skb->network_header; @@ -1100,8 +1098,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) struct ip6_tnl_parm *p = &t->parms; struct flowi *fl = &t->fl; - memcpy(&dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); - memcpy(&dev->broadcast, &p->raddr, sizeof(struct in6_addr)); + memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); /* Set up flowi template */ ipv6_addr_copy(&fl->fl6_src, &p->laddr); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 228be551e9c1..c769f155c698 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -398,10 +398,9 @@ static int pim6_rcv(struct sk_buff *skb) skb->protocol = htons(ETH_P_IPV6); skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; - dst_release(skb->dst); + skb_dst_drop(skb); reg_dev->stats.rx_bytes += skb->len; reg_dev->stats.rx_packets++; - skb->dst = NULL; nf_reset(skb); netif_rx(skb); dev_put(reg_dev); @@ -442,6 +441,7 @@ static void reg_vif_setup(struct net_device *dev) dev->flags = IFF_NOARP; dev->netdev_ops = ®_vif_netdev_ops; dev->destructor = free_netdev; + dev->features |= NETIF_F_NETNS_LOCAL; } static struct net_device *ip6mr_reg_vif(struct net *net) @@ -849,7 +849,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); - skb->dst = dst_clone(pkt->dst); + skb_dst_set(skb, dst_clone(skb_dst(pkt))); skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -1078,7 +1078,18 @@ int __init ip6_mr_init(void) err = register_netdevice_notifier(&ip6_mr_notifier); if (err) goto reg_notif_fail; +#ifdef CONFIG_IPV6_PIMSM_V2 + if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) { + printk(KERN_ERR "ip6_mr_init: can't add PIM protocol\n"); + err = -EAGAIN; + goto add_proto_fail; + } +#endif return 0; +#ifdef CONFIG_IPV6_PIMSM_V2 +add_proto_fail: + unregister_netdevice_notifier(&ip6_mr_notifier); +#endif reg_notif_fail: del_timer(&ipmr_expire_timer); unregister_pernet_subsys(&ip6mr_net_ops); @@ -1364,14 +1375,6 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int if (v != net->ipv6.mroute_do_pim) { net->ipv6.mroute_do_pim = v; net->ipv6.mroute_do_assert = v; - if (net->ipv6.mroute_do_pim) - ret = inet6_add_protocol(&pim6_protocol, - IPPROTO_PIM); - else - ret = inet6_del_protocol(&pim6_protocol, - IPPROTO_PIM); - if (ret < 0) - ret = -EAGAIN; } rtnl_unlock(); return ret; @@ -1487,7 +1490,7 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) static inline int ip6mr_forward2_finish(struct sk_buff *skb) { - IP6_INC_STATS_BH(dev_net(skb->dst->dev), ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTFORWDATAGRAMS); return dst_output(skb); } @@ -1532,8 +1535,8 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) if (!dst) goto out_free; - dst_release(skb->dst); - skb->dst = dst; + skb_dst_drop(skb); + skb_dst_set(skb, dst); /* * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally @@ -1722,7 +1725,7 @@ int ip6mr_get_route(struct net *net, { int err; struct mfc6_cache *cache; - struct rt6_info *rt = (struct rt6_info *)skb->dst; + struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); read_lock(&mrt_lock); cache = ip6mr_cache_find(net, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index a51fb33e6864..4b264ed40a8c 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1448,8 +1448,10 @@ static void mld_sendpack(struct sk_buff *skb) struct net *net = dev_net(skb->dev); int err; struct flowi fl; + struct dst_entry *dst; + + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); mldlen = skb->tail - skb->transport_header; pip6->payload_len = htons(payload_len); @@ -1458,9 +1460,9 @@ static void mld_sendpack(struct sk_buff *skb) IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), mldlen, 0)); - skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); + dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); - if (!skb->dst) { + if (!dst) { err = -ENOMEM; goto err_out; } @@ -1469,17 +1471,20 @@ static void mld_sendpack(struct sk_buff *skb) &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->dev->ifindex); - err = xfrm_lookup(net, &skb->dst, &fl, NULL, 0); + err = xfrm_lookup(net, &dst, &fl, NULL, 0); + skb_dst_set(skb, dst); if (err) goto err_out; + payload_len = skb->len; + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT); ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS); + IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); } else IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); @@ -1772,11 +1777,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_PADN, 0 }; struct flowi fl; + struct dst_entry *dst; - rcu_read_lock(); - IP6_INC_STATS(net, __in6_dev_get(dev), - IPSTATS_MIB_OUTREQUESTS); - rcu_read_unlock(); if (type == ICMPV6_MGM_REDUCTION) snd_addr = &in6addr_linklocal_allrouters; else @@ -1786,6 +1788,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) payload_len = len + sizeof(ra); full_len = sizeof(struct ipv6hdr) + payload_len; + rcu_read_lock(); + IP6_UPD_PO_STATS(net, __in6_dev_get(dev), + IPSTATS_MIB_OUT, full_len); + rcu_read_unlock(); + skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err); if (skb == NULL) { @@ -1824,8 +1831,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) idev = in6_dev_get(skb->dev); - skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); - if (!skb->dst) { + dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); + if (!dst) { err = -ENOMEM; goto err_out; } @@ -1834,17 +1841,18 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->dev->ifindex); - err = xfrm_lookup(net, &skb->dst, &fl, NULL, 0); + err = xfrm_lookup(net, &dst, &fl, NULL, 0); if (err) goto err_out; + skb_dst_set(skb, dst); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len); } else IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 9f061d1adbc2..9eb68e92cc18 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -465,8 +465,8 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, 1, &err); if (!skb) { ND_PRINTK0(KERN_ERR - "ICMPv6 ND: %s() failed to allocate an skb.\n", - __func__); + "ICMPv6 ND: %s() failed to allocate an skb, err=%d.\n", + __func__, err); return NULL; } @@ -530,10 +530,10 @@ void ndisc_send_skb(struct sk_buff *skb, return; } - skb->dst = dst; + skb_dst_set(skb, dst); idev = in6_dev_get(dst->dev); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, dst_output); @@ -658,6 +658,7 @@ void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, &icmp6h, NULL, send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0); } +EXPORT_SYMBOL(ndisc_send_rs); static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb) @@ -1561,8 +1562,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, 1, &err); if (buff == NULL) { ND_PRINTK0(KERN_ERR - "ICMPv6 Redirect: %s() failed to allocate an skb.\n", - __func__); + "ICMPv6 Redirect: %s() failed to allocate an skb, err=%d.\n", + __func__, err); goto release; } @@ -1611,9 +1612,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, len, IPPROTO_ICMPV6, csum_partial(icmph, len, 0)); - buff->dst = dst; + skb_dst_set(buff, dst); idev = in6_dev_get(dst->dev); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, dst_output); if (!err) { diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 834cea69fb53..d5ed92b14346 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -12,7 +12,7 @@ int ip6_route_me_harder(struct sk_buff *skb) { - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); struct ipv6hdr *iph = ipv6_hdr(skb); struct dst_entry *dst; struct flowi fl = { @@ -28,9 +28,15 @@ int ip6_route_me_harder(struct sk_buff *skb) #ifdef CONFIG_XFRM if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && - xfrm_decode_session(skb, &fl, AF_INET6) == 0) - if (xfrm_lookup(net, &skb->dst, &fl, skb->sk, 0)) + xfrm_decode_session(skb, &fl, AF_INET6) == 0) { + struct dst_entry *dst2 = skb_dst(skb); + + if (xfrm_lookup(net, &dst2, &fl, skb->sk, 0)) { + skb_dst_set(skb, NULL); return -1; + } + skb_dst_set(skb, dst2); + } #endif if (dst->error) { @@ -41,9 +47,9 @@ int ip6_route_me_harder(struct sk_buff *skb) } /* Drop old route. */ - dst_release(skb->dst); + skb_dst_drop(skb); - skb->dst = dst; + skb_dst_set(skb, dst); return 0; } EXPORT_SYMBOL(ip6_route_me_harder); diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index b693f841aeb4..1cf3f0c6a959 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -598,7 +598,7 @@ static int __init ip6_queue_init(void) #ifdef CONFIG_SYSCTL ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); #endif - status = nf_register_queue_handler(PF_INET6, &nfqh); + status = nf_register_queue_handler(NFPROTO_IPV6, &nfqh); if (status < 0) { printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); goto cleanup_sysctl; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 219e165aea10..ced1f2c0cb65 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -270,8 +270,8 @@ static struct nf_loginfo trace_loginfo = { /* Mildly perf critical (only if packet tracing is on) */ static inline int get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, - char *hookname, char **chainname, - char **comment, unsigned int *rulenum) + const char *hookname, const char **chainname, + const char **comment, unsigned int *rulenum) { struct ip6t_standard_target *t = (void *)ip6t_get_target(s); @@ -289,8 +289,8 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, && unconditional(&s->ipv6)) { /* Tail of chains: STANDARD target (return/policy) */ *comment = *chainname == hookname - ? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY] - : (char *)comments[NF_IP6_TRACE_COMMENT_RETURN]; + ? comments[NF_IP6_TRACE_COMMENT_POLICY] + : comments[NF_IP6_TRACE_COMMENT_RETURN]; } return 1; } else @@ -309,14 +309,14 @@ static void trace_packet(struct sk_buff *skb, { void *table_base; const struct ip6t_entry *root; - char *hookname, *chainname, *comment; + const char *hookname, *chainname, *comment; unsigned int rulenum = 0; - table_base = (void *)private->entries[smp_processor_id()]; + table_base = private->entries[smp_processor_id()]; root = get_entry(table_base, private->hook_entry[hook]); - hookname = chainname = (char *)hooknames[hook]; - comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE]; + hookname = chainname = hooknames[hook]; + comment = comments[NF_IP6_TRACE_COMMENT_RULE]; IP6T_ENTRY_ITERATE(root, private->size - private->hook_entry[hook], @@ -329,6 +329,12 @@ static void trace_packet(struct sk_buff *skb, } #endif +static inline __pure struct ip6t_entry * +ip6t_next_entry(const struct ip6t_entry *entry) +{ + return (void *)entry + entry->next_offset; +} + /* Returns one of the generic firewall policies, like NF_ACCEPT. */ unsigned int ip6t_do_table(struct sk_buff *skb, @@ -337,6 +343,8 @@ ip6t_do_table(struct sk_buff *skb, const struct net_device *out, struct xt_table *table) { +#define tb_comefrom ((struct ip6t_entry *)table_base)->comefrom + static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); bool hotdrop = false; /* Initializing verdict to NF_DROP keeps gcc happy. */ @@ -361,7 +369,7 @@ ip6t_do_table(struct sk_buff *skb, mtpar.in = tgpar.in = in; mtpar.out = tgpar.out = out; mtpar.family = tgpar.family = NFPROTO_IPV6; - tgpar.hooknum = hook; + mtpar.hooknum = tgpar.hooknum = hook; IP_NF_ASSERT(table->valid_hooks & (1 << hook)); @@ -375,96 +383,86 @@ ip6t_do_table(struct sk_buff *skb, back = get_entry(table_base, private->underflow[hook]); do { + struct ip6t_entry_target *t; + IP_NF_ASSERT(e); IP_NF_ASSERT(back); - if (ip6_packet_match(skb, indev, outdev, &e->ipv6, - &mtpar.thoff, &mtpar.fragoff, &hotdrop)) { - struct ip6t_entry_target *t; + if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, + &mtpar.thoff, &mtpar.fragoff, &hotdrop) || + IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { + e = ip6t_next_entry(e); + continue; + } - if (IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) - goto no_match; + ADD_COUNTER(e->counters, + ntohs(ipv6_hdr(skb)->payload_len) + + sizeof(struct ipv6hdr), 1); - ADD_COUNTER(e->counters, - ntohs(ipv6_hdr(skb)->payload_len) + - sizeof(struct ipv6hdr), 1); - - t = ip6t_get_target(e); - IP_NF_ASSERT(t->u.kernel.target); + t = ip6t_get_target(e); + IP_NF_ASSERT(t->u.kernel.target); #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) - /* The packet is traced: log it */ - if (unlikely(skb->nf_trace)) - trace_packet(skb, hook, in, out, - table->name, private, e); + /* The packet is traced: log it */ + if (unlikely(skb->nf_trace)) + trace_packet(skb, hook, in, out, + table->name, private, e); #endif - /* Standard target? */ - if (!t->u.kernel.target->target) { - int v; + /* Standard target? */ + if (!t->u.kernel.target->target) { + int v; - v = ((struct ip6t_standard_target *)t)->verdict; - if (v < 0) { - /* Pop from stack? */ - if (v != IP6T_RETURN) { - verdict = (unsigned)(-v) - 1; - break; - } - e = back; - back = get_entry(table_base, - back->comefrom); - continue; - } - if (table_base + v != (void *)e + e->next_offset - && !(e->ipv6.flags & IP6T_F_GOTO)) { - /* Save old back ptr in next entry */ - struct ip6t_entry *next - = (void *)e + e->next_offset; - next->comefrom - = (void *)back - table_base; - /* set back pointer to next entry */ - back = next; - } - - e = get_entry(table_base, v); - } else { - /* Targets which reenter must return - abs. verdicts */ - tgpar.target = t->u.kernel.target; - tgpar.targinfo = t->data; - -#ifdef CONFIG_NETFILTER_DEBUG - ((struct ip6t_entry *)table_base)->comefrom - = 0xeeeeeeec; -#endif - verdict = t->u.kernel.target->target(skb, - &tgpar); - -#ifdef CONFIG_NETFILTER_DEBUG - if (((struct ip6t_entry *)table_base)->comefrom - != 0xeeeeeeec - && verdict == IP6T_CONTINUE) { - printk("Target %s reentered!\n", - t->u.kernel.target->name); - verdict = NF_DROP; - } - ((struct ip6t_entry *)table_base)->comefrom - = 0x57acc001; -#endif - if (verdict == IP6T_CONTINUE) - e = (void *)e + e->next_offset; - else - /* Verdict */ + v = ((struct ip6t_standard_target *)t)->verdict; + if (v < 0) { + /* Pop from stack? */ + if (v != IP6T_RETURN) { + verdict = (unsigned)(-v) - 1; break; + } + e = back; + back = get_entry(table_base, back->comefrom); + continue; + } + if (table_base + v != ip6t_next_entry(e) + && !(e->ipv6.flags & IP6T_F_GOTO)) { + /* Save old back ptr in next entry */ + struct ip6t_entry *next = ip6t_next_entry(e); + next->comefrom = (void *)back - table_base; + /* set back pointer to next entry */ + back = next; } - } else { - no_match: - e = (void *)e + e->next_offset; + e = get_entry(table_base, v); + continue; } + + /* Targets which reenter must return + abs. verdicts */ + tgpar.target = t->u.kernel.target; + tgpar.targinfo = t->data; + +#ifdef CONFIG_NETFILTER_DEBUG + tb_comefrom = 0xeeeeeeec; +#endif + verdict = t->u.kernel.target->target(skb, &tgpar); + +#ifdef CONFIG_NETFILTER_DEBUG + if (tb_comefrom != 0xeeeeeeec && verdict == IP6T_CONTINUE) { + printk("Target %s reentered!\n", + t->u.kernel.target->name); + verdict = NF_DROP; + } + tb_comefrom = 0x57acc001; +#endif + if (verdict == IP6T_CONTINUE) + e = ip6t_next_entry(e); + else + /* Verdict */ + break; } while (!hotdrop); #ifdef CONFIG_NETFILTER_DEBUG - ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; + tb_comefrom = NETFILTER_LINK_POISON; #endif xt_info_rdunlock_bh(); @@ -475,6 +473,8 @@ ip6t_do_table(struct sk_buff *skb, return NF_DROP; else return verdict; #endif + +#undef tb_comefrom } /* Figures out from what hook each rule can be called: returns 0 if @@ -2191,7 +2191,7 @@ static bool icmp6_checkentry(const struct xt_mtchk_param *par) static struct xt_target ip6t_standard_target __read_mostly = { .name = IP6T_STANDARD_TARGET, .targetsize = sizeof(int), - .family = AF_INET6, + .family = NFPROTO_IPV6, #ifdef CONFIG_COMPAT .compatsize = sizeof(compat_int_t), .compat_from_user = compat_standard_from_user, @@ -2203,7 +2203,7 @@ static struct xt_target ip6t_error_target __read_mostly = { .name = IP6T_ERROR_TARGET, .target = ip6t_error, .targetsize = IP6T_FUNCTION_MAXNAMELEN, - .family = AF_INET6, + .family = NFPROTO_IPV6, }; static struct nf_sockopt_ops ip6t_sockopts = { @@ -2229,17 +2229,17 @@ static struct xt_match icmp6_matchstruct __read_mostly = { .matchsize = sizeof(struct ip6t_icmp), .checkentry = icmp6_checkentry, .proto = IPPROTO_ICMPV6, - .family = AF_INET6, + .family = NFPROTO_IPV6, }; static int __net_init ip6_tables_net_init(struct net *net) { - return xt_proto_init(net, AF_INET6); + return xt_proto_init(net, NFPROTO_IPV6); } static void __net_exit ip6_tables_net_exit(struct net *net) { - xt_proto_fini(net, AF_INET6); + xt_proto_fini(net, NFPROTO_IPV6); } static struct pernet_operations ip6_tables_net_ops = { diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 5a2d0a41694a..5a7f00cd15ce 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -112,7 +112,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) return; } - nskb->dst = dst; + skb_dst_set(nskb, dst); skb_reserve(nskb, hh_len + dst->header_len); diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 9903227bf37c..642dcb127bab 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -95,18 +95,10 @@ static int icmpv6_packet(struct nf_conn *ct, u_int8_t pf, unsigned int hooknum) { - /* Try to delete connection immediately after all replies: - won't actually vanish as we still have skb, and del_timer - means this will only run once even if count hits zero twice - (theoretically possible with SMP) */ - if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { - if (atomic_dec_and_test(&ct->proto.icmp.count)) - nf_ct_kill_acct(ct, ctinfo, skb); - } else { - atomic_inc(&ct->proto.icmp.count); - nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct); - nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); - } + /* Do not immediately delete the connection after the first + successful reply to avoid excessive conntrackd traffic + and also to handle correctly ICMP echo reply duplicates. */ + nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); return NF_ACCEPT; } @@ -132,7 +124,6 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, type + 128); return false; } - atomic_set(&ct->proto.icmp.count, 0); return true; } diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 058a5e4a60c3..f3aba255ad9f 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -409,7 +409,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ - if (skb_shinfo(head)->frag_list) { + if (skb_has_frags(head)) { struct sk_buff *clone; int i, plen = 0; @@ -420,7 +420,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) clone->next = head->next; head->next = clone; skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; - skb_shinfo(head)->frag_list = NULL; + skb_frag_list_init(head); for (i=0; inr_frags; i++) plen += skb_shinfo(head)->frags[i].size; clone->len = clone->data_len = head->data_len - plen; diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 97c17fdd6f75..590ddefb7ffc 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -61,7 +61,7 @@ static const struct file_operations sockstat6_seq_fops = { static struct snmp_mib snmp6_ipstats_list[] = { /* ipv6 mib according to RFC 2465 */ - SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES), + SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS), SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS), SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS), SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES), @@ -71,7 +71,7 @@ static struct snmp_mib snmp6_ipstats_list[] = { SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS), SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS), SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS), - SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS), + SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS), SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS), SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES), SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT), @@ -83,6 +83,12 @@ static struct snmp_mib snmp6_ipstats_list[] = { SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES), SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS), SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS), + SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS), + SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS), + SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS), + SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), + SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), + SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), SNMP_MIB_SENTINEL }; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 61f6827e5906..36a090d87a3d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -625,7 +625,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - skb->dst = dst_clone(&rt->u.dst); + skb_dst_set(skb, dst_clone(&rt->u.dst)); skb_put(skb, length); skb_reset_network_header(skb); @@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, if (err) goto error_fault; - IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index e9ac7a12f595..2642a41a8535 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -267,7 +267,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, struct sk_buff *prev, *next; struct net_device *dev; int offset, end; - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); if (fq->q.last_in & INET_FRAG_COMPLETE) goto err; @@ -277,7 +277,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); if ((unsigned int)end > IPV6_MAXPLEN) { - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, ((u8 *)&fhdr->frag_off - @@ -310,7 +310,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, /* RFC2460 says always send parameter problem in * this case. -DaveM */ - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, offsetof(struct ipv6hdr, payload_len)); @@ -434,7 +434,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, return -1; err: - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -1; @@ -494,7 +494,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ - if (skb_shinfo(head)->frag_list) { + if (skb_has_frags(head)) { struct sk_buff *clone; int i, plen = 0; @@ -503,7 +503,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, clone->next = head->next; head->next = clone; skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; - skb_shinfo(head)->frag_list = NULL; + skb_frag_list_init(head); for (i=0; inr_frags; i++) plen += skb_shinfo(head)->frags[i].size; clone->len = clone->data_len = head->data_len - plen; @@ -576,9 +576,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb) struct frag_hdr *fhdr; struct frag_queue *fq; struct ipv6hdr *hdr = ipv6_hdr(skb); - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); /* Jumbo payload inhibits frag. header */ if (hdr->payload_len==0) @@ -595,17 +595,17 @@ static int ipv6_frag_rcv(struct sk_buff *skb) /* It is not a fragmented frame */ skb->transport_header += sizeof(struct frag_hdr); IP6_INC_STATS_BH(net, - ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); + ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS); IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb); return 1; } if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) - ip6_evictor(net, ip6_dst_idev(skb->dst)); + ip6_evictor(net, ip6_dst_idev(skb_dst(skb))); if ((fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, - ip6_dst_idev(skb->dst))) != NULL) { + ip6_dst_idev(skb_dst(skb)))) != NULL) { int ret; spin_lock(&fq->q.lock); @@ -617,12 +617,12 @@ static int ipv6_frag_rcv(struct sk_buff *skb) return ret; } - IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMFAILS); kfree_skb(skb); return -1; fail_hdr: - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb)); return -1; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 032a5ec391c5..658293ea05ba 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -800,7 +800,7 @@ void ip6_route_input(struct sk_buff *skb) if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) flags |= RT6_LOOKUP_F_IFACE; - skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); + skb_dst_set(skb, fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input)); } static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, @@ -911,7 +911,7 @@ static void ip6_link_failure(struct sk_buff *skb) icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); - rt = (struct rt6_info *) skb->dst; + rt = (struct rt6_info *) skb_dst(skb); if (rt) { if (rt->rt6i_flags&RTF_CACHE) { dst_set_expires(&rt->u.dst, 0); @@ -1868,7 +1868,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) static int ip6_pkt_drop(struct sk_buff *skb, int code, int ipstats_mib_noroutes) { int type; - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); switch (ipstats_mib_noroutes) { case IPSTATS_MIB_INNOROUTES: type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); @@ -1895,7 +1895,7 @@ static int ip6_pkt_discard(struct sk_buff *skb) static int ip6_pkt_discard_out(struct sk_buff *skb) { - skb->dev = skb->dst->dev; + skb->dev = skb_dst(skb)->dev; return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); } @@ -1908,7 +1908,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb) static int ip6_pkt_prohibit_out(struct sk_buff *skb) { - skb->dev = skb->dst->dev; + skb->dev = skb_dst(skb)->dev; return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -2366,7 +2366,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); - skb->dst = &rt->u.dst; + skb_dst_set(skb, &rt->u.dst); err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, RTM_NEWROUTE, NETLINK_CB(in_skb).pid, diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 664ab82e03b2..68e52308e552 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -15,6 +15,7 @@ * Roger Venning : 6to4 support * Nate Thompson : 6to4 support * Fred Templin : isatap support + * Sascha Hlusiak : stateless autoconf for isatap */ #include @@ -80,7 +81,7 @@ struct sit_net { static DEFINE_RWLOCK(ipip6_lock); static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, - __be32 remote, __be32 local) + struct net_device *dev, __be32 remote, __be32 local) { unsigned h0 = HASH(remote); unsigned h1 = HASH(local); @@ -89,18 +90,25 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) { if (local == t->parms.iph.saddr && - remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) + remote == t->parms.iph.daddr && + (!dev || !t->parms.link || dev->iflink == t->parms.link) && + (t->dev->flags & IFF_UP)) return t; } for (t = sitn->tunnels_r[h0]; t; t = t->next) { - if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) + if (remote == t->parms.iph.daddr && + (!dev || !t->parms.link || dev->iflink == t->parms.link) && + (t->dev->flags & IFF_UP)) return t; } for (t = sitn->tunnels_l[h1]; t; t = t->next) { - if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) + if (local == t->parms.iph.saddr && + (!dev || !t->parms.link || dev->iflink == t->parms.link) && + (t->dev->flags & IFF_UP)) return t; } - if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) + t = sitn->tunnels_wc[0]; + if ((t != NULL) && (t->dev->flags & IFF_UP)) return t; return NULL; } @@ -165,8 +173,14 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, struct sit_net *sitn = net_generic(net, sit_net_id); for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { - if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) - return t; + if (local == t->parms.iph.saddr && + remote == t->parms.iph.daddr && + parms->link == t->parms.link) { + if (create) + return NULL; + else + return t; + } } if (!create) goto failed; @@ -209,6 +223,44 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, return NULL; } +static void ipip6_tunnel_rs_timer(unsigned long data) +{ + struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *) data; + struct inet6_dev *ifp; + struct inet6_ifaddr *addr; + + spin_lock(&p->lock); + ifp = __in6_dev_get(p->tunnel->dev); + + read_lock_bh(&ifp->lock); + for (addr = ifp->addr_list; addr; addr = addr->if_next) { + struct in6_addr rtr; + + if (!(ipv6_addr_type(&addr->addr) & IPV6_ADDR_LINKLOCAL)) + continue; + + /* Send RS to guessed linklocal address of router + * + * Better: send to ff02::2 encapsuled in unicast directly + * to router-v4 instead of guessing the v6 address. + * + * Cisco/Windows seem to not set the u/l bit correctly, + * so we won't guess right. + */ + ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0); + if (!__ipv6_isatap_ifid(rtr.s6_addr + 8, + p->addr)) { + ndisc_send_rs(p->tunnel->dev, &addr->addr, &rtr); + } + } + read_unlock_bh(&ifp->lock); + + mod_timer(&p->rs_timer, jiffies + HZ * p->rs_delay); + spin_unlock(&p->lock); + + return; +} + static struct ip_tunnel_prl_entry * __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) { @@ -267,6 +319,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, continue; kp[c].addr = prl->addr; kp[c].flags = prl->flags; + kp[c].rs_delay = prl->rs_delay; c++; if (kprl.addr != htonl(INADDR_ANY)) break; @@ -316,11 +369,23 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) } p->next = t->prl; + p->tunnel = t; t->prl = p; t->prl_count++; + + spin_lock_init(&p->lock); + setup_timer(&p->rs_timer, ipip6_tunnel_rs_timer, (unsigned long) p); update: p->addr = a->addr; p->flags = a->flags; + p->rs_delay = a->rs_delay; + if (p->rs_delay == 0) + p->rs_delay = IPTUNNEL_RS_DEFAULT_DELAY; + spin_lock(&p->lock); + del_timer(&p->rs_timer); + if (p->flags & PRL_DEFAULT) + mod_timer(&p->rs_timer, jiffies + 1); + spin_unlock(&p->lock); out: write_unlock(&ipip6_lock); return err; @@ -339,6 +404,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) if ((*p)->addr == a->addr) { x = *p; *p = x->next; + spin_lock(&x->lock); + del_timer(&x->rs_timer); + spin_unlock(&x->lock); kfree(x); t->prl_count--; goto out; @@ -349,13 +417,16 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) while (t->prl) { x = t->prl; t->prl = t->prl->next; + spin_lock(&x->lock); + del_timer(&x->rs_timer); + spin_unlock(&x->lock); kfree(x); t->prl_count--; } } out: write_unlock(&ipip6_lock); - return 0; + return err; } static int @@ -446,7 +517,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info) err = -ENOENT; read_lock(&ipip6_lock); - t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); + t = ipip6_tunnel_lookup(dev_net(skb->dev), + skb->dev, + iph->daddr, + iph->saddr); if (t == NULL || t->parms.iph.daddr == 0) goto out; @@ -481,8 +555,9 @@ static int ipip6_rcv(struct sk_buff *skb) iph = ip_hdr(skb); read_lock(&ipip6_lock); - if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), - iph->saddr, iph->daddr)) != NULL) { + tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, + iph->saddr, iph->daddr); + if (tunnel != NULL) { secpath_reset(skb); skb->mac_header = skb->network_header; skb_reset_network_header(skb); @@ -500,8 +575,7 @@ static int ipip6_rcv(struct sk_buff *skb) tunnel->dev->stats.rx_packets++; tunnel->dev->stats.rx_bytes += skb->len; skb->dev = tunnel->dev; - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); nf_reset(skb); ipip6_ecn_decapsulate(iph, skb); netif_rx(skb); @@ -563,8 +637,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (dev->priv_flags & IFF_ISATAP) { struct neighbour *neigh = NULL; - if (skb->dst) - neigh = skb->dst->neighbour; + if (skb_dst(skb)) + neigh = skb_dst(skb)->neighbour; if (neigh == NULL) { if (net_ratelimit()) @@ -588,8 +662,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (!dst) { struct neighbour *neigh = NULL; - if (skb->dst) - neigh = skb->dst->neighbour; + if (skb_dst(skb)) + neigh = skb_dst(skb)->neighbour; if (neigh == NULL) { if (net_ratelimit()) @@ -639,7 +713,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (tiph->frag_off) mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); else - mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; if (mtu < 68) { stats->collisions++; @@ -648,8 +722,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; - if (tunnel->parms.iph.daddr && skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (tunnel->parms.iph.daddr && skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->len > mtu) { icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); @@ -693,8 +767,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_network_header(skb); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); IPCB(skb)->flags = 0; - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* * Push down and install the IPIP header. diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 711175e0571f..8c2513982b61 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -131,7 +131,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) int mssind; const __u16 mss = *mssp; - tcp_sk(sk)->last_synq_overflow = jiffies; + tcp_synq_overflow(sk); for (mssind = 0; mss > msstab[mssind + 1]; mssind++) ; @@ -175,7 +175,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) if (!sysctl_tcp_syncookies || !th->ack) goto out; - if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || + if (tcp_synq_no_recent_overflow(sk) || (mss = cookie_check(skb, cookie)) == 0) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); goto out; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4b5aa1854260..53b6a4192b16 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -941,9 +941,10 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) return 0; } -struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) +static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, + struct sk_buff *skb) { - struct ipv6hdr *iph = ipv6_hdr(skb); + struct ipv6hdr *iph = skb_gro_network_header(skb); switch (skb->ip_summed) { case CHECKSUM_COMPLETE: @@ -961,9 +962,8 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) return tcp_gro_receive(head, skb); } -EXPORT_SYMBOL(tcp6_gro_receive); -int tcp6_gro_complete(struct sk_buff *skb) +static int tcp6_gro_complete(struct sk_buff *skb) { struct ipv6hdr *iph = ipv6_hdr(skb); struct tcphdr *th = tcp_hdr(skb); @@ -974,7 +974,6 @@ int tcp6_gro_complete(struct sk_buff *skb) return tcp_gro_complete(skb); } -EXPORT_SYMBOL(tcp6_gro_complete); static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, struct tcp_md5sig_key *key, int rst) @@ -982,9 +981,10 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, struct tcphdr *th = tcp_hdr(skb), *t1; struct sk_buff *buff; struct flowi fl; - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); struct sock *ctl_sk = net->ipv6.tcp_sk; unsigned int tot_len = sizeof(struct tcphdr); + struct dst_entry *dst; __be32 *topt; if (ts) @@ -1053,8 +1053,9 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, * Underlying function will use this to retrieve the network * namespace */ - if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { - if (xfrm_lookup(net, &buff->dst, &fl, NULL, 0) >= 0) { + if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { + if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { + skb_dst_set(buff, dst); ip6_xmit(ctl_sk, buff, &fl, NULL, 0); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); if (rst) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8905712cfbb8..fc333d854728 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -177,10 +177,9 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, if (unlikely(sk = skb_steal_sock(skb))) return sk; - else - return __udp6_lib_lookup(dev_net(skb->dst->dev), &iph->saddr, sport, - &iph->daddr, dport, inet6_iif(skb), - udptable); + return __udp6_lib_lookup(dev_net(skb_dst(skb)->dev), &iph->saddr, sport, + &iph->daddr, dport, inet6_iif(skb), + udptable); } /* diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index e20529b4c825..3927832227b9 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -31,7 +31,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) */ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct ipv6hdr *top_iph; int dsfield; @@ -45,7 +45,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, sizeof(top_iph->flow_lbl)); - top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family); + top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family); dsfield = XFRM_MODE_SKB_CB(skb)->tos; dsfield = INET_ECN_encapsulate(dsfield, dsfield); diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 5ee5a031bc93..c4f4eef032a3 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -30,7 +30,7 @@ EXPORT_SYMBOL(xfrm6_find_1stfragopt); static int xfrm6_tunnel_check_size(struct sk_buff *skb) { int mtu, ret = 0; - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); mtu = dst_mtu(dst); if (mtu < IPV6_MIN_MTU) @@ -90,6 +90,6 @@ static int xfrm6_output_finish(struct sk_buff *skb) int xfrm6_output(struct sk_buff *skb) { - return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dst->dev, + return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb_dst(skb)->dev, xfrm6_output_finish); } diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 2562ebc1b22c..7af2e74deda8 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -982,17 +982,12 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command) { struct sk_buff *tx_skb; struct sk_buff *skb; - int count; IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); - /* Initialize variables */ - count = skb_queue_len(&self->wx_list); - /* Resend unacknowledged frame(s) */ - skb = skb_peek(&self->wx_list); - while (skb != NULL) { + skb_queue_walk(&self->wx_list, skb) { irlap_wait_min_turn_around(self, &self->qos_tx); /* We copy the skb to be retransmitted since we will have to @@ -1011,21 +1006,12 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command) /* * Set poll bit on the last frame retransmitted */ - if (count-- == 1) + if (skb_queue_is_last(&self->wx_list, skb)) tx_skb->data[1] |= PF_BIT; /* Set p/f bit */ else tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */ irlap_send_i_frame(self, tx_skb, command); - - /* - * If our skb is the last buffer in the list, then - * we are finished, if not, move to the next sk-buffer - */ - if (skb == skb_peek_tail(&self->wx_list)) - skb = NULL; - else - skb = skb->next; } #if 0 /* Not yet */ /* diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index 2f05ec1037ab..8dd7ed7e7c1f 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -87,7 +87,7 @@ static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) if (!dev) return -ENODEV; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { dev_put(dev); return -ENOMEM; @@ -148,21 +148,8 @@ static struct genl_ops irda_nl_ops[] = { int irda_nl_register(void) { - int err, i; - - err = genl_register_family(&irda_nl_family); - if (err) - return err; - - for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) { - err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]); - if (err) - goto err_out; - } - return 0; - err_out: - genl_unregister_family(&irda_nl_family); - return err; + return genl_register_family_with_ops(&irda_nl_family, + irda_nl_ops, ARRAY_SIZE(irda_nl_ops)); } void irda_nl_unregister(void) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index b51c9187c347..a9b3a6f9ea95 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -29,10 +29,7 @@ #include #include -#define CONFIG_IUCV_SOCK_DEBUG 1 - -#define IPRMDATA 0x80 -#define VERSION "1.0" +#define VERSION "1.1" static char iucv_userid[80]; @@ -44,6 +41,19 @@ static struct proto iucv_proto = { .obj_size = sizeof(struct iucv_sock), }; +/* special AF_IUCV IPRM messages */ +static const u8 iprm_shutdown[8] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +#define TRGCLS_SIZE (sizeof(((struct iucv_message *)0)->class)) + +/* macros to set/get socket control buffer at correct offset */ +#define CB_TAG(skb) ((skb)->cb) /* iucv message tag */ +#define CB_TAG_LEN (sizeof(((struct iucv_message *) 0)->tag)) +#define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */ +#define CB_TRGCLS_LEN (TRGCLS_SIZE) + + static void iucv_sock_kill(struct sock *sk); static void iucv_sock_close(struct sock *sk); @@ -54,6 +64,7 @@ static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]); static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]); static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]); +static void iucv_callback_shutdown(struct iucv_path *, u8 ipuser[16]); static struct iucv_sock_list iucv_sk_list = { .lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock), @@ -65,7 +76,8 @@ static struct iucv_handler af_iucv_handler = { .path_complete = iucv_callback_connack, .path_severed = iucv_callback_connrej, .message_pending = iucv_callback_rx, - .message_complete = iucv_callback_txdone + .message_complete = iucv_callback_txdone, + .path_quiesced = iucv_callback_shutdown, }; static inline void high_nmcpy(unsigned char *dst, char *src) @@ -78,6 +90,37 @@ static inline void low_nmcpy(unsigned char *dst, char *src) memcpy(&dst[8], src, 8); } +/** + * iucv_msg_length() - Returns the length of an iucv message. + * @msg: Pointer to struct iucv_message, MUST NOT be NULL + * + * The function returns the length of the specified iucv message @msg of data + * stored in a buffer and of data stored in the parameter list (PRMDATA). + * + * For IUCV_IPRMDATA, AF_IUCV uses the following convention to transport socket + * data: + * PRMDATA[0..6] socket data (max 7 bytes); + * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) + * + * The socket data length is computed by substracting the socket data length + * value from 0xFF. + * If the socket data len is greater 7, then PRMDATA can be used for special + * notifications (see iucv_sock_shutdown); and further, + * if the socket data len is > 7, the function returns 8. + * + * Use this function to allocate socket buffers to store iucv message data. + */ +static inline size_t iucv_msg_length(struct iucv_message *msg) +{ + size_t datalen; + + if (msg->flags & IUCV_IPRMDATA) { + datalen = 0xff - msg->rmmsg[7]; + return (datalen < 8) ? datalen : 8; + } + return msg->length; +} + /* Timers */ static void iucv_sock_timeout(unsigned long arg) { @@ -225,6 +268,8 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) spin_lock_init(&iucv_sk(sk)->message_q.lock); skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); iucv_sk(sk)->send_tag = 0; + iucv_sk(sk)->flags = 0; + iucv_sk(sk)->msglimit = IUCV_QUEUELEN_DEFAULT; iucv_sk(sk)->path = NULL; memset(&iucv_sk(sk)->src_user_id , 0, 32); @@ -248,11 +293,22 @@ static int iucv_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; - if (sock->type != SOCK_STREAM) - return -ESOCKTNOSUPPORT; + if (protocol && protocol != PF_IUCV) + return -EPROTONOSUPPORT; sock->state = SS_UNCONNECTED; - sock->ops = &iucv_sock_ops; + + switch (sock->type) { + case SOCK_STREAM: + sock->ops = &iucv_sock_ops; + break; + case SOCK_SEQPACKET: + /* currently, proto ops can handle both sk types */ + sock->ops = &iucv_sock_ops; + break; + default: + return -ESOCKTNOSUPPORT; + } sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL); if (!sk) @@ -463,11 +519,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, if (sk->sk_state != IUCV_OPEN && sk->sk_state != IUCV_BOUND) return -EBADFD; - if (sk->sk_type != SOCK_STREAM) + if (sk->sk_type != SOCK_STREAM && sk->sk_type != SOCK_SEQPACKET) return -EINVAL; - iucv = iucv_sk(sk); - if (sk->sk_state == IUCV_OPEN) { err = iucv_sock_autobind(sk); if (unlikely(err)) @@ -486,8 +540,8 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, iucv = iucv_sk(sk); /* Create path. */ - iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT, - IPRMDATA, GFP_KERNEL); + iucv->path = iucv_path_alloc(iucv->msglimit, + IUCV_IPRMDATA, GFP_KERNEL); if (!iucv->path) { err = -ENOMEM; goto done; @@ -521,8 +575,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, } if (sk->sk_state == IUCV_DISCONN) { - release_sock(sk); - return -ECONNREFUSED; + err = -ECONNREFUSED; } if (err) { @@ -545,7 +598,10 @@ static int iucv_sock_listen(struct socket *sock, int backlog) lock_sock(sk); err = -EINVAL; - if (sk->sk_state != IUCV_BOUND || sock->type != SOCK_STREAM) + if (sk->sk_state != IUCV_BOUND) + goto done; + + if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) goto done; sk->sk_max_ack_backlog = backlog; @@ -636,6 +692,30 @@ static int iucv_sock_getname(struct socket *sock, struct sockaddr *addr, return 0; } +/** + * iucv_send_iprm() - Send socket data in parameter list of an iucv message. + * @path: IUCV path + * @msg: Pointer to a struct iucv_message + * @skb: The socket data to send, skb->len MUST BE <= 7 + * + * Send the socket data in the parameter list in the iucv message + * (IUCV_IPRMDATA). The socket data is stored at index 0 to 6 in the parameter + * list and the socket data len at index 7 (last byte). + * See also iucv_msg_length(). + * + * Returns the error code from the iucv_message_send() call. + */ +static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg, + struct sk_buff *skb) +{ + u8 prmdata[8]; + + memcpy(prmdata, (void *) skb->data, skb->len); + prmdata[7] = 0xff - (u8) skb->len; + return iucv_message_send(path, msg, IUCV_IPRMDATA, 0, + (void *) prmdata, 8); +} + static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { @@ -643,6 +723,8 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct iucv_sock *iucv = iucv_sk(sk); struct sk_buff *skb; struct iucv_message txmsg; + struct cmsghdr *cmsg; + int cmsg_done; char user_id[9]; char appl_id[9]; int err; @@ -654,6 +736,10 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; + /* SOCK_SEQPACKET: we do not support segmented records */ + if (sk->sk_type == SOCK_SEQPACKET && !(msg->msg_flags & MSG_EOR)) + return -EOPNOTSUPP; + lock_sock(sk); if (sk->sk_shutdown & SEND_SHUTDOWN) { @@ -662,6 +748,52 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, } if (sk->sk_state == IUCV_CONNECTED) { + /* initialize defaults */ + cmsg_done = 0; /* check for duplicate headers */ + txmsg.class = 0; + + /* iterate over control messages */ + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + + if (!CMSG_OK(msg, cmsg)) { + err = -EINVAL; + goto out; + } + + if (cmsg->cmsg_level != SOL_IUCV) + continue; + + if (cmsg->cmsg_type & cmsg_done) { + err = -EINVAL; + goto out; + } + cmsg_done |= cmsg->cmsg_type; + + switch (cmsg->cmsg_type) { + case SCM_IUCV_TRGCLS: + if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { + err = -EINVAL; + goto out; + } + + /* set iucv message target class */ + memcpy(&txmsg.class, + (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); + + break; + + default: + err = -EINVAL; + goto out; + break; + } + } + + /* allocate one skb for each iucv message: + * this is fine for SOCK_SEQPACKET (unless we want to support + * segmented records using the MSG_EOR flag), but + * for SOCK_STREAM we might want to improve it in future */ if (!(skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) @@ -672,13 +804,33 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, goto fail; } - txmsg.class = 0; - memcpy(&txmsg.class, skb->data, skb->len >= 4 ? 4 : skb->len); + /* increment and save iucv message tag for msg_completion cbk */ txmsg.tag = iucv->send_tag++; - memcpy(skb->cb, &txmsg.tag, 4); + memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); skb_queue_tail(&iucv->send_skb_q, skb); - err = iucv_message_send(iucv->path, &txmsg, 0, 0, - (void *) skb->data, skb->len); + + if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) + && skb->len <= 7) { + err = iucv_send_iprm(iucv->path, &txmsg, skb); + + /* on success: there is no message_complete callback + * for an IPRMDATA msg; remove skb from send queue */ + if (err == 0) { + skb_unlink(skb, &iucv->send_skb_q); + kfree_skb(skb); + } + + /* this error should never happen since the + * IUCV_IPRMDATA path flag is set... sever path */ + if (err == 0x15) { + iucv_path_sever(iucv->path, NULL); + skb_unlink(skb, &iucv->send_skb_q); + err = -EPIPE; + goto fail; + } + } else + err = iucv_message_send(iucv->path, &txmsg, 0, 0, + (void *) skb->data, skb->len); if (err) { if (err == 3) { user_id[8] = 0; @@ -725,6 +877,10 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len) if (!nskb) return -ENOMEM; + /* copy target class to control buffer of new skb */ + memcpy(CB_TRGCLS(nskb), CB_TRGCLS(skb), CB_TRGCLS_LEN); + + /* copy data fragment */ memcpy(nskb->data, skb->data + copied, size); copied += size; dataleft -= size; @@ -744,19 +900,33 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, struct iucv_message *msg) { int rc; + unsigned int len; - if (msg->flags & IPRMDATA) { - skb->data = NULL; - skb->len = 0; + len = iucv_msg_length(msg); + + /* store msg target class in the second 4 bytes of skb ctrl buffer */ + /* Note: the first 4 bytes are reserved for msg tag */ + memcpy(CB_TRGCLS(skb), &msg->class, CB_TRGCLS_LEN); + + /* check for special IPRM messages (e.g. iucv_sock_shutdown) */ + if ((msg->flags & IUCV_IPRMDATA) && len > 7) { + if (memcmp(msg->rmmsg, iprm_shutdown, 8) == 0) { + skb->data = NULL; + skb->len = 0; + } } else { - rc = iucv_message_receive(path, msg, 0, skb->data, - msg->length, NULL); + rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA, + skb->data, len, NULL); if (rc) { kfree_skb(skb); return; } - if (skb->truesize >= sk->sk_rcvbuf / 4) { - rc = iucv_fragment_skb(sk, skb, msg->length); + /* we need to fragment iucv messages for SOCK_STREAM only; + * for SOCK_SEQPACKET, it is only relevant if we support + * record segmentation using MSG_EOR (see also recvmsg()) */ + if (sk->sk_type == SOCK_STREAM && + skb->truesize >= sk->sk_rcvbuf / 4) { + rc = iucv_fragment_skb(sk, skb, len); kfree_skb(skb); skb = NULL; if (rc) { @@ -767,7 +937,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, } else { skb_reset_transport_header(skb); skb_reset_network_header(skb); - skb->len = msg->length; + skb->len = len; } } @@ -782,7 +952,7 @@ static void iucv_process_message_q(struct sock *sk) struct sock_msg_q *p, *n; list_for_each_entry_safe(p, n, &iucv->message_q.list, list) { - skb = alloc_skb(p->msg.length, GFP_ATOMIC | GFP_DMA); + skb = alloc_skb(iucv_msg_length(&p->msg), GFP_ATOMIC | GFP_DMA); if (!skb) break; iucv_process_message(sk, skb, p->path, &p->msg); @@ -799,7 +969,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; struct iucv_sock *iucv = iucv_sk(sk); - int target, copied = 0; + unsigned int copied, rlen; struct sk_buff *skb, *rskb, *cskb; int err = 0; @@ -812,8 +982,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); - /* receive/dequeue next skb: * the function understands MSG_PEEK and, thus, does not dequeue skb */ skb = skb_recv_datagram(sk, flags, noblock, &err); @@ -823,25 +991,45 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, return err; } - copied = min_t(unsigned int, skb->len, len); + rlen = skb->len; /* real length of skb */ + copied = min_t(unsigned int, rlen, len); cskb = skb; if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { - skb_queue_head(&sk->sk_receive_queue, skb); - if (copied == 0) - return -EFAULT; - goto done; + if (!(flags & MSG_PEEK)) + skb_queue_head(&sk->sk_receive_queue, skb); + return -EFAULT; } - len -= copied; + /* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */ + if (sk->sk_type == SOCK_SEQPACKET) { + if (copied < rlen) + msg->msg_flags |= MSG_TRUNC; + /* each iucv message contains a complete record */ + msg->msg_flags |= MSG_EOR; + } + + /* create control message to store iucv msg target class: + * get the trgcls from the control buffer of the skb due to + * fragmentation of original iucv message. */ + err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS, + CB_TRGCLS_LEN, CB_TRGCLS(skb)); + if (err) { + if (!(flags & MSG_PEEK)) + skb_queue_head(&sk->sk_receive_queue, skb); + return err; + } /* Mark read part of skb as used */ if (!(flags & MSG_PEEK)) { - skb_pull(skb, copied); - if (skb->len) { - skb_queue_head(&sk->sk_receive_queue, skb); - goto done; + /* SOCK_STREAM: re-queue skb if it contains unreceived data */ + if (sk->sk_type == SOCK_STREAM) { + skb_pull(skb, copied); + if (skb->len) { + skb_queue_head(&sk->sk_receive_queue, skb); + goto done; + } } kfree_skb(skb); @@ -866,7 +1054,11 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, } done: - return err ? : copied; + /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */ + if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC)) + copied = rlen; + + return copied; } static inline unsigned int iucv_accept_poll(struct sock *parent) @@ -928,7 +1120,6 @@ static int iucv_sock_shutdown(struct socket *sock, int how) struct iucv_sock *iucv = iucv_sk(sk); struct iucv_message txmsg; int err = 0; - u8 prmmsg[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; how++; @@ -953,7 +1144,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how) txmsg.class = 0; txmsg.tag = 0; err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0, - (void *) prmmsg, 8); + (void *) iprm_shutdown, 8); if (err) { switch (err) { case 1: @@ -1007,6 +1198,98 @@ static int iucv_sock_release(struct socket *sock) return err; } +/* getsockopt and setsockopt */ +static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, + char __user *optval, int optlen) +{ + struct sock *sk = sock->sk; + struct iucv_sock *iucv = iucv_sk(sk); + int val; + int rc; + + if (level != SOL_IUCV) + return -ENOPROTOOPT; + + if (optlen < sizeof(int)) + return -EINVAL; + + if (get_user(val, (int __user *) optval)) + return -EFAULT; + + rc = 0; + + lock_sock(sk); + switch (optname) { + case SO_IPRMDATA_MSG: + if (val) + iucv->flags |= IUCV_IPRMDATA; + else + iucv->flags &= ~IUCV_IPRMDATA; + break; + case SO_MSGLIMIT: + switch (sk->sk_state) { + case IUCV_OPEN: + case IUCV_BOUND: + if (val < 1 || val > (u16)(~0)) + rc = -EINVAL; + else + iucv->msglimit = val; + break; + default: + rc = -EINVAL; + break; + } + break; + default: + rc = -ENOPROTOOPT; + break; + } + release_sock(sk); + + return rc; +} + +static int iucv_sock_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) +{ + struct sock *sk = sock->sk; + struct iucv_sock *iucv = iucv_sk(sk); + int val, len; + + if (level != SOL_IUCV) + return -ENOPROTOOPT; + + if (get_user(len, optlen)) + return -EFAULT; + + if (len < 0) + return -EINVAL; + + len = min_t(unsigned int, len, sizeof(int)); + + switch (optname) { + case SO_IPRMDATA_MSG: + val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0; + break; + case SO_MSGLIMIT: + lock_sock(sk); + val = (iucv->path != NULL) ? iucv->path->msglim /* connected */ + : iucv->msglimit; /* default */ + release_sock(sk); + break; + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + + return 0; +} + + /* Callback wrappers - called from iucv base support */ static int iucv_callback_connreq(struct iucv_path *path, u8 ipvmid[8], u8 ipuser[16]) @@ -1060,7 +1343,7 @@ static int iucv_callback_connreq(struct iucv_path *path, } /* Create the new socket */ - nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC); + nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC); if (!nsk) { err = iucv_path_sever(path, user_data); iucv_path_free(path); @@ -1083,7 +1366,9 @@ static int iucv_callback_connreq(struct iucv_path *path, memcpy(nuser_data + 8, niucv->src_name, 8); ASCEBC(nuser_data + 8, 8); - path->msglim = IUCV_QUEUELEN_DEFAULT; + /* set message limit for path based on msglimit of accepting socket */ + niucv->msglimit = iucv->msglimit; + path->msglim = iucv->msglimit; err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk); if (err) { err = iucv_path_sever(path, user_data); @@ -1131,19 +1416,17 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) goto save_message; len = atomic_read(&sk->sk_rmem_alloc); - len += msg->length + sizeof(struct sk_buff); + len += iucv_msg_length(msg) + sizeof(struct sk_buff); if (len > sk->sk_rcvbuf) goto save_message; - skb = alloc_skb(msg->length, GFP_ATOMIC | GFP_DMA); + skb = alloc_skb(iucv_msg_length(msg), GFP_ATOMIC | GFP_DMA); if (!skb) goto save_message; iucv_process_message(sk, skb, path, msg); goto out_unlock; - return; - save_message: save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA); if (!save_msg) @@ -1170,7 +1453,7 @@ static void iucv_callback_txdone(struct iucv_path *path, spin_lock_irqsave(&list->lock, flags); while (list_skb != (struct sk_buff *)list) { - if (!memcmp(&msg->tag, list_skb->cb, 4)) { + if (!memcmp(&msg->tag, CB_TAG(list_skb), CB_TAG_LEN)) { this = list_skb; break; } @@ -1206,6 +1489,21 @@ static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16]) sk->sk_state_change(sk); } +/* called if the other communication side shuts down its RECV direction; + * in turn, the callback sets SEND_SHUTDOWN to disable sending of data. + */ +static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16]) +{ + struct sock *sk = path->private; + + bh_lock_sock(sk); + if (sk->sk_state != IUCV_CLOSED) { + sk->sk_shutdown |= SEND_SHUTDOWN; + sk->sk_state_change(sk); + } + bh_unlock_sock(sk); +} + static struct proto_ops iucv_sock_ops = { .family = PF_IUCV, .owner = THIS_MODULE, @@ -1222,8 +1520,8 @@ static struct proto_ops iucv_sock_ops = { .mmap = sock_no_mmap, .socketpair = sock_no_socketpair, .shutdown = iucv_sock_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt + .setsockopt = iucv_sock_setsockopt, + .getsockopt = iucv_sock_getsockopt, }; static struct net_proto_family iucv_sock_family_ops = { diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index a35240f61ec3..61e8038a55ee 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -280,6 +280,7 @@ union iucv_param { * Anchor for per-cpu IUCV command parameter block. */ static union iucv_param *iucv_param[NR_CPUS]; +static union iucv_param *iucv_param_irq[NR_CPUS]; /** * iucv_call_b2f0 @@ -358,7 +359,7 @@ static void iucv_allow_cpu(void *data) * 0x10 - Flag to allow priority message completion interrupts * 0x08 - Flag to allow IUCV control interrupts */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; memset(parm, 0, sizeof(union iucv_param)); parm->set_mask.ipmask = 0xf8; iucv_call_b2f0(IUCV_SETMASK, parm); @@ -379,7 +380,7 @@ static void iucv_block_cpu(void *data) union iucv_param *parm; /* Disable all iucv interrupts. */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; memset(parm, 0, sizeof(union iucv_param)); iucv_call_b2f0(IUCV_SETMASK, parm); @@ -403,7 +404,7 @@ static void iucv_declare_cpu(void *data) return; /* Declare interrupt buffer. */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; memset(parm, 0, sizeof(union iucv_param)); parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]); rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); @@ -460,7 +461,7 @@ static void iucv_retrieve_cpu(void *data) iucv_block_cpu(NULL); /* Retrieve interrupt buffer. */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); /* Clear indication that an iucv buffer exists for this cpu. */ @@ -574,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, iucv_irq_data[cpu] = NULL; return NOTIFY_BAD; } + iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_param_irq[cpu]) { + kfree(iucv_param[cpu]); + iucv_param[cpu] = NULL; + kfree(iucv_irq_data[cpu]); + iucv_irq_data[cpu] = NULL; + return NOTIFY_BAD; + } break; case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: + kfree(iucv_param_irq[cpu]); + iucv_param_irq[cpu] = NULL; kfree(iucv_param[cpu]); iucv_param[cpu] = NULL; kfree(iucv_irq_data[cpu]); @@ -625,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) { union iucv_param *parm; - parm = iucv_param[smp_processor_id()]; + parm = iucv_param_irq[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (userdata) memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); @@ -918,10 +930,8 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) if (iucv_active_cpu != smp_processor_id()) spin_lock_bh(&iucv_table_lock); rc = iucv_sever_pathid(path->pathid, userdata); - if (!rc) { - iucv_path_table[path->pathid] = NULL; - list_del_init(&path->list); - } + iucv_path_table[path->pathid] = NULL; + list_del_init(&path->list); if (iucv_active_cpu != smp_processor_id()) spin_unlock_bh(&iucv_table_lock); preempt_enable(); @@ -1378,6 +1388,8 @@ static void iucv_path_complete(struct iucv_irq_data *data) struct iucv_path_complete *ipc = (void *) data; struct iucv_path *path = iucv_path_table[ipc->ippathid]; + if (path) + path->flags = ipc->ipflags1; if (path && path->handler && path->handler->path_complete) path->handler->path_complete(path, ipc->ipuser); } @@ -1413,7 +1425,7 @@ static void iucv_path_severed(struct iucv_irq_data *data) else { iucv_sever_pathid(path->pathid, NULL); iucv_path_table[path->pathid] = NULL; - list_del_init(&path->list); + list_del(&path->list); iucv_path_free(path); } } @@ -1717,6 +1729,13 @@ static int __init iucv_init(void) rc = -ENOMEM; goto out_free; } + iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_param_irq[cpu]) { + rc = -ENOMEM; + goto out_free; + } + } rc = register_hotcpu_notifier(&iucv_cpu_notifier); if (rc) @@ -1734,6 +1753,8 @@ static int __init iucv_init(void) unregister_hotcpu_notifier(&iucv_cpu_notifier); out_free: for_each_possible_cpu(cpu) { + kfree(iucv_param_irq[cpu]); + iucv_param_irq[cpu] = NULL; kfree(iucv_param[cpu]); iucv_param[cpu] = NULL; kfree(iucv_irq_data[cpu]); @@ -1764,6 +1785,8 @@ static void __exit iucv_exit(void) spin_unlock_irq(&iucv_queue_lock); unregister_hotcpu_notifier(&iucv_cpu_notifier); for_each_possible_cpu(cpu) { + kfree(iucv_param_irq[cpu]); + iucv_param_irq[cpu] = NULL; kfree(iucv_param[cpu]); iucv_param[cpu] = NULL; kfree(iucv_irq_data[cpu]); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index febae702685c..9208cf5f2bd5 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -935,7 +935,7 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, if (llc->dev) { sllc.sllc_arphrd = llc->dev->type; - memcpy(&sllc.sllc_mac, &llc->dev->dev_addr, + memcpy(&sllc.sllc_mac, llc->dev->dev_addr, IFHWADDRLEN); } } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 3477624a4906..c6bab39b018e 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -79,10 +79,6 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) if (unlikely(!ev->ind_prim && !ev->cfm_prim)) { /* indicate or confirm not required */ - /* XXX this is not very pretty, perhaps we should store - * XXX indicate/confirm-needed state in the llc_conn_state_ev - * XXX control block of the SKB instead? -DaveM - */ if (!skb->next) goto out_kfree_skb; goto out_skb_put; diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index ecc3faf9f11a..ba2643a43c73 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -1,16 +1,35 @@ config MAC80211 tristate "Generic IEEE 802.11 Networking Stack (mac80211)" + depends on CFG80211 select CRYPTO select CRYPTO_ECB select CRYPTO_ARC4 select CRYPTO_AES select CRC32 select WIRELESS_EXT - select CFG80211 ---help--- This option enables the hardware independent IEEE 802.11 networking stack. +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 diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 07656d830bc4..bc064d7933ff 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -16,12 +16,12 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, u16 initiator, u16 reason) { struct ieee80211_local *local = sta->local; - struct ieee80211_hw *hw = &local->hw; int i; /* check if TID is in operational state */ @@ -41,8 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - if (local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, - &sta->sta, tid, NULL)) + if (drv_ampdu_action(local, IEEE80211_AMPDU_RX_STOP, + &sta->sta, tid, NULL)) printk(KERN_DEBUG "HW problem - can not stop rx " "aggregation for tid %d\n", tid); @@ -68,6 +68,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, spin_lock_bh(&sta->lock); /* free resources */ kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); + kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { kfree(sta->ampdu_mlme.tid_rx[tid]); @@ -268,19 +269,23 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, /* prepare reordering buffer */ tid_agg_rx->reorder_buf = kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); - if (!tid_agg_rx->reorder_buf) { + tid_agg_rx->reorder_time = + kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); + if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) printk(KERN_ERR "can not allocate reordering buffer " "to tid %d\n", tid); #endif + kfree(tid_agg_rx->reorder_buf); + kfree(tid_agg_rx->reorder_time); kfree(sta->ampdu_mlme.tid_rx[tid]); + sta->ampdu_mlme.tid_rx[tid] = NULL; goto end; } - if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num); + ret = drv_ampdu_action(local, IEEE80211_AMPDU_RX_START, + &sta->sta, tid, &start_seq_num); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); #endif /* CONFIG_MAC80211_HT_DEBUG */ diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 947aaaad35d2..9e5762ad307d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -16,6 +16,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "wme.h" /** @@ -131,11 +132,14 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, state = &sta->ampdu_mlme.tid_state_tx[tid]; + if (*state == HT_AGG_STATE_OPERATIONAL) + sta->ampdu_mlme.addba_req_num[tid] = 0; + *state = HT_AGG_STATE_REQ_STOP_BA_MSK | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); - ret = local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_STOP, - &sta->sta, tid, NULL); + ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_STOP, + &sta->sta, tid, NULL); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -306,8 +310,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) start_seq_num = sta->tid_seq[tid]; - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, - &sta->sta, tid, &start_seq_num); + ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_START, + &sta->sta, tid, &start_seq_num); if (ret) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -336,6 +340,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) sta->ampdu_mlme.tid_tx[tid]->dialog_token, sta->ampdu_mlme.tid_tx[tid]->ssn, 0x40, 5000); + sta->ampdu_mlme.addba_req_num[tid]++; /* activate the timer for the recipient's addBA response */ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = jiffies + ADDBA_RESP_INTERVAL; @@ -418,8 +423,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, ieee80211_agg_splice_finish(local, sta, tid); spin_unlock(&local->ampdu_lock); - local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL); + drv_ampdu_action(local, IEEE80211_AMPDU_TX_OPERATIONAL, + &sta->sta, tid, NULL); } void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) @@ -605,7 +610,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) *state = HT_AGG_STATE_IDLE; /* from now on packets are no longer put onto sta->pending */ - sta->ampdu_mlme.addba_req_num[tid] = 0; kfree(sta->ampdu_mlme.tid_tx[tid]); sta->ampdu_mlme.tid_tx[tid] = NULL; @@ -688,7 +692,6 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, sta->ampdu_mlme.addba_req_num[tid] = 0; } else { - sta->ampdu_mlme.addba_req_num[tid]++; ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); } spin_unlock_bh(&sta->lock); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e677b751d468..3f47276caeb8 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -13,6 +13,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "cfg.h" #include "rate.h" #include "mesh.h" @@ -111,7 +112,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, } static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_idx, u8 *mac_addr, + u8 key_idx, const u8 *mac_addr, struct key_params *params) { struct ieee80211_sub_if_data *sdata; @@ -140,7 +141,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, return -EINVAL; } - key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key); + key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, + params->seq_len, params->seq); if (!key) return -ENOMEM; @@ -165,7 +167,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, } static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_idx, u8 *mac_addr) + u8 key_idx, const u8 *mac_addr) { struct ieee80211_sub_if_data *sdata; struct sta_info *sta; @@ -207,7 +209,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, } static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_idx, u8 *mac_addr, void *cookie, + u8 key_idx, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *params)) { @@ -245,12 +247,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, iv32 = key->u.tkip.tx.iv32; iv16 = key->u.tkip.tx.iv16; - if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && - sdata->local->ops->get_tkip_seq) - sdata->local->ops->get_tkip_seq( - local_to_hw(sdata->local), - key->conf.hw_key_idx, - &iv32, &iv16); + if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + drv_get_tkip_seq(sdata->local, + key->conf.hw_key_idx, + &iv32, &iv16); seq[0] = iv16 & 0xff; seq[1] = (iv16 >> 8) & 0xff; @@ -451,18 +451,11 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, * This is a kludge. beacon interval should really be part * of the beacon information. */ - if (params->interval && (sdata->local->hw.conf.beacon_int != - params->interval)) { - sdata->local->hw.conf.beacon_int = params->interval; - err = ieee80211_hw_config(sdata->local, - IEEE80211_CONF_CHANGE_BEACON_INTERVAL); - if (err < 0) - return err; - /* - * We updated some parameter so if below bails out - * it's not an error. - */ - err = 0; + if (params->interval && + (sdata->vif.bss_conf.beacon_int != params->interval)) { + sdata->vif.bss_conf.beacon_int = params->interval; + ieee80211_bss_info_change_notify(sdata, + BSS_CHANGED_BEACON_INT); } /* Need to have a beacon head if we don't have one yet */ @@ -528,8 +521,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_BEACON); + return 0; } static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -580,7 +574,8 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) synchronize_rcu(); kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + return 0; } /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ @@ -635,35 +630,46 @@ static void sta_apply_parameters(struct ieee80211_local *local, int i, j; struct ieee80211_supported_band *sband; struct ieee80211_sub_if_data *sdata = sta->sdata; + u32 mask, set; sband = local->hw.wiphy->bands[local->oper_channel->band]; - /* - * FIXME: updating the flags is racy when this function is - * called from ieee80211_change_station(), this will - * be resolved in a future patch. - */ + spin_lock_bh(&sta->lock); + mask = params->sta_flags_mask; + set = params->sta_flags_set; - if (params->station_flags & STATION_FLAG_CHANGED) { - spin_lock_bh(&sta->lock); + if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { sta->flags &= ~WLAN_STA_AUTHORIZED; - if (params->station_flags & STATION_FLAG_AUTHORIZED) + if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) sta->flags |= WLAN_STA_AUTHORIZED; - - sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; - if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE) - sta->flags |= WLAN_STA_SHORT_PREAMBLE; - - sta->flags &= ~WLAN_STA_WME; - if (params->station_flags & STATION_FLAG_WME) - sta->flags |= WLAN_STA_WME; - - sta->flags &= ~WLAN_STA_MFP; - if (params->station_flags & STATION_FLAG_MFP) - sta->flags |= WLAN_STA_MFP; - spin_unlock_bh(&sta->lock); } + if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { + sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; + if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) + sta->flags |= WLAN_STA_SHORT_PREAMBLE; + } + + if (mask & BIT(NL80211_STA_FLAG_WME)) { + sta->flags &= ~WLAN_STA_WME; + if (set & BIT(NL80211_STA_FLAG_WME)) + sta->flags |= WLAN_STA_WME; + } + + if (mask & BIT(NL80211_STA_FLAG_MFP)) { + sta->flags &= ~WLAN_STA_MFP; + if (set & BIT(NL80211_STA_FLAG_MFP)) + sta->flags |= WLAN_STA_MFP; + } + spin_unlock_bh(&sta->lock); + + /* + * cfg80211 validates this (1-2007) and allows setting the AID + * only when creating a new station entry + */ + if (params->aid) + sta->sta.aid = params->aid; + /* * FIXME: updating the following information is racy when this * function is called from ieee80211_change_station(). @@ -671,12 +677,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, * maybe we should just reject attemps to change it. */ - if (params->aid) { - sta->sta.aid = params->aid; - if (sta->sta.aid > IEEE80211_MAX_AID) - sta->sta.aid = 0; /* XXX: should this be an error? */ - } - if (params->listen_interval >= 0) sta->listen_interval = params->listen_interval; @@ -1120,10 +1120,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, p.cw_max = params->cwmax; p.cw_min = params->cwmin; p.txop = params->txop; - if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { + if (drv_conf_tx(local, params->queue, &p)) { printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", local->mdev->name, - params->queue); + "parameters for queue %d\n", + wiphy_name(local->hw.wiphy), params->queue); return -EINVAL; } @@ -1167,7 +1167,8 @@ static int ieee80211_scan(struct wiphy *wiphy, if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_ADHOC && - sdata->vif.type != NL80211_IFTYPE_MESH_POINT) + sdata->vif.type != NL80211_IFTYPE_MESH_POINT && + (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) return -EOPNOTSUPP; return ieee80211_request_scan(sdata, req); @@ -1255,9 +1256,22 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL; ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len); - if (ret) + 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); @@ -1267,25 +1281,106 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - /* TODO: req->ie */ + /* TODO: req->ie, req->peer_addr */ return ieee80211_sta_deauthenticate(sdata, req->reason_code); } static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - /* TODO: req->ie */ + /* TODO: req->ie, req->peer_addr */ return ieee80211_sta_disassociate(sdata, req->reason_code); } +static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + return ieee80211_ibss_join(sdata, params); +} + +static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + return ieee80211_ibss_leave(sdata); +} + +static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + int err; + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + err = drv_set_rts_threshold(local, wiphy->rts_threshold); + + if (err) + return err; + } + + if (changed & WIPHY_PARAM_RETRY_SHORT) + local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; + if (changed & WIPHY_PARAM_RETRY_LONG) + local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; + if (changed & + (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); + + return 0; +} + +static int ieee80211_set_tx_power(struct wiphy *wiphy, + enum tx_power_setting type, int dbm) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_channel *chan = local->hw.conf.channel; + u32 changes = 0; + + switch (type) { + case TX_POWER_AUTOMATIC: + local->user_power_level = -1; + break; + case TX_POWER_LIMITED: + if (dbm < 0) + return -EINVAL; + local->user_power_level = dbm; + break; + case TX_POWER_FIXED: + if (dbm < 0) + return -EINVAL; + /* TODO: move to cfg80211 when it knows the channel */ + if (dbm > chan->max_power) + return -EINVAL; + local->user_power_level = dbm; + break; + } + + ieee80211_hw_config(local, changes); + + return 0; +} + +static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + + *dbm = local->hw.conf.power_level; + + return 0; +} + +static void ieee80211_rfkill_poll(struct wiphy *wiphy) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + + drv_rfkill_poll(local); +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1322,4 +1417,10 @@ struct cfg80211_ops mac80211_config_ops = { .assoc = ieee80211_assoc, .deauth = ieee80211_deauth, .disassoc = ieee80211_disassoc, + .join_ibss = ieee80211_join_ibss, + .leave_ibss = ieee80211_leave_ibss, + .set_wiphy_params = ieee80211_set_wiphy_params, + .set_tx_power = ieee80211_set_tx_power, + .get_tx_power = ieee80211_get_tx_power, + .rfkill_poll = ieee80211_rfkill_poll, }; diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 210b9b6fecd2..11c72311f35b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -10,6 +10,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "debugfs.h" @@ -51,14 +52,6 @@ static const struct file_operations name## _ops = { \ DEBUGFS_READONLY_FILE(frequency, 20, "%d", local->hw.conf.channel->center_freq); -DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", - local->rts_threshold); -DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", - local->fragmentation_threshold); -DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", - local->hw.conf.short_frame_max_tx_count); -DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", - local->hw.conf.long_frame_max_tx_count); DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", local->total_ps_buffered); DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", @@ -70,11 +63,10 @@ static ssize_t tsf_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ieee80211_local *local = file->private_data; - u64 tsf = 0; + u64 tsf; char buf[100]; - if (local->ops->get_tsf) - tsf = local->ops->get_tsf(local_to_hw(local)); + tsf = drv_get_tsf(local); snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); @@ -97,13 +89,13 @@ static ssize_t tsf_write(struct file *file, if (strncmp(buf, "reset", 5) == 0) { if (local->ops->reset_tsf) { - local->ops->reset_tsf(local_to_hw(local)); + drv_reset_tsf(local); printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); } } else { tsf = simple_strtoul(buf, NULL, 0); if (local->ops->set_tsf) { - local->ops->set_tsf(local_to_hw(local), tsf); + drv_set_tsf(local, tsf); printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); } } @@ -135,6 +127,42 @@ static const struct file_operations reset_ops = { .open = mac80211_open_file_generic, }; +static ssize_t noack_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + int res; + char buf[10]; + + res = scnprintf(buf, sizeof(buf), "%d\n", local->wifi_wme_noack_test); + + return simple_read_from_buffer(user_buf, count, ppos, buf, res); +} + +static ssize_t noack_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + char buf[10]; + size_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0); + + return count; +} + +static const struct file_operations noack_ops = { + .read = noack_read, + .write = noack_write, + .open = mac80211_open_file_generic +}; + /* statistics stuff */ #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ @@ -150,14 +178,12 @@ static ssize_t format_devstat_counter(struct ieee80211_local *local, char buf[20]; int res; - if (!local->ops->get_stats) - return -EOPNOTSUPP; - rtnl_lock(); - res = local->ops->get_stats(local_to_hw(local), &stats); + res = drv_get_stats(local, &stats); rtnl_unlock(); - if (!res) - res = printvalue(&stats, buf, sizeof(buf)); + if (res) + return res; + res = printvalue(&stats, buf, sizeof(buf)); return simple_read_from_buffer(userbuf, count, ppos, buf, res); } @@ -269,14 +295,11 @@ void debugfs_hw_add(struct ieee80211_local *local) local->debugfs.keys = debugfs_create_dir("keys", phyd); DEBUGFS_ADD(frequency); - DEBUGFS_ADD(rts_threshold); - DEBUGFS_ADD(fragmentation_threshold); - DEBUGFS_ADD(short_retry_limit); - DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); DEBUGFS_ADD(tsf); DEBUGFS_ADD_MODE(reset, 0200); + DEBUGFS_ADD(noack); statsd = debugfs_create_dir("statistics", phyd); local->debugfs.statistics = statsd; @@ -324,14 +347,11 @@ void debugfs_hw_add(struct ieee80211_local *local) void debugfs_hw_del(struct ieee80211_local *local) { DEBUGFS_DEL(frequency); - DEBUGFS_DEL(rts_threshold); - DEBUGFS_DEL(fragmentation_threshold); - DEBUGFS_DEL(short_retry_limit); - DEBUGFS_DEL(long_retry_limit); DEBUGFS_DEL(total_ps_buffered); DEBUGFS_DEL(wep_iv); DEBUGFS_DEL(tsf); DEBUGFS_DEL(reset); + DEBUGFS_DEL(noack); DEBUGFS_STATS_DEL(transmitted_fragment_count); DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h new file mode 100644 index 000000000000..b13446afd48f --- /dev/null +++ b/net/mac80211/driver-ops.h @@ -0,0 +1,191 @@ +#ifndef __MAC80211_DRIVER_OPS +#define __MAC80211_DRIVER_OPS + +#include +#include "ieee80211_i.h" + +static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) +{ + return local->ops->tx(&local->hw, skb); +} + +static inline int drv_start(struct ieee80211_local *local) +{ + return local->ops->start(&local->hw); +} + +static inline void drv_stop(struct ieee80211_local *local) +{ + local->ops->stop(&local->hw); +} + +static inline int drv_add_interface(struct ieee80211_local *local, + struct ieee80211_if_init_conf *conf) +{ + return local->ops->add_interface(&local->hw, conf); +} + +static inline void drv_remove_interface(struct ieee80211_local *local, + struct ieee80211_if_init_conf *conf) +{ + local->ops->remove_interface(&local->hw, conf); +} + +static inline int drv_config(struct ieee80211_local *local, u32 changed) +{ + return local->ops->config(&local->hw, changed); +} + +static inline void drv_bss_info_changed(struct ieee80211_local *local, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + if (local->ops->bss_info_changed) + local->ops->bss_info_changed(&local->hw, vif, info, changed); +} + +static inline void drv_configure_filter(struct ieee80211_local *local, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) +{ + local->ops->configure_filter(&local->hw, changed_flags, total_flags, + mc_count, mc_list); +} + +static inline int drv_set_tim(struct ieee80211_local *local, + struct ieee80211_sta *sta, bool set) +{ + if (local->ops->set_tim) + return local->ops->set_tim(&local->hw, sta, set); + return 0; +} + +static inline int drv_set_key(struct ieee80211_local *local, + enum set_key_cmd cmd, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + return local->ops->set_key(&local->hw, cmd, vif, sta, key); +} + +static inline void drv_update_tkip_key(struct ieee80211_local *local, + struct ieee80211_key_conf *conf, + const u8 *address, u32 iv32, + u16 *phase1key) +{ + if (local->ops->update_tkip_key) + local->ops->update_tkip_key(&local->hw, conf, address, + iv32, phase1key); +} + +static inline int drv_hw_scan(struct ieee80211_local *local, + struct cfg80211_scan_request *req) +{ + return local->ops->hw_scan(&local->hw, req); +} + +static inline void drv_sw_scan_start(struct ieee80211_local *local) +{ + if (local->ops->sw_scan_start) + local->ops->sw_scan_start(&local->hw); +} + +static inline void drv_sw_scan_complete(struct ieee80211_local *local) +{ + if (local->ops->sw_scan_complete) + local->ops->sw_scan_complete(&local->hw); +} + +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); +} + +static inline void drv_get_tkip_seq(struct ieee80211_local *local, + u8 hw_key_idx, u32 *iv32, u16 *iv16) +{ + if (local->ops->get_tkip_seq) + local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); +} + +static inline int drv_set_rts_threshold(struct ieee80211_local *local, + u32 value) +{ + if (local->ops->set_rts_threshold) + return local->ops->set_rts_threshold(&local->hw, value); + return 0; +} + +static inline void drv_sta_notify(struct ieee80211_local *local, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + if (local->ops->sta_notify) + local->ops->sta_notify(&local->hw, vif, cmd, sta); +} + +static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + if (local->ops->conf_tx) + return local->ops->conf_tx(&local->hw, queue, params); + return -EOPNOTSUPP; +} + +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); +} + +static inline u64 drv_get_tsf(struct ieee80211_local *local) +{ + if (local->ops->get_tsf) + return local->ops->get_tsf(&local->hw); + return -1ULL; +} + +static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) +{ + if (local->ops->set_tsf) + local->ops->set_tsf(&local->hw, tsf); +} + +static inline void drv_reset_tsf(struct ieee80211_local *local) +{ + if (local->ops->reset_tsf) + local->ops->reset_tsf(&local->hw); +} + +static inline int drv_tx_last_beacon(struct ieee80211_local *local) +{ + if (local->ops->tx_last_beacon) + return local->ops->tx_last_beacon(&local->hw); + return 1; +} + +static inline int drv_ampdu_action(struct ieee80211_local *local, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, + u16 *ssn) +{ + if (local->ops->ampdu_action) + return local->ops->ampdu_action(&local->hw, action, + sta, tid, ssn); + return -EOPNOTSUPP; +} + + +static inline void drv_rfkill_poll(struct ieee80211_local *local) +{ + if (local->ops->rfkill_poll) + local->ops->rfkill_poll(&local->hw); +} +#endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/event.c b/net/mac80211/event.c index 0d95561c0ee0..f288d01a6344 100644 --- a/net/mac80211/event.c +++ b/net/mac80211/event.c @@ -12,12 +12,12 @@ #include "ieee80211_i.h" /* - * indicate a failed Michael MIC to userspace; the passed packet - * (in the variable hdr) must be long enough to extract the TKIP - * fields like TSC + * Indicate a failed Michael MIC to userspace. If the caller knows the TSC of + * the frame that generated the MIC failure (i.e., if it was provided by the + * 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) + struct ieee80211_hdr *hdr, const u8 *tsc) { union iwreq_data wrqu; char *buf = kmalloc(128, GFP_ATOMIC); @@ -34,8 +34,9 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke kfree(buf); } - /* - * TODO: re-add support for sending MIC failure indication - * with all info via nl80211 - */ + cfg80211_michael_mic_failure(sdata->dev, hdr->addr2, + (hdr->addr1[0] & 0x01) ? + NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE, + keyidx, tsc); } diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 4e3c72f20de7..0891bfb06996 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -14,7 +14,6 @@ */ #include -#include #include #include "ieee80211_i.h" #include "rate.h" @@ -83,89 +82,6 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, ht_cap->mcs.rx_mask[32/8] |= 1; } -/* - * ieee80211_enable_ht should be called only after the operating band - * has been determined as ht configuration depends on the hw's - * HT abilities for a specific band. - */ -u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, - struct ieee80211_ht_info *hti, - 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 ieee80211_bss_ht_conf ht; - struct sta_info *sta; - u32 changed = 0; - bool enable_ht = true, ht_changed; - enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - memset(&ht, 0, sizeof(ht)); - - /* HT is not supported */ - if (!sband->ht_cap.ht_supported) - enable_ht = false; - - /* check that channel matches the right operating channel */ - if (local->hw.conf.channel->center_freq != - ieee80211_channel_to_frequency(hti->control_chan)) - enable_ht = false; - - if (enable_ht) { - channel_type = NL80211_CHAN_HT20; - - if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && - (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { - switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - channel_type = NL80211_CHAN_HT40MINUS; - break; - } - } - } - - ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || - channel_type != local->hw.conf.channel_type; - - local->oper_channel_type = channel_type; - - if (ht_changed) { - /* channel_type change automatically detected */ - ieee80211_hw_config(local, 0); - - rcu_read_lock(); - - sta = sta_info_get(local, ifmgd->bssid); - if (sta) - rate_control_rate_update(local, sband, sta, - IEEE80211_RC_HT_CHANGED); - - rcu_read_unlock(); - - } - - /* disable HT */ - if (!enable_ht) - return 0; - - ht.operation_mode = le16_to_cpu(hti->operation_mode); - - /* if bss configuration changed store the new one */ - if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) { - changed |= BSS_CHANGED_HT; - sdata->vif.bss_conf.ht = ht; - } - - return changed; -} - void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) { int i; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3201e1f96365..0b30277eb366 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -22,6 +22,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #define IEEE80211_SCAN_INTERVAL (2 * HZ) @@ -59,74 +60,65 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.bssid, 0); } -static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, - const u8 *bssid, const int beacon_int, - const int freq, - const size_t supp_rates_len, - const u8 *supp_rates, - const u16 capability, u64 tsf) +static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, + const u8 *bssid, const int beacon_int, + struct ieee80211_channel *chan, + const u32 basic_rates, + const u16 capability, u64 tsf) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; - int res = 0, rates, i, j; + int rates, i; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; struct ieee80211_supported_band *sband; - union iwreq_data wrqu; + u32 bss_change; + u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; - if (local->ops->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->ops->reset_tsf(local_to_hw(local)); - } + /* Reset own TSF to allow time synchronization work. */ + drv_reset_tsf(local); - if ((ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) && - memcmp(ifibss->bssid, bssid, ETH_ALEN) == 0) - return res; + skb = ifibss->skb; + rcu_assign_pointer(ifibss->presp, NULL); + synchronize_rcu(); + skb->data = skb->head; + skb->len = 0; + skb_reset_tail_pointer(skb); + skb_reserve(skb, sdata->local->hw.extra_tx_headroom); - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "response\n", sdata->dev->name); - return -ENOMEM; - } - - if (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) { - /* Remove possible STA entries from other IBSS networks. */ - sta_info_flush_delayed(sdata); - } + if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) + sta_info_flush(sdata->local, sdata); memcpy(ifibss->bssid, bssid, ETH_ALEN); - res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); - if (res) - return res; - local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; + sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - sdata->drop_unencrypted = capability & - WLAN_CAPABILITY_PRIVACY ? 1 : 0; + local->oper_channel = chan; + local->oper_channel_type = NL80211_CHAN_NO_HT; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - res = ieee80211_set_freq(sdata, freq); + sband = local->hw.wiphy->bands[chan->band]; - if (res) - return res; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + /* build supported rates array */ + pos = supp_rates; + for (i = 0; i < sband->n_bitrates; i++) { + int rate = sband->bitrates[i].bitrate; + u8 basic = 0; + if (basic_rates & BIT(i)) + basic = 0x80; + *pos++ = basic | (u8) (rate / 5); + } /* Build IBSS probe response */ - - skb_reserve(skb, local->hw.extra_tx_headroom); - - mgmt = (struct ieee80211_mgmt *) - skb_put(skb, 24 + sizeof(mgmt->u.beacon)); + mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); - mgmt->u.beacon.beacon_int = - cpu_to_le16(local->hw.conf.beacon_int); + mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); mgmt->u.beacon.timestamp = cpu_to_le64(tsf); mgmt->u.beacon.capab_info = cpu_to_le16(capability); @@ -135,7 +127,7 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, *pos++ = ifibss->ssid_len; memcpy(pos, ifibss->ssid, ifibss->ssid_len); - rates = supp_rates_len; + rates = sband->n_bitrates; if (rates > 8) rates = 8; pos = skb_put(skb, 2 + rates); @@ -147,7 +139,7 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, pos = skb_put(skb, 2 + 1); *pos++ = WLAN_EID_DS_PARAMS; *pos++ = 1; - *pos++ = ieee80211_frequency_to_channel(freq); + *pos++ = ieee80211_frequency_to_channel(chan->center_freq); } pos = skb_put(skb, 2 + 2); @@ -157,51 +149,73 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, *pos++ = 0; *pos++ = 0; - if (supp_rates_len > 8) { - rates = supp_rates_len - 8; + if (sband->n_bitrates > 8) { + rates = sband->n_bitrates - 8; pos = skb_put(skb, 2 + rates); *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = rates; memcpy(pos, &supp_rates[8], rates); } - ifibss->probe_resp = skb; + if (ifibss->ie_len) + memcpy(skb_put(skb, ifibss->ie_len), + ifibss->ie, ifibss->ie_len); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED); + rcu_assign_pointer(ifibss->presp, skb); + sdata->vif.bss_conf.beacon_int = beacon_int; + bss_change = BSS_CHANGED_BEACON_INT; + bss_change |= ieee80211_reset_erp_info(sdata); + bss_change |= BSS_CHANGED_BSSID; + bss_change |= BSS_CHANGED_BEACON; + bss_change |= BSS_CHANGED_BEACON_ENABLED; + ieee80211_bss_info_change_notify(sdata, bss_change); - rates = 0; - for (i = 0; i < supp_rates_len; i++) { - int bitrate = (supp_rates[i] & 0x7f) * 5; - for (j = 0; j < sband->n_bitrates; j++) - if (sband->bitrates[j].bitrate == bitrate) - rates |= BIT(j); - } + ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); - ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); - - ifibss->flags |= IEEE80211_IBSS_PREV_BSSID_SET; ifibss->state = IEEE80211_IBSS_MLME_JOINED; - mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + mod_timer(&ifibss->timer, + round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); - wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); - - return res; + cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, + mgmt, skb->len, 0, GFP_KERNEL); + cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); } -static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, - struct ieee80211_bss *bss) +static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss *bss) { - return __ieee80211_sta_join_ibss(sdata, - bss->cbss.bssid, - bss->cbss.beacon_interval, - bss->cbss.channel->center_freq, - bss->supp_rates_len, bss->supp_rates, - bss->cbss.capability, - bss->cbss.tsf); + struct ieee80211_supported_band *sband; + u32 basic_rates; + int i, j; + u16 beacon_int = bss->cbss.beacon_interval; + + if (beacon_int < 10) + beacon_int = 10; + + sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band]; + + basic_rates = 0; + + for (i = 0; i < bss->supp_rates_len; i++) { + int rate = (bss->supp_rates[i] & 0x7f) * 5; + bool is_basic = !!(bss->supp_rates[i] & 0x80); + + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) { + if (is_basic) + basic_rates |= BIT(j); + break; + } + } + } + + __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, + beacon_int, + bss->cbss.channel, + basic_rates, + bss->cbss.capability, + bss->cbss.tsf); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, @@ -277,7 +291,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, goto put_bss; /* we use a fixed BSSID */ - if (sdata->u.ibss.flags & IEEE80211_IBSS_BSSID_SET) + if (sdata->u.ibss.bssid) goto put_bss; /* not an IBSS */ @@ -322,12 +336,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bitrates[rx_status->rate_idx].bitrate; rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); - } else if (local && local->ops && local->ops->get_tsf) - /* second best option: get current TSF */ - rx_timestamp = local->ops->get_tsf(local_to_hw(local)); - else - /* can't merge without knowing the TSF */ - rx_timestamp = -1LLU; + } else { + /* + * second best option: get current TSF + * (will return -1 if not supported) + */ + rx_timestamp = drv_get_tsf(local); + } #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" @@ -369,13 +384,14 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; int band = local->hw.conf.channel->band; - /* TODO: Could consider removing the least recently used entry and - * allow new one to be added. */ + /* + * XXX: Consider removing the least recently used entry and + * allow new one to be added. + */ if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: No room for a new IBSS STA " - "entry %pM\n", sdata->dev->name, addr); - } + if (net_ratelimit()) + printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", + sdata->dev->name, addr); return NULL; } @@ -432,41 +448,33 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + mod_timer(&ifibss->timer, + round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); + if (ieee80211_sta_active_ibss(sdata)) return; - if ((ifibss->flags & IEEE80211_IBSS_BSSID_SET) && - (!(ifibss->flags & IEEE80211_IBSS_AUTO_CHANNEL_SEL))) + if (ifibss->fixed_channel) return; printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->dev->name); - /* XXX maybe racy? */ - if (sdata->local->scan_req) - return; - - memcpy(sdata->local->int_scan_req.ssids[0].ssid, - ifibss->ssid, IEEE80211_MAX_SSID_LEN); - sdata->local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; - ieee80211_request_scan(sdata, &sdata->local->int_scan_req); + ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); } -static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) +static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; - u8 *pos; u8 bssid[ETH_ALEN]; - u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; u16 capability; int i; - if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) { + if (ifibss->fixed_bssid) { memcpy(bssid, ifibss->bssid, ETH_ALEN); } else { /* Generate random, not broadcast, locally administered BSSID. Mix in @@ -482,10 +490,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", sdata->dev->name, bssid); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - if (local->hw.conf.beacon_int == 0) - local->hw.conf.beacon_int = 100; + sband = local->hw.wiphy->bands[ifibss->channel->band]; capability = WLAN_CAPABILITY_IBSS; @@ -494,29 +499,20 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) else sdata->drop_unencrypted = 0; - pos = supp_rates; - for (i = 0; i < sband->n_bitrates; i++) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } - - return __ieee80211_sta_join_ibss(sdata, - bssid, local->hw.conf.beacon_int, - local->hw.conf.channel->center_freq, - sband->n_bitrates, supp_rates, - capability, 0); + __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, + ifibss->channel, 3, /* first two are basic */ + capability, 0); } -static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) +static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; struct ieee80211_bss *bss; + struct ieee80211_channel *chan = NULL; const u8 *bssid = NULL; int active_ibss; - - if (ifibss->ssid_len == 0) - return -EINVAL; + u16 capability; active_ibss = ieee80211_sta_active_ibss(sdata); #ifdef CONFIG_MAC80211_IBSS_DEBUG @@ -525,14 +521,23 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (active_ibss) - return 0; + return; - if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) + capability = WLAN_CAPABILITY_IBSS; + if (sdata->default_key) + capability |= WLAN_CAPABILITY_PRIVACY; + + if (ifibss->fixed_bssid) bssid = ifibss->bssid; - bss = (void *)cfg80211_get_bss(local->hw.wiphy, NULL, bssid, + if (ifibss->fixed_channel) + chan = ifibss->channel; + if (!is_zero_ether_addr(ifibss->bssid)) + bssid = ifibss->bssid; + bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, ifibss->ssid, ifibss->ssid_len, - WLAN_CAPABILITY_IBSS, - WLAN_CAPABILITY_IBSS); + WLAN_CAPABILITY_IBSS | + WLAN_CAPABILITY_PRIVACY, + capability); #ifdef CONFIG_MAC80211_IBSS_DEBUG if (bss) @@ -540,18 +545,14 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) "%pM\n", bss->cbss.bssid, ifibss->bssid); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (bss && - (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) || - memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN))) { - int ret; - + if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) { printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" " based on configured SSID\n", sdata->dev->name, bss->cbss.bssid); - ret = ieee80211_sta_join_ibss(sdata, bss); + ieee80211_sta_join_ibss(sdata, bss); ieee80211_rx_bss_put(local, bss); - return ret; + return; } else if (bss) ieee80211_rx_bss_put(local, bss); @@ -562,29 +563,24 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) /* Selected IBSS not found in current scan results - try to scan */ if (ifibss->state == IEEE80211_IBSS_MLME_JOINED && !ieee80211_sta_active_ibss(sdata)) { - mod_timer(&ifibss->timer, jiffies + - IEEE80211_IBSS_MERGE_INTERVAL); - } else if (time_after(jiffies, local->last_scan_completed + + mod_timer(&ifibss->timer, + round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); + } else if (time_after(jiffies, ifibss->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->dev->name); - /* XXX maybe racy? */ - if (local->scan_req) - return -EBUSY; - - memcpy(local->int_scan_req.ssids[0].ssid, - ifibss->ssid, IEEE80211_MAX_SSID_LEN); - local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; - return ieee80211_request_scan(sdata, &local->int_scan_req); + ieee80211_request_internal_scan(sdata, ifibss->ssid, + ifibss->ssid_len); } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, ifibss->ibss_join_req + IEEE80211_IBSS_JOIN_TIMEOUT)) { - if (!(local->oper_channel->flags & - IEEE80211_CHAN_NO_IBSS)) - return ieee80211_sta_create_ibss(sdata); + if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) { + ieee80211_sta_create_ibss(sdata); + return; + } printk(KERN_DEBUG "%s: IBSS not allowed on" " %d MHz\n", sdata->dev->name, local->hw.conf.channel->center_freq); @@ -595,11 +591,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) } ifibss->state = IEEE80211_IBSS_MLME_SEARCH; - mod_timer(&ifibss->timer, jiffies + interval); - return 0; + mod_timer(&ifibss->timer, + round_jiffies(jiffies + interval)); } - - return 0; } static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, @@ -614,13 +608,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, u8 *pos, *end; if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || - len < 24 + 2 || !ifibss->probe_resp) + len < 24 + 2 || !ifibss->presp) return; - if (local->ops->tx_last_beacon) - tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local)); - else - tx_last_beacon = 1; + tx_last_beacon = drv_tx_last_beacon(local); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" @@ -649,13 +640,13 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, } if (pos[1] != 0 && (pos[1] != ifibss->ssid_len || - memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len) != 0)) { + !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { /* Ignore ProbeReq for foreign SSID */ return; } /* Reply with ProbeResp */ - skb = skb_copy(ifibss->probe_resp, GFP_KERNEL); + skb = skb_copy(ifibss->presp, GFP_KERNEL); if (!skb) return; @@ -746,6 +737,9 @@ static void ieee80211_ibss_work(struct work_struct *work) struct ieee80211_if_ibss *ifibss; struct sk_buff *skb; + if (WARN_ON(local->suspended)) + return; + if (!netif_running(sdata->dev)) return; @@ -782,10 +776,36 @@ static void ieee80211_ibss_timer(unsigned long data) struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; + if (local->quiescing) { + ifibss->timer_running = true; + return; + } + set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); queue_work(local->hw.workqueue, &ifibss->work); } +#ifdef CONFIG_PM +void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + + cancel_work_sync(&ifibss->work); + if (del_timer_sync(&ifibss->timer)) + ifibss->timer_running = true; +} + +void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + + if (ifibss->timer_running) { + add_timer(&ifibss->timer); + ifibss->timer_running = false; + } +} +#endif + void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; @@ -794,89 +814,25 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) setup_timer(&ifibss->timer, ieee80211_ibss_timer, (unsigned long) sdata); skb_queue_head_init(&ifibss->skb_queue); - - ifibss->flags |= IEEE80211_IBSS_AUTO_BSSID_SEL | - IEEE80211_IBSS_AUTO_CHANNEL_SEL; -} - -int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - ifibss->flags &= ~IEEE80211_IBSS_PREV_BSSID_SET; - - if (ifibss->ssid_len) - ifibss->flags |= IEEE80211_IBSS_SSID_SET; - else - ifibss->flags &= ~IEEE80211_IBSS_SSID_SET; - - ifibss->ibss_join_req = jiffies; - ifibss->state = IEEE80211_IBSS_MLME_SEARCH; - set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); - - return 0; -} - -int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - if (len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - - if (ifibss->ssid_len != len || memcmp(ifibss->ssid, ssid, len) != 0) { - memset(ifibss->ssid, 0, sizeof(ifibss->ssid)); - memcpy(ifibss->ssid, ssid, len); - ifibss->ssid_len = len; - } - - return ieee80211_ibss_commit(sdata); -} - -int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - memcpy(ssid, ifibss->ssid, ifibss->ssid_len); - *len = ifibss->ssid_len; - - return 0; -} - -int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - if (is_valid_ether_addr(bssid)) { - memcpy(ifibss->bssid, bssid, ETH_ALEN); - ifibss->flags |= IEEE80211_IBSS_BSSID_SET; - } else { - memset(ifibss->bssid, 0, ETH_ALEN); - ifibss->flags &= ~IEEE80211_IBSS_BSSID_SET; - } - - if (netif_running(sdata->dev)) { - if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", sdata->dev->name); - } - } - - return ieee80211_ibss_commit(sdata); } /* scan finished notification */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) { - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - struct ieee80211_if_ibss *ifibss; + struct ieee80211_sub_if_data *sdata; - if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { - ifibss = &sdata->u.ibss; - if ((!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) || - !ieee80211_sta_active_ibss(sdata)) - ieee80211_sta_find_ibss(sdata); + 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_ADHOC) + continue; + if (!sdata->u.ibss.ssid_len) + continue; + sdata->u.ibss.last_scan_completed = jiffies; + ieee80211_sta_find_ibss(sdata); } + mutex_unlock(&local->iflist_mtx); } ieee80211_rx_result @@ -906,3 +862,86 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_DROP_MONITOR; } + +int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, + struct cfg80211_ibss_params *params) +{ + struct sk_buff *skb; + + if (params->bssid) { + memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); + sdata->u.ibss.fixed_bssid = true; + } else + sdata->u.ibss.fixed_bssid = false; + + sdata->vif.bss_conf.beacon_int = params->beacon_interval; + + sdata->u.ibss.channel = params->channel; + sdata->u.ibss.fixed_channel = params->channel_fixed; + + if (params->ie) { + sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, + GFP_KERNEL); + if (sdata->u.ibss.ie) + sdata->u.ibss.ie_len = params->ie_len; + } + + skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + + 36 /* bitrates */ + + 34 /* SSID */ + + 3 /* DS params */ + + 4 /* IBSS params */ + + params->ie_len); + if (!skb) + return -ENOMEM; + + sdata->u.ibss.skb = skb; + sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; + sdata->u.ibss.ibss_join_req = jiffies; + + memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + + /* + * The ssid_len setting below is used to see whether + * we are active, and we need all other settings + * before that may get visible. + */ + mb(); + + sdata->u.ibss.ssid_len = params->ssid_len; + + 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); + + return 0; +} + +int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) +{ + struct sk_buff *skb; + + del_timer_sync(&sdata->u.ibss.timer); + clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); + cancel_work_sync(&sdata->u.ibss.work); + clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); + + sta_info_flush(sdata->local, sdata); + + /* remove beacon */ + kfree(sdata->u.ibss.ie); + skb = sdata->u.ibss.presp; + rcu_assign_pointer(sdata->u.ibss.presp, NULL); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + synchronize_rcu(); + kfree_skb(skb); + + skb_queue_purge(&sdata->u.ibss.skb_queue); + memset(sdata->u.ibss.bssid, 0, ETH_ALEN); + sdata->u.ibss.ssid_len = 0; + + ieee80211_recalc_idle(sdata->local); + + return 0; +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e6ed78cb16b3..4dbc28964196 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include "key.h" @@ -236,7 +235,7 @@ struct mesh_preq_queue { #define IEEE80211_STA_ASSOCIATED BIT(4) #define IEEE80211_STA_PROBEREQ_POLL BIT(5) #define IEEE80211_STA_CREATE_IBSS BIT(6) -/* hole at 7, please re-use */ +#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) @@ -249,9 +248,8 @@ struct mesh_preq_queue { #define IEEE80211_STA_EXT_SME BIT(17) /* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 -#define IEEE80211_STA_REQ_DIRECT_PROBE 1 -#define IEEE80211_STA_REQ_AUTH 2 -#define IEEE80211_STA_REQ_RUN 3 +#define IEEE80211_STA_REQ_AUTH 1 +#define IEEE80211_STA_REQ_RUN 2 /* bitfield of allowed auth algs */ #define IEEE80211_AUTH_ALG_OPEN BIT(0) @@ -295,6 +293,9 @@ struct ieee80211_if_managed { 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; @@ -306,6 +307,8 @@ struct ieee80211_if_managed { int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ int auth_transaction; + u32 beacon_crc; + enum { IEEE80211_MFP_DISABLED, IEEE80211_MFP_OPTIONAL, @@ -319,14 +322,6 @@ struct ieee80211_if_managed { size_t sme_auth_ie_len; }; -enum ieee80211_ibss_flags { - IEEE80211_IBSS_AUTO_CHANNEL_SEL = BIT(0), - IEEE80211_IBSS_AUTO_BSSID_SEL = BIT(1), - IEEE80211_IBSS_BSSID_SET = BIT(2), - IEEE80211_IBSS_PREV_BSSID_SET = BIT(3), - IEEE80211_IBSS_SSID_SET = BIT(4), -}; - enum ieee80211_ibss_request { IEEE80211_IBSS_REQ_RUN = 0, }; @@ -337,17 +332,23 @@ struct ieee80211_if_ibss { struct sk_buff_head skb_queue; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; + unsigned long request; + unsigned long last_scan_completed; - u32 flags; + bool timer_running; + + bool fixed_bssid; + bool fixed_channel; u8 bssid[ETH_ALEN]; - - unsigned long request; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len, ie_len; + u8 *ie; + struct ieee80211_channel *channel; unsigned long ibss_join_req; - struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ + /* probe response/beacon for IBSS */ + struct sk_buff *presp, *skb; enum { IEEE80211_IBSS_MLME_SEARCH, @@ -361,6 +362,8 @@ struct ieee80211_if_mesh { struct timer_list mesh_path_timer; struct sk_buff_head skb_queue; + unsigned long timers_running; + bool housekeeping; u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; @@ -430,6 +433,12 @@ struct ieee80211_sub_if_data { int drop_unencrypted; + /* + * keep track of whether the HT opmode (stored in + * vif.bss_info.ht_operation_mode) is valid. + */ + bool ht_opmode_valid; + /* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; unsigned int fragment_next; @@ -580,6 +589,7 @@ enum queue_stop_reason { 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 { @@ -606,6 +616,21 @@ struct ieee80211_local { unsigned int filter_flags; /* FIF_* */ struct iw_statistics wstats; bool tim_in_locked_section; /* see ieee80211_beacon_get() */ + + /* + * suspended is true if we finished all the suspend _and_ we have + * not yet come up from resume. This is to be used by mac80211 + * to ensure driver sanity during suspend and mac80211's own + * sanity. It can eventually be used for WoW as well. + */ + bool suspended; + + /* + * quiescing is true during the suspend process _only_ to + * ease timer cancelling etc. + */ + bool quiescing; + int tx_headroom; /* required headroom for hardware/radiotap */ /* Tasklet and skb queue to process calls from IRQ mode. All frames @@ -626,8 +651,6 @@ struct ieee80211_local { spinlock_t sta_lock; unsigned long num_sta; struct list_head sta_list; - struct list_head sta_flush_list; - struct work_struct sta_flush_work; struct sta_info *sta_hash[STA_HASH_SIZE]; struct timer_list sta_cleanup; @@ -647,9 +670,6 @@ struct ieee80211_local { struct rate_control_ref *rate_ctrl; - int rts_threshold; - int fragmentation_threshold; - struct crypto_blkcipher *wep_tx_tfm; struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; @@ -666,15 +686,18 @@ struct ieee80211_local { /* Scanning and BSS list */ + struct mutex scan_mtx; bool sw_scanning, hw_scanning; struct cfg80211_ssid scan_ssid; struct cfg80211_scan_request int_scan_req; struct cfg80211_scan_request *scan_req; struct ieee80211_channel *scan_channel; + const u8 *orig_ies; + int orig_ies_len; int scan_channel_idx; + int scan_ies_len; enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; - unsigned long last_scan_completed; struct delayed_work scan_work; struct ieee80211_sub_if_data *scan_sdata; enum nl80211_channel_type oper_channel_type; @@ -736,28 +759,32 @@ struct ieee80211_local { int wifi_wme_noack_test; unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ - bool powersave; bool pspolling; + /* + * PS can only be enabled when we have exactly one managed + * interface (and monitors) in PS, this then points there. + */ + struct ieee80211_sub_if_data *ps_sdata; struct work_struct dynamic_ps_enable_work; struct work_struct dynamic_ps_disable_work; struct timer_list dynamic_ps_timer; + struct notifier_block network_latency_notifier; int user_power_level; /* in dBm */ int power_constr_level; /* in dBm */ + struct work_struct restart_work; + #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { struct dentry *rcdir; struct dentry *rcname; struct dentry *frequency; - struct dentry *rts_threshold; - struct dentry *fragmentation_threshold; - struct dentry *short_retry_limit; - struct dentry *long_retry_limit; struct dentry *total_ps_buffered; struct dentry *wep_iv; struct dentry *tsf; struct dentry *reset; + struct dentry *noack; struct dentry *statistics; struct local_debugfsdentries_statsdentries { struct dentry *transmitted_fragment_count; @@ -830,7 +857,7 @@ struct ieee802_11_elems { u8 *fh_params; u8 *ds_params; u8 *cf_params; - u8 *tim; + struct ieee80211_tim_ie *tim; u8 *ibss_params; u8 *challenge; u8 *wpa; @@ -903,7 +930,6 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); -int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); @@ -927,12 +953,16 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); void ieee80211_send_pspoll(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); +void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); +int ieee80211_max_network_latency(struct notifier_block *nb, + unsigned long data, void *dummy); +void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel_sw_ie *sw_elem, + struct ieee80211_bss *bss); +void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); +void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); /* IBSS code */ -int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata); -int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); -int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); -int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); ieee80211_rx_result @@ -940,14 +970,22 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); 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, + struct cfg80211_ibss_params *params); +int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); +void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); +void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); +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, @@ -956,9 +994,6 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, const char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); -void ieee80211_scan_failed(struct ieee80211_local *local); -int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, - struct cfg80211_scan_request *req); struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, @@ -983,6 +1018,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype type); void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); +u32 __ieee80211_recalc_idle(struct ieee80211_local *local); +void ieee80211_recalc_idle(struct ieee80211_local *local); /* tx handling */ void ieee80211_clear_tx_pending(struct ieee80211_local *local); @@ -995,9 +1032,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_sta_ht_cap *ht_cap); -u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, - struct ieee80211_ht_info *hti, - u16 ap_ht_cap_flags); void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, @@ -1027,24 +1061,23 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len); -void ieee80211_chswitch_timer(unsigned long data); -void ieee80211_chswitch_work(struct work_struct *work); -void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel_sw_ie *sw_elem, - struct ieee80211_bss *bss); -void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, - u16 capab_info, u8 *pwr_constr_elem, - u8 pwr_constr_elem_len); -/* Suspend/resume */ +/* Suspend/resume and hw reconfiguration */ +int ieee80211_reconfig(struct ieee80211_local *local); + #ifdef CONFIG_PM int __ieee80211_suspend(struct ieee80211_hw *hw); -int __ieee80211_resume(struct ieee80211_hw *hw); + +static inline int __ieee80211_resume(struct ieee80211_hw *hw) +{ + return ieee80211_reconfig(hw_to_local(hw)); +} #else static inline int __ieee80211_suspend(struct ieee80211_hw *hw) { return 0; } + static inline int __ieee80211_resume(struct ieee80211_hw *hw) { return 0; @@ -1053,19 +1086,20 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ -extern const unsigned char rfc1042_header[6]; -extern const unsigned char bridge_tunnel_header[6]; u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum nl80211_iftype type); 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); + struct ieee80211_hdr *hdr, const u8 *tsc); 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); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); +u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, + struct ieee802_11_elems *elems, + u64 filter, u32 crc); int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); u32 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band); @@ -1088,14 +1122,20 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); +void ieee80211_add_pending_skb(struct ieee80211_local *local, + struct sk_buff *skb); +int ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs); 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); +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, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len); + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 91e8e1bacaaa..b7c8a4484298 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -20,6 +20,7 @@ #include "debugfs_netdev.h" #include "mesh.h" #include "led.h" +#include "driver-ops.h" /** * DOC: Interface list locking @@ -164,14 +165,12 @@ static int ieee80211_open(struct net_device *dev) } if (local->open_count == 0) { - res = 0; - if (local->ops->start) - res = local->ops->start(local_to_hw(local)); + res = drv_start(local); if (res) goto err_del_bss; /* we're brought up, everything changes */ hw_reconf_flags = ~0; - ieee80211_led_radio(local, local->hw.conf.radio_enabled); + ieee80211_led_radio(local, true); } /* @@ -199,8 +198,8 @@ static int ieee80211_open(struct net_device *dev) * Validate the MAC address for this device. */ if (!is_valid_ether_addr(dev->dev_addr)) { - if (!local->open_count && local->ops->stop) - local->ops->stop(local_to_hw(local)); + if (!local->open_count) + drv_stop(local); return -EADDRNOTAVAIL; } @@ -235,17 +234,13 @@ static int ieee80211_open(struct net_device *dev) netif_addr_unlock_bh(local->mdev); break; case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - if (sdata->vif.type == NL80211_IFTYPE_STATION) - sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; - else - sdata->u.ibss.flags &= ~IEEE80211_IBSS_PREV_BSSID_SET; + sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; /* fall through */ default: conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = dev->dev_addr; - res = local->ops->add_interface(local_to_hw(local), &conf); + res = drv_add_interface(local, &conf); if (res) goto err_stop; @@ -306,6 +301,8 @@ static int ieee80211_open(struct net_device *dev) if (sdata->flags & IEEE80211_SDATA_PROMISC) atomic_inc(&local->iff_promiscs); + hw_reconf_flags |= __ieee80211_recalc_idle(local); + local->open_count++; if (hw_reconf_flags) { ieee80211_hw_config(local, hw_reconf_flags); @@ -317,6 +314,8 @@ static int ieee80211_open(struct net_device *dev) ieee80211_set_wmm_default(sdata); } + ieee80211_recalc_ps(local, -1); + /* * ieee80211_sta_work is disabled while network interface * is down. Therefore, some configuration changes may not @@ -325,17 +324,15 @@ static int ieee80211_open(struct net_device *dev) */ if (sdata->vif.type == NL80211_IFTYPE_STATION) queue_work(local->hw.workqueue, &sdata->u.mgd.work); - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - queue_work(local->hw.workqueue, &sdata->u.ibss.work); netif_tx_start_all_queues(dev); return 0; err_del_interface: - local->ops->remove_interface(local_to_hw(local), &conf); + drv_remove_interface(local, &conf); err_stop: - if (!local->open_count && local->ops->stop) - local->ops->stop(local_to_hw(local)); + if (!local->open_count) + drv_stop(local); err_del_bss: sdata->bss = NULL; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) @@ -497,7 +494,6 @@ static int ieee80211_stop(struct net_device *dev) /* fall through */ case NL80211_IFTYPE_ADHOC: if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.ibss.timer); cancel_work_sync(&sdata->u.ibss.work); synchronize_rcu(); @@ -549,19 +545,22 @@ static int ieee80211_stop(struct net_device *dev) conf.mac_addr = dev->dev_addr; /* disable all keys for as long as this netdev is down */ ieee80211_disable_keys(sdata); - local->ops->remove_interface(local_to_hw(local), &conf); + drv_remove_interface(local, &conf); } sdata->bss = NULL; + hw_reconf_flags |= __ieee80211_recalc_idle(local); + + ieee80211_recalc_ps(local, -1); + if (local->open_count == 0) { if (netif_running(local->mdev)) dev_close(local->mdev); - if (local->ops->stop) - local->ops->stop(local_to_hw(local)); + drv_stop(local); - ieee80211_led_radio(local, 0); + ieee80211_led_radio(local, false); flush_workqueue(local->hw.workqueue); @@ -649,7 +648,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev) mesh_rmc_free(sdata); break; case NL80211_IFTYPE_ADHOC: - kfree_skb(sdata->u.ibss.probe_resp); + if (WARN_ON(sdata->u.ibss.presp)) + kfree_skb(sdata->u.ibss.presp); break; case NL80211_IFTYPE_STATION: kfree(sdata->u.mgd.extra_ie); @@ -896,3 +896,74 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) unregister_netdevice(sdata->dev); } } + +static u32 ieee80211_idle_off(struct ieee80211_local *local, + const char *reason) +{ + if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) + return 0; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: device no longer idle - %s\n", + wiphy_name(local->hw.wiphy), reason); +#endif + + local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; + return IEEE80211_CONF_CHANGE_IDLE; +} + +static u32 ieee80211_idle_on(struct ieee80211_local *local) +{ + if (local->hw.conf.flags & IEEE80211_CONF_IDLE) + return 0; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: device now idle\n", + wiphy_name(local->hw.wiphy)); +#endif + + local->hw.conf.flags |= IEEE80211_CONF_IDLE; + return IEEE80211_CONF_CHANGE_IDLE; +} + +u32 __ieee80211_recalc_idle(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + int count = 0; + + if (local->hw_scanning || local->sw_scanning) + return ieee80211_idle_off(local, "scanning"); + + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + /* do not count disabled managed interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.state == IEEE80211_STA_MLME_DISABLED) + continue; + /* do not count unused IBSS interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + !sdata->u.ibss.ssid_len) + continue; + /* count everything else */ + count++; + } + + if (!count) + return ieee80211_idle_on(local); + else + return ieee80211_idle_off(local, "in use"); + + return 0; +} + +void ieee80211_recalc_idle(struct ieee80211_local *local) +{ + u32 chg; + + mutex_lock(&local->iflist_mtx); + chg = __ieee80211_recalc_idle(local); + mutex_unlock(&local->iflist_mtx); + if (chg) + ieee80211_hw_config(local, chg); +} diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 687acf23054d..ce267565e180 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -16,6 +16,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "debugfs_key.h" #include "aes_ccm.h" #include "aes_cmac.h" @@ -136,8 +137,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, - &sdata->vif, sta, &key->conf); + ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); if (!ret) { spin_lock(&todo_lock); @@ -179,8 +179,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, - &sdata->vif, sta, &key->conf); + ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, + sta, &key->conf); if (ret) printk(KERN_ERR "mac80211-%s: failed to remove key " @@ -290,9 +290,11 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, int idx, size_t key_len, - const u8 *key_data) + const u8 *key_data, + size_t seq_len, const u8 *seq) { struct ieee80211_key *key; + int i, j; BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); @@ -318,14 +320,31 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, case ALG_TKIP: key->conf.iv_len = TKIP_IV_LEN; key->conf.icv_len = TKIP_ICV_LEN; + if (seq) { + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { + key->u.tkip.rx[i].iv32 = + get_unaligned_le32(&seq[2]); + key->u.tkip.rx[i].iv16 = + get_unaligned_le16(seq); + } + } break; case ALG_CCMP: key->conf.iv_len = CCMP_HDR_LEN; key->conf.icv_len = CCMP_MIC_LEN; + if (seq) { + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) + for (j = 0; j < CCMP_PN_LEN; j++) + key->u.ccmp.rx_pn[i][j] = + seq[CCMP_PN_LEN - j - 1]; + } break; case ALG_AES_CMAC: key->conf.iv_len = 0; key->conf.icv_len = sizeof(struct ieee80211_mmie); + if (seq) + for (j = 0; j < 6; j++) + key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; break; } memcpy(key->conf.key, key_data, key_len); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 215d3ef42a4f..9572e00f532c 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -144,7 +144,8 @@ struct ieee80211_key { struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, int idx, size_t key_len, - const u8 *key_data); + const u8 *key_data, + size_t seq_len, const u8 *seq); /* * Insert a key into data structures (sdata, sta if necessary) * to make it used, free old key. diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 14134193cd17..092a017b237e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -21,10 +21,12 @@ #include #include #include +#include #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "mesh.h" #include "wep.h" @@ -80,10 +82,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local) /* be a bit nasty */ new_flags |= (1<<31); - local->ops->configure_filter(local_to_hw(local), - changed_flags, &new_flags, - local->mdev->mc_count, - local->mdev->mc_list); + drv_configure_filter(local, changed_flags, &new_flags, + local->mdev->mc_count, + local->mdev->mc_list); WARN_ON(new_flags & (1<<31)); @@ -151,93 +152,19 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev) ieee80211_configure_filter(local); } -/* everything else */ - -int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_conf conf; - - if (WARN_ON(!netif_running(sdata->dev))) - return 0; - - memset(&conf, 0, sizeof(conf)); - - if (sdata->vif.type == NL80211_IFTYPE_STATION) - conf.bssid = sdata->u.mgd.bssid; - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - conf.bssid = sdata->u.ibss.bssid; - else if (sdata->vif.type == NL80211_IFTYPE_AP) - conf.bssid = sdata->dev->dev_addr; - else if (ieee80211_vif_is_mesh(&sdata->vif)) { - static const u8 zero[ETH_ALEN] = { 0 }; - conf.bssid = zero; - } else { - WARN_ON(1); - return -EINVAL; - } - - if (!local->ops->config_interface) - return 0; - - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - break; - default: - /* do not warn to simplify caller in scan.c */ - changed &= ~IEEE80211_IFCC_BEACON_ENABLED; - if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) - return -EINVAL; - changed &= ~IEEE80211_IFCC_BEACON; - break; - } - - if (changed & IEEE80211_IFCC_BEACON_ENABLED) { - if (local->sw_scanning) { - conf.enable_beacon = false; - } else { - /* - * Beacon should be enabled, but AP mode must - * check whether there is a beacon configured. - */ - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: - conf.enable_beacon = - !!rcu_dereference(sdata->u.ap.beacon); - break; - case NL80211_IFTYPE_ADHOC: - conf.enable_beacon = !!sdata->u.ibss.probe_resp; - break; - case NL80211_IFTYPE_MESH_POINT: - conf.enable_beacon = true; - break; - default: - /* not reached */ - WARN_ON(1); - break; - } - } - } - - conf.changed = changed; - - return local->ops->config_interface(local_to_hw(local), - &sdata->vif, &conf); -} - int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) { - struct ieee80211_channel *chan; + struct ieee80211_channel *chan, *scan_chan; int ret = 0; int power; enum nl80211_channel_type channel_type; might_sleep(); - if (local->sw_scanning) { - chan = local->scan_channel; + scan_chan = local->scan_channel; + + if (scan_chan) { + chan = scan_chan; channel_type = NL80211_CHAN_NO_HT; } else { chan = local->oper_channel; @@ -251,7 +178,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) changed |= IEEE80211_CONF_CHANGE_CHANNEL; } - if (local->sw_scanning) + if (scan_chan) power = chan->max_power; else power = local->power_constr_level ? @@ -267,7 +194,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) } if (changed && local->open_count) { - ret = local->ops->config(local_to_hw(local), changed); + ret = drv_config(local, changed); /* * Goal: * HW reconfiguration should never fail, the driver has told @@ -292,18 +219,78 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed) { struct ieee80211_local *local = sdata->local; - - if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) - return; + static const u8 zero[ETH_ALEN] = { 0 }; if (!changed) return; - if (local->ops->bss_info_changed) - local->ops->bss_info_changed(local_to_hw(local), - &sdata->vif, - &sdata->vif.bss_conf, - changed); + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + /* + * While not associated, claim a BSSID of all-zeroes + * so that drivers don't do any weird things with the + * BSSID at that time. + */ + if (sdata->vif.bss_conf.assoc) + sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; + else + sdata->vif.bss_conf.bssid = zero; + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; + else if (sdata->vif.type == NL80211_IFTYPE_AP) + sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; + else if (ieee80211_vif_is_mesh(&sdata->vif)) { + sdata->vif.bss_conf.bssid = zero; + } else { + WARN_ON(1); + return; + } + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + break; + default: + /* do not warn to simplify caller in scan.c */ + changed &= ~BSS_CHANGED_BEACON_ENABLED; + if (WARN_ON(changed & BSS_CHANGED_BEACON)) + return; + break; + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (local->sw_scanning) { + sdata->vif.bss_conf.enable_beacon = false; + } else { + /* + * Beacon should be enabled, but AP mode must + * check whether there is a beacon configured. + */ + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + sdata->vif.bss_conf.enable_beacon = + !!rcu_dereference(sdata->u.ap.beacon); + break; + case NL80211_IFTYPE_ADHOC: + sdata->vif.bss_conf.enable_beacon = + !!rcu_dereference(sdata->u.ibss.presp); + break; + case NL80211_IFTYPE_MESH_POINT: + sdata->vif.bss_conf.enable_beacon = true; + break; + default: + /* not reached */ + WARN_ON(1); + break; + } + } + } + + drv_bss_info_changed(local, &sdata->vif, + &sdata->vif.bss_conf, changed); + + /* DEPRECATED */ + local->hw.conf.beacon_int = sdata->vif.bss_conf.beacon_int; } u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) @@ -382,60 +369,12 @@ static void ieee80211_tasklet_handler(unsigned long data) } } -/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to - * make a prepared TX frame (one that has been given to hw) to look like brand - * new IEEE 802.11 frame that is ready to go through TX processing again. - */ -static void ieee80211_remove_tx_extra(struct ieee80211_local *local, - struct ieee80211_key *key, - struct sk_buff *skb) -{ - unsigned int hdrlen, iv_len, mic_len; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - - if (!key) - goto no_key; - - switch (key->conf.alg) { - case ALG_WEP: - iv_len = WEP_IV_LEN; - mic_len = WEP_ICV_LEN; - break; - case ALG_TKIP: - iv_len = TKIP_IV_LEN; - mic_len = TKIP_ICV_LEN; - break; - case ALG_CCMP: - iv_len = CCMP_HDR_LEN; - mic_len = CCMP_MIC_LEN; - break; - default: - goto no_key; - } - - if (skb->len >= hdrlen + mic_len && - !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) - skb_trim(skb, skb->len - mic_len); - if (skb->len >= hdrlen + iv_len) { - memmove(skb->data + iv_len, skb->data, hdrlen); - hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); - } - -no_key: - if (ieee80211_is_data_qos(hdr->frame_control)) { - hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); - memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, - hdrlen - IEEE80211_QOS_CTL_LEN); - skb_pull(skb, IEEE80211_QOS_CTL_LEN); - } -} - static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, struct sta_info *sta, struct sk_buff *skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + sta->tx_filtered_count++; /* @@ -477,16 +416,15 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, */ if (test_sta_flags(sta, WLAN_STA_PS) && skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { - ieee80211_remove_tx_extra(local, sta->key, skb); skb_queue_tail(&sta->tx_filtered, skb); return; } - if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) { + if (!test_sta_flags(sta, WLAN_STA_PS) && + !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { /* Software retry the packet once */ - skb->requeue = 1; - ieee80211_remove_tx_extra(local, sta->key, skb); - dev_queue_xmit(skb); + info->flags |= IEEE80211_TX_INTFL_RETRIED; + ieee80211_add_pending_skb(local, skb); return; } @@ -696,6 +634,28 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) } EXPORT_SYMBOL(ieee80211_tx_status); +static void ieee80211_restart_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, restart_work); + + rtnl_lock(); + ieee80211_reconfig(local); + rtnl_unlock(); +} + +void ieee80211_restart_hw(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + /* use this reason, __ieee80211_resume will unblock it */ + ieee80211_stop_queues_by_reason(hw, + IEEE80211_QUEUE_STOP_REASON_SUSPEND); + + schedule_work(&local->restart_work); +} +EXPORT_SYMBOL(ieee80211_restart_hw); + struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops) { @@ -718,9 +678,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, * +-------------------------+ * */ - priv_size = ((sizeof(struct ieee80211_local) + - NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) + - priv_data_len; + priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; wiphy = wiphy_new(&mac80211_config_ops, priv_size); @@ -728,17 +686,16 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, return NULL; wiphy->privid = mac80211_wiphy_privid; - wiphy->max_scan_ssids = 4; + /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - sizeof(struct cfg80211_bss); local = wiphy_priv(wiphy); + local->hw.wiphy = wiphy; - local->hw.priv = (char *)local + - ((sizeof(struct ieee80211_local) + - NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); + local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); BUG_ON(!ops->tx); BUG_ON(!ops->start); @@ -752,15 +709,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, /* set up some defaults */ local->hw.queues = 1; local->hw.max_rates = 1; - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - local->hw.conf.long_frame_max_tx_count = 4; - local->hw.conf.short_frame_max_tx_count = 7; + local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; + local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; local->hw.conf.radio_enabled = true; local->user_power_level = -1; INIT_LIST_HEAD(&local->interfaces); mutex_init(&local->iflist_mtx); + mutex_init(&local->scan_mtx); spin_lock_init(&local->key_lock); @@ -768,6 +724,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); + INIT_WORK(&local->restart_work, ieee80211_restart_work); + INIT_WORK(&local->dynamic_ps_enable_work, ieee80211_dynamic_ps_enable_work); INIT_WORK(&local->dynamic_ps_disable_work, @@ -821,7 +779,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) enum ieee80211_band band; struct net_device *mdev; struct ieee80211_master_priv *mpriv; - int channels, i, j; + int channels, i, j, max_bitrates; + bool supp_ht; + static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC + }; /* * generic code guarantees at least one band, @@ -829,18 +797,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) * that hw.conf.channel is assigned */ channels = 0; + max_bitrates = 0; + supp_ht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; - if (sband && !local->oper_channel) { + if (!sband) + continue; + if (!local->oper_channel) { /* init channel we're on */ local->hw.conf.channel = - local->oper_channel = - local->scan_channel = &sband->channels[0]; + local->oper_channel = &sband->channels[0]; + local->hw.conf.channel_type = NL80211_CHAN_NO_HT; } - if (sband) - channels += sband->n_channels; + channels += sband->n_channels; + + if (max_bitrates < sband->n_bitrates) + max_bitrates = sband->n_bitrates; + supp_ht = supp_ht || sband->ht_cap.ht_supported; } local->int_scan_req.n_channels = channels; @@ -860,6 +835,37 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; + /* + * Calculate scan IE length -- we need this to alloc + * memory and to subtract from the driver limit. It + * includes the (extended) supported rates and HT + * information -- SSID is the driver's responsibility. + */ + local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ + if (supp_ht) + local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); + + if (!local->ops->hw_scan) { + /* For hw_scan, driver needs to set these up. */ + local->hw.wiphy->max_scan_ssids = 4; + local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + } + + /* + * If the driver supports any scan IEs, then assume the + * limit includes the IEs mac80211 will add, otherwise + * leave it at zero and let the driver sort it out; we + * still pass our IEs to the driver but userspace will + * not be allowed to in that case. + */ + if (local->hw.wiphy->max_scan_ie_len) + local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; + + local->hw.wiphy->cipher_suites = cipher_suites; + local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) + local->hw.wiphy->n_cipher_suites--; + result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; @@ -898,9 +904,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) debugfs_hw_add(local); - if (local->hw.conf.beacon_int < 10) - local->hw.conf.beacon_int = 100; - if (local->hw.max_listen_interval == 0) local->hw.max_listen_interval = 1; @@ -965,25 +968,38 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } } + local->network_latency_notifier.notifier_call = + ieee80211_max_network_latency; + result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); + + if (result) { + rtnl_lock(); + goto fail_pm_qos; + } + return 0; -fail_rate: + fail_pm_qos: + ieee80211_led_exit(local); + ieee80211_remove_interfaces(local); + fail_rate: unregister_netdevice(local->mdev); local->mdev = NULL; -fail_dev: + fail_dev: rtnl_unlock(); ieee80211_wep_free(local); -fail_wep: + fail_wep: sta_info_stop(local); -fail_sta_info: + fail_sta_info: debugfs_hw_del(local); destroy_workqueue(local->hw.workqueue); -fail_workqueue: + fail_workqueue: if (local->mdev) free_netdev(local->mdev); -fail_mdev_alloc: + fail_mdev_alloc: wiphy_unregister(local->hw.wiphy); -fail_wiphy_register: + fail_wiphy_register: kfree(local->int_scan_req.channels); return result; } @@ -996,6 +1012,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); + pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); + rtnl_lock(); /* @@ -1038,6 +1057,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); mutex_destroy(&local->iflist_mtx); + mutex_destroy(&local->scan_mtx); wiphy_free(local->hw.wiphy); } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9a3e5de0410a..fc712e60705d 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -21,6 +21,9 @@ #define CAPAB_OFFSET 17 #define ACCEPT_PLINKS 0x80 +#define TMR_RUNNING_HK 0 +#define TMR_RUNNING_MP 1 + int mesh_allocated; static struct kmem_cache *rm_cache; @@ -45,6 +48,12 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; ifmsh->housekeeping = true; + + if (local->quiescing) { + set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); + return; + } + queue_work(local->hw.workqueue, &ifmsh->work); } @@ -343,6 +352,11 @@ static void ieee80211_mesh_path_timer(unsigned long data) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; + if (local->quiescing) { + set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); + return; + } + queue_work(local->hw.workqueue, &ifmsh->work); } @@ -417,13 +431,39 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.mesh.accepting_plinks) - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); ifmsh->housekeeping = false; mod_timer(&ifmsh->housekeeping_timer, round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); } +#ifdef CONFIG_PM +void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + /* might restart the timer but that doesn't matter */ + cancel_work_sync(&ifmsh->work); + + /* use atomic bitops in case both timers fire at the same time */ + + if (del_timer_sync(&ifmsh->housekeeping_timer)) + set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); + if (del_timer_sync(&ifmsh->mesh_path_timer)) + set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); +} + +void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) + add_timer(&ifmsh->housekeeping_timer); + if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) + add_timer(&ifmsh->mesh_path_timer); +} +#endif void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) { @@ -432,8 +472,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ifmsh->housekeeping = true; queue_work(local->hw.workqueue, &ifmsh->work); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED); } void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index d891d7ddccd7..c7d72819cdd2 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -191,12 +191,8 @@ struct mesh_rmc { #define PLINK_CATEGORY 30 #define MESH_PATH_SEL_CATEGORY 32 -/* Mesh Header Flags */ -#define IEEE80211S_FLAGS_AE 0x3 - /* Public interfaces */ /* Various */ -int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, struct ieee80211_sub_if_data *sdata); int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, @@ -267,6 +263,8 @@ void mesh_path_timer(unsigned long data); void mesh_path_flush_by_nexthop(struct sta_info *sta); void mesh_path_discard_frame(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); +void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); +void mesh_path_restart(struct ieee80211_sub_if_data *sdata); #ifdef CONFIG_MAC80211_MESH extern int mesh_allocated; @@ -294,10 +292,20 @@ static inline void mesh_path_activate(struct mesh_path *mpath) void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); +void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); +void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); +void mesh_plink_quiesce(struct sta_info *sta); +void mesh_plink_restart(struct sta_info *sta); #else #define mesh_allocated 0 static inline void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} +static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) +{} +static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) +{} +static inline void mesh_plink_quiesce(struct sta_info *sta) {} +static inline void mesh_plink_restart(struct sta_info *sta) {} #endif #endif /* IEEE80211S_H */ diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 60b35accda91..003cb470ac84 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -836,8 +836,14 @@ void mesh_path_timer(unsigned long data) mpath = rcu_dereference(mpath); if (!mpath) goto endmpathtimer; - spin_lock_bh(&mpath->state_lock); sdata = mpath->sdata; + + if (sdata->local->quiescing) { + rcu_read_unlock(); + return; + } + + spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_RESOLVED || (!(mpath->flags & MESH_PATH_RESOLVING))) mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index a8bbdeca013a..cb14253587f1 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -266,6 +266,11 @@ static void mesh_plink_timer(unsigned long data) */ sta = (struct sta_info *) data; + if (sta->sdata->local->quiescing) { + sta->plink_timer_was_running = true; + return; + } + spin_lock_bh(&sta->lock); if (sta->ignore_plink_timer) { sta->ignore_plink_timer = false; @@ -322,6 +327,22 @@ static void mesh_plink_timer(unsigned long data) } } +#ifdef CONFIG_PM +void mesh_plink_quiesce(struct sta_info *sta) +{ + if (del_timer_sync(&sta->plink_timer)) + sta->plink_timer_was_running = true; +} + +void mesh_plink_restart(struct sta_info *sta) +{ + if (sta->plink_timer_was_running) { + add_timer(&sta->plink_timer); + sta->plink_timer_was_running = false; + } +} +#endif + static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) { sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 132938b073dc..d779c57a8220 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -17,10 +17,13 @@ #include #include #include +#include +#include #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "led.h" @@ -30,9 +33,13 @@ #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 TMR_RUNNING_TIMER 0 +#define TMR_RUNNING_CHANSW 1 + /* utils */ static int ecw2cw(int ecw) { @@ -80,6 +87,92 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss, return count; } +/* + * ieee80211_enable_ht should be called only after the operating band + * has been determined as ht configuration depends on the hw's + * HT abilities for a specific band. + */ +static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, + struct ieee80211_ht_info *hti, + 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; + bool enable_ht = true, ht_changed; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + /* HT is not supported */ + if (!sband->ht_cap.ht_supported) + enable_ht = false; + + /* check that channel matches the right operating channel */ + if (local->hw.conf.channel->center_freq != + ieee80211_channel_to_frequency(hti->control_chan)) + enable_ht = false; + + if (enable_ht) { + channel_type = NL80211_CHAN_HT20; + + if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && + (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && + (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { + switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (!(local->hw.conf.channel->flags & + IEEE80211_CHAN_NO_HT40PLUS)) + channel_type = NL80211_CHAN_HT40PLUS; + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (!(local->hw.conf.channel->flags & + IEEE80211_CHAN_NO_HT40MINUS)) + channel_type = NL80211_CHAN_HT40MINUS; + break; + } + } + } + + ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || + channel_type != local->hw.conf.channel_type; + + local->oper_channel_type = channel_type; + + if (ht_changed) { + /* channel_type change automatically detected */ + ieee80211_hw_config(local, 0); + + rcu_read_lock(); + + sta = sta_info_get(local, ifmgd->bssid); + if (sta) + rate_control_rate_update(local, sband, sta, + IEEE80211_RC_HT_CHANGED); + + rcu_read_unlock(); + } + + /* disable HT */ + if (!enable_ht) + return 0; + + ht_opmode = le16_to_cpu(hti->operation_mode); + + /* if bss configuration changed store the new one */ + if (!sdata->ht_opmode_valid || + sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { + changed |= BSS_CHANGED_HT; + sdata->vif.bss_conf.ht_operation_mode = ht_opmode; + sdata->ht_opmode_valid = true; + } + + return changed; +} + /* frame sending functions */ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) @@ -263,13 +356,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { + if (flags & IEEE80211_CHAN_NO_HT40PLUS) { cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; cap &= ~IEEE80211_HT_CAP_SGI_40; } break; case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { + if (flags & IEEE80211_CHAN_NO_HT40MINUS) { cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; cap &= ~IEEE80211_HT_CAP_SGI_40; } @@ -325,6 +418,10 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* 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); + else + cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len); ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED); } @@ -359,6 +456,277 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, ieee80211_tx_skb(sdata, skb, 0); } +void ieee80211_send_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + int powersave) +{ + struct sk_buff *skb; + struct ieee80211_hdr *nullfunc; + __le16 fc; + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + return; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); + memset(nullfunc, 0, 24); + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS); + if (powersave) + fc |= cpu_to_le16(IEEE80211_FCTL_PM); + nullfunc->frame_control = fc; + memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); + memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); + memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); + + ieee80211_tx_skb(sdata, skb, 0); +} + +/* spectrum management related things */ +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; + + sdata->local->oper_channel = sdata->local->csa_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; + + 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); +} + +static void ieee80211_chswitch_timer(unsigned long data) +{ + struct ieee80211_sub_if_data *sdata = + (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + if (sdata->local->quiescing) { + set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); + return; + } + + queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); +} + +void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel_sw_ie *sw_elem, + struct ieee80211_bss *bss) +{ + struct ieee80211_channel *new_ch; + 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) + return; + + if (sdata->local->sw_scanning || sdata->local->hw_scanning) + return; + + /* Disregard subsequent beacons if we are already running a timer + processing a CSA */ + + if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) + return; + + new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); + if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) + return; + + sdata->local->csa_channel = new_ch; + + if (sw_elem->count <= 1) { + queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); + } else { + ieee80211_stop_queues_by_reason(&sdata->local->hw, + IEEE80211_QUEUE_STOP_REASON_CSA); + ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; + mod_timer(&ifmgd->chswitch_timer, + jiffies + + msecs_to_jiffies(sw_elem->count * + bss->cbss.beacon_interval)); + } +} + +static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, + u16 capab_info, u8 *pwr_constr_elem, + u8 pwr_constr_elem_len) +{ + struct ieee80211_conf *conf = &sdata->local->hw.conf; + + if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) + return; + + /* Power constraint IE length should be 1 octet */ + if (pwr_constr_elem_len != 1) + return; + + if ((*pwr_constr_elem <= conf->channel->max_power) && + (*pwr_constr_elem != sdata->local->power_constr_level)) { + sdata->local->power_constr_level = *pwr_constr_elem; + ieee80211_hw_config(sdata->local, 0); + } +} + +/* powersave */ +static void ieee80211_enable_ps(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_conf *conf = &local->hw.conf; + + /* + * If we are scanning right now then the parameters will + * take effect when scan finishes. + */ + if (local->hw_scanning || local->sw_scanning) + return; + + if (conf->dynamic_ps_timeout > 0 && + !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(conf->dynamic_ps_timeout)); + } else { + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + ieee80211_send_nullfunc(local, sdata, 1); + conf->flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } +} + +static void ieee80211_change_ps(struct ieee80211_local *local) +{ + struct ieee80211_conf *conf = &local->hw.conf; + + if (local->ps_sdata) { + ieee80211_enable_ps(local, local->ps_sdata); + } else if (conf->flags & IEEE80211_CONF_PS) { + conf->flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); + } +} + +/* need to hold RTNL or interface lock */ +void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) +{ + struct ieee80211_sub_if_data *sdata, *found = NULL; + int count = 0; + + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { + local->ps_sdata = NULL; + return; + } + + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + if (sdata->vif.type != NL80211_IFTYPE_STATION) + continue; + found = sdata; + count++; + } + + if (count == 1 && found->u.mgd.powersave && + (found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) && + !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) { + s32 beaconint_us; + + if (latency < 0) + latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY); + + beaconint_us = ieee80211_tu_to_usec( + found->vif.bss_conf.beacon_int); + + if (beaconint_us > latency) { + local->ps_sdata = NULL; + } else { + u8 dtimper = found->vif.bss_conf.dtim_period; + int maxslp = 1; + + if (dtimper > 1) + maxslp = min_t(int, dtimper, + latency / beaconint_us); + + local->hw.conf.max_sleep_period = maxslp; + local->ps_sdata = found; + } + } else { + local->ps_sdata = NULL; + } + + ieee80211_change_ps(local); +} + +void ieee80211_dynamic_ps_disable_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + dynamic_ps_disable_work); + + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + + ieee80211_wake_queues_by_reason(&local->hw, + IEEE80211_QUEUE_STOP_REASON_PS); +} + +void ieee80211_dynamic_ps_enable_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + dynamic_ps_enable_work); + struct ieee80211_sub_if_data *sdata = local->ps_sdata; + + /* can only happen when PS was just disabled anyway */ + if (!sdata) + return; + + if (local->hw.conf.flags & IEEE80211_CONF_PS) + return; + + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + ieee80211_send_nullfunc(local, sdata, 1); + + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); +} + +void ieee80211_dynamic_ps_timer(unsigned long data) +{ + struct ieee80211_local *local = (void *) data; + + if (local->quiescing) + return; + + queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); +} + /* MLME */ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, struct ieee80211_if_managed *ifmgd, @@ -424,41 +792,16 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " "cWmin=%d cWmax=%d txop=%d\n", - local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, - params.cw_max, params.txop); + wiphy_name(local->hw.wiphy), queue, aci, acm, + params.aifs, params.cw_min, params.cw_max, params.txop); #endif - if (local->ops->conf_tx && - local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { + if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", local->mdev->name, queue); - } + "parameters for queue %d\n", + wiphy_name(local->hw.wiphy), queue); } } -static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid) -{ - u8 mask; - u8 index, indexn1, indexn2; - struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim; - - if (unlikely(!tim || elems->tim_len < 4)) - return false; - - aid &= 0x3fff; - index = aid / 8; - mask = 1 << (aid & 7); - - indexn1 = tim->bitmap_ctrl & 0xfe; - indexn2 = elems->tim_len + indexn1 - 4; - - if (index < indexn1 || index > indexn2) - return false; - - index -= indexn1; - - return !!(tim->virtual_map[index] & mask); -} - static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, u16 capab, bool erp_valid, u8 erp) { @@ -610,6 +953,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 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); @@ -632,20 +976,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, * changed or not. */ bss_info_changed |= BSS_CHANGED_BASIC_RATES; + + /* And the BSSID changed - we're associated now */ + bss_info_changed |= BSS_CHANGED_BSSID; + ieee80211_bss_info_change_notify(sdata, bss_info_changed); - if (local->powersave) { - if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) && - local->hw.conf.dynamic_ps_timeout > 0) { - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies( - local->hw.conf.dynamic_ps_timeout)); - } else { - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - ieee80211_send_nullfunc(local, sdata, 1); - conf->flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } + /* will be same as sdata */ + if (local->ps_sdata) { + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, -1); + mutex_unlock(&local->iflist_mtx); } netif_tx_start_all_queues(sdata->dev); @@ -664,7 +1005,8 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_sta_send_apinfo(sdata); + ieee80211_recalc_idle(local); + cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); /* * Most likely AP is not in the range so remove the @@ -689,8 +1031,6 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; - set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifmgd->request); - /* Direct probe is sent to broadcast address as some APs * will not answer to direct packet in unassociated state. */ @@ -714,7 +1054,8 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) " timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_sta_send_apinfo(sdata); + 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); @@ -817,9 +1158,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); + ieee80211_set_wmm_default(sdata); + + ieee80211_recalc_idle(local); + /* channel(_type) changes are handled by ieee80211_hw_config */ local->oper_channel_type = NL80211_CHAN_NO_HT; + /* on the next assoc, re-program HT parameters */ + sdata->ht_opmode_valid = false; + local->power_constr_level = 0; del_timer_sync(&local->dynamic_ps_timer); @@ -831,6 +1179,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, } ieee80211_hw_config(local, config_changed); + + /* And the BSSID changed -- not very interesting here */ + changed |= BSS_CHANGED_BSSID; ieee80211_bss_info_change_notify(sdata, changed); rcu_read_lock(); @@ -897,7 +1248,8 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) " timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_sta_send_apinfo(sdata); + 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); @@ -917,6 +1269,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *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; } @@ -948,6 +1301,17 @@ void ieee80211_beacon_loss_work(struct work_struct *work) 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! + */ + if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) + return; + #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) { printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " @@ -957,10 +1321,15 @@ void ieee80211_beacon_loss_work(struct work_struct *work) #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_MONITORING_INTERVAL); + mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); } void ieee80211_beacon_loss(struct ieee80211_vif *vif) @@ -977,6 +1346,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) 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; /* TODO: start monitoring current AP signal quality and number of @@ -993,17 +1363,21 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n", sdata->dev->name, ifmgd->bssid); disassoc = true; - goto unlock; + rcu_read_unlock(); + goto out; } + last_rx = sta->last_rx; + rcu_read_unlock(); + if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) && - time_after(jiffies, sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { + 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 unlock; + goto out; } /* @@ -1022,27 +1396,31 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) } #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); - goto unlock; - + mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); + goto out; } - if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) { + 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); } - unlock: - rcu_read_unlock(); - - if (disassoc) + out: + if (!disassoc) + mod_timer(&ifmgd->timer, + jiffies + IEEE80211_MONITORING_INTERVAL); + else ieee80211_set_disassoc(sdata, true, true, WLAN_REASON_PREV_AUTH_NOT_VALID); - else - mod_timer(&ifmgd->timer, jiffies + - IEEE80211_MONITORING_INTERVAL); } @@ -1055,6 +1433,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata) 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); } @@ -1187,7 +1566,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, true, false, 0); ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED; - cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len); + cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len); } @@ -1218,7 +1597,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, } ieee80211_set_disassoc(sdata, false, false, reason_code); - cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len); + cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len); } @@ -1287,6 +1666,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * 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; } @@ -1340,8 +1725,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * 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 | - WLAN_STA_AUTHORIZED); + 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); rates = 0; basic_rates = 0; @@ -1421,6 +1807,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (elems.wmm_param) ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, elems.wmm_param_len); + else + ieee80211_set_wmm_default(sdata); if (elems.ht_info_elem && elems.wmm_param && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && @@ -1476,7 +1864,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) { struct ieee80211_channel_sw_ie *sw_elem = (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; - ieee80211_process_chanswitch(sdata, sw_elem, bss); + ieee80211_sta_process_chanswitch(sdata, sw_elem, bss); } ieee80211_rx_bss_put(local, bss); @@ -1507,57 +1895,98 @@ 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 (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, - &ifmgd->request)) { + if (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE) { printk(KERN_DEBUG "%s direct probe responded\n", sdata->dev->name); ieee80211_authenticate(sdata); } - if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) + if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; + mutex_lock(&sdata->local->iflist_mtx); + ieee80211_recalc_ps(sdata->local, -1); + mutex_unlock(&sdata->local->iflist_mtx); + } } +/* + * This is the canonical list of information elements we care about, + * the filter code also gives us all changes to the Microsoft OUI + * (00:50:F2) vendor IE which is used for WMM which we need to track. + * + * We implement beacon filtering in software since that means we can + * avoid processing the frame here and in cfg80211, and userspace + * will not be able to tell whether the hardware supports it or not. + * + * XXX: This list needs to be dynamic -- userspace needs to be able to + * add items it requires. It also needs to be able to tell us to + * look out for other vendor IEs. + */ +static const u64 care_about_ies = + (1ULL << WLAN_EID_COUNTRY) | + (1ULL << WLAN_EID_ERP_INFO) | + (1ULL << WLAN_EID_CHANNEL_SWITCH) | + (1ULL << WLAN_EID_PWR_CONSTRAINT) | + (1ULL << WLAN_EID_HT_CAPABILITY) | + (1ULL << WLAN_EID_HT_INFORMATION); + static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_if_managed *ifmgd; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; size_t baselen; struct ieee802_11_elems elems; struct ieee80211_local *local = sdata->local; u32 changed = 0; - bool erp_valid, directed_tim; + bool erp_valid, directed_tim = false; u8 erp_value = 0; + u32 ncrc; /* Process beacon from the current BSS */ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; if (baselen > len) return; - ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); - - if (sdata->vif.type != NL80211_IFTYPE_STATION) + if (rx_status->freq != local->hw.conf.channel->center_freq) return; - ifmgd = &sdata->u.mgd; - if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED) || memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - if (rx_status->freq != local->hw.conf.channel->center_freq) - return; + if (ifmgd->flags & IEEE80211_STA_PROBEREQ_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; + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, -1); + mutex_unlock(&local->iflist_mtx); + } - ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, - elems.wmm_param_len); + ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); + ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, + len - baselen, &elems, + care_about_ies, ncrc); + + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, + ifmgd->aid); + + if (ncrc != ifmgd->beacon_crc) { + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, + true); + + ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, + elems.wmm_param_len); + } if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { - directed_tim = ieee80211_check_tim(&elems, ifmgd->aid); - if (directed_tim) { if (local->hw.conf.dynamic_ps_timeout > 0) { local->hw.conf.flags &= ~IEEE80211_CONF_PS; @@ -1580,6 +2009,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, } } + if (ncrc == ifmgd->beacon_crc) + return; + ifmgd->beacon_crc = ncrc; + if (elems.erp_info && elems.erp_info_len >= 1) { erp_valid = true; erp_value = elems.erp_info[0]; @@ -1714,6 +2147,11 @@ static void ieee80211_sta_timer(unsigned long data) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; + if (local->quiescing) { + set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); + return; + } + set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); queue_work(local->hw.workqueue, &ifmgd->work); } @@ -1723,10 +2161,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - if (local->ops->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->ops->reset_tsf(local_to_hw(local)); - } + /* Reset own TSF to allow time synchronization work. */ + drv_reset_tsf(local); ifmgd->wmm_last_param_set = -1; /* allow any WMM update */ @@ -1814,25 +2250,18 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) return 0; } else { if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { - ifmgd->assoc_scan_tries++; - /* XXX maybe racy? */ - if (local->scan_req) - return -1; - memcpy(local->int_scan_req.ssids[0].ssid, - ifmgd->ssid, IEEE80211_MAX_SSID_LEN); - if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) - local->int_scan_req.ssids[0].ssid_len = 0; - else - local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; - if (ieee80211_start_scan(sdata, &local->int_scan_req)) - ieee80211_scan_failed(local); + ifmgd->assoc_scan_tries++; + + ieee80211_request_internal_scan(sdata, ifmgd->ssid, + ssid_len); 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); } } return -1; @@ -1855,6 +2284,17 @@ static void ieee80211_sta_work(struct work_struct *work) if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) return; + + /* + * 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)) + return; + ifmgd = &sdata->u.mgd; while ((skb = skb_dequeue(&ifmgd->skb_queue))) @@ -1864,14 +2304,8 @@ static void ieee80211_sta_work(struct work_struct *work) ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { - /* - * The call to ieee80211_start_scan can fail but ieee80211_request_scan - * (which queued ieee80211_sta_work) did not return an error. Thus, call - * ieee80211_scan_failed here if ieee80211_start_scan fails in order to - * notify the scan requester. - */ - if (ieee80211_start_scan(sdata, local->scan_req)) - ieee80211_scan_failed(local); + queue_delayed_work(local->hw.workqueue, &local->scan_work, + round_jiffies_relative(0)); return; } @@ -1882,6 +2316,8 @@ static void ieee80211_sta_work(struct work_struct *work) } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request)) return; + ieee80211_recalc_idle(local); + switch (ifmgd->state) { case IEEE80211_STA_MLME_DISABLED: break; @@ -1926,10 +2362,43 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) } } +#ifdef CONFIG_PM +void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + /* + * we need to use atomic bitops for the running bits + * only because both timers might fire at the same + * time -- the code here is properly synchronised. + */ + + cancel_work_sync(&ifmgd->work); + cancel_work_sync(&ifmgd->beacon_loss_work); + if (del_timer_sync(&ifmgd->timer)) + set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); + + cancel_work_sync(&ifmgd->chswitch_work); + if (del_timer_sync(&ifmgd->chswitch_timer)) + set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); +} + +void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) + add_timer(&ifmgd->timer); + if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) + add_timer(&ifmgd->chswitch_timer); +} +#endif + /* interface setup */ 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); @@ -1949,6 +2418,13 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) IEEE80211_STA_AUTO_CHANNEL_SEL; 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; + } } /* configuration hooks */ @@ -2032,13 +2508,6 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) ifmgd->flags &= ~IEEE80211_STA_BSSID_SET; } - if (netif_running(sdata->dev)) { - if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", sdata->dev->name); - } - } - return ieee80211_sta_commit(sdata); } @@ -2047,6 +2516,13 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + if (len == 0 && ifmgd->extra_ie_len == 0) + return -EALREADY; + + if (len == ifmgd->extra_ie_len && ifmgd->extra_ie && + memcmp(ifmgd->extra_ie, ie, len) == 0) + return -EALREADY; + kfree(ifmgd->extra_ie); if (len == 0) { ifmgd->extra_ie = NULL; @@ -2068,9 +2544,6 @@ 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 (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EINVAL; - ieee80211_set_disassoc(sdata, true, true, reason); return 0; } @@ -2082,9 +2555,6 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", sdata->dev->name, reason); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EINVAL; - if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED)) return -ENOLINK; @@ -2104,75 +2574,17 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) rcu_read_unlock(); } -void ieee80211_dynamic_ps_disable_work(struct work_struct *work) +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(work, struct ieee80211_local, - dynamic_ps_disable_work); + container_of(nb, struct ieee80211_local, + network_latency_notifier); - if (local->hw.conf.flags & IEEE80211_CONF_PS) { - local->hw.conf.flags &= ~IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, latency_usec); + mutex_unlock(&local->iflist_mtx); - ieee80211_wake_queues_by_reason(&local->hw, - IEEE80211_QUEUE_STOP_REASON_PS); -} - -void ieee80211_dynamic_ps_enable_work(struct work_struct *work) -{ - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, - dynamic_ps_enable_work); - /* XXX: using scan_sdata is completely broken! */ - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - - if (local->hw.conf.flags & IEEE80211_CONF_PS) - return; - - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK && sdata) - ieee80211_send_nullfunc(local, sdata, 1); - - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); -} - -void ieee80211_dynamic_ps_timer(unsigned long data) -{ - struct ieee80211_local *local = (void *) data; - - queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); -} - -void ieee80211_send_nullfunc(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - int powersave) -{ - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; - __le16 fc; - - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) - return; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " - "frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(nullfunc, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - if (powersave) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - nullfunc->frame_control = fc; - memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); - memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); - memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); - - ieee80211_tx_skb(sdata, skb, 0); + return 0; } diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 81985d27cbda..7a549f9deb96 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -2,6 +2,8 @@ #include #include "ieee80211_i.h" +#include "mesh.h" +#include "driver-ops.h" #include "led.h" int __ieee80211_suspend(struct ieee80211_hw *hw) @@ -12,11 +14,30 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct sta_info *sta; unsigned long flags; + ieee80211_scan_cancel(local); + ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); + /* flush out all packets */ + synchronize_net(); + + local->quiescing = true; + /* make quiescing visible to timers everywhere */ + mb(); + flush_workqueue(local->hw.workqueue); + /* Don't try to run timers while suspended. */ + del_timer_sync(&local->sta_cleanup); + + /* + * Note that this particular timer doesn't need to be + * restarted at resume. + */ + cancel_work_sync(&local->dynamic_ps_enable_work); + del_timer_sync(&local->dynamic_ps_timer); + /* disable keys */ list_for_each_entry(sdata, &local->interfaces, list) ieee80211_disable_keys(sdata); @@ -34,157 +55,70 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) rcu_read_unlock(); - /* remove STAs */ - if (local->ops->sta_notify) { - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(sta, &local->sta_list, list) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - - local->ops->sta_notify(hw, &sdata->vif, - STA_NOTIFY_REMOVE, &sta->sta); - } - spin_unlock_irqrestore(&local->sta_lock, flags); - } - - /* remove all interfaces */ - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_MONITOR && - netif_running(sdata->dev)) { - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->dev->dev_addr; - local->ops->remove_interface(hw, &conf); - } - } - /* flush again, in case driver queued work */ flush_workqueue(local->hw.workqueue); - /* stop hardware */ + /* stop hardware - this must stop RX */ if (local->open_count) { ieee80211_led_radio(local, false); - local->ops->stop(hw); - } - return 0; -} - -int __ieee80211_resume(struct ieee80211_hw *hw) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_init_conf conf; - struct sta_info *sta; - unsigned long flags; - int res; - - /* restart hardware */ - if (local->open_count) { - res = local->ops->start(hw); - - ieee80211_led_radio(local, hw->conf.radio_enabled); + drv_stop(local); } - /* add interfaces */ - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_MONITOR && - netif_running(sdata->dev)) { - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->dev->dev_addr; - res = local->ops->add_interface(hw, &conf); - } - } - - /* add STAs back */ - if (local->ops->sta_notify) { - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(sta, &local->sta_list, list) { + /* remove STAs */ + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry(sta, &local->sta_list, list) { + if (local->ops->sta_notify) { + sdata = sta->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(hw, &sdata->vif, - STA_NOTIFY_ADD, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + &sta->sta); } - spin_unlock_irqrestore(&local->sta_lock, flags); + + mesh_plink_quiesce(sta); } + spin_unlock_irqrestore(&local->sta_lock, flags); - /* Clear Suspend state so that ADDBA requests can be processed */ - - rcu_read_lock(); - - if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { - list_for_each_entry_rcu(sta, &local->sta_list, list) { - clear_sta_flags(sta, WLAN_STA_SUSPEND); - } - } - - rcu_read_unlock(); - - /* add back keys */ - list_for_each_entry(sdata, &local->interfaces, list) - if (netif_running(sdata->dev)) - ieee80211_enable_keys(sdata); - - /* setup RTS threshold */ - if (local->ops->set_rts_threshold) - local->ops->set_rts_threshold(hw, local->rts_threshold); - - /* reconfigure hardware */ - ieee80211_hw_config(local, ~0); - - netif_addr_lock_bh(local->mdev); - ieee80211_configure_filter(local); - netif_addr_unlock_bh(local->mdev); - - /* Finally also reconfigure all the BSS information */ + /* remove all interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { - u32 changed = ~0; - if (!netif_running(sdata->dev)) - continue; - switch (sdata->vif.type) { + switch(sdata->vif.type) { case NL80211_IFTYPE_STATION: - /* disable beacon change bits */ - changed &= ~IEEE80211_IFCC_BEACON; - /* fall through */ - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - /* - * Driver's config_interface can fail if rfkill is - * enabled. Accommodate this return code. - * FIXME: When mac80211 has knowledge of rfkill - * state the code below can change back to: - * WARN(ieee80211_if_config(sdata, changed)); - * ieee80211_bss_info_change_notify(sdata, ~0); - */ - if (ieee80211_if_config(sdata, changed)) - printk(KERN_DEBUG "%s: failed to configure interface during resume\n", - sdata->dev->name); - else - ieee80211_bss_info_change_notify(sdata, ~0); + ieee80211_sta_quiesce(sdata); break; - case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_quiesce(sdata); + break; + case NL80211_IFTYPE_MESH_POINT: + ieee80211_mesh_quiesce(sdata); break; case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_MONITOR: - /* ignore virtual */ - break; - case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: - WARN_ON(1); + /* don't tell driver about this */ + continue; + default: break; } + + if (!netif_running(sdata->dev)) + continue; + + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = sdata->dev->dev_addr; + drv_remove_interface(local, &conf); } - ieee80211_wake_queues_by_reason(hw, - IEEE80211_QUEUE_STOP_REASON_SUSPEND); + local->suspended = true; + local->quiescing = false; return 0; } + +/* + * __ieee80211_resume() is a static inline which just calls + * ieee80211_reconfig(), which is also needed for hardware + * hang/firmware failure/etc. recovery. + */ diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index d9233ec50610..b218b98fba7f 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -80,8 +80,7 @@ use_low_rate(struct sk_buff *skb) fc = le16_to_cpu(hdr->frame_control); return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || - (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1)); + (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA); } @@ -216,7 +215,7 @@ minstrel_get_next_sample(struct minstrel_sta_info *mi) unsigned int sample_ndx; sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); mi->sample_idx++; - if (mi->sample_idx > (mi->n_rates - 2)) { + if ((int) mi->sample_idx > (mi->n_rates - 2)) { mi->sample_idx = 0; mi->sample_column++; if (mi->sample_column >= SAMPLE_COLUMNS) @@ -245,7 +244,10 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, if (!sta || !mi || use_low_rate(skb)) { ar[0].idx = rate_lowest_index(sband, sta); - ar[0].count = mp->max_retry; + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + ar[0].count = 1; + else + ar[0].count = mp->max_retry; return; } diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 8bef9a1262ff..a0bef767ceb5 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -289,13 +289,15 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, info->control.rates[0].count = txrc->hw->conf.short_frame_max_tx_count; - /* Send management frames and broadcast/multicast data using lowest - * rate. */ + /* 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 || - is_multicast_ether_addr(hdr->addr1)) { + 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; + return; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9776f73c51ad..de5bba7f910a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -19,6 +19,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "led.h" #include "mesh.h" #include "wep.h" @@ -629,15 +630,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) * possible. */ - if (!ieee80211_has_protected(hdr->frame_control)) { - if (!ieee80211_is_mgmt(hdr->frame_control) || - rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) - return RX_CONTINUE; - mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); - if (mmie_keyidx < 0) - return RX_CONTINUE; - } - /* * No point in finding a key and decrypting if the frame is neither * addressed to us nor a multicast frame. @@ -648,8 +640,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) if (rx->sta) stakey = rcu_dereference(rx->sta->key); + if (!ieee80211_has_protected(hdr->frame_control)) + mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); + if (!is_multicast_ether_addr(hdr->addr1) && stakey) { rx->key = stakey; + /* Skip decryption if the frame is not protected. */ + if (!ieee80211_has_protected(hdr->frame_control)) + return RX_CONTINUE; } else if (mmie_keyidx >= 0) { /* Broadcast/multicast robust management frame / BIP */ if ((rx->status->flag & RX_FLAG_DECRYPTED) && @@ -660,6 +658,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) return RX_DROP_MONITOR; /* unexpected BIP keyidx */ rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); + } else if (!ieee80211_has_protected(hdr->frame_control)) { + /* + * The frame was not protected, so skip decryption. However, we + * need to set rx->key if there is a key that could have been + * used so that the frame may be dropped if encryption would + * have been expected. + */ + struct ieee80211_key *key = NULL; + if (ieee80211_is_mgmt(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1) && + (key = rcu_dereference(rx->sdata->default_mgmt_key))) + rx->key = key; + else if ((key = rcu_dereference(rx->sdata->default_key))) + rx->key = key; + return RX_CONTINUE; } else { /* * The device doesn't give us the IV so we won't be @@ -773,9 +786,7 @@ static void ap_sta_ps_start(struct sta_info *sta) atomic_inc(&sdata->bss->num_sta_ps); set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); - if (local->ops->sta_notify) - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_SLEEP, &sta->sta); + 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", sdata->dev->name, sta->sta.addr, sta->sta.aid); @@ -786,15 +797,12 @@ static int ap_sta_ps_end(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - int sent = 0; + int sent, buffered; atomic_dec(&sdata->bss->num_sta_ps); clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); - if (local->ops->sta_notify) - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_AWAKE, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); if (!skb_queue_empty(&sta->ps_tx_buf)) sta_info_clear_tim_bit(sta); @@ -805,22 +813,16 @@ static int ap_sta_ps_end(struct sta_info *sta) #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { - sent++; - skb->requeue = 1; - dev_queue_xmit(skb); - } - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - local->total_ps_buffered--; - sent++; + sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); + buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); + sent += buffered; + local->total_ps_buffered -= buffered; + #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame " - "since STA not sleeping anymore\n", sdata->dev->name, - sta->sta.addr, sta->sta.aid); + printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " + "since STA not sleeping anymore\n", sdata->dev->name, + sta->sta.addr, sta->sta.aid, sent - buffered, buffered); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - skb->requeue = 1; - dev_queue_xmit(skb); - } return sent; } @@ -1212,109 +1214,38 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) /* Drop unencrypted frames if key is set. */ if (unlikely(!ieee80211_has_protected(fc) && !ieee80211_is_nullfunc(fc) && - (!ieee80211_is_mgmt(fc) || - (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && - rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && - (rx->key || rx->sdata->drop_unencrypted))) - return -EACCES; - /* BIP does not use Protected field, so need to check MMIE */ - if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && - ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && - ieee80211_get_mmie_keyidx(rx->skb) < 0 && + ieee80211_is_data(fc) && (rx->key || rx->sdata->drop_unencrypted))) return -EACCES; + if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { + if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && + rx->key)) + return -EACCES; + /* BIP does not use Protected field, so need to check MMIE */ + if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) + && ieee80211_get_mmie_keyidx(rx->skb) < 0 && + rx->key)) + return -EACCES; + /* + * When using MFP, Action frames are not allowed prior to + * having configured keys. + */ + if (unlikely(ieee80211_is_action(fc) && !rx->key && + ieee80211_is_robust_mgmt_frame( + (struct ieee80211_hdr *) rx->skb->data))) + return -EACCES; + } return 0; } static int -ieee80211_data_to_8023(struct ieee80211_rx_data *rx) +__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - u16 hdrlen, ethertype; - u8 *payload; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN] __aligned(2); - struct sk_buff *skb = rx->skb; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) - return -1; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - - /* convert IEEE 802.11 header + possible LLC headers into Ethernet - * header - * IEEE 802.11 address fields: - * ToDS FromDS Addr1 Addr2 Addr3 Addr4 - * 0 0 DA SA BSSID n/a - * 0 1 DA BSSID SA n/a - * 1 0 BSSID SA DA n/a - * 1 1 RA TA DA SA - */ - memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); - memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); - - switch (hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case cpu_to_le16(IEEE80211_FCTL_TODS): - if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && - sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) - return -1; - break; - case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && - sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) - return -1; - if (ieee80211_vif_is_mesh(&sdata->vif)) { - struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) - (skb->data + hdrlen); - hdrlen += ieee80211_get_mesh_hdrlen(meshdr); - if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { - memcpy(dst, meshdr->eaddr1, ETH_ALEN); - memcpy(src, meshdr->eaddr2, ETH_ALEN); - } - } - break; - case cpu_to_le16(IEEE80211_FCTL_FROMDS): - if (sdata->vif.type != NL80211_IFTYPE_STATION || - (is_multicast_ether_addr(dst) && - !compare_ether_addr(src, dev->dev_addr))) - return -1; - break; - case cpu_to_le16(0): - if (sdata->vif.type != NL80211_IFTYPE_ADHOC) - return -1; - break; - } - - if (unlikely(skb->len - hdrlen < 8)) - return -1; - - payload = skb->data + hdrlen; - ethertype = (payload[6] << 8) | payload[7]; - - if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - compare_ether_addr(payload, bridge_tunnel_header) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ - skb_pull(skb, hdrlen + 6); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } else { - struct ethhdr *ehdr; - __be16 len; - - skb_pull(skb, hdrlen); - len = htons(skb->len); - ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); - memcpy(ehdr->h_dest, dst, ETH_ALEN); - memcpy(ehdr->h_source, src, ETH_ALEN); - ehdr->h_proto = len; - } - return 0; + return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); } /* @@ -1397,7 +1328,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) * mac80211. That also explains the __skb_push() * below. */ - align = (unsigned long)skb->data & 3; + align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; if (align) { if (WARN_ON(skb_headroom(skb) < 3)) { dev_kfree_skb(skb); @@ -1453,7 +1384,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_AMSDU)) return RX_CONTINUE; - err = ieee80211_data_to_8023(rx); + err = __ieee80211_data_to_8023(rx); if (unlikely(err)) return RX_DROP_UNUSABLE; @@ -1639,7 +1570,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) return RX_DROP_MONITOR; - err = ieee80211_data_to_8023(rx); + err = __ieee80211_data_to_8023(rx); if (unlikely(err)) return RX_DROP_UNUSABLE; @@ -1827,6 +1758,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) sizeof(mgmt->u.action.u.chan_switch))) return RX_DROP_MONITOR; + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return RX_DROP_MONITOR; + if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) return RX_DROP_MONITOR; @@ -1837,7 +1771,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (!bss) return RX_DROP_MONITOR; - ieee80211_process_chanswitch(sdata, + ieee80211_sta_process_chanswitch(sdata, &mgmt->u.action.u.chan_switch.sw_elem, bss); ieee80211_rx_bss_put(local, bss); break; @@ -1932,7 +1866,7 @@ 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); + mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL); ignore: dev_kfree_skb(rx->skb); rx->skb = NULL; @@ -2287,6 +2221,43 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) } +static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, + struct tid_ampdu_rx *tid_agg_rx, + int index) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_rate *rate; + struct ieee80211_rx_status status; + + if (!tid_agg_rx->reorder_buf[index]) + goto no_frame; + + /* 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) + 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); + tid_agg_rx->stored_mpdu_num--; + tid_agg_rx->reorder_buf[index] = NULL; + +no_frame: + tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); +} + + +/* + * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If + * the skb was added to the buffer longer than this time ago, the earlier + * frames that have not yet been received are assumed to be lost and the skb + * can be released for processing. This may also release other skb's from the + * reorder buffer if there are no additional gaps between the frames. + */ +#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) + /* * As it function blongs to Rx path it must be called with * the proper rcu_read_lock protection for its flow. @@ -2298,12 +2269,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, u16 mpdu_seq_num, int bar_req) { - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_rx_status status; u16 head_seq_num, buf_size; int index; - struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate; buf_size = tid_agg_rx->buf_size; head_seq_num = tid_agg_rx->head_seq_num; @@ -2328,28 +2295,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; - - if (tid_agg_rx->reorder_buf[index]) { - /* release the reordered frames to stack */ - memcpy(&status, - tid_agg_rx->reorder_buf[index]->cb, - sizeof(status)); - sband = local->hw.wiphy->bands[status.band]; - if (status.flag & RX_FLAG_HT) { - /* TODO: HT rates */ - rate = sband->bitrates; - } else { - rate = &sband->bitrates - [status.rate_idx]; - } - __ieee80211_rx_handle_packet(hw, - tid_agg_rx->reorder_buf[index], - &status, rate); - tid_agg_rx->stored_mpdu_num--; - tid_agg_rx->reorder_buf[index] = NULL; - } - tid_agg_rx->head_seq_num = - seq_inc(tid_agg_rx->head_seq_num); + ieee80211_release_reorder_frame(hw, tid_agg_rx, + index); } if (bar_req) return 1; @@ -2376,26 +2323,50 @@ 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) % tid_agg_rx->buf_size; - while (tid_agg_rx->reorder_buf[index]) { - /* release the reordered frame back to stack */ - memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, - sizeof(status)); - sband = local->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); - tid_agg_rx->stored_mpdu_num--; - tid_agg_rx->reorder_buf[index] = NULL; - tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); + if (!tid_agg_rx->reorder_buf[index] && + tid_agg_rx->stored_mpdu_num > 1) { + /* + * No buffers ready to be released, but check whether any + * frames in the reorder buffer have timed out. + */ + int j; + int skipped = 1; + for (j = (index + 1) % tid_agg_rx->buf_size; j != index; + j = (j + 1) % tid_agg_rx->buf_size) { + if (tid_agg_rx->reorder_buf[j] == NULL) { + skipped++; + continue; + } + if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + + HZ / 10)) + break; + +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: release an RX reorder " + "frame due to timeout on earlier " + "frames\n", + wiphy_name(hw->wiphy)); +#endif + ieee80211_release_reorder_frame(hw, tid_agg_rx, j); + + /* + * Increment the head seq# also for the skipped slots. + */ + tid_agg_rx->head_seq_num = + (tid_agg_rx->head_seq_num + skipped) & + SEQ_MASK; + skipped = 0; + } + } else while (tid_agg_rx->reorder_buf[index]) { + ieee80211_release_reorder_frame(hw, tid_agg_rx, index); index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; } @@ -2517,6 +2488,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, return; } + /* + * In theory, the block ack reordering should happen after duplicate + * removal (ieee80211_rx_h_check(), which is an RX handler). As such, + * the call to ieee80211_rx_reorder_ampdu() should really be moved to + * happen as a new RX handler between ieee80211_rx_h_check and + * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for + * the time being, the call can be here since RX reorder buf processing + * will implicitly skip duplicates. We could, in theory at least, + * process frames that ieee80211_rx_h_passive_scan would drop (e.g., + * 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); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 3bf9839f5916..2a8d09ad17ff 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -21,6 +21,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "mesh.h" #define IEEE80211_PROBE_DELAY (HZ / 33) @@ -202,18 +203,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_QUEUED; } -void ieee80211_scan_failed(struct ieee80211_local *local) -{ - if (WARN_ON(!local->scan_req)) - return; - - /* notify cfg80211 about the failed scan */ - if (local->scan_req != &local->int_scan_req) - cfg80211_scan_done(local->scan_req, true); - - local->scan_req = NULL; -} - /* * inform AP that we will go to sleep so that it will buffer the frames * while we scan @@ -253,7 +242,7 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - if (!local->powersave) + if (!local->ps_sdata) ieee80211_send_nullfunc(local, sdata, 0); else { /* @@ -274,51 +263,62 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) } } +static void ieee80211_restore_scan_ies(struct ieee80211_local *local) +{ + kfree(local->scan_req->ie); + local->scan_req->ie = local->orig_ies; + local->scan_req->ie_len = local->orig_ies_len; +} + void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; + bool was_hw_scan; - if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) - return; + mutex_lock(&local->scan_mtx); - if (WARN_ON(!local->scan_req)) + if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) { + mutex_unlock(&local->scan_mtx); return; + } + + if (WARN_ON(!local->scan_req)) { + mutex_unlock(&local->scan_mtx); + return; + } + + if (local->hw_scanning) + ieee80211_restore_scan_ies(local); if (local->scan_req != &local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; - local->last_scan_completed = jiffies; - - if (local->hw_scanning) { - local->hw_scanning = false; - /* - * Somebody might have requested channel change during scan - * that we won't have acted upon, try now. ieee80211_hw_config - * will set the flag based on actual changes. - */ - ieee80211_hw_config(local, 0); - goto done; - } - + was_hw_scan = local->hw_scanning; + local->hw_scanning = false; local->sw_scanning = false; + local->scan_channel = NULL; + + /* we only have to protect scan_req and hw/sw scan */ + mutex_unlock(&local->scan_mtx); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + if (was_hw_scan) + goto done; netif_tx_lock_bh(local->mdev); netif_addr_lock(local->mdev); local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); + 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); - if (local->ops->sw_scan_complete) - local->ops->sw_scan_complete(local_to_hw(local)); + drv_sw_scan_complete(local); mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { @@ -338,18 +338,160 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_ADHOC || sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_if_config(sdata, - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); } mutex_unlock(&local->iflist_mtx); done: + ieee80211_recalc_idle(local); ieee80211_mlme_notify_scan_completed(local); ieee80211_ibss_notify_scan_completed(local); ieee80211_mesh_notify_scan_completed(local); } EXPORT_SYMBOL(ieee80211_scan_completed); +static int ieee80211_start_sw_scan(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + /* + * Hardware/driver doesn't support hw_scan, so use software + * scanning instead. First send a nullfunc frame with power save + * bit on so that AP will buffer the frames for us while we are not + * listening, then send probe requests to each channel and wait for + * the responses. After all channels are scanned, tune back to the + * original channel and send a nullfunc frame with power save bit + * off to trigger the AP to send us all the buffered frames. + * + * Note that while local->sw_scanning is true everything else but + * nullfunc frames and probe requests will be dropped in + * ieee80211_tx_h_check_assoc(). + */ + drv_sw_scan_start(local); + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + + /* disable beaconing */ + if (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + 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 + netif_tx_stop_all_queues(sdata->dev); + } + mutex_unlock(&local->iflist_mtx); + + local->scan_state = SCAN_SET_CHANNEL; + local->scan_channel_idx = 0; + + netif_addr_lock_bh(local->mdev); + 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); + + /* TODO: start scan as soon as all nullfunc frames are ACKed */ + queue_delayed_work(local->hw.workqueue, &local->scan_work, + IEEE80211_CHANNEL_TIME); + + return 0; +} + + +static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + int rc; + + if (local->scan_req) + return -EBUSY; + + if (local->ops->hw_scan) { + u8 *ies; + int ielen; + + ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + req->ie_len, GFP_KERNEL); + if (!ies) + return -ENOMEM; + + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + local->orig_ies = req->ie; + local->orig_ies_len = req->ie_len; + req->ie = ies; + req->ie_len = ielen; + } + + local->scan_req = req; + local->scan_sdata = sdata; + + 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 */ + set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); + return 0; + } + + if (local->ops->hw_scan) + local->hw_scanning = true; + else + local->sw_scanning = true; + /* + * Kicking off the scan need not be protected, + * only the scan variable stuff, since now + * local->scan_req is assigned and other callers + * will abort their scan attempts. + * + * This avoids getting a scan_mtx -> iflist_mtx + * dependency, so that the scan completed calls + * have more locking freedom. + */ + + ieee80211_recalc_idle(local); + mutex_unlock(&local->scan_mtx); + + if (local->ops->hw_scan) + rc = drv_hw_scan(local, local->scan_req); + else + rc = ieee80211_start_sw_scan(local); + + mutex_lock(&local->scan_mtx); + + if (rc) { + if (local->ops->hw_scan) { + local->hw_scanning = false; + ieee80211_restore_scan_ies(local); + } else + local->sw_scanning = false; + + ieee80211_recalc_idle(local); + + local->scan_req = NULL; + local->scan_sdata = NULL; + } + + return rc; +} + void ieee80211_scan_work(struct work_struct *work) { struct ieee80211_local *local = @@ -359,17 +501,41 @@ void ieee80211_scan_work(struct work_struct *work) int skip, i; unsigned long next_delay = 0; + mutex_lock(&local->scan_mtx); + if (!sdata || !local->scan_req) { + mutex_unlock(&local->scan_mtx); + return; + } + + if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) { + struct cfg80211_scan_request *req = local->scan_req; + int rc; + + local->scan_req = NULL; + + rc = __ieee80211_start_scan(sdata, req); + mutex_unlock(&local->scan_mtx); + + if (rc) + ieee80211_scan_completed(&local->hw, true); + return; + } + + mutex_unlock(&local->scan_mtx); + /* * Avoid re-scheduling when the sdata is going away. */ - if (!netif_running(sdata->dev)) + if (!netif_running(sdata->dev)) { + ieee80211_scan_completed(&local->hw, true); 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_to_hw(local), false); + ieee80211_scan_completed(&local->hw, false); return; } skip = 0; @@ -393,24 +559,39 @@ void ieee80211_scan_work(struct work_struct *work) if (skip) break; - next_delay = IEEE80211_PROBE_DELAY + - usecs_to_jiffies(local->hw.channel_change_time); + /* + * 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; + break; + } + + next_delay = IEEE80211_PROBE_DELAY; local->scan_state = SCAN_SEND_PROBE; break; case SCAN_SEND_PROBE: - next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; - local->scan_state = SCAN_SET_CHANNEL; - - if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN || - !local->scan_req->n_ssids) - break; 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; } @@ -418,150 +599,53 @@ void ieee80211_scan_work(struct work_struct *work) next_delay); } - -int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, - struct cfg80211_scan_request *req) -{ - struct ieee80211_local *local = scan_sdata->local; - struct ieee80211_sub_if_data *sdata; - - if (!req) - return -EINVAL; - - if (local->scan_req && local->scan_req != req) - return -EBUSY; - - local->scan_req = req; - - /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) - * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS - * BSSID: MACAddress - * SSID - * ScanType: ACTIVE, PASSIVE - * ProbeDelay: delay (in microseconds) to be used prior to transmitting - * a Probe frame during active scanning - * ChannelList - * MinChannelTime (>= ProbeDelay), in TU - * MaxChannelTime: (>= MinChannelTime), in TU - */ - - /* MLME-SCAN.confirm - * BSSDescriptionSet - * ResultCode: SUCCESS, INVALID_PARAMETERS - */ - - if (local->sw_scanning || local->hw_scanning) { - if (local->scan_sdata == scan_sdata) - return 0; - return -EBUSY; - } - - if (local->ops->hw_scan) { - int rc; - - local->hw_scanning = true; - rc = local->ops->hw_scan(local_to_hw(local), req); - if (rc) { - local->hw_scanning = false; - return rc; - } - local->scan_sdata = scan_sdata; - return 0; - } - - /* - * Hardware/driver doesn't support hw_scan, so use software - * scanning instead. First send a nullfunc frame with power save - * bit on so that AP will buffer the frames for us while we are not - * listening, then send probe requests to each channel and wait for - * the responses. After all channels are scanned, tune back to the - * original channel and send a nullfunc frame with power save bit - * off to trigger the AP to send us all the buffered frames. - * - * Note that while local->sw_scanning is true everything else but - * nullfunc frames and probe requests will be dropped in - * ieee80211_tx_h_check_assoc(). - */ - local->sw_scanning = true; - if (local->ops->sw_scan_start) - local->ops->sw_scan_start(local_to_hw(local)); - - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) - continue; - - /* disable beaconing */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_if_config(sdata, - IEEE80211_IFCC_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 - netif_tx_stop_all_queues(sdata->dev); - } - mutex_unlock(&local->iflist_mtx); - - local->scan_state = SCAN_SET_CHANNEL; - local->scan_channel_idx = 0; - local->scan_sdata = scan_sdata; - local->scan_req = req; - - netif_addr_lock_bh(local->mdev); - local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); - netif_addr_unlock_bh(local->mdev); - - /* TODO: start scan as soon as all nullfunc frames are ACKed */ - queue_delayed_work(local->hw.workqueue, &local->scan_work, - IEEE80211_CHANNEL_TIME); - - return 0; -} - - int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req) +{ + int res; + + mutex_lock(&sdata->local->scan_mtx); + res = __ieee80211_start_scan(sdata, req); + mutex_unlock(&sdata->local->scan_mtx); + + return res; +} + +int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd; + int ret = -EBUSY; - if (!req) - return -EINVAL; + mutex_lock(&local->scan_mtx); - if (local->scan_req && local->scan_req != req) - return -EBUSY; + /* busy scanning */ + if (local->scan_req) + goto unlock; - local->scan_req = req; + memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); + local->int_scan_req.ssids[0].ssid_len = ssid_len; - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return ieee80211_start_scan(sdata, req); + ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); + unlock: + mutex_unlock(&local->scan_mtx); + return ret; +} + +void ieee80211_scan_cancel(struct ieee80211_local *local) +{ + bool swscan; + + cancel_delayed_work_sync(&local->scan_work); /* - * STA has a state machine that might need to defer scanning - * while it's trying to associate/authenticate, therefore we - * queue it up to the state machine in that case. + * Only call this function when a scan can't be + * queued -- mostly at suspend under RTNL. */ + mutex_lock(&local->scan_mtx); + swscan = local->sw_scanning; + mutex_unlock(&local->scan_mtx); - if (local->sw_scanning || local->hw_scanning) { - if (local->scan_sdata == sdata) - return 0; - return -EBUSY; - } - - ifmgd = &sdata->u.mgd; - set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); - queue_work(local->hw.workqueue, &ifmgd->work); - - return 0; + if (swscan) + ieee80211_scan_completed(&local->hw, true); } diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 5f7a2624ed74..68953033403d 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include "ieee80211_i.h" #include "sta_info.h" @@ -84,104 +84,3 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, mgmt->sa, mgmt->bssid, mgmt->u.action.u.measurement.dialog_token); } - -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; - - sdata->local->oper_channel = sdata->local->csa_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; - - 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); -} - -void ieee80211_chswitch_timer(unsigned long data) -{ - struct ieee80211_sub_if_data *sdata = - (struct ieee80211_sub_if_data *) data; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - - queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); -} - -void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel_sw_ie *sw_elem, - struct ieee80211_bss *bss) -{ - struct ieee80211_channel *new_ch; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); - - /* FIXME: Handle ADHOC later */ - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return; - - if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATED) - return; - - if (sdata->local->sw_scanning || sdata->local->hw_scanning) - return; - - /* Disregard subsequent beacons if we are already running a timer - processing a CSA */ - - if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) - return; - - new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); - if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) - return; - - sdata->local->csa_channel = new_ch; - - if (sw_elem->count <= 1) { - queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); - } else { - ieee80211_stop_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); - ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; - mod_timer(&ifmgd->chswitch_timer, - jiffies + - msecs_to_jiffies(sw_elem->count * - bss->cbss.beacon_interval)); - } -} - -void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, - u16 capab_info, u8 *pwr_constr_elem, - u8 pwr_constr_elem_len) -{ - struct ieee80211_conf *conf = &sdata->local->hw.conf; - - if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) - return; - - /* Power constraint IE length should be 1 octet */ - if (pwr_constr_elem_len != 1) - return; - - if ((*pwr_constr_elem <= conf->channel->max_power) && - (*pwr_constr_elem != sdata->local->power_constr_level)) { - sdata->local->power_constr_level = *pwr_constr_elem; - ieee80211_hw_config(sdata->local, 0); - } -} - diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c5f14e6bbde2..a360bceeba59 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -19,6 +19,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "sta_info.h" #include "debugfs_sta.h" @@ -43,6 +44,15 @@ * When the insertion fails (sta_info_insert()) returns non-zero), the * structure will have been freed by sta_info_insert()! * + * sta entries are added by mac80211 when you establish a link with a + * peer. This means different things for the different type of interfaces + * we support. For a regular station this mean we add the AP sta when we + * receive an assocation response from the AP. For IBSS this occurs when + * we receive a probe response or a beacon from target IBSS network. For + * WDS we add the sta for the peer imediately upon device open. When using + * AP mode we add stations for each respective station upon request from + * userspace through nl80211. + * * Because there are debugfs entries for each station, and adding those * must be able to sleep, it is also possible to "pin" a station entry, * that means it can be removed from the hash table but not be freed. @@ -292,6 +302,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, skb_queue_head_init(&sta->ps_tx_buf); skb_queue_head_init(&sta->tx_filtered); + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) + sta->last_seq_ctrl[i] = cpu_to_le16(USHORT_MAX); + #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Allocated STA %pM\n", wiphy_name(local->hw.wiphy), sta->sta.addr); @@ -346,8 +359,7 @@ int sta_info_insert(struct sta_info *sta) struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_ADD, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -405,8 +417,7 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; - sta->local->ops->set_tim(local_to_hw(sta->local), - &sta->sta, true); + drv_set_tim(sta->local, &sta->sta, true); sta->local->tim_in_locked_section = false; } } @@ -431,8 +442,7 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; - sta->local->ops->set_tim(local_to_hw(sta->local), - &sta->sta, false); + drv_set_tim(sta->local, &sta->sta, false); sta->local->tim_in_locked_section = false; } } @@ -482,8 +492,8 @@ static void __sta_info_unlink(struct sta_info **sta) struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_REMOVE, &(*sta)->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + &(*sta)->sta); } if (ieee80211_vif_is_mesh(&sdata->vif)) { @@ -543,9 +553,8 @@ void sta_info_unlink(struct sta_info **sta) spin_unlock_irqrestore(&local->sta_lock, flags); } -static inline int sta_info_buffer_expired(struct ieee80211_local *local, - struct sta_info *sta, - struct sk_buff *skb) +static int sta_info_buffer_expired(struct sta_info *sta, + struct sk_buff *skb) { struct ieee80211_tx_info *info; int timeout; @@ -556,8 +565,9 @@ static inline int sta_info_buffer_expired(struct ieee80211_local *local, info = IEEE80211_SKB_CB(skb); /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ - timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 / - 15625) * HZ; + timeout = (sta->listen_interval * + sta->sdata->vif.bss_conf.beacon_int * + 32 / 15625) * HZ; if (timeout < STA_TX_BUFFER_EXPIRE) timeout = STA_TX_BUFFER_EXPIRE; return time_after(jiffies, info->control.jiffies + timeout); @@ -577,7 +587,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, for (;;) { spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); skb = skb_peek(&sta->ps_tx_buf); - if (sta_info_buffer_expired(local, sta, skb)) + if (sta_info_buffer_expired(sta, skb)) skb = __skb_dequeue(&sta->ps_tx_buf); else skb = NULL; @@ -610,6 +620,9 @@ static void sta_info_cleanup(unsigned long data) sta_info_cleanup_expire_buffered(local, sta); rcu_read_unlock(); + if (local->quiescing) + return; + local->sta_cleanup.expires = round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); add_timer(&local->sta_cleanup); @@ -686,41 +699,10 @@ static void sta_info_debugfs_add_work(struct work_struct *work) } #endif -static void __ieee80211_run_pending_flush(struct ieee80211_local *local) -{ - struct sta_info *sta; - unsigned long flags; - - ASSERT_RTNL(); - - spin_lock_irqsave(&local->sta_lock, flags); - while (!list_empty(&local->sta_flush_list)) { - sta = list_first_entry(&local->sta_flush_list, - struct sta_info, list); - list_del(&sta->list); - spin_unlock_irqrestore(&local->sta_lock, flags); - sta_info_destroy(sta); - spin_lock_irqsave(&local->sta_lock, flags); - } - spin_unlock_irqrestore(&local->sta_lock, flags); -} - -static void ieee80211_sta_flush_work(struct work_struct *work) -{ - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, sta_flush_work); - - rtnl_lock(); - __ieee80211_run_pending_flush(local); - rtnl_unlock(); -} - void sta_info_init(struct ieee80211_local *local) { spin_lock_init(&local->sta_lock); INIT_LIST_HEAD(&local->sta_list); - INIT_LIST_HEAD(&local->sta_flush_list); - INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work); setup_timer(&local->sta_cleanup, sta_info_cleanup, (unsigned long)local); @@ -741,7 +723,6 @@ int sta_info_start(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { del_timer(&local->sta_cleanup); - cancel_work_sync(&local->sta_flush_work); #ifdef CONFIG_MAC80211_DEBUGFS /* * Make sure the debugfs adding work isn't pending after this @@ -752,10 +733,7 @@ void sta_info_stop(struct ieee80211_local *local) cancel_work_sync(&local->sta_debugfs_add); #endif - rtnl_lock(); sta_info_flush(local, NULL); - __ieee80211_run_pending_flush(local); - rtnl_unlock(); } /** @@ -767,7 +745,7 @@ void sta_info_stop(struct ieee80211_local *local) * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs */ int sta_info_flush(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) + struct ieee80211_sub_if_data *sdata) { struct sta_info *sta, *tmp; LIST_HEAD(tmp_list); @@ -775,7 +753,6 @@ int sta_info_flush(struct ieee80211_local *local, unsigned long flags; might_sleep(); - ASSERT_RTNL(); spin_lock_irqsave(&local->sta_lock, flags); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { @@ -795,39 +772,6 @@ int sta_info_flush(struct ieee80211_local *local, return ret; } -/** - * sta_info_flush_delayed - flush matching STA entries from the STA table - * - * This function unlinks all stations for a given interface and queues - * them for freeing. Note that the workqueue function scheduled here has - * to run before any new keys can be added to the system to avoid set_key() - * callback ordering issues. - * - * @sdata: the interface - */ -void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta, *tmp; - unsigned long flags; - bool work = false; - - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { - if (sdata == sta->sdata) { - __sta_info_unlink(&sta); - if (sta) { - list_add_tail(&sta->list, - &local->sta_flush_list); - work = true; - } - } - } - if (work) - schedule_work(&local->sta_flush_work); - spin_unlock_irqrestore(&local->sta_lock, flags); -} - void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5534d489f506..49a1a1f76511 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -88,6 +88,7 @@ struct tid_ampdu_tx { * struct tid_ampdu_rx - TID aggregation information (Rx). * * @reorder_buf: buffer to reorder incoming aggregated MPDUs + * @reorder_time: jiffies when skb was added * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer @@ -99,6 +100,7 @@ struct tid_ampdu_tx { */ struct tid_ampdu_rx { struct sk_buff **reorder_buf; + unsigned long *reorder_time; struct timer_list session_timer; u16 head_seq_num; u16 stored_mpdu_num; @@ -214,6 +216,7 @@ struct sta_ampdu_mlme { * @plink_state: peer link state * @plink_timeout: timeout of peer link * @plink_timer: peer link watch timer + * @plink_timer_was_running: used by suspend/resume to restore timers * @debugfs: debug filesystem info * @sta: station information we share with the driver */ @@ -291,6 +294,7 @@ struct sta_info { __le16 reason; u8 plink_retries; bool ignore_plink_timer; + bool plink_timer_was_running; enum plink_state plink_state; u32 plink_timeout; struct timer_list plink_timer; @@ -442,8 +446,7 @@ void sta_info_init(struct ieee80211_local *local); int sta_info_start(struct ieee80211_local *local); void sta_info_stop(struct ieee80211_local *local); int sta_info_flush(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata); -void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); + struct ieee80211_sub_if_data *sdata); void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time); diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 38fa111d2dc6..964b7faa7f17 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -13,6 +13,7 @@ #include #include +#include "driver-ops.h" #include "key.h" #include "tkip.h" #include "wep.h" @@ -307,9 +308,8 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, if (is_multicast_ether_addr(ra)) sta_addr = bcast; - key->local->ops->update_tkip_key( - local_to_hw(key->local), &key->conf, - sta_addr, iv32, key->u.tkip.rx[queue].p1k); + drv_update_tkip_key(key->local, &key->conf, sta_addr, + iv32, key->u.tkip.rx[queue].p1k); } } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 63656266d567..d238a8939a09 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -25,6 +25,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "led.h" #include "mesh.h" #include "wep.h" @@ -399,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->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; skb_queue_tail(&sta->ps_tx_buf, tx->skb); return TX_QUEUED; } @@ -409,8 +411,24 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) sta->sta.addr); } #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - clear_sta_flags(sta, WLAN_STA_PSPOLL); + 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; } @@ -429,7 +447,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) { - struct ieee80211_key *key; + struct ieee80211_key *key = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; @@ -500,7 +518,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) sband = tx->local->hw.wiphy->bands[tx->channel->band]; len = min_t(int, tx->skb->len + FCS_LEN, - tx->local->fragmentation_threshold); + tx->local->hw.wiphy->frag_threshold); /* set up the tx rate control struct we give the RC algo */ txrc.hw = local_to_hw(tx->local); @@ -511,8 +529,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; /* set up RTS protection if desired */ - if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && - len > tx->local->rts_threshold) { + if (len > tx->local->hw.wiphy->rts_threshold) { txrc.rts = rts = true; } @@ -542,6 +559,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) if (unlikely(!info->control.rates[0].count)) info->control.rates[0].count = 1; + if (WARN_ON_ONCE((info->control.rates[0].count > 1) && + (info->flags & IEEE80211_TX_CTL_NO_ACK))) + info->control.rates[0].count = 1; + if (is_multicast_ether_addr(hdr->addr1)) { /* * XXX: verify the rate is in the basic rateset @@ -754,7 +775,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) struct sk_buff *skb = tx->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; - int frag_threshold = tx->local->fragmentation_threshold; + int frag_threshold = tx->local->hw.wiphy->frag_threshold; int hdrlen; int fragnum; @@ -852,6 +873,8 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) do { hdr = (void *) skb->data; + if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) + break; /* must not overwrite AID */ next_len = skb->next ? skb->next->len : 0; group_addr = is_multicast_ether_addr(hdr->addr1); @@ -885,9 +908,8 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) * deal with packet injection down monitor interface * with Radiotap Header -- only called for monitor mode interface */ -static ieee80211_tx_result -__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, - struct sk_buff *skb) +static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, + struct sk_buff *skb) { /* * this is the moment to interpret and discard the radiotap header that @@ -938,7 +960,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, * on transmission */ if (skb->len < (iterator.max_length + FCS_LEN)) - return TX_DROP; + return false; skb_trim(skb, skb->len - FCS_LEN); } @@ -960,7 +982,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, } if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ - return TX_DROP; + return false; /* * remove the radiotap header @@ -969,7 +991,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, */ skb_pull(skb, iterator.max_length); - return TX_CONTINUE; + return true; } /* @@ -1003,7 +1025,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, /* 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) == TX_DROP) + if (!__ieee80211_parse_tx_radiotap(tx, skb)) return TX_DROP; /* @@ -1067,12 +1089,15 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, info->flags |= IEEE80211_TX_CTL_NO_ACK; } else { tx->flags |= IEEE80211_TX_UNICAST; - info->flags &= ~IEEE80211_TX_CTL_NO_ACK; + if (unlikely(local->wifi_wme_noack_test)) + info->flags |= IEEE80211_TX_CTL_NO_ACK; + else + info->flags &= ~IEEE80211_TX_CTL_NO_ACK; } if (tx->flags & IEEE80211_TX_FRAGMENTED) { if ((tx->flags & IEEE80211_TX_UNICAST) && - skb->len + FCS_LEN > local->fragmentation_threshold && + skb->len + FCS_LEN > local->hw.wiphy->frag_threshold && !(info->flags & IEEE80211_TX_CTL_AMPDU)) tx->flags |= IEEE80211_TX_FRAGMENTED; else @@ -1147,7 +1172,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, next = skb->next; len = skb->len; - ret = local->ops->tx(local_to_hw(local), skb); + ret = drv_tx(local, skb); if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { dev_kfree_skb(skb); ret = NETDEV_TX_OK; @@ -1213,7 +1238,6 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, bool txpending) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct sta_info *sta; struct ieee80211_tx_data tx; ieee80211_tx_result res_prepare; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -1245,7 +1269,6 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, return; } - sta = tx.sta; tx.channel = local->hw.conf.channel; info->band = tx.channel->band; @@ -1392,7 +1415,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) } if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && - local->hw.conf.dynamic_ps_timeout > 0) { + local->hw.conf.dynamic_ps_timeout > 0 && + !local->sw_scanning && !local->hw_scanning && local->ps_sdata) { if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_QUEUE_STOP_REASON_PS); @@ -1591,7 +1615,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; - int ret = 1, head_need; + int ret = NETDEV_TX_BUSY, head_need; u16 ethertype, hdrlen, meshhdrlen = 0; __le16 fc; struct ieee80211_hdr hdr; @@ -2086,18 +2110,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_hdr *hdr; + struct sk_buff *presp = rcu_dereference(ifibss->presp); - if (!ifibss->probe_resp) + if (!presp) goto out; - skb = skb_copy(ifibss->probe_resp, GFP_ATOMIC); + skb = skb_copy(presp, GFP_ATOMIC); if (!skb) goto out; hdr = (struct ieee80211_hdr *) skb->data; hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - } else if (ieee80211_vif_is_mesh(&sdata->vif)) { struct ieee80211_mgmt *mgmt; u8 *pos; @@ -2117,7 +2141,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.beacon.beacon_int = - cpu_to_le16(local->hw.conf.beacon_int); + cpu_to_le16(sdata->vif.bss_conf.beacon_int); mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ pos = skb_put(skb, 2); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index fdf432f14554..66ce96a69f31 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -20,27 +20,21 @@ #include #include #include +#include #include #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "mesh.h" #include "wme.h" +#include "led.h" /* privid for wiphys to determine whether they belong to us or not */ void *mac80211_wiphy_privid = &mac80211_wiphy_privid; -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -const unsigned char rfc1042_header[] __aligned(2) = - { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -const unsigned char bridge_tunnel_header[] __aligned(2) = - { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; - struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) { struct ieee80211_local *local; @@ -100,70 +94,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, return NULL; } -unsigned int ieee80211_hdrlen(__le16 fc) -{ - unsigned int hdrlen = 24; - - if (ieee80211_is_data(fc)) { - if (ieee80211_has_a4(fc)) - hdrlen = 30; - if (ieee80211_is_data_qos(fc)) - hdrlen += IEEE80211_QOS_CTL_LEN; - goto out; - } - - if (ieee80211_is_ctl(fc)) { - /* - * ACK and CTS are 10 bytes, all others 16. To see how - * to get this condition consider - * subtype mask: 0b0000000011110000 (0x00F0) - * ACK subtype: 0b0000000011010000 (0x00D0) - * CTS subtype: 0b0000000011000000 (0x00C0) - * bits that matter: ^^^ (0x00E0) - * value of those: 0b0000000011000000 (0x00C0) - */ - if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) - hdrlen = 10; - else - hdrlen = 16; - } -out: - return hdrlen; -} -EXPORT_SYMBOL(ieee80211_hdrlen); - -unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) -{ - const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; - - if (unlikely(skb->len < 10)) - return 0; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (unlikely(hdrlen > skb->len)) - return 0; - return hdrlen; -} -EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); - -int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) -{ - int ae = meshhdr->flags & IEEE80211S_FLAGS_AE; - /* 7.1.3.5a.2 */ - switch (ae) { - case 0: - return 6; - case 1: - return 12; - case 2: - return 18; - case 3: - return 24; - default: - return 6; - } -} - void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; @@ -411,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) } EXPORT_SYMBOL(ieee80211_stop_queue); +void ieee80211_add_pending_skb(struct ieee80211_local *local, + struct sk_buff *skb) +{ + struct ieee80211_hw *hw = &local->hw; + unsigned long flags; + int queue = skb_get_queue_mapping(skb); + + 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); + __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +} + +int ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs) +{ + struct ieee80211_hw *hw = &local->hw; + struct sk_buff *skb; + unsigned long flags; + int queue, ret = 0, i; + + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + for (i = 0; i < hw->queues; i++) + __ieee80211_stop_queue(hw, i, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + + while ((skb = skb_dequeue(skbs))) { + ret++; + queue = skb_get_queue_mapping(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); + __ieee80211_wake_queue(hw, i, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD); + } + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + return ret; +} + void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason) { @@ -535,9 +511,17 @@ EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems) +{ + ieee802_11_parse_elems_crc(start, len, elems, 0, 0); +} + +u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, + struct ieee802_11_elems *elems, + u64 filter, u32 crc) { size_t left = len; u8 *pos = start; + bool calc_crc = filter != 0; memset(elems, 0, sizeof(*elems)); elems->ie_start = start; @@ -551,7 +535,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len, left -= 2; if (elen > left) - return; + break; + + if (calc_crc && id < 64 && (filter & BIT(id))) + crc = crc32_be(crc, pos - 2, elen + 2); switch (id) { case WLAN_EID_SSID: @@ -575,8 +562,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->cf_params_len = elen; break; case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; + if (elen >= sizeof(struct ieee80211_tim_ie)) { + elems->tim = (void *)pos; + elems->tim_len = elen; + } break; case WLAN_EID_IBSS_PARAMS: elems->ibss_params = pos; @@ -586,15 +575,20 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->challenge = pos; elems->challenge_len = elen; break; - case WLAN_EID_WPA: + case WLAN_EID_VENDOR_SPECIFIC: if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && pos[2] == 0xf2) { /* Microsoft OUI (00:50:F2) */ + + if (calc_crc) + crc = crc32_be(crc, pos - 2, elen + 2); + if (pos[3] == 1) { /* OUI Type 1 - WPA IE */ elems->wpa = pos; elems->wpa_len = elen; } else if (elen >= 5 && pos[3] == 2) { + /* OUI Type 2 - WMM IE */ if (pos[4] == 0) { elems->wmm_info = pos; elems->wmm_info_len = elen; @@ -679,32 +673,70 @@ void ieee802_11_parse_elems(u8 *start, size_t len, left -= elen; pos += elen; } + + return crc; } void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_tx_queue_params qparam; - int i; + int queue; + bool use_11b; + int aCWmin, aCWmax; if (!local->ops->conf_tx) return; memset(&qparam, 0, sizeof(qparam)); - qparam.aifs = 2; + use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && + !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && - !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) - qparam.cw_min = 31; - else - qparam.cw_min = 15; + for (queue = 0; queue < local_to_hw(local)->queues; queue++) { + /* Set defaults according to 802.11-2007 Table 7-37 */ + aCWmax = 1023; + if (use_11b) + aCWmin = 31; + else + aCWmin = 15; - qparam.cw_max = 1023; - qparam.txop = 0; + switch (queue) { + case 3: /* AC_BK */ + qparam.cw_max = aCWmax; + qparam.cw_min = aCWmin; + qparam.txop = 0; + qparam.aifs = 7; + break; + default: /* never happens but let's not leave undefined */ + case 2: /* AC_BE */ + qparam.cw_max = aCWmax; + qparam.cw_min = aCWmin; + qparam.txop = 0; + qparam.aifs = 3; + break; + case 1: /* AC_VI */ + qparam.cw_max = aCWmin; + qparam.cw_min = (aCWmin + 1) / 2 - 1; + if (use_11b) + qparam.txop = 6016/32; + else + qparam.txop = 3008/32; + qparam.aifs = 2; + break; + case 0: /* AC_VO */ + qparam.cw_max = (aCWmin + 1) / 2 - 1; + qparam.cw_min = (aCWmin + 1) / 4 - 1; + if (use_11b) + qparam.txop = 3264/32; + else + qparam.txop = 1504/32; + qparam.aifs = 2; + break; + } - for (i = 0; i < local_to_hw(local)->queues; i++) - local->ops->conf_tx(local_to_hw(local), i, &qparam); + drv_conf_tx(local, queue, &qparam); + } } void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, @@ -831,16 +863,73 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb, encrypt); } +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len) +{ + struct ieee80211_supported_band *sband; + u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; + int i; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + pos = buffer; + + *pos++ = WLAN_EID_SUPP_RATES; + supp_rates_len = pos; + *pos++ = 0; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + + if (esupp_rates_len) { + *esupp_rates_len += 1; + } else if (*supp_rates_len == 8) { + *pos++ = WLAN_EID_EXT_SUPP_RATES; + esupp_rates_len = pos; + *pos++ = 1; + } else + *supp_rates_len += 1; + + *pos++ = rate->bitrate / 5; + } + + if (sband->ht_cap.ht_supported) { + __le16 tmp = cpu_to_le16(sband->ht_cap.cap); + + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + /* TODO: needs a define here for << 2 */ + *pos++ = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << 2); + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ + } + + /* + * If adding more here, adjust code in main.c + * that calculates local->scan_ies_len. + */ + + if (ie) { + memcpy(pos, ie, ie_len); + pos += ie_len; + } + + return pos - buffer; +} + void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len) + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; + u8 *pos; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ie_len); @@ -867,31 +956,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; memcpy(pos, ssid, ssid_len); + pos += ssid_len; - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - *pos = rate->bitrate / 5; - } - - if (ie) - memcpy(skb_put(skb, ie_len), ie, ie_len); + skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); ieee80211_tx_skb(sdata, skb, 0); } @@ -931,3 +998,151 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, } return supp_rates; } + +int ieee80211_reconfig(struct ieee80211_local *local) +{ + struct ieee80211_hw *hw = &local->hw; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_init_conf conf; + struct sta_info *sta; + unsigned long flags; + int res; + bool from_suspend = local->suspended; + + /* + * We're going to start the hardware, at that point + * we are no longer suspended and can RX frames. + */ + local->suspended = false; + + /* restart hardware */ + if (local->open_count) { + res = drv_start(local); + + ieee80211_led_radio(local, true); + } + + /* add interfaces */ + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && + sdata->vif.type != NL80211_IFTYPE_MONITOR && + netif_running(sdata->dev)) { + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = sdata->dev->dev_addr; + res = drv_add_interface(local, &conf); + } + } + + /* add STAs back */ + if (local->ops->sta_notify) { + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry(sta, &local->sta_list, list) { + sdata = sta->sdata; + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, + &sta->sta); + } + spin_unlock_irqrestore(&local->sta_lock, flags); + } + + /* Clear Suspend state so that ADDBA requests can be processed */ + + rcu_read_lock(); + + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + list_for_each_entry_rcu(sta, &local->sta_list, list) { + clear_sta_flags(sta, WLAN_STA_SUSPEND); + } + } + + rcu_read_unlock(); + + /* setup RTS threshold */ + drv_set_rts_threshold(local, hw->wiphy->rts_threshold); + + /* reconfigure hardware */ + ieee80211_hw_config(local, ~0); + + netif_addr_lock_bh(local->mdev); + ieee80211_configure_filter(local); + netif_addr_unlock_bh(local->mdev); + + /* Finally also reconfigure all the BSS information */ + list_for_each_entry(sdata, &local->interfaces, list) { + u32 changed = ~0; + if (!netif_running(sdata->dev)) + continue; + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + /* disable beacon change bits */ + changed &= ~(BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED); + /* fall through */ + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + ieee80211_bss_info_change_notify(sdata, changed); + break; + case NL80211_IFTYPE_WDS: + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* ignore virtual */ + break; + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: + WARN_ON(1); + break; + } + } + + /* add back keys */ + list_for_each_entry(sdata, &local->interfaces, list) + if (netif_running(sdata->dev)) + ieee80211_enable_keys(sdata); + + ieee80211_wake_queues_by_reason(hw, + IEEE80211_QUEUE_STOP_REASON_SUSPEND); + + /* + * If this is for hw restart things are still running. + * We may want to change that later, however. + */ + if (!from_suspend) + return 0; + +#ifdef CONFIG_PM + local->suspended = false; + + list_for_each_entry(sdata, &local->interfaces, list) { + switch(sdata->vif.type) { + case NL80211_IFTYPE_STATION: + ieee80211_sta_restart(sdata); + break; + case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_restart(sdata); + break; + case NL80211_IFTYPE_MESH_POINT: + ieee80211_mesh_restart(sdata); + break; + default: + break; + } + } + + add_timer(&local->sta_cleanup); + + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry(sta, &local->sta_list, list) + mesh_plink_restart(sta); + spin_unlock_irqrestore(&local->sta_lock, flags); +#else + WARN_ON(1); +#endif + return 0; +} diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 959aa8379ccf..d2d81b103341 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -27,100 +27,6 @@ #include "aes_ccm.h" -static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, - int idx, int alg, int remove, - int set_tx_key, const u8 *_key, - size_t key_len) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - struct ieee80211_key *key; - int err; - - if (alg == ALG_AES_CMAC) { - if (idx < NUM_DEFAULT_KEYS || - idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { - printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d " - "(BIP)\n", sdata->dev->name, idx); - return -EINVAL; - } - } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { - printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", - sdata->dev->name, idx); - return -EINVAL; - } - - if (remove) { - rcu_read_lock(); - - err = 0; - - if (is_broadcast_ether_addr(sta_addr)) { - key = sdata->keys[idx]; - } else { - sta = sta_info_get(local, sta_addr); - if (!sta) { - err = -ENOENT; - goto out_unlock; - } - key = sta->key; - } - - ieee80211_key_free(key); - } else { - key = ieee80211_key_alloc(alg, idx, key_len, _key); - if (!key) - return -ENOMEM; - - sta = NULL; - err = 0; - - rcu_read_lock(); - - if (!is_broadcast_ether_addr(sta_addr)) { - set_tx_key = 0; - /* - * According to the standard, the key index of a - * pairwise key must be zero. However, some AP are - * broken when it comes to WEP key indices, so we - * work around this. - */ - if (idx != 0 && alg != ALG_WEP) { - ieee80211_key_free(key); - err = -EINVAL; - goto out_unlock; - } - - sta = sta_info_get(local, sta_addr); - if (!sta) { - ieee80211_key_free(key); - err = -ENOENT; - goto out_unlock; - } - } - - if (alg == ALG_WEP && - key_len != LEN_WEP40 && key_len != LEN_WEP104) { - ieee80211_key_free(key); - err = -EINVAL; - goto out_unlock; - } - - ieee80211_key_link(key, sdata, sta); - - if (set_tx_key || (!sta && !sdata->default_key && key)) - ieee80211_set_default_key(sdata, idx); - if (alg == ALG_AES_CMAC && - (set_tx_key || (!sta && !sdata->default_mgmt_key && key))) - ieee80211_set_default_mgmt_key(sdata, idx); - } - - out_unlock: - rcu_read_unlock(); - - return err; -} - static int ieee80211_ioctl_siwgenie(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) @@ -131,11 +37,13 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, if (sdata->vif.type == NL80211_IFTYPE_STATION) { int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); - if (ret) + if (ret && ret != -EALREADY) return ret; sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; - ieee80211_sta_req_auth(sdata); + sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; + if (ret != -EALREADY) + ieee80211_sta_req_auth(sdata); return 0; } @@ -149,17 +57,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_CHANNEL_SEL; + 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_ADHOC) - sdata->u.ibss.flags |= - IEEE80211_IBSS_AUTO_CHANNEL_SEL; - else if (sdata->vif.type == NL80211_IFTYPE_STATION) + if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; @@ -183,8 +88,12 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, 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); - freq->m = local->hw.conf.channel->center_freq; + 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; @@ -195,15 +104,17 @@ 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; + 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--; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (data->flags) sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; @@ -215,10 +126,10 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, 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_ADHOC) - return ieee80211_ibss_set_ssid(sdata, ssid, len); + } return -EOPNOTSUPP; } @@ -229,9 +140,13 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, 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) { @@ -240,14 +155,6 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, } else data->flags = 0; return res; - } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - int res = ieee80211_ibss_get_ssid(sdata, ssid, &len); - if (res == 0) { - data->length = len; - data->flags = 1; - } else - data->flags = 0; - return res; } return -EOPNOTSUPP; @@ -258,9 +165,11 @@ 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; + 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); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { int ret; @@ -275,18 +184,9 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, 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_ADHOC) { - if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) - sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL | - IEEE80211_IBSS_AUTO_CHANNEL_SEL; - else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data)) - sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL; - else - sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_BSSID_SEL; - - return ieee80211_ibss_set_bssid(sdata, (u8 *) &ap_addr->sa_data); } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { /* * If it is necessary to update the WDS peer address @@ -312,9 +212,11 @@ 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; + 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); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { ap_addr->sa_family = ARPHRD_ETHER; @@ -322,13 +224,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, } else memset(&ap_addr->sa_data, 0, ETH_ALEN); return 0; - } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - if (sdata->u.ibss.state == IEEE80211_IBSS_MLME_JOINED) { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(&ap_addr->sa_data, sdata->u.ibss.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); @@ -411,334 +306,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, return 0; } -static int ieee80211_ioctl_siwtxpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_channel* chan = local->hw.conf.channel; - bool reconf = false; - u32 reconf_flags = 0; - int new_power_level; - - if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) - return -EINVAL; - if (data->txpower.flags & IW_TXPOW_RANGE) - return -EINVAL; - if (!chan) - return -EINVAL; - - /* only change when not disabling */ - if (!data->txpower.disabled) { - if (data->txpower.fixed) { - if (data->txpower.value < 0) - return -EINVAL; - new_power_level = data->txpower.value; - /* - * Debatable, but we cannot do a fixed power - * level above the regulatory constraint. - * Use "iwconfig wlan0 txpower 15dBm" instead. - */ - if (new_power_level > chan->max_power) - return -EINVAL; - } else { - /* - * Automatic power level setting, max being the value - * passed in from userland. - */ - if (data->txpower.value < 0) - new_power_level = -1; - else - new_power_level = data->txpower.value; - } - - reconf = true; - - /* - * ieee80211_hw_config() will limit to the channel's - * max power and possibly power constraint from AP. - */ - local->user_power_level = new_power_level; - } - - if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { - local->hw.conf.radio_enabled = !(data->txpower.disabled); - reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED; - ieee80211_led_radio(local, local->hw.conf.radio_enabled); - } - - if (reconf || reconf_flags) - ieee80211_hw_config(local, reconf_flags); - - return 0; -} - -static int ieee80211_ioctl_giwtxpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - data->txpower.fixed = 1; - data->txpower.disabled = !(local->hw.conf.radio_enabled); - data->txpower.value = local->hw.conf.power_level; - data->txpower.flags = IW_TXPOW_DBM; - - return 0; -} - -static int ieee80211_ioctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - if (rts->disabled) - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - else if (!rts->fixed) - /* if the rts value is not fixed, then take default */ - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) - return -EINVAL; - else - local->rts_threshold = rts->value; - - /* If the wlan card performs RTS/CTS in hardware/firmware, - * configure it here */ - - if (local->ops->set_rts_threshold) - local->ops->set_rts_threshold(local_to_hw(local), - local->rts_threshold); - - return 0; -} - -static int ieee80211_ioctl_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - rts->value = local->rts_threshold; - rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD); - rts->fixed = 1; - - return 0; -} - - -static int ieee80211_ioctl_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - if (frag->disabled) - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - else if (!frag->fixed) - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - else if (frag->value < 256 || - frag->value > IEEE80211_MAX_FRAG_THRESHOLD) - return -EINVAL; - else { - /* Fragment length must be even, so strip LSB. */ - local->fragmentation_threshold = frag->value & ~0x1; - } - - return 0; -} - -static int ieee80211_ioctl_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - frag->value = local->fragmentation_threshold; - frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD); - frag->fixed = 1; - - return 0; -} - - -static int ieee80211_ioctl_siwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *retry, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - if (retry->disabled || - (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) - return -EINVAL; - - if (retry->flags & IW_RETRY_MAX) { - local->hw.conf.long_frame_max_tx_count = retry->value; - } else if (retry->flags & IW_RETRY_MIN) { - local->hw.conf.short_frame_max_tx_count = retry->value; - } else { - local->hw.conf.long_frame_max_tx_count = retry->value; - local->hw.conf.short_frame_max_tx_count = retry->value; - } - - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); - - return 0; -} - - -static int ieee80211_ioctl_giwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *retry, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - retry->disabled = 0; - if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) { - /* first return min value, iwconfig will ask max value - * later if needed */ - retry->flags |= IW_RETRY_LIMIT; - retry->value = local->hw.conf.short_frame_max_tx_count; - if (local->hw.conf.long_frame_max_tx_count != - local->hw.conf.short_frame_max_tx_count) - retry->flags |= IW_RETRY_MIN; - return 0; - } - if (retry->flags & IW_RETRY_MAX) { - retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - retry->value = local->hw.conf.long_frame_max_tx_count; - } - - return 0; -} - -static int ieee80211_ioctl_siwmlme(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct ieee80211_sub_if_data *sdata; - struct iw_mlme *mlme = (struct iw_mlme *) extra; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (!(sdata->vif.type == NL80211_IFTYPE_STATION)) - return -EINVAL; - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); - case IW_MLME_DISASSOC: - /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_disassociate(sdata, mlme->reason_code); - default: - return -EOPNOTSUPP; - } -} - - -static int ieee80211_ioctl_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *keybuf) -{ - struct ieee80211_sub_if_data *sdata; - int idx, i, alg = ALG_WEP; - u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - int remove = 0, ret; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - idx = erq->flags & IW_ENCODE_INDEX; - if (idx == 0) { - if (sdata->default_key) - for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (sdata->default_key == sdata->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) { - /* No key data - just set the default TX key index */ - ieee80211_set_default_key(sdata, idx); - return 0; - } - - ret = ieee80211_set_encryption( - sdata, bcaddr, - idx, alg, remove, - !sdata->default_key, - keybuf, erq->length); - - if (!ret) { - if (remove) - sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED; - else - sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED; - } - - return ret; -} - - -static int ieee80211_ioctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - struct ieee80211_sub_if_data *sdata; - int idx, i; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - idx = erq->flags & IW_ENCODE_INDEX; - if (idx < 1 || idx > 4) { - idx = -1; - if (!sdata->default_key) - idx = 0; - else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (sdata->default_key == sdata->keys[i]) { - idx = i; - break; - } - } - if (idx < 0) - return -EINVAL; - } else - idx--; - - erq->flags = idx + 1; - - if (!sdata->keys[idx]) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - - memcpy(key, sdata->keys[idx]->conf.key, - min_t(int, erq->length, sdata->keys[idx]->conf.keylen)); - erq->length = sdata->keys[idx]->conf.keylen; - erq->flags |= IW_ENCODE_ENABLED; - - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - switch (sdata->u.mgd.auth_alg) { - case WLAN_AUTH_OPEN: - case WLAN_AUTH_LEAP: - erq->flags |= IW_ENCODE_OPEN; - break; - case WLAN_AUTH_SHARED_KEY: - erq->flags |= IW_ENCODE_RESTRICTED; - break; - } - } - - return 0; -} - static int ieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, @@ -747,7 +314,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, 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 ret = 0, timeout = 0; + int timeout = 0; bool ps; if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) @@ -779,42 +346,18 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, timeout = wrq->value / 1000; set: - if (ps == local->powersave && timeout == conf->dynamic_ps_timeout) - return ret; + if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout) + return 0; - local->powersave = ps; + sdata->u.mgd.powersave = ps; conf->dynamic_ps_timeout = timeout; if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)) - return ret; + ieee80211_recalc_ps(local, -1); - if (conf->dynamic_ps_timeout > 0 && - !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(conf->dynamic_ps_timeout)); - } else { - if (local->powersave) { - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - ieee80211_send_nullfunc(local, sdata, 1); - conf->flags |= IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); - } else { - conf->flags &= ~IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - ieee80211_send_nullfunc(local, sdata, 0); - del_timer_sync(&local->dynamic_ps_timer); - cancel_work_sync(&local->dynamic_ps_enable_work); - } - } - - return ret; + return 0; } static int ieee80211_ioctl_giwpower(struct net_device *dev, @@ -822,9 +365,9 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - wrqu->power.disabled = !local->powersave; + wrqu->power.disabled = !sdata->u.mgd.powersave; return 0; } @@ -997,82 +540,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev, } -static int ieee80211_ioctl_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *extra) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; - int uninitialized_var(alg), idx, i, remove = 0; - - switch (ext->alg) { - case IW_ENCODE_ALG_NONE: - remove = 1; - break; - case IW_ENCODE_ALG_WEP: - alg = ALG_WEP; - break; - case IW_ENCODE_ALG_TKIP: - alg = ALG_TKIP; - break; - case IW_ENCODE_ALG_CCMP: - alg = ALG_CCMP; - break; - case IW_ENCODE_ALG_AES_CMAC: - alg = ALG_AES_CMAC; - break; - default: - return -EOPNOTSUPP; - } - - if (erq->flags & IW_ENCODE_DISABLED) - remove = 1; - - idx = erq->flags & IW_ENCODE_INDEX; - if (alg == ALG_AES_CMAC) { - if (idx < NUM_DEFAULT_KEYS + 1 || - idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { - idx = -1; - if (!sdata->default_mgmt_key) - idx = 0; - else for (i = NUM_DEFAULT_KEYS; - i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS; - i++) { - if (sdata->default_mgmt_key == sdata->keys[i]) - { - idx = i; - break; - } - } - if (idx < 0) - return -EINVAL; - } else - idx--; - } else { - if (idx < 1 || idx > 4) { - idx = -1; - if (!sdata->default_key) - idx = 0; - else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (sdata->default_key == sdata->keys[i]) { - idx = i; - break; - } - } - if (idx < 0) - return -EINVAL; - } else - idx--; - } - - return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, - remove, - ext->ext_flags & - IW_ENCODE_EXT_SET_TX_KEY, - ext->key, ext->key_len); -} - - /* Structures to export the Wireless Handlers */ static const iw_handler ieee80211_handler[] = @@ -1099,7 +566,7 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* SIOCGIWTHRSPY */ (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */ + (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ @@ -1111,16 +578,16 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* -- hole -- */ (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ - (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ - (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */ - (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ - (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */ - (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ - (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ + (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 -- */ @@ -1129,7 +596,7 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* SIOCGIWGENIE */ (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ (iw_handler) NULL, /* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ (iw_handler) NULL, /* -- hole -- */ diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 0b8ad1f4ecdd..116a923b14d6 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -23,34 +23,6 @@ */ const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; -static const char llc_ip_hdr[8] = {0xAA, 0xAA, 0x3, 0, 0, 0, 0x08, 0}; - -/* Given a data frame determine the 802.1p/1d tag to use. */ -static unsigned int classify_1d(struct sk_buff *skb) -{ - unsigned int dscp; - - /* skb->priority values from 256->263 are magic values to - * directly indicate a specific 802.1d priority. This is used - * to allow 802.1d priority to be passed directly in from VLAN - * tags, etc. - */ - if (skb->priority >= 256 && skb->priority <= 263) - return skb->priority - 256; - - switch (skb->protocol) { - case htons(ETH_P_IP): - dscp = ip_hdr(skb)->tos & 0xfc; - break; - - default: - return 0; - } - - return dscp >> 5; -} - - static int wme_downgrade_ac(struct sk_buff *skb) { switch (skb->priority) { @@ -94,7 +66,7 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) /* use the data classifier to determine what 802.1d tag the * data frame has */ - skb->priority = classify_1d(skb); + skb->priority = cfg80211_classify8021d(skb); /* in case we are a client verify acm is not set for this ac */ while (unlikely(local->wmm_acm & BIT(skb->priority))) { @@ -129,11 +101,11 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) * Now we know the 1d priority, fill in the QoS header if * there is one (and we haven't done this before). */ - if (!skb->requeue && ieee80211_is_data_qos(hdr->frame_control)) { + if (ieee80211_is_data_qos(hdr->frame_control)) { u8 *p = ieee80211_get_qos_ctl(hdr); u8 ack_policy = 0; tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - if (local->wifi_wme_noack_test) + if (unlikely(local->wifi_wme_noack_test)) ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << QOS_CONTROL_ACK_POLICY_SHIFT; /* qos header is 2 bytes, second reserved */ diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 4f8bfea278f2..dcfae8884b86 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -122,7 +122,7 @@ 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); + (void *) skb->data, NULL); return RX_DROP_UNUSABLE; } diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c26a20c58dde..634d14affc8d 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -917,6 +917,19 @@ config NETFILTER_XT_MATCH_U32 Details and examples are in the kernel module source. +config NETFILTER_XT_MATCH_OSF + tristate '"osf" Passive OS fingerprint match' + depends on NETFILTER_ADVANCED && NETFILTER_NETLINK + help + This option selects the Passive OS Fingerprinting match module + that allows to passively match the remote operating system by + analyzing incoming TCP SYN packets. + + Rules and loading software can be downloaded from + http://www.ioremap.net/projects/osf + + To compile it as a module, choose M here. If unsure, say N. + endif # NETFILTER_XTABLES endmenu diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 6282060fbda9..49f62ee4e9ff 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o +obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index e01061f49cdc..7c1333c67ff3 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -3345,22 +3345,8 @@ static struct genl_ops ip_vs_genl_ops[] __read_mostly = { static int __init ip_vs_genl_register(void) { - int ret, i; - - ret = genl_register_family(&ip_vs_genl_family); - if (ret) - return ret; - - for (i = 0; i < ARRAY_SIZE(ip_vs_genl_ops); i++) { - ret = genl_register_ops(&ip_vs_genl_family, &ip_vs_genl_ops[i]); - if (ret) - goto err_out; - } - return 0; - -err_out: - genl_unregister_family(&ip_vs_genl_family); - return ret; + return genl_register_family_with_ops(&ip_vs_genl_family, + ip_vs_genl_ops, ARRAY_SIZE(ip_vs_genl_ops)); } static void ip_vs_genl_unregister(void) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 425ab144f15d..5874657af7f2 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -260,8 +260,8 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, ip_send_check(ip_hdr(skb)); /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; @@ -324,8 +324,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, } /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; @@ -388,8 +388,8 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error_put; /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* mangle the packet */ if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp)) @@ -465,8 +465,8 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error_put; /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* mangle the packet */ if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp)) @@ -553,8 +553,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, IP_VS_DBG_RL("ip_vs_tunnel_xmit(): mtu less than 68\n"); goto tx_error; } - if (skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); df |= (old_iph->frag_off & htons(IP_DF)); @@ -596,8 +596,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* * Push down and install the IPIP header. @@ -665,8 +665,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, IP_VS_DBG_RL("ip_vs_tunnel_xmit_v6(): mtu less than 1280\n"); goto tx_error; } - if (skb->dst) - skb->dst->ops->update_pmtu(skb->dst, mtu); + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr)) { icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); @@ -702,8 +702,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* * Push down and install the IPIP header. @@ -775,8 +775,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, ip_send_check(ip_hdr(skb)); /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; @@ -828,8 +828,8 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, } /* drop old route */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; @@ -900,8 +900,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error_put; /* drop the old route when skb is not shared */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); ip_vs_nat_icmp(skb, pp, cp, 0); @@ -975,8 +975,8 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error_put; /* drop the old route when skb is not shared */ - dst_release(skb->dst); - skb->dst = &rt->u.dst; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->u.dst); ip_vs_nat_icmp_v6(skb, pp, cp, 0); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 8020db6274b8..5f72b94b4918 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -182,10 +183,6 @@ destroy_conntrack(struct nf_conntrack *nfct) NF_CT_ASSERT(atomic_read(&nfct->use) == 0); NF_CT_ASSERT(!timer_pending(&ct->timeout)); - if (!test_bit(IPS_DYING_BIT, &ct->status)) - nf_conntrack_event(IPCT_DESTROY, ct); - set_bit(IPS_DYING_BIT, &ct->status); - /* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to nf_conntrack_lock!!! -HW */ @@ -219,27 +216,70 @@ destroy_conntrack(struct nf_conntrack *nfct) nf_conntrack_free(ct); } -static void death_by_timeout(unsigned long ul_conntrack) +void nf_ct_delete_from_lists(struct nf_conn *ct) { - struct nf_conn *ct = (void *)ul_conntrack; struct net *net = nf_ct_net(ct); - struct nf_conn_help *help = nfct_help(ct); - struct nf_conntrack_helper *helper; - - if (help) { - rcu_read_lock(); - helper = rcu_dereference(help->helper); - if (helper && helper->destroy) - helper->destroy(ct); - rcu_read_unlock(); - } + nf_ct_helper_destroy(ct); spin_lock_bh(&nf_conntrack_lock); /* Inside lock so preempt is disabled on module removal path. * Otherwise we can get spurious warnings. */ NF_CT_STAT_INC(net, delete_list); clean_from_lists(ct); spin_unlock_bh(&nf_conntrack_lock); +} +EXPORT_SYMBOL_GPL(nf_ct_delete_from_lists); + +static void death_by_event(unsigned long ul_conntrack) +{ + struct nf_conn *ct = (void *)ul_conntrack; + struct net *net = nf_ct_net(ct); + + if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { + /* bad luck, let's retry again */ + ct->timeout.expires = jiffies + + (random32() % net->ct.sysctl_events_retry_timeout); + add_timer(&ct->timeout); + return; + } + /* we've got the event delivered, now it's dying */ + set_bit(IPS_DYING_BIT, &ct->status); + spin_lock(&nf_conntrack_lock); + hlist_nulls_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); + spin_unlock(&nf_conntrack_lock); + nf_ct_put(ct); +} + +void nf_ct_insert_dying_list(struct nf_conn *ct) +{ + struct net *net = nf_ct_net(ct); + + /* add this conntrack to the dying list */ + spin_lock_bh(&nf_conntrack_lock); + hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, + &net->ct.dying); + spin_unlock_bh(&nf_conntrack_lock); + /* set a new timer to retry event delivery */ + setup_timer(&ct->timeout, death_by_event, (unsigned long)ct); + ct->timeout.expires = jiffies + + (random32() % net->ct.sysctl_events_retry_timeout); + add_timer(&ct->timeout); +} +EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); + +static void death_by_timeout(unsigned long ul_conntrack) +{ + struct nf_conn *ct = (void *)ul_conntrack; + + if (!test_bit(IPS_DYING_BIT, &ct->status) && + unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) { + /* destroy event was not delivered */ + nf_ct_delete_from_lists(ct); + nf_ct_insert_dying_list(ct); + return; + } + set_bit(IPS_DYING_BIT, &ct->status); + nf_ct_delete_from_lists(ct); nf_ct_put(ct); } @@ -398,11 +438,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) help = nfct_help(ct); if (help && help->helper) nf_conntrack_event_cache(IPCT_HELPER, ct); -#ifdef CONFIG_NF_NAT_NEEDED - if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || - test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) - nf_conntrack_event_cache(IPCT_NATINFO, ct); -#endif + nf_conntrack_event_cache(master_ct(ct) ? IPCT_RELATED : IPCT_NEW, ct); return NF_ACCEPT; @@ -523,6 +559,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, return ERR_PTR(-ENOMEM); } + spin_lock_init(&ct->lock); atomic_set(&ct->ct_general.use, 1); ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; @@ -580,6 +617,7 @@ init_conntrack(struct net *net, } nf_ct_acct_ext_add(ct, GFP_ATOMIC); + nf_ct_ecache_ext_add(ct, GFP_ATOMIC); spin_lock_bh(&nf_conntrack_lock); exp = nf_ct_find_expectation(net, tuple); @@ -807,13 +845,9 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, unsigned long extra_jiffies, int do_acct) { - int event = 0; - NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); NF_CT_ASSERT(skb); - spin_lock_bh(&nf_conntrack_lock); - /* Only update if this is not a fixed timeout */ if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) goto acct; @@ -821,19 +855,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, /* If not in hash table, timer will not be active yet */ if (!nf_ct_is_confirmed(ct)) { ct->timeout.expires = extra_jiffies; - event = IPCT_REFRESH; } else { unsigned long newtime = jiffies + extra_jiffies; /* Only update the timeout if the new timeout is at least HZ jiffies from the old timeout. Need del_timer for race avoidance (may already be dying). */ - if (newtime - ct->timeout.expires >= HZ - && del_timer(&ct->timeout)) { - ct->timeout.expires = newtime; - add_timer(&ct->timeout); - event = IPCT_REFRESH; - } + if (newtime - ct->timeout.expires >= HZ) + mod_timer_pending(&ct->timeout, newtime); } acct: @@ -842,17 +871,13 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, acct = nf_conn_acct_find(ct); if (acct) { + spin_lock_bh(&ct->lock); acct[CTINFO2DIR(ctinfo)].packets++; acct[CTINFO2DIR(ctinfo)].bytes += skb->len - skb_network_offset(skb); + spin_unlock_bh(&ct->lock); } } - - spin_unlock_bh(&nf_conntrack_lock); - - /* must be unlocked when calling event cache */ - if (event) - nf_conntrack_event_cache(event, ct); } EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct); @@ -864,14 +889,14 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, if (do_acct) { struct nf_conn_counter *acct; - spin_lock_bh(&nf_conntrack_lock); acct = nf_conn_acct_find(ct); if (acct) { + spin_lock_bh(&ct->lock); acct[CTINFO2DIR(ctinfo)].packets++; acct[CTINFO2DIR(ctinfo)].bytes += skb->len - skb_network_offset(skb); + spin_unlock_bh(&ct->lock); } - spin_unlock_bh(&nf_conntrack_lock); } if (del_timer(&ct->timeout)) { @@ -1001,15 +1026,22 @@ struct __nf_ct_flush_report { int report; }; -static int kill_all(struct nf_conn *i, void *data) +static int kill_report(struct nf_conn *i, void *data) { struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data; - /* get_next_corpse sets the dying bit for us */ - nf_conntrack_event_report(IPCT_DESTROY, - i, - fr->pid, - fr->report); + /* If we fail to deliver the event, death_by_timeout() will retry */ + if (nf_conntrack_event_report(IPCT_DESTROY, i, + fr->pid, fr->report) < 0) + return 1; + + /* Avoid the delivery of the destroy event in death_by_timeout(). */ + set_bit(IPS_DYING_BIT, &i->status); + return 1; +} + +static int kill_all(struct nf_conn *i, void *data) +{ return 1; } @@ -1023,15 +1055,30 @@ void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size) } EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); -void nf_conntrack_flush(struct net *net, u32 pid, int report) +void nf_conntrack_flush_report(struct net *net, u32 pid, int report) { struct __nf_ct_flush_report fr = { .pid = pid, .report = report, }; - nf_ct_iterate_cleanup(net, kill_all, &fr); + nf_ct_iterate_cleanup(net, kill_report, &fr); +} +EXPORT_SYMBOL_GPL(nf_conntrack_flush_report); + +static void nf_ct_release_dying_list(void) +{ + struct nf_conntrack_tuple_hash *h; + struct nf_conn *ct; + struct hlist_nulls_node *n; + + spin_lock_bh(&nf_conntrack_lock); + hlist_nulls_for_each_entry(h, n, &init_net.ct.dying, hnnode) { + ct = nf_ct_tuplehash_to_ctrack(h); + /* never fails to remove them, no listeners at this point */ + nf_ct_kill(ct); + } + spin_unlock_bh(&nf_conntrack_lock); } -EXPORT_SYMBOL_GPL(nf_conntrack_flush); static void nf_conntrack_cleanup_init_net(void) { @@ -1042,10 +1089,9 @@ static void nf_conntrack_cleanup_init_net(void) static void nf_conntrack_cleanup_net(struct net *net) { - nf_ct_event_cache_flush(net); - nf_conntrack_ecache_fini(net); i_see_dead_people: - nf_conntrack_flush(net, 0, 0); + nf_ct_iterate_cleanup(net, kill_all, NULL); + nf_ct_release_dying_list(); if (atomic_read(&net->ct.count) != 0) { schedule(); goto i_see_dead_people; @@ -1056,6 +1102,7 @@ static void nf_conntrack_cleanup_net(struct net *net) nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, nf_conntrack_htable_size); + nf_conntrack_ecache_fini(net); nf_conntrack_acct_fini(net); nf_conntrack_expect_fini(net); free_percpu(net->ct.stat); @@ -1226,14 +1273,12 @@ static int nf_conntrack_init_net(struct net *net) atomic_set(&net->ct.count, 0); INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, 0); + INIT_HLIST_NULLS_HEAD(&net->ct.dying, 0); net->ct.stat = alloc_percpu(struct ip_conntrack_stat); if (!net->ct.stat) { ret = -ENOMEM; goto err_stat; } - ret = nf_conntrack_ecache_init(net); - if (ret < 0) - goto err_ecache; net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, &net->ct.hash_vmalloc, 1); if (!net->ct.hash) { @@ -1247,6 +1292,9 @@ static int nf_conntrack_init_net(struct net *net) ret = nf_conntrack_acct_init(net); if (ret < 0) goto err_acct; + ret = nf_conntrack_ecache_init(net); + if (ret < 0) + goto err_ecache; /* Set up fake conntrack: - to never be deleted, not in any hashes */ @@ -1259,14 +1307,14 @@ static int nf_conntrack_init_net(struct net *net) return 0; +err_ecache: + nf_conntrack_acct_fini(net); err_acct: nf_conntrack_expect_fini(net); err_expect: nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, nf_conntrack_htable_size); err_hash: - nf_conntrack_ecache_fini(net); -err_ecache: free_percpu(net->ct.stat); err_stat: return ret; diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index dee4190209cc..aee560b4768d 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -16,121 +16,245 @@ #include #include #include -#include #include #include #include #include +#include -ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); -EXPORT_SYMBOL_GPL(nf_conntrack_chain); +static DEFINE_MUTEX(nf_ct_ecache_mutex); -ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain); -EXPORT_SYMBOL_GPL(nf_ct_expect_chain); +struct nf_ct_event_notifier *nf_conntrack_event_cb __read_mostly; +EXPORT_SYMBOL_GPL(nf_conntrack_event_cb); + +struct nf_exp_event_notifier *nf_expect_event_cb __read_mostly; +EXPORT_SYMBOL_GPL(nf_expect_event_cb); /* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ -static inline void -__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) +void nf_ct_deliver_cached_events(struct nf_conn *ct) { - if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) - && ecache->events) { + unsigned long events; + struct nf_ct_event_notifier *notify; + struct nf_conntrack_ecache *e; + + rcu_read_lock(); + notify = rcu_dereference(nf_conntrack_event_cb); + if (notify == NULL) + goto out_unlock; + + e = nf_ct_ecache_find(ct); + if (e == NULL) + goto out_unlock; + + events = xchg(&e->cache, 0); + + if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct) && events) { struct nf_ct_event item = { - .ct = ecache->ct, + .ct = ct, .pid = 0, .report = 0 }; + int ret; + /* We make a copy of the missed event cache without taking + * the lock, thus we may send missed events twice. However, + * this does not harm and it happens very rarely. */ + unsigned long missed = e->missed; - atomic_notifier_call_chain(&nf_conntrack_chain, - ecache->events, - &item); + ret = notify->fcn(events | missed, &item); + if (unlikely(ret < 0 || missed)) { + spin_lock_bh(&ct->lock); + if (ret < 0) + e->missed |= events; + else + e->missed &= ~missed; + spin_unlock_bh(&ct->lock); + } } - ecache->events = 0; - nf_ct_put(ecache->ct); - ecache->ct = NULL; -} - -/* Deliver all cached events for a particular conntrack. This is called - * by code prior to async packet handling for freeing the skb */ -void nf_ct_deliver_cached_events(const struct nf_conn *ct) -{ - struct net *net = nf_ct_net(ct); - struct nf_conntrack_ecache *ecache; - - local_bh_disable(); - ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id()); - if (ecache->ct == ct) - __nf_ct_deliver_cached_events(ecache); - local_bh_enable(); +out_unlock: + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); -/* Deliver cached events for old pending events, if current conntrack != old */ -void __nf_ct_event_cache_init(struct nf_conn *ct) +int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new) { - struct net *net = nf_ct_net(ct); - struct nf_conntrack_ecache *ecache; + int ret = 0; + struct nf_ct_event_notifier *notify; - /* take care of delivering potentially old events */ - ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id()); - BUG_ON(ecache->ct == ct); - if (ecache->ct) - __nf_ct_deliver_cached_events(ecache); - /* initialize for this conntrack/packet */ - ecache->ct = ct; - nf_conntrack_get(&ct->ct_general); -} -EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init); - -/* flush the event cache - touches other CPU's data and must not be called - * while packets are still passing through the code */ -void nf_ct_event_cache_flush(struct net *net) -{ - struct nf_conntrack_ecache *ecache; - int cpu; - - for_each_possible_cpu(cpu) { - ecache = per_cpu_ptr(net->ct.ecache, cpu); - if (ecache->ct) - nf_ct_put(ecache->ct); + mutex_lock(&nf_ct_ecache_mutex); + notify = rcu_dereference(nf_conntrack_event_cb); + if (notify != NULL) { + ret = -EBUSY; + goto out_unlock; } + rcu_assign_pointer(nf_conntrack_event_cb, new); + mutex_unlock(&nf_ct_ecache_mutex); + return ret; + +out_unlock: + mutex_unlock(&nf_ct_ecache_mutex); + return ret; } +EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); + +void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new) +{ + struct nf_ct_event_notifier *notify; + + mutex_lock(&nf_ct_ecache_mutex); + notify = rcu_dereference(nf_conntrack_event_cb); + BUG_ON(notify != new); + rcu_assign_pointer(nf_conntrack_event_cb, NULL); + mutex_unlock(&nf_ct_ecache_mutex); +} +EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); + +int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new) +{ + int ret = 0; + struct nf_exp_event_notifier *notify; + + mutex_lock(&nf_ct_ecache_mutex); + notify = rcu_dereference(nf_expect_event_cb); + if (notify != NULL) { + ret = -EBUSY; + goto out_unlock; + } + rcu_assign_pointer(nf_expect_event_cb, new); + mutex_unlock(&nf_ct_ecache_mutex); + return ret; + +out_unlock: + mutex_unlock(&nf_ct_ecache_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); + +void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new) +{ + struct nf_exp_event_notifier *notify; + + mutex_lock(&nf_ct_ecache_mutex); + notify = rcu_dereference(nf_expect_event_cb); + BUG_ON(notify != new); + rcu_assign_pointer(nf_expect_event_cb, NULL); + mutex_unlock(&nf_ct_ecache_mutex); +} +EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); + +#define NF_CT_EVENTS_DEFAULT 1 +static int nf_ct_events __read_mostly = NF_CT_EVENTS_DEFAULT; +static int nf_ct_events_retry_timeout __read_mostly = 15*HZ; + +#ifdef CONFIG_SYSCTL +static struct ctl_table event_sysctl_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "nf_conntrack_events", + .data = &init_net.ct.sysctl_events, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "nf_conntrack_events_retry_timeout", + .data = &init_net.ct.sysctl_events_retry_timeout, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + {} +}; +#endif /* CONFIG_SYSCTL */ + +static struct nf_ct_ext_type event_extend __read_mostly = { + .len = sizeof(struct nf_conntrack_ecache), + .align = __alignof__(struct nf_conntrack_ecache), + .id = NF_CT_EXT_ECACHE, +}; + +#ifdef CONFIG_SYSCTL +static int nf_conntrack_event_init_sysctl(struct net *net) +{ + struct ctl_table *table; + + table = kmemdup(event_sysctl_table, sizeof(event_sysctl_table), + GFP_KERNEL); + if (!table) + goto out; + + table[0].data = &net->ct.sysctl_events; + table[1].data = &net->ct.sysctl_events_retry_timeout; + + net->ct.event_sysctl_header = + register_net_sysctl_table(net, + nf_net_netfilter_sysctl_path, table); + if (!net->ct.event_sysctl_header) { + printk(KERN_ERR "nf_ct_event: can't register to sysctl.\n"); + goto out_register; + } + return 0; + +out_register: + kfree(table); +out: + return -ENOMEM; +} + +static void nf_conntrack_event_fini_sysctl(struct net *net) +{ + struct ctl_table *table; + + table = net->ct.event_sysctl_header->ctl_table_arg; + unregister_net_sysctl_table(net->ct.event_sysctl_header); + kfree(table); +} +#else +static int nf_conntrack_event_init_sysctl(struct net *net) +{ + return 0; +} + +static void nf_conntrack_event_fini_sysctl(struct net *net) +{ +} +#endif /* CONFIG_SYSCTL */ int nf_conntrack_ecache_init(struct net *net) { - net->ct.ecache = alloc_percpu(struct nf_conntrack_ecache); - if (!net->ct.ecache) - return -ENOMEM; + int ret; + + net->ct.sysctl_events = nf_ct_events; + net->ct.sysctl_events_retry_timeout = nf_ct_events_retry_timeout; + + if (net_eq(net, &init_net)) { + ret = nf_ct_extend_register(&event_extend); + if (ret < 0) { + printk(KERN_ERR "nf_ct_event: Unable to register " + "event extension.\n"); + goto out_extend_register; + } + } + + ret = nf_conntrack_event_init_sysctl(net); + if (ret < 0) + goto out_sysctl; + return 0; + +out_sysctl: + if (net_eq(net, &init_net)) + nf_ct_extend_unregister(&event_extend); +out_extend_register: + return ret; } void nf_conntrack_ecache_fini(struct net *net) { - free_percpu(net->ct.ecache); + nf_conntrack_event_fini_sysctl(net); + if (net_eq(net, &init_net)) + nf_ct_extend_unregister(&event_extend); } - -int nf_conntrack_register_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&nf_conntrack_chain, nb); -} -EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); - -int nf_conntrack_unregister_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb); -} -EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); - -int nf_ct_expect_register_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&nf_ct_expect_chain, nb); -} -EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); - -int nf_ct_expect_unregister_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb); -} -EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 00fecc385f9b..5509dd1f14cf 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -338,11 +338,9 @@ static void update_nl_seq(struct nf_conn *ct, u32 nl_seq, if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) { info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq; - nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, ct); } else if (oldest != NUM_SEQ_TO_REMEMBER && after(nl_seq, info->seq_aft_nl[dir][oldest])) { info->seq_aft_nl[dir][oldest] = nl_seq; - nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, ct); } } diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 0fa5a422959f..65c2a7bc3afc 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -136,6 +136,20 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i, return 0; } +void nf_ct_helper_destroy(struct nf_conn *ct) +{ + struct nf_conn_help *help = nfct_help(ct); + struct nf_conntrack_helper *helper; + + if (help) { + rcu_read_lock(); + helper = rcu_dereference(help->helper); + if (helper && helper->destroy) + helper->destroy(ct); + rcu_read_unlock(); + } +} + int nf_conntrack_helper_register(struct nf_conntrack_helper *me) { unsigned int h = helper_hash(&me->tuple); diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 8a3875e36ec2..497b2224536f 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -48,7 +48,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, { struct nf_conntrack_expect *exp; struct iphdr *iph = ip_hdr(skb); - struct rtable *rt = skb->rtable; + struct rtable *rt = skb_rtable(skb); struct in_device *in_dev; __be32 mask = 0; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c523f0b8cee5..49479d194570 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -144,7 +143,7 @@ ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct) } static inline int -ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct) +ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct) { struct nf_conntrack_l4proto *l4proto; struct nlattr *nest_proto; @@ -346,23 +345,21 @@ ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) return -1; } -#define tuple(ct, dir) (&(ct)->tuplehash[dir].tuple) - static int ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, - int event, int nowait, - const struct nf_conn *ct) + int event, struct nf_conn *ct) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; struct nlattr *nest_parms; - unsigned char *b = skb_tail_pointer(skb); + unsigned int flags = pid ? NLM_F_MULTI : 0; event |= NFNL_SUBSYS_CTNETLINK << 8; - nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg)); - nfmsg = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); + if (nlh == NULL) + goto nlmsg_failure; - nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0; + nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = nf_ct_l3num(ct); nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; @@ -370,14 +367,14 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; - if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) + if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) goto nla_put_failure; nla_nest_end(skb, nest_parms); nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; - if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0) + if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0) goto nla_put_failure; nla_nest_end(skb, nest_parms); @@ -395,132 +392,109 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, ctnetlink_dump_nat_seq_adj(skb, ct) < 0) goto nla_put_failure; - nlh->nlmsg_len = skb_tail_pointer(skb) - b; + nlmsg_end(skb, nlh); return skb->len; nlmsg_failure: nla_put_failure: - nlmsg_trim(skb, b); + nlmsg_cancel(skb, nlh); return -1; } #ifdef CONFIG_NF_CONNTRACK_EVENTS -/* - * The general structure of a ctnetlink event is - * - * CTA_TUPLE_ORIG - * - * CTA_TUPLE_REPLY - * - * CTA_ID - * ... - * CTA_PROTOINFO - * - * CTA_TUPLE_MASTER - * - * - * Therefore the formular is - * - * size = sizeof(headers) + sizeof(generic_nlas) + 3 * sizeof(tuple_nlas) - * + sizeof(protoinfo_nlas) - */ -static struct sk_buff * -ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp) +static inline size_t +ctnetlink_proto_size(const struct nf_conn *ct) { struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; - int len; - -#define NLA_TYPE_SIZE(type) nla_total_size(sizeof(type)) - - /* proto independant part */ - len = NLMSG_SPACE(sizeof(struct nfgenmsg)) - + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ - + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ - + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ - + 3 * NLA_TYPE_SIZE(u_int8_t) /* CTA_PROTO_NUM */ - + NLA_TYPE_SIZE(u_int32_t) /* CTA_ID */ - + NLA_TYPE_SIZE(u_int32_t) /* CTA_STATUS */ -#ifdef CONFIG_NF_CT_ACCT - + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ - + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_PACKETS */ - + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_BYTES */ -#endif - + NLA_TYPE_SIZE(u_int32_t) /* CTA_TIMEOUT */ - + nla_total_size(0) /* CTA_PROTOINFO */ - + nla_total_size(0) /* CTA_HELP */ - + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ -#ifdef CONFIG_NF_CONNTRACK_SECMARK - + NLA_TYPE_SIZE(u_int32_t) /* CTA_SECMARK */ -#endif -#ifdef CONFIG_NF_NAT_NEEDED - + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ - + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_POS */ - + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_BEFORE */ - + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_AFTER */ -#endif -#ifdef CONFIG_NF_CONNTRACK_MARK - + NLA_TYPE_SIZE(u_int32_t) /* CTA_MARK */ -#endif - ; - -#undef NLA_TYPE_SIZE + size_t len = 0; rcu_read_lock(); - l3proto = __nf_ct_l3proto_find(tuple->src.l3num); + l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); len += l3proto->nla_size; - l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); + l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); len += l4proto->nla_size; rcu_read_unlock(); - return alloc_skb(len, gfp); + return len; } -static int ctnetlink_conntrack_event(struct notifier_block *this, - unsigned long events, void *ptr) +static inline size_t +ctnetlink_nlmsg_size(const struct nf_conn *ct) +{ + return NLMSG_ALIGN(sizeof(struct nfgenmsg)) + + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ + + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ + + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ + + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */ + + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */ + + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */ +#ifdef CONFIG_NF_CT_ACCT + + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ + + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */ + + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */ +#endif + + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */ + + nla_total_size(0) /* CTA_PROTOINFO */ + + nla_total_size(0) /* CTA_HELP */ + + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ +#ifdef CONFIG_NF_CONNTRACK_SECMARK + + nla_total_size(sizeof(u_int32_t)) /* CTA_SECMARK */ +#endif +#ifdef CONFIG_NF_NAT_NEEDED + + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ + + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */ +#endif +#ifdef CONFIG_NF_CONNTRACK_MARK + + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */ +#endif + + ctnetlink_proto_size(ct) + ; +} + +static int +ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; struct nlattr *nest_parms; - struct nf_ct_event *item = (struct nf_ct_event *)ptr; struct nf_conn *ct = item->ct; struct sk_buff *skb; unsigned int type; - sk_buff_data_t b; unsigned int flags = 0, group; + int err; /* ignore our fake conntrack entry */ if (ct == &nf_conntrack_untracked) - return NOTIFY_DONE; + return 0; - if (events & IPCT_DESTROY) { + if (events & (1 << IPCT_DESTROY)) { type = IPCTNL_MSG_CT_DELETE; group = NFNLGRP_CONNTRACK_DESTROY; - } else if (events & (IPCT_NEW | IPCT_RELATED)) { + } else if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) { type = IPCTNL_MSG_CT_NEW; flags = NLM_F_CREATE|NLM_F_EXCL; group = NFNLGRP_CONNTRACK_NEW; - } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) { + } else if (events) { type = IPCTNL_MSG_CT_NEW; group = NFNLGRP_CONNTRACK_UPDATE; } else - return NOTIFY_DONE; + return 0; if (!item->report && !nfnetlink_has_listeners(group)) - return NOTIFY_DONE; + return 0; - skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC); - if (!skb) + skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); + if (skb == NULL) goto errout; - b = skb->tail; - type |= NFNL_SUBSYS_CTNETLINK << 8; - nlh = NLMSG_PUT(skb, item->pid, 0, type, sizeof(struct nfgenmsg)); - nfmsg = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, item->pid, 0, type, sizeof(*nfmsg), flags); + if (nlh == NULL) + goto nlmsg_failure; - nlh->nlmsg_flags = flags; + nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = nf_ct_l3num(ct); nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; @@ -529,14 +503,14 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; - if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) + if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0) goto nla_put_failure; nla_nest_end(skb, nest_parms); nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; - if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0) + if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0) goto nla_put_failure; nla_nest_end(skb, nest_parms); @@ -546,7 +520,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, if (ctnetlink_dump_status(skb, ct) < 0) goto nla_put_failure; - if (events & IPCT_DESTROY) { + if (events & (1 << IPCT_DESTROY)) { if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) goto nla_put_failure; @@ -554,47 +528,51 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, if (ctnetlink_dump_timeout(skb, ct) < 0) goto nla_put_failure; - if (events & IPCT_PROTOINFO + if (events & (1 << IPCT_PROTOINFO) && ctnetlink_dump_protoinfo(skb, ct) < 0) goto nla_put_failure; - if ((events & IPCT_HELPER || nfct_help(ct)) + if ((events & (1 << IPCT_HELPER) || nfct_help(ct)) && ctnetlink_dump_helpinfo(skb, ct) < 0) goto nla_put_failure; #ifdef CONFIG_NF_CONNTRACK_SECMARK - if ((events & IPCT_SECMARK || ct->secmark) + if ((events & (1 << IPCT_SECMARK) || ct->secmark) && ctnetlink_dump_secmark(skb, ct) < 0) goto nla_put_failure; #endif - if (events & IPCT_RELATED && + if (events & (1 << IPCT_RELATED) && ctnetlink_dump_master(skb, ct) < 0) goto nla_put_failure; - if (events & IPCT_NATSEQADJ && + if (events & (1 << IPCT_NATSEQADJ) && ctnetlink_dump_nat_seq_adj(skb, ct) < 0) goto nla_put_failure; } #ifdef CONFIG_NF_CONNTRACK_MARK - if ((events & IPCT_MARK || ct->mark) + if ((events & (1 << IPCT_MARK) || ct->mark) && ctnetlink_dump_mark(skb, ct) < 0) goto nla_put_failure; #endif rcu_read_unlock(); - nlh->nlmsg_len = skb->tail - b; - nfnetlink_send(skb, item->pid, group, item->report); - return NOTIFY_DONE; + nlmsg_end(skb, nlh); + err = nfnetlink_send(skb, item->pid, group, item->report, GFP_ATOMIC); + if (err == -ENOBUFS || err == -EAGAIN) + return -ENOBUFS; + + return 0; nla_put_failure: rcu_read_unlock(); + nlmsg_cancel(skb, nlh); nlmsg_failure: kfree_skb(skb); errout: nfnetlink_set_err(0, group, -ENOBUFS); - return NOTIFY_DONE; + return 0; } #endif /* CONFIG_NF_CONNTRACK_EVENTS */ @@ -611,7 +589,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) struct nf_conn *ct, *last; struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; - struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); + struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; rcu_read_lock(); @@ -637,8 +615,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) } if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, - IPCTNL_MSG_CT_NEW, - 1, ct) < 0) { + IPCTNL_MSG_CT_NEW, ct) < 0) { cb->args[1] = (unsigned long)ct; goto out; } @@ -792,7 +769,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; struct nf_conn *ct; - struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; int err = 0; @@ -802,9 +779,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3); else { /* Flush the whole table */ - nf_conntrack_flush(&init_net, - NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + nf_conntrack_flush_report(&init_net, + NETLINK_CB(skb).pid, + nlmsg_report(nlh)); return 0; } @@ -825,10 +802,15 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, } } - nf_conntrack_event_report(IPCT_DESTROY, - ct, - NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + if (nf_conntrack_event_report(IPCT_DESTROY, ct, + NETLINK_CB(skb).pid, + nlmsg_report(nlh)) < 0) { + nf_ct_delete_from_lists(ct); + /* we failed to report the event, try later */ + nf_ct_insert_dying_list(ct); + nf_ct_put(ct); + return 0; + } /* death_by_timeout would report the event again */ set_bit(IPS_DYING_BIT, &ct->status); @@ -847,7 +829,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, struct nf_conntrack_tuple tuple; struct nf_conn *ct; struct sk_buff *skb2 = NULL; - struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; int err = 0; @@ -872,15 +854,15 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ct = nf_ct_tuplehash_to_ctrack(h); err = -ENOMEM; - skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb2) { + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (skb2 == NULL) { nf_ct_put(ct); return -ENOMEM; } rcu_read_lock(); err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, - IPCTNL_MSG_CT_NEW, 1, ct); + IPCTNL_MSG_CT_NEW, ct); rcu_read_unlock(); nf_ct_put(ct); if (err <= 0) @@ -1280,6 +1262,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[], } nf_ct_acct_ext_add(ct, GFP_ATOMIC); + nf_ct_ecache_ext_add(ct, GFP_ATOMIC); #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK]) @@ -1325,7 +1308,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, { struct nf_conntrack_tuple otuple, rtuple; struct nf_conntrack_tuple_hash *h = NULL; - struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; int err = 0; @@ -1367,13 +1350,13 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, else events = IPCT_NEW; - nf_conntrack_event_report(IPCT_STATUS | - IPCT_HELPER | - IPCT_PROTOINFO | - IPCT_NATSEQADJ | - IPCT_MARK | events, - ct, NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + nf_conntrack_eventmask_report((1 << IPCT_STATUS) | + (1 << IPCT_HELPER) | + (1 << IPCT_PROTOINFO) | + (1 << IPCT_NATSEQADJ) | + (1 << IPCT_MARK) | events, + ct, NETLINK_CB(skb).pid, + nlmsg_report(nlh)); nf_ct_put(ct); } else spin_unlock_bh(&nf_conntrack_lock); @@ -1392,13 +1375,13 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err == 0) { nf_conntrack_get(&ct->ct_general); spin_unlock_bh(&nf_conntrack_lock); - nf_conntrack_event_report(IPCT_STATUS | - IPCT_HELPER | - IPCT_PROTOINFO | - IPCT_NATSEQADJ | - IPCT_MARK, - ct, NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + nf_conntrack_eventmask_report((1 << IPCT_STATUS) | + (1 << IPCT_HELPER) | + (1 << IPCT_PROTOINFO) | + (1 << IPCT_NATSEQADJ) | + (1 << IPCT_MARK), + ct, NETLINK_CB(skb).pid, + nlmsg_report(nlh)); nf_ct_put(ct); } else spin_unlock_bh(&nf_conntrack_lock); @@ -1503,19 +1486,18 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, static int ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq, - int event, - int nowait, - const struct nf_conntrack_expect *exp) + int event, const struct nf_conntrack_expect *exp) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; - unsigned char *b = skb_tail_pointer(skb); + unsigned int flags = pid ? NLM_F_MULTI : 0; event |= NFNL_SUBSYS_CTNETLINK_EXP << 8; - nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg)); - nfmsg = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); + if (nlh == NULL) + goto nlmsg_failure; - nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0; + nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = exp->tuple.src.l3num; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; @@ -1523,49 +1505,46 @@ ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq, if (ctnetlink_exp_dump_expect(skb, exp) < 0) goto nla_put_failure; - nlh->nlmsg_len = skb_tail_pointer(skb) - b; + nlmsg_end(skb, nlh); return skb->len; nlmsg_failure: nla_put_failure: - nlmsg_trim(skb, b); + nlmsg_cancel(skb, nlh); return -1; } #ifdef CONFIG_NF_CONNTRACK_EVENTS -static int ctnetlink_expect_event(struct notifier_block *this, - unsigned long events, void *ptr) +static int +ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) { struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; - struct nf_exp_event *item = (struct nf_exp_event *)ptr; struct nf_conntrack_expect *exp = item->exp; struct sk_buff *skb; unsigned int type; - sk_buff_data_t b; int flags = 0; - if (events & IPEXP_NEW) { + if (events & (1 << IPEXP_NEW)) { type = IPCTNL_MSG_EXP_NEW; flags = NLM_F_CREATE|NLM_F_EXCL; } else - return NOTIFY_DONE; + return 0; if (!item->report && !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) - return NOTIFY_DONE; + return 0; - skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); - if (!skb) + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (skb == NULL) goto errout; - b = skb->tail; - type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; - nlh = NLMSG_PUT(skb, item->pid, 0, type, sizeof(struct nfgenmsg)); - nfmsg = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, item->pid, 0, type, sizeof(*nfmsg), flags); + if (nlh == NULL) + goto nlmsg_failure; - nlh->nlmsg_flags = flags; + nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = exp->tuple.src.l3num; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = 0; @@ -1575,17 +1554,19 @@ static int ctnetlink_expect_event(struct notifier_block *this, goto nla_put_failure; rcu_read_unlock(); - nlh->nlmsg_len = skb->tail - b; - nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report); - return NOTIFY_DONE; + nlmsg_end(skb, nlh); + nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, + item->report, GFP_ATOMIC); + return 0; nla_put_failure: rcu_read_unlock(); + nlmsg_cancel(skb, nlh); nlmsg_failure: kfree_skb(skb); errout: nfnetlink_set_err(0, 0, -ENOBUFS); - return NOTIFY_DONE; + return 0; } #endif static int ctnetlink_exp_done(struct netlink_callback *cb) @@ -1600,7 +1581,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = &init_net; struct nf_conntrack_expect *exp, *last; - struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); + struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); struct hlist_node *n; u_int8_t l3proto = nfmsg->nfgen_family; @@ -1617,10 +1598,11 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) continue; cb->args[1] = 0; } - if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, + if (ctnetlink_exp_fill_info(skb, + NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, - 1, exp) < 0) { + exp) < 0) { if (!atomic_inc_not_zero(&exp->use)) continue; cb->args[1] = (unsigned long)exp; @@ -1652,7 +1634,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, struct nf_conntrack_tuple tuple; struct nf_conntrack_expect *exp; struct sk_buff *skb2; - struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; int err = 0; @@ -1683,14 +1665,13 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, } err = -ENOMEM; - skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb2) + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (skb2 == NULL) goto out; rcu_read_lock(); err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, - nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, - 1, exp); + nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp); rcu_read_unlock(); if (err <= 0) goto free; @@ -1713,7 +1694,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, struct nf_conntrack_expect *exp; struct nf_conntrack_tuple tuple; struct nf_conntrack_helper *h; - struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfgenmsg *nfmsg = nlmsg_data(nlh); struct hlist_node *n, *next; u_int8_t u3 = nfmsg->nfgen_family; unsigned int i; @@ -1854,7 +1835,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, { struct nf_conntrack_tuple tuple; struct nf_conntrack_expect *exp; - struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; int err = 0; @@ -1891,12 +1872,12 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, } #ifdef CONFIG_NF_CONNTRACK_EVENTS -static struct notifier_block ctnl_notifier = { - .notifier_call = ctnetlink_conntrack_event, +static struct nf_ct_event_notifier ctnl_notifier = { + .fcn = ctnetlink_conntrack_event, }; -static struct notifier_block ctnl_notifier_exp = { - .notifier_call = ctnetlink_expect_event, +static struct nf_exp_event_notifier ctnl_notifier_exp = { + .fcn = ctnetlink_expect_event, }; #endif diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index aee0d6bea309..1b816a2ea813 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -25,8 +25,6 @@ #include #include -static DEFINE_RWLOCK(dccp_lock); - /* Timeouts are based on values from RFC4340: * * - REQUEST: @@ -492,7 +490,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, return NF_ACCEPT; } - write_lock_bh(&dccp_lock); + spin_lock_bh(&ct->lock); role = ct->proto.dccp.role[dir]; old_state = ct->proto.dccp.state; @@ -536,13 +534,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, ct->proto.dccp.last_dir = dir; ct->proto.dccp.last_pkt = type; - write_unlock_bh(&dccp_lock); + spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_DCCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_dccp: invalid packet ignored "); return NF_ACCEPT; case CT_DCCP_INVALID: - write_unlock_bh(&dccp_lock); + spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_DCCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_dccp: invalid state transition "); @@ -552,7 +550,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, ct->proto.dccp.last_dir = dir; ct->proto.dccp.last_pkt = type; ct->proto.dccp.state = new_state; - write_unlock_bh(&dccp_lock); + spin_unlock_bh(&ct->lock); if (new_state != old_state) nf_conntrack_event_cache(IPCT_PROTOINFO, ct); @@ -621,36 +619,39 @@ static int dccp_print_tuple(struct seq_file *s, ntohs(tuple->dst.u.dccp.port)); } -static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) +static int dccp_print_conntrack(struct seq_file *s, struct nf_conn *ct) { return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]); } #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, - const struct nf_conn *ct) + struct nf_conn *ct) { struct nlattr *nest_parms; - read_lock_bh(&dccp_lock); + spin_lock_bh(&ct->lock); nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE, ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]); + NLA_PUT_BE64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + cpu_to_be64(ct->proto.dccp.handshake_seq)); nla_nest_end(skb, nest_parms); - read_unlock_bh(&dccp_lock); + spin_unlock_bh(&ct->lock); return 0; nla_put_failure: - read_unlock_bh(&dccp_lock); + spin_unlock_bh(&ct->lock); return -1; } static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 }, [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 }, + [CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ] = { .type = NLA_U64 }, }; static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) @@ -674,7 +675,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) return -EINVAL; } - write_lock_bh(&dccp_lock); + spin_lock_bh(&ct->lock); ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) { ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; @@ -683,7 +684,11 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER; ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT; } - write_unlock_bh(&dccp_lock); + if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) { + ct->proto.dccp.handshake_seq = + be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ])); + } + spin_unlock_bh(&ct->lock); return 0; } diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 117b80112fcb..a54a0af0edba 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -176,7 +176,7 @@ static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple, static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { - struct net *net = dev_net(skb->dev ? skb->dev : skb->dst->dev); + struct net *net = dev_net(skb->dev ? skb->dev : skb_dst(skb)->dev); const struct gre_hdr_pptp *pgrehdr; struct gre_hdr_pptp _pgrehdr; __be16 srckey; @@ -219,8 +219,7 @@ static int gre_print_tuple(struct seq_file *s, } /* print private data for conntrack */ -static int gre_print_conntrack(struct seq_file *s, - const struct nf_conn *ct) +static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct) { return seq_printf(s, "timeout=%u, stream_timeout=%u ", (ct->proto.gre.timeout / HZ), diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 101b4ad9e817..c10e6f36e31e 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -25,9 +25,6 @@ #include #include -/* Protects ct->proto.sctp */ -static DEFINE_RWLOCK(sctp_lock); - /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR @@ -164,13 +161,13 @@ static int sctp_print_tuple(struct seq_file *s, } /* Print out the private part of the conntrack. */ -static int sctp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) +static int sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct) { enum sctp_conntrack state; - read_lock_bh(&sctp_lock); + spin_lock_bh(&ct->lock); state = ct->proto.sctp.state; - read_unlock_bh(&sctp_lock); + spin_unlock_bh(&ct->lock); return seq_printf(s, "%s ", sctp_conntrack_names[state]); } @@ -318,7 +315,7 @@ static int sctp_packet(struct nf_conn *ct, } old_state = new_state = SCTP_CONNTRACK_NONE; - write_lock_bh(&sctp_lock); + spin_lock_bh(&ct->lock); for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { /* Special cases of Verification tag check (Sec 8.5.1) */ if (sch->type == SCTP_CID_INIT) { @@ -371,7 +368,7 @@ static int sctp_packet(struct nf_conn *ct, if (old_state != new_state) nf_conntrack_event_cache(IPCT_PROTOINFO, ct); } - write_unlock_bh(&sctp_lock); + spin_unlock_bh(&ct->lock); nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]); @@ -386,7 +383,7 @@ static int sctp_packet(struct nf_conn *ct, return NF_ACCEPT; out_unlock: - write_unlock_bh(&sctp_lock); + spin_unlock_bh(&ct->lock); out: return -NF_ACCEPT; } @@ -469,11 +466,11 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb, #include static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, - const struct nf_conn *ct) + struct nf_conn *ct) { struct nlattr *nest_parms; - read_lock_bh(&sctp_lock); + spin_lock_bh(&ct->lock); nest_parms = nla_nest_start(skb, CTA_PROTOINFO_SCTP | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; @@ -488,14 +485,14 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, CTA_PROTOINFO_SCTP_VTAG_REPLY, ct->proto.sctp.vtag[IP_CT_DIR_REPLY]); - read_unlock_bh(&sctp_lock); + spin_unlock_bh(&ct->lock); nla_nest_end(skb, nest_parms); return 0; nla_put_failure: - read_unlock_bh(&sctp_lock); + spin_unlock_bh(&ct->lock); return -1; } @@ -527,13 +524,13 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct) !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) return -EINVAL; - write_lock_bh(&sctp_lock); + spin_lock_bh(&ct->lock); ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]); ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]); - write_unlock_bh(&sctp_lock); + spin_unlock_bh(&ct->lock); return 0; } diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 97a6e93d742e..33fc0a443f3d 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -29,9 +29,6 @@ #include #include -/* Protects ct->proto.tcp */ -static DEFINE_RWLOCK(tcp_lock); - /* "Be conservative in what you do, be liberal in what you accept from others." If it's non-zero, we mark only out of window RST segments as INVALID. */ @@ -59,7 +56,7 @@ static const char *const tcp_conntrack_names[] = { "LAST_ACK", "TIME_WAIT", "CLOSE", - "LISTEN" + "SYN_SENT2", }; #define SECS * HZ @@ -82,6 +79,7 @@ static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX] __read_mostly = { [TCP_CONNTRACK_LAST_ACK] = 30 SECS, [TCP_CONNTRACK_TIME_WAIT] = 2 MINS, [TCP_CONNTRACK_CLOSE] = 10 SECS, + [TCP_CONNTRACK_SYN_SENT2] = 2 MINS, }; #define sNO TCP_CONNTRACK_NONE @@ -93,7 +91,7 @@ static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX] __read_mostly = { #define sLA TCP_CONNTRACK_LAST_ACK #define sTW TCP_CONNTRACK_TIME_WAIT #define sCL TCP_CONNTRACK_CLOSE -#define sLI TCP_CONNTRACK_LISTEN +#define sS2 TCP_CONNTRACK_SYN_SENT2 #define sIV TCP_CONNTRACK_MAX #define sIG TCP_CONNTRACK_IGNORE @@ -123,6 +121,7 @@ enum tcp_bit_set { * * NONE: initial state * SYN_SENT: SYN-only packet seen + * SYN_SENT2: SYN-only packet seen from reply dir, simultaneous open * SYN_RECV: SYN-ACK packet seen * ESTABLISHED: ACK packet seen * FIN_WAIT: FIN packet seen @@ -131,26 +130,24 @@ enum tcp_bit_set { * TIME_WAIT: last ACK seen * CLOSE: closed connection (RST) * - * LISTEN state is not used. - * * Packets marked as IGNORED (sIG): * if they may be either invalid or valid * and the receiver may send back a connection * closing RST or a SYN/ACK. * * Packets marked as INVALID (sIV): - * if they are invalid - * or we do not support the request (simultaneous open) + * if we regard them as truly invalid packets */ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { { /* ORIGINAL */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*syn*/ { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*syn*/ { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sS2 }, /* * sNO -> sSS Initialize a new connection * sSS -> sSS Retransmitted SYN - * sSR -> sIG Late retransmitted SYN? + * sS2 -> sS2 Late retransmitted SYN + * sSR -> sIG * sES -> sIG Error: SYNs in window outside the SYN_SENT state * are errors. Receiver will reply with RST * and close the connection. @@ -161,22 +158,30 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sTW -> sSS Reopened connection (RFC 1122). * sCL -> sSS */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, /* - * A SYN/ACK from the client is always invalid: - * - either it tries to set up a simultaneous open, which is - * not supported; - * - or the firewall has just been inserted between the two hosts - * during the session set-up. The SYN will be retransmitted - * by the true client (or it'll time out). + * sNO -> sIV Too late and no reason to do anything + * sSS -> sIV Client can't send SYN and then SYN/ACK + * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open + * sSR -> sIG + * sES -> sIG Error: SYNs in window outside the SYN_SENT state + * are errors. Receiver will reply with RST + * and close the connection. + * Or we are not in sync and hold a dead connection. + * sFW -> sIG + * sCW -> sIG + * sLA -> sIG + * sTW -> sIG + * sCL -> sIG */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, /* * sNO -> sIV Too late and no reason to do anything... * sSS -> sIV Client migth not send FIN in this state: * we enforce waiting for a SYN/ACK reply first. + * sS2 -> sIV * sSR -> sFW Close started. * sES -> sFW * sFW -> sLA FIN seen in both directions, waiting for @@ -187,11 +192,12 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sTW -> sTW * sCL -> sCL */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*ack*/ { sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV }, /* * sNO -> sES Assumed. * sSS -> sIV ACK is invalid: we haven't seen a SYN/ACK yet. + * sS2 -> sIV * sSR -> sES Established state is reached. * sES -> sES :-) * sFW -> sCW Normal close request answered by ACK. @@ -200,29 +206,31 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sTW -> sTW Retransmitted last ACK. Remain in the same state. * sCL -> sCL */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*rst*/ { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*rst*/ { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL }, /*none*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV } }, { /* REPLY */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*syn*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 }, /* * sNO -> sIV Never reached. - * sSS -> sIV Simultaneous open, not supported - * sSR -> sIV Simultaneous open, not supported. - * sES -> sIV Server may not initiate a connection. + * sSS -> sS2 Simultaneous open + * sS2 -> sS2 Retransmitted simultaneous SYN + * sSR -> sIV Invalid SYN packets sent by the server + * sES -> sIV * sFW -> sIV * sCW -> sIV * sLA -> sIV * sTW -> sIV Reopened connection, but server may not do it. * sCL -> sIV */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, /* * sSS -> sSR Standard open. + * sS2 -> sSR Simultaneous open * sSR -> sSR Retransmitted SYN/ACK. * sES -> sIG Late retransmitted SYN/ACK? * sFW -> sIG Might be SYN/ACK answering ignored SYN @@ -231,10 +239,11 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sTW -> sIG * sCL -> sIG */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, /* * sSS -> sIV Server might not send FIN in this state. + * sS2 -> sIV * sSR -> sFW Close started. * sES -> sFW * sFW -> sLA FIN seen in both directions. @@ -243,10 +252,11 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sTW -> sTW * sCL -> sCL */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIG }, /* * sSS -> sIG Might be a half-open connection. + * sS2 -> sIG * sSR -> sSR Might answer late resent SYN. * sES -> sES :-) * sFW -> sCW Normal close request answered by ACK. @@ -255,8 +265,8 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sTW -> sTW Retransmitted last ACK. * sCL -> sCL */ -/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*rst*/ { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV }, +/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ +/*rst*/ { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL }, /*none*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV } } }; @@ -296,13 +306,13 @@ static int tcp_print_tuple(struct seq_file *s, } /* Print out the private part of the conntrack. */ -static int tcp_print_conntrack(struct seq_file *s, const struct nf_conn *ct) +static int tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct) { enum tcp_conntrack state; - read_lock_bh(&tcp_lock); + spin_lock_bh(&ct->lock); state = ct->proto.tcp.state; - read_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); return seq_printf(s, "%s ", tcp_conntrack_names[state]); } @@ -521,13 +531,14 @@ static bool tcp_in_window(const struct nf_conn *ct, receiver->td_end, receiver->td_maxend, receiver->td_maxwin, receiver->td_scale); - if (sender->td_end == 0) { + if (sender->td_maxwin == 0) { /* * Initialize sender data. */ - if (tcph->syn && tcph->ack) { + if (tcph->syn) { /* - * Outgoing SYN-ACK in reply to a SYN. + * SYN-ACK in reply to a SYN + * or SYN from reply direction in simultaneous open. */ sender->td_end = sender->td_maxend = end; @@ -543,6 +554,9 @@ static bool tcp_in_window(const struct nf_conn *ct, && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) sender->td_scale = receiver->td_scale = 0; + if (!tcph->ack) + /* Simultaneous open */ + return true; } else { /* * We are in the middle of a connection, @@ -716,14 +730,14 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb, end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); - write_lock_bh(&tcp_lock); + spin_lock_bh(&ct->lock); /* * We have to worry for the ack in the reply packet only... */ if (after(end, ct->proto.tcp.seen[dir].td_end)) ct->proto.tcp.seen[dir].td_end = end; ct->proto.tcp.last_end = end; - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " "receiver end=%u maxend=%u maxwin=%u scale=%i\n", sender->td_end, sender->td_maxend, sender->td_maxwin, @@ -832,7 +846,7 @@ static int tcp_packet(struct nf_conn *ct, th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); BUG_ON(th == NULL); - write_lock_bh(&tcp_lock); + spin_lock_bh(&ct->lock); old_state = ct->proto.tcp.state; dir = CTINFO2DIR(ctinfo); index = get_conntrack_index(th); @@ -862,7 +876,7 @@ static int tcp_packet(struct nf_conn *ct, && ct->proto.tcp.last_index == TCP_RST_SET)) { /* Attempt to reopen a closed/aborted connection. * Delete this connection and look up again. */ - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); /* Only repeat if we can actually remove the timer. * Destruction may already be in progress in process @@ -898,7 +912,7 @@ static int tcp_packet(struct nf_conn *ct, * that the client cannot but retransmit its SYN and * thus initiate a clean new session. */ - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: killing out of sync session "); @@ -911,7 +925,7 @@ static int tcp_packet(struct nf_conn *ct, ct->proto.tcp.last_end = segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: invalid packet ignored "); @@ -920,7 +934,7 @@ static int tcp_packet(struct nf_conn *ct, /* Invalid packet */ pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", dir, get_conntrack_index(th), old_state); - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: invalid state "); @@ -930,7 +944,7 @@ static int tcp_packet(struct nf_conn *ct, && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) { /* Invalid RST */ - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: invalid RST "); @@ -961,7 +975,7 @@ static int tcp_packet(struct nf_conn *ct, if (!tcp_in_window(ct, &ct->proto.tcp, dir, index, skb, dataoff, th, pf)) { - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); return -NF_ACCEPT; } in_window: @@ -990,9 +1004,8 @@ static int tcp_packet(struct nf_conn *ct, timeout = nf_ct_tcp_timeout_unacknowledged; else timeout = tcp_timeouts[new_state]; - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); - nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct); if (new_state != old_state) nf_conntrack_event_cache(IPCT_PROTOINFO, ct); @@ -1086,7 +1099,7 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, ct->proto.tcp.seen[1].td_end = 0; ct->proto.tcp.seen[1].td_maxend = 0; - ct->proto.tcp.seen[1].td_maxwin = 1; + ct->proto.tcp.seen[1].td_maxwin = 0; ct->proto.tcp.seen[1].td_scale = 0; /* tcp_packet will set them */ @@ -1108,12 +1121,12 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, #include static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, - const struct nf_conn *ct) + struct nf_conn *ct) { struct nlattr *nest_parms; struct nf_ct_tcp_flags tmp = {}; - read_lock_bh(&tcp_lock); + spin_lock_bh(&ct->lock); nest_parms = nla_nest_start(skb, CTA_PROTOINFO_TCP | NLA_F_NESTED); if (!nest_parms) goto nla_put_failure; @@ -1133,14 +1146,14 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, tmp.flags = ct->proto.tcp.seen[1].flags; NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY, sizeof(struct nf_ct_tcp_flags), &tmp); - read_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); nla_nest_end(skb, nest_parms); return 0; nla_put_failure: - read_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); return -1; } @@ -1171,7 +1184,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) return -EINVAL; - write_lock_bh(&tcp_lock); + spin_lock_bh(&ct->lock); if (tb[CTA_PROTOINFO_TCP_STATE]) ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); @@ -1198,7 +1211,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) ct->proto.tcp.seen[1].td_scale = nla_get_u8(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]); } - write_unlock_bh(&tcp_lock); + spin_unlock_bh(&ct->lock); return 0; } @@ -1327,6 +1340,13 @@ static struct ctl_table tcp_compat_sysctl_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, + { + .procname = "ip_conntrack_tcp_timeout_syn_sent2", + .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT2], + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, { .procname = "ip_conntrack_tcp_timeout_syn_recv", .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV], diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index beb37311e1a5..2fefe147750a 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -248,14 +248,14 @@ static int nf_log_proc_dostring(ctl_table *table, int write, struct file *filp, rcu_assign_pointer(nf_loggers[tindex], logger); mutex_unlock(&nf_log_mutex); } else { - rcu_read_lock(); - logger = rcu_dereference(nf_loggers[tindex]); + mutex_lock(&nf_log_mutex); + logger = nf_loggers[tindex]; if (!logger) table->data = "NONE"; else table->data = logger->name; r = proc_dostring(table, write, filp, buffer, lenp, ppos); - rcu_read_unlock(); + mutex_unlock(&nf_log_mutex); } return r; diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 4f2310c93e01..3a6fd77f7761 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -204,10 +204,10 @@ int nf_queue(struct sk_buff *skb, queuenum); switch (pf) { - case AF_INET: + case NFPROTO_IPV4: skb->protocol = htons(ETH_P_IP); break; - case AF_INET6: + case NFPROTO_IPV6: skb->protocol = htons(ETH_P_IPV6); break; } diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index b8ab37ad7ed5..92761a988375 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -107,9 +107,10 @@ int nfnetlink_has_listeners(unsigned int group) } EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); -int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) +int nfnetlink_send(struct sk_buff *skb, u32 pid, + unsigned group, int echo, gfp_t flags) { - return nlmsg_notify(nfnl, skb, pid, group, echo, gfp_any()); + return nlmsg_notify(nfnl, skb, pid, group, echo, flags); } EXPORT_SYMBOL_GPL(nfnetlink_send); @@ -136,7 +137,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return -EPERM; /* All the messages must at least contain nfgenmsg */ - if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg))) + if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) return 0; type = nlh->nlmsg_type; @@ -160,19 +161,14 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); - u_int16_t attr_count = ss->cb[cb_id].attr_count; - struct nlattr *cda[attr_count+1]; + struct nlattr *cda[ss->cb[cb_id].attr_count + 1]; + struct nlattr *attr = (void *)nlh + min_len; + int attrlen = nlh->nlmsg_len - min_len; - if (likely(nlh->nlmsg_len >= min_len)) { - struct nlattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); - int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - - err = nla_parse(cda, attr_count, attr, attrlen, - ss->cb[cb_id].policy); - if (err < 0) - return err; - } else - return -EINVAL; + err = nla_parse(cda, ss->cb[cb_id].attr_count, + attr, attrlen, ss->cb[cb_id].policy); + if (err < 0) + return err; err = nc->call(nfnl, skb, nlh, cda); if (err == -EAGAIN) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 8c860112ce05..71daa0934b6c 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -1,6 +1,6 @@ /* * This is a module which is used for queueing packets and communicating with - * userspace via nfetlink. + * userspace via nfnetlink. * * (C) 2005 by Harald Welte * (C) 2007 by Patrick McHardy @@ -932,6 +932,8 @@ static void __exit nfnetlink_queue_fini(void) #endif nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); + + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } MODULE_DESCRIPTION("netfilter packet queue handler"); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 150e5cf62f85..025d1a0af78b 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -329,6 +329,32 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target, } EXPORT_SYMBOL_GPL(xt_find_revision); +static char *textify_hooks(char *buf, size_t size, unsigned int mask) +{ + static const char *const names[] = { + "PREROUTING", "INPUT", "FORWARD", + "OUTPUT", "POSTROUTING", "BROUTING", + }; + unsigned int i; + char *p = buf; + bool np = false; + int res; + + *p = '\0'; + for (i = 0; i < ARRAY_SIZE(names); ++i) { + if (!(mask & (1 << i))) + continue; + res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]); + if (res > 0) { + size -= res; + p += res; + } + np = true; + } + + return buf; +} + int xt_check_match(struct xt_mtchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { @@ -338,26 +364,30 @@ int xt_check_match(struct xt_mtchk_param *par, * ebt_among is exempt from centralized matchsize checking * because it uses a dynamic-size data set. */ - printk("%s_tables: %s match: invalid size %Zu != %u\n", + pr_err("%s_tables: %s match: invalid size %Zu != %u\n", xt_prefix[par->family], par->match->name, XT_ALIGN(par->match->matchsize), size); return -EINVAL; } if (par->match->table != NULL && strcmp(par->match->table, par->table) != 0) { - printk("%s_tables: %s match: only valid in %s table, not %s\n", + pr_err("%s_tables: %s match: only valid in %s table, not %s\n", xt_prefix[par->family], par->match->name, par->match->table, par->table); return -EINVAL; } if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) { - printk("%s_tables: %s match: bad hook_mask %#x/%#x\n", + char used[64], allow[64]; + + pr_err("%s_tables: %s match: used from hooks %s, but only " + "valid from %s\n", xt_prefix[par->family], par->match->name, - par->hook_mask, par->match->hooks); + textify_hooks(used, sizeof(used), par->hook_mask), + textify_hooks(allow, sizeof(allow), par->match->hooks)); return -EINVAL; } if (par->match->proto && (par->match->proto != proto || inv_proto)) { - printk("%s_tables: %s match: only valid for protocol %u\n", + pr_err("%s_tables: %s match: only valid for protocol %u\n", xt_prefix[par->family], par->match->name, par->match->proto); return -EINVAL; @@ -484,26 +514,30 @@ int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { if (XT_ALIGN(par->target->targetsize) != size) { - printk("%s_tables: %s target: invalid size %Zu != %u\n", + pr_err("%s_tables: %s target: invalid size %Zu != %u\n", xt_prefix[par->family], par->target->name, XT_ALIGN(par->target->targetsize), size); return -EINVAL; } if (par->target->table != NULL && strcmp(par->target->table, par->table) != 0) { - printk("%s_tables: %s target: only valid in %s table, not %s\n", + pr_err("%s_tables: %s target: only valid in %s table, not %s\n", xt_prefix[par->family], par->target->name, par->target->table, par->table); return -EINVAL; } if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) { - printk("%s_tables: %s target: bad hook_mask %#x/%#x\n", + char used[64], allow[64]; + + pr_err("%s_tables: %s target: used from hooks %s, but only " + "usable from %s\n", xt_prefix[par->family], par->target->name, - par->hook_mask, par->target->hooks); + textify_hooks(used, sizeof(used), par->hook_mask), + textify_hooks(allow, sizeof(allow), par->target->hooks)); return -EINVAL; } if (par->target->proto && (par->target->proto != proto || inv_proto)) { - printk("%s_tables: %s target: only valid for protocol %u\n", + pr_err("%s_tables: %s target: only valid for protocol %u\n", xt_prefix[par->family], par->target->name, par->target->proto); return -EINVAL; diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index f9977b3311f7..498b45101df7 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -11,6 +11,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -23,6 +27,8 @@ MODULE_ALIAS("ipt_NFQUEUE"); MODULE_ALIAS("ip6t_NFQUEUE"); MODULE_ALIAS("arpt_NFQUEUE"); +static u32 jhash_initval __read_mostly; + static unsigned int nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) { @@ -31,32 +37,105 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) return NF_QUEUE_NR(tinfo->queuenum); } +static u32 hash_v4(const struct sk_buff *skb) +{ + const struct iphdr *iph = ip_hdr(skb); + u32 ipaddr; + + /* packets in either direction go into same queue */ + ipaddr = iph->saddr ^ iph->daddr; + + return jhash_2words(ipaddr, iph->protocol, jhash_initval); +} + +static unsigned int +nfqueue_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_NFQ_info_v1 *info = par->targinfo; + u32 queue = info->queuenum; + + if (info->queues_total > 1) + queue = hash_v4(skb) % info->queues_total + queue; + return NF_QUEUE_NR(queue); +} + +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) +static u32 hash_v6(const struct sk_buff *skb) +{ + const struct ipv6hdr *ip6h = ipv6_hdr(skb); + u32 addr[4]; + + addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0]; + addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1]; + addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2]; + addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3]; + + return jhash2(addr, ARRAY_SIZE(addr), jhash_initval); +} + +static unsigned int +nfqueue_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_NFQ_info_v1 *info = par->targinfo; + u32 queue = info->queuenum; + + if (info->queues_total > 1) + queue = hash_v6(skb) % info->queues_total + queue; + return NF_QUEUE_NR(queue); +} +#endif + +static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par) +{ + const struct xt_NFQ_info_v1 *info = par->targinfo; + u32 maxid; + + if (info->queues_total == 0) { + pr_err("NFQUEUE: number of total queues is 0\n"); + return false; + } + maxid = info->queues_total - 1 + info->queuenum; + if (maxid > 0xffff) { + pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n", + info->queues_total, maxid); + return false; + } + return true; +} + static struct xt_target nfqueue_tg_reg[] __read_mostly = { { .name = "NFQUEUE", + .family = NFPROTO_UNSPEC, + .target = nfqueue_tg, + .targetsize = sizeof(struct xt_NFQ_info), + .me = THIS_MODULE, + }, + { + .name = "NFQUEUE", + .revision = 1, .family = NFPROTO_IPV4, - .target = nfqueue_tg, - .targetsize = sizeof(struct xt_NFQ_info), + .checkentry = nfqueue_tg_v1_check, + .target = nfqueue_tg4_v1, + .targetsize = sizeof(struct xt_NFQ_info_v1), .me = THIS_MODULE, }, +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) { .name = "NFQUEUE", + .revision = 1, .family = NFPROTO_IPV6, - .target = nfqueue_tg, - .targetsize = sizeof(struct xt_NFQ_info), - .me = THIS_MODULE, - }, - { - .name = "NFQUEUE", - .family = NFPROTO_ARP, - .target = nfqueue_tg, - .targetsize = sizeof(struct xt_NFQ_info), + .checkentry = nfqueue_tg_v1_check, + .target = nfqueue_tg6_v1, + .targetsize = sizeof(struct xt_NFQ_info_v1), .me = THIS_MODULE, }, +#endif }; static int __init nfqueue_tg_init(void) { + get_random_bytes(&jhash_initval, sizeof(jhash_initval)); return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg)); } diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 4f3b1f808795..eda64c1cb1e5 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -73,11 +73,11 @@ tcpmss_mangle_packet(struct sk_buff *skb, } if (info->mss == XT_TCPMSS_CLAMP_PMTU) { - if (dst_mtu(skb->dst) <= minlen) { + if (dst_mtu(skb_dst(skb)) <= minlen) { if (net_ratelimit()) printk(KERN_ERR "xt_TCPMSS: " "unknown or invalid path-MTU (%u)\n", - dst_mtu(skb->dst)); + dst_mtu(skb_dst(skb))); return -1; } if (in_mtu <= minlen) { @@ -86,7 +86,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, "invalid path-MTU (%u)\n", in_mtu); return -1; } - newmss = min(dst_mtu(skb->dst), in_mtu) - minlen; + newmss = min(dst_mtu(skb_dst(skb)), in_mtu) - minlen; } else newmss = info->mss; diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c new file mode 100644 index 000000000000..863e40977a4d --- /dev/null +++ b/net/netfilter/xt_osf.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2003+ Evgeniy Polyakov + * + * + * 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 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +struct xt_osf_finger { + struct rcu_head rcu_head; + struct list_head finger_entry; + struct xt_osf_user_finger finger; +}; + +enum osf_fmatch_states { + /* Packet does not match the fingerprint */ + FMATCH_WRONG = 0, + /* Packet matches the fingerprint */ + FMATCH_OK, + /* Options do not match the fingerprint, but header does */ + FMATCH_OPT_WRONG, +}; + +/* + * Indexed by dont-fragment bit. + * It is the only constant value in the fingerprint. + */ +static struct list_head xt_osf_fingers[2]; + +static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = { + [OSF_ATTR_FINGER] = { .len = sizeof(struct xt_osf_user_finger) }, +}; + +static void xt_osf_finger_free_rcu(struct rcu_head *rcu_head) +{ + struct xt_osf_finger *f = container_of(rcu_head, struct xt_osf_finger, rcu_head); + + kfree(f); +} + +static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb, + struct nlmsghdr *nlh, struct nlattr *osf_attrs[]) +{ + struct xt_osf_user_finger *f; + struct xt_osf_finger *kf = NULL, *sf; + int err = 0; + + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + + if (!(nlh->nlmsg_flags & NLM_F_CREATE)) + return -EINVAL; + + f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + + kf = kmalloc(sizeof(struct xt_osf_finger), GFP_KERNEL); + if (!kf) + return -ENOMEM; + + memcpy(&kf->finger, f, sizeof(struct xt_osf_user_finger)); + + list_for_each_entry(sf, &xt_osf_fingers[!!f->df], finger_entry) { + if (memcmp(&sf->finger, f, sizeof(struct xt_osf_user_finger))) + continue; + + kfree(kf); + kf = NULL; + + if (nlh->nlmsg_flags & NLM_F_EXCL) + err = -EEXIST; + break; + } + + /* + * We are protected by nfnl mutex. + */ + if (kf) + list_add_tail_rcu(&kf->finger_entry, &xt_osf_fingers[!!f->df]); + + return err; +} + +static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb, + struct nlmsghdr *nlh, struct nlattr *osf_attrs[]) +{ + struct xt_osf_user_finger *f; + struct xt_osf_finger *sf; + int err = ENOENT; + + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + + f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + + list_for_each_entry(sf, &xt_osf_fingers[!!f->df], finger_entry) { + if (memcmp(&sf->finger, f, sizeof(struct xt_osf_user_finger))) + continue; + + /* + * We are protected by nfnl mutex. + */ + list_del_rcu(&sf->finger_entry); + call_rcu(&sf->rcu_head, xt_osf_finger_free_rcu); + + err = 0; + break; + } + + return err; +} + +static const struct nfnl_callback xt_osf_nfnetlink_callbacks[OSF_MSG_MAX] = { + [OSF_MSG_ADD] = { + .call = xt_osf_add_callback, + .attr_count = OSF_ATTR_MAX, + .policy = xt_osf_policy, + }, + [OSF_MSG_REMOVE] = { + .call = xt_osf_remove_callback, + .attr_count = OSF_ATTR_MAX, + .policy = xt_osf_policy, + }, +}; + +static const struct nfnetlink_subsystem xt_osf_nfnetlink = { + .name = "osf", + .subsys_id = NFNL_SUBSYS_OSF, + .cb_count = OSF_MSG_MAX, + .cb = xt_osf_nfnetlink_callbacks, +}; + +static inline int xt_osf_ttl(const struct sk_buff *skb, const struct xt_osf_info *info, + unsigned char f_ttl) +{ + const struct iphdr *ip = ip_hdr(skb); + + if (info->flags & XT_OSF_TTL) { + if (info->ttl == XT_OSF_TTL_TRUE) + return ip->ttl == f_ttl; + if (info->ttl == XT_OSF_TTL_NOCHECK) + return 1; + else if (ip->ttl <= f_ttl) + return 1; + else { + struct in_device *in_dev = __in_dev_get_rcu(skb->dev); + int ret = 0; + + for_ifa(in_dev) { + if (inet_ifa_match(ip->saddr, ifa)) { + ret = (ip->ttl == f_ttl); + break; + } + } + endfor_ifa(in_dev); + + return ret; + } + } + + return ip->ttl == f_ttl; +} + +static bool xt_osf_match_packet(const struct sk_buff *skb, + const struct xt_match_param *p) +{ + const struct xt_osf_info *info = p->matchinfo; + const struct iphdr *ip = ip_hdr(skb); + const struct tcphdr *tcp; + struct tcphdr _tcph; + int fmatch = FMATCH_WRONG, fcount = 0; + unsigned int optsize = 0, check_WSS = 0; + u16 window, totlen, mss = 0; + bool df; + const unsigned char *optp = NULL, *_optp = NULL; + unsigned char opts[MAX_IPOPTLEN]; + const struct xt_osf_finger *kf; + const struct xt_osf_user_finger *f; + + if (!info) + return false; + + tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph); + if (!tcp) + return false; + + if (!tcp->syn) + return false; + + totlen = ntohs(ip->tot_len); + df = ntohs(ip->frag_off) & IP_DF; + window = ntohs(tcp->window); + + if (tcp->doff * 4 > sizeof(struct tcphdr)) { + optsize = tcp->doff * 4 - sizeof(struct tcphdr); + + _optp = optp = skb_header_pointer(skb, ip_hdrlen(skb) + + sizeof(struct tcphdr), optsize, opts); + } + + rcu_read_lock(); + list_for_each_entry_rcu(kf, &xt_osf_fingers[df], finger_entry) { + f = &kf->finger; + + if (!(info->flags & XT_OSF_LOG) && strcmp(info->genre, f->genre)) + continue; + + optp = _optp; + fmatch = FMATCH_WRONG; + + if (totlen == f->ss && xt_osf_ttl(skb, info, f->ttl)) { + int foptsize, optnum; + + /* + * Should not happen if userspace parser was written correctly. + */ + if (f->wss.wc >= OSF_WSS_MAX) + continue; + + /* Check options */ + + foptsize = 0; + for (optnum = 0; optnum < f->opt_num; ++optnum) + foptsize += f->opt[optnum].length; + + if (foptsize > MAX_IPOPTLEN || + optsize > MAX_IPOPTLEN || + optsize != foptsize) + continue; + + check_WSS = f->wss.wc; + + for (optnum = 0; optnum < f->opt_num; ++optnum) { + if (f->opt[optnum].kind == (*optp)) { + __u32 len = f->opt[optnum].length; + const __u8 *optend = optp + len; + int loop_cont = 0; + + fmatch = FMATCH_OK; + + switch (*optp) { + case OSFOPT_MSS: + mss = optp[3]; + mss <<= 8; + mss |= optp[2]; + + mss = ntohs(mss); + break; + case OSFOPT_TS: + loop_cont = 1; + break; + } + + optp = optend; + } else + fmatch = FMATCH_OPT_WRONG; + + if (fmatch != FMATCH_OK) + break; + } + + if (fmatch != FMATCH_OPT_WRONG) { + fmatch = FMATCH_WRONG; + + switch (check_WSS) { + case OSF_WSS_PLAIN: + if (f->wss.val == 0 || window == f->wss.val) + fmatch = FMATCH_OK; + break; + case OSF_WSS_MSS: + /* + * Some smart modems decrease mangle MSS to + * SMART_MSS_2, so we check standard, decreased + * and the one provided in the fingerprint MSS + * values. + */ +#define SMART_MSS_1 1460 +#define SMART_MSS_2 1448 + if (window == f->wss.val * mss || + window == f->wss.val * SMART_MSS_1 || + window == f->wss.val * SMART_MSS_2) + fmatch = FMATCH_OK; + break; + case OSF_WSS_MTU: + if (window == f->wss.val * (mss + 40) || + window == f->wss.val * (SMART_MSS_1 + 40) || + window == f->wss.val * (SMART_MSS_2 + 40)) + fmatch = FMATCH_OK; + break; + case OSF_WSS_MODULO: + if ((window % f->wss.val) == 0) + fmatch = FMATCH_OK; + break; + } + } + + if (fmatch != FMATCH_OK) + continue; + + fcount++; + + if (info->flags & XT_OSF_LOG) + nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, + "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", + f->genre, f->version, f->subtype, + &ip->saddr, ntohs(tcp->source), + &ip->daddr, ntohs(tcp->dest), + f->ttl - ip->ttl); + + if ((info->flags & XT_OSF_LOG) && + info->loglevel == XT_OSF_LOGLEVEL_FIRST) + break; + } + } + rcu_read_unlock(); + + if (!fcount && (info->flags & XT_OSF_LOG)) + nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, + "Remote OS is not known: %pi4:%u -> %pi4:%u\n", + &ip->saddr, ntohs(tcp->source), + &ip->daddr, ntohs(tcp->dest)); + + if (fcount) + fmatch = FMATCH_OK; + + return fmatch == FMATCH_OK; +} + +static struct xt_match xt_osf_match = { + .name = "osf", + .revision = 0, + .family = NFPROTO_IPV4, + .proto = IPPROTO_TCP, + .hooks = (1 << NF_INET_LOCAL_IN) | + (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_FORWARD), + .match = xt_osf_match_packet, + .matchsize = sizeof(struct xt_osf_info), + .me = THIS_MODULE, +}; + +static int __init xt_osf_init(void) +{ + int err = -EINVAL; + int i; + + for (i=0; ifinger_entry); + call_rcu(&f->rcu_head, xt_osf_finger_free_rcu); + } + } + rcu_read_unlock(); + + rcu_barrier(); +} + +module_init(xt_osf_init); +module_exit(xt_osf_fini); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Passive OS fingerprint matching."); +MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF); diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 328bd20ddd25..4cbfebda8fa1 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c @@ -86,7 +86,7 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info, unsigned short family) { const struct xt_policy_elem *e; - const struct dst_entry *dst = skb->dst; + const struct dst_entry *dst = skb_dst(skb); int strict = info->flags & XT_POLICY_MATCH_STRICT; int i, pos; diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c index 67419287bc7e..484d1689bfde 100644 --- a/net/netfilter/xt_realm.c +++ b/net/netfilter/xt_realm.c @@ -25,7 +25,7 @@ static bool realm_mt(const struct sk_buff *skb, const struct xt_match_param *par) { const struct xt_realm_info *info = par->matchinfo; - const struct dst_entry *dst = skb->dst; + const struct dst_entry *dst = skb_dst(skb); return (info->id == (dst->tclassid & info->mask)) ^ info->invert; } diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 1acc089be7e9..ebf00ad5b194 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -22,6 +22,8 @@ #include #include +#include + #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #define XT_SOCKET_HAVE_CONNTRACK 1 #include @@ -86,7 +88,8 @@ extract_icmp_fields(const struct sk_buff *skb, static bool -socket_mt(const struct sk_buff *skb, const struct xt_match_param *par) +socket_match(const struct sk_buff *skb, const struct xt_match_param *par, + const struct xt_socket_mtinfo1 *info) { const struct iphdr *iph = ip_hdr(skb); struct udphdr _hdr, *hp = NULL; @@ -141,10 +144,24 @@ socket_mt(const struct sk_buff *skb, const struct xt_match_param *par) sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol, saddr, daddr, sport, dport, par->in, false); if (sk != NULL) { - bool wildcard = (sk->sk_state != TCP_TIME_WAIT && inet_sk(sk)->rcv_saddr == 0); + bool wildcard; + bool transparent = true; + + /* Ignore sockets listening on INADDR_ANY */ + wildcard = (sk->sk_state != TCP_TIME_WAIT && + inet_sk(sk)->rcv_saddr == 0); + + /* Ignore non-transparent sockets, + if XT_SOCKET_TRANSPARENT is used */ + if (info && info->flags & XT_SOCKET_TRANSPARENT) + transparent = ((sk->sk_state != TCP_TIME_WAIT && + inet_sk(sk)->transparent) || + (sk->sk_state == TCP_TIME_WAIT && + inet_twsk(sk)->tw_transparent)); nf_tproxy_put_sock(sk); - if (wildcard) + + if (wildcard || !transparent) sk = NULL; } @@ -157,23 +174,47 @@ socket_mt(const struct sk_buff *skb, const struct xt_match_param *par) return (sk != NULL); } -static struct xt_match socket_mt_reg __read_mostly = { - .name = "socket", - .family = AF_INET, - .match = socket_mt, - .hooks = 1 << NF_INET_PRE_ROUTING, - .me = THIS_MODULE, +static bool +socket_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) +{ + return socket_match(skb, par, NULL); +} + +static bool +socket_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) +{ + return socket_match(skb, par, par->matchinfo); +} + +static struct xt_match socket_mt_reg[] __read_mostly = { + { + .name = "socket", + .revision = 0, + .family = NFPROTO_IPV4, + .match = socket_mt_v0, + .hooks = 1 << NF_INET_PRE_ROUTING, + .me = THIS_MODULE, + }, + { + .name = "socket", + .revision = 1, + .family = NFPROTO_IPV4, + .match = socket_mt_v1, + .matchsize = sizeof(struct xt_socket_mtinfo1), + .hooks = 1 << NF_INET_PRE_ROUTING, + .me = THIS_MODULE, + }, }; static int __init socket_mt_init(void) { nf_defrag_ipv4_enable(); - return xt_register_match(&socket_mt_reg); + return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); } static void __exit socket_mt_exit(void) { - xt_unregister_match(&socket_mt_reg); + xt_unregister_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); } module_init(socket_mt_init); diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index bf1ab1a6790d..e639298bc9c8 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -785,18 +785,6 @@ static struct genl_ops netlbl_cipsov4_ops[] = { */ int __init netlbl_cipsov4_genl_init(void) { - int ret_val, i; - - ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); - if (ret_val != 0) - return ret_val; - - for (i = 0; i < ARRAY_SIZE(netlbl_cipsov4_ops); i++) { - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_ops[i]); - if (ret_val != 0) - return ret_val; - } - - return 0; + return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family, + netlbl_cipsov4_ops, ARRAY_SIZE(netlbl_cipsov4_ops)); } diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 1821c5d50fb8..8203623e65ad 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -779,18 +779,6 @@ static struct genl_ops netlbl_mgmt_genl_ops[] = { */ int __init netlbl_mgmt_genl_init(void) { - int ret_val, i; - - ret_val = genl_register_family(&netlbl_mgmt_gnl_family); - if (ret_val != 0) - return ret_val; - - for (i = 0; i < ARRAY_SIZE(netlbl_mgmt_genl_ops); i++) { - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_ops[i]); - if (ret_val != 0) - return ret_val; - } - - return 0; + return genl_register_family_with_ops(&netlbl_mgmt_gnl_family, + netlbl_mgmt_genl_ops, ARRAY_SIZE(netlbl_mgmt_genl_ops)); } diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index f3c5c68c6848..fb357f010189 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1478,20 +1478,8 @@ static struct genl_ops netlbl_unlabel_genl_ops[] = { */ int __init netlbl_unlabel_genl_init(void) { - int ret_val, i; - - ret_val = genl_register_family(&netlbl_unlabel_gnl_family); - if (ret_val != 0) - return ret_val; - - for (i = 0; i < ARRAY_SIZE(netlbl_unlabel_genl_ops); i++) { - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_ops[i]); - if (ret_val != 0) - return ret_val; - } - - return 0; + return genl_register_family_with_ops(&netlbl_unlabel_gnl_family, + netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops)); } /* diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 1d3dd30099df..eed4c6a8afc0 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -383,6 +383,52 @@ int genl_register_family(struct genl_family *family) return err; } +/** + * genl_register_family_with_ops - register a generic netlink family + * @family: generic netlink family + * @ops: operations to be registered + * @n_ops: number of elements to register + * + * Registers the specified family and operations from the specified table. + * Only one family may be registered with the same family name or identifier. + * + * The family id may equal GENL_ID_GENERATE causing an unique id to + * be automatically generated and assigned. + * + * Either a doit or dumpit callback must be specified for every registered + * operation or the function will fail. Only one operation structure per + * command identifier may be registered. + * + * See include/net/genetlink.h for more documenation on the operations + * structure. + * + * This is equivalent to calling genl_register_family() followed by + * genl_register_ops() for every operation entry in the table taking + * care to unregister the family on error path. + * + * Return 0 on success or a negative error code. + */ +int genl_register_family_with_ops(struct genl_family *family, + struct genl_ops *ops, size_t n_ops) +{ + int err, i; + + err = genl_register_family(family); + if (err) + return err; + + for (i = 0; i < n_ops; ++i, ++ops) { + err = genl_register_ops(family, ops); + if (err) + goto err_out; + } + return 0; +err_out: + genl_unregister_family(family); + return err; +} +EXPORT_SYMBOL(genl_register_family_with_ops); + /** * genl_unregister_family - unregister generic netlink family * @family: generic netlink family diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f546e81acc45..4f76e5552d8e 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -39,6 +39,7 @@ * will simply extend the hardware address * byte arrays at the end of sockaddr_ll * and packet_mreq. + * Johann Baudy : Added TX RING. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -157,7 +158,25 @@ struct packet_mreq_max }; #ifdef CONFIG_PACKET_MMAP -static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing); +static int packet_set_ring(struct sock *sk, struct tpacket_req *req, + int closing, int tx_ring); + +struct packet_ring_buffer { + char * *pg_vec; + unsigned int head; + unsigned int frames_per_block; + unsigned int frame_size; + unsigned int frame_max; + + unsigned int pg_vec_order; + unsigned int pg_vec_pages; + unsigned int pg_vec_len; + + atomic_t pending; +}; + +struct packet_sock; +static int tpacket_snd(struct packet_sock *po, struct msghdr *msg); #endif static void packet_flush_mclist(struct sock *sk); @@ -167,11 +186,8 @@ struct packet_sock { struct sock sk; struct tpacket_stats stats; #ifdef CONFIG_PACKET_MMAP - char * *pg_vec; - unsigned int head; - unsigned int frames_per_block; - unsigned int frame_size; - unsigned int frame_max; + struct packet_ring_buffer rx_ring; + struct packet_ring_buffer tx_ring; int copy_thresh; #endif struct packet_type prot_hook; @@ -185,12 +201,10 @@ struct packet_sock { struct packet_mclist *mclist; #ifdef CONFIG_PACKET_MMAP atomic_t mapped; - unsigned int pg_vec_order; - unsigned int pg_vec_pages; - unsigned int pg_vec_len; enum tpacket_versions tp_version; unsigned int tp_hdrlen; unsigned int tp_reserve; + unsigned int tp_loss:1; #endif }; @@ -206,35 +220,6 @@ struct packet_skb_cb { #ifdef CONFIG_PACKET_MMAP -static void *packet_lookup_frame(struct packet_sock *po, unsigned int position, - int status) -{ - unsigned int pg_vec_pos, frame_offset; - union { - struct tpacket_hdr *h1; - struct tpacket2_hdr *h2; - void *raw; - } h; - - pg_vec_pos = position / po->frames_per_block; - frame_offset = position % po->frames_per_block; - - h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); - switch (po->tp_version) { - case TPACKET_V1: - if (status != (h.h1->tp_status ? TP_STATUS_USER : - TP_STATUS_KERNEL)) - return NULL; - break; - case TPACKET_V2: - if (status != (h.h2->tp_status ? TP_STATUS_USER : - TP_STATUS_KERNEL)) - return NULL; - break; - } - return h.raw; -} - static void __packet_set_status(struct packet_sock *po, void *frame, int status) { union { @@ -247,12 +232,88 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status) switch (po->tp_version) { case TPACKET_V1: h.h1->tp_status = status; + flush_dcache_page(virt_to_page(&h.h1->tp_status)); break; case TPACKET_V2: h.h2->tp_status = status; + flush_dcache_page(virt_to_page(&h.h2->tp_status)); break; + default: + printk(KERN_ERR "TPACKET version not supported\n"); + BUG(); + } + + smp_wmb(); +} + +static int __packet_get_status(struct packet_sock *po, void *frame) +{ + union { + struct tpacket_hdr *h1; + struct tpacket2_hdr *h2; + void *raw; + } h; + + smp_rmb(); + + h.raw = frame; + switch (po->tp_version) { + case TPACKET_V1: + flush_dcache_page(virt_to_page(&h.h1->tp_status)); + return h.h1->tp_status; + case TPACKET_V2: + flush_dcache_page(virt_to_page(&h.h2->tp_status)); + return h.h2->tp_status; + default: + printk(KERN_ERR "TPACKET version not supported\n"); + BUG(); + return 0; } } + +static void *packet_lookup_frame(struct packet_sock *po, + struct packet_ring_buffer *rb, + unsigned int position, + int status) +{ + unsigned int pg_vec_pos, frame_offset; + union { + struct tpacket_hdr *h1; + struct tpacket2_hdr *h2; + void *raw; + } h; + + pg_vec_pos = position / rb->frames_per_block; + frame_offset = position % rb->frames_per_block; + + h.raw = rb->pg_vec[pg_vec_pos] + (frame_offset * rb->frame_size); + + if (status != __packet_get_status(po, h.raw)) + return NULL; + + return h.raw; +} + +static inline void *packet_current_frame(struct packet_sock *po, + struct packet_ring_buffer *rb, + int status) +{ + return packet_lookup_frame(po, rb, rb->head, status); +} + +static inline void *packet_previous_frame(struct packet_sock *po, + struct packet_ring_buffer *rb, + int status) +{ + unsigned int previous = rb->head ? rb->head - 1 : rb->frame_max; + return packet_lookup_frame(po, rb, previous, status); +} + +static inline void packet_increment_head(struct packet_ring_buffer *buff) +{ + buff->head = buff->head != buff->frame_max ? buff->head+1 : 0; +} + #endif static inline struct packet_sock *pkt_sk(struct sock *sk) @@ -311,8 +372,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct goto oom; /* drop any routing info */ - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); /* drop conntrack reference */ nf_reset(skb); @@ -560,8 +620,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet skb_set_owner_r(skb, sk); skb->dev = NULL; - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); /* drop conntrack reference */ nf_reset(skb); @@ -648,7 +707,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe macoff = netoff - maclen; } - if (macoff + snaplen > po->frame_size) { + if (macoff + snaplen > po->rx_ring.frame_size) { if (po->copy_thresh && atomic_read(&sk->sk_rmem_alloc) + skb->truesize < (unsigned)sk->sk_rcvbuf) { @@ -661,16 +720,16 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe if (copy_skb) skb_set_owner_r(copy_skb, sk); } - snaplen = po->frame_size - macoff; + snaplen = po->rx_ring.frame_size - macoff; if ((int)snaplen < 0) snaplen = 0; } spin_lock(&sk->sk_receive_queue.lock); - h.raw = packet_lookup_frame(po, po->head, TP_STATUS_KERNEL); + h.raw = packet_current_frame(po, &po->rx_ring, TP_STATUS_KERNEL); if (!h.raw) goto ring_is_full; - po->head = po->head != po->frame_max ? po->head+1 : 0; + packet_increment_head(&po->rx_ring); po->stats.tp_packets++; if (copy_skb) { status |= TP_STATUS_COPY; @@ -727,7 +786,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe __packet_set_status(po, h.raw, status); smp_mb(); - { struct page *p_start, *p_end; u8 *h_end = h.raw + macoff + snaplen - 1; @@ -760,10 +818,249 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe goto drop_n_restore; } +static void tpacket_destruct_skb(struct sk_buff *skb) +{ + struct packet_sock *po = pkt_sk(skb->sk); + void * ph; + + BUG_ON(skb == NULL); + + if (likely(po->tx_ring.pg_vec)) { + ph = skb_shinfo(skb)->destructor_arg; + BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING); + BUG_ON(atomic_read(&po->tx_ring.pending) == 0); + atomic_dec(&po->tx_ring.pending); + __packet_set_status(po, ph, TP_STATUS_AVAILABLE); + } + + 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) +{ + union { + struct tpacket_hdr *h1; + struct tpacket2_hdr *h2; + void *raw; + } ph; + int to_write, offset, len, tp_len, nr_frags, len_max; + struct socket *sock = po->sk.sk_socket; + struct page *page; + void *data; + int err; + + ph.raw = frame; + + skb->protocol = proto; + skb->dev = dev; + skb->priority = po->sk.sk_priority; + skb_shinfo(skb)->destructor_arg = ph.raw; + + switch (po->tp_version) { + case TPACKET_V2: + tp_len = ph.h2->tp_len; + break; + default: + tp_len = ph.h1->tp_len; + break; + } + if (unlikely(tp_len > size_max)) { + printk(KERN_ERR "packet size is too long (%d > %d)\n", + tp_len, size_max); + return -EMSGSIZE; + } + + skb_reserve(skb, LL_RESERVED_SPACE(dev)); + skb_reset_network_header(skb); + + data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll); + to_write = tp_len; + + if (sock->type == SOCK_DGRAM) { + err = dev_hard_header(skb, dev, ntohs(proto), addr, + NULL, tp_len); + if (unlikely(err < 0)) + return -EINVAL; + } 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); + return -EINVAL; + } + + skb_push(skb, dev->hard_header_len); + err = skb_store_bits(skb, 0, data, + dev->hard_header_len); + if (unlikely(err)) + return err; + + data += dev->hard_header_len; + to_write -= dev->hard_header_len; + } + + err = -EFAULT; + page = virt_to_page(data); + offset = offset_in_page(data); + len_max = PAGE_SIZE - offset; + len = ((to_write > len_max) ? len_max : to_write); + + skb->data_len = to_write; + skb->len += to_write; + skb->truesize += to_write; + atomic_add(to_write, &po->sk.sk_wmem_alloc); + + while (likely(to_write)) { + 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); + return -EFAULT; + } + + flush_dcache_page(page); + get_page(page); + skb_fill_page_desc(skb, + nr_frags, + page++, offset, len); + to_write -= len; + offset = 0; + len_max = PAGE_SIZE; + len = ((to_write > len_max) ? len_max : to_write); + } + + return tp_len; +} + +static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) +{ + struct socket *sock; + struct sk_buff *skb; + struct net_device *dev; + __be16 proto; + int ifindex, err, reserve = 0; + void * ph; + struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name; + int tp_len, size_max; + unsigned char *addr; + int len_sum = 0; + int status = 0; + + sock = po->sk.sk_socket; + + mutex_lock(&po->pg_vec_lock); + + err = -EBUSY; + if (saddr == NULL) { + ifindex = po->ifindex; + proto = po->num; + addr = NULL; + } else { + err = -EINVAL; + if (msg->msg_namelen < sizeof(struct sockaddr_ll)) + goto out; + if (msg->msg_namelen < (saddr->sll_halen + + offsetof(struct sockaddr_ll, + sll_addr))) + goto out; + ifindex = saddr->sll_ifindex; + proto = saddr->sll_protocol; + addr = saddr->sll_addr; + } + + dev = dev_get_by_index(sock_net(&po->sk), ifindex); + err = -ENXIO; + if (unlikely(dev == NULL)) + goto out; + + reserve = dev->hard_header_len; + + err = -ENETDOWN; + if (unlikely(!(dev->flags & IFF_UP))) + goto out_put; + + size_max = po->tx_ring.frame_size + - sizeof(struct skb_shared_info) + - po->tp_hdrlen + - LL_ALLOCATED_SPACE(dev) + - sizeof(struct sockaddr_ll); + + if (size_max > dev->mtu + reserve) + size_max = dev->mtu + reserve; + + do { + ph = packet_current_frame(po, &po->tx_ring, + TP_STATUS_SEND_REQUEST); + + if (unlikely(ph == NULL)) { + schedule(); + continue; + } + + status = TP_STATUS_SEND_REQUEST; + skb = sock_alloc_send_skb(&po->sk, + LL_ALLOCATED_SPACE(dev) + + sizeof(struct sockaddr_ll), + 0, &err); + + if (unlikely(skb == NULL)) + goto out_status; + + tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, + addr); + + if (unlikely(tp_len < 0)) { + if (po->tp_loss) { + __packet_set_status(po, ph, + TP_STATUS_AVAILABLE); + packet_increment_head(&po->tx_ring); + kfree_skb(skb); + continue; + } else { + status = TP_STATUS_WRONG_FORMAT; + err = tp_len; + goto out_status; + } + } + + skb->destructor = tpacket_destruct_skb; + __packet_set_status(po, ph, TP_STATUS_SENDING); + atomic_inc(&po->tx_ring.pending); + + status = TP_STATUS_SEND_REQUEST; + err = dev_queue_xmit(skb); + if (unlikely(err > 0 && (err = net_xmit_errno(err)) != 0)) + goto out_xmit; + packet_increment_head(&po->tx_ring); + len_sum += tp_len; + } + while (likely((ph != NULL) || ((!(msg->msg_flags & MSG_DONTWAIT)) + && (atomic_read(&po->tx_ring.pending)))) + ); + + err = len_sum; + goto out_put; + +out_xmit: + skb->destructor = sock_wfree; + atomic_dec(&po->tx_ring.pending); +out_status: + __packet_set_status(po, ph, status); + kfree_skb(skb); +out_put: + dev_put(dev); +out: + mutex_unlock(&po->pg_vec_lock); + return err; +} #endif - -static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, +static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; @@ -854,6 +1151,19 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, return err; } +static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t len) +{ +#ifdef CONFIG_PACKET_MMAP + struct sock *sk = sock->sk; + struct packet_sock *po = pkt_sk(sk); + if (po->tx_ring.pg_vec) + return tpacket_snd(po, msg); + else +#endif + return packet_snd(sock, msg, len); +} + /* * Close a PACKET socket. This is fairly simple. We immediately go * to 'closed' state and remove our protocol entry in the device list. @@ -864,6 +1174,9 @@ static int packet_release(struct socket *sock) struct sock *sk = sock->sk; struct packet_sock *po; struct net *net; +#ifdef CONFIG_PACKET_MMAP + struct tpacket_req req; +#endif if (!sk) return 0; @@ -893,11 +1206,13 @@ static int packet_release(struct socket *sock) packet_flush_mclist(sk); #ifdef CONFIG_PACKET_MMAP - if (po->pg_vec) { - struct tpacket_req req; - memset(&req, 0, sizeof(req)); - packet_set_ring(sk, &req, 1); - } + memset(&req, 0, sizeof(req)); + + if (po->rx_ring.pg_vec) + packet_set_ring(sk, &req, 1, 0); + + if (po->tx_ring.pg_vec) + packet_set_ring(sk, &req, 1, 1); #endif /* @@ -1253,9 +1568,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, switch (i->type) { case PACKET_MR_MULTICAST: if (what > 0) - dev_mc_add(dev, i->addr, i->alen, 0); + return dev_mc_add(dev, i->addr, i->alen, 0); else - dev_mc_delete(dev, i->addr, i->alen, 0); + return dev_mc_delete(dev, i->addr, i->alen, 0); break; case PACKET_MR_PROMISC: return dev_set_promiscuity(dev, what); @@ -1263,6 +1578,12 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, case PACKET_MR_ALLMULTI: return dev_set_allmulti(dev, what); break; + case PACKET_MR_UNICAST: + if (what > 0) + return dev_unicast_add(dev, i->addr); + else + return dev_unicast_delete(dev, i->addr); + break; default:; } return 0; @@ -1391,7 +1712,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (level != SOL_PACKET) return -ENOPROTOOPT; - switch(optname) { + switch (optname) { case PACKET_ADD_MEMBERSHIP: case PACKET_DROP_MEMBERSHIP: { @@ -1415,6 +1736,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv #ifdef CONFIG_PACKET_MMAP case PACKET_RX_RING: + case PACKET_TX_RING: { struct tpacket_req req; @@ -1422,7 +1744,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv return -EINVAL; if (copy_from_user(&req,optval,sizeof(req))) return -EFAULT; - return packet_set_ring(sk, &req, 0); + return packet_set_ring(sk, &req, 0, optname == PACKET_TX_RING); } case PACKET_COPY_THRESH: { @@ -1442,7 +1764,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; - if (po->pg_vec) + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; @@ -1461,13 +1783,26 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; - if (po->pg_vec) + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; po->tp_reserve = val; return 0; } + case PACKET_LOSS: + { + unsigned int val; + + if (optlen != sizeof(val)) + return -EINVAL; + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) + return -EBUSY; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + po->tp_loss = !!val; + return 0; + } #endif case PACKET_AUXDATA: { @@ -1517,7 +1852,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, if (len < 0) return -EINVAL; - switch(optname) { + switch (optname) { case PACKET_STATISTICS: if (len > sizeof(struct tpacket_stats)) len = sizeof(struct tpacket_stats); @@ -1573,6 +1908,12 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, val = po->tp_reserve; data = &val; break; + case PACKET_LOSS: + if (len > sizeof(unsigned int)) + len = sizeof(unsigned int); + val = po->tp_loss; + data = &val; + break; #endif default: return -ENOPROTOOPT; @@ -1643,7 +1984,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, { struct sock *sk = sock->sk; - switch(cmd) { + switch (cmd) { case SIOCOUTQ: { int amount = atomic_read(&sk->sk_wmem_alloc); @@ -1705,13 +2046,17 @@ static unsigned int packet_poll(struct file * file, struct socket *sock, unsigned int mask = datagram_poll(file, sock, wait); spin_lock_bh(&sk->sk_receive_queue.lock); - if (po->pg_vec) { - unsigned last = po->head ? po->head-1 : po->frame_max; - - if (packet_lookup_frame(po, last, TP_STATUS_USER)) + if (po->rx_ring.pg_vec) { + if (!packet_previous_frame(po, &po->rx_ring, TP_STATUS_KERNEL)) mask |= POLLIN | POLLRDNORM; } spin_unlock_bh(&sk->sk_receive_queue.lock); + spin_lock_bh(&sk->sk_write_queue.lock); + if (po->tx_ring.pg_vec) { + if (packet_current_frame(po, &po->tx_ring, TP_STATUS_AVAILABLE)) + mask |= POLLOUT | POLLWRNORM; + } + spin_unlock_bh(&sk->sk_write_queue.lock); return mask; } @@ -1788,21 +2133,33 @@ static char **alloc_pg_vec(struct tpacket_req *req, int order) goto out; } -static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing) +static int packet_set_ring(struct sock *sk, struct tpacket_req *req, + int closing, int tx_ring) { char **pg_vec = NULL; struct packet_sock *po = pkt_sk(sk); int was_running, order = 0; + struct packet_ring_buffer *rb; + struct sk_buff_head *rb_queue; __be16 num; - int err = 0; + int err; + + rb = tx_ring ? &po->tx_ring : &po->rx_ring; + rb_queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; + + err = -EBUSY; + if (!closing) { + if (atomic_read(&po->mapped)) + goto out; + if (atomic_read(&rb->pending)) + goto out; + } if (req->tp_block_nr) { - int i; - /* Sanity tests and some calculations */ - - if (unlikely(po->pg_vec)) - return -EBUSY; + err = -EBUSY; + if (unlikely(rb->pg_vec)) + goto out; switch (po->tp_version) { case TPACKET_V1: @@ -1813,42 +2170,35 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing break; } + err = -EINVAL; if (unlikely((int)req->tp_block_size <= 0)) - return -EINVAL; + goto out; if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) - return -EINVAL; + goto out; if (unlikely(req->tp_frame_size < po->tp_hdrlen + - po->tp_reserve)) - return -EINVAL; + po->tp_reserve)) + goto out; if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) - return -EINVAL; + goto out; - po->frames_per_block = req->tp_block_size/req->tp_frame_size; - if (unlikely(po->frames_per_block <= 0)) - return -EINVAL; - if (unlikely((po->frames_per_block * req->tp_block_nr) != - req->tp_frame_nr)) - return -EINVAL; + rb->frames_per_block = req->tp_block_size/req->tp_frame_size; + if (unlikely(rb->frames_per_block <= 0)) + goto out; + if (unlikely((rb->frames_per_block * req->tp_block_nr) != + req->tp_frame_nr)) + goto out; err = -ENOMEM; order = get_order(req->tp_block_size); pg_vec = alloc_pg_vec(req, order); if (unlikely(!pg_vec)) goto out; - - for (i = 0; i < req->tp_block_nr; i++) { - void *ptr = pg_vec[i]; - int k; - - for (k = 0; k < po->frames_per_block; k++) { - __packet_set_status(po, ptr, TP_STATUS_KERNEL); - ptr += req->tp_frame_size; - } - } - /* Done */ - } else { + } + /* Done */ + else { + err = -EINVAL; if (unlikely(req->tp_frame_nr)) - return -EINVAL; + goto out; } lock_sock(sk); @@ -1872,23 +2222,24 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing if (closing || atomic_read(&po->mapped) == 0) { err = 0; #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) + spin_lock_bh(&rb_queue->lock); + pg_vec = XC(rb->pg_vec, pg_vec); + rb->frame_max = (req->tp_frame_nr - 1); + rb->head = 0; + rb->frame_size = req->tp_frame_size; + spin_unlock_bh(&rb_queue->lock); - spin_lock_bh(&sk->sk_receive_queue.lock); - pg_vec = XC(po->pg_vec, pg_vec); - po->frame_max = (req->tp_frame_nr - 1); - po->head = 0; - po->frame_size = req->tp_frame_size; - spin_unlock_bh(&sk->sk_receive_queue.lock); + order = XC(rb->pg_vec_order, order); + req->tp_block_nr = XC(rb->pg_vec_len, req->tp_block_nr); - order = XC(po->pg_vec_order, order); - req->tp_block_nr = XC(po->pg_vec_len, req->tp_block_nr); - - po->pg_vec_pages = req->tp_block_size/PAGE_SIZE; - po->prot_hook.func = po->pg_vec ? tpacket_rcv : packet_rcv; - skb_queue_purge(&sk->sk_receive_queue); + rb->pg_vec_pages = req->tp_block_size/PAGE_SIZE; + po->prot_hook.func = (po->rx_ring.pg_vec) ? + tpacket_rcv : packet_rcv; + 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)); + printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", + atomic_read(&po->mapped)); } mutex_unlock(&po->pg_vec_lock); @@ -1909,11 +2260,13 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing return err; } -static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma) +static int packet_mmap(struct file *file, struct socket *sock, + struct vm_area_struct *vma) { struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); - unsigned long size; + unsigned long size, expected_size; + struct packet_ring_buffer *rb; unsigned long start; int err = -EINVAL; int i; @@ -1921,26 +2274,43 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st if (vma->vm_pgoff) return -EINVAL; - size = vma->vm_end - vma->vm_start; - mutex_lock(&po->pg_vec_lock); - if (po->pg_vec == NULL) + + expected_size = 0; + for (rb = &po->rx_ring; rb <= &po->tx_ring; rb++) { + if (rb->pg_vec) { + expected_size += rb->pg_vec_len + * rb->pg_vec_pages + * PAGE_SIZE; + } + } + + if (expected_size == 0) goto out; - if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) + + size = vma->vm_end - vma->vm_start; + if (size != expected_size) goto out; start = vma->vm_start; - for (i = 0; i < po->pg_vec_len; i++) { - struct page *page = virt_to_page(po->pg_vec[i]); - int pg_num; + for (rb = &po->rx_ring; rb <= &po->tx_ring; rb++) { + if (rb->pg_vec == NULL) + continue; - for (pg_num = 0; pg_num < po->pg_vec_pages; pg_num++, page++) { - err = vm_insert_page(vma, start, page); - if (unlikely(err)) - goto out; - start += PAGE_SIZE; + for (i = 0; i < rb->pg_vec_len; i++) { + struct page *page = virt_to_page(rb->pg_vec[i]); + int pg_num; + + for (pg_num = 0; pg_num < rb->pg_vec_pages; + pg_num++,page++) { + err = vm_insert_page(vma, start, page); + if (unlikely(err)) + goto out; + start += PAGE_SIZE; + } } } + atomic_inc(&po->mapped); vma->vm_ops = &packet_mmap_ops; err = 0; diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index 4aa888584d20..480839dfc560 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c @@ -115,10 +115,10 @@ static int gprs_recv(struct gprs_dev *gp, struct sk_buff *skb) rskb->truesize += rskb->len; /* Avoid nested fragments */ - for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) + skb_walk_frags(skb, fs) flen += fs->len; skb->next = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; + skb_frag_list_init(skb); skb->len -= flen; skb->data_len -= flen; skb->truesize -= flen; @@ -212,8 +212,9 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_bytes += len; } - if (!pep_writeable(sk)) - netif_stop_queue(dev); + netif_stop_queue(dev); + if (pep_writeable(sk)) + netif_wake_queue(dev); return 0; } diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 8ad2b5333881..eef833ea6d7b 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -940,10 +940,10 @@ int pep_write(struct sock *sk, struct sk_buff *skb) rskb->truesize += rskb->len; /* Avoid nested fragments */ - for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) + skb_walk_frags(skb, fs) flen += fs->len; skb->next = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; + skb_frag_list_init(skb); skb->len -= flen; skb->data_len -= flen; skb->truesize -= flen; diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 20cf16fc572f..b11e7e527864 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include "rds.h" diff --git a/net/rds/connection.c b/net/rds/connection.c index 273f064930a8..d14445c48304 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c @@ -148,14 +148,12 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, if (conn) goto out; - conn = kmem_cache_alloc(rds_conn_slab, gfp); + conn = kmem_cache_zalloc(rds_conn_slab, gfp); if (conn == NULL) { conn = ERR_PTR(-ENOMEM); goto out; } - memset(conn, 0, sizeof(*conn)); - INIT_HLIST_NODE(&conn->c_hash_node); conn->c_version = RDS_PROTOCOL_3_0; conn->c_laddr = laddr; diff --git a/net/rds/ib.c b/net/rds/ib.c index 4933b380985e..b9bcd32431e1 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -224,8 +224,8 @@ static int rds_ib_laddr_check(__be32 addr) * IB and iWARP capable NICs. */ cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP); - if (!cm_id) - return -EADDRNOTAVAIL; + if (IS_ERR(cm_id)) + return PTR_ERR(cm_id); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; diff --git a/net/rds/ib.h b/net/rds/ib.h index 069206cae733..455ae73047fe 100644 --- a/net/rds/ib.h +++ b/net/rds/ib.h @@ -333,7 +333,7 @@ int rds_ib_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op); void rds_ib_send_add_credits(struct rds_connection *conn, unsigned int credits); void rds_ib_advertise_credits(struct rds_connection *conn, unsigned int posted); int rds_ib_send_grab_credits(struct rds_ib_connection *ic, u32 wanted, - u32 *adv_credits, int need_posted); + u32 *adv_credits, int need_posted, int max_posted); /* ib_stats.c */ DECLARE_PER_CPU(struct rds_ib_statistics, rds_ib_stats); diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 36d931573ff4..5709bad28329 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c @@ -524,7 +524,7 @@ void rds_ib_attempt_ack(struct rds_ib_connection *ic) } /* Can we get a send credit? */ - if (!rds_ib_send_grab_credits(ic, 1, &adv_credits, 0)) { + if (!rds_ib_send_grab_credits(ic, 1, &adv_credits, 0, RDS_MAX_ADV_CREDIT)) { rds_ib_stats_inc(s_ib_tx_throttle); clear_bit(IB_ACK_IN_FLIGHT, &ic->i_ack_flags); return; diff --git a/net/rds/ib_ring.c b/net/rds/ib_ring.c index 99a6ccae964c..ff97e8eda858 100644 --- a/net/rds/ib_ring.c +++ b/net/rds/ib_ring.c @@ -137,7 +137,7 @@ int rds_ib_ring_empty(struct rds_ib_work_ring *ring) int rds_ib_ring_low(struct rds_ib_work_ring *ring) { - return __rds_ib_ring_used(ring) <= (ring->w_nr >> 2); + return __rds_ib_ring_used(ring) <= (ring->w_nr >> 1); } /* diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index cb6c52cb1c4c..23bf830db2d5 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -311,7 +311,7 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) * and using atomic_cmpxchg when updating the two counters. */ int rds_ib_send_grab_credits(struct rds_ib_connection *ic, - u32 wanted, u32 *adv_credits, int need_posted) + u32 wanted, u32 *adv_credits, int need_posted, int max_posted) { unsigned int avail, posted, got = 0, advertise; long oldval, newval; @@ -351,7 +351,7 @@ int rds_ib_send_grab_credits(struct rds_ib_connection *ic, * available. */ if (posted && (got || need_posted)) { - advertise = min_t(unsigned int, posted, RDS_MAX_ADV_CREDIT); + advertise = min_t(unsigned int, posted, max_posted); newval -= IB_SET_POST_CREDITS(advertise); } @@ -498,7 +498,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, credit_alloc = work_alloc; if (ic->i_flowctl) { - credit_alloc = rds_ib_send_grab_credits(ic, work_alloc, &posted, 0); + credit_alloc = rds_ib_send_grab_credits(ic, work_alloc, &posted, 0, RDS_MAX_ADV_CREDIT); adv_credits += posted; if (credit_alloc < work_alloc) { rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc - credit_alloc); @@ -506,7 +506,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, flow_controlled++; } if (work_alloc == 0) { - rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc); + set_bit(RDS_LL_SEND_FULL, &conn->c_flags); rds_ib_stats_inc(s_ib_tx_throttle); ret = -ENOMEM; goto out; @@ -571,7 +571,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, /* * Update adv_credits since we reset the ACK_REQUIRED bit. */ - rds_ib_send_grab_credits(ic, 0, &posted, 1); + rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); adv_credits += posted; BUG_ON(adv_credits > 255); } else if (ic->i_rm != rm) diff --git a/net/rds/info.c b/net/rds/info.c index 1d885535214d..62aeef37aefe 100644 --- a/net/rds/info.c +++ b/net/rds/info.c @@ -188,10 +188,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval, ret = -ENOMEM; goto out; } - down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, start, nr_pages, 1, 0, - pages, NULL); - up_read(¤t->mm->mmap_sem); + ret = get_user_pages_fast(start, nr_pages, 1, pages); if (ret != nr_pages) { if (ret > 0) nr_pages = ret; diff --git a/net/rds/iw.c b/net/rds/iw.c index b732efb5b634..d16e1cbc8e83 100644 --- a/net/rds/iw.c +++ b/net/rds/iw.c @@ -233,8 +233,8 @@ static int rds_iw_laddr_check(__be32 addr) * IB and iWARP capable NICs. */ cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP); - if (!cm_id) - return -EADDRNOTAVAIL; + if (IS_ERR(cm_id)) + return PTR_ERR(cm_id); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; diff --git a/net/rds/iw.h b/net/rds/iw.h index b4fb27252895..0715dde323e7 100644 --- a/net/rds/iw.h +++ b/net/rds/iw.h @@ -361,7 +361,7 @@ int rds_iw_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op); void rds_iw_send_add_credits(struct rds_connection *conn, unsigned int credits); void rds_iw_advertise_credits(struct rds_connection *conn, unsigned int posted); int rds_iw_send_grab_credits(struct rds_iw_connection *ic, u32 wanted, - u32 *adv_credits, int need_posted); + u32 *adv_credits, int need_posted, int max_posted); /* ib_stats.c */ DECLARE_PER_CPU(struct rds_iw_statistics, rds_iw_stats); diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index fde470fa50d5..8683f5f66c4b 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c @@ -524,7 +524,7 @@ void rds_iw_attempt_ack(struct rds_iw_connection *ic) } /* Can we get a send credit? */ - if (!rds_iw_send_grab_credits(ic, 1, &adv_credits, 0)) { + if (!rds_iw_send_grab_credits(ic, 1, &adv_credits, 0, RDS_MAX_ADV_CREDIT)) { rds_iw_stats_inc(s_iw_tx_throttle); clear_bit(IB_ACK_IN_FLIGHT, &ic->i_ack_flags); return; diff --git a/net/rds/iw_ring.c b/net/rds/iw_ring.c index d422d4b5deef..da8e3b63f663 100644 --- a/net/rds/iw_ring.c +++ b/net/rds/iw_ring.c @@ -137,7 +137,7 @@ int rds_iw_ring_empty(struct rds_iw_work_ring *ring) int rds_iw_ring_low(struct rds_iw_work_ring *ring) { - return __rds_iw_ring_used(ring) <= (ring->w_nr >> 2); + return __rds_iw_ring_used(ring) <= (ring->w_nr >> 1); } diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 22dd38ffd608..44a6a0551f28 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c @@ -347,7 +347,7 @@ void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context) * and using atomic_cmpxchg when updating the two counters. */ int rds_iw_send_grab_credits(struct rds_iw_connection *ic, - u32 wanted, u32 *adv_credits, int need_posted) + u32 wanted, u32 *adv_credits, int need_posted, int max_posted) { unsigned int avail, posted, got = 0, advertise; long oldval, newval; @@ -387,7 +387,7 @@ int rds_iw_send_grab_credits(struct rds_iw_connection *ic, * available. */ if (posted && (got || need_posted)) { - advertise = min_t(unsigned int, posted, RDS_MAX_ADV_CREDIT); + advertise = min_t(unsigned int, posted, max_posted); newval -= IB_SET_POST_CREDITS(advertise); } @@ -541,7 +541,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, credit_alloc = work_alloc; if (ic->i_flowctl) { - credit_alloc = rds_iw_send_grab_credits(ic, work_alloc, &posted, 0); + credit_alloc = rds_iw_send_grab_credits(ic, work_alloc, &posted, 0, RDS_MAX_ADV_CREDIT); adv_credits += posted; if (credit_alloc < work_alloc) { rds_iw_ring_unalloc(&ic->i_send_ring, work_alloc - credit_alloc); @@ -549,7 +549,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, flow_controlled++; } if (work_alloc == 0) { - rds_iw_ring_unalloc(&ic->i_send_ring, work_alloc); + set_bit(RDS_LL_SEND_FULL, &conn->c_flags); rds_iw_stats_inc(s_iw_tx_throttle); ret = -ENOMEM; goto out; @@ -614,7 +614,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, /* * Update adv_credits since we reset the ACK_REQUIRED bit. */ - rds_iw_send_grab_credits(ic, 0, &posted, 1); + rds_iw_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); adv_credits += posted; BUG_ON(adv_credits > 255); } else if (ic->i_rm != rm) diff --git a/net/rds/rdma.c b/net/rds/rdma.c index eaeeb91e1119..8dc83d2caa58 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -150,12 +150,9 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages, { int ret; - down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, user_addr, - nr_pages, write, 0, pages, NULL); - up_read(¤t->mm->mmap_sem); + ret = get_user_pages_fast(user_addr, nr_pages, write, pages); - if (0 <= ret && (unsigned) ret < nr_pages) { + if (ret >= 0 && ret < nr_pages) { while (ret--) put_page(pages[ret]); ret = -EFAULT; diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 7b19024f9706..7d0f901c93d5 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c @@ -34,7 +34,7 @@ #include "rdma_transport.h" -static struct rdma_cm_id *rds_iw_listen_id; +static struct rdma_cm_id *rds_rdma_listen_id; int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, struct rdma_cm_event *event) @@ -161,7 +161,7 @@ static int __init rds_rdma_listen_init(void) rdsdebug("cm %p listening on port %u\n", cm_id, RDS_PORT); - rds_iw_listen_id = cm_id; + rds_rdma_listen_id = cm_id; cm_id = NULL; out: if (cm_id) @@ -171,10 +171,10 @@ static int __init rds_rdma_listen_init(void) static void rds_rdma_listen_stop(void) { - if (rds_iw_listen_id) { - rdsdebug("cm %p\n", rds_iw_listen_id); - rdma_destroy_id(rds_iw_listen_id); - rds_iw_listen_id = NULL; + if (rds_rdma_listen_id) { + rdsdebug("cm %p\n", rds_rdma_listen_id); + rdma_destroy_id(rds_rdma_listen_id); + rds_rdma_listen_id = NULL; } } diff --git a/net/rds/rds.h b/net/rds/rds.h index 71794449ca4e..dbe111236783 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -132,7 +132,7 @@ struct rds_connection { #define RDS_FLAG_CONG_BITMAP 0x01 #define RDS_FLAG_ACK_REQUIRED 0x02 #define RDS_FLAG_RETRANSMITTED 0x04 -#define RDS_MAX_ADV_CREDIT 127 +#define RDS_MAX_ADV_CREDIT 255 /* * Maximum space available for extension headers. diff --git a/net/rds/send.c b/net/rds/send.c index 104fe033203d..a4a7f428cd76 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -854,11 +854,6 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rm->m_daddr = daddr; - /* Parse any control messages the user may have included. */ - ret = rds_cmsg_send(rs, rm, msg, &allocated_mr); - if (ret) - goto out; - /* rds_conn_create has a spinlock that runs with IRQ off. * Caching the conn in the socket helps a lot. */ if (rs->rs_conn && rs->rs_conn->c_faddr == daddr) @@ -874,6 +869,11 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rs->rs_conn = conn; } + /* Parse any control messages the user may have included. */ + ret = rds_cmsg_send(rs, rm, msg, &allocated_mr); + if (ret) + goto out; + if ((rm->m_rdma_cookie || rm->m_rdma_op) && conn->c_trans->xmit_rdma == NULL) { if (printk_ratelimit()) diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig index 7f807b30cfbb..eaf765876458 100644 --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig @@ -10,22 +10,15 @@ menuconfig RFKILL To compile this driver as a module, choose M here: the module will be called rfkill. -config RFKILL_INPUT - tristate "Input layer to RF switch connector" - depends on RFKILL && INPUT - help - Say Y here if you want kernel automatically toggle state - of RF switches on and off when user presses appropriate - button or a key on the keyboard. Without this module you - need a some kind of userspace application to control - state of the switches. - - To compile this driver as a module, choose M here: the - module will be called rfkill-input. - # LED trigger support config RFKILL_LEDS bool - depends on RFKILL && LEDS_TRIGGERS + depends on RFKILL + depends on LEDS_TRIGGERS = y || RFKILL = LEDS_TRIGGERS default y +config RFKILL_INPUT + bool "RF switch input support" if EMBEDDED + depends on RFKILL + depends on INPUT = y || RFKILL = INPUT + default y if !EMBEDDED diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile index b38c430be057..662105352691 100644 --- a/net/rfkill/Makefile +++ b/net/rfkill/Makefile @@ -2,5 +2,6 @@ # Makefile for the RF switch subsystem. # -obj-$(CONFIG_RFKILL) += rfkill.o -obj-$(CONFIG_RFKILL_INPUT) += rfkill-input.o +rfkill-y += core.o +rfkill-$(CONFIG_RFKILL_INPUT) += input.o +obj-$(CONFIG_RFKILL) += rfkill.o diff --git a/net/rfkill/core.c b/net/rfkill/core.c new file mode 100644 index 000000000000..4e68ab439d5d --- /dev/null +++ b/net/rfkill/core.c @@ -0,0 +1,1205 @@ +/* + * Copyright (C) 2006 - 2007 Ivo van Doorn + * Copyright (C) 2007 Dmitry Torokhov + * Copyright 2009 Johannes Berg + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rfkill.h" + +#define POLL_INTERVAL (5 * HZ) + +#define RFKILL_BLOCK_HW BIT(0) +#define RFKILL_BLOCK_SW BIT(1) +#define RFKILL_BLOCK_SW_PREV BIT(2) +#define RFKILL_BLOCK_ANY (RFKILL_BLOCK_HW |\ + RFKILL_BLOCK_SW |\ + RFKILL_BLOCK_SW_PREV) +#define RFKILL_BLOCK_SW_SETCALL BIT(31) + +struct rfkill { + spinlock_t lock; + + const char *name; + enum rfkill_type type; + + unsigned long state; + + u32 idx; + + bool registered; + bool suspended; + bool persistent; + + const struct rfkill_ops *ops; + void *data; + +#ifdef CONFIG_RFKILL_LEDS + struct led_trigger led_trigger; + const char *ledtrigname; +#endif + + struct device dev; + struct list_head node; + + struct delayed_work poll_work; + struct work_struct uevent_work; + struct work_struct sync_work; +}; +#define to_rfkill(d) container_of(d, struct rfkill, dev) + +struct rfkill_int_event { + struct list_head list; + struct rfkill_event ev; +}; + +struct rfkill_data { + struct list_head list; + struct list_head events; + struct mutex mtx; + wait_queue_head_t read_wait; + bool input_handler; +}; + + +MODULE_AUTHOR("Ivo van Doorn "); +MODULE_AUTHOR("Johannes Berg "); +MODULE_DESCRIPTION("RF switch support"); +MODULE_LICENSE("GPL"); + + +/* + * The locking here should be made much smarter, we currently have + * a bit of a stupid situation because drivers might want to register + * the rfkill struct under their own lock, and take this lock during + * rfkill method calls -- which will cause an AB-BA deadlock situation. + * + * To fix that, we need to rework this code here to be mostly lock-free + * and only use the mutex for list manipulations, not to protect the + * various other global variables. Then we can avoid holding the mutex + * around driver operations, and all is happy. + */ +static LIST_HEAD(rfkill_list); /* list of registered rf switches */ +static DEFINE_MUTEX(rfkill_global_mutex); +static LIST_HEAD(rfkill_fds); /* list of open fds of /dev/rfkill */ + +static unsigned int rfkill_default_state = 1; +module_param_named(default_state, rfkill_default_state, uint, 0444); +MODULE_PARM_DESC(default_state, + "Default initial state for all radio types, 0 = radio off"); + +static struct { + bool cur, sav; +} rfkill_global_states[NUM_RFKILL_TYPES]; + +static bool rfkill_epo_lock_active; + + +#ifdef CONFIG_RFKILL_LEDS +static void rfkill_led_trigger_event(struct rfkill *rfkill) +{ + struct led_trigger *trigger; + + if (!rfkill->registered) + return; + + trigger = &rfkill->led_trigger; + + if (rfkill->state & RFKILL_BLOCK_ANY) + led_trigger_event(trigger, LED_OFF); + else + led_trigger_event(trigger, LED_FULL); +} + +static void rfkill_led_trigger_activate(struct led_classdev *led) +{ + struct rfkill *rfkill; + + rfkill = container_of(led->trigger, struct rfkill, led_trigger); + + rfkill_led_trigger_event(rfkill); +} + +const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) +{ + return rfkill->led_trigger.name; +} +EXPORT_SYMBOL(rfkill_get_led_trigger_name); + +void rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name) +{ + BUG_ON(!rfkill); + + rfkill->ledtrigname = name; +} +EXPORT_SYMBOL(rfkill_set_led_trigger_name); + +static int rfkill_led_trigger_register(struct rfkill *rfkill) +{ + rfkill->led_trigger.name = rfkill->ledtrigname + ? : dev_name(&rfkill->dev); + rfkill->led_trigger.activate = rfkill_led_trigger_activate; + return led_trigger_register(&rfkill->led_trigger); +} + +static void rfkill_led_trigger_unregister(struct rfkill *rfkill) +{ + led_trigger_unregister(&rfkill->led_trigger); +} +#else +static void rfkill_led_trigger_event(struct rfkill *rfkill) +{ +} + +static inline int rfkill_led_trigger_register(struct rfkill *rfkill) +{ + return 0; +} + +static inline void rfkill_led_trigger_unregister(struct rfkill *rfkill) +{ +} +#endif /* CONFIG_RFKILL_LEDS */ + +static void rfkill_fill_event(struct rfkill_event *ev, struct rfkill *rfkill, + enum rfkill_operation op) +{ + unsigned long flags; + + ev->idx = rfkill->idx; + ev->type = rfkill->type; + ev->op = op; + + spin_lock_irqsave(&rfkill->lock, flags); + ev->hard = !!(rfkill->state & RFKILL_BLOCK_HW); + ev->soft = !!(rfkill->state & (RFKILL_BLOCK_SW | + RFKILL_BLOCK_SW_PREV)); + spin_unlock_irqrestore(&rfkill->lock, flags); +} + +static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op) +{ + struct rfkill_data *data; + struct rfkill_int_event *ev; + + list_for_each_entry(data, &rfkill_fds, list) { + ev = kzalloc(sizeof(*ev), GFP_KERNEL); + if (!ev) + continue; + rfkill_fill_event(&ev->ev, rfkill, op); + mutex_lock(&data->mtx); + list_add_tail(&ev->list, &data->events); + mutex_unlock(&data->mtx); + wake_up_interruptible(&data->read_wait); + } +} + +static void rfkill_event(struct rfkill *rfkill) +{ + if (!rfkill->registered || rfkill->suspended) + return; + + kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); + + /* also send event to /dev/rfkill */ + rfkill_send_events(rfkill, RFKILL_OP_CHANGE); +} + +static bool __rfkill_set_hw_state(struct rfkill *rfkill, + bool blocked, bool *change) +{ + unsigned long flags; + bool prev, any; + + BUG_ON(!rfkill); + + spin_lock_irqsave(&rfkill->lock, flags); + prev = !!(rfkill->state & RFKILL_BLOCK_HW); + if (blocked) + rfkill->state |= RFKILL_BLOCK_HW; + else + rfkill->state &= ~RFKILL_BLOCK_HW; + *change = prev != blocked; + any = rfkill->state & RFKILL_BLOCK_ANY; + spin_unlock_irqrestore(&rfkill->lock, flags); + + rfkill_led_trigger_event(rfkill); + + return any; +} + +/** + * rfkill_set_block - wrapper for set_block method + * + * @rfkill: the rfkill struct to use + * @blocked: the new software state + * + * Calls the set_block method (when applicable) and handles notifications + * etc. as well. + */ +static void rfkill_set_block(struct rfkill *rfkill, bool blocked) +{ + unsigned long flags; + int err; + + /* + * Some platforms (...!) generate input events which affect the + * _hard_ kill state -- whenever something tries to change the + * current software state query the hardware state too. + */ + if (rfkill->ops->query) + rfkill->ops->query(rfkill, rfkill->data); + + spin_lock_irqsave(&rfkill->lock, flags); + if (rfkill->state & RFKILL_BLOCK_SW) + rfkill->state |= RFKILL_BLOCK_SW_PREV; + else + rfkill->state &= ~RFKILL_BLOCK_SW_PREV; + + if (blocked) + rfkill->state |= RFKILL_BLOCK_SW; + else + rfkill->state &= ~RFKILL_BLOCK_SW; + + rfkill->state |= RFKILL_BLOCK_SW_SETCALL; + spin_unlock_irqrestore(&rfkill->lock, flags); + + if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) + return; + + err = rfkill->ops->set_block(rfkill->data, blocked); + + spin_lock_irqsave(&rfkill->lock, flags); + if (err) { + /* + * Failed -- reset status to _prev, this may be different + * from what set set _PREV to earlier in this function + * if rfkill_set_sw_state was invoked. + */ + if (rfkill->state & RFKILL_BLOCK_SW_PREV) + rfkill->state |= RFKILL_BLOCK_SW; + else + rfkill->state &= ~RFKILL_BLOCK_SW; + } + rfkill->state &= ~RFKILL_BLOCK_SW_SETCALL; + rfkill->state &= ~RFKILL_BLOCK_SW_PREV; + spin_unlock_irqrestore(&rfkill->lock, flags); + + rfkill_led_trigger_event(rfkill); + rfkill_event(rfkill); +} + +#ifdef CONFIG_RFKILL_INPUT +static atomic_t rfkill_input_disabled = ATOMIC_INIT(0); + +/** + * __rfkill_switch_all - Toggle state of all switches of given type + * @type: type of interfaces to be affected + * @state: the new state + * + * This function sets the state of all switches of given type, + * unless a specific switch is claimed by userspace (in which case, + * that switch is left alone) or suspended. + * + * Caller must have acquired rfkill_global_mutex. + */ +static void __rfkill_switch_all(const enum rfkill_type type, bool blocked) +{ + struct rfkill *rfkill; + + rfkill_global_states[type].cur = blocked; + list_for_each_entry(rfkill, &rfkill_list, node) { + if (rfkill->type != type) + continue; + + rfkill_set_block(rfkill, blocked); + } +} + +/** + * rfkill_switch_all - Toggle state of all switches of given type + * @type: type of interfaces to be affected + * @state: the new state + * + * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state). + * Please refer to __rfkill_switch_all() for details. + * + * Does nothing if the EPO lock is active. + */ +void rfkill_switch_all(enum rfkill_type type, bool blocked) +{ + if (atomic_read(&rfkill_input_disabled)) + return; + + mutex_lock(&rfkill_global_mutex); + + if (!rfkill_epo_lock_active) + __rfkill_switch_all(type, blocked); + + mutex_unlock(&rfkill_global_mutex); +} + +/** + * rfkill_epo - emergency power off all transmitters + * + * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, + * ignoring everything in its path but rfkill_global_mutex and rfkill->mutex. + * + * The global state before the EPO is saved and can be restored later + * using rfkill_restore_states(). + */ +void rfkill_epo(void) +{ + struct rfkill *rfkill; + int i; + + if (atomic_read(&rfkill_input_disabled)) + return; + + mutex_lock(&rfkill_global_mutex); + + rfkill_epo_lock_active = true; + list_for_each_entry(rfkill, &rfkill_list, node) + rfkill_set_block(rfkill, true); + + for (i = 0; i < NUM_RFKILL_TYPES; i++) { + rfkill_global_states[i].sav = rfkill_global_states[i].cur; + rfkill_global_states[i].cur = true; + } + + mutex_unlock(&rfkill_global_mutex); +} + +/** + * rfkill_restore_states - restore global states + * + * Restore (and sync switches to) the global state from the + * states in rfkill_default_states. This can undo the effects of + * a call to rfkill_epo(). + */ +void rfkill_restore_states(void) +{ + int i; + + if (atomic_read(&rfkill_input_disabled)) + return; + + mutex_lock(&rfkill_global_mutex); + + rfkill_epo_lock_active = false; + for (i = 0; i < NUM_RFKILL_TYPES; i++) + __rfkill_switch_all(i, rfkill_global_states[i].sav); + mutex_unlock(&rfkill_global_mutex); +} + +/** + * rfkill_remove_epo_lock - unlock state changes + * + * Used by rfkill-input manually unlock state changes, when + * the EPO switch is deactivated. + */ +void rfkill_remove_epo_lock(void) +{ + if (atomic_read(&rfkill_input_disabled)) + return; + + mutex_lock(&rfkill_global_mutex); + rfkill_epo_lock_active = false; + mutex_unlock(&rfkill_global_mutex); +} + +/** + * rfkill_is_epo_lock_active - returns true EPO is active + * + * Returns 0 (false) if there is NOT an active EPO contidion, + * and 1 (true) if there is an active EPO contition, which + * locks all radios in one of the BLOCKED states. + * + * Can be called in atomic context. + */ +bool rfkill_is_epo_lock_active(void) +{ + return rfkill_epo_lock_active; +} + +/** + * rfkill_get_global_sw_state - returns global state for a type + * @type: the type to get the global state of + * + * Returns the current global state for a given wireless + * device type. + */ +bool rfkill_get_global_sw_state(const enum rfkill_type type) +{ + return rfkill_global_states[type].cur; +} +#endif + + +bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked) +{ + bool ret, change; + + ret = __rfkill_set_hw_state(rfkill, blocked, &change); + + if (!rfkill->registered) + return ret; + + if (change) + schedule_work(&rfkill->uevent_work); + + return ret; +} +EXPORT_SYMBOL(rfkill_set_hw_state); + +static void __rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) +{ + u32 bit = RFKILL_BLOCK_SW; + + /* if in a ops->set_block right now, use other bit */ + if (rfkill->state & RFKILL_BLOCK_SW_SETCALL) + bit = RFKILL_BLOCK_SW_PREV; + + if (blocked) + rfkill->state |= bit; + else + rfkill->state &= ~bit; +} + +bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) +{ + unsigned long flags; + bool prev, hwblock; + + BUG_ON(!rfkill); + + spin_lock_irqsave(&rfkill->lock, flags); + prev = !!(rfkill->state & RFKILL_BLOCK_SW); + __rfkill_set_sw_state(rfkill, blocked); + hwblock = !!(rfkill->state & RFKILL_BLOCK_HW); + blocked = blocked || hwblock; + spin_unlock_irqrestore(&rfkill->lock, flags); + + if (!rfkill->registered) { + rfkill->persistent = true; + } else { + if (prev != blocked && !hwblock) + schedule_work(&rfkill->uevent_work); + + rfkill_led_trigger_event(rfkill); + } + + return blocked; +} +EXPORT_SYMBOL(rfkill_set_sw_state); + +void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) +{ + unsigned long flags; + bool swprev, hwprev; + + BUG_ON(!rfkill); + + spin_lock_irqsave(&rfkill->lock, flags); + + /* + * No need to care about prev/setblock ... this is for uevent only + * and that will get triggered by rfkill_set_block anyway. + */ + swprev = !!(rfkill->state & RFKILL_BLOCK_SW); + hwprev = !!(rfkill->state & RFKILL_BLOCK_HW); + __rfkill_set_sw_state(rfkill, sw); + + spin_unlock_irqrestore(&rfkill->lock, flags); + + if (!rfkill->registered) { + rfkill->persistent = true; + } else { + if (swprev != sw || hwprev != hw) + schedule_work(&rfkill->uevent_work); + + rfkill_led_trigger_event(rfkill); + } +} +EXPORT_SYMBOL(rfkill_set_states); + +static ssize_t rfkill_name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + + return sprintf(buf, "%s\n", rfkill->name); +} + +static const char *rfkill_get_type_str(enum rfkill_type type) +{ + switch (type) { + case RFKILL_TYPE_WLAN: + return "wlan"; + case RFKILL_TYPE_BLUETOOTH: + return "bluetooth"; + case RFKILL_TYPE_UWB: + return "ultrawideband"; + case RFKILL_TYPE_WIMAX: + return "wimax"; + case RFKILL_TYPE_WWAN: + return "wwan"; + default: + BUG(); + } + + BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_WWAN + 1); +} + +static ssize_t rfkill_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + + return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); +} + +static ssize_t rfkill_idx_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + + return sprintf(buf, "%d\n", rfkill->idx); +} + +static u8 user_state_from_blocked(unsigned long state) +{ + if (state & RFKILL_BLOCK_HW) + return RFKILL_USER_STATE_HARD_BLOCKED; + if (state & RFKILL_BLOCK_SW) + return RFKILL_USER_STATE_SOFT_BLOCKED; + + return RFKILL_USER_STATE_UNBLOCKED; +} + +static ssize_t rfkill_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + unsigned long flags; + u32 state; + + spin_lock_irqsave(&rfkill->lock, flags); + state = rfkill->state; + spin_unlock_irqrestore(&rfkill->lock, flags); + + return sprintf(buf, "%d\n", user_state_from_blocked(state)); +} + +static ssize_t rfkill_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + /* + * The intention was that userspace can only take control over + * a given device when/if rfkill-input doesn't control it due + * to user_claim. Since user_claim is currently unsupported, + * we never support changing the state from userspace -- this + * can be implemented again later. + */ + + return -EPERM; +} + +static ssize_t rfkill_claim_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", 0); +} + +static ssize_t rfkill_claim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return -EOPNOTSUPP; +} + +static struct device_attribute rfkill_dev_attrs[] = { + __ATTR(name, S_IRUGO, rfkill_name_show, NULL), + __ATTR(type, S_IRUGO, rfkill_type_show, NULL), + __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), + __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), + __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), + __ATTR_NULL +}; + +static void rfkill_release(struct device *dev) +{ + struct rfkill *rfkill = to_rfkill(dev); + + kfree(rfkill); +} + +static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct rfkill *rfkill = to_rfkill(dev); + unsigned long flags; + u32 state; + int error; + + error = add_uevent_var(env, "RFKILL_NAME=%s", rfkill->name); + if (error) + return error; + error = add_uevent_var(env, "RFKILL_TYPE=%s", + rfkill_get_type_str(rfkill->type)); + if (error) + return error; + spin_lock_irqsave(&rfkill->lock, flags); + state = rfkill->state; + spin_unlock_irqrestore(&rfkill->lock, flags); + error = add_uevent_var(env, "RFKILL_STATE=%d", + user_state_from_blocked(state)); + return error; +} + +void rfkill_pause_polling(struct rfkill *rfkill) +{ + BUG_ON(!rfkill); + + if (!rfkill->ops->poll) + return; + + cancel_delayed_work_sync(&rfkill->poll_work); +} +EXPORT_SYMBOL(rfkill_pause_polling); + +void rfkill_resume_polling(struct rfkill *rfkill) +{ + BUG_ON(!rfkill); + + if (!rfkill->ops->poll) + return; + + schedule_work(&rfkill->poll_work.work); +} +EXPORT_SYMBOL(rfkill_resume_polling); + +static int rfkill_suspend(struct device *dev, pm_message_t state) +{ + struct rfkill *rfkill = to_rfkill(dev); + + rfkill_pause_polling(rfkill); + + rfkill->suspended = true; + + return 0; +} + +static int rfkill_resume(struct device *dev) +{ + struct rfkill *rfkill = to_rfkill(dev); + bool cur; + + cur = !!(rfkill->state & RFKILL_BLOCK_SW); + rfkill_set_block(rfkill, cur); + + rfkill->suspended = false; + + rfkill_resume_polling(rfkill); + + return 0; +} + +static struct class rfkill_class = { + .name = "rfkill", + .dev_release = rfkill_release, + .dev_attrs = rfkill_dev_attrs, + .dev_uevent = rfkill_dev_uevent, + .suspend = rfkill_suspend, + .resume = rfkill_resume, +}; + +bool rfkill_blocked(struct rfkill *rfkill) +{ + unsigned long flags; + u32 state; + + spin_lock_irqsave(&rfkill->lock, flags); + state = rfkill->state; + spin_unlock_irqrestore(&rfkill->lock, flags); + + return !!(state & RFKILL_BLOCK_ANY); +} +EXPORT_SYMBOL(rfkill_blocked); + + +struct rfkill * __must_check rfkill_alloc(const char *name, + struct device *parent, + const enum rfkill_type type, + const struct rfkill_ops *ops, + void *ops_data) +{ + struct rfkill *rfkill; + struct device *dev; + + if (WARN_ON(!ops)) + return NULL; + + if (WARN_ON(!ops->set_block)) + return NULL; + + if (WARN_ON(!name)) + return NULL; + + if (WARN_ON(type == RFKILL_TYPE_ALL || type >= NUM_RFKILL_TYPES)) + return NULL; + + rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); + if (!rfkill) + return NULL; + + spin_lock_init(&rfkill->lock); + INIT_LIST_HEAD(&rfkill->node); + rfkill->type = type; + rfkill->name = name; + rfkill->ops = ops; + rfkill->data = ops_data; + + dev = &rfkill->dev; + dev->class = &rfkill_class; + dev->parent = parent; + device_initialize(dev); + + return rfkill; +} +EXPORT_SYMBOL(rfkill_alloc); + +static void rfkill_poll(struct work_struct *work) +{ + struct rfkill *rfkill; + + rfkill = container_of(work, struct rfkill, poll_work.work); + + /* + * Poll hardware state -- driver will use one of the + * rfkill_set{,_hw,_sw}_state functions and use its + * return value to update the current status. + */ + rfkill->ops->poll(rfkill, rfkill->data); + + schedule_delayed_work(&rfkill->poll_work, + round_jiffies_relative(POLL_INTERVAL)); +} + +static void rfkill_uevent_work(struct work_struct *work) +{ + struct rfkill *rfkill; + + rfkill = container_of(work, struct rfkill, uevent_work); + + mutex_lock(&rfkill_global_mutex); + rfkill_event(rfkill); + mutex_unlock(&rfkill_global_mutex); +} + +static void rfkill_sync_work(struct work_struct *work) +{ + struct rfkill *rfkill; + bool cur; + + rfkill = container_of(work, struct rfkill, sync_work); + + mutex_lock(&rfkill_global_mutex); + cur = rfkill_global_states[rfkill->type].cur; + rfkill_set_block(rfkill, cur); + mutex_unlock(&rfkill_global_mutex); +} + +int __must_check rfkill_register(struct rfkill *rfkill) +{ + static unsigned long rfkill_no; + struct device *dev = &rfkill->dev; + int error; + + BUG_ON(!rfkill); + + mutex_lock(&rfkill_global_mutex); + + if (rfkill->registered) { + error = -EALREADY; + goto unlock; + } + + rfkill->idx = rfkill_no; + dev_set_name(dev, "rfkill%lu", rfkill_no); + rfkill_no++; + + list_add_tail(&rfkill->node, &rfkill_list); + + error = device_add(dev); + if (error) + goto remove; + + error = rfkill_led_trigger_register(rfkill); + if (error) + goto devdel; + + rfkill->registered = true; + + INIT_DELAYED_WORK(&rfkill->poll_work, rfkill_poll); + INIT_WORK(&rfkill->uevent_work, rfkill_uevent_work); + INIT_WORK(&rfkill->sync_work, rfkill_sync_work); + + if (rfkill->ops->poll) + schedule_delayed_work(&rfkill->poll_work, + round_jiffies_relative(POLL_INTERVAL)); + + if (!rfkill->persistent || rfkill_epo_lock_active) { + schedule_work(&rfkill->sync_work); + } else { +#ifdef CONFIG_RFKILL_INPUT + bool soft_blocked = !!(rfkill->state & RFKILL_BLOCK_SW); + + if (!atomic_read(&rfkill_input_disabled)) + __rfkill_switch_all(rfkill->type, soft_blocked); +#endif + } + + rfkill_send_events(rfkill, RFKILL_OP_ADD); + + mutex_unlock(&rfkill_global_mutex); + return 0; + + devdel: + device_del(&rfkill->dev); + remove: + list_del_init(&rfkill->node); + unlock: + mutex_unlock(&rfkill_global_mutex); + return error; +} +EXPORT_SYMBOL(rfkill_register); + +void rfkill_unregister(struct rfkill *rfkill) +{ + BUG_ON(!rfkill); + + if (rfkill->ops->poll) + cancel_delayed_work_sync(&rfkill->poll_work); + + cancel_work_sync(&rfkill->uevent_work); + cancel_work_sync(&rfkill->sync_work); + + rfkill->registered = false; + + device_del(&rfkill->dev); + + mutex_lock(&rfkill_global_mutex); + rfkill_send_events(rfkill, RFKILL_OP_DEL); + list_del_init(&rfkill->node); + mutex_unlock(&rfkill_global_mutex); + + rfkill_led_trigger_unregister(rfkill); +} +EXPORT_SYMBOL(rfkill_unregister); + +void rfkill_destroy(struct rfkill *rfkill) +{ + if (rfkill) + put_device(&rfkill->dev); +} +EXPORT_SYMBOL(rfkill_destroy); + +static int rfkill_fop_open(struct inode *inode, struct file *file) +{ + struct rfkill_data *data; + struct rfkill *rfkill; + struct rfkill_int_event *ev, *tmp; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + INIT_LIST_HEAD(&data->events); + mutex_init(&data->mtx); + init_waitqueue_head(&data->read_wait); + + mutex_lock(&rfkill_global_mutex); + mutex_lock(&data->mtx); + /* + * start getting events from elsewhere but hold mtx to get + * startup events added first + */ + list_add(&data->list, &rfkill_fds); + + list_for_each_entry(rfkill, &rfkill_list, node) { + ev = kzalloc(sizeof(*ev), GFP_KERNEL); + if (!ev) + goto free; + rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); + list_add_tail(&ev->list, &data->events); + } + mutex_unlock(&data->mtx); + mutex_unlock(&rfkill_global_mutex); + + file->private_data = data; + + return nonseekable_open(inode, file); + + free: + mutex_unlock(&data->mtx); + mutex_unlock(&rfkill_global_mutex); + mutex_destroy(&data->mtx); + list_for_each_entry_safe(ev, tmp, &data->events, list) + kfree(ev); + kfree(data); + return -ENOMEM; +} + +static unsigned int rfkill_fop_poll(struct file *file, poll_table *wait) +{ + struct rfkill_data *data = file->private_data; + unsigned int res = POLLOUT | POLLWRNORM; + + poll_wait(file, &data->read_wait, wait); + + mutex_lock(&data->mtx); + if (!list_empty(&data->events)) + res = POLLIN | POLLRDNORM; + mutex_unlock(&data->mtx); + + return res; +} + +static bool rfkill_readable(struct rfkill_data *data) +{ + bool r; + + mutex_lock(&data->mtx); + r = !list_empty(&data->events); + mutex_unlock(&data->mtx); + + return r; +} + +static ssize_t rfkill_fop_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + struct rfkill_data *data = file->private_data; + struct rfkill_int_event *ev; + unsigned long sz; + int ret; + + mutex_lock(&data->mtx); + + while (list_empty(&data->events)) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto out; + } + mutex_unlock(&data->mtx); + ret = wait_event_interruptible(data->read_wait, + rfkill_readable(data)); + mutex_lock(&data->mtx); + + if (ret) + goto out; + } + + ev = list_first_entry(&data->events, struct rfkill_int_event, + list); + + sz = min_t(unsigned long, sizeof(ev->ev), count); + ret = sz; + if (copy_to_user(buf, &ev->ev, sz)) + ret = -EFAULT; + + list_del(&ev->list); + kfree(ev); + out: + mutex_unlock(&data->mtx); + return ret; +} + +static ssize_t rfkill_fop_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + struct rfkill *rfkill; + struct rfkill_event ev; + + /* we don't need the 'hard' variable but accept it */ + if (count < sizeof(ev) - 1) + return -EINVAL; + + if (copy_from_user(&ev, buf, sizeof(ev) - 1)) + return -EFAULT; + + if (ev.op != RFKILL_OP_CHANGE && ev.op != RFKILL_OP_CHANGE_ALL) + return -EINVAL; + + if (ev.type >= NUM_RFKILL_TYPES) + return -EINVAL; + + mutex_lock(&rfkill_global_mutex); + + if (ev.op == RFKILL_OP_CHANGE_ALL) { + if (ev.type == RFKILL_TYPE_ALL) { + enum rfkill_type i; + for (i = 0; i < NUM_RFKILL_TYPES; i++) + rfkill_global_states[i].cur = ev.soft; + } else { + rfkill_global_states[ev.type].cur = ev.soft; + } + } + + list_for_each_entry(rfkill, &rfkill_list, node) { + if (rfkill->idx != ev.idx && ev.op != RFKILL_OP_CHANGE_ALL) + continue; + + if (rfkill->type != ev.type && ev.type != RFKILL_TYPE_ALL) + continue; + + rfkill_set_block(rfkill, ev.soft); + } + mutex_unlock(&rfkill_global_mutex); + + return count; +} + +static int rfkill_fop_release(struct inode *inode, struct file *file) +{ + struct rfkill_data *data = file->private_data; + struct rfkill_int_event *ev, *tmp; + + mutex_lock(&rfkill_global_mutex); + list_del(&data->list); + mutex_unlock(&rfkill_global_mutex); + + mutex_destroy(&data->mtx); + list_for_each_entry_safe(ev, tmp, &data->events, list) + kfree(ev); + +#ifdef CONFIG_RFKILL_INPUT + if (data->input_handler) + if (atomic_dec_return(&rfkill_input_disabled) == 0) + printk(KERN_DEBUG "rfkill: input handler enabled\n"); +#endif + + kfree(data); + + return 0; +} + +#ifdef CONFIG_RFKILL_INPUT +static long rfkill_fop_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct rfkill_data *data = file->private_data; + + if (_IOC_TYPE(cmd) != RFKILL_IOC_MAGIC) + return -ENOSYS; + + if (_IOC_NR(cmd) != RFKILL_IOC_NOINPUT) + return -ENOSYS; + + mutex_lock(&data->mtx); + + if (!data->input_handler) { + if (atomic_inc_return(&rfkill_input_disabled) == 1) + printk(KERN_DEBUG "rfkill: input handler disabled\n"); + data->input_handler = true; + } + + mutex_unlock(&data->mtx); + + return 0; +} +#endif + +static const struct file_operations rfkill_fops = { + .open = rfkill_fop_open, + .read = rfkill_fop_read, + .write = rfkill_fop_write, + .poll = rfkill_fop_poll, + .release = rfkill_fop_release, +#ifdef CONFIG_RFKILL_INPUT + .unlocked_ioctl = rfkill_fop_ioctl, + .compat_ioctl = rfkill_fop_ioctl, +#endif +}; + +static struct miscdevice rfkill_miscdev = { + .name = "rfkill", + .fops = &rfkill_fops, + .minor = MISC_DYNAMIC_MINOR, +}; + +static int __init rfkill_init(void) +{ + int error; + int i; + + for (i = 0; i < NUM_RFKILL_TYPES; i++) + rfkill_global_states[i].cur = !rfkill_default_state; + + error = class_register(&rfkill_class); + if (error) + goto out; + + error = misc_register(&rfkill_miscdev); + if (error) { + class_unregister(&rfkill_class); + goto out; + } + +#ifdef CONFIG_RFKILL_INPUT + error = rfkill_handler_init(); + if (error) { + misc_deregister(&rfkill_miscdev); + class_unregister(&rfkill_class); + goto out; + } +#endif + + out: + return error; +} +subsys_initcall(rfkill_init); + +static void __exit rfkill_exit(void) +{ +#ifdef CONFIG_RFKILL_INPUT + rfkill_handler_exit(); +#endif + misc_deregister(&rfkill_miscdev); + class_unregister(&rfkill_class); +} +module_exit(rfkill_exit); diff --git a/net/rfkill/input.c b/net/rfkill/input.c new file mode 100644 index 000000000000..a7295ad5f9cb --- /dev/null +++ b/net/rfkill/input.c @@ -0,0 +1,342 @@ +/* + * Input layer to RF Kill interface connector + * + * Copyright (c) 2007 Dmitry Torokhov + * Copyright 2009 Johannes Berg + * + * 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. + * + * If you ever run into a situation in which you have a SW_ type rfkill + * input device, then you can revive code that was removed in the patch + * "rfkill-input: remove unused code". + */ + +#include +#include +#include +#include +#include +#include + +#include "rfkill.h" + +enum rfkill_input_master_mode { + RFKILL_INPUT_MASTER_UNLOCK = 0, + RFKILL_INPUT_MASTER_RESTORE = 1, + RFKILL_INPUT_MASTER_UNBLOCKALL = 2, + NUM_RFKILL_INPUT_MASTER_MODES +}; + +/* Delay (in ms) between consecutive switch ops */ +#define RFKILL_OPS_DELAY 200 + +static enum rfkill_input_master_mode rfkill_master_switch_mode = + RFKILL_INPUT_MASTER_UNBLOCKALL; +module_param_named(master_switch_mode, rfkill_master_switch_mode, uint, 0); +MODULE_PARM_DESC(master_switch_mode, + "SW_RFKILL_ALL ON should: 0=do nothing (only unlock); 1=restore; 2=unblock all"); + +static spinlock_t rfkill_op_lock; +static bool rfkill_op_pending; +static unsigned long rfkill_sw_pending[BITS_TO_LONGS(NUM_RFKILL_TYPES)]; +static unsigned long rfkill_sw_state[BITS_TO_LONGS(NUM_RFKILL_TYPES)]; + +enum rfkill_sched_op { + RFKILL_GLOBAL_OP_EPO = 0, + RFKILL_GLOBAL_OP_RESTORE, + RFKILL_GLOBAL_OP_UNLOCK, + RFKILL_GLOBAL_OP_UNBLOCK, +}; + +static enum rfkill_sched_op rfkill_master_switch_op; +static enum rfkill_sched_op rfkill_op; + +static void __rfkill_handle_global_op(enum rfkill_sched_op op) +{ + unsigned int i; + + switch (op) { + case RFKILL_GLOBAL_OP_EPO: + rfkill_epo(); + break; + case RFKILL_GLOBAL_OP_RESTORE: + rfkill_restore_states(); + break; + case RFKILL_GLOBAL_OP_UNLOCK: + rfkill_remove_epo_lock(); + break; + case RFKILL_GLOBAL_OP_UNBLOCK: + rfkill_remove_epo_lock(); + for (i = 0; i < NUM_RFKILL_TYPES; i++) + rfkill_switch_all(i, false); + break; + default: + /* memory corruption or bug, fail safely */ + rfkill_epo(); + WARN(1, "Unknown requested operation %d! " + "rfkill Emergency Power Off activated\n", + op); + } +} + +static void __rfkill_handle_normal_op(const enum rfkill_type type, + const bool complement) +{ + bool blocked; + + blocked = rfkill_get_global_sw_state(type); + if (complement) + blocked = !blocked; + + rfkill_switch_all(type, blocked); +} + +static void rfkill_op_handler(struct work_struct *work) +{ + unsigned int i; + bool c; + + spin_lock_irq(&rfkill_op_lock); + do { + if (rfkill_op_pending) { + enum rfkill_sched_op op = rfkill_op; + rfkill_op_pending = false; + memset(rfkill_sw_pending, 0, + sizeof(rfkill_sw_pending)); + spin_unlock_irq(&rfkill_op_lock); + + __rfkill_handle_global_op(op); + + spin_lock_irq(&rfkill_op_lock); + + /* + * handle global ops first -- during unlocked period + * we might have gotten a new global op. + */ + if (rfkill_op_pending) + continue; + } + + if (rfkill_is_epo_lock_active()) + continue; + + for (i = 0; i < NUM_RFKILL_TYPES; i++) { + if (__test_and_clear_bit(i, rfkill_sw_pending)) { + c = __test_and_clear_bit(i, rfkill_sw_state); + spin_unlock_irq(&rfkill_op_lock); + + __rfkill_handle_normal_op(i, c); + + spin_lock_irq(&rfkill_op_lock); + } + } + } while (rfkill_op_pending); + spin_unlock_irq(&rfkill_op_lock); +} + +static DECLARE_DELAYED_WORK(rfkill_op_work, rfkill_op_handler); +static unsigned long rfkill_last_scheduled; + +static unsigned long rfkill_ratelimit(const unsigned long last) +{ + const unsigned long delay = msecs_to_jiffies(RFKILL_OPS_DELAY); + return (time_after(jiffies, last + delay)) ? 0 : delay; +} + +static void rfkill_schedule_ratelimited(void) +{ + if (delayed_work_pending(&rfkill_op_work)) + return; + schedule_delayed_work(&rfkill_op_work, + rfkill_ratelimit(rfkill_last_scheduled)); + rfkill_last_scheduled = jiffies; +} + +static void rfkill_schedule_global_op(enum rfkill_sched_op op) +{ + unsigned long flags; + + spin_lock_irqsave(&rfkill_op_lock, flags); + rfkill_op = op; + rfkill_op_pending = true; + if (op == RFKILL_GLOBAL_OP_EPO && !rfkill_is_epo_lock_active()) { + /* bypass the limiter for EPO */ + cancel_delayed_work(&rfkill_op_work); + schedule_delayed_work(&rfkill_op_work, 0); + rfkill_last_scheduled = jiffies; + } else + rfkill_schedule_ratelimited(); + spin_unlock_irqrestore(&rfkill_op_lock, flags); +} + +static void rfkill_schedule_toggle(enum rfkill_type type) +{ + unsigned long flags; + + if (rfkill_is_epo_lock_active()) + return; + + spin_lock_irqsave(&rfkill_op_lock, flags); + if (!rfkill_op_pending) { + __set_bit(type, rfkill_sw_pending); + __change_bit(type, rfkill_sw_state); + rfkill_schedule_ratelimited(); + } + spin_unlock_irqrestore(&rfkill_op_lock, flags); +} + +static void rfkill_schedule_evsw_rfkillall(int state) +{ + if (state) + rfkill_schedule_global_op(rfkill_master_switch_op); + else + rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO); +} + +static void rfkill_event(struct input_handle *handle, unsigned int type, + unsigned int code, int data) +{ + if (type == EV_KEY && data == 1) { + switch (code) { + case KEY_WLAN: + rfkill_schedule_toggle(RFKILL_TYPE_WLAN); + break; + case KEY_BLUETOOTH: + rfkill_schedule_toggle(RFKILL_TYPE_BLUETOOTH); + break; + case KEY_UWB: + rfkill_schedule_toggle(RFKILL_TYPE_UWB); + break; + case KEY_WIMAX: + rfkill_schedule_toggle(RFKILL_TYPE_WIMAX); + break; + } + } else if (type == EV_SW && code == SW_RFKILL_ALL) + rfkill_schedule_evsw_rfkillall(data); +} + +static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "rfkill"; + + /* causes rfkill_start() to be called */ + error = input_register_handle(handle); + if (error) + goto err_free_handle; + + error = input_open_device(handle); + if (error) + goto err_unregister_handle; + + return 0; + + err_unregister_handle: + input_unregister_handle(handle); + err_free_handle: + kfree(handle); + return error; +} + +static void rfkill_start(struct input_handle *handle) +{ + /* + * Take event_lock to guard against configuration changes, we + * should be able to deal with concurrency with rfkill_event() + * just fine (which event_lock will also avoid). + */ + spin_lock_irq(&handle->dev->event_lock); + + if (test_bit(EV_SW, handle->dev->evbit) && + test_bit(SW_RFKILL_ALL, handle->dev->swbit)) + rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL, + handle->dev->sw)); + + spin_unlock_irq(&handle->dev->event_lock); +} + +static void rfkill_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id rfkill_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_WLAN)] = BIT_MASK(KEY_WLAN) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_BLUETOOTH)] = BIT_MASK(KEY_BLUETOOTH) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT, + .evbit = { BIT(EV_SW) }, + .swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) }, + }, + { } +}; + +static struct input_handler rfkill_handler = { + .name = "rfkill", + .event = rfkill_event, + .connect = rfkill_connect, + .start = rfkill_start, + .disconnect = rfkill_disconnect, + .id_table = rfkill_ids, +}; + +int __init rfkill_handler_init(void) +{ + switch (rfkill_master_switch_mode) { + case RFKILL_INPUT_MASTER_UNBLOCKALL: + rfkill_master_switch_op = RFKILL_GLOBAL_OP_UNBLOCK; + break; + case RFKILL_INPUT_MASTER_RESTORE: + rfkill_master_switch_op = RFKILL_GLOBAL_OP_RESTORE; + break; + case RFKILL_INPUT_MASTER_UNLOCK: + rfkill_master_switch_op = RFKILL_GLOBAL_OP_UNLOCK; + break; + default: + return -EINVAL; + } + + spin_lock_init(&rfkill_op_lock); + + /* Avoid delay at first schedule */ + rfkill_last_scheduled = + jiffies - msecs_to_jiffies(RFKILL_OPS_DELAY) - 1; + return input_register_handler(&rfkill_handler); +} + +void __exit rfkill_handler_exit(void) +{ + input_unregister_handler(&rfkill_handler); + cancel_delayed_work_sync(&rfkill_op_work); +} diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c deleted file mode 100644 index 84efde97c5a7..000000000000 --- a/net/rfkill/rfkill-input.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Input layer to RF Kill interface connector - * - * Copyright (c) 2007 Dmitry Torokhov - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include - -#include "rfkill-input.h" - -MODULE_AUTHOR("Dmitry Torokhov "); -MODULE_DESCRIPTION("Input layer to RF switch connector"); -MODULE_LICENSE("GPL"); - -enum rfkill_input_master_mode { - RFKILL_INPUT_MASTER_DONOTHING = 0, - RFKILL_INPUT_MASTER_RESTORE = 1, - RFKILL_INPUT_MASTER_UNBLOCKALL = 2, - RFKILL_INPUT_MASTER_MAX, /* marker */ -}; - -/* Delay (in ms) between consecutive switch ops */ -#define RFKILL_OPS_DELAY 200 - -static enum rfkill_input_master_mode rfkill_master_switch_mode = - RFKILL_INPUT_MASTER_UNBLOCKALL; -module_param_named(master_switch_mode, rfkill_master_switch_mode, uint, 0); -MODULE_PARM_DESC(master_switch_mode, - "SW_RFKILL_ALL ON should: 0=do nothing; 1=restore; 2=unblock all"); - -enum rfkill_global_sched_op { - RFKILL_GLOBAL_OP_EPO = 0, - RFKILL_GLOBAL_OP_RESTORE, - RFKILL_GLOBAL_OP_UNLOCK, - RFKILL_GLOBAL_OP_UNBLOCK, -}; - -/* - * Currently, the code marked with RFKILL_NEED_SWSET is inactive. - * If handling of EV_SW SW_WLAN/WWAN/BLUETOOTH/etc is needed in the - * future, when such events are added, that code will be necessary. - */ - -struct rfkill_task { - struct delayed_work dwork; - - /* ensures that task is serialized */ - struct mutex mutex; - - /* protects everything below */ - spinlock_t lock; - - /* pending regular switch operations (1=pending) */ - unsigned long sw_pending[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; - -#ifdef RFKILL_NEED_SWSET - /* set operation pending (1=pending) */ - unsigned long sw_setpending[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; - - /* desired state for pending set operation (1=unblock) */ - unsigned long sw_newstate[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; -#endif - - /* should the state be complemented (1=yes) */ - unsigned long sw_togglestate[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; - - bool global_op_pending; - enum rfkill_global_sched_op op; - - /* last time it was scheduled */ - unsigned long last_scheduled; -}; - -static void __rfkill_handle_global_op(enum rfkill_global_sched_op op) -{ - unsigned int i; - - switch (op) { - case RFKILL_GLOBAL_OP_EPO: - rfkill_epo(); - break; - case RFKILL_GLOBAL_OP_RESTORE: - rfkill_restore_states(); - break; - case RFKILL_GLOBAL_OP_UNLOCK: - rfkill_remove_epo_lock(); - break; - case RFKILL_GLOBAL_OP_UNBLOCK: - rfkill_remove_epo_lock(); - for (i = 0; i < RFKILL_TYPE_MAX; i++) - rfkill_switch_all(i, RFKILL_STATE_UNBLOCKED); - break; - default: - /* memory corruption or bug, fail safely */ - rfkill_epo(); - WARN(1, "Unknown requested operation %d! " - "rfkill Emergency Power Off activated\n", - op); - } -} - -#ifdef RFKILL_NEED_SWSET -static void __rfkill_handle_normal_op(const enum rfkill_type type, - const bool sp, const bool s, const bool c) -{ - enum rfkill_state state; - - if (sp) - state = (s) ? RFKILL_STATE_UNBLOCKED : - RFKILL_STATE_SOFT_BLOCKED; - else - state = rfkill_get_global_state(type); - - if (c) - state = rfkill_state_complement(state); - - rfkill_switch_all(type, state); -} -#else -static void __rfkill_handle_normal_op(const enum rfkill_type type, - const bool c) -{ - enum rfkill_state state; - - state = rfkill_get_global_state(type); - if (c) - state = rfkill_state_complement(state); - - rfkill_switch_all(type, state); -} -#endif - -static void rfkill_task_handler(struct work_struct *work) -{ - struct rfkill_task *task = container_of(work, - struct rfkill_task, dwork.work); - bool doit = true; - - mutex_lock(&task->mutex); - - spin_lock_irq(&task->lock); - while (doit) { - if (task->global_op_pending) { - enum rfkill_global_sched_op op = task->op; - task->global_op_pending = false; - memset(task->sw_pending, 0, sizeof(task->sw_pending)); - spin_unlock_irq(&task->lock); - - __rfkill_handle_global_op(op); - - /* make sure we do at least one pass with - * !task->global_op_pending */ - spin_lock_irq(&task->lock); - continue; - } else if (!rfkill_is_epo_lock_active()) { - unsigned int i = 0; - - while (!task->global_op_pending && - i < RFKILL_TYPE_MAX) { - if (test_and_clear_bit(i, task->sw_pending)) { - bool c; -#ifdef RFKILL_NEED_SWSET - bool sp, s; - sp = test_and_clear_bit(i, - task->sw_setpending); - s = test_bit(i, task->sw_newstate); -#endif - c = test_and_clear_bit(i, - task->sw_togglestate); - spin_unlock_irq(&task->lock); - -#ifdef RFKILL_NEED_SWSET - __rfkill_handle_normal_op(i, sp, s, c); -#else - __rfkill_handle_normal_op(i, c); -#endif - - spin_lock_irq(&task->lock); - } - i++; - } - } - doit = task->global_op_pending; - } - spin_unlock_irq(&task->lock); - - mutex_unlock(&task->mutex); -} - -static struct rfkill_task rfkill_task = { - .dwork = __DELAYED_WORK_INITIALIZER(rfkill_task.dwork, - rfkill_task_handler), - .mutex = __MUTEX_INITIALIZER(rfkill_task.mutex), - .lock = __SPIN_LOCK_UNLOCKED(rfkill_task.lock), -}; - -static unsigned long rfkill_ratelimit(const unsigned long last) -{ - const unsigned long delay = msecs_to_jiffies(RFKILL_OPS_DELAY); - return (time_after(jiffies, last + delay)) ? 0 : delay; -} - -static void rfkill_schedule_ratelimited(void) -{ - if (!delayed_work_pending(&rfkill_task.dwork)) { - schedule_delayed_work(&rfkill_task.dwork, - rfkill_ratelimit(rfkill_task.last_scheduled)); - rfkill_task.last_scheduled = jiffies; - } -} - -static void rfkill_schedule_global_op(enum rfkill_global_sched_op op) -{ - unsigned long flags; - - spin_lock_irqsave(&rfkill_task.lock, flags); - rfkill_task.op = op; - rfkill_task.global_op_pending = true; - if (op == RFKILL_GLOBAL_OP_EPO && !rfkill_is_epo_lock_active()) { - /* bypass the limiter for EPO */ - cancel_delayed_work(&rfkill_task.dwork); - schedule_delayed_work(&rfkill_task.dwork, 0); - rfkill_task.last_scheduled = jiffies; - } else - rfkill_schedule_ratelimited(); - spin_unlock_irqrestore(&rfkill_task.lock, flags); -} - -#ifdef RFKILL_NEED_SWSET -/* Use this if you need to add EV_SW SW_WLAN/WWAN/BLUETOOTH/etc handling */ - -static void rfkill_schedule_set(enum rfkill_type type, - enum rfkill_state desired_state) -{ - unsigned long flags; - - if (rfkill_is_epo_lock_active()) - return; - - spin_lock_irqsave(&rfkill_task.lock, flags); - if (!rfkill_task.global_op_pending) { - set_bit(type, rfkill_task.sw_pending); - set_bit(type, rfkill_task.sw_setpending); - clear_bit(type, rfkill_task.sw_togglestate); - if (desired_state) - set_bit(type, rfkill_task.sw_newstate); - else - clear_bit(type, rfkill_task.sw_newstate); - rfkill_schedule_ratelimited(); - } - spin_unlock_irqrestore(&rfkill_task.lock, flags); -} -#endif - -static void rfkill_schedule_toggle(enum rfkill_type type) -{ - unsigned long flags; - - if (rfkill_is_epo_lock_active()) - return; - - spin_lock_irqsave(&rfkill_task.lock, flags); - if (!rfkill_task.global_op_pending) { - set_bit(type, rfkill_task.sw_pending); - change_bit(type, rfkill_task.sw_togglestate); - rfkill_schedule_ratelimited(); - } - spin_unlock_irqrestore(&rfkill_task.lock, flags); -} - -static void rfkill_schedule_evsw_rfkillall(int state) -{ - if (state) { - switch (rfkill_master_switch_mode) { - case RFKILL_INPUT_MASTER_UNBLOCKALL: - rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNBLOCK); - break; - case RFKILL_INPUT_MASTER_RESTORE: - rfkill_schedule_global_op(RFKILL_GLOBAL_OP_RESTORE); - break; - case RFKILL_INPUT_MASTER_DONOTHING: - rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNLOCK); - break; - default: - /* memory corruption or driver bug! fail safely */ - rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO); - WARN(1, "Unknown rfkill_master_switch_mode (%d), " - "driver bug or memory corruption detected!\n", - rfkill_master_switch_mode); - break; - } - } else - rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO); -} - -static void rfkill_event(struct input_handle *handle, unsigned int type, - unsigned int code, int data) -{ - if (type == EV_KEY && data == 1) { - enum rfkill_type t; - - switch (code) { - case KEY_WLAN: - t = RFKILL_TYPE_WLAN; - break; - case KEY_BLUETOOTH: - t = RFKILL_TYPE_BLUETOOTH; - break; - case KEY_UWB: - t = RFKILL_TYPE_UWB; - break; - case KEY_WIMAX: - t = RFKILL_TYPE_WIMAX; - break; - default: - return; - } - rfkill_schedule_toggle(t); - return; - } else if (type == EV_SW) { - switch (code) { - case SW_RFKILL_ALL: - rfkill_schedule_evsw_rfkillall(data); - return; - default: - return; - } - } -} - -static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, - const struct input_device_id *id) -{ - struct input_handle *handle; - int error; - - handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - handle->dev = dev; - handle->handler = handler; - handle->name = "rfkill"; - - /* causes rfkill_start() to be called */ - error = input_register_handle(handle); - if (error) - goto err_free_handle; - - error = input_open_device(handle); - if (error) - goto err_unregister_handle; - - return 0; - - err_unregister_handle: - input_unregister_handle(handle); - err_free_handle: - kfree(handle); - return error; -} - -static void rfkill_start(struct input_handle *handle) -{ - /* Take event_lock to guard against configuration changes, we - * should be able to deal with concurrency with rfkill_event() - * just fine (which event_lock will also avoid). */ - spin_lock_irq(&handle->dev->event_lock); - - if (test_bit(EV_SW, handle->dev->evbit)) { - if (test_bit(SW_RFKILL_ALL, handle->dev->swbit)) - rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL, - handle->dev->sw)); - /* add resync for further EV_SW events here */ - } - - spin_unlock_irq(&handle->dev->event_lock); -} - -static void rfkill_disconnect(struct input_handle *handle) -{ - input_close_device(handle); - input_unregister_handle(handle); - kfree(handle); -} - -static const struct input_device_id rfkill_ids[] = { - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT_MASK(EV_KEY) }, - .keybit = { [BIT_WORD(KEY_WLAN)] = BIT_MASK(KEY_WLAN) }, - }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT_MASK(EV_KEY) }, - .keybit = { [BIT_WORD(KEY_BLUETOOTH)] = BIT_MASK(KEY_BLUETOOTH) }, - }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT_MASK(EV_KEY) }, - .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) }, - }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT_MASK(EV_KEY) }, - .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, - }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT, - .evbit = { BIT(EV_SW) }, - .swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) }, - }, - { } -}; - -static struct input_handler rfkill_handler = { - .event = rfkill_event, - .connect = rfkill_connect, - .disconnect = rfkill_disconnect, - .start = rfkill_start, - .name = "rfkill", - .id_table = rfkill_ids, -}; - -static int __init rfkill_handler_init(void) -{ - if (rfkill_master_switch_mode >= RFKILL_INPUT_MASTER_MAX) - return -EINVAL; - - /* - * The penalty to not doing this is a possible RFKILL_OPS_DELAY delay - * at the first use. Acceptable, but if we can avoid it, why not? - */ - rfkill_task.last_scheduled = - jiffies - msecs_to_jiffies(RFKILL_OPS_DELAY) - 1; - return input_register_handler(&rfkill_handler); -} - -static void __exit rfkill_handler_exit(void) -{ - input_unregister_handler(&rfkill_handler); - cancel_delayed_work_sync(&rfkill_task.dwork); - rfkill_remove_epo_lock(); -} - -module_init(rfkill_handler_init); -module_exit(rfkill_handler_exit); diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c deleted file mode 100644 index 3eaa39403c13..000000000000 --- a/net/rfkill/rfkill.c +++ /dev/null @@ -1,882 +0,0 @@ -/* - * Copyright (C) 2006 - 2007 Ivo van Doorn - * Copyright (C) 2007 Dmitry Torokhov - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Get declaration of rfkill_switch_all() to shut up sparse. */ -#include "rfkill-input.h" - - -MODULE_AUTHOR("Ivo van Doorn "); -MODULE_VERSION("1.0"); -MODULE_DESCRIPTION("RF switch support"); -MODULE_LICENSE("GPL"); - -static LIST_HEAD(rfkill_list); /* list of registered rf switches */ -static DEFINE_MUTEX(rfkill_global_mutex); - -static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED; -module_param_named(default_state, rfkill_default_state, uint, 0444); -MODULE_PARM_DESC(default_state, - "Default initial state for all radio types, 0 = radio off"); - -struct rfkill_gsw_state { - enum rfkill_state current_state; - enum rfkill_state default_state; -}; - -static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX]; -static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; -static bool rfkill_epo_lock_active; - - -#ifdef CONFIG_RFKILL_LEDS -static void rfkill_led_trigger(struct rfkill *rfkill, - enum rfkill_state state) -{ - struct led_trigger *led = &rfkill->led_trigger; - - if (!led->name) - return; - if (state != RFKILL_STATE_UNBLOCKED) - led_trigger_event(led, LED_OFF); - else - led_trigger_event(led, LED_FULL); -} - -static void rfkill_led_trigger_activate(struct led_classdev *led) -{ - struct rfkill *rfkill = container_of(led->trigger, - struct rfkill, led_trigger); - - rfkill_led_trigger(rfkill, rfkill->state); -} -#endif /* CONFIG_RFKILL_LEDS */ - -static void rfkill_uevent(struct rfkill *rfkill) -{ - kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); -} - -static void update_rfkill_state(struct rfkill *rfkill) -{ - enum rfkill_state newstate, oldstate; - - if (rfkill->get_state) { - mutex_lock(&rfkill->mutex); - if (!rfkill->get_state(rfkill->data, &newstate)) { - oldstate = rfkill->state; - rfkill->state = newstate; - if (oldstate != newstate) - rfkill_uevent(rfkill); - } - mutex_unlock(&rfkill->mutex); - } -} - -/** - * rfkill_toggle_radio - wrapper for toggle_radio hook - * @rfkill: the rfkill struct to use - * @force: calls toggle_radio even if cache says it is not needed, - * and also makes sure notifications of the state will be - * sent even if it didn't change - * @state: the new state to call toggle_radio() with - * - * Calls rfkill->toggle_radio, enforcing the API for toggle_radio - * calls and handling all the red tape such as issuing notifications - * if the call is successful. - * - * Suspended devices are not touched at all, and -EAGAIN is returned. - * - * Note that the @force parameter cannot override a (possibly cached) - * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of - * RFKILL_STATE_HARD_BLOCKED implements either get_state() or - * rfkill_force_state(), so the cache either is bypassed or valid. - * - * Note that we do call toggle_radio for RFKILL_STATE_SOFT_BLOCKED - * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to - * give the driver a hint that it should double-BLOCK the transmitter. - * - * Caller must have acquired rfkill->mutex. - */ -static int rfkill_toggle_radio(struct rfkill *rfkill, - enum rfkill_state state, - int force) -{ - int retval = 0; - enum rfkill_state oldstate, newstate; - - if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) - return -EBUSY; - - oldstate = rfkill->state; - - if (rfkill->get_state && !force && - !rfkill->get_state(rfkill->data, &newstate)) - rfkill->state = newstate; - - switch (state) { - case RFKILL_STATE_HARD_BLOCKED: - /* typically happens when refreshing hardware state, - * such as on resume */ - state = RFKILL_STATE_SOFT_BLOCKED; - break; - case RFKILL_STATE_UNBLOCKED: - /* force can't override this, only rfkill_force_state() can */ - if (rfkill->state == RFKILL_STATE_HARD_BLOCKED) - return -EPERM; - break; - case RFKILL_STATE_SOFT_BLOCKED: - /* nothing to do, we want to give drivers the hint to double - * BLOCK even a transmitter that is already in state - * RFKILL_STATE_HARD_BLOCKED */ - break; - default: - WARN(1, KERN_WARNING - "rfkill: illegal state %d passed as parameter " - "to rfkill_toggle_radio\n", state); - return -EINVAL; - } - - if (force || state != rfkill->state) { - retval = rfkill->toggle_radio(rfkill->data, state); - /* never allow a HARD->SOFT downgrade! */ - if (!retval && rfkill->state != RFKILL_STATE_HARD_BLOCKED) - rfkill->state = state; - } - - if (force || rfkill->state != oldstate) - rfkill_uevent(rfkill); - - return retval; -} - -/** - * __rfkill_switch_all - Toggle state of all switches of given type - * @type: type of interfaces to be affected - * @state: the new state - * - * This function toggles the state of all switches of given type, - * unless a specific switch is claimed by userspace (in which case, - * that switch is left alone) or suspended. - * - * Caller must have acquired rfkill_global_mutex. - */ -static void __rfkill_switch_all(const enum rfkill_type type, - const enum rfkill_state state) -{ - struct rfkill *rfkill; - - if (WARN((state >= RFKILL_STATE_MAX || type >= RFKILL_TYPE_MAX), - KERN_WARNING - "rfkill: illegal state %d or type %d " - "passed as parameter to __rfkill_switch_all\n", - state, type)) - return; - - rfkill_global_states[type].current_state = state; - list_for_each_entry(rfkill, &rfkill_list, node) { - if ((!rfkill->user_claim) && (rfkill->type == type)) { - mutex_lock(&rfkill->mutex); - rfkill_toggle_radio(rfkill, state, 0); - mutex_unlock(&rfkill->mutex); - } - } -} - -/** - * rfkill_switch_all - Toggle state of all switches of given type - * @type: type of interfaces to be affected - * @state: the new state - * - * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state). - * Please refer to __rfkill_switch_all() for details. - * - * Does nothing if the EPO lock is active. - */ -void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) -{ - mutex_lock(&rfkill_global_mutex); - if (!rfkill_epo_lock_active) - __rfkill_switch_all(type, state); - mutex_unlock(&rfkill_global_mutex); -} -EXPORT_SYMBOL(rfkill_switch_all); - -/** - * rfkill_epo - emergency power off all transmitters - * - * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, - * ignoring everything in its path but rfkill_global_mutex and rfkill->mutex. - * - * The global state before the EPO is saved and can be restored later - * using rfkill_restore_states(). - */ -void rfkill_epo(void) -{ - struct rfkill *rfkill; - int i; - - mutex_lock(&rfkill_global_mutex); - - rfkill_epo_lock_active = true; - list_for_each_entry(rfkill, &rfkill_list, node) { - mutex_lock(&rfkill->mutex); - rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); - mutex_unlock(&rfkill->mutex); - } - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - rfkill_global_states[i].default_state = - rfkill_global_states[i].current_state; - rfkill_global_states[i].current_state = - RFKILL_STATE_SOFT_BLOCKED; - } - mutex_unlock(&rfkill_global_mutex); -} -EXPORT_SYMBOL_GPL(rfkill_epo); - -/** - * rfkill_restore_states - restore global states - * - * Restore (and sync switches to) the global state from the - * states in rfkill_default_states. This can undo the effects of - * a call to rfkill_epo(). - */ -void rfkill_restore_states(void) -{ - int i; - - mutex_lock(&rfkill_global_mutex); - - rfkill_epo_lock_active = false; - for (i = 0; i < RFKILL_TYPE_MAX; i++) - __rfkill_switch_all(i, rfkill_global_states[i].default_state); - mutex_unlock(&rfkill_global_mutex); -} -EXPORT_SYMBOL_GPL(rfkill_restore_states); - -/** - * rfkill_remove_epo_lock - unlock state changes - * - * Used by rfkill-input manually unlock state changes, when - * the EPO switch is deactivated. - */ -void rfkill_remove_epo_lock(void) -{ - mutex_lock(&rfkill_global_mutex); - rfkill_epo_lock_active = false; - mutex_unlock(&rfkill_global_mutex); -} -EXPORT_SYMBOL_GPL(rfkill_remove_epo_lock); - -/** - * rfkill_is_epo_lock_active - returns true EPO is active - * - * Returns 0 (false) if there is NOT an active EPO contidion, - * and 1 (true) if there is an active EPO contition, which - * locks all radios in one of the BLOCKED states. - * - * Can be called in atomic context. - */ -bool rfkill_is_epo_lock_active(void) -{ - return rfkill_epo_lock_active; -} -EXPORT_SYMBOL_GPL(rfkill_is_epo_lock_active); - -/** - * rfkill_get_global_state - returns global state for a type - * @type: the type to get the global state of - * - * Returns the current global state for a given wireless - * device type. - */ -enum rfkill_state rfkill_get_global_state(const enum rfkill_type type) -{ - return rfkill_global_states[type].current_state; -} -EXPORT_SYMBOL_GPL(rfkill_get_global_state); - -/** - * rfkill_force_state - Force the internal rfkill radio state - * @rfkill: pointer to the rfkill class to modify. - * @state: the current radio state the class should be forced to. - * - * This function updates the internal state of the radio cached - * by the rfkill class. It should be used when the driver gets - * a notification by the firmware/hardware of the current *real* - * state of the radio rfkill switch. - * - * Devices which are subject to external changes on their rfkill - * state (such as those caused by a hardware rfkill line) MUST - * have their driver arrange to call rfkill_force_state() as soon - * as possible after such a change. - * - * This function may not be called from an atomic context. - */ -int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) -{ - enum rfkill_state oldstate; - - BUG_ON(!rfkill); - if (WARN((state >= RFKILL_STATE_MAX), - KERN_WARNING - "rfkill: illegal state %d passed as parameter " - "to rfkill_force_state\n", state)) - return -EINVAL; - - mutex_lock(&rfkill->mutex); - - oldstate = rfkill->state; - rfkill->state = state; - - if (state != oldstate) - rfkill_uevent(rfkill); - - mutex_unlock(&rfkill->mutex); - - return 0; -} -EXPORT_SYMBOL(rfkill_force_state); - -static ssize_t rfkill_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct rfkill *rfkill = to_rfkill(dev); - - return sprintf(buf, "%s\n", rfkill->name); -} - -static const char *rfkill_get_type_str(enum rfkill_type type) -{ - switch (type) { - case RFKILL_TYPE_WLAN: - return "wlan"; - case RFKILL_TYPE_BLUETOOTH: - return "bluetooth"; - case RFKILL_TYPE_UWB: - return "ultrawideband"; - case RFKILL_TYPE_WIMAX: - return "wimax"; - case RFKILL_TYPE_WWAN: - return "wwan"; - default: - BUG(); - } -} - -static ssize_t rfkill_type_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct rfkill *rfkill = to_rfkill(dev); - - return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); -} - -static ssize_t rfkill_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct rfkill *rfkill = to_rfkill(dev); - - update_rfkill_state(rfkill); - return sprintf(buf, "%d\n", rfkill->state); -} - -static ssize_t rfkill_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct rfkill *rfkill = to_rfkill(dev); - unsigned long state; - int error; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - error = strict_strtoul(buf, 0, &state); - if (error) - return error; - - /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ - if (state != RFKILL_STATE_UNBLOCKED && - state != RFKILL_STATE_SOFT_BLOCKED) - return -EINVAL; - - error = mutex_lock_killable(&rfkill->mutex); - if (error) - return error; - - if (!rfkill_epo_lock_active) - error = rfkill_toggle_radio(rfkill, state, 0); - else - error = -EPERM; - - mutex_unlock(&rfkill->mutex); - - return error ? error : count; -} - -static ssize_t rfkill_claim_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct rfkill *rfkill = to_rfkill(dev); - - return sprintf(buf, "%d\n", rfkill->user_claim); -} - -static ssize_t rfkill_claim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct rfkill *rfkill = to_rfkill(dev); - unsigned long claim_tmp; - bool claim; - int error; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (rfkill->user_claim_unsupported) - return -EOPNOTSUPP; - - error = strict_strtoul(buf, 0, &claim_tmp); - if (error) - return error; - claim = !!claim_tmp; - - /* - * Take the global lock to make sure the kernel is not in - * the middle of rfkill_switch_all - */ - error = mutex_lock_killable(&rfkill_global_mutex); - if (error) - return error; - - if (rfkill->user_claim != claim) { - if (!claim && !rfkill_epo_lock_active) { - mutex_lock(&rfkill->mutex); - rfkill_toggle_radio(rfkill, - rfkill_global_states[rfkill->type].current_state, - 0); - mutex_unlock(&rfkill->mutex); - } - rfkill->user_claim = claim; - } - - mutex_unlock(&rfkill_global_mutex); - - return error ? error : count; -} - -static struct device_attribute rfkill_dev_attrs[] = { - __ATTR(name, S_IRUGO, rfkill_name_show, NULL), - __ATTR(type, S_IRUGO, rfkill_type_show, NULL), - __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), - __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), - __ATTR_NULL -}; - -static void rfkill_release(struct device *dev) -{ - struct rfkill *rfkill = to_rfkill(dev); - - kfree(rfkill); - module_put(THIS_MODULE); -} - -#ifdef CONFIG_PM -static int rfkill_suspend(struct device *dev, pm_message_t state) -{ - struct rfkill *rfkill = to_rfkill(dev); - - /* mark class device as suspended */ - if (dev->power.power_state.event != state.event) - dev->power.power_state = state; - - /* store state for the resume handler */ - rfkill->state_for_resume = rfkill->state; - - return 0; -} - -static int rfkill_resume(struct device *dev) -{ - struct rfkill *rfkill = to_rfkill(dev); - enum rfkill_state newstate; - - if (dev->power.power_state.event != PM_EVENT_ON) { - mutex_lock(&rfkill->mutex); - - dev->power.power_state.event = PM_EVENT_ON; - - /* - * rfkill->state could have been modified before we got - * called, and won't be updated by rfkill_toggle_radio() - * in force mode. Sync it FIRST. - */ - if (rfkill->get_state && - !rfkill->get_state(rfkill->data, &newstate)) - rfkill->state = newstate; - - /* - * If we are under EPO, kick transmitter offline, - * otherwise restore to pre-suspend state. - * - * Issue a notification in any case - */ - rfkill_toggle_radio(rfkill, - rfkill_epo_lock_active ? - RFKILL_STATE_SOFT_BLOCKED : - rfkill->state_for_resume, - 1); - - mutex_unlock(&rfkill->mutex); - } - - return 0; -} -#else -#define rfkill_suspend NULL -#define rfkill_resume NULL -#endif - -static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct rfkill *rfkill = to_rfkill(dev); - int error; - - error = add_uevent_var(env, "RFKILL_NAME=%s", rfkill->name); - if (error) - return error; - error = add_uevent_var(env, "RFKILL_TYPE=%s", - rfkill_get_type_str(rfkill->type)); - if (error) - return error; - error = add_uevent_var(env, "RFKILL_STATE=%d", rfkill->state); - return error; -} - -static struct class rfkill_class = { - .name = "rfkill", - .dev_release = rfkill_release, - .dev_attrs = rfkill_dev_attrs, - .suspend = rfkill_suspend, - .resume = rfkill_resume, - .dev_uevent = rfkill_dev_uevent, -}; - -static int rfkill_check_duplicity(const struct rfkill *rfkill) -{ - struct rfkill *p; - unsigned long seen[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; - - memset(seen, 0, sizeof(seen)); - - list_for_each_entry(p, &rfkill_list, node) { - if (WARN((p == rfkill), KERN_WARNING - "rfkill: illegal attempt to register " - "an already registered rfkill struct\n")) - return -EEXIST; - set_bit(p->type, seen); - } - - /* 0: first switch of its kind */ - return (test_bit(rfkill->type, seen)) ? 1 : 0; -} - -static int rfkill_add_switch(struct rfkill *rfkill) -{ - int error; - - mutex_lock(&rfkill_global_mutex); - - error = rfkill_check_duplicity(rfkill); - if (error < 0) - goto unlock_out; - - if (!error) { - /* lock default after first use */ - set_bit(rfkill->type, rfkill_states_lockdflt); - rfkill_global_states[rfkill->type].current_state = - rfkill_global_states[rfkill->type].default_state; - } - - rfkill_toggle_radio(rfkill, - rfkill_global_states[rfkill->type].current_state, - 0); - - list_add_tail(&rfkill->node, &rfkill_list); - - error = 0; -unlock_out: - mutex_unlock(&rfkill_global_mutex); - - return error; -} - -static void rfkill_remove_switch(struct rfkill *rfkill) -{ - mutex_lock(&rfkill_global_mutex); - list_del_init(&rfkill->node); - mutex_unlock(&rfkill_global_mutex); - - mutex_lock(&rfkill->mutex); - rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); - mutex_unlock(&rfkill->mutex); -} - -/** - * rfkill_allocate - allocate memory for rfkill structure. - * @parent: device that has rf switch on it - * @type: type of the switch (RFKILL_TYPE_*) - * - * This function should be called by the network driver when it needs - * rfkill structure. Once the structure is allocated the driver should - * finish its initialization by setting the name, private data, enable_radio - * and disable_radio methods and then register it with rfkill_register(). - * - * NOTE: If registration fails the structure shoudl be freed by calling - * rfkill_free() otherwise rfkill_unregister() should be used. - */ -struct rfkill * __must_check rfkill_allocate(struct device *parent, - enum rfkill_type type) -{ - struct rfkill *rfkill; - struct device *dev; - - if (WARN((type >= RFKILL_TYPE_MAX), - KERN_WARNING - "rfkill: illegal type %d passed as parameter " - "to rfkill_allocate\n", type)) - return NULL; - - rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL); - if (!rfkill) - return NULL; - - mutex_init(&rfkill->mutex); - INIT_LIST_HEAD(&rfkill->node); - rfkill->type = type; - - dev = &rfkill->dev; - dev->class = &rfkill_class; - dev->parent = parent; - device_initialize(dev); - - __module_get(THIS_MODULE); - - return rfkill; -} -EXPORT_SYMBOL(rfkill_allocate); - -/** - * rfkill_free - Mark rfkill structure for deletion - * @rfkill: rfkill structure to be destroyed - * - * Decrements reference count of the rfkill structure so it is destroyed. - * Note that rfkill_free() should _not_ be called after rfkill_unregister(). - */ -void rfkill_free(struct rfkill *rfkill) -{ - if (rfkill) - put_device(&rfkill->dev); -} -EXPORT_SYMBOL(rfkill_free); - -static void rfkill_led_trigger_register(struct rfkill *rfkill) -{ -#ifdef CONFIG_RFKILL_LEDS - int error; - - if (!rfkill->led_trigger.name) - rfkill->led_trigger.name = dev_name(&rfkill->dev); - if (!rfkill->led_trigger.activate) - rfkill->led_trigger.activate = rfkill_led_trigger_activate; - error = led_trigger_register(&rfkill->led_trigger); - if (error) - rfkill->led_trigger.name = NULL; -#endif /* CONFIG_RFKILL_LEDS */ -} - -static void rfkill_led_trigger_unregister(struct rfkill *rfkill) -{ -#ifdef CONFIG_RFKILL_LEDS - if (rfkill->led_trigger.name) { - led_trigger_unregister(&rfkill->led_trigger); - rfkill->led_trigger.name = NULL; - } -#endif -} - -/** - * rfkill_register - Register a rfkill structure. - * @rfkill: rfkill structure to be registered - * - * This function should be called by the network driver when the rfkill - * structure needs to be registered. Immediately from registration the - * switch driver should be able to service calls to toggle_radio. - */ -int __must_check rfkill_register(struct rfkill *rfkill) -{ - static atomic_t rfkill_no = ATOMIC_INIT(0); - struct device *dev = &rfkill->dev; - int error; - - if (WARN((!rfkill || !rfkill->toggle_radio || - rfkill->type >= RFKILL_TYPE_MAX || - rfkill->state >= RFKILL_STATE_MAX), - KERN_WARNING - "rfkill: attempt to register a " - "badly initialized rfkill struct\n")) - return -EINVAL; - - dev_set_name(dev, "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1); - - rfkill_led_trigger_register(rfkill); - - error = rfkill_add_switch(rfkill); - if (error) { - rfkill_led_trigger_unregister(rfkill); - return error; - } - - error = device_add(dev); - if (error) { - rfkill_remove_switch(rfkill); - rfkill_led_trigger_unregister(rfkill); - return error; - } - - return 0; -} -EXPORT_SYMBOL(rfkill_register); - -/** - * rfkill_unregister - Unregister a rfkill structure. - * @rfkill: rfkill structure to be unregistered - * - * This function should be called by the network driver during device - * teardown to destroy rfkill structure. Note that rfkill_free() should - * _not_ be called after rfkill_unregister(). - */ -void rfkill_unregister(struct rfkill *rfkill) -{ - BUG_ON(!rfkill); - device_del(&rfkill->dev); - rfkill_remove_switch(rfkill); - rfkill_led_trigger_unregister(rfkill); - put_device(&rfkill->dev); -} -EXPORT_SYMBOL(rfkill_unregister); - -/** - * rfkill_set_default - set initial value for a switch type - * @type - the type of switch to set the default state of - * @state - the new default state for that group of switches - * - * Sets the initial state rfkill should use for a given type. - * The following initial states are allowed: RFKILL_STATE_SOFT_BLOCKED - * and RFKILL_STATE_UNBLOCKED. - * - * This function is meant to be used by platform drivers for platforms - * that can save switch state across power down/reboot. - * - * The default state for each switch type can be changed exactly once. - * After a switch of that type is registered, the default state cannot - * be changed anymore. This guards against multiple drivers it the - * same platform trying to set the initial switch default state, which - * is not allowed. - * - * Returns -EPERM if the state has already been set once or is in use, - * so drivers likely want to either ignore or at most printk(KERN_NOTICE) - * if this function returns -EPERM. - * - * Returns 0 if the new default state was set, or an error if it - * could not be set. - */ -int rfkill_set_default(enum rfkill_type type, enum rfkill_state state) -{ - int error; - - if (WARN((type >= RFKILL_TYPE_MAX || - (state != RFKILL_STATE_SOFT_BLOCKED && - state != RFKILL_STATE_UNBLOCKED)), - KERN_WARNING - "rfkill: illegal state %d or type %d passed as " - "parameter to rfkill_set_default\n", state, type)) - return -EINVAL; - - mutex_lock(&rfkill_global_mutex); - - if (!test_and_set_bit(type, rfkill_states_lockdflt)) { - rfkill_global_states[type].default_state = state; - rfkill_global_states[type].current_state = state; - error = 0; - } else - error = -EPERM; - - mutex_unlock(&rfkill_global_mutex); - return error; -} -EXPORT_SYMBOL_GPL(rfkill_set_default); - -/* - * Rfkill module initialization/deinitialization. - */ -static int __init rfkill_init(void) -{ - int error; - int i; - - /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ - if (rfkill_default_state != RFKILL_STATE_SOFT_BLOCKED && - rfkill_default_state != RFKILL_STATE_UNBLOCKED) - return -EINVAL; - - for (i = 0; i < RFKILL_TYPE_MAX; i++) - rfkill_global_states[i].default_state = rfkill_default_state; - - error = class_register(&rfkill_class); - if (error) { - printk(KERN_ERR "rfkill: unable to register rfkill class\n"); - return error; - } - - return 0; -} - -static void __exit rfkill_exit(void) -{ - class_unregister(&rfkill_class); -} - -subsys_initcall(rfkill_init); -module_exit(rfkill_exit); diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill.h similarity index 60% rename from net/rfkill/rfkill-input.h rename to net/rfkill/rfkill.h index fe8df6b5b935..d1117cb6e4de 100644 --- a/net/rfkill/rfkill-input.h +++ b/net/rfkill/rfkill.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ivo van Doorn + * Copyright 2009 Johannes Berg */ /* @@ -11,11 +12,16 @@ #ifndef __RFKILL_INPUT_H #define __RFKILL_INPUT_H -void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state); +/* core code */ +void rfkill_switch_all(const enum rfkill_type type, bool blocked); void rfkill_epo(void); void rfkill_restore_states(void); void rfkill_remove_epo_lock(void); bool rfkill_is_epo_lock_active(void); -enum rfkill_state rfkill_get_global_state(const enum rfkill_type type); +bool rfkill_get_global_sw_state(const enum rfkill_type type); + +/* input handler */ +int rfkill_handler_init(void); +void rfkill_handler_exit(void); #endif /* __RFKILL_INPUT_H */ diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 7dcf2569613b..389d6e0d7740 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -137,7 +137,7 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev) if (!netif_running(dev)) { printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n"); - return 1; + return NETDEV_TX_BUSY; } dev_kfree_skb(skb); stats->tx_errors++; diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index e5becb92b3e7..e4877ca6727c 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -62,13 +62,7 @@ static u64 read_classid(struct cgroup *cgrp, struct cftype *cft) static int write_classid(struct cgroup *cgrp, struct cftype *cft, u64 value) { - if (!cgroup_lock_live_group(cgrp)) - return -ENODEV; - cgrp_cls_state(cgrp)->classid = (u32) value; - - cgroup_unlock(); - return 0; } diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 0ef4e3065bcd..9402a7fd3785 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -84,7 +84,7 @@ static u32 flow_get_dst(const struct sk_buff *skb) case htons(ETH_P_IPV6): return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); default: - return addr_fold(skb->dst) ^ (__force u16)skb->protocol; + return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; } } @@ -163,7 +163,7 @@ static u32 flow_get_proto_dst(const struct sk_buff *skb) break; } default: - res = addr_fold(skb->dst) ^ (__force u16)skb->protocol; + res = addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; } return res; @@ -251,8 +251,8 @@ static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb) static u32 flow_get_rtclassid(const struct sk_buff *skb) { #ifdef CONFIG_NET_CLS_ROUTE - if (skb->dst) - return skb->dst->tclassid; + if (skb_dst(skb)) + return skb_dst(skb)->tclassid; #endif return 0; } diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index bdf1f4172eef..dd872d5383ef 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -137,7 +137,7 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, u32 id, h; int iif, dont_cache = 0; - if ((dst = skb->dst) == NULL) + if ((dst = skb_dst(skb)) == NULL) goto failure; id = dst->tclassid; diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index fad596bf32d7..266151ae85a3 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -246,11 +246,11 @@ META_COLLECTOR(int_tcindex) META_COLLECTOR(int_rtclassid) { - if (unlikely(skb->dst == NULL)) + if (unlikely(skb_dst(skb) == NULL)) *err = -1; else #ifdef CONFIG_NET_CLS_ROUTE - dst->value = skb->dst->tclassid; + dst->value = skb_dst(skb)->tclassid; #else dst->value = 0; #endif @@ -258,10 +258,10 @@ META_COLLECTOR(int_rtclassid) META_COLLECTOR(int_rtiif) { - if (unlikely(skb->rtable == NULL)) + if (unlikely(skb_rtable(skb) == NULL)) *err = -1; else - dst->value = skb->rtable->fl.iif; + dst->value = skb_rtable(skb)->fl.iif; } /************************************************************************** diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 32009793307b..24d17ce9c294 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -484,7 +484,7 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) wd->qdisc->flags |= TCQ_F_THROTTLED; time = ktime_set(0, 0); - time = ktime_add_ns(time, PSCHED_US2NS(expires)); + time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); } EXPORT_SYMBOL(qdisc_watchdog_schedule); @@ -1680,7 +1680,7 @@ static int psched_show(struct seq_file *seq, void *v) hrtimer_get_res(CLOCK_MONOTONIC, &ts); seq_printf(seq, "%08x %08x %08x %08x\n", - (u32)NSEC_PER_USEC, (u32)PSCHED_US2NS(1), + (u32)NSEC_PER_USEC, (u32)PSCHED_TICKS2NS(1), 1000000, (u32)NSEC_PER_SEC/(u32)ktime_to_ns(timespec_to_ktime(ts))); diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index d728d8111732..23a167670fd5 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -509,7 +509,7 @@ static void cbq_ovl_delay(struct cbq_class *cl) q->pmask |= (1<delay_timer) && ktime_to_ns(ktime_sub( hrtimer_get_expires(&q->delay_timer), @@ -620,7 +620,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) ktime_t time; time = ktime_set(0, 0); - time = ktime_add_ns(time, PSCHED_US2NS(now + delay)); + time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay)); hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5f5efe4e6072..27d03816ec3e 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -196,6 +196,21 @@ void __qdisc_run(struct Qdisc *q) clear_bit(__QDISC_STATE_RUNNING, &q->state); } +unsigned long dev_trans_start(struct net_device *dev) +{ + unsigned long val, res = dev->trans_start; + unsigned int i; + + for (i = 0; i < dev->num_tx_queues; i++) { + val = netdev_get_tx_queue(dev, i)->trans_start; + if (val && time_after(val, res)) + res = val; + } + dev->trans_start = res; + return res; +} +EXPORT_SYMBOL(dev_trans_start); + static void dev_watchdog(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; @@ -205,25 +220,30 @@ static void dev_watchdog(unsigned long arg) if (netif_device_present(dev) && netif_running(dev) && netif_carrier_ok(dev)) { - int some_queue_stopped = 0; + int some_queue_timedout = 0; unsigned int i; + unsigned long trans_start; for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *txq; txq = netdev_get_tx_queue(dev, i); - if (netif_tx_queue_stopped(txq)) { - some_queue_stopped = 1; + /* + * old device drivers set dev->trans_start + */ + trans_start = txq->trans_start ? : dev->trans_start; + if (netif_tx_queue_stopped(txq) && + time_after(jiffies, (trans_start + + dev->watchdog_timeo))) { + some_queue_timedout = 1; break; } } - if (some_queue_stopped && - time_after(jiffies, (dev->trans_start + - dev->watchdog_timeo))) { + if (some_queue_timedout) { char drivername[64]; - WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", - dev->name, netdev_drivername(dev, drivername, 64)); + WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n", + dev->name, netdev_drivername(dev, drivername, 64), i); dev->netdev_ops->ndo_tx_timeout(dev); } if (!mod_timer(&dev->watchdog_timer, @@ -602,8 +622,10 @@ static void transition_one_qdisc(struct net_device *dev, clear_bit(__QDISC_STATE_DEACTIVATED, &new_qdisc->state); rcu_assign_pointer(dev_queue->qdisc, new_qdisc); - if (need_watchdog_p && new_qdisc != &noqueue_qdisc) + if (need_watchdog_p && new_qdisc != &noqueue_qdisc) { + dev_queue->trans_start = 0; *need_watchdog_p = 1; + } } void dev_activate(struct net_device *dev) diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 5022f9c1f34b..362c2811b2df 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -372,7 +372,7 @@ cftree_update(struct hfsc_class *cl) * ism: (psched_us/byte) << ISM_SHIFT * dx: psched_us * - * The clock source resolution with ktime is 1.024us. + * The clock source resolution with ktime and PSCHED_SHIFT 10 is 1.024us. * * sm and ism are scaled in order to keep effective digits. * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective @@ -383,9 +383,11 @@ cftree_update(struct hfsc_class *cl) * bytes/1.024us 12.8e-3 128e-3 1280e-3 12800e-3 128000e-3 * * 1.024us/byte 78.125 7.8125 0.78125 0.078125 0.0078125 + * + * So, for PSCHED_SHIFT 10 we need: SM_SHIFT 20, ISM_SHIFT 18. */ -#define SM_SHIFT 20 -#define ISM_SHIFT 18 +#define SM_SHIFT (30 - PSCHED_SHIFT) +#define ISM_SHIFT (8 + PSCHED_SHIFT) #define SM_MASK ((1ULL << SM_SHIFT) - 1) #define ISM_MASK ((1ULL << ISM_SHIFT) - 1) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 33133d27b539..8706920a6d45 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -149,7 +149,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) break; } default: - h = (unsigned long)skb->dst ^ skb->protocol; + h = (unsigned long)skb_dst(skb) ^ skb->protocol; h2 = (unsigned long)skb->sk; } diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 3b6418297231..9c002b6e0533 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -58,7 +58,6 @@ struct teql_master struct net_device *dev; struct Qdisc *slaves; struct list_head master_list; - struct net_device_stats stats; }; struct teql_sched_data @@ -223,7 +222,7 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * { struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc); - struct neighbour *mn = skb->dst->neighbour; + struct neighbour *mn = skb_dst(skb)->neighbour; struct neighbour *n = q->ncache; if (mn->tbl == NULL) @@ -263,8 +262,8 @@ static inline int teql_resolve(struct sk_buff *skb, return -ENODEV; if (dev->header_ops == NULL || - skb->dst == NULL || - skb->dst->neighbour == NULL) + skb_dst(skb) == NULL || + skb_dst(skb)->neighbour == NULL) return 0; return __teql_resolve(skb, skb_res, dev); } @@ -272,6 +271,7 @@ static inline int teql_resolve(struct sk_buff *skb, static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) { struct teql_master *master = netdev_priv(dev); + struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); struct Qdisc *start, *q; int busy; int nores; @@ -308,11 +308,12 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) if (!netif_tx_queue_stopped(slave_txq) && !netif_tx_queue_frozen(slave_txq) && slave_ops->ndo_start_xmit(skb, slave) == 0) { + txq_trans_update(slave_txq); __netif_tx_unlock(slave_txq); master->slaves = NEXT_SLAVE(q); netif_wake_queue(dev); - master->stats.tx_packets++; - master->stats.tx_bytes += length; + txq->tx_packets++; + txq->tx_bytes += length; return 0; } __netif_tx_unlock(slave_txq); @@ -337,12 +338,12 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) if (busy) { netif_stop_queue(dev); - return 1; + return NETDEV_TX_BUSY; } - master->stats.tx_errors++; + dev->stats.tx_errors++; drop: - master->stats.tx_dropped++; + txq->tx_dropped++; dev_kfree_skb(skb); return 0; } @@ -395,12 +396,6 @@ static int teql_master_close(struct net_device *dev) return 0; } -static struct net_device_stats *teql_master_stats(struct net_device *dev) -{ - struct teql_master *m = netdev_priv(dev); - return &m->stats; -} - static int teql_master_mtu(struct net_device *dev, int new_mtu) { struct teql_master *m = netdev_priv(dev); @@ -425,7 +420,6 @@ static const struct net_device_ops teql_netdev_ops = { .ndo_open = teql_master_open, .ndo_stop = teql_master_close, .ndo_start_xmit = teql_master_xmit, - .ndo_get_stats = teql_master_stats, .ndo_change_mtu = teql_master_mtu, }; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f4b23043b610..525864bf4f07 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -293,7 +293,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a * told otherwise. */ asoc->peer.ipv4_address = 1; - asoc->peer.ipv6_address = 1; + if (asoc->base.sk->sk_family == PF_INET6) + asoc->peer.ipv6_address = 1; INIT_LIST_HEAD(&asoc->asocs); asoc->autoclose = sp->autoclose; @@ -566,6 +567,21 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, if (asoc->init_last_sent_to == peer) asoc->init_last_sent_to = NULL; + /* If we remove the transport an SHUTDOWN was last sent to, set it + * to NULL. Combined with the update of the retran path above, this + * will cause the next SHUTDOWN to be sent to the next available + * transport, maintaining the cycle. + */ + if (asoc->shutdown_last_sent_to == peer) + asoc->shutdown_last_sent_to = NULL; + + /* If we remove the transport an ASCONF was last sent to, set it to + * NULL. + */ + if (asoc->addip_last_asconf && + asoc->addip_last_asconf->transport == peer) + asoc->addip_last_asconf->transport = NULL; + asoc->peer.transport_count--; sctp_transport_free(peer); @@ -1268,49 +1284,21 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) ntohs(t->ipaddr.v4.sin_port)); } -/* Choose the transport for sending a INIT packet. */ -struct sctp_transport *sctp_assoc_choose_init_transport( - struct sctp_association *asoc) +/* Choose the transport for sending retransmit packet. */ +struct sctp_transport *sctp_assoc_choose_alter_transport( + struct sctp_association *asoc, struct sctp_transport *last_sent_to) { - struct sctp_transport *t; - - /* Use the retran path. If the last INIT was sent over the + /* If this is the first time packet is sent, use the active path, + * else use the retran path. If the last packet was sent over the * retran path, update the retran path and use it. */ - if (!asoc->init_last_sent_to) { - t = asoc->peer.active_path; - } else { - if (asoc->init_last_sent_to == asoc->peer.retran_path) - sctp_assoc_update_retran_path(asoc); - t = asoc->peer.retran_path; - } - - SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" - " %p addr: ", - " port: %d\n", - asoc, - (&t->ipaddr), - ntohs(t->ipaddr.v4.sin_port)); - - return t; -} - -/* Choose the transport for sending a SHUTDOWN packet. */ -struct sctp_transport *sctp_assoc_choose_shutdown_transport( - struct sctp_association *asoc) -{ - /* If this is the first time SHUTDOWN is sent, use the active path, - * else use the retran path. If the last SHUTDOWN was sent over the - * retran path, update the retran path and use it. - */ - if (!asoc->shutdown_last_sent_to) + if (!last_sent_to) return asoc->peer.active_path; else { - if (asoc->shutdown_last_sent_to == asoc->peer.retran_path) + if (last_sent_to == asoc->peer.retran_path) sctp_assoc_update_retran_path(asoc); return asoc->peer.retran_path; } - } /* Update the association's pmtu and frag_point by going through all the @@ -1482,6 +1470,10 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) { int assoc_id; int error = 0; + + /* If the id is already assigned, keep it. */ + if (asoc->assoc_id) + return error; retry: if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) return -ENOMEM; diff --git a/net/sctp/input.c b/net/sctp/input.c index d2e98803ffe3..c0c973e67add 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -81,13 +81,13 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); /* Calculate the SCTP checksum of an SCTP packet. */ static inline int sctp_rcv_checksum(struct sk_buff *skb) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sctphdr *sh = sctp_hdr(skb); __le32 cmp = sh->checksum; + struct sk_buff *list; __le32 val; __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); - for (; list; list = list->next) + skb_walk_frags(skb, list) tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), tmp); diff --git a/net/sctp/output.c b/net/sctp/output.c index 7d08f522ec84..b76411444515 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -405,13 +405,14 @@ int sctp_packet_transmit(struct sctp_packet *packet) sctp_assoc_sync_pmtu(asoc); } } - nskb->dst = dst_clone(tp->dst); - if (!nskb->dst) + dst = dst_clone(tp->dst); + skb_dst_set(nskb, dst); + if (dst) goto no_route; - dst = nskb->dst; /* Build the SCTP header. */ sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); + skb_reset_transport_header(nskb); sh->source = htons(packet->source_port); sh->dest = htons(packet->destination_port); @@ -527,15 +528,25 @@ int sctp_packet_transmit(struct sctp_packet *packet) * Note: Adler-32 is no longer applicable, as has been replaced * by CRC32-C as described in . */ - if (!sctp_checksum_disable && !(dst->dev->features & NETIF_F_NO_CSUM)) { + if (!sctp_checksum_disable && + !(dst->dev->features & (NETIF_F_NO_CSUM | NETIF_F_SCTP_CSUM))) { __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); /* 3) Put the resultant value into the checksum field in the * common header, and leave the rest of the bits unchanged. */ sh->checksum = sctp_end_cksum(crc32); - } else - nskb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + if (dst->dev->features & NETIF_F_SCTP_CSUM) { + /* no need to seed psuedo checksum for SCTP */ + nskb->ip_summed = CHECKSUM_PARTIAL; + nskb->csum_start = (skb_transport_header(nskb) - + nskb->head); + nskb->csum_offset = offsetof(struct sctphdr, checksum); + } else { + nskb->ip_summed = CHECKSUM_UNNECESSARY; + } + } /* IP layer ECN support * From RFC 2481 diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 8eb3e61cb701..79cbd47f4df7 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -393,7 +393,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, return 0; /* Is this a broadcast address? */ - if (skb && skb->rtable->rt_flags & RTCF_BROADCAST) + if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST) return 0; return 1; @@ -572,7 +572,7 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk, /* What interface did this skb arrive on? */ static int sctp_v4_skb_iif(const struct sk_buff *skb) { - return skb->rtable->rt_iif; + return skb_rtable(skb)->rt_iif; } /* Was this packet marked by Explicit Congestion Notification? */ @@ -848,8 +848,8 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb, skb->len, - &skb->rtable->rt_src, - &skb->rtable->rt_dst); + &skb_rtable(skb)->rt_src, + &skb_rtable(skb)->rt_dst); inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; @@ -1370,6 +1370,8 @@ SCTP_STATIC __exit void sctp_exit(void) sctp_proc_exit(); cleanup_sctp_mibs(); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ + kmem_cache_destroy(sctp_chunk_cachep); kmem_cache_destroy(sctp_bucket_cachep); } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 6851ee94e974..61cc6075b0df 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2864,19 +2864,19 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, switch (addr_param->v4.param_hdr.type) { case SCTP_PARAM_IPV6_ADDRESS: if (!asoc->peer.ipv6_address) - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_DNS_FAILED; break; case SCTP_PARAM_IPV4_ADDRESS: if (!asoc->peer.ipv4_address) - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_DNS_FAILED; break; default: - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_DNS_FAILED; } af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); if (unlikely(!af)) - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_DNS_FAILED; af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); @@ -2886,7 +2886,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * make sure we check for that) */ if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb)) - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_DNS_FAILED; switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: @@ -2954,12 +2954,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, peer = sctp_assoc_lookup_paddr(asoc, &addr); if (!peer) - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_DNS_FAILED; sctp_assoc_set_primary(asoc, peer); break; default: - return SCTP_ERROR_INV_PARAM; + return SCTP_ERROR_UNKNOWN_PARAM; break; } @@ -3273,7 +3273,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, retval = 1; break; - case SCTP_ERROR_INV_PARAM: + case SCTP_ERROR_UNKNOWN_PARAM: /* Disable sending this type of asconf parameter in * future. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index e2020eb2c8ca..86426aac1600 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -686,7 +686,8 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, { struct sctp_transport *t; - t = sctp_assoc_choose_shutdown_transport(asoc); + t = sctp_assoc_choose_alter_transport(asoc, + asoc->shutdown_last_sent_to); asoc->shutdown_last_sent_to = t; asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; chunk->transport = t; @@ -777,7 +778,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, { struct sctp_transport *t; - t = asoc->peer.active_path; + t = sctp_assoc_choose_alter_transport(asoc, chunk->transport); asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; chunk->transport = t; } @@ -1379,7 +1380,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_INIT_CHOOSE_TRANSPORT: chunk = cmd->obj.ptr; - t = sctp_assoc_choose_init_transport(asoc); + t = sctp_assoc_choose_alter_transport(asoc, + asoc->init_last_sent_to); asoc->init_last_sent_to = t; chunk->transport = t; t->init_sent_count++; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 55a61aa69662..7288192f7df5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5432,9 +5432,13 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, if (!reply) goto nomem; - /* Do some failure management (Section 8.2). */ - sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, - SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); + /* Do some failure management (Section 8.2). + * If we remove the transport an SHUTDOWN was last sent to, don't + * do failure management. + */ + if (asoc->shutdown_last_sent_to) + sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, + SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for * the T2-shutdown timer. @@ -5471,7 +5475,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire( * detection on the appropriate destination address as defined in * RFC2960 [5] section 8.1 and 8.2. */ - sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); + if (transport) + sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, + SCTP_TRANSPORT(transport)); /* Reconfig T4 timer and transport. */ sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 5c8186d88c61..6d9b3aafcc5d 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -698,7 +698,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ -} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ +} /* TYPE_SCTP_PRIMITIVE_ASCONF */ /* The primary index for this table is the primitive type. * The secondary index for this table is the state. diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5fb3a8c9792e..0f01e5d8a24f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1100,6 +1100,15 @@ static int __sctp_connect(struct sock* sk, goto out_free; } + /* In case the user of sctp_connectx() wants an association + * id back, assign one now. + */ + if (assoc_id) { + err = sctp_assoc_set_id(asoc, GFP_KERNEL); + if (err < 0) + goto out_free; + } + err = sctp_primitive_ASSOCIATE(asoc, NULL); if (err < 0) { goto out_free; @@ -1120,7 +1129,7 @@ static int __sctp_connect(struct sock* sk, timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); err = sctp_wait_for_connect(asoc, &timeo); - if (!err && assoc_id) + if ((err == 0 || err == -EINPROGRESS) && assoc_id) *assoc_id = asoc->assoc_id; /* Don't free association on exit. */ @@ -1264,6 +1273,34 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, return assoc_id; } +/* + * New (hopefully final) interface for the API. The option buffer is used + * both for the returned association id and the addresses. + */ +SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, + char __user *optval, + int __user *optlen) +{ + sctp_assoc_t assoc_id = 0; + int err = 0; + + if (len < sizeof(assoc_id)) + return -EINVAL; + + err = __sctp_setsockopt_connectx(sk, + (struct sockaddr __user *)(optval + sizeof(assoc_id)), + len - sizeof(assoc_id), &assoc_id); + + if (err == 0 || err == -EINPROGRESS) { + if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) + return -EFAULT; + if (put_user(sizeof(assoc_id), optlen)) + return -EFAULT; + } + + return err; +} + /* API 3.1.4 close() - UDP Style Syntax * Applications use close() to perform graceful shutdown (as described in * Section 10.1 of [SCTP]) on ALL the associations currently represented @@ -1844,7 +1881,7 @@ static int sctp_skb_pull(struct sk_buff *skb, int len) len -= skb_len; __skb_pull(skb, skb_len); - for (list = skb_shinfo(skb)->frag_list; list; list = list->next) { + skb_walk_frags(skb, list) { rlen = sctp_skb_pull(list, len); skb->len -= (len-rlen); skb->data_len -= (len-rlen); @@ -5578,6 +5615,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, retval = sctp_getsockopt_local_addrs(sk, len, optval, optlen); break; + case SCTP_SOCKOPT_CONNECTX3: + retval = sctp_getsockopt_connectx3(sk, len, optval, optlen); + break; case SCTP_DEFAULT_SEND_PARAM: retval = sctp_getsockopt_default_send_param(sk, len, optval, optlen); @@ -6620,7 +6660,7 @@ static void sctp_sock_rfree_frag(struct sk_buff *skb) goto done; /* Don't forget the fragments. */ - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) + skb_walk_frags(skb, frag) sctp_sock_rfree_frag(frag); done: @@ -6635,7 +6675,7 @@ static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) goto done; /* Don't forget the fragments. */ - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) + skb_walk_frags(skb, frag) sctp_skb_set_owner_r_frag(frag, sk); done: diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index f58e994e6852..63eabbc71298 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -49,8 +49,8 @@ static int zero = 0; static int one = 1; static int timer_max = 86400000; /* ms in one day */ static int int_max = INT_MAX; -static long sack_timer_min = 1; -static long sack_timer_max = 500; +static int sack_timer_min = 1; +static int sack_timer_max = 500; extern int sysctl_sctp_mem[3]; extern int sysctl_sctp_rmem[3]; @@ -223,7 +223,7 @@ static ctl_table sctp_table[] = { .ctl_name = NET_SCTP_SACK_TIMEOUT, .procname = "sack_timeout", .data = &sctp_sack_timeout, - .maxlen = sizeof(long), + .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, .strategy = sysctl_intvec, diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 5f186ca550d7..8b3560fd876d 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -976,9 +976,8 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, * In general, the skb passed from IP can have only 1 level of * fragments. But we allow multiple levels of fragments. */ - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + skb_walk_frags(skb, frag) sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc); - } } /* Do accounting for bytes just read by user and release the references to @@ -1003,7 +1002,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) goto done; /* Don't forget the fragments. */ - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + skb_walk_frags(skb, frag) { /* NOTE: skb_shinfos are recursive. Although IP returns * skb's with only 1 level of fragments, SCTP reassembly can * increase the levels. @@ -1026,7 +1025,7 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) goto done; /* Don't forget the fragments. */ - for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { + skb_walk_frags(skb, frag) { /* NOTE: skb_shinfos are recursive. Although IP returns * skb's with only 1 level of fragments, SCTP reassembly can * increase the levels. diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index e630b38a6047..66d458fc6920 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1548,6 +1548,7 @@ static void __exit exit_rpcsec_gss(void) { gss_svc_shutdown(); rpcauth_unregister(&authgss_ops); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } MODULE_LICENSE("GPL"); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index e18596146013..6c2d61586551 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -918,7 +918,7 @@ static void xs_udp_data_ready(struct sock *sk, int len) UDPX_INC_STATS_BH(sk, UDP_MIB_INDATAGRAMS); /* Something worked... */ - dst_confirm(skb->dst); + dst_confirm(skb_dst(skb)); xprt_adjust_cwnd(task, copied); xprt_update_rtt(task); diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index f72ba774c246..524ba5696d4d 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -167,7 +167,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) tb_ptr->mtu = dev->mtu; tb_ptr->blocked = 0; tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH); - memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN); + memcpy(&tb_ptr->addr.dev_addr, dev->dev_addr, ETH_ALEN); return 0; } diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index c387217bb230..3c57005e44d1 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -68,7 +68,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) return 0; } -static struct genl_family family = { +static struct genl_family tipc_genl_family = { .id = GENL_ID_GENERATE, .name = TIPC_GENL_NAME, .version = TIPC_GENL_VERSION, @@ -76,39 +76,33 @@ static struct genl_family family = { .maxattr = 0, }; -static struct genl_ops ops = { +static struct genl_ops tipc_genl_ops = { .cmd = TIPC_GENL_CMD, .doit = handle_cmd, }; -static int family_registered = 0; +static int tipc_genl_family_registered; int tipc_netlink_start(void) { + int res; + res = genl_register_family_with_ops(&tipc_genl_family, + &tipc_genl_ops, 1); + if (res) { + err("Failed to register netlink interface\n"); + return res; + } - if (genl_register_family(&family)) - goto err; - - family_registered = 1; - - if (genl_register_ops(&family, &ops)) - goto err_unregister; - + tipc_genl_family_registered = 1; return 0; - - err_unregister: - genl_unregister_family(&family); - family_registered = 0; - err: - err("Failed to register netlink interface\n"); - return -EFAULT; } void tipc_netlink_stop(void) { - if (family_registered) { - genl_unregister_family(&family); - family_registered = 0; - } + if (!tipc_genl_family_registered) + return; + + genl_unregister_family(&tipc_genl_family); + tipc_genl_family_registered = 0; } diff --git a/net/wimax/Kconfig b/net/wimax/Kconfig index 1b46747a5f5a..e4d97ab476d5 100644 --- a/net/wimax/Kconfig +++ b/net/wimax/Kconfig @@ -1,23 +1,10 @@ # # WiMAX LAN device configuration # -# Note the ugly 'depends on' on WIMAX: that disallows RFKILL to be a -# module if WIMAX is to be linked in. The WiMAX code is done in such a -# way that it doesn't require and explicit dependency on RFKILL in -# case an embedded system wants to rip it out. -# -# As well, enablement of the RFKILL code means we need the INPUT layer -# support to inject events coming from hw rfkill switches. That -# dependency could be killed if input.h provided appropriate means to -# work when input is disabled. - -comment "WiMAX Wireless Broadband support requires CONFIG_INPUT enabled" - depends on INPUT = n && RFKILL != n menuconfig WIMAX tristate "WiMAX Wireless Broadband support" - depends on (y && RFKILL != m) || m - depends on (INPUT && RFKILL != n) || RFKILL = n + depends on RFKILL || !RFKILL help Select to configure support for devices that provide diff --git a/net/wimax/Makefile b/net/wimax/Makefile index 5b80b941c2c9..8f1510d0cc2b 100644 --- a/net/wimax/Makefile +++ b/net/wimax/Makefile @@ -6,6 +6,7 @@ wimax-y := \ op-msg.o \ op-reset.o \ op-rfkill.o \ + op-state-get.o \ stack.o wimax-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/net/wimax/debug-levels.h b/net/wimax/debug-levels.h index 1c29123a3aa9..0975adba6b71 100644 --- a/net/wimax/debug-levels.h +++ b/net/wimax/debug-levels.h @@ -36,6 +36,7 @@ enum d_module { D_SUBMODULE_DECLARE(op_msg), D_SUBMODULE_DECLARE(op_reset), D_SUBMODULE_DECLARE(op_rfkill), + D_SUBMODULE_DECLARE(op_state_get), D_SUBMODULE_DECLARE(stack), }; diff --git a/net/wimax/debugfs.c b/net/wimax/debugfs.c index 94d216a46407..6c9bedb7431e 100644 --- a/net/wimax/debugfs.c +++ b/net/wimax/debugfs.c @@ -61,6 +61,7 @@ int wimax_debugfs_add(struct wimax_dev *wimax_dev) __debugfs_register("wimax_dl_", op_msg, dentry); __debugfs_register("wimax_dl_", op_reset, dentry); __debugfs_register("wimax_dl_", op_rfkill, dentry); + __debugfs_register("wimax_dl_", op_state_get, dentry); __debugfs_register("wimax_dl_", stack, dentry); result = 0; out: diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index 9ad4d893a566..d631a17186bc 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c @@ -108,6 +108,12 @@ * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. + * + * Unlike other WiMAX stack calls, this call can be used way early, + * even before wimax_dev_add() is called, as long as the + * wimax_dev->net_dev pointer is set to point to a proper + * net_dev. This is so that drivers can use it early in case they need + * to send stuff around or communicate with user space. */ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, const char *pipe_name, @@ -115,7 +121,7 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, gfp_t gfp_flags) { int result; - struct device *dev = wimax_dev->net_dev->dev.parent; + struct device *dev = wimax_dev_to_dev(wimax_dev); size_t msg_size; void *genl_msg; struct sk_buff *skb; @@ -161,7 +167,6 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, error_new: nlmsg_free(skb); return ERR_PTR(result); - } EXPORT_SYMBOL_GPL(wimax_msg_alloc); @@ -256,10 +261,16 @@ EXPORT_SYMBOL_GPL(wimax_msg_len); * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. + * + * Unlike other WiMAX stack calls, this call can be used way early, + * even before wimax_dev_add() is called, as long as the + * wimax_dev->net_dev pointer is set to point to a proper + * net_dev. This is so that drivers can use it early in case they need + * to send stuff around or communicate with user space. */ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { - struct device *dev = wimax_dev->net_dev->dev.parent; + struct device *dev = wimax_dev_to_dev(wimax_dev); void *msg = skb->data; size_t size = skb->len; might_sleep(); diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c index 2b75aee04217..70ef4df863b9 100644 --- a/net/wimax/op-rfkill.c +++ b/net/wimax/op-rfkill.c @@ -29,8 +29,8 @@ * A non-polled generic rfkill device is embedded into the WiMAX * subsystem's representation of a device. * - * FIXME: Need polled support? use a timer or add the implementation - * to the stack. + * FIXME: Need polled support? Let drivers provide a poll routine + * and hand it to rfkill ops then? * * All device drivers have to do is after wimax_dev_init(), call * wimax_report_rfkill_hw() and wimax_report_rfkill_sw() to update @@ -43,7 +43,7 @@ * wimax_rfkill() Kernel calling wimax_rfkill() * __wimax_rf_toggle_radio() * - * wimax_rfkill_toggle_radio() RF-Kill subsytem calling + * wimax_rfkill_set_radio_block() RF-Kill subsytem calling * __wimax_rf_toggle_radio() * * __wimax_rf_toggle_radio() @@ -65,15 +65,11 @@ #include #include #include -#include #include "wimax-internal.h" #define D_SUBMODULE op_rfkill #include "debug-levels.h" -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - - /** * wimax_report_rfkill_hw - Reports changes in the hardware RF switch * @@ -99,7 +95,6 @@ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev, int result; struct device *dev = wimax_dev_to_dev(wimax_dev); enum wimax_st wimax_state; - enum rfkill_state rfkill_state; d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); BUG_ON(state == WIMAX_RF_QUERY); @@ -112,16 +107,16 @@ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev, if (state != wimax_dev->rf_hw) { wimax_dev->rf_hw = state; - rfkill_state = state == WIMAX_RF_ON ? - RFKILL_STATE_OFF : RFKILL_STATE_ON; if (wimax_dev->rf_hw == WIMAX_RF_ON && wimax_dev->rf_sw == WIMAX_RF_ON) wimax_state = WIMAX_ST_READY; else wimax_state = WIMAX_ST_RADIO_OFF; + + result = rfkill_set_hw_state(wimax_dev->rfkill, + state == WIMAX_RF_OFF); + __wimax_state_change(wimax_dev, wimax_state); - input_report_key(wimax_dev->rfkill_input, KEY_WIMAX, - rfkill_state); } error_not_ready: mutex_unlock(&wimax_dev->mutex); @@ -174,6 +169,7 @@ void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev, else wimax_state = WIMAX_ST_RADIO_OFF; __wimax_state_change(wimax_dev, wimax_state); + rfkill_set_sw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF); } error_not_ready: mutex_unlock(&wimax_dev->mutex); @@ -249,36 +245,31 @@ int __wimax_rf_toggle_radio(struct wimax_dev *wimax_dev, * * NOTE: This call will block until the operation is completed. */ -static -int wimax_rfkill_toggle_radio(void *data, enum rfkill_state state) +static int wimax_rfkill_set_radio_block(void *data, bool blocked) { int result; struct wimax_dev *wimax_dev = data; struct device *dev = wimax_dev_to_dev(wimax_dev); enum wimax_rf_state rf_state; - d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); - switch (state) { - case RFKILL_STATE_ON: + d_fnstart(3, dev, "(wimax_dev %p blocked %u)\n", wimax_dev, blocked); + rf_state = WIMAX_RF_ON; + if (blocked) rf_state = WIMAX_RF_OFF; - break; - case RFKILL_STATE_OFF: - rf_state = WIMAX_RF_ON; - break; - default: - BUG(); - } mutex_lock(&wimax_dev->mutex); if (wimax_dev->state <= __WIMAX_ST_QUIESCING) - result = 0; /* just pretend it didn't happen */ + result = 0; else result = __wimax_rf_toggle_radio(wimax_dev, rf_state); mutex_unlock(&wimax_dev->mutex); - d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n", - wimax_dev, state, result); + d_fnend(3, dev, "(wimax_dev %p blocked %u) = %d\n", + wimax_dev, blocked, result); return result; } +static const struct rfkill_ops wimax_rfkill_ops = { + .set_block = wimax_rfkill_set_radio_block, +}; /** * wimax_rfkill - Set the software RF switch state for a WiMAX device @@ -322,6 +313,7 @@ int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state) result = __wimax_rf_toggle_radio(wimax_dev, state); if (result < 0) goto error; + rfkill_set_sw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF); break; case WIMAX_RF_QUERY: break; @@ -349,41 +341,20 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev) { int result; struct rfkill *rfkill; - struct input_dev *input_dev; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev); /* Initialize RF Kill */ result = -ENOMEM; - rfkill = rfkill_allocate(dev, RFKILL_TYPE_WIMAX); + rfkill = rfkill_alloc(wimax_dev->name, dev, RFKILL_TYPE_WIMAX, + &wimax_rfkill_ops, wimax_dev); if (rfkill == NULL) goto error_rfkill_allocate; + + d_printf(1, dev, "rfkill %p\n", rfkill); + wimax_dev->rfkill = rfkill; - rfkill->name = wimax_dev->name; - rfkill->state = RFKILL_STATE_OFF; - rfkill->data = wimax_dev; - rfkill->toggle_radio = wimax_rfkill_toggle_radio; - rfkill->user_claim_unsupported = 1; - - /* Initialize the input device for the hw key */ - input_dev = input_allocate_device(); - if (input_dev == NULL) - goto error_input_allocate; - wimax_dev->rfkill_input = input_dev; - d_printf(1, dev, "rfkill %p input %p\n", rfkill, input_dev); - - input_dev->name = wimax_dev->name; - /* FIXME: get a real device bus ID and stuff? do we care? */ - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0xffff; - input_dev->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WIMAX, input_dev->keybit); - - /* Register both */ - result = input_register_device(wimax_dev->rfkill_input); - if (result < 0) - goto error_input_register; result = rfkill_register(wimax_dev->rfkill); if (result < 0) goto error_rfkill_register; @@ -395,17 +366,8 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev) d_fnend(3, dev, "(wimax_dev %p) = 0\n", wimax_dev); return 0; - /* if rfkill_register() suceeds, can't use rfkill_free() any - * more, only rfkill_unregister() [it owns the refcount]; with - * the input device we have the same issue--hence the if. */ error_rfkill_register: - input_unregister_device(wimax_dev->rfkill_input); - wimax_dev->rfkill_input = NULL; -error_input_register: - if (wimax_dev->rfkill_input) - input_free_device(wimax_dev->rfkill_input); -error_input_allocate: - rfkill_free(wimax_dev->rfkill); + rfkill_destroy(wimax_dev->rfkill); error_rfkill_allocate: d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result); return result; @@ -424,45 +386,12 @@ void wimax_rfkill_rm(struct wimax_dev *wimax_dev) { struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev); - rfkill_unregister(wimax_dev->rfkill); /* frees */ - input_unregister_device(wimax_dev->rfkill_input); + rfkill_unregister(wimax_dev->rfkill); + rfkill_destroy(wimax_dev->rfkill); d_fnend(3, dev, "(wimax_dev %p)\n", wimax_dev); } -#else /* #ifdef CONFIG_RFKILL */ - -void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev, - enum wimax_rf_state state) -{ -} -EXPORT_SYMBOL_GPL(wimax_report_rfkill_hw); - -void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev, - enum wimax_rf_state state) -{ -} -EXPORT_SYMBOL_GPL(wimax_report_rfkill_sw); - -int wimax_rfkill(struct wimax_dev *wimax_dev, - enum wimax_rf_state state) -{ - return WIMAX_RF_ON << 1 | WIMAX_RF_ON; -} -EXPORT_SYMBOL_GPL(wimax_rfkill); - -int wimax_rfkill_add(struct wimax_dev *wimax_dev) -{ - return 0; -} - -void wimax_rfkill_rm(struct wimax_dev *wimax_dev) -{ -} - -#endif /* #ifdef CONFIG_RFKILL */ - - /* * Exporting to user space over generic netlink * diff --git a/net/wimax/op-state-get.c b/net/wimax/op-state-get.c new file mode 100644 index 000000000000..a76b8fcb056d --- /dev/null +++ b/net/wimax/op-state-get.c @@ -0,0 +1,86 @@ +/* + * Linux WiMAX + * Implement and export a method for getting a WiMAX device current state + * + * Copyright (C) 2009 Paulius Zaleckas + * + * Based on previous WiMAX core work by: + * Copyright (C) 2008 Intel Corporation + * Inaky Perez-Gonzalez + * + * 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 +#include +#include +#include +#include "wimax-internal.h" + +#define D_SUBMODULE op_state_get +#include "debug-levels.h" + + +static const +struct nla_policy wimax_gnl_state_get_policy[WIMAX_GNL_ATTR_MAX + 1] = { + [WIMAX_GNL_STGET_IFIDX] = { + .type = NLA_U32, + }, +}; + + +/* + * Exporting to user space over generic netlink + * + * Parse the state get command from user space, return a combination + * value that describe the current state. + * + * No attributes. + */ +static +int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info) +{ + int result, ifindex; + struct wimax_dev *wimax_dev; + struct device *dev; + + d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); + result = -ENODEV; + if (info->attrs[WIMAX_GNL_STGET_IFIDX] == NULL) { + printk(KERN_ERR "WIMAX_GNL_OP_STATE_GET: can't find IFIDX " + "attribute\n"); + goto error_no_wimax_dev; + } + ifindex = nla_get_u32(info->attrs[WIMAX_GNL_STGET_IFIDX]); + wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); + if (wimax_dev == NULL) + goto error_no_wimax_dev; + dev = wimax_dev_to_dev(wimax_dev); + /* Execute the operation and send the result back to user space */ + result = wimax_state_get(wimax_dev); + dev_put(wimax_dev->net_dev); +error_no_wimax_dev: + d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result); + return result; +} + + +struct genl_ops wimax_gnl_state_get = { + .cmd = WIMAX_GNL_OP_STATE_GET, + .flags = GENL_ADMIN_PERM, + .policy = wimax_gnl_state_get_policy, + .doit = wimax_gnl_doit_state_get, + .dumpit = NULL, +}; diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 933e1422b09f..79fb7d7c640f 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -402,13 +402,15 @@ EXPORT_SYMBOL_GPL(wimax_dev_init); extern struct genl_ops wimax_gnl_msg_from_user, wimax_gnl_reset, - wimax_gnl_rfkill; + wimax_gnl_rfkill, + wimax_gnl_state_get; static struct genl_ops *wimax_gnl_ops[] = { &wimax_gnl_msg_from_user, &wimax_gnl_reset, &wimax_gnl_rfkill, + &wimax_gnl_state_get, }; @@ -533,6 +535,7 @@ struct d_level D_LEVEL[] = { D_SUBMODULE_DEFINE(op_msg), D_SUBMODULE_DEFINE(op_reset), D_SUBMODULE_DEFINE(op_rfkill), + D_SUBMODULE_DEFINE(op_state_get), D_SUBMODULE_DEFINE(stack), }; size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 3c3bc9e579ed..4428dd5e911d 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -1,5 +1,6 @@ config CFG80211 - tristate "Improved wireless configuration API" + tristate "Improved wireless configuration API" + depends on RFKILL || !RFKILL config CFG80211_REG_DEBUG bool "cfg80211 regulatory debugging" @@ -10,6 +11,14 @@ config CFG80211_REG_DEBUG If unsure, say N. +config CFG80211_DEBUGFS + bool "cfg80211 DebugFS entries" + depends on CFG80211 && DEBUG_FS + ---help--- + You can enable this if you want to debugfs entries for cfg80211. + + If unsure, say N. + config WIRELESS_OLD_REGULATORY bool "Old wireless static regulatory definitions" default n diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 6d1e7b27b752..f78c4832a9ca 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -5,7 +5,8 @@ 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 +cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o +cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/net/wireless/core.c b/net/wireless/core.c index d1f556535f6d..d5850292b3df 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1,7 +1,7 @@ /* * This is the linux wireless configuration interface. * - * Copyright 2006-2008 Johannes Berg + * Copyright 2006-2009 Johannes Berg */ #include @@ -12,12 +12,13 @@ #include #include #include +#include #include #include -#include #include "nl80211.h" #include "core.h" #include "sysfs.h" +#include "debugfs.h" /* name for sysfs, %d is appended */ #define PHY_NAME "phy" @@ -227,9 +228,44 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, return 0; } +static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) +{ + struct cfg80211_registered_device *drv = data; + + drv->ops->rfkill_poll(&drv->wiphy); +} + +static int cfg80211_rfkill_set_block(void *data, bool blocked) +{ + struct cfg80211_registered_device *drv = data; + struct wireless_dev *wdev; + + if (!blocked) + return 0; + + rtnl_lock(); + mutex_lock(&drv->devlist_mtx); + + list_for_each_entry(wdev, &drv->netdev_list, list) + dev_close(wdev->netdev); + + mutex_unlock(&drv->devlist_mtx); + rtnl_unlock(); + + return 0; +} + +static void cfg80211_rfkill_sync_work(struct work_struct *work) +{ + struct cfg80211_registered_device *drv; + + drv = container_of(work, struct cfg80211_registered_device, rfkill_sync); + cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill)); +} + /* exported functions */ -struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) +struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) { static int wiphy_counter; @@ -274,6 +310,28 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) drv->wiphy.dev.class = &ieee80211_class; drv->wiphy.dev.platform_data = drv; + 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); + + if (!drv->rfkill) { + kfree(drv); + return NULL; + } + + INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_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; + return &drv->wiphy; } EXPORT_SYMBOL(wiphy_new); @@ -337,17 +395,23 @@ int wiphy_register(struct wiphy *wiphy) /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); + res = device_add(&drv->wiphy.dev); + if (res) + return res; + + res = rfkill_register(drv->rfkill); + if (res) + goto out_rm_dev; + mutex_lock(&cfg80211_mutex); /* set up regulatory info */ wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); - res = device_add(&drv->wiphy.dev); - if (res) - goto out_unlock; - list_add(&drv->list, &cfg80211_drv_list); + mutex_unlock(&cfg80211_mutex); + /* add to debugfs */ drv->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&drv->wiphy), @@ -366,17 +430,41 @@ int wiphy_register(struct wiphy *wiphy) nl80211_send_reg_change_event(&request); } - res = 0; -out_unlock: - mutex_unlock(&cfg80211_mutex); + cfg80211_debugfs_drv_add(drv); + + return 0; + + out_rm_dev: + device_del(&drv->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); + + if (!drv->ops->rfkill_poll) + return; + drv->rfkill_ops.poll = cfg80211_rfkill_poll; + rfkill_resume_polling(drv->rfkill); +} +EXPORT_SYMBOL(wiphy_rfkill_start_polling); + +void wiphy_rfkill_stop_polling(struct wiphy *wiphy) +{ + struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); + + rfkill_pause_polling(drv->rfkill); +} +EXPORT_SYMBOL(wiphy_rfkill_stop_polling); + void wiphy_unregister(struct wiphy *wiphy) { struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); + rfkill_unregister(drv->rfkill); + /* protect the device list */ mutex_lock(&cfg80211_mutex); @@ -396,6 +484,8 @@ void wiphy_unregister(struct wiphy *wiphy) /* unlock again before freeing */ mutex_unlock(&drv->mtx); + cfg80211_debugfs_drv_del(drv); + /* 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); @@ -411,6 +501,7 @@ EXPORT_SYMBOL(wiphy_unregister); void cfg80211_dev_free(struct cfg80211_registered_device *drv) { 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) @@ -424,6 +515,15 @@ void wiphy_free(struct wiphy *wiphy) } EXPORT_SYMBOL(wiphy_free); +void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) +{ + struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); + + if (rfkill_set_hw_state(drv->rfkill, blocked)) + schedule_work(&drv->rfkill_sync); +} +EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); + static int cfg80211_netdev_notifier_call(struct notifier_block * nb, unsigned long state, void *ndev) @@ -432,7 +532,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, struct cfg80211_registered_device *rdev; if (!dev->ieee80211_ptr) - return 0; + return NOTIFY_DONE; rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); @@ -448,8 +548,28 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, "symlink to netdev!\n"); } dev->ieee80211_ptr->netdev = dev; +#ifdef CONFIG_WIRELESS_EXT + dev->ieee80211_ptr->wext.default_key = -1; + dev->ieee80211_ptr->wext.default_mgmt_key = -1; +#endif mutex_unlock(&rdev->devlist_mtx); break; + case NETDEV_GOING_DOWN: + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) + break; + if (!dev->ieee80211_ptr->ssid_len) + break; + cfg80211_leave_ibss(rdev, dev, true); + break; + case NETDEV_UP: +#ifdef CONFIG_WIRELESS_EXT + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) + break; + if (!dev->ieee80211_ptr->wext.ibss.ssid_len) + break; + cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss); + break; +#endif case NETDEV_UNREGISTER: mutex_lock(&rdev->devlist_mtx); if (!list_empty(&dev->ieee80211_ptr->list)) { @@ -458,9 +578,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, } mutex_unlock(&rdev->devlist_mtx); break; + case NETDEV_PRE_UP: + if (rfkill_blocked(rdev->rfkill)) + return notifier_from_errno(-ERFKILL); + break; } - return 0; + return NOTIFY_DONE; } static struct notifier_block cfg80211_netdev_notifier = { diff --git a/net/wireless/core.h b/net/wireless/core.h index 0a592e4295f0..bfa340c7abb5 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -1,7 +1,7 @@ /* * Wireless configuration interface internals. * - * Copyright 2006, 2007 Johannes Berg + * Copyright 2006-2009 Johannes Berg */ #ifndef __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H @@ -10,14 +10,15 @@ #include #include #include -#include +#include +#include +#include #include -#include #include #include "reg.h" struct cfg80211_registered_device { - struct cfg80211_ops *ops; + const struct cfg80211_ops *ops; struct list_head list; /* we hold this mutex during any call so that * we cannot do multiple calls at once, and also @@ -25,6 +26,11 @@ struct cfg80211_registered_device { * any call is in progress */ struct mutex mtx; + /* rfkill support */ + struct rfkill_ops rfkill_ops; + struct rfkill *rfkill; + struct work_struct rfkill_sync; + /* ISO / IEC 3166 alpha2 for which this device is receiving * country IEs on, this can help disregard country IEs from APs * on the same alpha2 quickly. The alpha2 may differ from @@ -52,6 +58,17 @@ struct cfg80211_registered_device { struct cfg80211_scan_request *scan_req; /* protected by RTNL */ unsigned long suspend_at; +#ifdef CONFIG_CFG80211_DEBUGFS + /* Debugfs entries */ + struct wiphy_debugfsdentries { + struct dentry *rts_threshold; + struct dentry *fragmentation_threshold; + struct dentry *short_retry_limit; + struct dentry *long_retry_limit; + struct dentry *ht40allow_map; + } debugfs; +#endif + /* must be last because of the way we do wiphy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); @@ -74,10 +91,7 @@ bool wiphy_idx_valid(int wiphy_idx) extern struct mutex cfg80211_mutex; extern struct list_head cfg80211_drv_list; -static inline void assert_cfg80211_lock(void) -{ - WARN_ON(!mutex_is_locked(&cfg80211_mutex)); -} +#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. @@ -148,4 +162,16 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev); 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); +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); + +/* internal helpers */ +int cfg80211_validate_key_settings(struct key_params *params, int key_idx, + const u8 *mac_addr); + #endif /* __NET_WIRELESS_CORE_H */ diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c new file mode 100644 index 000000000000..679ddfcec1ee --- /dev/null +++ b/net/wireless/debugfs.c @@ -0,0 +1,131 @@ +/* + * cfg80211 debugfs + * + * Copyright 2009 Luis R. Rodriguez + * Copyright 2007 Johannes Berg + * + * 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 "core.h" +#include "debugfs.h" + +static int cfg80211_open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +#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 wiphy *wiphy= 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 = cfg80211_open_file_generic, \ +}; + +DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", + wiphy->rts_threshold) +DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", + wiphy->frag_threshold); +DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", + wiphy->retry_short) +DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", + wiphy->retry_long); + +static int ht_print_chan(struct ieee80211_channel *chan, + char *buf, int buf_size, int offset) +{ + if (WARN_ON(offset > buf_size)) + return 0; + + if (chan->flags & IEEE80211_CHAN_DISABLED) + return snprintf(buf + offset, + buf_size - offset, + "%d Disabled\n", + chan->center_freq); + + return snprintf(buf + offset, + buf_size - offset, + "%d HT40 %c%c\n", + chan->center_freq, + (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-', + (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+'); +} + +static ssize_t ht40allow_map_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wiphy *wiphy = file->private_data; + char *buf; + unsigned int offset = 0, buf_size = PAGE_SIZE, i, r; + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + + buf = kzalloc(buf_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + mutex_lock(&cfg80211_mutex); + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + for (i = 0; i < sband->n_channels; i++) + offset += ht_print_chan(&sband->channels[i], + buf, buf_size, offset); + } + + mutex_unlock(&cfg80211_mutex); + + r = simple_read_from_buffer(user_buf, count, ppos, buf, offset); + + kfree(buf); + + return r; +} + +static const struct file_operations ht40allow_map_ops = { + .read = ht40allow_map_read, + .open = cfg80211_open_file_generic, +}; + +#define DEBUGFS_ADD(name) \ + drv->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \ + &drv->wiphy, &name## _ops); +#define DEBUGFS_DEL(name) \ + debugfs_remove(drv->debugfs.name); \ + drv->debugfs.name = NULL; + +void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) +{ + struct dentry *phyd = drv->wiphy.debugfsdir; + + DEBUGFS_ADD(rts_threshold); + DEBUGFS_ADD(fragmentation_threshold); + DEBUGFS_ADD(short_retry_limit); + DEBUGFS_ADD(long_retry_limit); + DEBUGFS_ADD(ht40allow_map); +} + +void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) +{ + DEBUGFS_DEL(rts_threshold); + DEBUGFS_DEL(fragmentation_threshold); + DEBUGFS_DEL(short_retry_limit); + DEBUGFS_DEL(long_retry_limit); + DEBUGFS_DEL(ht40allow_map); +} diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h new file mode 100644 index 000000000000..c226983ae66b --- /dev/null +++ b/net/wireless/debugfs.h @@ -0,0 +1,14 @@ +#ifndef __CFG80211_DEBUGFS_H +#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); +#else +static inline +void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) {} +static inline +void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) {} +#endif + +#endif /* __CFG80211_DEBUGFS_H */ diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c new file mode 100644 index 000000000000..a4a1c3498ff2 --- /dev/null +++ b/net/wireless/ibss.c @@ -0,0 +1,369 @@ +/* + * Some IBSS support code for cfg80211. + * + * Copyright 2009 Johannes Berg + */ + +#include +#include +#include +#include "nl80211.h" + + +void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_bss *bss; +#ifdef CONFIG_WIRELESS_EXT + union iwreq_data wrqu; +#endif + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return; + + 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); + + if (WARN_ON(!bss)) + return; + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->current_bss); + } + + cfg80211_hold_bss(bss); + wdev->current_bss = bss; + memcpy(wdev->bssid, bssid, ETH_ALEN); + + nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp); +#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 +} +EXPORT_SYMBOL(cfg80211_ibss_joined); + +int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; + + if (wdev->ssid_len) + return -EALREADY; + +#ifdef CONFIG_WIRELESS_EXT + wdev->wext.ibss.channel = params->channel; +#endif + err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); + + if (err) + return err; + + memcpy(wdev->ssid, params->ssid, params->ssid_len); + wdev->ssid_len = params->ssid_len; + + return 0; +} + +void cfg80211_clear_ibss(struct net_device *dev, bool nowext) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->current_bss); + } + + 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) +{ + int err; + + err = rdev->ops->leave_ibss(&rdev->wiphy, dev); + + if (err) + return err; + + cfg80211_clear_ibss(dev, nowext); + + return 0; +} + +#ifdef CONFIG_WIRELESS_EXT +static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev) +{ + enum ieee80211_band band; + int i; + + if (!wdev->wext.ibss.beacon_interval) + wdev->wext.ibss.beacon_interval = 100; + + /* try to find an IBSS channel if none requested ... */ + if (!wdev->wext.ibss.channel) { + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + sband = rdev->wiphy.bands[band]; + if (!sband) + continue; + + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + if (chan->flags & IEEE80211_CHAN_NO_IBSS) + continue; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + wdev->wext.ibss.channel = chan; + break; + } + + if (wdev->wext.ibss.channel) + break; + } + + if (!wdev->wext.ibss.channel) + return -EINVAL; + } + + /* don't join -- SSID is not there */ + if (!wdev->wext.ibss.ssid_len) + return 0; + + if (!netif_running(wdev->netdev)) + return 0; + + return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), + wdev->netdev, &wdev->wext.ibss); +} + +int cfg80211_ibss_wext_siwfreq(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; + int err; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) + return -EOPNOTSUPP; + + chan = cfg80211_wext_freq(wdev->wiphy, freq); + if (chan && IS_ERR(chan)) + return PTR_ERR(chan); + + if (chan && + (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; + } + + if (chan) { + wdev->wext.ibss.channel = chan; + wdev->wext.ibss.channel_fixed = true; + } else { + /* cfg80211_ibss_wext_join will pick one if needed */ + wdev->wext.ibss.channel_fixed = false; + } + + return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); +} +/* 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, + struct iw_freq *freq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct ieee80211_channel *chan = NULL; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (wdev->current_bss) + chan = wdev->current_bss->channel; + else if (wdev->wext.ibss.channel) + chan = wdev->wext.ibss.channel; + + if (chan) { + freq->m = chan->center_freq; + freq->e = 6; + return 0; + } + + /* 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; + size_t len = data->length; + int err; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) + return -EOPNOTSUPP; + + if (wdev->ssid_len) { + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), + dev, true); + if (err) + return err; + } + + /* iwconfig uses nul termination in SSID.. */ + if (len > 0 && ssid[len - 1] == '\0') + len--; + + wdev->wext.ibss.ssid = wdev->ssid; + memcpy(wdev->wext.ibss.ssid, ssid, len); + wdev->wext.ibss.ssid_len = len; + + return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); +} +/* 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, + struct iw_point *data, char *ssid) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + data->flags = 0; + + if (wdev->ssid_len) { + data->flags = 1; + data->length = wdev->ssid_len; + memcpy(ssid, wdev->ssid, data->length); + } else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) { + data->flags = 1; + data->length = wdev->wext.ibss.ssid_len; + memcpy(ssid, wdev->wext.ibss.ssid, data->length); + } + + 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; + u8 *bssid = ap_addr->sa_data; + int err; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) + return -EOPNOTSUPP; + + if (ap_addr->sa_family != ARPHRD_ETHER) + return -EINVAL; + + /* automatic mode */ + if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) + bssid = NULL; + + /* both automatic */ + if (!bssid && !wdev->wext.ibss.bssid) + return 0; + + /* fixed already - and no change */ + if (wdev->wext.ibss.bssid && bssid && + 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; + } + + if (bssid) { + memcpy(wdev->wext.bssid, bssid, ETH_ALEN); + wdev->wext.ibss.bssid = wdev->wext.bssid; + } else + wdev->wext.ibss.bssid = NULL; + + return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); +} +/* 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, + struct sockaddr *ap_addr, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + ap_addr->sa_family = ARPHRD_ETHER; + + if (wdev->wext.ibss.bssid) { + memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); + return 0; + } + + 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 bec5721b6f99..42184361a109 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -28,19 +28,55 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) } EXPORT_SYMBOL(cfg80211_send_rx_assoc); -void cfg80211_send_rx_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) { struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - nl80211_send_rx_deauth(rdev, dev, buf, len); + nl80211_send_deauth(rdev, dev, buf, len); } -EXPORT_SYMBOL(cfg80211_send_rx_deauth); +EXPORT_SYMBOL(cfg80211_send_deauth); -void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, - size_t len) +void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) { struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - nl80211_send_rx_disassoc(rdev, dev, buf, len); + nl80211_send_disassoc(rdev, dev, buf, len); } -EXPORT_SYMBOL(cfg80211_send_rx_disassoc); +EXPORT_SYMBOL(cfg80211_send_disassoc); + +static void cfg80211_wext_disconnected(struct net_device *dev) +{ +#ifdef CONFIG_WIRELESS_EXT + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); +#endif +} + +void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_auth_timeout(rdev, dev, addr); + cfg80211_wext_disconnected(dev); +} +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 cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_assoc_timeout(rdev, dev, addr); + cfg80211_wext_disconnected(dev); +} +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) +{ + 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); +} +EXPORT_SYMBOL(cfg80211_michael_mic_failure); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2456e4ee445e..24168560ebae 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1,7 +1,7 @@ /* * This is the new netlink-based wireless configuration interface. * - * Copyright 2006, 2007 Johannes Berg + * Copyright 2006-2009 Johannes Berg */ #include @@ -57,10 +57,14 @@ static int get_drv_dev_by_info_ifindex(struct nlattr **attrs, static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, - .len = BUS_ID_SIZE-1 }, + .len = 20-1 }, [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, + [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, + [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, @@ -73,6 +77,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, + [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, @@ -116,8 +121,45 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { .len = IEEE80211_MAX_SSID_LEN }, [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 }, [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, + [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, + [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG }, + [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 }, + [NL80211_ATTR_STA_FLAGS2] = { + .len = sizeof(struct nl80211_sta_flag_update), + }, + [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, }; +/* IE validation */ +static bool is_valid_ie_attr(const struct nlattr *attr) +{ + const u8 *pos; + int len; + + if (!attr) + return true; + + pos = nla_data(attr); + len = nla_len(attr); + + while (len) { + u8 elemlen; + + if (len < 2) + return false; + len -= 2; + + elemlen = pos[1]; + if (elemlen > len) + return false; + + len -= elemlen; + pos += 2 + elemlen; + } + + return true; +} + /* message building helper */ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, int flags, u8 cmd) @@ -126,6 +168,30 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); } +static int nl80211_msg_put_channel(struct sk_buff *msg, + struct ieee80211_channel *chan) +{ + NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, + chan->center_freq); + + if (chan->flags & IEEE80211_CHAN_DISABLED) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); + if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); + if (chan->flags & IEEE80211_CHAN_NO_IBSS) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); + if (chan->flags & IEEE80211_CHAN_RADAR) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); + + NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, + DBM_TO_MBM(chan->max_power)); + + return 0; + + nla_put_failure: + return -ENOBUFS; +} + /* netlink command implementations */ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, @@ -149,8 +215,24 @@ 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_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, + dev->wiphy.retry_short); + NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, + dev->wiphy.retry_long); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + dev->wiphy.frag_threshold); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, + dev->wiphy.rts_threshold); + NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); + NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, + dev->wiphy.max_scan_ie_len); + + NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, + sizeof(u32) * dev->wiphy.n_cipher_suites, + dev->wiphy.cipher_suites); nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) @@ -202,20 +284,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, goto nla_put_failure; chan = &dev->wiphy.bands[band]->channels[i]; - NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, - chan->center_freq); - if (chan->flags & IEEE80211_CHAN_DISABLED) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); - if (chan->flags & IEEE80211_CHAN_NO_IBSS) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); - if (chan->flags & IEEE80211_CHAN_RADAR) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); - - NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - DBM_TO_MBM(chan->max_power)); + if (nl80211_msg_put_channel(msg, chan)) + goto nla_put_failure; nla_nest_end(msg, nl_freq); } @@ -273,6 +344,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(assoc, ASSOCIATE); CMD(deauth, DEAUTHENTICATE); CMD(disassoc, DISASSOCIATE); + CMD(join_ibss, JOIN_IBSS); #undef CMD nla_nest_end(msg, nl_cmds); @@ -317,7 +389,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(dev)) return PTR_ERR(dev); - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) goto out_err; @@ -365,6 +437,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev; int result = 0, rem_txq_params = 0; struct nlattr *nl_txq_params; + u32 changed; + u8 retry_short = 0, retry_long = 0; + u32 frag_threshold = 0, rts_threshold = 0; rtnl_lock(); @@ -418,7 +493,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; struct ieee80211_channel *chan; struct ieee80211_sta_ht_cap *ht_cap; - u32 freq, sec_freq; + u32 freq; if (!rdev->ops->set_channel) { result = -EOPNOTSUPP; @@ -444,33 +519,28 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) goto bad_res; - if (channel_type == NL80211_CHAN_HT40MINUS) - sec_freq = freq - 20; - else if (channel_type == NL80211_CHAN_HT40PLUS) - sec_freq = freq + 20; - else - sec_freq = 0; + 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 */ - if (channel_type != NL80211_CHAN_NO_HT && - !ht_cap->ht_supported) - goto bad_res; - - if (sec_freq) { - struct ieee80211_channel *schan; - - /* no 40 MHz capabilities */ + /* 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; - - schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); - - /* Secondary channel not allowed */ - if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) - goto bad_res; } result = rdev->ops->set_channel(&rdev->wiphy, chan, @@ -479,6 +549,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } + changed = 0; + + if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { + retry_short = nla_get_u8( + info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]); + if (retry_short == 0) { + result = -EINVAL; + goto bad_res; + } + changed |= WIPHY_PARAM_RETRY_SHORT; + } + + if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) { + retry_long = nla_get_u8( + info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]); + if (retry_long == 0) { + result = -EINVAL; + goto bad_res; + } + changed |= WIPHY_PARAM_RETRY_LONG; + } + + if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { + frag_threshold = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); + if (frag_threshold < 256) { + result = -EINVAL; + goto bad_res; + } + if (frag_threshold != (u32) -1) { + /* + * Fragments (apart from the last one) are required to + * have even length. Make the fragmentation code + * simpler by stripping LSB should someone try to use + * odd threshold value. + */ + frag_threshold &= ~0x1; + } + changed |= WIPHY_PARAM_FRAG_THRESHOLD; + } + + if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) { + rts_threshold = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]); + changed |= WIPHY_PARAM_RTS_THRESHOLD; + } + + if (changed) { + u8 old_retry_short, old_retry_long; + u32 old_frag_threshold, old_rts_threshold; + + if (!rdev->ops->set_wiphy_params) { + result = -EOPNOTSUPP; + goto bad_res; + } + + old_retry_short = rdev->wiphy.retry_short; + old_retry_long = rdev->wiphy.retry_long; + old_frag_threshold = rdev->wiphy.frag_threshold; + old_rts_threshold = rdev->wiphy.rts_threshold; + + if (changed & WIPHY_PARAM_RETRY_SHORT) + rdev->wiphy.retry_short = retry_short; + if (changed & WIPHY_PARAM_RETRY_LONG) + rdev->wiphy.retry_long = retry_long; + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + rdev->wiphy.frag_threshold = frag_threshold; + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + rdev->wiphy.rts_threshold = rts_threshold; + + result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); + if (result) { + rdev->wiphy.retry_short = old_retry_short; + rdev->wiphy.retry_long = old_retry_long; + rdev->wiphy.frag_threshold = old_frag_threshold; + rdev->wiphy.rts_threshold = old_rts_threshold; + } + } bad_res: mutex_unlock(&rdev->mtx); @@ -489,6 +637,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, + struct cfg80211_registered_device *rdev, struct net_device *dev) { void *hdr; @@ -498,6 +647,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, return -1; NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); + 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); return genlmsg_end(msg, hdr); @@ -532,7 +682,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * } if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - wdev->netdev) < 0) { + dev, wdev->netdev) < 0) { mutex_unlock(&dev->devlist_mtx); goto out; } @@ -562,11 +712,12 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) if (err) return err; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) goto out_err; - if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) + if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, + dev, netdev) < 0) goto out_free; dev_put(netdev); @@ -616,7 +767,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *drv; struct vif_params params; int err, ifindex; - enum nl80211_iftype type; + enum nl80211_iftype otype, ntype; struct net_device *dev; u32 _flags, *flags = NULL; bool change = false; @@ -630,30 +781,27 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) goto unlock_rtnl; ifindex = dev->ifindex; - type = dev->ieee80211_ptr->iftype; + otype = ntype = dev->ieee80211_ptr->iftype; dev_put(dev); if (info->attrs[NL80211_ATTR_IFTYPE]) { - enum nl80211_iftype ntype; - ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); - if (type != ntype) + if (otype != ntype) change = true; - type = ntype; - if (type > NL80211_IFTYPE_MAX) { + if (ntype > NL80211_IFTYPE_MAX) { err = -EINVAL; goto unlock; } } if (!drv->ops->change_virtual_intf || - !(drv->wiphy.interface_modes & (1 << type))) { + !(drv->wiphy.interface_modes & (1 << ntype))) { err = -EOPNOTSUPP; goto unlock; } if (info->attrs[NL80211_ATTR_MESH_ID]) { - if (type != NL80211_IFTYPE_MESH_POINT) { + if (ntype != NL80211_IFTYPE_MESH_POINT) { err = -EINVAL; goto unlock; } @@ -663,7 +811,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { - if (type != NL80211_IFTYPE_MONITOR) { + if (ntype != NL80211_IFTYPE_MONITOR) { err = -EINVAL; goto unlock; } @@ -678,12 +826,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) if (change) err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, - type, flags, ¶ms); + ntype, flags, ¶ms); else err = 0; dev = __dev_get_by_index(&init_net, ifindex); - WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); + WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != ntype)); + + if (dev && !err && (ntype != otype)) { + if (otype == NL80211_IFTYPE_ADHOC) + cfg80211_clear_ibss(dev, false); + } unlock: cfg80211_put_dev(drv); @@ -832,7 +985,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) goto out; } - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { err = -ENOMEM; goto out; @@ -920,6 +1073,14 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) } err = func(&drv->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; + else + dev->ieee80211_ptr->wext.default_mgmt_key = key_idx; + } +#endif out: cfg80211_put_dev(drv); @@ -934,7 +1095,7 @@ 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; + int err, i; struct net_device *dev; struct key_params params; u8 key_idx = 0; @@ -950,6 +1111,11 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 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]); @@ -958,51 +1124,23 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); - if (key_idx > 5) + if (cfg80211_validate_key_settings(¶ms, key_idx, mac_addr)) return -EINVAL; - /* - * Disallow pairwise keys with non-zero index unless it's WEP - * (because current deployments use pairwise WEP keys with - * non-zero indizes but 802.11i clearly specifies to use zero) - */ - if (mac_addr && key_idx && - params.cipher != WLAN_CIPHER_SUITE_WEP40 && - params.cipher != WLAN_CIPHER_SUITE_WEP104) - return -EINVAL; - - /* TODO: add definitions for the lengths to linux/ieee80211.h */ - switch (params.cipher) { - case WLAN_CIPHER_SUITE_WEP40: - if (params.key_len != 5) - return -EINVAL; - break; - case WLAN_CIPHER_SUITE_TKIP: - if (params.key_len != 32) - return -EINVAL; - break; - case WLAN_CIPHER_SUITE_CCMP: - if (params.key_len != 16) - return -EINVAL; - break; - case WLAN_CIPHER_SUITE_WEP104: - if (params.key_len != 13) - return -EINVAL; - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - if (params.key_len != 16) - return -EINVAL; - break; - default: - return -EINVAL; - } - rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &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; + goto out; + } + if (!drv->ops->add_key) { err = -EOPNOTSUPP; goto out; @@ -1049,6 +1187,15 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); +#ifdef CONFIG_WIRELESS_EXT + if (!err) { + 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) + dev->ieee80211_ptr->wext.default_mgmt_key = -1; + } +#endif + out: cfg80211_put_dev(drv); dev_put(dev); @@ -1069,6 +1216,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) struct beacon_parameters params; int haveinfo = 0; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -1186,15 +1336,36 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, + [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, }; -static int parse_station_flags(struct nlattr *nla, u32 *staflags) +static int parse_station_flags(struct genl_info *info, + struct station_parameters *params) { struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; + struct nlattr *nla; int flag; - *staflags = 0; + /* + * Try parsing the new attribute first so userspace + * can specify both for older kernels. + */ + nla = info->attrs[NL80211_ATTR_STA_FLAGS2]; + if (nla) { + struct nl80211_sta_flag_update *sta_flags; + sta_flags = nla_data(nla); + params->sta_flags_mask = sta_flags->mask; + params->sta_flags_set = sta_flags->set; + if ((params->sta_flags_mask | + params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) + return -EINVAL; + return 0; + } + + /* if present, parse the old attribute */ + + nla = info->attrs[NL80211_ATTR_STA_FLAGS]; if (!nla) return 0; @@ -1202,11 +1373,12 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags) nla, sta_flags_policy)) return -EINVAL; - *staflags = STATION_FLAG_CHANGED; + params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1; + params->sta_flags_mask &= ~1; for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) if (flags[flag]) - *staflags |= (1<sta_flags_set |= (1<attrs[NL80211_ATTR_HT_CAPABILITY]); - if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], - ¶ms.station_flags)) + if (parse_station_flags(info, ¶ms)) return -EINVAL; if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) @@ -1516,6 +1687,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) if (err) goto out_rtnl; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { + err = -EINVAL; + goto out; + } + err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); if (err) goto out; @@ -1567,13 +1744,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + if (!params.aid || params.aid > IEEE80211_MAX_AID) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) params.ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); - if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], - ¶ms.station_flags)) + if (parse_station_flags(info, ¶ms)) return -EINVAL; rtnl_lock(); @@ -1582,6 +1762,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (err) goto out_rtnl; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { + err = -EINVAL; + goto out; + } + err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); if (err) goto out; @@ -1625,6 +1811,12 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) if (err) goto out_rtnl; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { + err = -EINVAL; + goto out; + } + if (!drv->ops->del_station) { err = -EOPNOTSUPP; goto out; @@ -1808,7 +2000,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) if (err) goto out; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) goto out; @@ -2124,7 +2316,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, goto out; /* Draw up a netlink message to send back */ - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { err = -ENOBUFS; goto out; @@ -2302,7 +2494,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) if (!cfg80211_regdomain) goto out; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { err = -ENOBUFS; goto out; @@ -2385,18 +2577,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) rem_reg_rules) { num_rules++; if (num_rules > NL80211_MAX_SUPP_REG_RULES) - goto bad_reg; + return -EINVAL; } - if (!reg_is_valid_request(alpha2)) - return -EINVAL; + mutex_lock(&cfg80211_mutex); + + if (!reg_is_valid_request(alpha2)) { + r = -EINVAL; + goto bad_reg; + } size_of_regd = sizeof(struct ieee80211_regdomain) + (num_rules * sizeof(struct ieee80211_reg_rule)); rd = kzalloc(size_of_regd, GFP_KERNEL); - if (!rd) - return -ENOMEM; + if (!rd) { + r = -ENOMEM; + goto bad_reg; + } rd->n_reg_rules = num_rules; rd->alpha2[0] = alpha2[0]; @@ -2413,20 +2611,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) rule_idx++; - if (rule_idx > NL80211_MAX_SUPP_REG_RULES) + if (rule_idx > NL80211_MAX_SUPP_REG_RULES) { + r = -EINVAL; goto bad_reg; + } } BUG_ON(rule_idx != num_rules); - mutex_lock(&cfg80211_mutex); r = set_regdom(rd); + mutex_unlock(&cfg80211_mutex); + return r; bad_reg: + mutex_unlock(&cfg80211_mutex); kfree(rd); - return -EINVAL; + return r; } static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) @@ -2442,6 +2644,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) enum ieee80211_band band; size_t ie_len; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2492,6 +2697,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) else ie_len = 0; + if (ie_len > wiphy->max_scan_ie_len) { + err = -EINVAL; + goto out; + } + request = kzalloc(sizeof(*request) + sizeof(*ssid) * n_ssids + sizeof(channel) * n_channels @@ -2554,7 +2764,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_IE]) { request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); - memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]), + memcpy((void *)request->ie, + nla_data(info->attrs[NL80211_ATTR_IE]), request->ie_len); } @@ -2710,6 +2921,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_AUTH_TYPE]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2731,11 +2951,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC]) { - err = -EINVAL; - goto out; - } - wiphy = &drv->wiphy; memset(&req, 0, sizeof(req)); @@ -2761,13 +2976,10 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } - if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { - req.auth_type = - nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); - if (!nl80211_valid_auth_type(req.auth_type)) { - err = -EINVAL; - goto out; - } + req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); + if (!nl80211_valid_auth_type(req.auth_type)) { + err = -EINVAL; + goto out; } err = drv->ops->auth(&drv->wiphy, dev, &req); @@ -2788,6 +3000,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC] || + !info->attrs[NL80211_ATTR_SSID]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2809,12 +3028,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC] || - !info->attrs[NL80211_ATTR_SSID]) { - err = -EINVAL; - goto out; - } - wiphy = &drv->wiphy; memset(&req, 0, sizeof(req)); @@ -2838,6 +3051,19 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } + if (info->attrs[NL80211_ATTR_USE_MFP]) { + enum nl80211_mfp use_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) { + err = -EINVAL; + goto out; + } + } + + req.control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; + err = drv->ops->assoc(&drv->wiphy, dev, &req); out: @@ -2856,6 +3082,15 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_REASON_CODE]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2877,24 +3112,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC]) { - err = -EINVAL; - 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_REASON_CODE]) { - req.reason_code = - nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); - if (req.reason_code == 0) { - /* Reason Code 0 is reserved */ - err = -EINVAL; - goto out; - } + req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + if (req.reason_code == 0) { + /* Reason Code 0 is reserved */ + err = -EINVAL; + goto out; } if (info->attrs[NL80211_ATTR_IE]) { @@ -2920,6 +3147,15 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_REASON_CODE]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2941,24 +3177,16 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC]) { - err = -EINVAL; - 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_REASON_CODE]) { - req.reason_code = - nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); - if (req.reason_code == 0) { - /* Reason Code 0 is reserved */ - err = -EINVAL; - goto out; - } + req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + if (req.reason_code == 0) { + /* Reason Code 0 is reserved */ + err = -EINVAL; + goto out; } if (info->attrs[NL80211_ATTR_IE]) { @@ -2976,6 +3204,124 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) return err; } +static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + struct cfg80211_ibss_params ibss; + struct wiphy *wiphy; + int err; + + memset(&ibss, 0, sizeof(ibss)); + + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || + !info->attrs[NL80211_ATTR_SSID] || + !nla_len(info->attrs[NL80211_ATTR_SSID])) + return -EINVAL; + + ibss.beacon_interval = 100; + + if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { + ibss.beacon_interval = + nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); + if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000) + return -EINVAL; + } + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->join_ibss) { + err = -EOPNOTSUPP; + goto out; + } + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + wiphy = &drv->wiphy; + + if (info->attrs[NL80211_ATTR_MAC]) + ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); + ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); + ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + + if (info->attrs[NL80211_ATTR_IE]) { + ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + ibss.channel = ieee80211_get_channel(wiphy, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); + if (!ibss.channel || + ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || + ibss.channel->flags & IEEE80211_CHAN_DISABLED) { + err = -EINVAL; + goto out; + } + + ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; + + err = cfg80211_join_ibss(drv, dev, &ibss); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + int err; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->leave_ibss) { + err = -EOPNOTSUPP; + goto out; + } + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + err = cfg80211_leave_ibss(drv, dev, false); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -3177,6 +3523,18 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_JOIN_IBSS, + .doit = nl80211_join_ibss, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_LEAVE_IBSS, + .doit = nl80211_leave_ibss, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { .name = "mlme", @@ -3199,7 +3557,7 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) { struct sk_buff *msg; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return; @@ -3211,11 +3569,43 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); } +static int nl80211_add_scan_req(struct sk_buff *msg, + struct cfg80211_registered_device *rdev) +{ + struct cfg80211_scan_request *req = rdev->scan_req; + struct nlattr *nest; + int i; + + if (WARN_ON(!req)) + return 0; + + nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); + if (!nest) + goto nla_put_failure; + for (i = 0; i < req->n_ssids; i++) + NLA_PUT(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid); + nla_nest_end(msg, nest); + + nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); + if (!nest) + goto nla_put_failure; + for (i = 0; i < req->n_channels; i++) + NLA_PUT_U32(msg, i, req->channels[i]->center_freq); + nla_nest_end(msg, nest); + + if (req->ie) + NLA_PUT(msg, NL80211_ATTR_IE, req->ie_len, req->ie); + + return 0; + nla_put_failure: + 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) + struct cfg80211_registered_device *rdev, + struct net_device *netdev, + u32 pid, u32 seq, int flags, + u32 cmd) { void *hdr; @@ -3226,7 +3616,8 @@ static int nl80211_send_scan_donemsg(struct sk_buff *msg, NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - /* XXX: we should probably bounce back the request? */ + /* ignore errors and send incomplete event anyway */ + nl80211_add_scan_req(msg, rdev); return genlmsg_end(msg, hdr); @@ -3240,7 +3631,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, { struct sk_buff *msg; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return; @@ -3258,7 +3649,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, { struct sk_buff *msg; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return; @@ -3280,7 +3671,7 @@ void nl80211_send_reg_change_event(struct regulatory_request *request) struct sk_buff *msg; void *hdr; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return; @@ -3334,7 +3725,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, struct sk_buff *msg; void *hdr; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!msg) return; @@ -3375,38 +3766,208 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE); } -void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *buf, - size_t len) +void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, size_t len) { nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_DEAUTHENTICATE); } -void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *buf, - size_t len) +void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len) { nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_DISASSOCIATE); } +static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, int cmd, + const u8 *addr) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); + 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_FLAG(msg, NL80211_ATTR_TIMED_OUT); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *addr) +{ + nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE, + addr); +} + +void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *addr) +{ + nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr); +} + +void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *bssid, + gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS); + 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 (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +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) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE); + 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 (addr) + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); + NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); + if (tsc) + NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +void nl80211_send_beacon_hint_event(struct wiphy *wiphy, + struct ieee80211_channel *channel_before, + struct ieee80211_channel *channel_after) +{ + struct sk_buff *msg; + void *hdr; + struct nlattr *nl_freq; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT); + if (!hdr) { + nlmsg_free(msg); + return; + } + + /* + * Since we are applying the beacon hint to a wiphy we know its + * wiphy_idx is valid + */ + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)); + + /* Before */ + nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); + if (!nl_freq) + goto nla_put_failure; + if (nl80211_msg_put_channel(msg, channel_before)) + goto nla_put_failure; + nla_nest_end(msg, nl_freq); + + /* After */ + nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); + if (!nl_freq) + goto nla_put_failure; + if (nl80211_msg_put_channel(msg, channel_after)) + goto nla_put_failure; + nla_nest_end(msg, nl_freq); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC); + + return; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + /* initialisation/exit functions */ int nl80211_init(void) { - int err, i; + int err; - err = genl_register_family(&nl80211_fam); + err = genl_register_family_with_ops(&nl80211_fam, + nl80211_ops, ARRAY_SIZE(nl80211_ops)); if (err) return err; - for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) { - err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]); - if (err) - goto err_out; - } - err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); if (err) goto err_out; diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b77af4ab80be..5c12ad13499b 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -17,11 +17,31 @@ extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, 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_rx_deauth(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - const u8 *buf, size_t len); -extern void nl80211_send_rx_disassoc(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, + 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 +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); + +extern void +nl80211_send_beacon_hint_event(struct wiphy *wiphy, + struct ieee80211_channel *channel_before, + struct ieee80211_channel *channel_after); + +void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *bssid, + gfp_t gfp); #endif /* __NET_WIRELESS_NL80211_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 487cb627ddba..5e14371cda70 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include "core.h" #include "reg.h" @@ -49,12 +48,6 @@ static struct regulatory_request *last_request; /* To trigger userspace events */ static struct platform_device *reg_pdev; -/* Keep the ordering from large to small */ -static u32 supported_bandwidths[] = { - MHZ_TO_KHZ(40), - MHZ_TO_KHZ(20), -}; - /* * Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no @@ -389,6 +382,8 @@ static int call_crda(const char *alpha2) /* Used by nl80211 before kmalloc'ing our regulatory domain */ bool reg_is_valid_request(const char *alpha2) { + assert_cfg80211_lock(); + if (!last_request) return false; @@ -436,19 +431,20 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd) return true; } -/* Returns value in KHz */ -static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, - u32 freq) +static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, + u32 center_freq_khz, + u32 bw_khz) { - unsigned int i; - for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { - u32 start_freq_khz = freq - supported_bandwidths[i]/2; - u32 end_freq_khz = freq + supported_bandwidths[i]/2; - if (start_freq_khz >= freq_range->start_freq_khz && - end_freq_khz <= freq_range->end_freq_khz) - return supported_bandwidths[i]; - } - return 0; + u32 start_freq_khz, end_freq_khz; + + start_freq_khz = center_freq_khz - (bw_khz/2); + end_freq_khz = center_freq_khz + (bw_khz/2); + + if (start_freq_khz >= freq_range->start_freq_khz && + end_freq_khz <= freq_range->end_freq_khz) + return true; + + return false; } /** @@ -848,14 +844,17 @@ static u32 map_regdom_flags(u32 rd_flags) static int freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, - u32 *bandwidth, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule, const struct ieee80211_regdomain *custom_regd) { int i; bool band_rule_found = false; const struct ieee80211_regdomain *regd; - u32 max_bandwidth = 0; + bool bw_fits = false; + + if (!desired_bw_khz) + desired_bw_khz = MHZ_TO_KHZ(20); regd = custom_regd ? custom_regd : cfg80211_regdomain; @@ -888,38 +887,54 @@ static int freq_reg_info_regd(struct wiphy *wiphy, if (!band_rule_found) band_rule_found = freq_in_rule_band(fr, center_freq); - max_bandwidth = freq_max_bandwidth(fr, center_freq); + bw_fits = reg_does_bw_fit(fr, + center_freq, + desired_bw_khz); - if (max_bandwidth && *bandwidth <= max_bandwidth) { + if (band_rule_found && bw_fits) { *reg_rule = rr; - *bandwidth = max_bandwidth; - break; + return 0; } } if (!band_rule_found) return -ERANGE; - return !max_bandwidth; + return -EINVAL; } EXPORT_SYMBOL(freq_reg_info); -int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule) +int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, + const struct ieee80211_reg_rule **reg_rule) { assert_cfg80211_lock(); - return freq_reg_info_regd(wiphy, center_freq, - bandwidth, reg_rule, NULL); + return freq_reg_info_regd(wiphy, + center_freq, + desired_bw_khz, + reg_rule, + NULL); } +/* + * Note that right now we assume the desired channel bandwidth + * is always 20 MHz for each individual channel (HT40 uses 20 MHz + * per channel, the primary and the extension channel). To support + * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a + * new ieee80211_channel.target_bw and re run the regulatory check + * on the wiphy with the target_bw specified. Then we can simply use + * that below for the desired_bw_khz below. + */ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx) { int r; - u32 flags; - u32 max_bandwidth = 0; + u32 flags, bw_flags = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; struct wiphy *request_wiphy = NULL; @@ -934,8 +949,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, flags = chan->orig_flags; - r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule); + r = freq_reg_info(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule); if (r) { /* @@ -978,6 +995,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && @@ -988,19 +1009,19 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, * settings */ chan->flags = chan->orig_flags = - map_regdom_flags(reg_rule->flags); + 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(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = chan->orig_mpwr = (int) MBM_TO_DBM(power_rule->max_eirp); return; } - chan->flags = flags | map_regdom_flags(reg_rule->flags); + 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(max_bandwidth); + 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)); @@ -1050,18 +1071,10 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, struct reg_beacon *reg_beacon) { -#ifdef CONFIG_CFG80211_REG_DEBUG -#define REG_DEBUG_BEACON_FLAG(desc) \ - printk(KERN_DEBUG "cfg80211: Enabling " desc " on " \ - "frequency: %d MHz (Ch %d) on %s\n", \ - reg_beacon->chan.center_freq, \ - ieee80211_frequency_to_channel(reg_beacon->chan.center_freq), \ - wiphy_name(wiphy)); -#else -#define REG_DEBUG_BEACON_FLAG(desc) do {} while (0) -#endif struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; + bool channel_changed = false; + struct ieee80211_channel chan_before; assert_cfg80211_lock(); @@ -1071,18 +1084,28 @@ static void handle_reg_beacon(struct wiphy *wiphy, if (likely(chan->center_freq != reg_beacon->chan.center_freq)) return; - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { - chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - REG_DEBUG_BEACON_FLAG("active scanning"); - } - - if (chan->flags & IEEE80211_CHAN_NO_IBSS) { - chan->flags &= ~IEEE80211_CHAN_NO_IBSS; - REG_DEBUG_BEACON_FLAG("beaconing"); - } + if (chan->beacon_found) + return; chan->beacon_found = true; -#undef REG_DEBUG_BEACON_FLAG + + chan_before.center_freq = chan->center_freq; + chan_before.flags = chan->flags; + + if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) { + chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + channel_changed = true; + } + + if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && + !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) { + chan->flags &= ~IEEE80211_CHAN_NO_IBSS; + channel_changed = true; + } + + if (channel_changed) + nl80211_send_beacon_hint_event(wiphy, &chan_before, chan); } /* @@ -1155,6 +1178,93 @@ static void reg_process_beacons(struct wiphy *wiphy) wiphy_update_beacon_reg(wiphy); } +static bool is_ht40_not_allowed(struct ieee80211_channel *chan) +{ + if (!chan) + return true; + if (chan->flags & IEEE80211_CHAN_DISABLED) + return true; + /* This would happen when regulatory rules disallow HT40 completely */ + if (IEEE80211_CHAN_NO_HT40 == (chan->flags & (IEEE80211_CHAN_NO_HT40))) + return true; + return false; +} + +static void reg_process_ht_flags_channel(struct wiphy *wiphy, + enum ieee80211_band band, + unsigned int chan_idx) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *channel; + struct ieee80211_channel *channel_before = NULL, *channel_after = NULL; + unsigned int i; + + assert_cfg80211_lock(); + + sband = wiphy->bands[band]; + BUG_ON(chan_idx >= sband->n_channels); + channel = &sband->channels[chan_idx]; + + if (is_ht40_not_allowed(channel)) { + channel->flags |= IEEE80211_CHAN_NO_HT40; + return; + } + + /* + * We need to ensure the extension channels exist to + * be able to use HT40- or HT40+, this finds them (or not) + */ + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *c = &sband->channels[i]; + if (c->center_freq == (channel->center_freq - 20)) + channel_before = c; + if (c->center_freq == (channel->center_freq + 20)) + channel_after = c; + } + + /* + * Please note that this assumes target bandwidth is 20 MHz, + * if that ever changes we also need to change the below logic + * to include that as well. + */ + if (is_ht40_not_allowed(channel_before)) + channel->flags |= IEEE80211_CHAN_NO_HT40MINUS; + else + channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; + + if (is_ht40_not_allowed(channel_after)) + channel->flags |= IEEE80211_CHAN_NO_HT40PLUS; + else + channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; +} + +static void reg_process_ht_flags_band(struct wiphy *wiphy, + enum ieee80211_band band) +{ + unsigned int i; + struct ieee80211_supported_band *sband; + + BUG_ON(!wiphy->bands[band]); + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) + reg_process_ht_flags_channel(wiphy, band, i); +} + +static void reg_process_ht_flags(struct wiphy *wiphy) +{ + enum ieee80211_band band; + + if (!wiphy) + return; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (wiphy->bands[band]) + reg_process_ht_flags_band(wiphy, band); + } + +} + void wiphy_update_regulatory(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { @@ -1168,6 +1278,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, } out: reg_process_beacons(wiphy); + reg_process_ht_flags(wiphy); if (wiphy->reg_notifier) wiphy->reg_notifier(wiphy, last_request); } @@ -1178,9 +1289,11 @@ static void handle_channel_custom(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { int r; - u32 max_bandwidth = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); + u32 bw_flags = 0; const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; @@ -1190,8 +1303,11 @@ static void handle_channel_custom(struct wiphy *wiphy, BUG_ON(chan_idx >= sband->n_channels); chan = &sband->channels[chan_idx]; - r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule, regd); + r = freq_reg_info_regd(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule, + regd); if (r) { chan->flags = IEEE80211_CHAN_DISABLED; @@ -1199,10 +1315,14 @@ static void handle_channel_custom(struct wiphy *wiphy, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; - chan->flags |= map_regdom_flags(reg_rule->flags); + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; + + 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(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); } @@ -1224,13 +1344,22 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { enum ieee80211_band band; + unsigned int bands_set = 0; mutex_lock(&cfg80211_mutex); for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (wiphy->bands[band]) - handle_band_custom(wiphy, band, regd); + if (!wiphy->bands[band]) + continue; + handle_band_custom(wiphy, band, regd); + bands_set++; } mutex_unlock(&cfg80211_mutex); + + /* + * no point in calling this if it won't have any effect + * on your device's supportd bands. + */ + WARN_ON(!bands_set); } EXPORT_SYMBOL(wiphy_apply_custom_regulatory); @@ -2000,7 +2129,12 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * driver wanted to the wiphy to deal with conflicts */ - BUG_ON(request_wiphy->regd); + /* + * Userspace could have sent two replies with only + * one kernel request. + */ + if (request_wiphy->regd) + return -EALREADY; r = reg_copy_regd(&request_wiphy->regd, rd); if (r) @@ -2042,7 +2176,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * the country IE rd with what CRDA believes that country should have */ - BUG_ON(!country_ie_regdomain); + /* + * Userspace could have sent two replies with only + * one kernel request. By the second reply we would have + * already processed and consumed the country_ie_regdomain. + */ + if (!country_ie_regdomain) + return -EALREADY; BUG_ON(rd == country_ie_regdomain); /* @@ -2119,14 +2259,14 @@ void reg_device_remove(struct wiphy *wiphy) assert_cfg80211_lock(); + kfree(wiphy->regd); + if (last_request) request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); - kfree(wiphy->regd); - if (!last_request || !request_wiphy) - return; - if (request_wiphy != wiphy) + if (!request_wiphy || request_wiphy != wiphy) return; + last_request->wiphy_idx = WIPHY_IDX_STALE; last_request->country_ie_env = ENVIRON_ANY; } diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 1f260c40b6ca..e95b638b919f 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -29,13 +29,14 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) goto out; WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); - wiphy_to_dev(request->wiphy)->scan_req = NULL; if (aborted) nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); else nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); + wiphy_to_dev(request->wiphy)->scan_req = NULL; + #ifdef CONFIG_WIRELESS_EXT if (!aborted) { memset(&wrqu, 0, sizeof(wrqu)); @@ -377,18 +378,16 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, size_t used = dev->wiphy.bss_priv_size + sizeof(*res); size_t ielen = res->pub.len_information_elements; - if (ksize(found) >= used + ielen) { + if (!found->ies_allocated && ksize(found) >= used + ielen) { memcpy(found->pub.information_elements, res->pub.information_elements, ielen); found->pub.len_information_elements = ielen; } else { u8 *ies = found->pub.information_elements; - if (found->ies_allocated) { - if (ksize(ies) < ielen) - ies = krealloc(ies, ielen, - GFP_ATOMIC); - } else + if (found->ies_allocated) + ies = krealloc(ies, ielen, GFP_ATOMIC); + else ies = kmalloc(ielen, GFP_ATOMIC); if (ies) { @@ -415,6 +414,55 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, return found; } +struct cfg80211_bss* +cfg80211_inform_bss(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *bssid, + u64 timestamp, u16 capability, u16 beacon_interval, + const u8 *ie, size_t ielen, + s32 signal, gfp_t gfp) +{ + struct cfg80211_internal_bss *res; + size_t privsz; + + if (WARN_ON(!wiphy)) + return NULL; + + privsz = wiphy->bss_priv_size; + + if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && + (signal < 0 || signal > 100))) + return NULL; + + res = kzalloc(sizeof(*res) + privsz + ielen, gfp); + if (!res) + return NULL; + + memcpy(res->pub.bssid, bssid, ETH_ALEN); + res->pub.channel = channel; + res->pub.signal = signal; + res->pub.tsf = timestamp; + res->pub.beacon_interval = beacon_interval; + res->pub.capability = capability; + /* point to after the private area */ + res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; + memcpy(res->pub.information_elements, ie, ielen); + res->pub.len_information_elements = ielen; + + kref_init(&res->ref); + + res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0); + if (!res) + return NULL; + + if (res->pub.capability & WLAN_CAPABILITY_ESS) + regulatory_hint_found_beacon(wiphy, channel, gfp); + + /* cfg80211_bss_update gives us a referenced result */ + return &res->pub; +} +EXPORT_SYMBOL(cfg80211_inform_bss); + struct cfg80211_bss * cfg80211_inform_bss_frame(struct wiphy *wiphy, struct ieee80211_channel *channel, @@ -605,7 +653,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, cfg80211_put_dev(rdev); return err; } -EXPORT_SYMBOL(cfg80211_wext_siwscan); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); static void ieee80211_scan_add_ies(struct iw_request_info *info, struct cfg80211_bss *bss, @@ -914,5 +962,5 @@ int cfg80211_wext_giwscan(struct net_device *dev, cfg80211_put_dev(rdev); return res; } -EXPORT_SYMBOL(cfg80211_wext_giwscan); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); #endif diff --git a/net/wireless/util.c b/net/wireless/util.c index 487cdd9bcffc..25550692dda6 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1,10 +1,12 @@ /* * Wireless utility functions * - * Copyright 2007 Johannes Berg + * Copyright 2007-2009 Johannes Berg */ -#include -#include +#include +#include +#include +#include #include "core.h" struct ieee80211_rate * @@ -138,3 +140,365 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) if (wiphy->bands[band]) set_mandatory_flags_band(wiphy->bands[band], band); } + +int cfg80211_validate_key_settings(struct key_params *params, int key_idx, + const u8 *mac_addr) +{ + if (key_idx > 5) + return -EINVAL; + + /* + * Disallow pairwise keys with non-zero index unless it's WEP + * (because current deployments use pairwise WEP keys with + * non-zero indizes but 802.11i clearly specifies to use zero) + */ + if (mac_addr && key_idx && + params->cipher != WLAN_CIPHER_SUITE_WEP40 && + params->cipher != WLAN_CIPHER_SUITE_WEP104) + return -EINVAL; + + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + if (params->key_len != WLAN_KEY_LEN_WEP40) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_TKIP: + if (params->key_len != WLAN_KEY_LEN_TKIP) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_CCMP: + if (params->key_len != WLAN_KEY_LEN_CCMP) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_WEP104: + if (params->key_len != WLAN_KEY_LEN_WEP104) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + if (params->key_len != WLAN_KEY_LEN_AES_CMAC) + return -EINVAL; + break; + default: + return -EINVAL; + } + + if (params->seq) { + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + /* These ciphers do not use key sequence */ + return -EINVAL; + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_AES_CMAC: + if (params->seq_len != 6) + return -EINVAL; + break; + } + } + + return 0; +} + +/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ +/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ +const unsigned char rfc1042_header[] __aligned(2) = + { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +EXPORT_SYMBOL(rfc1042_header); + +/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ +const unsigned char bridge_tunnel_header[] __aligned(2) = + { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +EXPORT_SYMBOL(bridge_tunnel_header); + +unsigned int ieee80211_hdrlen(__le16 fc) +{ + unsigned int hdrlen = 24; + + if (ieee80211_is_data(fc)) { + if (ieee80211_has_a4(fc)) + hdrlen = 30; + if (ieee80211_is_data_qos(fc)) + hdrlen += IEEE80211_QOS_CTL_LEN; + goto out; + } + + if (ieee80211_is_ctl(fc)) { + /* + * ACK and CTS are 10 bytes, all others 16. To see how + * to get this condition consider + * subtype mask: 0b0000000011110000 (0x00F0) + * ACK subtype: 0b0000000011010000 (0x00D0) + * CTS subtype: 0b0000000011000000 (0x00C0) + * bits that matter: ^^^ (0x00E0) + * value of those: 0b0000000011000000 (0x00C0) + */ + if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) + hdrlen = 10; + else + hdrlen = 16; + } +out: + return hdrlen; +} +EXPORT_SYMBOL(ieee80211_hdrlen); + +unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) +{ + const struct ieee80211_hdr *hdr = + (const struct ieee80211_hdr *)skb->data; + unsigned int hdrlen; + + if (unlikely(skb->len < 10)) + return 0; + hdrlen = ieee80211_hdrlen(hdr->frame_control); + if (unlikely(hdrlen > skb->len)) + return 0; + return hdrlen; +} +EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); + +static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +{ + int ae = meshhdr->flags & MESH_FLAGS_AE; + /* 7.1.3.5a.2 */ + switch (ae) { + case 0: + return 6; + case 1: + return 12; + case 2: + return 18; + case 3: + return 24; + default: + return 6; + } +} + +int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, + enum nl80211_iftype iftype) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u16 hdrlen, ethertype; + u8 *payload; + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN] __aligned(2); + + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) + return -1; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + /* convert IEEE 802.11 header + possible LLC headers into Ethernet + * header + * IEEE 802.11 address fields: + * ToDS FromDS Addr1 Addr2 Addr3 Addr4 + * 0 0 DA SA BSSID n/a + * 0 1 DA BSSID SA n/a + * 1 0 BSSID SA DA n/a + * 1 1 RA TA DA SA + */ + memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); + memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); + + switch (hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { + case cpu_to_le16(IEEE80211_FCTL_TODS): + if (unlikely(iftype != NL80211_IFTYPE_AP && + iftype != NL80211_IFTYPE_AP_VLAN)) + return -1; + break; + case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): + if (unlikely(iftype != NL80211_IFTYPE_WDS && + iftype != NL80211_IFTYPE_MESH_POINT)) + 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_A5_A6) { + memcpy(dst, meshdr->eaddr1, ETH_ALEN); + memcpy(src, meshdr->eaddr2, ETH_ALEN); + } + } + break; + case cpu_to_le16(IEEE80211_FCTL_FROMDS): + if (iftype != NL80211_IFTYPE_STATION || + (is_multicast_ether_addr(dst) && + !compare_ether_addr(src, addr))) + return -1; + break; + case cpu_to_le16(0): + if (iftype != NL80211_IFTYPE_ADHOC) + return -1; + break; + } + + if (unlikely(skb->len - hdrlen < 8)) + return -1; + + payload = skb->data + hdrlen; + ethertype = (payload[6] << 8) | payload[7]; + + if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + compare_ether_addr(payload, bridge_tunnel_header) == 0)) { + /* remove RFC1042 or Bridge-Tunnel encapsulation and + * replace EtherType */ + skb_pull(skb, hdrlen + 6); + memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); + } else { + struct ethhdr *ehdr; + __be16 len; + + skb_pull(skb, hdrlen); + len = htons(skb->len); + ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); + memcpy(ehdr->h_dest, dst, ETH_ALEN); + memcpy(ehdr->h_source, src, ETH_ALEN); + ehdr->h_proto = len; + } + return 0; +} +EXPORT_SYMBOL(ieee80211_data_to_8023); + +int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, + enum nl80211_iftype iftype, u8 *bssid, bool qos) +{ + struct ieee80211_hdr hdr; + u16 hdrlen, ethertype; + __le16 fc; + const u8 *encaps_data; + int encaps_len, skip_header_bytes; + int nh_pos, h_pos; + int head_need; + + if (unlikely(skb->len < ETH_HLEN)) + return -EINVAL; + + nh_pos = skb_network_header(skb) - skb->data; + h_pos = skb_transport_header(skb) - skb->data; + + /* convert Ethernet header to proper 802.11 header (based on + * operation mode) */ + ethertype = (skb->data[12] << 8) | skb->data[13]; + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); + + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); + /* DA BSSID SA */ + memcpy(hdr.addr1, skb->data, ETH_ALEN); + memcpy(hdr.addr2, addr, ETH_ALEN); + memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); + hdrlen = 24; + break; + case NL80211_IFTYPE_STATION: + fc |= cpu_to_le16(IEEE80211_FCTL_TODS); + /* BSSID SA DA */ + memcpy(hdr.addr1, bssid, ETH_ALEN); + memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); + memcpy(hdr.addr3, skb->data, ETH_ALEN); + hdrlen = 24; + break; + case NL80211_IFTYPE_ADHOC: + /* DA SA BSSID */ + memcpy(hdr.addr1, skb->data, ETH_ALEN); + memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); + memcpy(hdr.addr3, bssid, ETH_ALEN); + hdrlen = 24; + break; + default: + return -EOPNOTSUPP; + } + + if (qos) { + fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); + hdrlen += 2; + } + + hdr.frame_control = fc; + hdr.duration_id = 0; + hdr.seq_ctrl = 0; + + skip_header_bytes = ETH_HLEN; + if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { + encaps_data = bridge_tunnel_header; + encaps_len = sizeof(bridge_tunnel_header); + skip_header_bytes -= 2; + } else if (ethertype > 0x600) { + encaps_data = rfc1042_header; + encaps_len = sizeof(rfc1042_header); + skip_header_bytes -= 2; + } else { + encaps_data = NULL; + encaps_len = 0; + } + + skb_pull(skb, skip_header_bytes); + nh_pos -= skip_header_bytes; + h_pos -= skip_header_bytes; + + head_need = hdrlen + encaps_len - skb_headroom(skb); + + if (head_need > 0 || skb_cloned(skb)) { + head_need = max(head_need, 0); + if (head_need) + skb_orphan(skb); + + if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) { + printk(KERN_ERR "failed to reallocate Tx buffer\n"); + return -ENOMEM; + } + skb->truesize += head_need; + } + + if (encaps_data) { + memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); + nh_pos += encaps_len; + h_pos += encaps_len; + } + + memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); + + nh_pos += hdrlen; + h_pos += hdrlen; + + /* Update skb pointers to various headers since this modified frame + * is going to go through Linux networking code that may potentially + * need things like pointer to IP header. */ + skb_set_mac_header(skb, 0); + skb_set_network_header(skb, nh_pos); + skb_set_transport_header(skb, h_pos); + + return 0; +} +EXPORT_SYMBOL(ieee80211_data_from_8023); + +/* Given a data frame determine the 802.1p/1d tag to use. */ +unsigned int cfg80211_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp; + + /* skb->priority values from 256->263 are magic values to + * directly indicate a specific 802.1d priority. This is used + * to allow 802.1d priority to be passed directly in from VLAN + * tags, etc. + */ + if (skb->priority >= 256 && skb->priority <= 263) + return skb->priority - 256; + + switch (skb->protocol) { + case htons(ETH_P_IP): + dscp = ip_hdr(skb)->tos & 0xfc; + break; + default: + return 0; + } + + return dscp >> 5; +} +EXPORT_SYMBOL(cfg80211_classify8021d); diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 0fd1db6e95bb..d030c5315672 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -5,13 +5,14 @@ * into cfg80211, when that happens all the exports here go away and * we directly assign the wireless handlers of wireless interfaces. * - * Copyright 2008 Johannes Berg + * Copyright 2008-2009 Johannes Berg */ #include #include +#include +#include #include -#include #include #include "core.h" @@ -57,7 +58,7 @@ int cfg80211_wext_giwname(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwname); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwname); int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, u32 *mode, char *extra) @@ -108,7 +109,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, return ret; } -EXPORT_SYMBOL(cfg80211_wext_siwmode); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, u32 *mode, char *extra) @@ -143,7 +144,7 @@ int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, } return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwmode); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode); int cfg80211_wext_giwrange(struct net_device *dev, @@ -206,7 +207,6 @@ int cfg80211_wext_giwrange(struct net_device *dev, range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { int i; struct ieee80211_supported_band *sband; @@ -240,4 +240,590 @@ int cfg80211_wext_giwrange(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwrange); +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! + */ +struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, + struct iw_freq *freq) +{ + struct ieee80211_channel *chan; + int f; + + /* + * Parse frequency - return NULL for auto and + * -EINVAL for impossible things. + */ + if (freq->e == 0) { + if (freq->m < 0) + return NULL; + f = 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; + } + + /* + * 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, + struct iw_param *rts, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + u32 orts = wdev->wiphy->rts_threshold; + int err; + + if (rts->disabled || !rts->fixed) + wdev->wiphy->rts_threshold = (u32) -1; + else if (rts->value < 0) + return -EINVAL; + else + wdev->wiphy->rts_threshold = rts->value; + + err = rdev->ops->set_wiphy_params(wdev->wiphy, + WIPHY_PARAM_RTS_THRESHOLD); + if (err) + wdev->wiphy->rts_threshold = orts; + + return err; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts); + +int cfg80211_wext_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + rts->value = wdev->wiphy->rts_threshold; + rts->disabled = rts->value == (u32) -1; + rts->fixed = 1; + + return 0; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts); + +int cfg80211_wext_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + u32 ofrag = wdev->wiphy->frag_threshold; + int err; + + if (frag->disabled || !frag->fixed) + wdev->wiphy->frag_threshold = (u32) -1; + else if (frag->value < 256) + return -EINVAL; + else { + /* Fragment length must be even, so strip LSB. */ + wdev->wiphy->frag_threshold = frag->value & ~0x1; + } + + err = rdev->ops->set_wiphy_params(wdev->wiphy, + WIPHY_PARAM_FRAG_THRESHOLD); + if (err) + wdev->wiphy->frag_threshold = ofrag; + + return err; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag); + +int cfg80211_wext_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + frag->value = wdev->wiphy->frag_threshold; + frag->disabled = frag->value == (u32) -1; + frag->fixed = 1; + + return 0; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag); + +int cfg80211_wext_siwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + u32 changed = 0; + u8 olong = wdev->wiphy->retry_long; + u8 oshort = wdev->wiphy->retry_short; + int err; + + if (retry->disabled || + (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) + return -EINVAL; + + if (retry->flags & IW_RETRY_LONG) { + wdev->wiphy->retry_long = retry->value; + changed |= WIPHY_PARAM_RETRY_LONG; + } else if (retry->flags & IW_RETRY_SHORT) { + wdev->wiphy->retry_short = retry->value; + changed |= WIPHY_PARAM_RETRY_SHORT; + } else { + wdev->wiphy->retry_short = retry->value; + wdev->wiphy->retry_long = retry->value; + changed |= WIPHY_PARAM_RETRY_LONG; + changed |= WIPHY_PARAM_RETRY_SHORT; + } + + if (!changed) + return 0; + + err = rdev->ops->set_wiphy_params(wdev->wiphy, changed); + if (err) { + wdev->wiphy->retry_short = oshort; + wdev->wiphy->retry_long = olong; + } + + return err; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry); + +int cfg80211_wext_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + retry->disabled = 0; + + if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) { + /* + * First return short value, iwconfig will ask long value + * later if needed + */ + retry->flags |= IW_RETRY_LIMIT; + retry->value = wdev->wiphy->retry_short; + if (wdev->wiphy->retry_long != wdev->wiphy->retry_short) + retry->flags |= IW_RETRY_LONG; + + return 0; + } + + if (retry->flags & IW_RETRY_LONG) { + retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; + retry->value = wdev->wiphy->retry_long; + } + + return 0; +} +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) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; + + if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + if (!rdev->ops->set_default_mgmt_key) + return -EOPNOTSUPP; + + if (idx < 4 || idx > 5) + return -EINVAL; + } else if (idx < 0 || idx > 3) + return -EINVAL; + + if (remove) { + err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); + if (!err) { + if (idx == wdev->wext.default_key) + wdev->wext.default_key = -1; + else if (idx == wdev->wext.default_mgmt_key) + wdev->wext.default_mgmt_key = -1; + } + /* + * Applications using wireless extensions expect to be + * able to delete keys that don't exist, so allow that. + */ + if (err == -ENOENT) + return 0; + + return err; + } else { + if (addr) + tx_key = false; + + if (cfg80211_validate_key_settings(params, idx, addr)) + return -EINVAL; + + err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); + if (err) + return err; + + if (tx_key || (!addr && wdev->wext.default_key == -1)) { + err = rdev->ops->set_default_key(&rdev->wiphy, + dev, idx); + 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))) { + err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, + dev, idx); + if (!err) + wdev->wext.default_mgmt_key = idx; + return err; + } + + return 0; + } +} + +int cfg80211_wext_siwencode(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; + bool remove = false; + struct key_params params; + + /* no use -- only MFP (set_default_mgmt_key) is optional */ + if (!rdev->ops->del_key || + !rdev->ops->add_key || + !rdev->ops->set_default_key) + return -EOPNOTSUPP; + + idx = erq->flags & IW_ENCODE_INDEX; + if (idx == 0) { + idx = wdev->wext.default_key; + if (idx < 0) + idx = 0; + } else if (idx < 1 || idx > 4) + return -EINVAL; + else + idx--; + + if (erq->flags & IW_ENCODE_DISABLED) + 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); + if (!err) + wdev->wext.default_key = idx; + return err; + } + + memset(¶ms, 0, sizeof(params)); + params.key = keybuf; + params.key_len = erq->length; + if (erq->length == 5) + params.cipher = WLAN_CIPHER_SUITE_WEP40; + else if (erq->length == 13) + params.cipher = WLAN_CIPHER_SUITE_WEP104; + else if (!remove) + return -EINVAL; + + return cfg80211_set_encryption(rdev, dev, NULL, remove, + wdev->wext.default_key == -1, + idx, ¶ms); +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwencode); + +int cfg80211_wext_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; + const u8 *addr; + int idx; + bool remove = false; + struct key_params params; + u32 cipher; + + /* no use -- only MFP (set_default_mgmt_key) is optional */ + if (!rdev->ops->del_key || + !rdev->ops->add_key || + !rdev->ops->set_default_key) + return -EOPNOTSUPP; + + switch (ext->alg) { + case IW_ENCODE_ALG_NONE: + remove = true; + cipher = 0; + break; + case IW_ENCODE_ALG_WEP: + if (ext->key_len == 5) + cipher = WLAN_CIPHER_SUITE_WEP40; + else if (ext->key_len == 13) + cipher = WLAN_CIPHER_SUITE_WEP104; + else + return -EINVAL; + break; + case IW_ENCODE_ALG_TKIP: + cipher = WLAN_CIPHER_SUITE_TKIP; + break; + case IW_ENCODE_ALG_CCMP: + cipher = WLAN_CIPHER_SUITE_CCMP; + break; + case IW_ENCODE_ALG_AES_CMAC: + cipher = WLAN_CIPHER_SUITE_AES_CMAC; + break; + default: + return -EOPNOTSUPP; + } + + if (erq->flags & IW_ENCODE_DISABLED) + remove = true; + + idx = erq->flags & IW_ENCODE_INDEX; + if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + if (idx < 4 || idx > 5) { + idx = wdev->wext.default_mgmt_key; + if (idx < 0) + return -EINVAL; + } else + idx--; + } else { + if (idx < 1 || idx > 4) { + idx = wdev->wext.default_key; + if (idx < 0) + return -EINVAL; + } else + idx--; + } + + addr = ext->addr.sa_data; + if (is_broadcast_ether_addr(addr)) + addr = NULL; + + memset(¶ms, 0, sizeof(params)); + params.key = ext->key; + params.key_len = ext->key_len; + params.cipher = cipher; + + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + params.seq = ext->rx_seq; + params.seq_len = 6; + } + + return cfg80211_set_encryption( + rdev, dev, addr, remove, + ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, + idx, ¶ms); +} +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, + }; + + if (!rdev->ops->get_key) + return -EOPNOTSUPP; + + idx = erq->flags & IW_ENCODE_INDEX; + if (idx == 0) { + idx = wdev->wext.default_key; + if (idx < 0) + idx = 0; + } else if (idx < 1 || idx > 4) + return -EINVAL; + else + idx--; + + 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) { + erq->flags |= IW_ENCODE_DISABLED; + erq->length = 0; + return 0; + } + + return err; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); + +int cfg80211_wext_siwtxpower(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + enum tx_power_setting type; + int dbm = 0; + + if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) + return -EINVAL; + if (data->txpower.flags & IW_TXPOW_RANGE) + return -EINVAL; + + if (!rdev->ops->set_tx_power) + return -EOPNOTSUPP; + + /* only change when not disabling */ + if (!data->txpower.disabled) { + rfkill_set_sw_state(rdev->rfkill, false); + + if (data->txpower.fixed) { + /* + * wext doesn't support negative values, see + * below where it's for automatic + */ + if (data->txpower.value < 0) + return -EINVAL; + dbm = data->txpower.value; + type = TX_POWER_FIXED; + /* TODO: do regulatory check! */ + } else { + /* + * Automatic power level setting, max being the value + * passed in from userland. + */ + if (data->txpower.value < 0) { + type = TX_POWER_AUTOMATIC; + } else { + dbm = data->txpower.value; + type = TX_POWER_LIMITED; + } + } + } else { + rfkill_set_sw_state(rdev->rfkill, true); + schedule_work(&rdev->rfkill_sync); + return 0; + } + + return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower); + +int cfg80211_wext_giwtxpower(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + int err, val; + + if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) + return -EINVAL; + if (data->txpower.flags & IW_TXPOW_RANGE) + return -EINVAL; + + if (!rdev->ops->get_tx_power) + return -EOPNOTSUPP; + + err = rdev->ops->get_tx_power(wdev->wiphy, &val); + if (err) + return err; + + /* well... oh well */ + data->txpower.fixed = 1; + data->txpower.disabled = rfkill_blocked(rdev->rfkill); + data->txpower.value = val; + data->txpower.flags = IW_TXPOW_DBM; + + return 0; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower); diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 0e59f9ae9b81..252c2010c2e2 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c @@ -636,8 +636,10 @@ static void wireless_seq_printf_stats(struct seq_file *seq, /* * Print info for /proc/net/wireless (print all entries) */ -static int wireless_seq_show(struct seq_file *seq, void *v) +static int wireless_dev_seq_show(struct seq_file *seq, void *v) { + might_sleep(); + if (v == SEQ_START_TOKEN) seq_printf(seq, "Inter-| sta-| Quality | Discarded " "packets | Missed | WE\n" @@ -649,14 +651,46 @@ static int wireless_seq_show(struct seq_file *seq, void *v) return 0; } +static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct net *net = seq_file_net(seq); + loff_t off; + struct net_device *dev; + + rtnl_lock(); + if (!*pos) + return SEQ_START_TOKEN; + + off = 1; + for_each_netdev(net, dev) + if (off++ == *pos) + return dev; + return NULL; +} + +static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct net *net = seq_file_net(seq); + + ++*pos; + + return v == SEQ_START_TOKEN ? + first_net_device(net) : next_net_device(v); +} + +static void wireless_dev_seq_stop(struct seq_file *seq, void *v) +{ + rtnl_unlock(); +} + static const struct seq_operations wireless_seq_ops = { - .start = dev_seq_start, - .next = dev_seq_next, - .stop = dev_seq_stop, - .show = wireless_seq_show, + .start = wireless_dev_seq_start, + .next = wireless_dev_seq_next, + .stop = wireless_dev_seq_stop, + .show = wireless_dev_seq_show, }; -static int wireless_seq_open(struct inode *inode, struct file *file) +static int seq_open_wireless(struct inode *inode, struct file *file) { return seq_open_net(inode, file, &wireless_seq_ops, sizeof(struct seq_net_private)); @@ -664,7 +698,7 @@ static int wireless_seq_open(struct inode *inode, struct file *file) static const struct file_operations wireless_seq_fops = { .owner = THIS_MODULE, - .open = wireless_seq_open, + .open = seq_open_wireless, .read = seq_read, .llseek = seq_lseek, .release = seq_release_net, diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 96036cf2216d..d31ccb487730 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -696,8 +696,9 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, { int start = skb_headlen(skb); int i, copy = start - offset; - int err; + struct sk_buff *frag_iter; struct scatterlist sg; + int err; /* Checksum header. */ if (copy > 0) { @@ -742,28 +743,24 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, start = end; } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; + skb_walk_frags(skb, frag_iter) { + int end; - for (; list; list = list->next) { - int end; + WARN_ON(start > offset + len); - WARN_ON(start > offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - err = skb_icv_walk(list, desc, offset-start, - copy, icv_update); - if (unlikely(err)) - return err; - if ((len -= copy) == 0) - return 0; - offset += copy; - } - start = end; + end = start + frag_iter->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + err = skb_icv_walk(frag_iter, desc, offset-start, + copy, icv_update); + if (unlikely(err)) + return err; + if ((len -= copy) == 0) + return 0; + offset += copy; } + start = end; } BUG_ON(len); return 0; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index b4a13178fb40..e0009c17d809 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -251,8 +251,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) nf_reset(skb); if (decaps) { - dst_release(skb->dst); - skb->dst = NULL; + skb_dst_drop(skb); netif_rx(skb); return 0; } else { diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index c235597ba8dd..b9fe13138c07 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -22,7 +22,7 @@ static int xfrm_output2(struct sk_buff *skb); static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); int nhead = dst->header_len + LL_RESERVED_SPACE(dst->dev) - skb_headroom(skb); int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); @@ -39,7 +39,7 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) static int xfrm_output_one(struct sk_buff *skb, int err) { - struct dst_entry *dst = skb->dst; + struct dst_entry *dst = skb_dst(skb); struct xfrm_state *x = dst->xfrm; struct net *net = xs_net(x); @@ -94,12 +94,13 @@ static int xfrm_output_one(struct sk_buff *skb, int err) goto error_nolock; } - if (!(skb->dst = dst_pop(dst))) { + dst = dst_pop(dst); + if (!dst) { XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); err = -EHOSTUNREACH; goto error_nolock; } - dst = skb->dst; + skb_dst_set(skb, dst); x = dst->xfrm; } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); @@ -119,16 +120,16 @@ int xfrm_output_resume(struct sk_buff *skb, int err) while (likely((err = xfrm_output_one(skb, err)) == 0)) { nf_reset(skb); - err = skb->dst->ops->local_out(skb); + err = skb_dst(skb)->ops->local_out(skb); if (unlikely(err != 1)) goto out; - if (!skb->dst->xfrm) + if (!skb_dst(skb)->xfrm) return dst_output(skb); - err = nf_hook(skb->dst->ops->family, + err = nf_hook(skb_dst(skb)->ops->family, NF_INET_POST_ROUTING, skb, - NULL, skb->dst->dev, xfrm_output2); + NULL, skb_dst(skb)->dev, xfrm_output2); if (unlikely(err != 1)) goto out; } @@ -179,7 +180,7 @@ static int xfrm_output_gso(struct sk_buff *skb) int xfrm_output(struct sk_buff *skb) { - struct net *net = dev_net(skb->dst->dev); + struct net *net = dev_net(skb_dst(skb)->dev); int err; if (skb_is_gso(skb)) @@ -202,7 +203,7 @@ int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) struct xfrm_mode *inner_mode; if (x->sel.family == AF_UNSPEC) inner_mode = xfrm_ip2inner_mode(x, - xfrm_af2proto(skb->dst->ops->family)); + xfrm_af2proto(skb_dst(skb)->ops->family)); else inner_mode = x->inner_mode; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 9c068ab3a834..cb81ca35b0d6 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2027,6 +2027,8 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) { struct net *net = dev_net(skb->dev); struct flowi fl; + struct dst_entry *dst; + int res; if (xfrm_decode_session(skb, &fl, family) < 0) { /* XXX: we should have something like FWDHDRERROR here. */ @@ -2034,7 +2036,11 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) return 0; } - return xfrm_lookup(net, &skb->dst, &fl, NULL, 0) == 0; + dst = skb_dst(skb); + + res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0; + skb_dst_set(skb, dst); + return res; } EXPORT_SYMBOL(__xfrm_route_forward); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 195906bce266..15c2a08a66f1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4495,7 +4495,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, * when the packet is on it's final way out. * NOTE: there appear to be some IPv6 multicast cases where skb->dst * is NULL, in this case go ahead and apply access control. */ - if (skb->dst != NULL && skb->dst->xfrm != NULL) + if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) return NF_ACCEPT; #endif secmark_active = selinux_secmark_enabled(); diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index c0eb72013d67..72b18452e1a1 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -447,7 +447,7 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, struct dst_entry *dst; int rc = 0; - dst = skb->dst; + dst = skb_dst(skb); if (dst) { struct dst_entry *dst_test;