diff options
Diffstat (limited to 'drivers')
452 files changed, 17642 insertions, 19693 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8a851d0f438..431f8b43955 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -11,9 +11,9 @@ menuconfig ACPI select PNP select CPU_IDLE default y - ---help--- + help Advanced Configuration and Power Interface (ACPI) support for - Linux requires an ACPI compliant platform (hardware/firmware), + Linux requires an ACPI-compliant platform (hardware/firmware), and assumes the presence of OS-directed configuration and power management (OSPM) software. This option will enlarge your kernel by about 70K. @@ -23,20 +23,19 @@ menuconfig ACPI the Plug-and-Play BIOS specification (PnP BIOS), the MultiProcessor Specification (MPS), and the Advanced Power Management (APM) specification. If both ACPI and APM support - are configured, whichever is loaded first shall be used. + are configured, ACPI is used. - The ACPI SourceForge project contains the latest source code, - documentation, tools, mailing list subscription, and other - information. This project is available at: - <http://sourceforge.net/projects/acpi> + The project home page for the Linux ACPI subsystem is here: + <http://www.lesswatts.org/projects/acpi/> Linux support for ACPI is based on Intel Corporation's ACPI - Component Architecture (ACPI CA). For more information see: - <http://developer.intel.com/technology/iapc/acpi> + Component Architecture (ACPI CA). For more information on the + ACPI CA, see: + <http://acpica.org/> - ACPI is an open industry specification co-developed by Compaq, - Intel, Microsoft, Phoenix, and Toshiba. The specification is - available at: + ACPI is an open industry specification co-developed by + Hewlett-Packard, Intel, Microsoft, Phoenix, and Toshiba. + The specification is available at: <http://www.acpi.info> if ACPI @@ -49,14 +48,14 @@ config ACPI_SLEEP config ACPI_PROCFS bool "Deprecated /proc/acpi files" depends on PROC_FS - ---help--- + help For backwards compatibility, this option allows deprecated /proc/acpi/ files to exist, even when they have been replaced by functions in /sys. The deprecated files (and their replacements) include: /proc/acpi/sleep (/sys/power/state) - /proc/acpi/info (/sys/modules/acpi/parameters/acpica_version) + /proc/acpi/info (/sys/module/acpi/parameters/acpica_version) /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) @@ -66,11 +65,12 @@ config ACPI_PROCFS and functions which do not yet exist in /sys. Say N to delete /proc/acpi/ files that have moved to /sys/ + config ACPI_PROCFS_POWER bool "Deprecated power /proc/acpi directories" depends on PROC_FS default y - ---help--- + help For backwards compatibility, this option allows deprecated power /proc/acpi/ directories to exist, even when they have been replaced by functions in /sys. @@ -86,19 +86,19 @@ config ACPI_SYSFS_POWER bool "Future power /sys interface" select POWER_SUPPLY default y - ---help--- + help Say N to disable power /sys interface config ACPI_PROC_EVENT bool "Deprecated /proc/acpi/event support" depends on PROC_FS default y - ---help--- - A user-space daemon, acpi, typically read /proc/acpi/event - and handled all ACPI sub-system generated events. + help + A user-space daemon, acpid, typically reads /proc/acpi/event + and handles all ACPI-generated events. - These events are now delivered to user-space via - either the input layer, or as netlink events. + These events are now delivered to user-space either + via the input layer or as netlink events. This build option enables the old code for legacy user-space implementation. After some time, this will @@ -112,10 +112,13 @@ config ACPI_AC depends on X86 default y help - This driver adds support for the AC Adapter object, which indicates - whether a system is on AC, or not. If you have a system that can + This driver supports the AC Adapter object, which indicates + whether a system is on AC or not. If you have a system that can switch between A/C and battery, say Y. + To compile this driver as a module, choose M here: + the module will be called ac. + config ACPI_BATTERY tristate "Battery" depends on X86 @@ -125,15 +128,21 @@ config ACPI_BATTERY /proc/acpi/battery. If you have a mobile system with a battery, say Y. + To compile this driver as a module, choose M here: + the module will be called battery. + config ACPI_BUTTON tristate "Button" depends on INPUT default y help - This driver handles events on the power, sleep and lid buttons. + This driver handles events on the power, sleep, and lid buttons. A daemon reads /proc/acpi/event and perform user-defined actions such as shutting down the system. This is necessary for - software controlled poweroff. + software-controlled poweroff. + + To compile this driver as a module, choose M here: + the module will be called button. config ACPI_VIDEO tristate "Video" @@ -141,38 +150,45 @@ config ACPI_VIDEO depends on INPUT select THERMAL help - This driver implement the ACPI Extensions For Display Adapters + This driver implements the ACPI Extensions For Display Adapters for integrated graphics devices on motherboard, as specified in - ACPI 2.0 Specification, Appendix B, allowing to perform some basic - control like defining the video POST device, retrieving EDID information - or to setup a video output, etc. - Note that this is an ref. implementation only. It may or may not work - for your integrated video device. + ACPI 2.0 Specification, Appendix B. This supports basic operations + such as defining the video POST device, retrieving EDID information, + and setting up a video output. + + To compile this driver as a module, choose M here: + the module will be called video. config ACPI_FAN tristate "Fan" select THERMAL default y help - This driver adds support for ACPI fan devices, allowing user-mode + This driver supports ACPI fan devices, allowing user-mode applications to perform basic fan control (on, off, status). + To compile this driver as a module, choose M here: + the module will be called fan. + config ACPI_DOCK bool "Dock" depends on EXPERIMENTAL help - This driver adds support for ACPI controlled docking stations and removable - drive bays such as the IBM ultrabay or the Dell Module Bay. + This driver supports ACPI-controlled docking stations and removable + drive bays such as the IBM Ultrabay and the Dell Module Bay. config ACPI_PROCESSOR tristate "Processor" select THERMAL default y help - This driver installs ACPI as the idle handler for Linux, and uses - ACPI C2 and C3 processor states to save power, on systems that + This driver installs ACPI as the idle handler for Linux and uses + ACPI C2 and C3 processor states to save power on systems that support it. It is required by several flavors of cpufreq - Performance-state drivers. + performance-state drivers. + + To compile this driver as a module, choose M here: + the module will be called processor. config ACPI_HOTPLUG_CPU bool @@ -186,11 +202,14 @@ config ACPI_THERMAL select THERMAL default y help - This driver adds support for ACPI thermal zones. Most mobile and + This driver supports ACPI thermal zones. Most mobile and some desktop systems support ACPI thermal zones. It is HIGHLY recommended that this option be enabled, as your processor(s) may be damaged without it. + To compile this driver as a module, choose M here: + the module will be called thermal. + config ACPI_NUMA bool "NUMA support" depends on NUMA @@ -218,7 +237,7 @@ config ACPI_BLACKLIST_YEAR int "Disable ACPI for systems before Jan 1st this year" if X86_32 default 0 help - enter a 4-digit year, eg. 2001 to disable ACPI by default + Enter a 4-digit year, e.g., 2001, to disable ACPI by default on platforms with DMI BIOS date before January 1st that year. "acpi=force" can be used to override this mechanism. @@ -249,10 +268,13 @@ config ACPI_PCI_SLOT tristate "PCI slot detection driver" default n help - This driver will attempt to discover all PCI slots in your system, - and creates entries in /sys/bus/pci/slots/. This feature can - help you correlate PCI bus addresses with the physical geography - of your slots. If you are unsure, say N. + This driver creates entries in /sys/bus/pci/slots/ for all PCI + slots in the system. This can help correlate PCI bus addresses, + i.e., segment/bus/device/function tuples, with physical slots in + the system. If you are unsure, say N. + + To compile this driver as a module, choose M here: + the module will be called pci_slot. config X86_PM_TIMER bool "Power Management Timer Support" if EMBEDDED @@ -271,43 +293,43 @@ config X86_PM_TIMER systems require this timer. config ACPI_CONTAINER - tristate "ACPI0004,PNP0A05 and PNP0A06 Container Driver (EXPERIMENTAL)" + tristate "Container and Module Devices (EXPERIMENTAL)" depends on EXPERIMENTAL default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) - ---help--- - This allows _physical_ insertion and removal of CPUs and memory. - This can be useful, for example, on NUMA machines that support - ACPI based physical hotplug of nodes, or non-NUMA machines that - support physical cpu/memory hot-plug. + help + This driver supports ACPI Container and Module devices (IDs + ACPI0004, PNP0A05, and PNP0A06). - If one selects "m", this driver can be loaded with - "modprobe container". + This helps support hotplug of nodes, CPUs, and memory. + + To compile this driver as a module, choose M here: + the module will be called container. config ACPI_HOTPLUG_MEMORY tristate "Memory Hotplug" depends on MEMORY_HOTPLUG default n help - This driver adds supports for ACPI Memory Hotplug. This driver - provides support for fielding notifications on ACPI memory - devices (PNP0C80) which represent memory ranges that may be - onlined or offlined during runtime. + This driver supports ACPI memory hotplug. The driver + fields notifications on ACPI memory devices (PNP0C80), + which represent memory ranges that may be onlined or + offlined during runtime. - Enabling this driver assumes that your platform hardware - and firmware have support for hot-plugging physical memory. If - your system does not support physically adding or ripping out - memory DIMMs at some platform defined granularity (individually - or as a bank) at runtime, then you need not enable this driver. + If your hardware and firmware do not support adding or + removing memory devices at runtime, you need not enable + this driver. - If one selects "m," this driver can be loaded using the following - command: - $>modprobe acpi_memhotplug + To compile this driver as a module, choose M here: + the module will be called acpi_memhotplug. config ACPI_SBS tristate "Smart Battery System" depends on X86 help - This driver adds support for the Smart Battery System, another + This driver supports the Smart Battery System, another type of access to battery information, found on some laptops. + To compile this driver as a module, choose M here: + the modules will be called sbs and sbshc. + endif # ACPI diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b130ea0d075..61675e21fba 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -32,10 +32,8 @@ ifdef CONFIG_CPU_FREQ processor-objs += processor_perflib.o endif -obj-y += bus.o glue.o -obj-y += scan.o -# Keep EC driver first. Initialization of others depend on it. -obj-y += ec.o +obj-y += bus.o glue.o scan.o ec.o \ + power.o system.o event.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o @@ -51,8 +49,6 @@ obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o -obj-y += power.o -obj-y += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 3f23298ee3f..17e50824a6f 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -18,7 +18,7 @@ obj-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o -obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o +obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o obj-$(ACPI_FUTURE_USAGE) += hwtimer.o @@ -41,4 +41,4 @@ obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ - utstate.o utmutex.o utobject.o utresrc.o + utstate.o utmutex.o utobject.o utresrc.o utlock.o diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ddb40f5c68f..16e5210ae93 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -148,9 +148,12 @@ ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT; ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; -/* These addresses are calculated from FADT address values */ +/* These addresses are calculated from the FADT Event Block addresses */ +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_status; ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; + +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status; ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; /* @@ -162,6 +165,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; + /***************************************************************************** * * Mutual exlusion within ACPICA subsystem @@ -245,6 +252,7 @@ ACPI_EXTERN u8 acpi_gbl_step_to_next_call; ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; ACPI_EXTERN u8 acpi_gbl_events_initialized; ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; +ACPI_EXTERN u8 acpi_gbl_osi_data; #ifndef DEFINE_ACPI_GLOBALS @@ -371,7 +379,6 @@ ACPI_EXTERN char *acpi_gbl_db_buffer; ACPI_EXTERN char *acpi_gbl_db_filename; ACPI_EXTERN u32 acpi_gbl_db_debug_level; ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; -ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; /* diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 58c69dc49ab..4afa3d8e0ef 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -64,14 +64,22 @@ u32 acpi_hw_get_mode(void); */ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); -acpi_status -acpi_hw_register_read(u32 register_id, u32 * return_value); +acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); + +acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value); acpi_status acpi_hw_register_write(u32 register_id, u32 value); acpi_status acpi_hw_clear_acpi_status(void); /* + * hwvalid - Port I/O with validation + */ +acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width); + +acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); + +/* * hwgpe - GPE support */ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 492d02761bb..772ee5c4ccc 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -108,6 +108,14 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { #endif #endif +/* Lock structure for reader/writer interfaces */ + +struct acpi_rw_lock { + acpi_mutex writer_mutex; + acpi_mutex reader_mutex; + u32 num_readers; +}; + /* * Predefined handles for spinlocks used within the subsystem. * These spinlocks are created by acpi_ut_mutex_initialize @@ -772,7 +780,19 @@ struct acpi_bit_register_info { * must be preserved. */ #define ACPI_PM1_STATUS_PRESERVED_BITS 0x0800 /* Bit 11 */ -#define ACPI_PM1_CONTROL_PRESERVED_BITS 0x0200 /* Bit 9 (whatever) */ + +/* Write-only bits must be zeroed by software */ + +#define ACPI_PM1_CONTROL_WRITEONLY_BITS 0x2004 /* Bits 13, 2 */ + +/* For control registers, both ignored and reserved bits must be preserved */ + +#define ACPI_PM1_CONTROL_IGNORED_BITS 0x0201 /* Bits 9, 0(SCI_EN) */ +#define ACPI_PM1_CONTROL_RESERVED_BITS 0xC1F8 /* Bits 14-15, 3-8 */ +#define ACPI_PM1_CONTROL_PRESERVED_BITS \ + (ACPI_PM1_CONTROL_IGNORED_BITS | ACPI_PM1_CONTROL_RESERVED_BITS) + +#define ACPI_PM2_CONTROL_PRESERVED_BITS 0xFFFFFFFE /* All except bit 0 */ /* * Register IDs @@ -781,12 +801,10 @@ struct acpi_bit_register_info { #define ACPI_REGISTER_PM1_STATUS 0x01 #define ACPI_REGISTER_PM1_ENABLE 0x02 #define ACPI_REGISTER_PM1_CONTROL 0x03 -#define ACPI_REGISTER_PM1A_CONTROL 0x04 -#define ACPI_REGISTER_PM1B_CONTROL 0x05 -#define ACPI_REGISTER_PM2_CONTROL 0x06 -#define ACPI_REGISTER_PM_TIMER 0x07 -#define ACPI_REGISTER_PROCESSOR_BLOCK 0x08 -#define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x09 +#define ACPI_REGISTER_PM2_CONTROL 0x04 +#define ACPI_REGISTER_PM_TIMER 0x05 +#define ACPI_REGISTER_PROCESSOR_BLOCK 0x06 +#define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x07 /* Masks used to access the bit_registers */ @@ -818,7 +836,7 @@ struct acpi_bit_register_info { #define ACPI_BITMASK_SCI_ENABLE 0x0001 #define ACPI_BITMASK_BUS_MASTER_RLD 0x0002 #define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004 -#define ACPI_BITMASK_SLEEP_TYPE_X 0x1C00 +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 #define ACPI_BITMASK_SLEEP_ENABLE 0x2000 #define ACPI_BITMASK_ARB_DISABLE 0x0001 @@ -844,11 +862,35 @@ struct acpi_bit_register_info { #define ACPI_BITPOSITION_SCI_ENABLE 0x00 #define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01 #define ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE 0x02 -#define ACPI_BITPOSITION_SLEEP_TYPE_X 0x0A +#define ACPI_BITPOSITION_SLEEP_TYPE 0x0A #define ACPI_BITPOSITION_SLEEP_ENABLE 0x0D #define ACPI_BITPOSITION_ARB_DISABLE 0x00 +/* Structs and definitions for _OSI support and I/O port validation */ + +#define ACPI_OSI_WIN_2000 0x01 +#define ACPI_OSI_WIN_XP 0x02 +#define ACPI_OSI_WIN_XP_SP1 0x03 +#define ACPI_OSI_WINSRV_2003 0x04 +#define ACPI_OSI_WIN_XP_SP2 0x05 +#define ACPI_OSI_WINSRV_2003_SP1 0x06 +#define ACPI_OSI_WIN_VISTA 0x07 + +#define ACPI_ALWAYS_ILLEGAL 0x00 + +struct acpi_interface_info { + char *name; + u8 value; +}; + +struct acpi_port_info { + char *name; + u16 start; + u16 end; + u8 osi_dependency; +}; + /***************************************************************************** * * Resource descriptors diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 9c127e8e2d6..91ac7d7b440 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -292,10 +292,6 @@ #define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type) #define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t) -/* Macro to test the object type */ - -#define ACPI_GET_OBJECT_TYPE(d) (((union acpi_operand_object *)(void *)(d))->common.type) - /* * Macros for the master AML opcode table */ diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index eb6f038b03d..544dcf83492 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -97,7 +97,6 @@ #define AOPOBJ_OBJECT_INITIALIZED 0x08 #define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SINGLE_DATUM 0x20 -#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ /****************************************************************************** * diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 16a9ca9a66e..63f656ae360 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -52,41 +52,44 @@ * 1) PTYPE1 packages do not contain sub-packages. * * ACPI_PTYPE1_FIXED: Fixed length, 1 or 2 object types: - * object type - * count - * object type - * count + * object type + * count + * object type + * count * * ACPI_PTYPE1_VAR: Variable length: - * object type (Int/Buf/Ref) + * object type (Int/Buf/Ref) * - * ACPI_PTYPE1_OPTION: Package has some required and some optional elements: - * Used for _PRW + * ACPI_PTYPE1_OPTION: Package has some required and some optional elements + * (Used for _PRW) * * * 2) PTYPE2 packages contain a variable number of sub-packages. Each of the * different types describe the contents of each of the sub-packages. * * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: - * object type - * count - * object type - * count + * object type + * count + * object type + * count + * (Used for _ALR,_MLS,_PSS,_TRT,_TSS) * * ACPI_PTYPE2_COUNT: Each subpackage has a count as first element: - * object type + * object type + * (Used for _CSD,_PSD,_TSD) * * ACPI_PTYPE2_PKG_COUNT: Count of subpackages at start, 1 or 2 object types: - * object type - * count - * object type - * count + * object type + * count + * object type + * count + * (Used for _CST) * - * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length: - * Used for _PRT + * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length + * (Used for _PRT) * * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length - * Used for _HPX + * (Used for _HPX) * *****************************************************************************/ diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 7ce6e33c7f7..01c76b8ea7b 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -49,7 +49,7 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count); /* * tbfadt - FADT parse/convert/validate */ -void acpi_tb_parse_fadt(u32 table_index, u8 flags); +void acpi_tb_parse_fadt(u32 table_index); void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); @@ -79,7 +79,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc); void acpi_tb_terminate(void); -void acpi_tb_delete_namespace_by_owner(u32 table_index); +acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index); acpi_status acpi_tb_allocate_owner_id(u32 table_index); @@ -109,9 +109,8 @@ acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length); void acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index); + char *signature, u32 table_index); -acpi_status -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags); +acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address); #endif /* __ACTABLES_H__ */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 80d8813484f..897810ba0cc 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -346,6 +346,21 @@ acpi_status acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest); /* + * utlock - reader/writer locks + */ +acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock); + +void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock); + +acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock); + +acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock); + +acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock); + +void acpi_ut_release_write_lock(struct acpi_rw_lock *lock); + +/* * utobject - internal object create/delete/cache routines */ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index eb144b13d8f..3aae13f30c5 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -180,11 +180,23 @@ acpi_ds_initialize_objects(u32 table_index, /* Walk entire namespace from the supplied root */ - status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, - acpi_ds_init_one_object, &info, NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * We don't use acpi_walk_namespace since we do not want to acquire + * the namespace reader lock. + */ + status = + acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object, + &info, NULL); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); status = acpi_get_table_by_index(table_index, &table); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index da0f5468184..22b1a3ce2c9 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -713,6 +713,6 @@ acpi_ds_method_data_get_type(u16 opcode, /* Get the object type */ - return_VALUE(ACPI_GET_OBJECT_TYPE(object)); + return_VALUE(object->type); } #endif diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 15c628e6aa0..dab3f48f0b4 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -565,7 +565,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, /* Re-type the object according to its argument */ - node->type = ACPI_GET_OBJECT_TYPE(obj_desc); + node->type = obj_desc->common.type; /* Attach obj to node */ @@ -619,7 +619,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Perform per-object initialization */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: /* @@ -803,7 +803,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, default: ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", - ACPI_GET_OBJECT_TYPE(obj_desc))); + obj_desc->common.type)); status = AE_AML_OPERAND_TYPE; break; diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 0c3b4dd60e8..b4c87b5053e 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -397,30 +397,6 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), extra_desc->extra.aml_length, extra_desc->extra.aml_start); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate the region address/length via the host OS */ - - status = acpi_os_validate_address(obj_desc->region.space_id, - obj_desc->region.address, - (acpi_size) obj_desc->region.length, - acpi_ut_get_node_name(node)); - - if (ACPI_FAILURE(status)) { - /* - * Invalid address/length. We will emit an error message and mark - * the region as invalid, so that it will cause an additional error if - * it is ever used. Then return AE_OK. - */ - ACPI_EXCEPTION((AE_INFO, status, - "During address validation of OpRegion [%4.4s]", - node->name.ascii)); - obj_desc->common.flags |= AOPOBJ_INVALID; - status = AE_OK; - } - return_ACPI_STATUS(status); } @@ -484,7 +460,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Host object must be a Buffer */ - if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { + if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "Target of Create Field is not a Buffer object - %s", acpi_ut_get_object_type_name(buffer_desc))); @@ -1365,10 +1341,8 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) - && - (ACPI_GET_OBJECT_TYPE - (walk_state->results->results.obj_desc[0]) == - ACPI_TYPE_LOCAL_REFERENCE) + && ((walk_state->results->results.obj_desc[0])-> + common.type == ACPI_TYPE_LOCAL_REFERENCE) && ((walk_state->results->results.obj_desc[0])-> reference.class != ACPI_REFCLASS_INDEX)) { status = diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index dabc23a4617..dfa10410292 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -816,7 +816,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) goto push_result; } - type = ACPI_GET_OBJECT_TYPE(*operand); + type = (*operand)->common.type; status = acpi_ex_resolve_to_value(operand, walk_state); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 350e6656bc8..f0280856dc0 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -138,11 +138,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, goto cleanup; } - if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { + if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", - obj_desc, walk_state, - ACPI_GET_OBJECT_TYPE(obj_desc))); + obj_desc, walk_state, obj_desc->common.type)); status = AE_AML_OPERAND_TYPE; goto cleanup; diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 803edd9e3f6..cd55c774e88 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -183,7 +183,7 @@ acpi_status acpi_ev_install_xrupt_handlers(void) * * RETURN: Status * - * DESCRIPTION: Install the fixed event handlers and enable the fixed events. + * DESCRIPTION: Install the fixed event handlers and disable all fixed events. * ******************************************************************************/ @@ -200,12 +200,13 @@ static acpi_status acpi_ev_fixed_event_initialize(void) acpi_gbl_fixed_event_handlers[i].handler = NULL; acpi_gbl_fixed_event_handlers[i].context = NULL; - /* Enable the fixed event */ + /* Disable the fixed event */ if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { status = - acpi_set_register(acpi_gbl_fixed_event_info[i]. - enable_register_id, 0); + acpi_write_bit_register(acpi_gbl_fixed_event_info + [i].enable_register_id, + ACPI_DISABLE_EVENT); if (ACPI_FAILURE(status)) { return (status); } @@ -288,16 +289,17 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) /* Clear the status bit */ - (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + status_register_id, ACPI_CLEAR_STATUS); /* * Make sure we've got a handler. If not, report an error. The event is * disabled to prevent further interrupts. */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { - (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, + ACPI_DISABLE_EVENT); ACPI_ERROR((AE_INFO, "No installed handler for fixed event [%08X]", diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index f345ced3647..b9d8ee69ca6 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -88,10 +88,10 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) status = acpi_ev_disable_gpe(gpe_event_info); - /* Type was validated above */ + /* Clear the type bits and insert the new Type */ - gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */ - gpe_event_info->flags |= type; /* Insert type */ + gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; + gpe_event_info->flags |= type; return_ACPI_STATUS(status); } @@ -122,6 +122,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, if (!gpe_register_info) { return_ACPI_STATUS(AE_NOT_EXIST); } + register_bit = (u8) (1 << (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 484cc0565d5..7b346363942 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -104,9 +104,9 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) while (gpe_block) { if ((&gpe_block->event_info[0] <= gpe_event_info) && - (&gpe_block-> - event_info[((acpi_size) gpe_block-> - register_count) * 8] > + (&gpe_block->event_info[((acpi_size) + gpe_block-> + register_count) * 8] > gpe_event_info)) { return (TRUE); } @@ -210,10 +210,9 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - gpe_event_info = - &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + gpe_event_info = &gpe_block->event_info[((acpi_size) i * + ACPI_GPE_REGISTER_WIDTH) + + j]; if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { @@ -293,8 +292,8 @@ acpi_ev_save_method_info(acpi_handle obj_handle, /* Unknown method type, just ignore it! */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)", - name)); + "Ignoring unknown GPE method type: %s " + "(name not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } @@ -306,17 +305,16 @@ acpi_ev_save_method_info(acpi_handle obj_handle, /* Conversion failed; invalid method, just ignore it */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", - name)); + "Could not extract GPE number from name: %s " + "(name is not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ if ((gpe_number < gpe_block->block_base_number) || - (gpe_number >= - (gpe_block->block_base_number + - (gpe_block->register_count * 8)))) { + (gpe_number >= (gpe_block->block_base_number + + (gpe_block->register_count * 8)))) { /* * Not valid for this GPE block, just ignore it. However, it may be * valid for a different GPE block, since GPE0 and GPE1 methods both @@ -408,7 +406,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, */ obj_desc = pkg_desc->package.elements[0]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Use FADT-defined GPE device (from definition of _PRW) */ @@ -417,15 +415,15 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, /* Integer is the GPE number in the FADT described GPE blocks */ gpe_number = (u32) obj_desc->integer.value; - } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + } else if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { /* Package contains a GPE reference and GPE number within a GPE block */ if ((obj_desc->package.count < 2) || - (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) != - ACPI_TYPE_LOCAL_REFERENCE) - || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) != - ACPI_TYPE_INTEGER)) { + ((obj_desc->package.elements[0])->common.type != + ACPI_TYPE_LOCAL_REFERENCE) || + ((obj_desc->package.elements[1])->common.type != + ACPI_TYPE_INTEGER)) { goto cleanup; } @@ -450,11 +448,11 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, */ if ((gpe_device == target_gpe_device) && (gpe_number >= gpe_block->block_base_number) && - (gpe_number < - gpe_block->block_base_number + (gpe_block->register_count * 8))) { - gpe_event_info = - &gpe_block->event_info[gpe_number - - gpe_block->block_base_number]; + (gpe_number < gpe_block->block_base_number + + (gpe_block->register_count * 8))) { + gpe_event_info = &gpe_block->event_info[gpe_number - + gpe_block-> + block_base_number]; /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ @@ -1033,8 +1031,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, * 1) are "runtime" or "run/wake" GPEs, and * 2) have a corresponding _Lxx or _Exx method * - * Any other GPEs within this block must be enabled via the acpi_enable_gpe() - * external interface. + * Any other GPEs within this block must be enabled via the + * acpi_enable_gpe() external interface. */ wake_gpe_count = 0; gpe_enabled_count = 0; @@ -1044,14 +1042,13 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, /* Get the info block for this particular GPE */ - gpe_event_info = - &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + gpe_event_info = &gpe_block->event_info[((acpi_size) i * + ACPI_GPE_REGISTER_WIDTH) + + j]; if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_METHOD) - && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { + ACPI_GPE_DISPATCH_METHOD) && + (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { gpe_enabled_count++; } @@ -1105,8 +1102,8 @@ acpi_status acpi_ev_gpe_initialize(void) /* * Initialize the GPE Block(s) defined in the FADT * - * Why the GPE register block lengths are divided by 2: From the ACPI Spec, - * section "General-Purpose Event Registers", we have: + * Why the GPE register block lengths are divided by 2: From the ACPI + * Spec, section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the @@ -1163,7 +1160,8 @@ acpi_status acpi_ev_gpe_initialize(void) if ((register_count0) && (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { ACPI_ERROR((AE_INFO, - "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", + "GPE0 block (GPE 0 to %d) overlaps the GPE1 block " + "(GPE %d to %d) - Ignoring GPE1", gpe_number_max, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT.gpe1_base + ((register_count1 * diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 5f893057bcc..ce224e1eaa8 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -163,10 +163,10 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, * 2) Global device notify handler * 3) Per-device notify handler */ - if ((acpi_gbl_system_notify.handler - && (notify_value <= ACPI_MAX_SYS_NOTIFY)) - || (acpi_gbl_device_notify.handler - && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { + if ((acpi_gbl_system_notify.handler && + (notify_value <= ACPI_MAX_SYS_NOTIFY)) || + (acpi_gbl_device_notify.handler && + (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state(); if (!notify_info) { return (AE_NO_MEMORY); @@ -174,7 +174,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, if (!handler_obj) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Executing system notify handler for Notify (%4.4s, %X) node %p\n", + "Executing system notify handler for Notify (%4.4s, %X) " + "node %p\n", acpi_ut_get_node_name(node), notify_value, node)); } @@ -534,8 +535,9 @@ acpi_status acpi_ev_release_global_lock(void) */ if (pending) { status = - acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE, - 1); + acpi_write_bit_register + (ACPI_BITREG_GLOBAL_LOCK_RELEASE, + ACPI_ENABLE_EVENT); } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 665c0887ab4..538d6326455 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -691,7 +691,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, /* Devices are handled different than regions */ - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { + if (obj_desc->common.type == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ @@ -703,7 +703,8 @@ acpi_ev_install_handler(acpi_handle obj_handle, if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) { ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler for region [%s] in device %p(%p) handler %p\n", + "Found handler for region [%s] in device %p(%p) " + "handler %p\n", acpi_ut_get_region_name (handler_obj->address_space. space_id), obj_desc, diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index f3f1fb45c3d..284a7becbe9 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -241,7 +241,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, status = AE_OK; } else { ACPI_EXCEPTION((AE_INFO, status, - "Could not install PciConfig handler for Root Bridge %4.4s", + "Could not install PciConfig handler " + "for Root Bridge %4.4s", acpi_ut_get_node_name (pci_root_node))); } @@ -293,9 +294,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, * Get the PCI device and function numbers from the _ADR object contained * in the parent's scope. */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, - &pci_value); + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, + pci_device_node, &pci_value); /* * The default is zero, and since the allocation above zeroed the data, @@ -308,18 +308,16 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* The PCI segment number comes from the _SEG method */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, - &pci_value); + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, + pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->segment = ACPI_LOWORD(pci_value); } /* The PCI bus number comes from the _BBN method */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, - &pci_value); + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, + pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->bus = ACPI_LOWORD(pci_value); } @@ -632,8 +630,8 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, acpi_ns_locked); /* - * Tell all users that this region is usable by running the _REG - * method + * Tell all users that this region is usable by + * running the _REG method */ if (acpi_ns_locked) { status = diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 3aca9010a11..10b8543dd46 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -631,7 +631,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device, /* Setup up dispatch flags to indicate handler (vs. method) */ - gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ + gpe_event_info->flags &= + ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); acpi_os_release_lock(acpi_gbl_gpe_lock, flags); diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 35485e4b60a..d0a080747ec 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -172,8 +172,8 @@ acpi_status acpi_enable_event(u32 event, u32 flags) * register bit) */ status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 1); + acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, ACPI_ENABLE_EVENT); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -181,8 +181,8 @@ acpi_status acpi_enable_event(u32 event, u32 flags) /* Make sure that the hardware responded */ status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -354,15 +354,15 @@ acpi_status acpi_disable_event(u32 event, u32 flags) * register bit) */ status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, ACPI_DISABLE_EVENT); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -407,8 +407,8 @@ acpi_status acpi_clear_event(u32 event) * register bit) */ status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + status_register_id, ACPI_CLEAR_STATUS); return_ACPI_STATUS(status); } @@ -495,7 +495,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) /* Get the status of the requested fixed event */ status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. enable_register_id, &value); if (ACPI_FAILURE(status)) return_ACPI_STATUS(status); @@ -503,7 +503,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) *event_status = value; status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. status_register_id, &value); if (ACPI_FAILURE(status)) return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 479e7a3721b..7c3d2d356ff 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -193,7 +193,8 @@ acpi_remove_address_space_handler(acpi_handle device, /* Matched space_id, first dereference this in the Regions */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Removing address handler %p(%p) for region %s on Device %p(%p)\n", + "Removing address handler %p(%p) for region %s " + "on Device %p(%p)\n", handler_obj, handler, acpi_ut_get_region_name(space_id), node, obj_desc)); diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 932bbc26aa0..3deb20a126b 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -291,7 +291,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Source Object can be either an op_region or a Buffer/Field */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_REGION: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -501,7 +501,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) */ if ((!ddb_handle) || (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || - (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { + (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -520,13 +520,14 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) } } - /* - * Delete the entire namespace under this table Node - * (Offset contains the table_id) - */ - acpi_tb_delete_namespace_by_owner(table_index); - (void)acpi_tb_release_owner_id(table_index); + /* Delete the portion of the namespace owned by this table */ + + status = acpi_tb_delete_namespace_by_owner(table_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + (void)acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); /* Table unloaded, remove a reference to the ddb_handle object */ diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 0be10188316..37d0d39e60a 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -82,7 +82,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: /* No conversion necessary */ @@ -116,7 +116,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* String conversion is different than Buffer conversion */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_STRING: /* @@ -206,7 +206,7 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: /* No conversion necessary */ @@ -409,7 +409,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_STRING: /* No conversion necessary */ @@ -605,8 +605,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, default: /* No conversion allowed for these types */ - if (destination_type != - ACPI_GET_OBJECT_TYPE(source_desc)) { + if (destination_type != source_desc->common.type) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Explicit operator, will store (%s) over existing type (%s)\n", acpi_ut_get_object_type_name diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index aa313574b0d..89d141fdae0 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -350,6 +350,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, break; case ACPI_EXD_TYPE: + acpi_ex_out_string("Type", acpi_ut_get_object_type_name (obj_desc)); @@ -422,6 +423,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, break; default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", info->opcode); return; @@ -492,7 +494,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) /* Decode object type */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: acpi_os_printf("Reference: [%s] ", @@ -527,44 +529,16 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) type)); break; - case ACPI_REFCLASS_ARG: - - acpi_os_printf("%X", obj_desc->reference.value); - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Value is an Integer */ - - acpi_os_printf(" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64(obj_desc-> - integer. - value)); - } + case ACPI_REFCLASS_NAME: - acpi_os_printf("\n"); + acpi_os_printf("- [%4.4s]\n", + obj_desc->reference.node->name.ascii); break; + case ACPI_REFCLASS_ARG: case ACPI_REFCLASS_LOCAL: - acpi_os_printf("%X", obj_desc->reference.value); - - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { - - /* Value is an Integer */ - - acpi_os_printf(" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64(obj_desc-> - integer. - value)); - } - - acpi_os_printf("\n"); - break; - - case ACPI_REFCLASS_NAME: - - acpi_os_printf("- [%4.4s]\n", - obj_desc->reference.node->name.ascii); + acpi_os_printf("%X\n", obj_desc->reference.value); break; default: /* Unknown reference class */ @@ -661,8 +635,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf - ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", - obj_desc->field.bit_length, + ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at " + "byte=%X bit=%X of below:\n", obj_desc->field.bit_length, obj_desc->field.access_byte_width, obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, @@ -686,9 +660,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) if (!obj_desc->buffer_field.buffer_obj) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n")); - } else - if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj) - != ACPI_TYPE_BUFFER) { + } else if ((obj_desc->buffer_field.buffer_obj)->common.type != + ACPI_TYPE_BUFFER) { acpi_os_printf("*not a Buffer*\n"); } else { acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj, @@ -737,8 +710,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) default: /* Unknown Type */ - acpi_os_printf("Unknown Type %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc)); + acpi_os_printf("Unknown Type %X\n", obj_desc->common.type); break; } @@ -939,7 +911,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, /* Packages may only contain a few object types */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: acpi_os_printf("[Integer] = %8.8X%8.8X\n", @@ -990,8 +962,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, default: - acpi_os_printf("[Unknown Type] %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc)); + acpi_os_printf("[Unknown Type] %X\n", obj_desc->common.type); break; } } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index a352d023385..546dcdd8678 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -84,7 +84,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. @@ -95,9 +95,8 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } } - } else - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) - && (obj_desc->field.region_obj->region.space_id == + } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { /* * This is an SMBus read. We must create a buffer to hold the data @@ -163,7 +162,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", - obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer, + obj_desc, obj_desc->common.type, buffer, (u32) length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", @@ -222,7 +221,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(AE_AML_NO_OPERAND); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. @@ -233,9 +232,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } } - } else - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) - && (obj_desc->field.region_obj->region.space_id == + } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { /* * This is an SMBus write. We will bypass the entire field mechanism @@ -243,7 +241,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, * * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). */ - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { + if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "SMBus write requires Buffer, found type %s", acpi_ut_get_object_type_name(source_desc))); @@ -291,7 +289,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Get a pointer to the data to be written */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); @@ -314,15 +312,14 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE - (source_desc)), - ACPI_GET_OBJECT_TYPE(source_desc), buffer, length)); + acpi_ut_get_type_name(source_desc->common.type), + source_desc->common.type, buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)), - ACPI_GET_OBJECT_TYPE(obj_desc), + acpi_ut_get_type_name(obj_desc->common.type), + obj_desc->common.type, obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index ef58ac4e687..99cee61e655 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -94,9 +94,9 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, /* We must have a valid region */ - if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) { + if (rgn_desc->common.type != ACPI_TYPE_REGION) { ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)", - ACPI_GET_OBJECT_TYPE(rgn_desc), + rgn_desc->common.type, acpi_ut_get_object_type_name(rgn_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -113,12 +113,6 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } - /* Exit if Address/Length have been disallowed by the host OS */ - - if (rgn_desc->common.flags & AOPOBJ_INVALID) { - return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); - } - /* * Exit now for SMBus address space, it has a non-linear address space * and the request cannot be directly validated @@ -390,7 +384,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, * index_field - Write to an Index Register, then read/write from/to a * Data Register */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER_FIELD: /* * If the buffer_field arguments have not been previously evaluated, @@ -527,7 +521,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, default: ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X", - ACPI_GET_OBJECT_TYPE(obj_desc))); + obj_desc->common.type)); status = AE_AML_INTERNAL; break; } diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 6b0747ac683..998eac32993 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -80,7 +80,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { case ACPI_DESC_TYPE_OPERAND: - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { + if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -260,7 +260,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { + switch (operand0->common.type) { case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); @@ -277,7 +277,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, default: ACPI_ERROR((AE_INFO, "Invalid object type: %X", - ACPI_GET_OBJECT_TYPE(operand0))); + operand0->common.type)); status = AE_AML_INTERNAL; } @@ -298,7 +298,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { + switch (operand0->common.type) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ @@ -379,7 +379,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Invalid object type, should not happen here */ ACPI_ERROR((AE_INFO, "Invalid object type: %X", - ACPI_GET_OBJECT_TYPE(operand0))); + operand0->common.type)); status = AE_AML_INTERNAL; goto cleanup; } @@ -581,7 +581,7 @@ acpi_ex_do_logical_op(u16 opcode, * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { + switch (operand0->common.type) { case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); @@ -608,7 +608,7 @@ acpi_ex_do_logical_op(u16 opcode, /* * Two cases: 1) Both Integers, 2) Both Strings or Buffers */ - if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) { + if (operand0->common.type == ACPI_TYPE_INTEGER) { /* * 1) Both operands are of type integer * Note: local_operand1 may have changed above diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index b530480cc7d..9635d21e568 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -807,11 +807,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_namespace_node *) operand[0]); if (temp_desc - && - ((ACPI_GET_OBJECT_TYPE(temp_desc) == - ACPI_TYPE_STRING) - || (ACPI_GET_OBJECT_TYPE(temp_desc) == - ACPI_TYPE_LOCAL_REFERENCE))) { + && ((temp_desc->common.type == ACPI_TYPE_STRING) + || (temp_desc->common.type == + ACPI_TYPE_LOCAL_REFERENCE))) { operand[0] = temp_desc; acpi_ut_add_reference(temp_desc); } else { @@ -819,7 +817,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } } else { - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + switch ((operand[0])->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: /* * This is a deref_of (local_x | arg_x) @@ -877,8 +875,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != ACPI_DESC_TYPE_NAMED) { - if (ACPI_GET_OBJECT_TYPE(operand[0]) == - ACPI_TYPE_STRING) { + if ((operand[0])->common.type == ACPI_TYPE_STRING) { /* * This is a deref_of (String). The string is a reference * to a named ACPI object. diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index 0b4f513ca88..85d95c92dfd 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -399,7 +399,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) * At this point, the Source operand is a String, Buffer, or Package. * Verify that the index is within range. */ - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + switch ((operand[0])->common.type) { case ACPI_TYPE_STRING: if (index >= operand[0]->string.length) { diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index c6520bbf882..253f9e12258 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -161,9 +161,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) * Create the return object. The Source operand is guaranteed to be * either a String or a Buffer, so just use its type. */ - return_desc = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE - (operand[0])); + return_desc = acpi_ut_create_internal_object((operand[0])-> + common.type); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; @@ -191,7 +190,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* Strings always have a sub-pointer, not so for buffers */ - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + switch ((operand[0])->common.type) { case ACPI_TYPE_STRING: /* Always allocate a new buffer for the String */ diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index a226f74d4a5..52fec07064f 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -279,7 +279,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, return_UINT32(0); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * buffer_field access can be on any byte boundary, so the * byte_alignment is always 1 byte -- regardless of any byte_alignment diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 76ec8ff903b..3a54b737d2d 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -294,14 +294,14 @@ acpi_ex_system_io_space_handler(u32 function, switch (function) { case ACPI_READ: - status = acpi_os_read_port((acpi_io_address) address, + status = acpi_hw_read_port((acpi_io_address) address, &value32, bit_width); *value = value32; break; case ACPI_WRITE: - status = acpi_os_write_port((acpi_io_address) address, + status = acpi_hw_write_port((acpi_io_address) address, (u32) * value, bit_width); break; diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index a063a74006f..607958ff467 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -136,7 +136,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, switch (entry_type) { case ACPI_TYPE_PACKAGE: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) { + if (source_desc->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Object not a Package, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -154,7 +154,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_BUFFER: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { + if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -172,7 +172,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_STRING: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) { + if (source_desc->common.type != ACPI_TYPE_STRING) { ACPI_ERROR((AE_INFO, "Object not a String, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -186,7 +186,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_INTEGER: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) { + if (source_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "Object not a Integer, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index f6105a6d612..c93b54ce7f7 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -149,7 +149,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* This is a union acpi_operand_object */ - switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { + switch (stack_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: ref_type = stack_desc->reference.class; @@ -297,8 +297,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "FieldRead SourceDesc=%p Type=%X\n", - stack_desc, - ACPI_GET_OBJECT_TYPE(stack_desc))); + stack_desc, stack_desc->common.type)); status = acpi_ex_read_data_from_field(walk_state, stack_desc, @@ -386,7 +385,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, * specification of the object_type and size_of operators). This means * traversing the list of possibly many nested references. */ - while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { + while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.class) { case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_NAME: @@ -518,7 +517,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, * Now we are guaranteed to have an object that has not been created * via the ref_of or Index operators. */ - type = ACPI_GET_OBJECT_TYPE(obj_desc); + type = obj_desc->common.type; exit: /* Convert internal types to external types */ diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 3c3802764bf..5c729a9e913 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -212,7 +212,7 @@ acpi_ex_resolve_operands(u16 opcode, /* ACPI internal object */ - object_type = ACPI_GET_OBJECT_TYPE(obj_desc); + object_type = obj_desc->common.type; /* Check for bad acpi_object_type */ @@ -287,8 +287,7 @@ acpi_ex_resolve_operands(u16 opcode, if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_OBJECT_TYPE(obj_desc) == - ACPI_TYPE_STRING)) { + && (obj_desc->common.type == ACPI_TYPE_STRING)) { /* * String found - the string references a named object and * must be resolved to a node @@ -336,7 +335,7 @@ acpi_ex_resolve_operands(u16 opcode, * -- All others must be resolved below. */ if ((opcode == AML_STORE_OP) && - (ACPI_GET_OBJECT_TYPE(*stack_ptr) == + ((*stack_ptr)->common.type == ACPI_TYPE_LOCAL_REFERENCE) && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { goto next_operand; @@ -490,7 +489,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need an operand of type INTEGER, STRING or BUFFER */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -512,7 +511,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need an operand of type STRING or BUFFER */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -553,7 +552,7 @@ acpi_ex_resolve_operands(u16 opcode, * The only reference allowed here is a direct reference to * a namespace node. */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -576,7 +575,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need a buffer or package or (ACPI 2.0) String */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -598,7 +597,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_REGION: @@ -619,7 +618,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Used by the Store() operator only */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: @@ -677,8 +676,8 @@ acpi_ex_resolve_operands(u16 opcode, * required object type (Simple cases only). */ status = acpi_ex_check_object_type(type_needed, - ACPI_GET_OBJECT_TYPE - (*stack_ptr), *stack_ptr); + (*stack_ptr)->common.type, + *stack_ptr); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index e35e9b4f6a4..90d606196c9 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -129,7 +129,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: /* Output correct integer width */ @@ -324,7 +324,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, /* Destination object must be a Reference or a Constant object */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + switch (dest_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: break; @@ -460,9 +460,8 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, */ obj_desc = *(index_desc->reference.where); - if (ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE - && source_desc->reference.class == ACPI_REFCLASS_TABLE) { + if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE && + source_desc->reference.class == ACPI_REFCLASS_TABLE) { /* This is a DDBHandle, just add a reference to it */ @@ -520,8 +519,8 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * by the INDEX_OP code. */ obj_desc = index_desc->reference.object; - if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) { + if ((obj_desc->common.type != ACPI_TYPE_BUFFER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -529,7 +528,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * The assignment of the individual elements will be slightly * different for each source type. */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: /* Use the least-significant byte of the integer */ @@ -707,8 +706,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* No conversions for all other types. Just attach the source object */ status = acpi_ns_attach_object(node, source_desc, - ACPI_GET_OBJECT_TYPE - (source_desc)); + source_desc->common.type); break; } diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index 145d15305f7..608e838d537 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -96,8 +96,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * are all essentially the same. This case handles the * "interchangeable" types Integer, String, and Buffer. */ - if (ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE) { + if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { /* Resolve a reference object first */ @@ -117,13 +116,11 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, /* Must have a Integer, Buffer, or String */ - if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) && - (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && - !((ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE) - && (source_desc->reference.class == - ACPI_REFCLASS_TABLE))) { + if ((source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING) && + !((source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && + (source_desc->reference.class == ACPI_REFCLASS_TABLE))) { /* Conversion successful but still not a valid type */ @@ -218,8 +215,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } - if (ACPI_GET_OBJECT_TYPE(source_desc) != - ACPI_GET_OBJECT_TYPE(dest_desc)) { + if (source_desc->common.type != dest_desc->common.type) { /* * The source type does not match the type of the destination. * Perform the "implicit conversion" of the source to the current type @@ -229,11 +225,10 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, * Otherwise, actual_src_desc is a temporary object to hold the * converted object. */ - status = - acpi_ex_convert_to_target_type(ACPI_GET_OBJECT_TYPE - (dest_desc), source_desc, - &actual_src_desc, - walk_state); + status = acpi_ex_convert_to_target_type(dest_desc->common.type, + source_desc, + &actual_src_desc, + walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -252,7 +247,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, * We now have two objects of identical types, and we can perform a * copy of the *value* of the source object. */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + switch (dest_desc->common.type) { case ACPI_TYPE_INTEGER: dest_desc->integer.value = actual_src_desc->integer.value; diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 32b85d68e75..87730e94413 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -221,7 +221,7 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) */ if ((!obj_desc) || (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || - (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { + (obj_desc->common.type != ACPI_TYPE_INTEGER)) { return; } diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index a9d4fea4167..9af361a191e 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -86,7 +86,8 @@ acpi_status acpi_hw_set_mode(u32 mode) */ if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) { ACPI_ERROR((AE_INFO, - "No ACPI mode transition supported in this system (enable/disable both zero)")); + "No ACPI mode transition supported in this system " + "(enable/disable both zero)")); return_ACPI_STATUS(AE_OK); } @@ -95,7 +96,7 @@ acpi_status acpi_hw_set_mode(u32 mode) /* BIOS should have disabled ALL fixed and GP events */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, (u32) acpi_gbl_FADT.acpi_enable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable ACPI mode\n")); @@ -107,7 +108,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * BIOS should clear all fixed status bits and restore fixed event * enable bits to default */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, (u32) acpi_gbl_FADT.acpi_disable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -172,7 +173,7 @@ u32 acpi_hw_get_mode(void) return_UINT32(ACPI_SYS_MODE_ACPI); } - status = acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value); + status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); if (ACPI_FAILURE(status)) { return_UINT32(ACPI_SYS_MODE_LEGACY); } diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 2013b66745d..d3b7e37c9ee 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -89,10 +89,9 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) /* Clear just the bit that corresponds to this GPE */ - ACPI_CLEAR_BIT(enable_mask, - ((u32) 1 << - (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number))); + ACPI_CLEAR_BIT(enable_mask, ((u32)1 << + (gpe_event_info->gpe_number - + gpe_register_info->base_gpe_number))); /* Write the updated enable mask */ @@ -156,10 +155,9 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) ACPI_FUNCTION_ENTRY(); - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + register_bit = (u8)(1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); /* * Write a one to the appropriate bit in the status register to @@ -206,10 +204,9 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* Get the register bitmask for this GPE */ - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + register_bit = (u8)(1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); /* GPE currently enabled? (enabled for runtime?) */ diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 4dc43b01851..7b2fb602b5c 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -51,6 +51,17 @@ #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwregs") +/* Local Prototypes */ +static acpi_status +acpi_hw_read_multiple(u32 *value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b); + +static acpi_status +acpi_hw_write_multiple(u32 value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b); + /******************************************************************************* * * FUNCTION: acpi_hw_clear_acpi_status @@ -60,9 +71,9 @@ ACPI_MODULE_NAME("hwregs") * RETURN: Status * * DESCRIPTION: Clears all fixed and general purpose status bits - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ + acpi_status acpi_hw_clear_acpi_status(void) { acpi_status status; @@ -70,28 +81,20 @@ acpi_status acpi_hw_clear_acpi_status(void) ACPI_FUNCTION_TRACE(hw_clear_acpi_status); - ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", + ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %0llX\n", ACPI_BITMASK_ALL_FIXED_STATUS, - (u16) acpi_gbl_FADT.xpm1a_event_block.address)); + acpi_gbl_xpm1a_status.address)); lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + /* Clear the fixed events in PM1 A/B */ + status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, ACPI_BITMASK_ALL_FIXED_STATUS); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } - /* Clear the fixed events */ - - if (acpi_gbl_FADT.xpm1b_event_block.address) { - status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT.xpm1b_event_block); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - /* Clear the GPE Bits in all GPE registers in all GPE blocks */ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); @@ -128,6 +131,42 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) /****************************************************************************** * + * FUNCTION: acpi_hw_write_pm1_control + * + * PARAMETERS: pm1a_control - Value to be written to PM1A control + * pm1b_control - Value to be written to PM1B control + * + * RETURN: Status + * + * DESCRIPTION: Write the PM1 A/B control registers. These registers are + * different than than the PM1 A/B status and enable registers + * in that different values can be written to the A/B registers. + * Most notably, the SLP_TYP bits can be different, as per the + * values returned from the _Sx predefined methods. + * + ******************************************************************************/ + +acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_write_pm1_control); + + status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (acpi_gbl_FADT.xpm1b_control_block.address) { + status = + acpi_write(pm1b_control, + &acpi_gbl_FADT.xpm1b_control_block); + } + return_ACPI_STATUS(status); +} + +/****************************************************************************** + * * FUNCTION: acpi_hw_register_read * * PARAMETERS: register_id - ACPI Register ID @@ -141,64 +180,56 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) acpi_status acpi_hw_register_read(u32 register_id, u32 * return_value) { - u32 value1 = 0; - u32 value2 = 0; + u32 value = 0; acpi_status status; ACPI_FUNCTION_TRACE(hw_register_read); switch (register_id) { - case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - - status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ + case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ - status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block); - value1 |= value2; + status = acpi_hw_read_multiple(&value, + &acpi_gbl_xpm1a_status, + &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ - status = acpi_read(&value1, &acpi_gbl_xpm1a_enable); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_read(&value2, &acpi_gbl_xpm1b_enable); - value1 |= value2; + status = acpi_hw_read_multiple(&value, + &acpi_gbl_xpm1a_enable, + &acpi_gbl_xpm1b_enable); break; - case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ + case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block); - if (ACPI_FAILURE(status)) { - goto exit; - } + status = acpi_hw_read_multiple(&value, + &acpi_gbl_FADT. + xpm1a_control_block, + &acpi_gbl_FADT. + xpm1b_control_block); - status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block); - value1 |= value2; + /* + * Zero the write-only bits. From the ACPI specification, "Hardware + * Write-Only Bits": "Upon reads to registers with write-only bits, + * software masks out all write-only bits." + */ + value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block); + status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ status = - acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); + acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8); break; default: @@ -207,10 +238,8 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) break; } - exit: - if (ACPI_SUCCESS(status)) { - *return_value = value1; + *return_value = value; } return_ACPI_STATUS(status); @@ -250,52 +279,42 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) ACPI_FUNCTION_TRACE(hw_register_write); switch (register_id) { - case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - - /* Perform a read first to preserve certain bits (per ACPI spec) */ - - status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, - &read_value); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Insert the bits to be preserved */ - - ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS, - read_value); - - /* Now we can write the data */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ + case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ + /* + * Handle the "ignored" bit in PM1 Status. According to the ACPI + * specification, ignored bits are to be preserved when writing. + * Normally, this would mean a read/modify/write sequence. However, + * preserving a bit in the status register is different. Writing a + * one clears the status, and writing a zero preserves the status. + * Therefore, we must always write zero to the ignored bit. + * + * This behavior is clarified in the ACPI 4.0 specification. + */ + value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block); + status = acpi_hw_write_multiple(value, + &acpi_gbl_xpm1a_status, + &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access */ - status = acpi_write(value, &acpi_gbl_xpm1a_enable); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_write(value, &acpi_gbl_xpm1b_enable); + status = acpi_hw_write_multiple(value, + &acpi_gbl_xpm1a_enable, + &acpi_gbl_xpm1b_enable); break; - case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ + case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ /* * Perform a read first to preserve certain bits (per ACPI spec) + * Note: This includes SCI_EN, we never want to change this bit */ - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, - &read_value); + status = acpi_hw_read_multiple(&read_value, + &acpi_gbl_FADT. + xpm1a_control_block, + &acpi_gbl_FADT. + xpm1b_control_block); if (ACPI_FAILURE(status)) { goto exit; } @@ -307,25 +326,29 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) /* Now we can write the data */ - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); + status = acpi_hw_write_multiple(value, + &acpi_gbl_FADT. + xpm1a_control_block, + &acpi_gbl_FADT. + xpm1b_control_block); break; - case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); - break; + case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ + /* + * For control registers, all reserved bits must be preserved, + * as per the ACPI spec. + */ + status = + acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block); + if (ACPI_FAILURE(status)) { + goto exit; + } - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); - break; + /* Insert the bits to be preserved */ - case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ + ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, + read_value); status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); break; @@ -340,10 +363,11 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) /* SMI_CMD is currently always in IO space */ status = - acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); + acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8); break; default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); status = AE_BAD_PARAMETER; break; } @@ -351,3 +375,103 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) exit: return_ACPI_STATUS(status); } + +/****************************************************************************** + * + * FUNCTION: acpi_hw_read_multiple + * + * PARAMETERS: Value - Where the register value is returned + * register_a - First ACPI register (required) + * register_b - Second ACPI register (optional) + * + * RETURN: Status + * + * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) + * + ******************************************************************************/ + +static acpi_status +acpi_hw_read_multiple(u32 *value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b) +{ + u32 value_a = 0; + u32 value_b = 0; + acpi_status status; + + /* The first register is always required */ + + status = acpi_read(&value_a, register_a); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Second register is optional */ + + if (register_b->address) { + status = acpi_read(&value_b, register_b); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* + * OR the two return values together. No shifting or masking is necessary, + * because of how the PM1 registers are defined in the ACPI specification: + * + * "Although the bits can be split between the two register blocks (each + * register block has a unique pointer within the FADT), the bit positions + * are maintained. The register block with unimplemented bits (that is, + * those implemented in the other register block) always returns zeros, + * and writes have no side effects" + */ + *value = (value_a | value_b); + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_write_multiple + * + * PARAMETERS: Value - The value to write + * register_a - First ACPI register (required) + * register_b - Second ACPI register (optional) + * + * RETURN: Status + * + * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) + * + ******************************************************************************/ + +static acpi_status +acpi_hw_write_multiple(u32 value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b) +{ + acpi_status status; + + /* The first register is always required */ + + status = acpi_write(value, register_a); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Second register is optional + * + * No bit shifting or clearing is necessary, because of how the PM1 + * registers are defined in the ACPI specification: + * + * "Although the bits can be split between the two register blocks (each + * register block has a unique pointer within the FADT), the bit positions + * are maintained. The register block with unimplemented bits (that is, + * those implemented in the other register block) always returns zeros, + * and writes have no side effects" + */ + if (register_b->address) { + status = acpi_write(value, register_b); + } + + return (status); +} diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index a2af2a4f2f2..baa5fc05e12 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -90,6 +90,7 @@ acpi_set_firmware_waking_vector(u32 physical_address) ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) +#if ACPI_MACHINE_WIDTH == 64 /******************************************************************************* * * FUNCTION: acpi_set_firmware_waking_vector64 @@ -100,7 +101,8 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) * RETURN: Status * * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if - * it exists in the table. + * it exists in the table. This function is intended for use with + * 64-bit host operating systems. * ******************************************************************************/ acpi_status @@ -124,6 +126,7 @@ acpi_set_firmware_waking_vector64(u64 physical_address) } ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) +#endif /******************************************************************************* * @@ -147,9 +150,8 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); - /* - * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. - */ + /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ + status = acpi_get_sleep_type_data(sleep_state, &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b); @@ -223,8 +225,8 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) ******************************************************************************/ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) { - u32 PM1Acontrol; - u32 PM1Bcontrol; + u32 pm1a_control; + u32 pm1b_control; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 in_value; @@ -242,13 +244,14 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) } sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); /* Clear wake status */ - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + status = + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -289,24 +292,25 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Get current value of PM1A control */ - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, + &pm1a_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Entering sleep state [S%d]\n", sleep_state)); - /* Clear SLP_EN and SLP_TYP fields */ + /* Clear the SLP_EN and SLP_TYP fields */ - PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | - sleep_enable_reg_info->access_bit_mask); - PM1Bcontrol = PM1Acontrol; + pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info->access_bit_mask); + pm1b_control = pm1a_control; - /* Insert SLP_TYP bits */ + /* Insert the SLP_TYP bits */ - PM1Acontrol |= + pm1a_control |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); - PM1Bcontrol |= + pm1b_control |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); /* @@ -314,37 +318,25 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) * poorly implemented hardware. */ - /* Write #1: fill in SLP_TYP data */ + /* Write #1: write the SLP_TYP data to the PM1 Control registers */ - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); + status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Insert the sleep enable (SLP_EN) bit */ - /* Insert SLP_ENABLE bit */ + pm1a_control |= sleep_enable_reg_info->access_bit_mask; + pm1b_control |= sleep_enable_reg_info->access_bit_mask; - PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; - PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; - - /* Write #2: SLP_TYP + SLP_EN */ + /* Flush caches, as per ACPI specification */ ACPI_FLUSH_CPU_CACHE(); - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Write #2: Write both SLP_TYP + SLP_EN */ - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); + status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -357,8 +349,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) * Wait ten seconds, then try again. This is to get S4/S5 to work on * all machines. * - * We wait so long to allow chipsets that poll this reg very slowly to - * still read the right value. Ideally, this block would go + * We wait so long to allow chipsets that poll this reg very slowly + * to still read the right value. Ideally, this block would go * away entirely. */ acpi_os_stall(10000000); @@ -374,7 +366,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Wait until we enter sleep state */ do { - status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS, + status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -408,7 +400,10 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + /* Clear the wake status bit (PM1) */ + + status = + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -435,12 +430,13 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FLUSH_CPU_CACHE(); - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, (u32) acpi_gbl_FADT.S4bios_request, 8); do { acpi_os_stall(1000); - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); + status = + acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -471,8 +467,8 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) acpi_status status; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; - u32 PM1Acontrol; - u32 PM1Bcontrol; + u32 pm1a_control; + u32 pm1b_control; ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); @@ -486,38 +482,34 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) &acpi_gbl_sleep_type_b); if (ACPI_SUCCESS(status)) { sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, - &PM1Acontrol); + &pm1a_control); if (ACPI_SUCCESS(status)) { - /* Clear SLP_EN and SLP_TYP fields */ + /* Clear the SLP_EN and SLP_TYP fields */ - PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | - sleep_enable_reg_info-> - access_bit_mask); - PM1Bcontrol = PM1Acontrol; + pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info-> + access_bit_mask); + pm1b_control = pm1a_control; - /* Insert SLP_TYP bits */ + /* Insert the SLP_TYP bits */ - PM1Acontrol |= - (acpi_gbl_sleep_type_a << sleep_type_reg_info-> - bit_position); - PM1Bcontrol |= - (acpi_gbl_sleep_type_b << sleep_type_reg_info-> - bit_position); + pm1a_control |= (acpi_gbl_sleep_type_a << + sleep_type_reg_info->bit_position); + pm1b_control |= (acpi_gbl_sleep_type_b << + sleep_type_reg_info->bit_position); - /* Just ignore any errors */ + /* Write the control registers and ignore any errors */ - (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); + (void)acpi_hw_write_pm1_control(pm1a_control, + pm1b_control); } } @@ -603,19 +595,21 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) * it to determine whether the system is rebooting or resuming. Clear * it for compatibility. */ - acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ (void) - acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); + acpi_write_bit_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_POWER_BUTTON]. + enable_register_id, ACPI_ENABLE_EVENT); (void) - acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); + acpi_write_bit_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_POWER_BUTTON]. + status_register_id, ACPI_CLEAR_STATUS); arg.integer.value = ACPI_SST_WORKING; status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c new file mode 100644 index 00000000000..bd3c937b0ac --- /dev/null +++ b/drivers/acpi/acpica/hwvalid.c @@ -0,0 +1,258 @@ + +/****************************************************************************** + * + * Module Name: hwvalid - I/O request validation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2009, Intel Corp. + * 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 + * substantially 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. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * 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 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 <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwvalid") + +/* Local prototypes */ +static acpi_status +acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width); + +/* + * Protected I/O ports. Some ports are always illegal, and some are + * conditionally illegal. This table must remain ordered by port address. + * + * The table is used to implement the Microsoft port access rules that + * first appeared in Windows XP. Some ports are always illegal, and some + * ports are only illegal if the BIOS calls _OSI with a win_xP string or + * later (meaning that the BIOS itelf is post-XP.) + * + * This provides ACPICA with the desired port protections and + * Microsoft compatibility. + * + * Description of port entries: + * DMA: DMA controller + * PIC0: Programmable Interrupt Controller (8259_a) + * PIT1: System Timer 1 + * PIT2: System Timer 2 failsafe + * RTC: Real-time clock + * CMOS: Extended CMOS + * DMA1: DMA 1 page registers + * DMA1L: DMA 1 Ch 0 low page + * DMA2: DMA 2 page registers + * DMA2L: DMA 2 low page refresh + * ARBC: Arbitration control + * SETUP: Reserved system board setup + * POS: POS channel select + * PIC1: Cascaded PIC + * IDMA: ISA DMA + * ELCR: PIC edge/level registers + * PCI: PCI configuration space + */ +static const struct acpi_port_info acpi_protected_ports[] = { + {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, + {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL}, + {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP}, + {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP}, + {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP}, + {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP}, + {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP}, + {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, + {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP}, + {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, + {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, + {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, + {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP}, + {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, + {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, + {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, + {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP} +}; + +#define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (acpi_protected_ports) + +/****************************************************************************** + * + * FUNCTION: acpi_hw_validate_io_request + * + * PARAMETERS: Address Address of I/O port/register + * bit_width Number of bits (8,16,32) + * + * RETURN: Status + * + * DESCRIPTION: Validates an I/O request (address/length). Certain ports are + * always illegal and some ports are only illegal depending on + * the requests the BIOS AML code makes to the predefined + * _OSI method. + * + ******************************************************************************/ + +static acpi_status +acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) +{ + u32 i; + u32 byte_width; + acpi_io_address last_address; + const struct acpi_port_info *port_info; + + ACPI_FUNCTION_TRACE(hw_validate_io_request); + + /* Supported widths are 8/16/32 */ + + if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { + return AE_BAD_PARAMETER; + } + + port_info = acpi_protected_ports; + byte_width = ACPI_DIV_8(bit_width); + last_address = address + byte_width - 1; + + ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X", + ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, + last_address), + byte_width)); + + /* Maximum 16-bit address in I/O space */ + + if (last_address > ACPI_UINT16_MAX) { + ACPI_ERROR((AE_INFO, + "Illegal I/O port address/length above 64K: 0x%p/%X", + ACPI_CAST_PTR(void, address), byte_width)); + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + + /* Exit if requested address is not within the protected port table */ + + if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) { + return_ACPI_STATUS(AE_OK); + } + + /* Check request against the list of protected I/O ports */ + + for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) { + /* + * Check if the requested address range will write to a reserved + * port. Four cases to consider: + * + * 1) Address range is contained completely in the port address range + * 2) Address range overlaps port range at the port range start + * 3) Address range overlaps port range at the port range end + * 4) Address range completely encompasses the port range + */ + if ((address <= port_info->end) + && (last_address >= port_info->start)) { + + /* Port illegality may depend on the _OSI calls made by the BIOS */ + + if (acpi_gbl_osi_data >= port_info->osi_dependency) { + ACPI_ERROR((AE_INFO, + "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", + ACPI_CAST_PTR(void, address), + byte_width, port_info->name, + port_info->start, port_info->end)); + + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + } + + /* Finished if address range ends before the end of this port */ + + if (last_address <= port_info->end) { + break; + } + } + + return_ACPI_STATUS(AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_read_port + * + * PARAMETERS: Address Address of I/O port/register to read + * Value Where value is placed + * Width Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register. This is a front-end + * to acpi_os_read_port that performs validation on both the port + * address and the length. + * + *****************************************************************************/ + +acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) +{ + acpi_status status; + + status = acpi_hw_validate_io_request(address, width); + if (ACPI_FAILURE(status)) { + return status; + } + + status = acpi_os_read_port(address, value, width); + return status; +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_write_port + * + * PARAMETERS: Address Address of I/O port/register to write + * Value Value to write + * Width Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register. This is a front-end + * to acpi_os_write_port that performs validation on both the port + * address and the length. + * + *****************************************************************************/ + +acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) +{ + acpi_status status; + + status = acpi_hw_validate_io_request(address, width); + if (ACPI_FAILURE(status)) { + return status; + } + + status = acpi_os_write_port(address, value, width); + return status; +} diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index ae597c0ab53..9829979f2bd 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -107,19 +107,18 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) ACPI_FUNCTION_NAME(acpi_read); /* - * Must have a valid pointer to a GAS structure, and - * a non-zero address within. However, don't return an error - * because the PM1A/B code must not fail if B isn't present. + * Must have a valid pointer to a GAS structure, and a non-zero address + * within. */ if (!reg) { - return (AE_OK); + return (AE_BAD_PARAMETER); } /* Get a local copy of the address. Handles possible alignment issues */ ACPI_MOVE_64_TO_64(&address, ®->address); if (!address) { - return (AE_OK); + return (AE_BAD_ADDRESS); } /* Supported widths are 8/16/32 */ @@ -134,8 +133,8 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) *value = 0; /* - * Two address spaces supported: Memory or IO. - * PCI_Config is not supported here because the GAS struct is insufficient + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient */ switch (reg->space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: @@ -147,7 +146,7 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) case ACPI_ADR_SPACE_SYSTEM_IO: status = - acpi_os_read_port((acpi_io_address) address, value, width); + acpi_hw_read_port((acpi_io_address) address, value, width); break; default: @@ -187,19 +186,18 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) ACPI_FUNCTION_NAME(acpi_write); /* - * Must have a valid pointer to a GAS structure, and - * a non-zero address within. However, don't return an error - * because the PM1A/B code must not fail if B isn't present. + * Must have a valid pointer to a GAS structure, and a non-zero address + * within. */ if (!reg) { - return (AE_OK); + return (AE_BAD_PARAMETER); } /* Get a local copy of the address. Handles possible alignment issues */ ACPI_MOVE_64_TO_64(&address, ®->address); if (!address) { - return (AE_OK); + return (AE_BAD_ADDRESS); } /* Supported widths are 8/16/32 */ @@ -222,7 +220,7 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) case ACPI_ADR_SPACE_SYSTEM_IO: - status = acpi_os_write_port((acpi_io_address) address, value, + status = acpi_hw_write_port((acpi_io_address) address, value, width); break; @@ -244,24 +242,36 @@ ACPI_EXPORT_SYMBOL(acpi_write) /******************************************************************************* * - * FUNCTION: acpi_get_register_unlocked + * FUNCTION: acpi_read_bit_register * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * return_value - Value that was read from the register + * PARAMETERS: register_id - ID of ACPI Bit Register to access + * return_value - Value that was read from the register, + * normalized to bit position zero. * - * RETURN: Status and the value read from specified Register. Value + * RETURN: Status and the value read from the specified Register. Value * returned is normalized to bit0 (is shifted all the way right) * * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock. * + * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and + * PM2 Control. + * + * Note: The hardware lock is not required when reading the ACPI bit registers + * since almost all of them are single bit and it does not matter that + * the parent hardware register can be split across two physical + * registers. The only multi-bit field is SLP_TYP in the PM1 control + * register, but this field does not cross an 8-bit boundary (nor does + * it make much sense to actually read this field.) + * ******************************************************************************/ -acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) +acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) { - u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; + u32 register_value; + u32 value; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_get_register_unlocked); + ACPI_FUNCTION_TRACE_U32(acpi_read_bit_register, register_id); /* Get the info structure corresponding to the requested ACPI Register */ @@ -270,209 +280,133 @@ acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Read from the register */ + /* Read the entire parent register */ status = acpi_hw_register_read(bit_reg_info->parent_register, ®ister_value); - - if (ACPI_SUCCESS(status)) { - - /* Normalize the value that was read */ - - register_value = - ((register_value & bit_reg_info->access_bit_mask) - >> bit_reg_info->bit_position); - - *return_value = register_value; - - ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n", - register_value, - bit_reg_info->parent_register)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - return_ACPI_STATUS(status); -} + /* Normalize the value that was read, mask off other bits */ -ACPI_EXPORT_SYMBOL(acpi_get_register_unlocked) + value = ((register_value & bit_reg_info->access_bit_mask) + >> bit_reg_info->bit_position); -/******************************************************************************* - * - * FUNCTION: acpi_get_register - * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * return_value - Value that was read from the register - * - * RETURN: Status and the value read from specified Register. Value - * returned is normalized to bit0 (is shifted all the way right) - * - * DESCRIPTION: ACPI bit_register read function. - * - ******************************************************************************/ -acpi_status acpi_get_register(u32 register_id, u32 *return_value) -{ - acpi_status status; - acpi_cpu_flags flags; - - flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - status = acpi_get_register_unlocked(register_id, return_value); - acpi_os_release_lock(acpi_gbl_hardware_lock, flags); + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", + register_id, bit_reg_info->parent_register, + register_value, value)); - return (status); + *return_value = value; + return_ACPI_STATUS(AE_OK); } -ACPI_EXPORT_SYMBOL(acpi_get_register) +ACPI_EXPORT_SYMBOL(acpi_read_bit_register) /******************************************************************************* * - * FUNCTION: acpi_set_register + * FUNCTION: acpi_write_bit_register * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * Value - (only used on write) value to write to the - * Register, NOT pre-normalized to the bit pos + * PARAMETERS: register_id - ID of ACPI Bit Register to access + * Value - Value to write to the register, in bit + * position zero. The bit is automaticallly + * shifted to the correct position. * * RETURN: Status * - * DESCRIPTION: ACPI Bit Register write function. + * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock + * since most operations require a read/modify/write sequence. + * + * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and + * PM2 Control. + * + * Note that at this level, the fact that there may be actually two + * hardware registers (A and B - and B may not exist) is abstracted. * ******************************************************************************/ -acpi_status acpi_set_register(u32 register_id, u32 value) +acpi_status acpi_write_bit_register(u32 register_id, u32 value) { - u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; - acpi_status status; acpi_cpu_flags lock_flags; + u32 register_value; + acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); + ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id); /* Get the info structure corresponding to the requested ACPI Register */ bit_reg_info = acpi_hw_get_bit_register_info(register_id); if (!bit_reg_info) { - ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", - register_id)); return_ACPI_STATUS(AE_BAD_PARAMETER); } lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - /* Always do a register read first so we can insert the new bits */ - - status = acpi_hw_register_read(bit_reg_info->parent_register, - ®ister_value); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - /* - * Decode the Register ID - * Register ID = [Register block ID] | [bit ID] - * - * Check bit ID to fine locate Register offset. - * Check Mask to determine Register offset, and then read-write. + * At this point, we know that the parent register is one of the + * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control */ - switch (bit_reg_info->parent_register) { - case ACPI_REGISTER_PM1_STATUS: - + if (bit_reg_info->parent_register != ACPI_REGISTER_PM1_STATUS) { /* - * Status Registers are different from the rest. Clear by - * writing 1, and writing 0 has no effect. So, the only relevant - * information is the single bit we're interested in, all others should - * be written as 0 so they will be left unchanged. + * 1) Case for PM1 Enable, PM1 Control, and PM2 Control + * + * Perform a register read to preserve the bits that we are not + * interested in */ - value = ACPI_REGISTER_PREPARE_BITS(value, - bit_reg_info->bit_position, - bit_reg_info-> - access_bit_mask); - if (value) { - status = - acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, - (u16) value); - register_value = 0; - } - break; - - case ACPI_REGISTER_PM1_ENABLE: - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE, - (u16) register_value); - break; - - case ACPI_REGISTER_PM1_CONTROL: - - /* - * Write the PM1 Control register. - * Note that at this level, the fact that there are actually TWO - * registers (A and B - and B may not exist) is abstracted. - */ - ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n", - register_value)); - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, - (u16) register_value); - break; - - case ACPI_REGISTER_PM2_CONTROL: - - status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL, + status = acpi_hw_register_read(bit_reg_info->parent_register, ®ister_value); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "PM2 control: Read %X from %8.8X%8.8X\n", - register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); - + /* + * Insert the input bit into the value that was just read + * and write the register + */ ACPI_REGISTER_INSERT_VALUE(register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "About to write %4.4X to %8.8X%8.8X\n", - register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); + status = acpi_hw_register_write(bit_reg_info->parent_register, + register_value); + } else { + /* + * 2) Case for PM1 Status + * + * The Status register is different from the rest. Clear an event + * by writing 1, writing 0 has no effect. So, the only relevant + * information is the single bit we're interested in, all others + * should be written as 0 so they will be left unchanged. + */ + register_value = ACPI_REGISTER_PREPARE_BITS(value, + bit_reg_info-> + bit_position, + bit_reg_info-> + access_bit_mask); - status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL, - (u8) (register_value)); - break; + /* No need to write the register if value is all zeros */ - default: - break; + if (register_value) { + status = + acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, + register_value); + } } - unlock_and_exit: - - acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); - - /* Normalize the value that was read */ + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", + register_id, bit_reg_info->parent_register, value, + register_value)); - ACPI_DEBUG_EXEC(register_value = - ((register_value & bit_reg_info->access_bit_mask) >> - bit_reg_info->bit_position)); +unlock_and_exit: - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Set bits: %8.8X actual %8.8X register %X\n", value, - register_value, bit_reg_info->parent_register)); + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_set_register) +ACPI_EXPORT_SYMBOL(acpi_write_bit_register) /******************************************************************************* * @@ -534,7 +468,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) /* It must be of type Package */ - else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) { + else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; @@ -555,12 +489,13 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) /* The first two elements must both be of type Integer */ - else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0]) + else if (((info->return_object->package.elements[0])->common.type != ACPI_TYPE_INTEGER) || - (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1]) + ((info->return_object->package.elements[1])->common.type != ACPI_TYPE_INTEGER)) { ACPI_ERROR((AE_INFO, - "Sleep State return package elements are not both Integers (%s, %s)", + "Sleep State return package elements are not both Integers " + "(%s, %s)", acpi_ut_get_object_type_name(info->return_object-> package.elements[0]), acpi_ut_get_object_type_name(info->return_object-> diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 88303ebe924..9c3cdbe2d82 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -118,9 +118,8 @@ acpi_status acpi_ns_root_initialize(void) } /* - * Name entered successfully. - * If entry in pre_defined_names[] specifies an - * initial value, create the initial value. + * Name entered successfully. If entry in pre_defined_names[] specifies + * an initial value, create the initial value. */ if (init_val->val) { status = acpi_os_predefined_override(init_val, &val); @@ -178,9 +177,8 @@ acpi_status acpi_ns_root_initialize(void) case ACPI_TYPE_STRING: - /* - * Build an object around the static string - */ + /* Build an object around the static string */ + obj_desc->string.length = (u32) ACPI_STRLEN(val); obj_desc->string.pointer = val; @@ -234,8 +232,7 @@ acpi_status acpi_ns_root_initialize(void) /* Store pointer to value descriptor in the Node */ status = acpi_ns_attach_object(new_node, obj_desc, - ACPI_GET_OBJECT_TYPE - (obj_desc)); + obj_desc->common.type); /* Remove local reference to the object */ @@ -315,10 +312,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(AE_NO_NAMESPACE); } - /* - * Get the prefix scope. - * A null scope means use the root scope - */ + /* Get the prefix scope. A null scope means use the root scope */ + if ((!scope_info) || (!scope_info->scope.node)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", @@ -338,8 +333,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { /* * This node might not be a actual "scope" node (such as a - * Device/Method, etc.) It could be a Package or other object node. - * Backup up the tree to find the containing scope node. + * Device/Method, etc.) It could be a Package or other object + * node. Backup up the tree to find the containing scope node. */ while (!acpi_ns_opens_scope(prefix_node->type) && prefix_node->type != ACPI_TYPE_ANY) { @@ -349,7 +344,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, } } - /* Save type TBD: may be no longer necessary */ + /* Save type. TBD: may be no longer necessary */ type_to_check_for = type; @@ -414,6 +409,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Name is fully qualified, no search rules apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; + /* * Point past this prefix to the name segment * part or the next Parent Prefix @@ -429,7 +425,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, - "ACPI path has too many parent prefixes (^) - reached beyond root node")); + "ACPI path has too many parent prefixes (^) " + "- reached beyond root node")); return_ACPI_STATUS(AE_NOT_FOUND); } } @@ -531,9 +528,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, while (num_segments && current_node) { num_segments--; if (!num_segments) { - /* - * This is the last segment, enable typechecking - */ + + /* This is the last segment, enable typechecking */ + this_search_type = type; /* @@ -584,9 +581,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, if (num_segments > 0) { /* * If we have an alias to an object that opens a scope (such as a - * device or processor), we need to dereference the alias here so that - * we can access any children of the original node (via the remaining - * segments). + * device or processor), we need to dereference the alias here so + * that we can access any children of the original node (via the + * remaining segments). */ if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { if (!this_node->object) { @@ -594,8 +591,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, } if (acpi_ns_opens_scope - (((struct acpi_namespace_node *)this_node-> - object)->type)) { + (((struct acpi_namespace_node *) + this_node->object)->type)) { this_node = (struct acpi_namespace_node *) this_node->object; @@ -639,8 +636,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* * If this is the last name segment and we are not looking for a - * specific type, but the type of found object is known, use that type - * to (later) see if it opens a scope. + * specific type, but the type of found object is known, use that + * type to (later) see if it opens a scope. */ if (type == ACPI_TYPE_ANY) { type = this_node->type; @@ -653,9 +650,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, current_node = this_node; } - /* - * Always check if we need to open a new scope - */ + /* Always check if we need to open a new scope */ + if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) { /* * If entry is a type which opens a scope, push the new scope on the diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index f976d848fe8..aceb9311196 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -76,8 +76,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); #ifdef ACPI_DBG_TRACK_ALLOCATIONS - temp = - acpi_gbl_ns_node_list->total_allocated - + temp = acpi_gbl_ns_node_list->total_allocated - acpi_gbl_ns_node_list->total_freed; if (temp > acpi_gbl_ns_node_list->max_occupied) { acpi_gbl_ns_node_list->max_occupied = temp; @@ -145,9 +144,8 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); - /* - * Detach an object if there is one, then delete the node - */ + /* Detach an object if there is one, then delete the node */ + acpi_ns_detach_object(node); (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); return_VOID; @@ -183,9 +181,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp ACPI_FUNCTION_TRACE(ns_install_node); /* - * Get the owner ID from the Walk state - * The owner ID is used to track table deletion and - * deletion of objects created by methods + * Get the owner ID from the Walk state. The owner ID is used to track + * table deletion and deletion of objects created by methods. */ if (walk_state) { owner_id = walk_state->owner_id; @@ -260,9 +257,8 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) return_VOID; } - /* - * Deallocate all children at this level - */ + /* Deallocate all children at this level */ + do { /* Get the things we need */ @@ -285,9 +281,8 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) "Object %p, Remaining %X\n", child_node, acpi_gbl_current_node_count)); - /* - * Detach an object if there is one, then free the child node - */ + /* Detach an object if there is one, then free the child node */ + acpi_ns_detach_object(child_node); /* Now we can delete the node */ @@ -304,7 +299,6 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) /* Clear the parent's child pointer */ parent_node->child = NULL; - return_VOID; } diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 0da33c8e9ba..2bad613db73 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -181,6 +181,12 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, } this_node = acpi_ns_map_handle_to_node(obj_handle); + if (!this_node) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n", + obj_handle)); + return (AE_OK); + } + type = this_node->type; /* Check if the owner matches */ @@ -214,9 +220,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); } - /* - * Now we can print out the pertinent information - */ + /* Now we can print out the pertinent information */ + acpi_os_printf(" %-12s %p %2.2X ", acpi_ut_get_type_name(type), this_node, this_node->owner_id); @@ -509,7 +514,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, case ACPI_DESC_TYPE_OPERAND: - obj_type = ACPI_GET_OBJECT_TYPE(obj_desc); + obj_type = obj_desc->common.type; if (obj_type > ACPI_TYPE_LOCAL_MAX) { acpi_os_printf @@ -539,9 +544,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, goto cleanup; } - /* - * Valid object, get the pointer to next level, if any - */ + /* Valid object, get the pointer to next level, if any */ + switch (obj_type) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: @@ -602,14 +606,14 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, * display_type - 0 or ACPI_DISPLAY_SUMMARY * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX * for an effectively unlimited depth. - * owner_id - Dump only objects owned by this ID. Use + * owner_id - Dump only objects owned by this ID. Use * ACPI_UINT32_MAX to match all owners. * start_handle - Where in namespace to start/end search * * RETURN: None * - * DESCRIPTION: Dump typed objects within the loaded namespace. - * Uses acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object. + * DESCRIPTION: Dump typed objects within the loaded namespace. Uses + * acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 0f3d5f9b596..8e7dec1176c 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -155,7 +155,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) } - ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", + ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 13501cb8186..2adfcf329e1 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -103,7 +103,8 @@ acpi_status acpi_ns_initialize_objects(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n", + "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd " + "Buffers %hd/%hd Packages (%hd nodes)\n", info.op_region_init, info.op_region_count, info.field_init, info.field_count, info.buffer_init, info.buffer_count, @@ -148,7 +149,8 @@ acpi_status acpi_ns_initialize_devices(void) info.num_INI = 0; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Initializing Device/Processor/Thermal objects by executing _INI methods:")); + "Initializing Device/Processor/Thermal objects " + "by executing _INI methods:")); /* Tree analysis: find all subtrees that contain _INI methods */ @@ -180,7 +182,8 @@ acpi_status acpi_ns_initialize_devices(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n", + "\nExecuted %hd _INI methods requiring %hd _STA executions " + "(examined %hd objects)\n", info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); @@ -263,16 +266,14 @@ acpi_ns_init_one_object(acpi_handle obj_handle, return (AE_OK); } - /* - * If the object is already initialized, nothing else to do - */ + /* If the object is already initialized, nothing else to do */ + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } - /* - * Must lock the interpreter before executing AML code - */ + /* Must lock the interpreter before executing AML code */ + acpi_ex_enter_interpreter(); /* diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index a0ba9e12379..dcd7a6adbbb 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -128,12 +128,12 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) * parse trees. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Begin Table Method Parsing and Object Initialization ****\n")); + "**** Begin Table Method Parsing and Object Initialization\n")); status = acpi_ds_initialize_objects(table_index, node); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Completed Table Method Parsing and Object Initialization ****\n")); + "**** Completed Table Method Parsing and Object Initialization\n")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index 08a97a57f8f..3eb20bfda9d 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -209,8 +209,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) obj_desc = node->object; - if (!obj_desc || - (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) { + if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { return_VOID; } @@ -220,8 +219,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { node->object = obj_desc->common.next_object; if (node->object && - (ACPI_GET_OBJECT_TYPE(node->object) != - ACPI_TYPE_LOCAL_DATA)) { + ((node->object)->common.type != ACPI_TYPE_LOCAL_DATA)) { node->object = node->object->common.next_object; } } @@ -267,7 +265,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) && (ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_NAMED)) - || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) { + || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) { return_PTR(NULL); } @@ -294,9 +292,9 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); if ((!obj_desc) || - (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) || + (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) || (!obj_desc->common.next_object) || - (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) == + ((obj_desc->common.next_object)->common.type == ACPI_TYPE_LOCAL_DATA)) { return_PTR(NULL); } @@ -331,7 +329,7 @@ acpi_ns_attach_data(struct acpi_namespace_node *node, prev_obj_desc = NULL; obj_desc = node->object; while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && (obj_desc->data.handler == handler)) { return (AE_ALREADY_EXISTS); } @@ -385,7 +383,7 @@ acpi_ns_detach_data(struct acpi_namespace_node * node, prev_obj_desc = NULL; obj_desc = node->object; while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && (obj_desc->data.handler == handler)) { if (prev_obj_desc) { prev_obj_desc->common.next_object = @@ -428,7 +426,7 @@ acpi_ns_get_attached_data(struct acpi_namespace_node * node, obj_desc = node->object; while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && (obj_desc->data.handler == handler)) { *data = obj_desc->data.pointer; return (AE_OK); diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index b9e8d0070b6..662a4bd5b62 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -176,9 +176,8 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) * performs another complete parse of the AML. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); - status = - acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, - start_node); + status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, + table_index, start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -193,9 +192,8 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) * parse objects are all cached. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); - status = - acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, - start_node); + status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, + table_index, start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 452703290d3..d9e8cbc6e67 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -79,7 +79,9 @@ acpi_ns_check_package(char *pathname, static acpi_status acpi_ns_check_package_elements(char *pathname, union acpi_operand_object **elements, - u8 type1, u32 count1, u8 type2, u32 count2); + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index); static acpi_status acpi_ns_check_object_type(char *pathname, @@ -221,7 +223,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, /* For returned Package objects, check the type of all sub-objects */ - if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { + if (return_object->common.type == ACPI_TYPE_PACKAGE) { status = acpi_ns_check_package(pathname, return_object_ptr, predefined); @@ -302,7 +304,8 @@ acpi_ns_check_parameter_count(char *pathname, if ((user_param_count != required_params_current) && (user_param_count != required_params_old)) { ACPI_WARNING((AE_INFO, - "%s: Parameter count mismatch - caller passed %d, ACPI requires %d", + "%s: Parameter count mismatch - " + "caller passed %d, ACPI requires %d", pathname, user_param_count, required_params_current)); } @@ -472,7 +475,7 @@ acpi_ns_check_package(char *pathname, package->ret_info. object_type2, package->ret_info. - count2); + count2, 0); if (ACPI_FAILURE(status)) { return (status); } @@ -623,7 +626,7 @@ acpi_ns_check_package(char *pathname, object_type2, package-> ret_info. - count2); + count2, 0); if (ACPI_FAILURE(status)) { return (status); } @@ -672,7 +675,8 @@ acpi_ns_check_package(char *pathname, object_type1, sub_package-> package. - count, 0, 0); + count, 0, 0, + 0); if (ACPI_FAILURE(status)) { return (status); } @@ -710,7 +714,8 @@ acpi_ns_check_package(char *pathname, ret_info. object_type1, (expected_count - - 1), 0, 0); + - 1), 0, 0, + 1); if (ACPI_FAILURE(status)) { return (status); } @@ -758,6 +763,7 @@ acpi_ns_check_package(char *pathname, * Count1 - Count for first group * Type2 - Object type for second group * Count2 - Count for second group + * start_index - Start of the first group of elements * * RETURN: Status * @@ -769,7 +775,9 @@ acpi_ns_check_package(char *pathname, static acpi_status acpi_ns_check_package_elements(char *pathname, union acpi_operand_object **elements, - u8 type1, u32 count1, u8 type2, u32 count2) + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index) { union acpi_operand_object **this_element = elements; acpi_status status; @@ -782,7 +790,7 @@ acpi_ns_check_package_elements(char *pathname, */ for (i = 0; i < count1; i++) { status = acpi_ns_check_object_type(pathname, this_element, - type1, i); + type1, i + start_index); if (ACPI_FAILURE(status)) { return (status); } @@ -791,7 +799,8 @@ acpi_ns_check_package_elements(char *pathname, for (i = 0; i < count2; i++) { status = acpi_ns_check_object_type(pathname, this_element, - type2, (i + count1)); + type2, + (i + count1 + start_index)); if (ACPI_FAILURE(status)) { return (status); } @@ -858,7 +867,7 @@ acpi_ns_check_object_type(char *pathname, * from all of the predefined names (including elements of returned * packages) */ - switch (ACPI_GET_OBJECT_TYPE(return_object)) { + switch (return_object->common.type) { case ACPI_TYPE_INTEGER: return_btype = ACPI_RTYPE_INTEGER; break; @@ -901,7 +910,7 @@ acpi_ns_check_object_type(char *pathname, /* For reference objects, check that the reference type is correct */ - if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { + if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { status = acpi_ns_check_reference(pathname, return_object); } @@ -974,7 +983,8 @@ acpi_ns_check_reference(char *pathname, } ACPI_WARNING((AE_INFO, - "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", + "%s: Return type mismatch - " + "unexpected reference object type [%s] %2.2X", pathname, acpi_ut_get_reference_name(return_object), return_object->reference.class)); @@ -1006,7 +1016,7 @@ acpi_ns_repair_object(u32 expected_btypes, union acpi_operand_object *new_object; acpi_size length; - switch (ACPI_GET_OBJECT_TYPE(return_object)) { + switch (return_object->common.type) { case ACPI_TYPE_BUFFER: if (!(expected_btypes & ACPI_RTYPE_STRING)) { diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 6fea13f3f52..f9b4f51bf8f 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -167,7 +167,8 @@ acpi_ns_search_one_scope(u32 target_name, /* Searched entire namespace level, not found */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", + "Name [%4.4s] (%s) not found in search in scope [%4.4s] " + "%p first child %p\n", ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type), acpi_ut_get_node_name(parent_node), parent_node, @@ -239,9 +240,8 @@ acpi_ns_search_parent_tree(u32 target_name, acpi_ut_get_node_name(parent_node), ACPI_CAST_PTR(char, &target_name))); - /* - * Search parents until target is found or we have backed up to the root - */ + /* Search parents until target is found or we have backed up to the root */ + while (parent_node) { /* * Search parent scope. Use TYPE_ANY because we don't care about the @@ -395,9 +395,9 @@ acpi_ns_search_and_enter(u32 target_name, return_ACPI_STATUS(AE_NO_MEMORY); } #ifdef ACPI_ASL_COMPILER - /* - * Node is an object defined by an External() statement - */ + + /* Node is an object defined by an External() statement */ + if (flags & ACPI_NS_EXTERNAL) { new_node->flags |= ANOBJ_IS_EXTERNAL; } diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 3e1149bf4aa..78277ed0833 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -325,9 +325,8 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) next_external_char++; } } else { - /* - * Handle Carat prefixes - */ + /* Handle Carat prefixes */ + while (*next_external_char == '^') { info->num_carats++; next_external_char++; @@ -552,9 +551,8 @@ acpi_ns_externalize_name(u32 internal_name_length, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* - * Check for a prefix (one '\' | one or more '^'). - */ + /* Check for a prefix (one '\' | one or more '^') */ + switch (internal_name[0]) { case '\\': prefix_length = 1; @@ -580,7 +578,7 @@ acpi_ns_externalize_name(u32 internal_name_length, } /* - * Check for object names. Note that there could be 0-255 of these + * Check for object names. Note that there could be 0-255 of these * 4-byte elements. */ if (prefix_length < internal_name_length) { @@ -637,9 +635,8 @@ acpi_ns_externalize_name(u32 internal_name_length, return_ACPI_STATUS(AE_BAD_PATHNAME); } - /* - * Build converted_name - */ + /* Build the converted_name */ + *converted_name = ACPI_ALLOCATE_ZEROED(required_length); if (!(*converted_name)) { return_ACPI_STATUS(AE_NO_MEMORY); @@ -685,6 +682,9 @@ acpi_ns_externalize_name(u32 internal_name_length, * and keep all pointers within this subsystem - however this introduces * more (and perhaps unnecessary) overhead. * + * The current implemenation is basically a placeholder until such time comes + * that it is needed. + * ******************************************************************************/ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) @@ -692,9 +692,8 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) ACPI_FUNCTION_ENTRY(); - /* - * Simple implementation - */ + /* Parameter validation */ + if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { return (acpi_gbl_root_node); } @@ -872,7 +871,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, return_node); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n", pathname, acpi_format_exception(status))); } diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 200895fa272..83e3aa6d4b9 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -135,8 +135,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct * starting (and ending) at the node specified by start_handle. * The user_function is called whenever a node that matches * the type parameter is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. + * a non-zero value, the search is terminated immediately and + * this value is returned to the caller. * * The point of this procedure is to provide a generic namespace * walk routine that can be called from multiple places to @@ -200,10 +200,10 @@ acpi_ns_walk_namespace(acpi_object_type type, /* * Ignore all temporary namespace nodes (created during control * method execution) unless told otherwise. These temporary nodes - * can cause a race condition because they can be deleted during the - * execution of the user function (if the namespace is unlocked before - * invocation of the user function.) Only the debugger namespace dump - * will examine the temporary nodes. + * can cause a race condition because they can be deleted during + * the execution of the user function (if the namespace is + * unlocked before invocation of the user function.) Only the + * debugger namespace dump will examine the temporary nodes. */ if ((child_node->flags & ANOBJ_TEMPORARY) && !(flags & ACPI_NS_WALK_TEMP_NODES)) { diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 22a7171ac1e..045054037c2 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -387,8 +387,7 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) /* We are interested in reference objects only */ - if (ACPI_GET_OBJECT_TYPE(info->return_object) != - ACPI_TYPE_LOCAL_REFERENCE) { + if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) { return; } @@ -476,21 +475,40 @@ acpi_walk_namespace(acpi_object_type type, } /* - * Lock the namespace around the walk. - * The namespace will be unlocked/locked around each call - * to the user function - since this function - * must be allowed to make Acpi calls itself. + * Need to acquire the namespace reader lock to prevent interference + * with any concurrent table unloads (which causes the deletion of + * namespace objects). We cannot allow the deletion of a namespace node + * while the user function is using it. The exception to this are the + * nodes created and deleted during control method execution -- these + * nodes are marked as temporary nodes and are ignored by the namespace + * walk. Thus, control methods can be executed while holding the + * namespace deletion lock (and the user function can execute control + * methods.) + */ + status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock); + if (ACPI_FAILURE(status)) { + return status; + } + + /* + * Lock the namespace around the walk. The namespace will be + * unlocked/locked around each call to the user function - since the user + * function must be allowed to make ACPICA calls itself (for example, it + * will typically execute control methods during device enumeration.) */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto unlock_and_exit; } status = acpi_ns_walk_namespace(type, start_object, max_depth, - ACPI_NS_WALK_UNLOCK, - user_function, context, return_value); + ACPI_NS_WALK_UNLOCK, user_function, + context, return_value); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + unlock_and_exit: + (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 52865ee6bc7..b6667ff059e 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -557,9 +557,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, table_index++) { if (*sub_object_list && /* Null object allowed */ ((ACPI_TYPE_STRING == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) || + (*sub_object_list)->common.type) || ((ACPI_TYPE_LOCAL_REFERENCE == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) && + (*sub_object_list)->common.type) && ((*sub_object_list)->reference.class == ACPI_REFCLASS_NAME)))) { name_found = TRUE; @@ -575,8 +575,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, /* Was a String type found? */ if (name_found) { - if (ACPI_GET_OBJECT_TYPE(*sub_object_list) == - ACPI_TYPE_STRING) { + if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) { /* * The length String.Length field does not include the * terminating NULL, add 1 diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 61566b1a061..663f692fffc 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -212,7 +212,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* Each element of the top-level package must also be a package */ - if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) { + if ((*top_object_list)->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "(PRT[%X]) Need sub-package, found %s", index, @@ -240,7 +240,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 1) First subobject: Dereference the PRT.Address */ obj_desc = sub_object_list[0]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].Address) Need Integer, found %s", index, @@ -253,7 +253,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 2) Second subobject: Dereference the PRT.Pin */ obj_desc = sub_object_list[1]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].Pin) Need Integer, found %s", index, @@ -265,7 +265,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * If BIOS erroneously reversed the _PRT source_name and source_index, * then reverse them back. */ - if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) != + if ((sub_object_list[3])->common.type != ACPI_TYPE_INTEGER) { if (acpi_gbl_enable_interpreter_slack) { source_name_index = 3; @@ -291,8 +291,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * other ACPI implementations. */ obj_desc = sub_object_list[3]; - if (!obj_desc - || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { + if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { sub_object_list[3] = sub_object_list[2]; sub_object_list[2] = obj_desc; @@ -307,7 +306,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, */ obj_desc = sub_object_list[source_name_index]; if (obj_desc) { - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: if (obj_desc->reference.class != @@ -380,7 +379,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ obj_desc = sub_object_list[source_index_index]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].SourceIndex) Need Integer, found %s", index, diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 3636e4f8fb7..71e655d14cb 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -57,6 +57,8 @@ static void acpi_tb_convert_fadt(void); static void acpi_tb_validate_fadt(void); +static void acpi_tb_setup_fadt_registers(void); + /* Table for conversion of FADT to common internal format and FADT validation */ typedef struct acpi_fadt_info { @@ -130,7 +132,38 @@ static struct acpi_fadt_info fadt_info_table[] = { ACPI_FADT_SEPARATE_LENGTH} }; -#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) +#define ACPI_FADT_INFO_ENTRIES \ + (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) + +/* Table used to split Event Blocks into separate status/enable registers */ + +typedef struct acpi_fadt_pm_info { + struct acpi_generic_address *target; + u8 source; + u8 register_num; + +} acpi_fadt_pm_info; + +static struct acpi_fadt_pm_info fadt_pm_info_table[] = { + {&acpi_gbl_xpm1a_status, + ACPI_FADT_OFFSET(xpm1a_event_block), + 0}, + + {&acpi_gbl_xpm1a_enable, + ACPI_FADT_OFFSET(xpm1a_event_block), + 1}, + + {&acpi_gbl_xpm1b_status, + ACPI_FADT_OFFSET(xpm1b_event_block), + 0}, + + {&acpi_gbl_xpm1b_enable, + ACPI_FADT_OFFSET(xpm1b_event_block), + 1} +}; + +#define ACPI_FADT_PM_INFO_ENTRIES \ + (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info)) /******************************************************************************* * @@ -172,7 +205,6 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, * FUNCTION: acpi_tb_parse_fadt * * PARAMETERS: table_index - Index for the FADT - * Flags - Flags * * RETURN: None * @@ -181,7 +213,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, * ******************************************************************************/ -void acpi_tb_parse_fadt(u32 table_index, u8 flags) +void acpi_tb_parse_fadt(u32 table_index) { u32 length; struct acpi_table_header *table; @@ -208,7 +240,7 @@ void acpi_tb_parse_fadt(u32 table_index, u8 flags) */ (void)acpi_tb_verify_checksum(table, length); - /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ + /* Create a local copy of the FADT in common ACPI 2.0+ format */ acpi_tb_create_local_fadt(table, length); @@ -219,10 +251,10 @@ void acpi_tb_parse_fadt(u32 table_index, u8 flags) /* Obtain the DSDT and FACS tables via their addresses within the FADT */ acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, - flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); + ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); } /******************************************************************************* @@ -266,11 +298,17 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) ACPI_MEMCPY(&acpi_gbl_FADT, table, ACPI_MIN(length, sizeof(struct acpi_table_fadt))); - /* - * 1) Convert the local copy of the FADT to the common internal format - * 2) Validate some of the important values within the FADT - */ + /* Convert the local copy of the FADT to the common internal format */ + acpi_tb_convert_fadt(); + + /* Validate FADT values now, before we make any changes */ + + acpi_tb_validate_fadt(); + + /* Initialize the global ACPI register structures */ + + acpi_tb_setup_fadt_registers(); } /******************************************************************************* @@ -282,31 +320,35 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) * RETURN: None * * DESCRIPTION: Converts all versions of the FADT to a common internal format. - * Expand all 32-bit addresses to 64-bit. + * Expand 32-bit addresses to 64-bit as necessary. * * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), * and must contain a copy of the actual FADT. * - * ACPICA will use the "X" fields of the FADT for all addresses. + * Notes on 64-bit register addresses: + * + * After this FADT conversion, later ACPICA code will only use the 64-bit "X" + * fields of the FADT for all ACPI register addresses. * - * "X" fields are optional extensions to the original V1.0 fields. Even if - * they are present in the structure, they can be optionally not used by - * setting them to zero. Therefore, we must selectively expand V1.0 fields - * if the corresponding X field is zero. + * The 64-bit "X" fields are optional extensions to the original 32-bit FADT + * V1.0 fields. Even if they are present in the FADT, they are optional and + * are unused if the BIOS sets them to zero. Therefore, we must copy/expand + * 32-bit V1.0 fields if the corresponding X field is zero. * - * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding - * "X" fields. + * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the + * corresponding "X" fields in the internal FADT. * - * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by - * expanding the corresponding ACPI 1.0 field. + * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded + * to the corresponding 64-bit X fields. For compatibility with other ACPI + * implementations, we ignore the 64-bit field if the 32-bit field is valid, + * regardless of whether the host OS is 32-bit or 64-bit. * ******************************************************************************/ static void acpi_tb_convert_fadt(void) { - u8 pm1_register_bit_width; - u8 pm1_register_byte_width; - struct acpi_generic_address *target64; + struct acpi_generic_address *address64; + u32 address32; u32 i; /* Update the local FADT table header length */ @@ -355,140 +397,56 @@ static void acpi_tb_convert_fadt(void) * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. Later code will always use * the 64-bit address structures. + * + * March 2009: + * We now always use the 32-bit address if it is valid (non-null). This + * is not in accordance with the ACPI specification which states that + * the 64-bit address supersedes the 32-bit version, but we do this for + * compatibility with other ACPI implementations. Most notably, in the + * case where both the 32 and 64 versions are non-null, we use the 32-bit + * version. This is the only address that is guaranteed to have been + * tested by the BIOS manufacturer. */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target64 = - ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, - fadt_info_table[i].address64); + address32 = *ACPI_ADD_PTR(u32, + &acpi_gbl_FADT, + fadt_info_table[i].address32); - /* Expand only if the 64-bit X target is null */ + address64 = ACPI_ADD_PTR(struct acpi_generic_address, + &acpi_gbl_FADT, + fadt_info_table[i].address64); - if (!target64->address) { + /* + * If both 32- and 64-bit addresses are valid (non-zero), + * they must match. + */ + if (address64->address && address32 && + (address64->address != (u64) address32)) { + ACPI_ERROR((AE_INFO, + "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 32", + fadt_info_table[i].name, address32, + ACPI_FORMAT_UINT64(address64->address))); + } - /* The space_id is always I/O for the 32-bit legacy address fields */ + /* Always use 32-bit address if it is valid (non-null) */ - acpi_tb_init_generic_address(target64, + if (address32) { + /* + * Copy the 32-bit address to the 64-bit GAS structure. The + * Space ID is always I/O for 32-bit legacy address fields + */ + acpi_tb_init_generic_address(address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, fadt_info_table [i].length), - (u64) * ACPI_ADD_PTR(u32, - &acpi_gbl_FADT, - fadt_info_table - [i]. - address32)); - } - } - - /* Validate FADT values now, before we make any changes */ - - acpi_tb_validate_fadt(); - - /* - * Optionally check all register lengths against the default values and - * update them if they are incorrect. - */ - if (acpi_gbl_use_default_register_widths) { - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target64 = - ACPI_ADD_PTR(struct acpi_generic_address, - &acpi_gbl_FADT, - fadt_info_table[i].address64); - - /* - * If a valid register (Address != 0) and the (default_length > 0) - * (Not a GPE register), then check the width against the default. - */ - if ((target64->address) && - (fadt_info_table[i].default_length > 0) && - (fadt_info_table[i].default_length != - target64->bit_width)) { - ACPI_WARNING((AE_INFO, - "Invalid length for %s: %d, using default %d", - fadt_info_table[i].name, - target64->bit_width, - fadt_info_table[i]. - default_length)); - - /* Incorrect size, set width to the default */ - - target64->bit_width = - fadt_info_table[i].default_length; - } + address32); } } - - /* - * Get the length of the individual PM1 registers (enable and status). - * Each register is defined to be (event block length / 2). - */ - pm1_register_bit_width = - (u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width); - pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width); - - /* - * Adjust the lengths of the PM1 Event Blocks so that they can be used to - * access the PM1 status register(s). Use (width / 2) - */ - acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width; - acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width; - - /* - * Calculate separate GAS structs for the PM1 Enable registers. - * These addresses do not appear (directly) in the FADT, so it is - * useful to calculate them once, here. - * - * The PM event blocks are split into two register blocks, first is the - * PM Status Register block, followed immediately by the PM Enable - * Register block. Each is of length (xpm1x_event_block.bit_width/2). - * - * On various systems the v2 fields (and particularly the bit widths) - * cannot be relied upon, though. Hence resort to using the v1 length - * here (and warn about the inconsistency). - */ - if (acpi_gbl_FADT.xpm1a_event_block.bit_width - != acpi_gbl_FADT.pm1_event_length * 8) - printk(KERN_WARNING "FADT: " - "X_PM1a_EVT_BLK.bit_width (%u) does not match" - " PM1_EVT_LEN (%u)\n", - acpi_gbl_FADT.xpm1a_event_block.bit_width, - acpi_gbl_FADT.pm1_event_length); - - /* The PM1A register block is required */ - - acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, - acpi_gbl_FADT.xpm1a_event_block.space_id, - pm1_register_byte_width, - (acpi_gbl_FADT.xpm1a_event_block.address + - pm1_register_byte_width)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1a_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; - - /* The PM1B register block is optional, ignore if not present */ - - if (acpi_gbl_FADT.xpm1b_event_block.address) { - if (acpi_gbl_FADT.xpm1b_event_block.bit_width - != acpi_gbl_FADT.pm1_event_length * 8) - printk(KERN_WARNING "FADT: " - "X_PM1b_EVT_BLK.bit_width (%u) does not match" - " PM1_EVT_LEN (%u)\n", - acpi_gbl_FADT.xpm1b_event_block.bit_width, - acpi_gbl_FADT.pm1_event_length); - acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, - acpi_gbl_FADT.xpm1b_event_block.space_id, - pm1_register_byte_width, - (acpi_gbl_FADT.xpm1b_event_block. - address + pm1_register_byte_width)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1b_event_block.space_id; - - } } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_tb_validate_fadt * @@ -525,18 +483,22 @@ static void acpi_tb_validate_fadt(void) (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { ACPI_WARNING((AE_INFO, "32/64X FACS address mismatch in FADT - " - "two FACS tables! %8.8X/%8.8X%8.8X", + "%8.8X/%8.8X%8.8X, using 32", acpi_gbl_FADT.facs, ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs))); + + acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; } if (acpi_gbl_FADT.dsdt && (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { ACPI_WARNING((AE_INFO, "32/64X DSDT address mismatch in FADT - " - "two DSDT tables! %8.8X/%8.8X%8.8X", + "%8.8X/%8.8X%8.8X, using 32", acpi_gbl_FADT.dsdt, ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt))); + + acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; } /* Examine all of the 64-bit extended address fields (X fields) */ @@ -561,7 +523,8 @@ static void acpi_tb_validate_fadt(void) * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. */ - if (address64 && (address64->bit_width != ACPI_MUL_8(length))) { + if (address64->address && + (address64->bit_width != ACPI_MUL_8(length))) { ACPI_WARNING((AE_INFO, "32/64X length mismatch in %s: %d/%d", name, ACPI_MUL_8(length), @@ -575,7 +538,8 @@ static void acpi_tb_validate_fadt(void) */ if (!address64->address || !length) { ACPI_ERROR((AE_INFO, - "Required field %s has zero address and/or length: %8.8X%8.8X/%X", + "Required field %s has zero address and/or length:" + " %8.8X%8.8X/%X", name, ACPI_FORMAT_UINT64(address64-> address), @@ -584,27 +548,112 @@ static void acpi_tb_validate_fadt(void) } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (PM2Control, GPE0, GPE1) AND has its own - * length field. If present, both the address and length must be valid. + * length field. If present, both the address and length must + * be valid. */ - if ((address64->address && !length) - || (!address64->address && length)) { + if ((address64->address && !length) || + (!address64->address && length)) { ACPI_WARNING((AE_INFO, - "Optional field %s has zero address or length: %8.8X%8.8X/%X", + "Optional field %s has zero address or length: " + "%8.8X%8.8X/%X", name, ACPI_FORMAT_UINT64(address64-> address), length)); } } + } +} - /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ +/******************************************************************************* + * + * FUNCTION: acpi_tb_setup_fadt_registers + * + * PARAMETERS: None, uses acpi_gbl_FADT. + * + * RETURN: None + * + * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally, + * force FADT register definitions to their default lengths. + * + ******************************************************************************/ - if (address64->address && *address32 && - (address64->address != (u64) * address32)) { - ACPI_ERROR((AE_INFO, - "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 64X", - name, *address32, - ACPI_FORMAT_UINT64(address64->address))); +static void acpi_tb_setup_fadt_registers(void) +{ + struct acpi_generic_address *target64; + struct acpi_generic_address *source64; + u8 pm1_register_byte_width; + u32 i; + + /* + * Optionally check all register lengths against the default values and + * update them if they are incorrect. + */ + if (acpi_gbl_use_default_register_widths) { + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { + target64 = + ACPI_ADD_PTR(struct acpi_generic_address, + &acpi_gbl_FADT, + fadt_info_table[i].address64); + + /* + * If a valid register (Address != 0) and the (default_length > 0) + * (Not a GPE register), then check the width against the default. + */ + if ((target64->address) && + (fadt_info_table[i].default_length > 0) && + (fadt_info_table[i].default_length != + target64->bit_width)) { + ACPI_WARNING((AE_INFO, + "Invalid length for %s: %d, using default %d", + fadt_info_table[i].name, + target64->bit_width, + fadt_info_table[i]. + default_length)); + + /* Incorrect size, set width to the default */ + + target64->bit_width = + fadt_info_table[i].default_length; + } + } + } + + /* + * Get the length of the individual PM1 registers (enable and status). + * Each register is defined to be (event block length / 2). Extra divide + * by 8 converts bits to bytes. + */ + pm1_register_byte_width = (u8) + ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width); + + /* + * Calculate separate GAS structs for the PM1x (A/B) Status and Enable + * registers. These addresses do not appear (directly) in the FADT, so it + * is useful to pre-calculate them from the PM1 Event Block definitions. + * + * The PM event blocks are split into two register blocks, first is the + * PM Status Register block, followed immediately by the PM Enable + * Register block. Each is of length (pm1_event_length/2) + * + * Note: The PM1A event block is required by the ACPI specification. + * However, the PM1B event block is optional and is rarely, if ever, + * used. + */ + + for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) { + source64 = + ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, + fadt_pm_info_table[i].source); + + if (source64->address) { + acpi_tb_init_generic_address(fadt_pm_info_table[i]. + target, source64->space_id, + pm1_register_byte_width, + source64->address + + (fadt_pm_info_table[i]. + register_num * + pm1_register_byte_width)); } } } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 37374b21969..f865d5a096d 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -103,7 +103,9 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) * * RETURN: Status * - * DESCRIPTION: This function is called to add the ACPI table + * DESCRIPTION: This function is called to add an ACPI table. It is used to + * dynamically load tables via the Load and load_table AML + * operators. * ******************************************************************************/ @@ -112,6 +114,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; acpi_status status = AE_OK; + struct acpi_table_header *override_table = NULL; ACPI_FUNCTION_TRACE(tb_add_table); @@ -201,6 +204,29 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } } + /* + * ACPI Table Override: + * Allow the host to override dynamically loaded tables. + */ + status = acpi_os_table_override(table_desc->pointer, &override_table); + if (ACPI_SUCCESS(status) && override_table) { + ACPI_INFO((AE_INFO, + "%4.4s @ 0x%p Table override, replaced with:", + table_desc->pointer->signature, + ACPI_CAST_PTR(void, table_desc->address))); + + /* We can delete the table that was passed as a parameter */ + + acpi_tb_delete_table(table_desc); + + /* Setup descriptor for the new table */ + + table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table); + table_desc->pointer = override_table; + table_desc->length = override_table->length; + table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE; + } + /* Add the table to the global root table list */ status = acpi_tb_store_table(table_desc->address, table_desc->pointer, @@ -247,8 +273,9 @@ acpi_status acpi_tb_resize_root_table_list(void) /* Increase the Table Array size */ tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. - size + ACPI_ROOT_TABLE_SIZE_INCREMENT) - * sizeof(struct acpi_table_desc)); + size + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * + sizeof(struct acpi_table_desc)); if (!tables) { ACPI_ERROR((AE_INFO, "Could not allocate new root table array")); @@ -407,27 +434,56 @@ void acpi_tb_terminate(void) * * PARAMETERS: table_index - Table index * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Delete all namespace objects created when this table was loaded. * ******************************************************************************/ -void acpi_tb_delete_namespace_by_owner(u32 table_index) +acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) { acpi_owner_id owner_id; + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); + + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (table_index >= acpi_gbl_root_table_list.count) { + + /* The table index does not exist */ - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - } else { (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return; + return_ACPI_STATUS(AE_NOT_EXIST); } + /* Get the owner ID for this table, used to delete namespace nodes */ + + owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + /* + * Need to acquire the namespace writer lock to prevent interference + * with any concurrent namespace walks. The interpreter must be + * released during the deletion since the acquisition of the deletion + * lock may block, and also since the execution of a namespace walk + * must be allowed to use the interpreter. + */ + acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); + acpi_ns_delete_namespace_by_owner(owner_id); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -535,8 +591,8 @@ u8 acpi_tb_is_table_loaded(u32 table_index) (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); if (table_index < acpi_gbl_root_table_list.count) { is_loaded = (u8) - (acpi_gbl_root_table_list.tables[table_index]. - flags & ACPI_TABLE_IS_LOADED); + (acpi_gbl_root_table_list.tables[table_index].flags & + ACPI_TABLE_IS_LOADED); } (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 22ce4898572..ef7d2c2d8f0 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -177,19 +177,23 @@ acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header *header) { + /* + * The reason that the Address is cast to a void pointer is so that we + * can use %p which will work properly on both 32-bit and 64-bit hosts. + */ if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { - /* FACS only has signature and length fields of common table header */ + /* FACS only has signature and length fields */ - ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", - header->signature, (unsigned long)address, + ACPI_INFO((AE_INFO, "%4.4s %p %05X", + header->signature, ACPI_CAST_PTR(void, address), header->length)); } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { /* RSDP has no common fields */ - ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", - (unsigned long)address, + ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", + ACPI_CAST_PTR (void, address), (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> revision > 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, @@ -202,8 +206,8 @@ acpi_tb_print_table_header(acpi_physical_address address, /* Standard ACPI table with full common header */ ACPI_INFO((AE_INFO, - "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", - header->signature, (unsigned long)address, + "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", + header->signature, ACPI_CAST_PTR (void, address), header->length, header->revision, header->oem_id, header->oem_table_id, header->oem_revision, header->asl_compiler_id, @@ -280,22 +284,28 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) * FUNCTION: acpi_tb_install_table * * PARAMETERS: Address - Physical address of DSDT or FACS - * Flags - Flags * Signature - Table signature, NULL if no need to * match * table_index - Index into root table array * * RETURN: None * - * DESCRIPTION: Install an ACPI table into the global data structure. + * DESCRIPTION: Install an ACPI table into the global data structure. The + * table override mechanism is implemented here to allow the host + * OS to replace any table before it is installed in the root + * table array. * ******************************************************************************/ void acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index) + char *signature, u32 table_index) { - struct acpi_table_header *table; + u8 flags; + acpi_status status; + struct acpi_table_header *table_to_install; + struct acpi_table_header *mapped_table; + struct acpi_table_header *override_table = NULL; if (!address) { ACPI_ERROR((AE_INFO, @@ -306,41 +316,69 @@ acpi_tb_install_table(acpi_physical_address address, /* Map just the table header */ - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) { + mapped_table = + acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!mapped_table) { return; } - /* If a particular signature is expected, signature must match */ + /* If a particular signature is expected (DSDT/FACS), it must match */ - if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { + if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { ACPI_ERROR((AE_INFO, - "Invalid signature 0x%X for ACPI table [%s]", - *ACPI_CAST_PTR(u32, table->signature), signature)); + "Invalid signature 0x%X for ACPI table, expected [%s]", + *ACPI_CAST_PTR(u32, mapped_table->signature), + signature)); goto unmap_and_exit; } + /* + * ACPI Table Override: + * + * Before we install the table, let the host OS override it with a new + * one if desired. Any table within the RSDT/XSDT can be replaced, + * including the DSDT which is pointed to by the FADT. + */ + status = acpi_os_table_override(mapped_table, &override_table); + if (ACPI_SUCCESS(status) && override_table) { + ACPI_INFO((AE_INFO, + "%4.4s @ 0x%p Table override, replaced with:", + mapped_table->signature, ACPI_CAST_PTR(void, + address))); + + acpi_gbl_root_table_list.tables[table_index].pointer = + override_table; + address = ACPI_PTR_TO_PHYSADDR(override_table); + + table_to_install = override_table; + flags = ACPI_TABLE_ORIGIN_OVERRIDE; + } else { + table_to_install = mapped_table; + flags = ACPI_TABLE_ORIGIN_MAPPED; + } + /* Initialize the table entry */ acpi_gbl_root_table_list.tables[table_index].address = address; - acpi_gbl_root_table_list.tables[table_index].length = table->length; + acpi_gbl_root_table_list.tables[table_index].length = + table_to_install->length; acpi_gbl_root_table_list.tables[table_index].flags = flags; ACPI_MOVE_32_TO_32(& (acpi_gbl_root_table_list.tables[table_index]. - signature), table->signature); + signature), table_to_install->signature); - acpi_tb_print_table_header(address, table); + acpi_tb_print_table_header(address, table_to_install); if (table_index == ACPI_TABLE_INDEX_DSDT) { /* Global integer width is based upon revision of the DSDT */ - acpi_ut_set_integer_width(table->revision); + acpi_ut_set_integer_width(table_to_install->revision); } unmap_and_exit: - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); } /******************************************************************************* @@ -379,7 +417,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) } else { /* * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return - * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit + * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, + * return 64-bit */ ACPI_MOVE_64_TO_64(&address64, table_entry); @@ -389,7 +428,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) /* Will truncate 64-bit address to 32 bits, issue warning */ ACPI_WARNING((AE_INFO, - "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", + "64-bit Physical Address in XSDT is too large (%8.8X%8.8X)," + " truncating", ACPI_FORMAT_UINT64(address64))); } #endif @@ -402,7 +442,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * FUNCTION: acpi_tb_parse_root_table * * PARAMETERS: Rsdp - Pointer to the RSDP - * Flags - Flags * * RETURN: Status * @@ -416,7 +455,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) ******************************************************************************/ acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) +acpi_tb_parse_root_table(acpi_physical_address rsdp_address) { struct acpi_table_rsdp *rsdp; u32 table_entry_size; @@ -513,13 +552,12 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) /* Calculate the number of tables described in the root table */ - table_count = - (u32) ((table->length - - sizeof(struct acpi_table_header)) / table_entry_size); - + table_count = (u32)((table->length - sizeof(struct acpi_table_header)) / + table_entry_size); /* - * First two entries in the table array are reserved for the DSDT and FACS, - * which are not actually present in the RSDT/XSDT - they come from the FADT + * First two entries in the table array are reserved for the DSDT + * and FACS, which are not actually present in the RSDT/XSDT - they + * come from the FADT */ table_entry = ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); @@ -567,14 +605,14 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) */ for (i = 2; i < acpi_gbl_root_table_list.count; i++) { acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. - address, flags, NULL, i); + address, NULL, i); /* Special case for FADT - get the DSDT and FACS */ if (ACPI_COMPARE_NAME (&acpi_gbl_root_table_list.tables[i].signature, ACPI_SIG_FADT)) { - acpi_tb_parse_fadt(i, flags); + acpi_tb_parse_fadt(i); } } diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index c3e841f3cde..dbca2265150 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -150,8 +150,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, * Root Table Array. This array contains the information of the RSDT/XSDT * in a common, more useable format. */ - status = - acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); + status = acpi_tb_parse_root_table(rsdp_address); return_ACPI_STATUS(status); } @@ -247,7 +246,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) ACPI_EXPORT_SYMBOL(acpi_load_table) -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_get_table_header * @@ -262,7 +261,7 @@ ACPI_EXPORT_SYMBOL(acpi_load_table) * NOTE: Caller is responsible in unmapping the header with * acpi_os_unmap_memory * - *****************************************************************************/ + ******************************************************************************/ acpi_status acpi_get_table_header(char *signature, u32 instance, struct acpi_table_header *out_table_header) @@ -277,9 +276,8 @@ acpi_get_table_header(char *signature, return (AE_BAD_PARAMETER); } - /* - * Walk the root table list - */ + /* Walk the root table list */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { if (!ACPI_COMPARE_NAME (&(acpi_gbl_root_table_list.tables[i].signature), @@ -292,8 +290,8 @@ acpi_get_table_header(char *signature, } if (!acpi_gbl_root_table_list.tables[i].pointer) { - if ((acpi_gbl_root_table_list.tables[i]. - flags & ACPI_TABLE_ORIGIN_MASK) == + if ((acpi_gbl_root_table_list.tables[i].flags & + ACPI_TABLE_ORIGIN_MASK) == ACPI_TABLE_ORIGIN_MAPPED) { header = acpi_os_map_memory(acpi_gbl_root_table_list. @@ -324,7 +322,7 @@ acpi_get_table_header(char *signature, ACPI_EXPORT_SYMBOL(acpi_get_table_header) -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_unload_table_id * @@ -375,7 +373,7 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) * * DESCRIPTION: Finds and verifies an ACPI table. * - *****************************************************************************/ + ******************************************************************************/ acpi_status acpi_get_table(char *signature, u32 instance, struct acpi_table_header **out_table) @@ -390,9 +388,8 @@ acpi_get_table(char *signature, return (AE_BAD_PARAMETER); } - /* - * Walk the root table list - */ + /* Walk the root table list */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { if (!ACPI_COMPARE_NAME (&(acpi_gbl_root_table_list.tables[i].signature), @@ -491,7 +488,6 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) static acpi_status acpi_tb_load_namespace(void) { acpi_status status; - struct acpi_table_header *table; u32 i; ACPI_FUNCTION_TRACE(tb_load_namespace); @@ -515,58 +511,28 @@ static acpi_status acpi_tb_load_namespace(void) goto unlock_and_exit; } - /* - * Find DSDT table - */ - status = - acpi_os_table_override(acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].pointer, - &table); - if (ACPI_SUCCESS(status) && table) { - /* - * DSDT table has been found - */ - acpi_tb_delete_table(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]); - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = - table; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = - table->length; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = - ACPI_TABLE_ORIGIN_UNKNOWN; - - ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); - acpi_tb_print_table_header(0, table); - - if (no_auto_ssdt == 0) { - printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); - } - } + /* A valid DSDT is required */ status = acpi_tb_verify_table(&acpi_gbl_root_table_list. tables[ACPI_TABLE_INDEX_DSDT]); if (ACPI_FAILURE(status)) { - /* A valid DSDT is required */ - status = AE_NO_ACPI_TABLES; goto unlock_and_exit; } (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - /* - * Load and parse tables. - */ + /* Load and parse tables */ + status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* - * Load any SSDT or PSDT tables. Note: Loop leaves tables locked - */ + /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { if ((!ACPI_COMPARE_NAME @@ -619,9 +585,8 @@ acpi_status acpi_load_tables(void) ACPI_FUNCTION_TRACE(acpi_load_tables); - /* - * Load the namespace from the tables - */ + /* Load the namespace from the tables */ + status = acpi_tb_load_namespace(); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index b7fc8dd4334..85ea834199e 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -75,8 +75,8 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ - if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) - != 0) { + if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, + sizeof(ACPI_SIG_RSDP) - 1) != 0) { /* Nope, BAD Signature */ diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index b0dcfd3c872..919624f123d 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -135,11 +135,11 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, * In general, the external object will be the same type as * the internal object */ - external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); + external_object->type = internal_object->common.type; /* However, only a limited number of external types are supported */ - switch (ACPI_GET_OBJECT_TYPE(internal_object)) { + switch (internal_object->common.type) { case ACPI_TYPE_STRING: external_object->string.pointer = (char *)data_space; @@ -222,8 +222,8 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, */ ACPI_ERROR((AE_INFO, "Unsupported object type, cannot convert to external object: %s", - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE - (internal_object)))); + acpi_ut_get_type_name(internal_object->common. + type))); return_ACPI_STATUS(AE_SUPPORT); } @@ -355,7 +355,7 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, info.object_space = 0; info.num_packages = 1; - external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); + external_object->type = internal_object->common.type; external_object->package.count = internal_object->package.count; external_object->package.elements = ACPI_CAST_PTR(union acpi_object, info.free_space); @@ -399,7 +399,7 @@ acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); - if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) { + if (internal_object->common.type == ACPI_TYPE_PACKAGE) { /* * Package object: Copy all subobjects (including * nested packages) @@ -496,8 +496,9 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_STRING: internal_object->string.pointer = - ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string. - length + 1); + ACPI_ALLOCATE_ZEROED((acpi_size) + external_object->string.length + 1); + if (!internal_object->string.pointer) { goto error_exit; } @@ -697,7 +698,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, /* Handle the objects with extra data */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + switch (dest_desc->common.type) { case ACPI_TYPE_BUFFER: /* * Allocate and copy the actual buffer if and only if: @@ -814,8 +815,8 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, * This is a simple object, just copy it */ target_object = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE - (source_object)); + acpi_ut_create_internal_object(source_object-> + common.type); if (!target_object) { return (AE_NO_MEMORY); } @@ -892,7 +893,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); - dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj); + dest_obj->common.type = source_obj->common.type; dest_obj->common.flags = source_obj->common.flags; dest_obj->package.count = source_obj->package.count; @@ -950,15 +951,14 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, /* Create the top level object */ - *dest_desc = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc)); + *dest_desc = acpi_ut_create_internal_object(source_desc->common.type); if (!*dest_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Copy the object and possible subobjects */ - if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) { + if (source_desc->common.type == ACPI_TYPE_PACKAGE) { status = acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc, walk_state); diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index a0be9e39531..a5ee23bc4f5 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -86,7 +86,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) * Must delete or free any pointers within the object that are not * actual ACPI objects (for example, a raw buffer pointer). */ - switch (ACPI_GET_OBJECT_TYPE(object)) { + switch (object->common.type) { case ACPI_TYPE_STRING: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -382,7 +382,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) object, new_count)); } - if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) { + if (object->common.type == ACPI_TYPE_METHOD) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Method Obj %p Refs=%X, [Decremented]\n", object, new_count)); @@ -469,7 +469,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) * All sub-objects must have their reference count incremented also. * Different object types have different subobjects. */ - switch (ACPI_GET_OBJECT_TYPE(object)) { + switch (object->common.type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 9c9897dbe90..006b16c2601 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -59,26 +59,35 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, /* * Strings supported by the _OSI predefined (internal) method. + * + * March 2009: Removed "Linux" as this host no longer wants to respond true + * for this string. Basically, the only safe OS strings are windows-related + * and in many or most cases represent the only test path within the + * BIOS-provided ASL code. + * + * The second element of each entry is used to track the newest version of + * Windows that the BIOS has requested. */ -static char *acpi_interfaces_supported[] = { +static struct acpi_interface_info acpi_interfaces_supported[] = { /* Operating System Vendor Strings */ - "Windows 2000", /* Windows 2000 */ - "Windows 2001", /* Windows XP */ - "Windows 2001 SP1", /* Windows XP SP1 */ - "Windows 2001 SP2", /* Windows XP SP2 */ - "Windows 2001.1", /* Windows Server 2003 */ - "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ - "Windows 2006", /* Windows Vista - Added 03/2006 */ + {"Windows 2000", ACPI_OSI_WIN_2000}, /* Windows 2000 */ + {"Windows 2001", ACPI_OSI_WIN_XP}, /* Windows XP */ + {"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ + {"Windows 2001.1", ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ + {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ + {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ + {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ /* Feature Group Strings */ - "Extended Address Space Descriptor" - /* - * All "optional" feature group strings (features that are implemented - * by the host) should be implemented in the host version of - * acpi_os_validate_interface and should not be added here. - */ + {"Extended Address Space Descriptor", 0} + + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be implemented in the host version of + * acpi_os_validate_interface and should not be added here. + */ }; /******************************************************************************* @@ -98,6 +107,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) acpi_status status; union acpi_operand_object *string_desc; union acpi_operand_object *return_desc; + u32 return_value; u32 i; ACPI_FUNCTION_TRACE(ut_osi_implementation); @@ -116,19 +126,28 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) return_ACPI_STATUS(AE_NO_MEMORY); } - /* Default return value is 0, NOT-SUPPORTED */ + /* Default return value is 0, NOT SUPPORTED */ - return_desc->integer.value = 0; - walk_state->return_desc = return_desc; + return_value = 0; /* Compare input string to static table of supported interfaces */ for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { - if (!ACPI_STRCMP - (string_desc->string.pointer, - acpi_interfaces_supported[i])) { - return_desc->integer.value = ACPI_UINT32_MAX; - goto done; + if (!ACPI_STRCMP(string_desc->string.pointer, + acpi_interfaces_supported[i].name)) { + /* + * The interface is supported. + * Update the osi_data if necessary. We keep track of the latest + * version of Windows that has been requested by the BIOS. + */ + if (acpi_interfaces_supported[i].value > + acpi_gbl_osi_data) { + acpi_gbl_osi_data = + acpi_interfaces_supported[i].value; + } + + return_value = ACPI_UINT32_MAX; + goto exit; } } @@ -139,15 +158,22 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) */ status = acpi_os_validate_interface(string_desc->string.pointer); if (ACPI_SUCCESS(status)) { - return_desc->integer.value = ACPI_UINT32_MAX; + + /* The interface is supported */ + + return_value = ACPI_UINT32_MAX; } -done: - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, "ACPI: BIOS _OSI(%s) %ssupported\n", - string_desc->string.pointer, - return_desc->integer.value == 0 ? "not-" : "")); +exit: + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + "ACPI: BIOS _OSI(%s) is %ssupported\n", + string_desc->string.pointer, return_value == 0 ? "not " : "")); - return_ACPI_STATUS(AE_OK); + /* Complete the return value */ + + return_desc->integer.value = return_value; + walk_state->return_desc = return_desc; + return_ACPI_STATUS (AE_OK); } /******************************************************************************* @@ -167,8 +193,8 @@ acpi_status acpi_osi_invalidate(char *interface) int i; for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { - if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) { - *acpi_interfaces_supported[i] = '\0'; + if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) { + *acpi_interfaces_supported[i].name = '\0'; return AE_OK; } } @@ -248,7 +274,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, /* Map the return object type to the bitmapped type */ - switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { + switch ((info->return_object)->common.type) { case ACPI_TYPE_INTEGER: return_btype = ACPI_BTYPE_INTEGER; break; @@ -418,7 +444,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, return_ACPI_STATUS(status); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Convert the Numeric HID to string */ @@ -459,7 +485,7 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, struct acpi_compatible_id *one_cid) { - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: /* Convert the Numeric CID to string */ @@ -527,7 +553,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, /* Get the number of _CIDs returned */ count = 1; - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { count = obj_desc->package.count; } @@ -555,7 +581,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, /* The _CID object can be either a single CID or a package (list) of CIDs */ - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { /* Translate each package element */ @@ -620,7 +646,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, return_ACPI_STATUS(status); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Convert the Numeric UID to string */ diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index a3ab9d9da29..59e46f257c0 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -294,12 +294,9 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = { /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE}, - /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_TYPE_X, - ACPI_BITMASK_SLEEP_TYPE_X}, - /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_TYPE_X, - ACPI_BITMASK_SLEEP_TYPE_X}, + /* ACPI_BITREG_SLEEP_TYPE */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_SLEEP_TYPE, + ACPI_BITMASK_SLEEP_TYPE}, /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE}, @@ -476,7 +473,7 @@ char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) return ("[NULL Object Descriptor]"); } - return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc))); + return (acpi_ut_get_type_name(obj_desc->common.type)); } /******************************************************************************* @@ -749,7 +746,10 @@ acpi_status acpi_ut_init_globals(void) for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { acpi_gbl_owner_id_mask[i] = 0; } - acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */ + + /* Last owner_iD is never valid */ + + acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* GPE support */ @@ -789,6 +789,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_trace_dbg_layer = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; + acpi_gbl_osi_data = 0; /* Hardware oriented */ diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c new file mode 100644 index 00000000000..25e03120686 --- /dev/null +++ b/drivers/acpi/acpica/utlock.c @@ -0,0 +1,175 @@ +/****************************************************************************** + * + * Module Name: utlock - Reader/Writer lock interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2009, Intel Corp. + * 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 + * substantially 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. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * 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 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 <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utlock") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_rw_lock + * acpi_ut_delete_rw_lock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader/writer lock creation and deletion interfaces. + * + ******************************************************************************/ +acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + lock->num_readers = 0; + status = acpi_os_create_mutex(&lock->reader_mutex); + if (ACPI_FAILURE(status)) { + return status; + } + + status = acpi_os_create_mutex(&lock->writer_mutex); + return status; +} + +void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock) +{ + + acpi_os_delete_mutex(lock->reader_mutex); + acpi_os_delete_mutex(lock->writer_mutex); + + lock->num_readers = 0; + lock->reader_mutex = NULL; + lock->writer_mutex = NULL; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_acquire_read_lock + * acpi_ut_release_read_lock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition, + * only the first reader acquires the write mutex. On release, + * only the last reader releases the write mutex. Although this + * algorithm can in theory starve writers, this should not be a + * problem with ACPICA since the subsystem is infrequently used + * in comparison to (for example) an I/O system. + * + ******************************************************************************/ + +acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return status; + } + + /* Acquire the write lock only for the first reader */ + + lock->num_readers++; + if (lock->num_readers == 1) { + status = + acpi_os_acquire_mutex(lock->writer_mutex, + ACPI_WAIT_FOREVER); + } + + acpi_os_release_mutex(lock->reader_mutex); + return status; +} + +acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return status; + } + + /* Release the write lock only for the very last reader */ + + lock->num_readers--; + if (lock->num_readers == 0) { + acpi_os_release_mutex(lock->writer_mutex); + } + + acpi_os_release_mutex(lock->reader_mutex); + return status; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_acquire_write_lock + * acpi_ut_release_write_lock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or + * release the writer mutex associated with the lock. Acquisition + * of the lock is fully exclusive and will block all readers and + * writers until it is released. + * + ******************************************************************************/ + +acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER); + return status; +} + +void acpi_ut_release_write_lock(struct acpi_rw_lock *lock) +{ + + acpi_os_release_mutex(lock->writer_mutex); +} diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index c1f7f4e1a72..1c9e250caef 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -938,8 +938,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, if ((!this_source_obj) || (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) != ACPI_DESC_TYPE_OPERAND) - || (ACPI_GET_OBJECT_TYPE(this_source_obj) != - ACPI_TYPE_PACKAGE)) { + || (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) { status = walk_callback(ACPI_COPY_TYPE_SIMPLE, this_source_obj, state, context); diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 14eb52c4d64..26c93a748e6 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -60,7 +60,8 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id); * * RETURN: Status * - * DESCRIPTION: Create the system mutex objects. + * DESCRIPTION: Create the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. * ******************************************************************************/ @@ -71,9 +72,8 @@ acpi_status acpi_ut_mutex_initialize(void) ACPI_FUNCTION_TRACE(ut_mutex_initialize); - /* - * Create each of the predefined mutex objects - */ + /* Create each of the predefined mutex objects */ + for (i = 0; i < ACPI_NUM_MUTEX; i++) { status = acpi_ut_create_mutex(i); if (ACPI_FAILURE(status)) { @@ -86,6 +86,9 @@ acpi_status acpi_ut_mutex_initialize(void) spin_lock_init(acpi_gbl_gpe_lock); spin_lock_init(acpi_gbl_hardware_lock); + /* Create the reader/writer lock for namespace access */ + + status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } @@ -97,7 +100,8 @@ acpi_status acpi_ut_mutex_initialize(void) * * RETURN: None. * - * DESCRIPTION: Delete all of the system mutex objects. + * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. * ******************************************************************************/ @@ -107,9 +111,8 @@ void acpi_ut_mutex_terminate(void) ACPI_FUNCTION_TRACE(ut_mutex_terminate); - /* - * Delete each predefined mutex object - */ + /* Delete each predefined mutex object */ + for (i = 0; i < ACPI_NUM_MUTEX; i++) { (void)acpi_ut_delete_mutex(i); } @@ -118,6 +121,10 @@ void acpi_ut_mutex_terminate(void) acpi_os_delete_lock(acpi_gbl_gpe_lock); acpi_os_delete_lock(acpi_gbl_hardware_lock); + + /* Delete the reader/writer lock */ + + acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock); return_VOID; } diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index fd5ea7543e5..0207b625274 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -310,7 +310,7 @@ u8 acpi_ut_valid_internal_object(void *object) /* Check for a null pointer */ if (!object) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Null Object Ptr\n")); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "**** Null Object Ptr\n")); return (FALSE); } @@ -324,7 +324,7 @@ u8 acpi_ut_valid_internal_object(void *object) return (TRUE); default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p is not not an ACPI operand obj [%s]\n", object, acpi_ut_get_descriptor_name(object))); break; @@ -457,7 +457,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, * must be accessed bytewise or there may be alignment problems on * certain processors */ - switch (ACPI_GET_OBJECT_TYPE(internal_object)) { + switch (internal_object->common.type) { case ACPI_TYPE_STRING: length += (acpi_size) internal_object->string.length + 1; @@ -518,8 +518,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, ACPI_ERROR((AE_INFO, "Cannot convert to external object - " "unsupported type [%s] %X in object %p", acpi_ut_get_object_type_name(internal_object), - ACPI_GET_OBJECT_TYPE(internal_object), - internal_object)); + internal_object->common.type, internal_object)); status = AE_TYPE; break; } @@ -664,7 +663,7 @@ acpi_ut_get_object_size(union acpi_operand_object *internal_object, if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE)) { + && (internal_object->common.type == ACPI_TYPE_PACKAGE)) { status = acpi_ut_get_package_object_size(internal_object, obj_length); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd..e8f7b64e92d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -39,6 +39,8 @@ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> +#include "internal.h" + #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("bus"); @@ -758,8 +760,7 @@ static int __init acpi_bus_init(void) acpi_status status = AE_OK; extern acpi_status acpi_os_initialize1(void); - - status = acpi_os_initialize1(); + acpi_os_initialize1(); status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); @@ -769,12 +770,6 @@ static int __init acpi_bus_init(void) goto error1; } - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to initialize ACPI OS objects\n"); - goto error1; - } - /* * ACPI 2.0 requires the EC driver to be loaded and work before * the EC device is found in the namespace (i.e. before acpi_initialize_objects() @@ -853,6 +848,7 @@ static int __init acpi_init(void) acpi_kobj = NULL; } + init_acpi_device_notify(); result = acpi_bus_init(); if (!result) { @@ -867,11 +863,23 @@ static int __init acpi_init(void) } } else disable_acpi(); + + if (acpi_disabled) + return result; + /* * If the laptop falls into the DMI check table, the power state check * will be disabled in the course of device power transistion. */ dmi_check_system(power_nocheck_dmi_table); + + acpi_scan_init(); + acpi_ec_init(); + acpi_power_init(); + acpi_system_init(); + acpi_debug_init(); + acpi_sleep_proc_init(); + acpi_wakeup_device_init(); return result; } diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 20223cbd0d1..9cb189f3c77 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -297,17 +297,15 @@ acpi_system_write_debug(struct file *file, return count; } +#endif -static int __init acpi_debug_init(void) +int __init acpi_debug_init(void) { +#ifdef CONFIG_ACPI_PROCFS struct proc_dir_entry *entry; int error = 0; char *name; - - if (acpi_disabled) - return 0; - /* 'debug_layer' [R/W] */ name = ACPI_SYSTEM_FILE_DEBUG_LAYER; entry = @@ -338,7 +336,7 @@ static int __init acpi_debug_init(void) remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir); error = -ENODEV; goto Done; -} - -subsys_initcall(acpi_debug_init); +#else + return 0; #endif +} diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2fe15060dcd..bf88f180380 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1069,13 +1069,10 @@ static struct acpi_driver acpi_ec_driver = { }, }; -static int __init acpi_ec_init(void) +int __init acpi_ec_init(void) { int result = 0; - if (acpi_disabled) - return 0; - acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); if (!acpi_ec_dir) return -ENODEV; @@ -1090,8 +1087,6 @@ static int __init acpi_ec_init(void) return result; } -subsys_initcall(acpi_ec_init); - /* EC driver currently not unloadable */ #if 0 static void __exit acpi_ec_exit(void) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 5479b9f4251..8bd2c2a6884 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -286,10 +286,8 @@ static int acpi_platform_notify_remove(struct device *dev) return 0; } -static int __init init_acpi_device_notify(void) +int __init init_acpi_device_notify(void) { - if (acpi_disabled) - return 0; if (platform_notify || platform_notify_remove) { printk(KERN_ERR PREFIX "Can't use platform_notify\n"); return 0; @@ -298,5 +296,3 @@ static int __init init_acpi_device_notify(void) platform_notify_remove = acpi_platform_notify_remove; return 0; } - -arch_initcall(init_acpi_device_notify); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h new file mode 100644 index 00000000000..11a69b53004 --- /dev/null +++ b/drivers/acpi/internal.h @@ -0,0 +1,43 @@ +/* For use by Linux/ACPI infrastructure, not drivers */ + +int init_acpi_device_notify(void); +int acpi_scan_init(void); +int acpi_system_init(void); + +#ifdef CONFIG_ACPI_DEBUG +int acpi_debug_init(void); +#else +static inline int acpi_debug_init(void) { return 0; } +#endif + +/* -------------------------------------------------------------------------- + Power Resource + -------------------------------------------------------------------------- */ +int acpi_power_init(void); +int acpi_device_sleep_wake(struct acpi_device *dev, + int enable, int sleep_state, int dev_state); +int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); +int acpi_disable_wakeup_device_power(struct acpi_device *dev); +int acpi_power_get_inferred_state(struct acpi_device *device); +int acpi_power_transition(struct acpi_device *device, int state); +extern int acpi_power_nocheck; + +int acpi_wakeup_device_init(void); + +/* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ +int acpi_ec_init(void); +int acpi_ec_ecdt_probe(void); +int acpi_boot_ec_enable(void); + +/*-------------------------------------------------------------------------- + Suspend/Resume + -------------------------------------------------------------------------- */ +extern int acpi_sleep_init(void); + +#ifdef CONFIG_ACPI_SLEEP +int acpi_sleep_proc_init(void); +#else +static inline int acpi_sleep_proc_init(void) { return 0; } +#endif diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index c5e292aab0e..3a0d8ef25c7 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -277,7 +277,7 @@ int acpi_get_node(acpi_handle *handle) int pxm, node = -1; pxm = acpi_get_pxm(handle); - if (pxm >= 0) + if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) node = acpi_map_pxm_to_node(pxm); return node; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b3193ec0a2e..1e35f342957 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1317,54 +1317,6 @@ acpi_os_validate_interface (char *interface) return AE_SUPPORT; } -#ifdef CONFIG_X86 - -struct aml_port_desc { - uint start; - uint end; - char* name; - char warned; -}; - -static struct aml_port_desc aml_invalid_port_list[] = { - {0x20, 0x21, "PIC0", 0}, - {0xA0, 0xA1, "PIC1", 0}, - {0x4D0, 0x4D1, "ELCR", 0} -}; - -/* - * valid_aml_io_address() - * - * if valid, return true - * else invalid, warn once, return false - */ -static bool valid_aml_io_address(uint address, uint length) -{ - int i; - int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc); - - for (i = 0; i < entries; ++i) { - if ((address >= aml_invalid_port_list[i].start && - address <= aml_invalid_port_list[i].end) || - (address + length >= aml_invalid_port_list[i].start && - address + length <= aml_invalid_port_list[i].end)) - { - if (!aml_invalid_port_list[i].warned) - { - printk(KERN_ERR "ACPI: Denied BIOS AML access" - " to invalid port 0x%x+0x%x (%s)\n", - address, length, - aml_invalid_port_list[i].name); - aml_invalid_port_list[i].warned = 1; - } - return false; /* invalid */ - } - } - return true; /* valid */ -} -#else -static inline bool valid_aml_io_address(uint address, uint length) { return true; } -#endif /****************************************************************************** * * FUNCTION: acpi_os_validate_address @@ -1394,8 +1346,6 @@ acpi_os_validate_address ( switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: - if (!valid_aml_io_address(address, length)) - return AE_AML_ILLEGAL_ADDRESS; case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 891bdf6679f..be6b9093f8d 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -319,7 +319,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) */ bridge = dev->bus->self; while (bridge) { - pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; + pin = pci_swizzle_interrupt_pin(dev, pin); if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { /* PC card has the same IRQ as its cardbridge */ diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6c772ca76bd..16e0f9d3d17 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -43,13 +43,14 @@ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> -#define _COMPONENT ACPI_PCI_COMPONENT +#define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" #define ACPI_PCI_LINK_FILE_INFO "info" #define ACPI_PCI_LINK_FILE_STATUS "state" -#define ACPI_PCI_LINK_MAX_POSSIBLE 16 +#define ACPI_PCI_LINK_MAX_POSSIBLE 16 + static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); @@ -66,7 +67,7 @@ static struct acpi_driver acpi_pci_link_driver = { .ops = { .add = acpi_pci_link_add, .remove = acpi_pci_link_remove, - }, + }, }; /* @@ -76,7 +77,7 @@ static struct acpi_driver acpi_pci_link_driver = { struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 triggering; /* All IRQs */ - u8 polarity; /* All IRQs */ + u8 polarity; /* All IRQs */ u8 resource_type; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; @@ -85,16 +86,13 @@ struct acpi_pci_link_irq { }; struct acpi_pci_link { - struct list_head node; - struct acpi_device *device; - struct acpi_pci_link_irq irq; - int refcnt; + struct list_head list; + struct acpi_device *device; + struct acpi_pci_link_irq irq; + int refcnt; }; -static struct { - int count; - struct list_head entries; -} acpi_link; +static LIST_HEAD(acpi_link_list); static DEFINE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- @@ -104,12 +102,11 @@ static DEFINE_MUTEX(acpi_link_lock); /* * set context (link) possible list from resource list */ -static acpi_status -acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) +static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource, + void *context) { struct acpi_pci_link *link = context; - u32 i = 0; - + u32 i; switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -179,10 +176,6 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) { acpi_status status; - - if (!link) - return -EINVAL; - status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS, acpi_pci_link_check_possible, link); if (ACPI_FAILURE(status)) { @@ -197,11 +190,10 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) return 0; } -static acpi_status -acpi_pci_link_check_current(struct acpi_resource *resource, void *context) +static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource, + void *context) { - int *irq = (int *)context; - + int *irq = context; switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -258,12 +250,9 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) static int acpi_pci_link_get_current(struct acpi_pci_link *link) { int result = 0; - acpi_status status = AE_OK; + acpi_status status; int irq = 0; - if (!link) - return -EINVAL; - link->irq.active = 0; /* in practice, status disabled is meaningless, ignore it */ @@ -308,16 +297,15 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link) static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) { - int result = 0; - acpi_status status = AE_OK; + int result; + acpi_status status; struct { struct acpi_resource res; struct acpi_resource end; } *resource; struct acpi_buffer buffer = { 0, NULL }; - - if (!link || !irq) + if (!irq) return -EINVAL; resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); @@ -479,30 +467,22 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ - PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ - PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ - PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ - PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ + PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ + PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ + PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ + PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ /* >IRQ15 */ }; int __init acpi_irq_penalty_init(void) { - struct list_head *node = NULL; - struct acpi_pci_link *link = NULL; - int i = 0; - + struct acpi_pci_link *link; + int i; /* * Update penalties to facilitate IRQ balancing. */ - list_for_each(node, &acpi_link.entries) { - - link = list_entry(node, struct acpi_pci_link, node); - if (!link) { - printk(KERN_ERR PREFIX "Invalid link context\n"); - continue; - } + list_for_each_entry(link, &acpi_link_list, list) { /* * reflect the possible and active irqs in the penalty table -- @@ -527,7 +507,6 @@ int __init acpi_irq_penalty_init(void) } /* Add a penalty for the SCI */ acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING; - return 0; } @@ -538,7 +517,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) int irq; int i; - if (link->irq.initialized) { if (link->refcnt == 0) /* This means the link is disabled but initialized */ @@ -566,11 +544,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) /* * if active found, use it; else pick entry from end of possible list. */ - if (link->irq.active) { + if (link->irq.active) irq = link->irq.active; - } else { + else irq = link->irq.possible[link->irq.possible_count - 1]; - } if (acpi_irq_balance || !link->irq.active) { /* @@ -599,7 +576,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) } link->irq.initialized = 1; - return 0; } @@ -608,16 +584,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * success: return IRQ >= 0 * failure: return -1 */ - -int -acpi_pci_link_allocate_irq(acpi_handle handle, - int index, - int *triggering, int *polarity, char **name) +int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, + int *polarity, char **name) { - int result = 0; - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; - + int result; + struct acpi_device *device; + struct acpi_pci_link *link; result = acpi_bus_get_device(handle, &device); if (result) { @@ -669,11 +641,10 @@ acpi_pci_link_allocate_irq(acpi_handle handle, */ int acpi_pci_link_free_irq(acpi_handle handle) { - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; + struct acpi_device *device; + struct acpi_pci_link *link; acpi_status result; - result = acpi_bus_get_device(handle, &device); if (result) { printk(KERN_ERR PREFIX "Invalid link device\n"); @@ -708,9 +679,9 @@ int acpi_pci_link_free_irq(acpi_handle handle) "Link %s is dereferenced\n", acpi_device_bid(link->device))); - if (link->refcnt == 0) { + if (link->refcnt == 0) acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); - } + mutex_unlock(&acpi_link_lock); return (link->irq.active); } @@ -721,15 +692,11 @@ int acpi_pci_link_free_irq(acpi_handle handle) static int acpi_pci_link_add(struct acpi_device *device) { - int result = 0; - struct acpi_pci_link *link = NULL; - int i = 0; + int result; + struct acpi_pci_link *link; + int i; int found = 0; - - if (!device) - return -EINVAL; - link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); if (!link) return -ENOMEM; @@ -767,9 +734,7 @@ static int acpi_pci_link_add(struct acpi_device *device) printk("\n"); - /* TBD: Acquire/release lock */ - list_add_tail(&link->node, &acpi_link.entries); - acpi_link.count++; + list_add_tail(&link->list, &acpi_link_list); end: /* disable all links -- to be activated on use */ @@ -784,24 +749,17 @@ static int acpi_pci_link_add(struct acpi_device *device) static int acpi_pci_link_resume(struct acpi_pci_link *link) { - if (link->refcnt && link->irq.active && link->irq.initialized) return (acpi_pci_link_set(link, link->irq.active)); - else - return 0; + + return 0; } static int irqrouter_resume(struct sys_device *dev) { - struct list_head *node = NULL; - struct acpi_pci_link *link = NULL; + struct acpi_pci_link *link; - list_for_each(node, &acpi_link.entries) { - link = list_entry(node, struct acpi_pci_link, node); - if (!link) { - printk(KERN_ERR PREFIX "Invalid link context\n"); - continue; - } + list_for_each_entry(link, &acpi_link_list, list) { acpi_pci_link_resume(link); } return 0; @@ -809,20 +767,15 @@ static int irqrouter_resume(struct sys_device *dev) static int acpi_pci_link_remove(struct acpi_device *device, int type) { - struct acpi_pci_link *link = NULL; - - - if (!device || !acpi_driver_data(device)) - return -EINVAL; + struct acpi_pci_link *link; link = acpi_driver_data(device); mutex_lock(&acpi_link_lock); - list_del(&link->node); + list_del(&link->list); mutex_unlock(&acpi_link_lock); kfree(link); - return 0; } @@ -931,7 +884,6 @@ static int __init irqrouter_init_sysfs(void) { int error; - if (acpi_disabled || acpi_noirq) return 0; @@ -957,9 +909,6 @@ static int __init acpi_pci_link_init(void) acpi_irq_balance = 0; } - acpi_link.count = 0; - INIT_LIST_HEAD(&acpi_link.entries); - if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) return -ENODEV; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index c926e7d4a0d..11968ba28fe 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -773,14 +773,10 @@ static int acpi_power_resume(struct acpi_device *device) return 0; } -static int __init acpi_power_init(void) +int __init acpi_power_init(void) { int result = 0; - - if (acpi_disabled) - return 0; - INIT_LIST_HEAD(&acpi_power_resource_list); acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); @@ -795,5 +791,3 @@ static int __init acpi_power_init(void) return 0; } - -subsys_initcall(acpi_power_init); diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 428c911dba0..05dfdc96802 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -496,11 +496,8 @@ static u32 rtc_handler(void *context) } #endif /* HAVE_ACPI_LEGACY_ALARM */ -static int __init acpi_sleep_proc_init(void) +int __init acpi_sleep_proc_init(void) { - if (acpi_disabled) - return 0; - #ifdef CONFIG_ACPI_PROCFS /* 'sleep' [R/W] */ proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR, @@ -527,5 +524,3 @@ static int __init acpi_sleep_proc_init(void) return 0; } - -late_initcall(acpi_sleep_proc_init); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7bc22a471fe..397f2a7fee4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -101,57 +101,6 @@ static int set_max_cstate(const struct dmi_system_id *id) /* Actually this shouldn't be __cpuinitdata, would be better to fix the callers to only run once -AK */ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET70WW")}, (void *)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1}, - { set_max_cstate, "Medion 41700", { - DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1}, { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, @@ -630,7 +579,7 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, * In either case, the proper way to * handle BM_RLD is to set it and leave it set. */ - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); + acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1); return; } @@ -800,9 +749,9 @@ static int acpi_idle_bm_check(void) { u32 bm_status = 0; - acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); + acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); if (bm_status) - acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); + acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); /* * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect * the true state of bus mastering activity; forcing us to @@ -1028,7 +977,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); + acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); @@ -1041,7 +990,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, /* Re-enable bus master arbitration */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c54d7b6c406..b7308efce45 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -11,6 +11,8 @@ #include <acpi/acpi_drivers.h> +#include "internal.h" + #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("scan"); #define STRUCT_TO_INT(s) (*((int*)&s)) @@ -395,22 +397,10 @@ static int acpi_device_remove(struct device * dev) return 0; } -static void acpi_device_shutdown(struct device *dev) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; - - if (acpi_drv && acpi_drv->ops.shutdown) - acpi_drv->ops.shutdown(acpi_dev); - - return ; -} - struct bus_type acpi_bus_type = { .name = "acpi", .suspend = acpi_device_suspend, .resume = acpi_device_resume, - .shutdown = acpi_device_shutdown, .match = acpi_bus_match, .probe = acpi_device_probe, .remove = acpi_device_remove, @@ -1524,16 +1514,11 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) return result; } - -static int __init acpi_scan_init(void) +int __init acpi_scan_init(void) { int result; struct acpi_bus_ops ops; - - if (acpi_disabled) - return 0; - memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; @@ -1566,5 +1551,3 @@ static int __init acpi_scan_init(void) Done: return result; } - -subsys_initcall(acpi_scan_init); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 519266654f0..91a284b54db 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -21,6 +21,8 @@ #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> + +#include "internal.h" #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; @@ -248,7 +250,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* If ACPI is not enabled by the BIOS, we need to enable it here. */ if (set_sci_en_on_resume) - acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); else acpi_enable(); @@ -378,6 +380,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Toshiba Satellite L300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index c8859047acf..44be75ee726 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -616,12 +616,9 @@ static int acpi_system_procfs_init(void) } #endif -static int __init acpi_system_init(void) +int __init acpi_system_init(void) { - int result = 0; - - if (acpi_disabled) - return 0; + int result; result = acpi_system_procfs_init(); if (result) @@ -631,5 +628,3 @@ static int __init acpi_system_init(void) return result; } - -subsys_initcall(acpi_system_init); diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 2d34806d45d..5aee8c26cc9 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -8,6 +8,8 @@ #include <acpi/acpi_drivers.h> #include <linux/kernel.h> #include <linux/types.h> + +#include "internal.h" #include "sleep.h" #define _COMPONENT ACPI_SYSTEM_COMPONENT @@ -136,13 +138,10 @@ void acpi_disable_wakeup_device(u8 sleep_state) spin_unlock(&acpi_device_lock); } -static int __init acpi_wakeup_device_init(void) +int __init acpi_wakeup_device_init(void) { struct list_head *node, *next; - if (acpi_disabled) - return 0; - spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, @@ -163,5 +162,3 @@ static int __init acpi_wakeup_device_init(void) spin_unlock(&acpi_device_lock); return 0; } - -late_initcall(acpi_wakeup_device_init); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a603bbf9b1b..66e012cd327 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -582,18 +582,18 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */ - { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */ /* SiS */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 54961c0b2c7..ef8b30d577b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, return map; } +static bool piix_no_sidpr(struct ata_host *host) +{ + struct pci_dev *pdev = to_pci_dev(host->dev); + + /* + * Samsung DB-P70 only has three ATA ports exposed and + * curiously the unconnected first port reports link online + * while not responding to SRST protocol causing excessive + * detection delay. + * + * Unfortunately, the system doesn't carry enough DMI + * information to identify the machine but does have subsystem + * vendor and device set. As it's unclear whether the + * subsystem vendor/device is used only for this specific + * board, the port can't be disabled solely with the + * information; however, turning off SIDPR access works around + * the problem. Turn it off. + * + * This problem is reported in bnc#441240. + * + * https://bugzilla.novell.com/show_bug.cgi?id=441420 + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && + pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && + pdev->subsystem_device == 0xb049) { + dev_printk(KERN_WARNING, host->dev, + "Samsung DB-P70 detected, disabling SIDPR\n"); + return true; + } + + return false; +} + static int __devinit piix_init_sidpr(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); @@ -1302,6 +1335,10 @@ static int __devinit piix_init_sidpr(struct ata_host *host) if (hpriv->map[i] == IDE) return 0; + /* is it blacklisted? */ + if (piix_no_sidpr(host)) + return 0; + if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) return 0; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9fbf0595f3d..060bcd601f5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1322,14 +1322,16 @@ static u64 ata_id_n_sectors(const u16 *id) { if (ata_id_has_lba(id)) { if (ata_id_has_lba48(id)) - return ata_id_u64(id, 100); + return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); else - return ata_id_u32(id, 60); + return ata_id_u32(id, ATA_ID_LBA_CAPACITY); } else { if (ata_id_current_chs_valid(id)) - return ata_id_u32(id, 57); + return id[ATA_ID_CUR_CYLS] * id[ATA_ID_CUR_HEADS] * + id[ATA_ID_CUR_SECTORS]; else - return id[1] * id[3] * id[6]; + return id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * + id[ATA_ID_SECTORS]; } } @@ -4612,7 +4614,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc) VPRINTK("unmapping %u sg elements\n", qc->n_elem); if (qc->n_elem) - dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->dev, sg, qc->orig_n_elem, dir); qc->flags &= ~ATA_QCFLAG_DMAMAP; qc->sg = NULL; @@ -4727,7 +4729,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) return -1; DPRINTK("%d sg elements mapped\n", n_elem); - + qc->orig_n_elem = qc->n_elem; qc->n_elem = n_elem; qc->flags |= ATA_QCFLAG_DMAMAP; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ce2ef047533..ea890911d4f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2423,11 +2423,14 @@ int ata_eh_reset(struct ata_link *link, int classify, } /* prereset() might have cleared ATA_EH_RESET. If so, - * bang classes and return. + * bang classes, thaw and return. */ if (reset && !(ehc->i.action & ATA_EH_RESET)) { ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_NONE; + if ((ap->pflags & ATA_PFLAG_FROZEN) && + ata_is_host_link(link)) + ata_eh_thaw_port(ap); rc = 0; goto out; } @@ -2901,7 +2904,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev) int i; for (i = 0; i < ATA_EH_UA_TRIES; i++) { - u8 sense_buffer[SCSI_SENSE_BUFFERSIZE]; + u8 *sense_buffer = dev->link->ap->sector_buf; u8 sense_key = 0; unsigned int err_mask; diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 714cb046b59..f93dc029dfd 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2066,6 +2066,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); udelay(20); /* FIXME: flush */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; /* wait the port to become ready */ return ata_sff_wait_after_reset(&ap->link, devmask, deadline); @@ -2190,8 +2191,10 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) } /* set up device control */ - if (ap->ioaddr.ctl_addr) + if (ap->ioaddr.ctl_addr) { iowrite8(ap->ctl, ap->ioaddr.ctl_addr); + ap->last_ctl = ap->ctl; + } } EXPORT_SYMBOL_GPL(ata_sff_postreset); @@ -2534,6 +2537,7 @@ void ata_bus_reset(struct ata_port *ap) if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) { /* set up device control for ATA_FLAG_SATA_RESET */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; } DPRINTK("EXIT\n"); diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 63719ab9ea4..115b1cd6dcf 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -24,7 +24,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_amd" -#define DRV_VERSION "0.3.11" +#define DRV_VERSION "0.4.1" /** * timing_setup - shared timing computation and load @@ -145,6 +145,13 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline) return ata_sff_prereset(link, deadline); } +/** + * amd_cable_detect - report cable type + * @ap: port + * + * AMD controller/BIOS setups record the cable type in word 0x42 + */ + static int amd_cable_detect(struct ata_port *ap) { static const u32 bitmask[2] = {0x03, 0x0C}; @@ -158,6 +165,40 @@ static int amd_cable_detect(struct ata_port *ap) } /** + * amd_fifo_setup - set the PIO FIFO for ATA/ATAPI + * @ap: ATA interface + * @adev: ATA device + * + * Set the PCI fifo for this device according to the devices present + * on the bus at this point in time. We need to turn the post write buffer + * off for ATAPI devices as we may need to issue a word sized write to the + * device as the final I/O + */ + +static void amd_fifo_setup(struct ata_port *ap) +{ + struct ata_device *adev; + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + static const u8 fifobit[2] = { 0xC0, 0x30}; + u8 fifo = fifobit[ap->port_no]; + u8 r; + + + ata_for_each_dev(adev, &ap->link, ENABLED) { + if (adev->class == ATA_DEV_ATAPI) + fifo = 0; + } + if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */ + fifo = 0; + + /* On the later chips the read prefetch bits become no-op bits */ + pci_read_config_byte(pdev, 0x41, &r); + r &= ~fifobit[ap->port_no]; + r |= fifo; + pci_write_config_byte(pdev, 0x41, r); +} + +/** * amd33_set_piomode - set initial PIO mode data * @ap: ATA interface * @adev: ATA device @@ -167,21 +208,25 @@ static int amd_cable_detect(struct ata_port *ap) static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev) { + amd_fifo_setup(ap); timing_setup(ap, adev, 0x40, adev->pio_mode, 1); } static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev) { + amd_fifo_setup(ap); timing_setup(ap, adev, 0x40, adev->pio_mode, 2); } static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev) { + amd_fifo_setup(ap); timing_setup(ap, adev, 0x40, adev->pio_mode, 3); } static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev) { + amd_fifo_setup(ap); timing_setup(ap, adev, 0x40, adev->pio_mode, 4); } @@ -397,6 +442,16 @@ static struct ata_port_operations nv133_port_ops = { .set_dmamode = nv133_set_dmamode, }; +static void amd_clear_fifo(struct pci_dev *pdev) +{ + u8 fifo; + /* Disable the FIFO, the FIFO logic will re-enable it as + appropriate */ + pci_read_config_byte(pdev, 0x41, &fifo); + fifo &= 0x0F; + pci_write_config_byte(pdev, 0x41, fifo); +} + static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info[10] = { @@ -503,14 +558,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (type < 3) ata_pci_bmdma_clear_simplex(pdev); - - /* Check for AMD7411 */ - if (type == 3) - /* FIFO is broken */ - pci_write_config_byte(pdev, 0x41, fifo & 0x0F); - else - pci_write_config_byte(pdev, 0x41, fifo | 0xF0); - + if (pdev->vendor == PCI_VENDOR_ID_AMD) + amd_clear_fifo(pdev); /* Cable detection on Nvidia chips doesn't work too well, * cache BIOS programmed UDMA mode. */ @@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev) return rc; if (pdev->vendor == PCI_VENDOR_ID_AMD) { - u8 fifo; - pci_read_config_byte(pdev, 0x41, &fifo); - if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) - /* FIFO is broken */ - pci_write_config_byte(pdev, 0x41, fifo & 0x0F); - else - pci_write_config_byte(pdev, 0x41, fifo | 0xF0); + amd_clear_fifo(pdev); if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 || pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401) ata_pci_bmdma_clear_simplex(pdev); } - ata_host_resume(host); return 0; } diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index f1bb2f9fecb..b05b86a912c 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -557,6 +557,9 @@ static unsigned int it821x_read_id(struct ata_device *adev, id[83] |= 0x4400; /* Word 83 is valid and LBA48 */ id[86] |= 0x0400; /* LBA48 on */ id[ATA_ID_MAJOR_VER] |= 0x1F; + /* Clear the serial number because it's different each boot + which breaks validation on resume */ + memset(&id[ATA_ID_SERNO], 0x20, ATA_ID_SERNO_LEN); } return err_mask; } diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 6c1d778b63a..e3bc1b43628 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -283,9 +283,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) static unsigned int pdc_data_xfer_vlb(struct ata_device *dev, unsigned char *buf, unsigned int buflen, int rw) { - if (ata_id_has_dword_io(dev->id)) { + int slop = buflen & 3; + /* 32bit I/O capable *and* we need to write a whole number of dwords */ + if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) { struct ata_port *ap = dev->link->ap; - int slop = buflen & 3; unsigned long flags; local_irq_save(flags); @@ -735,7 +736,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf, struct ata_port *ap = adev->link->ap; int slop = buflen & 3; - if (ata_id_has_dword_io(adev->id)) { + if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) { if (rw == WRITE) iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); else diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 4ae1a4138b4..74b1080d116 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2218,12 +2218,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) else handled = mv_host_intr(host, pending_irqs); } - spin_unlock(&host->lock); /* for MSI: unmask; interrupt cause bits will retrigger now */ if (using_msi) writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); + spin_unlock(&host->lock); + return IRQ_RETVAL(handled); } @@ -3114,19 +3115,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); } - if (!IS_SOC(hpriv)) { - /* Clear any currently outstanding host interrupt conditions */ - writelfl(0, mmio + hpriv->irq_cause_ofs); + /* Clear any currently outstanding host interrupt conditions */ + writelfl(0, mmio + hpriv->irq_cause_ofs); - /* and unmask interrupt generation for host regs */ - writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); + /* and unmask interrupt generation for host regs */ + writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); - /* - * enable only global host interrupts for now. - * The per-port interrupts get done later as ports are set up. - */ - mv_set_main_irq_mask(host, 0, PCI_ERR); - } + /* + * enable only global host interrupts for now. + * The per-port interrupts get done later as ports are set up. + */ + mv_set_main_irq_mask(host, 0, PCI_ERR); done: return rc; } diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 55a8eed3f3a..f65b53785a8 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -2523,7 +2523,7 @@ static void __exit nv_exit(void) module_init(nv_init); module_exit(nv_exit); module_param_named(adma, adma_enabled, bool, 0444); -MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); +MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)"); module_param_named(swncq, swncq_enabled, bool, 0444); MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)"); diff --git a/drivers/base/node.c b/drivers/base/node.c index 43fa90b837e..f8f578a71b2 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -303,7 +303,7 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { - unsigned int nid; + int nid; nid = get_nid_for_pfn(pfn); if (nid < 0) diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 204332b2957..87e120e0a79 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_PS3_DISK) += ps3disk.o +obj-$(CONFIG_PS3_VRAM) += ps3vram.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index cc250577d40..eeea477d960 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -173,7 +173,7 @@ skbfree(struct sk_buff *skb) return; while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0) msleep(Sms); - if (i <= 0) { + if (i < 0) { printk(KERN_ERR "aoe: %s holds ref: %s\n", skb->dev ? skb->dev->name : "netif", diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index d2cb67b6117..4f9b6d79201 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3606,16 +3606,18 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev)) return -ENODEV; - /* Some devices (notably the HP Smart Array 5i Controller) - need a little pause here */ - schedule_timeout_uninterruptible(30*HZ); - - /* Now try to get the controller to respond to a no-op */ - for (i=0; i<12; i++) { + /* Now try to get the controller to respond to a no-op. Some + devices (notably the HP Smart Array 5i Controller) need + up to 30 seconds to respond. */ + for (i=0; i<30; i++) { if (cciss_noop(pdev) == 0) break; - else - printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : "")); + + schedule_timeout_uninterruptible(HZ); + } + if (i == 30) { + printk(KERN_ERR "cciss: controller seems dead\n"); + return -EBUSY; } } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index edbaac6c057..bf034557767 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -392,8 +392,7 @@ lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, struct loop_device *lo = p->lo; struct page *page = buf->page; sector_t IV; - size_t size; - int ret; + int size, ret; ret = buf->ops->confirm(pipe, buf); if (unlikely(ret)) diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c new file mode 100644 index 00000000000..393ed6760d7 --- /dev/null +++ b/drivers/block/ps3vram.c @@ -0,0 +1,865 @@ +/* + * ps3vram - Use extra PS3 video ram as MTD block device. + * + * Copyright 2009 Sony Corporation + * + * Based on the MTD ps3vram driver, which is + * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com> + * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr> + */ + +#include <linux/blkdev.h> +#include <linux/delay.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> + +#include <asm/firmware.h> +#include <asm/lv1call.h> +#include <asm/ps3.h> + + +#define DEVICE_NAME "ps3vram" + + +#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ +#define XDR_IOIF 0x0c000000 + +#define FIFO_BASE XDR_IOIF +#define FIFO_SIZE (64 * 1024) + +#define DMA_PAGE_SIZE (4 * 1024) + +#define CACHE_PAGE_SIZE (256 * 1024) +#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) + +#define CACHE_OFFSET CACHE_PAGE_SIZE +#define FIFO_OFFSET 0 + +#define CTRL_PUT 0x10 +#define CTRL_GET 0x11 +#define CTRL_TOP 0x15 + +#define UPLOAD_SUBCH 1 +#define DOWNLOAD_SUBCH 2 + +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 + +#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 + +#define CACHE_PAGE_PRESENT 1 +#define CACHE_PAGE_DIRTY 2 + +struct ps3vram_tag { + unsigned int address; + unsigned int flags; +}; + +struct ps3vram_cache { + unsigned int page_count; + unsigned int page_size; + struct ps3vram_tag *tags; + unsigned int hit; + unsigned int miss; +}; + +struct ps3vram_priv { + struct request_queue *queue; + struct gendisk *gendisk; + + u64 size; + + u64 memory_handle; + u64 context_handle; + u32 *ctrl; + u32 *reports; + u8 __iomem *ddr_base; + u8 *xdr_buf; + + u32 *fifo_base; + u32 *fifo_ptr; + + struct ps3vram_cache cache; + + /* Used to serialize cache/DMA operations */ + struct mutex lock; +}; + + +static int ps3vram_major; + + +static struct block_device_operations ps3vram_fops = { + .owner = THIS_MODULE, +}; + + +#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ +#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ +#define DMA_NOTIFIER_SIZE 0x40 +#define NOTIFIER 7 /* notifier used for completion report */ + +static char *size = "256M"; +module_param(size, charp, 0); +MODULE_PARM_DESC(size, "memory size"); + +static u32 *ps3vram_get_notifier(u32 *reports, int notifier) +{ + return (void *)reports + DMA_NOTIFIER_OFFSET_BASE + + DMA_NOTIFIER_SIZE * notifier; +} + +static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + int i; + + for (i = 0; i < 4; i++) + notify[i] = 0xffffffff; +} + +static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (!notify[3]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static void ps3vram_init_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; +} + +static int ps3vram_wait_ring(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n", + priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], + priv->ctrl[CTRL_TOP]); + + return -ETIMEDOUT; +} + +static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) +{ + *(priv->fifo_ptr)++ = data; +} + +static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, u32 tag, + u32 size) +{ + ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); +} + +static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + priv->fifo_ptr = priv->fifo_base; +} + +static void ps3vram_fire_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + mutex_lock(&ps3_gpu_mutex); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + + (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > + FIFO_SIZE - 1024) { + dev_dbg(&dev->core, "FIFO full, rewinding\n"); + ps3vram_wait_ring(dev, 200); + ps3vram_rewind_ring(dev); + } + + mutex_unlock(&ps3_gpu_mutex); +} + +static void ps3vram_bind(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x31337303); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x3137c0de); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + + ps3vram_fire_ring(dev); +} + +static int ps3vram_upload(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, XDR_IOIF + src_offset); + ps3vram_out_ring(priv, dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static int ps3vram_download(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, src_offset); + ps3vram_out_ring(priv, XDR_IOIF + dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY)) + return; + + dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry, + cache->tags[entry].address); + if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size, + cache->tags[entry].address, DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to upload from 0x%x to " "0x%x size 0x%x\n", + entry * cache->page_size, cache->tags[entry].address, + cache->page_size); + } + cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; +} + +static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry, + unsigned int address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address); + if (ps3vram_download(dev, address, + CACHE_OFFSET + entry * cache->page_size, + DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to download from 0x%x to 0x%x size 0x%x\n", + address, entry * cache->page_size, cache->page_size); + } + + cache->tags[entry].address = address; + cache->tags[entry].flags |= CACHE_PAGE_PRESENT; +} + + +static void ps3vram_cache_flush(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + int i; + + dev_dbg(&dev->core, "FLUSH\n"); + for (i = 0; i < cache->page_count; i++) { + ps3vram_cache_evict(dev, i); + cache->tags[i].flags = 0; + } +} + +static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev, + loff_t address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + unsigned int base; + unsigned int offset; + int i; + static int counter; + + offset = (unsigned int) (address & (cache->page_size - 1)); + base = (unsigned int) (address - offset); + + /* fully associative check */ + for (i = 0; i < cache->page_count; i++) { + if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && + cache->tags[i].address == base) { + cache->hit++; + dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i, + cache->tags[i].address); + return i; + } + } + + /* choose a random entry */ + i = (jiffies + (counter++)) % cache->page_count; + dev_dbg(&dev->core, "Using entry %d\n", i); + + ps3vram_cache_evict(dev, i); + ps3vram_cache_load(dev, i, base); + + cache->miss++; + return i; +} + +static int ps3vram_cache_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->cache.page_count = CACHE_PAGE_COUNT; + priv->cache.page_size = CACHE_PAGE_SIZE; + priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * + CACHE_PAGE_COUNT, GFP_KERNEL); + if (priv->cache.tags == NULL) { + dev_err(&dev->core, "Could not allocate cache tags\n"); + return -ENOMEM; + } + + dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n", + CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); + + return 0; +} + +static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_cache_flush(dev); + kfree(priv->cache.tags); +} + +static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__, + (unsigned int)from, len); + + if (from >= priv->size) + return -EIO; + + if (len > priv->size - from) + len = priv->size - from; + + /* Copy from vram to buf */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (from & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, from); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, + (unsigned int)from, cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(buf, priv->xdr_buf + cached, avail); + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + from += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, + size_t len, size_t *retlen, const u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + if (to >= priv->size) + return -EIO; + + if (len > priv->size - to) + len = priv->size - to; + + /* Copy from buf to vram */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (to & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, to); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, (unsigned int)to, + cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(priv->xdr_buf + cached, buf, avail); + + priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + to += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_proc_show(struct seq_file *m, void *v) +{ + struct ps3vram_priv *priv = m->private; + + seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss); + return 0; +} + +static int ps3vram_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ps3vram_proc_show, PDE(inode)->data); +} + +static const struct file_operations ps3vram_proc_fops = { + .owner = THIS_MODULE, + .open = ps3vram_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct proc_dir_entry *pde; + + pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops); + if (!pde) { + dev_warn(&dev->core, "failed to create /proc entry\n"); + return; + } + + pde->owner = THIS_MODULE; + pde->data = priv; +} + +static int ps3vram_make_request(struct request_queue *q, struct bio *bio) +{ + struct ps3_system_bus_device *dev = q->queuedata; + int write = bio_data_dir(bio) == WRITE; + const char *op = write ? "write" : "read"; + loff_t offset = bio->bi_sector << 9; + int error = 0; + struct bio_vec *bvec; + unsigned int i; + + dev_dbg(&dev->core, "%s\n", __func__); + + bio_for_each_segment(bvec, bio, i) { + /* PS3 is ppc64, so we don't handle highmem */ + char *ptr = page_address(bvec->bv_page) + bvec->bv_offset; + size_t len = bvec->bv_len, retlen; + + dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, + len, offset); + if (write) + error = ps3vram_write(dev, offset, len, &retlen, ptr); + else + error = ps3vram_read(dev, offset, len, &retlen, ptr); + + if (error) { + dev_err(&dev->core, "%s failed\n", op); + goto out; + } + + if (retlen != len) { + dev_err(&dev->core, "Short %s\n", op); + goto out; + } + + offset += len; + } + + dev_dbg(&dev->core, "%s completed\n", op); + +out: + bio_endio(bio, error); + return 0; +} + +static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv; + int error, status; + struct request_queue *queue; + struct gendisk *gendisk; + u64 ddr_lpar, ctrl_lpar, info_lpar, reports_lpar, ddr_size, + reports_size; + char *rest; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + error = -ENOMEM; + goto fail; + } + + mutex_init(&priv->lock); + dev->core.driver_data = priv; + + priv = dev->core.driver_data; + + /* Allocate XDR buffer (1MiB aligned) */ + priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, + get_order(XDR_BUF_SIZE)); + if (priv->xdr_buf == NULL) { + dev_err(&dev->core, "Could not allocate XDR buffer\n"); + error = -ENOMEM; + goto fail_free_priv; + } + + /* Put FIFO at begginning of XDR buffer */ + priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); + priv->fifo_ptr = priv->fifo_base; + + /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ + if (ps3_open_hv_device(dev)) { + dev_err(&dev->core, "ps3_open_hv_device failed\n"); + error = -EAGAIN; + goto out_close_gpu; + } + + /* Request memory */ + status = -1; + ddr_size = ALIGN(memparse(size, &rest), 1024*1024); + if (!ddr_size) { + dev_err(&dev->core, "Specified size is too small\n"); + error = -EINVAL; + goto out_close_gpu; + } + + while (ddr_size > 0) { + status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, + &priv->memory_handle, + &ddr_lpar); + if (!status) + break; + ddr_size -= 1024*1024; + } + if (status) { + dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_xdr_buf; + } + + /* Request context */ + status = lv1_gpu_context_allocate(priv->memory_handle, 0, + &priv->context_handle, &ctrl_lpar, + &info_lpar, &reports_lpar, + &reports_size); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_memory; + } + + /* Map XDR buffer to RSX */ + status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, + ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), + XDR_BUF_SIZE, 0); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n", + status); + error = -ENOMEM; + goto out_free_context; + } + + priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); + + if (!priv->ddr_base) { + dev_err(&dev->core, "ioremap DDR failed\n"); + error = -ENOMEM; + goto out_free_context; + } + + priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); + if (!priv->ctrl) { + dev_err(&dev->core, "ioremap CTRL failed\n"); + error = -ENOMEM; + goto out_unmap_vram; + } + + priv->reports = ioremap(reports_lpar, reports_size); + if (!priv->reports) { + dev_err(&dev->core, "ioremap REPORTS failed\n"); + error = -ENOMEM; + goto out_unmap_ctrl; + } + + mutex_lock(&ps3_gpu_mutex); + ps3vram_init_ring(dev); + mutex_unlock(&ps3_gpu_mutex); + + priv->size = ddr_size; + + ps3vram_bind(dev); + + mutex_lock(&ps3_gpu_mutex); + error = ps3vram_wait_ring(dev, 100); + mutex_unlock(&ps3_gpu_mutex); + if (error < 0) { + dev_err(&dev->core, "Failed to initialize channels\n"); + error = -ETIMEDOUT; + goto out_unmap_reports; + } + + ps3vram_cache_init(dev); + ps3vram_proc_init(dev); + + queue = blk_alloc_queue(GFP_KERNEL); + if (!queue) { + dev_err(&dev->core, "blk_alloc_queue failed\n"); + error = -ENOMEM; + goto out_cache_cleanup; + } + + priv->queue = queue; + queue->queuedata = dev; + blk_queue_make_request(queue, ps3vram_make_request); + blk_queue_max_phys_segments(queue, MAX_PHYS_SEGMENTS); + blk_queue_max_hw_segments(queue, MAX_HW_SEGMENTS); + blk_queue_max_segment_size(queue, MAX_SEGMENT_SIZE); + blk_queue_max_sectors(queue, SAFE_MAX_SECTORS); + + gendisk = alloc_disk(1); + if (!gendisk) { + dev_err(&dev->core, "alloc_disk failed\n"); + error = -ENOMEM; + goto fail_cleanup_queue; + } + + priv->gendisk = gendisk; + gendisk->major = ps3vram_major; + gendisk->first_minor = 0; + gendisk->fops = &ps3vram_fops; + gendisk->queue = queue; + gendisk->private_data = dev; + gendisk->driverfs_dev = &dev->core; + strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name)); + set_capacity(gendisk, priv->size >> 9); + + dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n", + gendisk->disk_name, get_capacity(gendisk) >> 11); + + add_disk(gendisk); + return 0; + +fail_cleanup_queue: + blk_cleanup_queue(queue); +out_cache_cleanup: + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); +out_unmap_reports: + iounmap(priv->reports); +out_unmap_ctrl: + iounmap(priv->ctrl); +out_unmap_vram: + iounmap(priv->ddr_base); +out_free_context: + lv1_gpu_context_free(priv->context_handle); +out_free_memory: + lv1_gpu_memory_free(priv->memory_handle); +out_close_gpu: + ps3_close_hv_device(dev); +out_free_xdr_buf: + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); +fail_free_priv: + kfree(priv); + dev->core.driver_data = NULL; +fail: + return error; +} + +static int ps3vram_remove(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + del_gendisk(priv->gendisk); + put_disk(priv->gendisk); + blk_cleanup_queue(priv->queue); + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); + iounmap(priv->reports); + iounmap(priv->ctrl); + iounmap(priv->ddr_base); + lv1_gpu_context_free(priv->context_handle); + lv1_gpu_memory_free(priv->memory_handle); + ps3_close_hv_device(dev); + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); + kfree(priv); + dev->core.driver_data = NULL; + return 0; +} + +static struct ps3_system_bus_driver ps3vram = { + .match_id = PS3_MATCH_ID_GPU, + .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, + .core.name = DEVICE_NAME, + .core.owner = THIS_MODULE, + .probe = ps3vram_probe, + .remove = ps3vram_remove, + .shutdown = ps3vram_remove, +}; + + +static int __init ps3vram_init(void) +{ + int error; + + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return -ENODEV; + + error = register_blkdev(0, DEVICE_NAME); + if (error <= 0) { + pr_err("%s: register_blkdev failed %d\n", DEVICE_NAME, error); + return error; + } + ps3vram_major = error; + + pr_info("%s: registered block device major %d\n", DEVICE_NAME, + ps3vram_major); + + error = ps3_system_bus_driver_register(&ps3vram); + if (error) + unregister_blkdev(ps3vram_major, DEVICE_NAME); + + return error; +} + +static void __exit ps3vram_exit(void) +{ + ps3_system_bus_driver_unregister(&ps3vram); + unregister_blkdev(ps3vram_major, DEVICE_NAME); +} + +module_init(ps3vram_init); +module_exit(ps3vram_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PS3 Video RAM Storage Driver"); +MODULE_AUTHOR("Sony Corporation"); +MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 918ef725de4..8f905089b72 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -40,6 +40,7 @@ #include <linux/hdreg.h> #include <linux/cdrom.h> #include <linux/module.h> +#include <linux/scatterlist.h> #include <xen/xenbus.h> #include <xen/grant_table.h> @@ -82,6 +83,7 @@ struct blkfront_info enum blkif_state connected; int ring_ref; struct blkif_front_ring ring; + struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; unsigned int evtchn, irq; struct request_queue *rq; struct work_struct work; @@ -204,12 +206,11 @@ static int blkif_queue_request(struct request *req) struct blkfront_info *info = req->rq_disk->private_data; unsigned long buffer_mfn; struct blkif_request *ring_req; - struct req_iterator iter; - struct bio_vec *bvec; unsigned long id; unsigned int fsect, lsect; - int ref; + int i, ref; grant_ref_t gref_head; + struct scatterlist *sg; if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) return 1; @@ -238,12 +239,13 @@ static int blkif_queue_request(struct request *req) if (blk_barrier_rq(req)) ring_req->operation = BLKIF_OP_WRITE_BARRIER; - ring_req->nr_segments = 0; - rq_for_each_segment(bvec, req, iter) { - BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); - buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); - fsect = bvec->bv_offset >> 9; - lsect = fsect + (bvec->bv_len >> 9) - 1; + ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); + BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST); + + for_each_sg(info->sg, sg, ring_req->nr_segments, i) { + buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg))); + fsect = sg->offset >> 9; + lsect = fsect + (sg->length >> 9) - 1; /* install a grant reference. */ ref = gnttab_claim_grant_reference(&gref_head); BUG_ON(ref == -ENOSPC); @@ -254,16 +256,12 @@ static int blkif_queue_request(struct request *req) buffer_mfn, rq_data_dir(req) ); - info->shadow[id].frame[ring_req->nr_segments] = - mfn_to_pfn(buffer_mfn); - - ring_req->seg[ring_req->nr_segments] = + info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); + ring_req->seg[i] = (struct blkif_request_segment) { .gref = ref, .first_sect = fsect, .last_sect = lsect }; - - ring_req->nr_segments++; } info->ring.req_prod_pvt++; @@ -622,6 +620,8 @@ static int setup_blkring(struct xenbus_device *dev, SHARED_RING_INIT(sring); FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); + sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST); + err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); if (err < 0) { free_page((unsigned long)sring); @@ -977,6 +977,8 @@ static void backend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: + if (info->gd == NULL) + xenbus_dev_fatal(dev, -ENODEV, "gd is NULL"); bd = bdget_disk(info->gd, 0); if (bd == NULL) xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 381d686fc1a..119be3442f2 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -489,6 +489,28 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state, ace->id_req_count); #endif + /* Verify that there is actually a CF in the slot. If not, then + * bail out back to the idle state and wake up all the waiters */ + status = ace_in32(ace, ACE_STATUS); + if ((status & ACE_STATUS_CFDETECT) == 0) { + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->media_change = 1; + set_capacity(ace->gd, 0); + dev_info(ace->dev, "No CF in slot\n"); + + /* Drop all pending requests */ + while ((req = elv_next_request(ace->queue)) != NULL) + end_request(req, 0); + + /* Drop back to IDLE state and notify waiters */ + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->id_result = -EIO; + while (ace->id_req_count) { + complete(&ace->id_completion); + ace->id_req_count--; + } + } + switch (ace->fsm_state) { case ACE_FSM_STATE_IDLE: /* See if there is anything to do */ diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 52f4361eb6e..d765afda9c2 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -271,15 +271,15 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, nb_order = (nb_order >> 1) & 7; pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base); nb_aper = nb_base << 25; - if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) { - return 0; - } /* Northbridge seems to contain crap. Try the AGP bridge. */ pci_read_config_word(agp, cap+0x14, &apsize); - if (apsize == 0xffff) + if (apsize == 0xffff) { + if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) + return 0; return -1; + } apsize &= 0xfff; /* Some BIOS use weird encodings not in the AGPv3 table. */ @@ -301,6 +301,11 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, order = nb_order; } + if (nb_order >= order) { + if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) + return 0; + } + dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index c7714185f83..4373adb2119 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -633,13 +633,15 @@ static void intel_i830_init_gtt_entries(void) break; } } - if (gtt_entries > 0) + if (gtt_entries > 0) { dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", gtt_entries / KB(1), local ? "local" : "stolen"); - else + gtt_entries /= KB(4); + } else { dev_info(&agp_bridge->dev->dev, "no pre-allocated video memory detected\n"); - gtt_entries /= KB(4); + gtt_entries = 0; + } intel_private.gtt_entries = gtt_entries; } diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index db60539bf67..699e3422ad9 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -359,9 +359,16 @@ fail: return error; } -static struct device *next_device(struct klist_iter *i) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; +static int +find_quicksilver(struct device *dev, void *data) +{ + struct parisc_device **lba = data; + struct parisc_device *padev = to_parisc_device(dev); + + if (IS_QUICKSILVER(padev)) + *lba = padev; + + return 0; } static int @@ -372,8 +379,6 @@ parisc_agp_init(void) int err = -1; struct parisc_device *sba = NULL, *lba = NULL; struct lba_device *lbadev = NULL; - struct device *dev = NULL; - struct klist_iter i; if (!sba_list) goto out; @@ -386,13 +391,7 @@ parisc_agp_init(void) } /* Now search our Pluto for our precious AGP device... */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - if (IS_QUICKSILVER(padev)) - lba = padev; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &lba, find_quicksilver); if (!lba) { printk(KERN_INFO DRVPFX "No AGP devices found.\n"); diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 6e6eb445d37..c76bccf5354 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -1139,15 +1139,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) hvcsd->tty = tty; tty->driver_data = hvcsd; - /* - * Set this driver to low latency so that we actually have a chance at - * catching a throttled TTY after we flip_buffer_push. Otherwise the - * flush_to_async may not execute until after the kernel_thread has - * yielded and resumed the next flip_buffer_push resulting in data - * loss. - */ - tty->low_latency = 1; - memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); /* diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 406f8742a26..2989056a9e3 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -810,7 +810,6 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) hp = &hvsi_ports[line]; tty->driver_data = hp; - tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */ mb(); if (hp->state == HVSI_FSP_DIED) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b55cb67435b..d6daf3c507d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -754,11 +754,6 @@ static struct kobj_type ktype_cpufreq = { .release = cpufreq_sysfs_release, }; -static struct kobj_type ktype_empty_cpufreq = { - .sysfs_ops = &sysfs_ops, - .release = cpufreq_sysfs_release, -}; - /** * cpufreq_add_dev - add a CPU device @@ -892,36 +887,26 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); /* prepare interface data */ - if (!cpufreq_driver->hide_interface) { - ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, - &sys_dev->kobj, "cpufreq"); + ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, + "cpufreq"); + if (ret) + goto err_out_driver_exit; + + /* set up files for this cpu device */ + drv_attr = cpufreq_driver->attr; + while ((drv_attr) && (*drv_attr)) { + ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); if (ret) goto err_out_driver_exit; - - /* set up files for this cpu device */ - drv_attr = cpufreq_driver->attr; - while ((drv_attr) && (*drv_attr)) { - ret = sysfs_create_file(&policy->kobj, - &((*drv_attr)->attr)); - if (ret) - goto err_out_driver_exit; - drv_attr++; - } - if (cpufreq_driver->get) { - ret = sysfs_create_file(&policy->kobj, - &cpuinfo_cur_freq.attr); - if (ret) - goto err_out_driver_exit; - } - if (cpufreq_driver->target) { - ret = sysfs_create_file(&policy->kobj, - &scaling_cur_freq.attr); - if (ret) - goto err_out_driver_exit; - } - } else { - ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq, - &sys_dev->kobj, "cpufreq"); + drv_attr++; + } + if (cpufreq_driver->get) { + ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); + if (ret) + goto err_out_driver_exit; + } + if (cpufreq_driver->target) { + ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) goto err_out_driver_exit; } diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 2d637e0fbc0..d9e751be8c5 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -457,10 +457,12 @@ static int init_ixp_crypto(void) if (!ctx_pool) { goto err; } - ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0); + ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0, + "ixp_crypto:out", NULL); if (ret) goto err; - ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0); + ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0, + "ixp_crypto:in", NULL); if (ret) { qmgr_release_queue(SEND_QID); goto err; diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 856b3cc2558..3f0fdd18255 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -489,4 +489,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Ludvig"); -MODULE_ALIAS("aes"); +MODULE_ALIAS("aes-all"); diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index a7fbadebf62..a2c8e8514b6 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c @@ -304,7 +304,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Ludvig"); -MODULE_ALIAS("sha1"); -MODULE_ALIAS("sha256"); +MODULE_ALIAS("sha1-all"); +MODULE_ALIAS("sha256-all"); MODULE_ALIAS("sha1-padlock"); MODULE_ALIAS("sha256-padlock"); diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 33bd7534751..25b743abfb5 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. 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 as published by the Free diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c index bb538b9690e..ee916c9857e 100644 --- a/drivers/dca/dca-sysfs.c +++ b/drivers/dca/dca-sysfs.c @@ -1,3 +1,24 @@ +/* + * Copyright(c) 2007 - 2009 Intel Corporation. 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 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. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #include <linux/kernel.h> #include <linux/spinlock.h> #include <linux/device.h> diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 732fa1ec36a..e190d8b3070 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -430,13 +430,15 @@ late_initcall(dmatest_init); static void __exit dmatest_exit(void) { struct dmatest_chan *dtc, *_dtc; + struct dma_chan *chan; list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { list_del(&dtc->node); + chan = dtc->chan; dmatest_cleanup_channel(dtc); pr_debug("dmatest: dropped channel %s\n", - dma_chan_name(dtc->chan)); - dma_release_channel(dtc->chan); + dma_chan_name(chan)); + dma_release_channel(chan); } } module_exit(dmatest_exit); diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 70126a60623..86d6da47f55 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -158,7 +158,8 @@ static void dma_start(struct fsl_dma_chan *fsl_chan) static void dma_halt(struct fsl_dma_chan *fsl_chan) { - int i = 0; + int i; + DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA, 32); @@ -166,8 +167,11 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan) DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32); - while (!dma_is_idle(fsl_chan) && (i++ < 100)) + for (i = 0; i < 100; i++) { + if (dma_is_idle(fsl_chan)) + break; udelay(10); + } if (i >= 100 && !dma_is_idle(fsl_chan)) dev_err(fsl_chan->dev, "DMA halt timeout!\n"); } diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index 4105d6575b6..ed83dd9df19 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c @@ -1,6 +1,6 @@ /* * Intel I/OAT DMA Linux driver - * Copyright(c) 2007 Intel Corporation. + * Copyright(c) 2007 - 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, diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c index 6cf622da028..c012a1e1504 100644 --- a/drivers/dma/ioat_dca.c +++ b/drivers/dma/ioat_dca.c @@ -1,6 +1,6 @@ /* * Intel I/OAT DMA Linux driver - * Copyright(c) 2007 Intel Corporation. + * Copyright(c) 2007 - 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, @@ -49,6 +49,23 @@ #define DCA_TAG_MAP_MASK 0xDF +/* expected tag map bytes for I/OAT ver.2 */ +#define DCA2_TAG_MAP_BYTE0 0x80 +#define DCA2_TAG_MAP_BYTE1 0x0 +#define DCA2_TAG_MAP_BYTE2 0x81 +#define DCA2_TAG_MAP_BYTE3 0x82 +#define DCA2_TAG_MAP_BYTE4 0x82 + +/* verify if tag map matches expected values */ +static inline int dca2_tag_map_valid(u8 *tag_map) +{ + return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) && + (tag_map[1] == DCA2_TAG_MAP_BYTE1) && + (tag_map[2] == DCA2_TAG_MAP_BYTE2) && + (tag_map[3] == DCA2_TAG_MAP_BYTE3) && + (tag_map[4] == DCA2_TAG_MAP_BYTE4)); +} + /* * "Legacy" DCA systems do not implement the DCA register set in the * I/OAT device. Software needs direct support for their tag mappings. @@ -452,6 +469,13 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase) ioatdca->tag_map[i] = 0; } + if (!dca2_tag_map_valid(ioatdca->tag_map)) { + dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, " + "disabling DCA\n"); + free_dca_provider(dca); + return NULL; + } + err = register_dca_provider(dca, &pdev->dev); if (err) { free_dca_provider(dca); diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index b3759c4b653..5905cd36bcd 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1,6 +1,6 @@ /* * Intel I/OAT DMA Linux driver - * Copyright(c) 2004 - 2007 Intel Corporation. + * Copyright(c) 2004 - 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, @@ -189,11 +189,13 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) ioat_chan->xfercap = xfercap; ioat_chan->desccount = 0; INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2); - if (ioat_chan->device->version != IOAT_VER_1_2) { - writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE - | IOAT_DMA_DCA_ANY_CPU, - ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); - } + if (ioat_chan->device->version == IOAT_VER_2_0) + writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE | + IOAT_DMA_DCA_ANY_CPU, + ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); + else if (ioat_chan->device->version == IOAT_VER_3_0) + writel(IOAT_DMA_DCA_ANY_CPU, + ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); spin_lock_init(&ioat_chan->cleanup_lock); spin_lock_init(&ioat_chan->desc_lock); INIT_LIST_HEAD(&ioat_chan->free_desc); @@ -1169,9 +1171,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) * up if the client is done with the descriptor */ if (async_tx_test_ack(&desc->async_tx)) { - list_del(&desc->node); - list_add_tail(&desc->node, - &ioat_chan->free_desc); + list_move_tail(&desc->node, + &ioat_chan->free_desc); } else desc->async_tx.cookie = 0; } else { @@ -1362,6 +1363,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) dma_cookie_t cookie; int err = 0; struct completion cmp; + unsigned long tmo; src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); if (!src) @@ -1413,9 +1415,10 @@ static int ioat_dma_self_test(struct ioatdma_device *device) } device->common.device_issue_pending(dma_chan); - wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); + tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); - if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) + if (tmo == 0 || + device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { dev_err(&device->pdev->dev, "Self-test copy timed out, disabling\n"); @@ -1657,6 +1660,13 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, " %d channels, device version 0x%02x, driver version %s\n", device->common.chancnt, device->version, IOAT_DMA_VERSION); + if (!device->common.chancnt) { + dev_err(&device->pdev->dev, + "Intel(R) I/OAT DMA Engine problem found: " + "zero channels detected\n"); + goto err_setup_interrupts; + } + err = ioat_dma_setup_interrupts(device); if (err) goto err_setup_interrupts; @@ -1696,6 +1706,9 @@ void ioat_dma_remove(struct ioatdma_device *device) struct dma_chan *chan, *_chan; struct ioat_dma_chan *ioat_chan; + if (device->version != IOAT_VER_3_0) + cancel_delayed_work(&device->work); + ioat_dma_remove_interrupts(device); dma_async_device_unregister(&device->common); @@ -1707,10 +1720,6 @@ void ioat_dma_remove(struct ioatdma_device *device) pci_release_regions(device->pdev); pci_disable_device(device->pdev); - if (device->version != IOAT_VER_3_0) { - cancel_delayed_work(&device->work); - } - list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) { ioat_chan = to_ioat_chan(chan); diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index a3306d0e137..a52ff4bd460 100644 --- a/drivers/dma/ioatdma.h +++ b/drivers/dma/ioatdma.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2009 Intel Corporation. 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 as published by the Free @@ -29,7 +29,7 @@ #include <linux/pci_ids.h> #include <net/tcp.h> -#define IOAT_DMA_VERSION "3.30" +#define IOAT_DMA_VERSION "3.64" enum ioat_interrupt { none = 0, @@ -135,12 +135,14 @@ static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev) #ifdef CONFIG_NET_DMA switch (dev->version) { case IOAT_VER_1_2: - case IOAT_VER_3_0: sysctl_tcp_dma_copybreak = 4096; break; case IOAT_VER_2_0: sysctl_tcp_dma_copybreak = 2048; break; + case IOAT_VER_3_0: + sysctl_tcp_dma_copybreak = 262144; + break; } #endif } diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h index f1ae2c776f7..afa57eef86c 100644 --- a/drivers/dma/ioatdma_hw.h +++ b/drivers/dma/ioatdma_hw.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2009 Intel Corporation. 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 as published by the Free diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h index 827cb503cac..49bc277424f 100644 --- a/drivers/dma/ioatdma_registers.h +++ b/drivers/dma/ioatdma_registers.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2009 Intel Corporation. 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 as published by the Free diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index ea5440dd10d..16adbe61cfb 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -928,19 +928,19 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { xor_srcs[src_idx] = alloc_page(GFP_KERNEL); - if (!xor_srcs[src_idx]) - while (src_idx--) { + if (!xor_srcs[src_idx]) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } } dest = alloc_page(GFP_KERNEL); - if (!dest) - while (src_idx--) { + if (!dest) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } /* Fill in src buffers */ for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { @@ -1401,7 +1401,7 @@ MODULE_ALIAS("platform:iop-adma"); static struct platform_driver iop_adma_driver = { .probe = iop_adma_probe, - .remove = iop_adma_remove, + .remove = __devexit_p(iop_adma_remove), .driver = { .owner = THIS_MODULE, .name = "iop-adma", diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 1f154d08e98..ae50a9d1a4e 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -729,7 +729,7 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan, ichan->status = IPU_CHANNEL_READY; - spin_unlock_irqrestore(ipu->lock, flags); + spin_unlock_irqrestore(&ipu->lock, flags); return 0; } diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index d35cbd1ff0b..cb7f26fb9f1 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -1019,19 +1019,19 @@ mv_xor_xor_self_test(struct mv_xor_device *device) for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { xor_srcs[src_idx] = alloc_page(GFP_KERNEL); - if (!xor_srcs[src_idx]) - while (src_idx--) { + if (!xor_srcs[src_idx]) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } } dest = alloc_page(GFP_KERNEL); - if (!dest) - while (src_idx--) { + if (!dest) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } /* Fill in src buffers */ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { @@ -1287,7 +1287,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp, static struct platform_driver mv_xor_driver = { .probe = mv_xor_probe, - .remove = mv_xor_remove, + .remove = __devexit_p(mv_xor_remove), .driver = { .owner = THIS_MODULE, .name = MV_XOR_NAME, diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 72c667f9bee..12715d3c078 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -420,7 +420,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) dev->sigdata.lock = NULL; master->lock.hw_lock = NULL; /* SHM removed */ master->lock.file_priv = NULL; - wake_up_interruptible(&master->lock.lock_queue); + wake_up_interruptible_all(&master->lock.lock_queue); } break; case _DRM_AGP: diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 6c020fe5431..f52663ebe01 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -484,6 +484,7 @@ int drm_release(struct inode *inode, struct file *filp) mutex_lock(&dev->struct_mutex); if (file_priv->is_master) { + struct drm_master *master = file_priv->master; struct drm_file *temp; list_for_each_entry(temp, &dev->filelist, lhead) { if ((temp->master == file_priv->master) && @@ -491,6 +492,19 @@ int drm_release(struct inode *inode, struct file *filp) temp->authenticated = 0; } + /** + * Since the master is disappearing, so is the + * possibility to lock. + */ + + if (master->lock.hw_lock) { + if (dev->sigdata.lock == master->lock.hw_lock) + dev->sigdata.lock = NULL; + master->lock.hw_lock = NULL; + master->lock.file_priv = NULL; + wake_up_interruptible_all(&master->lock.lock_queue); + } + if (file_priv->minor->master == file_priv->master) { /* drop the reference held my the minor */ drm_master_put(&file_priv->minor->master); diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 46e7b28f070..e2f70a516c3 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) __set_current_state(TASK_INTERRUPTIBLE); if (!master->lock.hw_lock) { /* Device has been unregistered */ + send_sig(SIGTERM, current, 0); ret = -EINTR; break; } @@ -93,7 +94,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) /* Contention */ schedule(); if (signal_pending(current)) { - ret = -ERESTARTSYS; + ret = -EINTR; break; } } diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 46bb923b097..7c8b15b22bf 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref) drm_ht_remove(&master->magiclist); - if (master->lock.hw_lock) { - if (dev->sigdata.lock == master->lock.hw_lock) - dev->sigdata.lock = NULL; - master->lock.hw_lock = NULL; - master->lock.file_priv = NULL; - wake_up_interruptible(&master->lock.lock_queue); - } - drm_free(master, sizeof(*master), DRM_MEM_DRIVER); } @@ -176,7 +168,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, file_priv->minor->master != file_priv->master) { mutex_lock(&dev->struct_mutex); file_priv->minor->master = drm_master_get(file_priv->master); - mutex_lock(&dev->struct_mutex); + mutex_unlock(&dev->struct_mutex); } return 0; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index cc4649577a6..6d21b9e48b8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1090,6 +1090,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, dev->agp->agp_info.aper_size * 1024*1024); + if (dev_priv->mm.gtt_mapping == NULL) { + ret = -EIO; + goto out_rmmap; + } + /* Set up a WC MTRR for non-PAT systems. This is more common than * one would think, because the kernel disables PAT on first * generation Core chips because WC PAT gets overridden by a UC @@ -1100,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) 1024 * 1024, MTRR_TYPE_WRCOMB, 1); if (dev_priv->mm.gtt_mtrr < 0) { - DRM_INFO("MTRR allocation failed\n. Graphics " + DRM_INFO("MTRR allocation failed. Graphics " "performance may suffer.\n"); } @@ -1122,7 +1127,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!I915_NEED_GFX_HWS(dev)) { ret = i915_init_phys_hws(dev); if (ret != 0) - goto out_rmmap; + goto out_iomapfree; } /* On the 945G/GM, the chipset reports the MSI capability on the @@ -1161,6 +1166,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; +out_iomapfree: + io_mapping_free(dev_priv->mm.gtt_mapping); out_rmmap: iounmap(dev_priv->regs); free_priv: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17fa40858d2..d6cc9861e0a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -279,7 +279,6 @@ typedef struct drm_i915_private { u8 saveAR_INDEX; u8 saveAR[21]; u8 saveDACMASK; - u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveCR[37]; struct { @@ -457,6 +456,12 @@ struct drm_i915_gem_object { /** for phy allocated objects */ struct drm_i915_gem_phys_object *phys_obj; + + /** + * Used for checking the object doesn't appear more than once + * in an execbuffer object list. + */ + int in_execbuffer; }; /** diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 85685bfd12d..37427e4016c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1476,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) struct drm_i915_gem_object *obj_priv = obj->driver_private; int regnum = obj_priv->fence_reg; int tile_width; - uint32_t val; + uint32_t fence_reg, val; uint32_t pitch_val; if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || @@ -1503,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) val |= pitch_val << I830_FENCE_PITCH_SHIFT; val |= I830_FENCE_REG_VALID; - I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); + if (regnum < 8) + fence_reg = FENCE_REG_830_0 + (regnum * 4); + else + fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); + I915_WRITE(fence_reg, val); } static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) @@ -1557,7 +1561,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_i915_fence_reg *reg = NULL; - int i, ret; + struct drm_i915_gem_object *old_obj_priv = NULL; + int i, ret, avail; switch (obj_priv->tiling_mode) { case I915_TILING_NONE: @@ -1580,25 +1585,46 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) } /* First try to find a free reg */ +try_again: + avail = 0; for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { reg = &dev_priv->fence_regs[i]; if (!reg->obj) break; + + old_obj_priv = reg->obj->driver_private; + if (!old_obj_priv->pin_count) + avail++; } /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { - struct drm_i915_gem_object *old_obj_priv = NULL; + uint32_t seqno = dev_priv->mm.next_gem_seqno; loff_t offset; -try_again: - /* Could try to use LRU here instead... */ + if (avail == 0) + return -ENOMEM; + for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { + uint32_t this_seqno; + reg = &dev_priv->fence_regs[i]; old_obj_priv = reg->obj->driver_private; - if (!old_obj_priv->pin_count) + + if (old_obj_priv->pin_count) + continue; + + /* i915 uses fences for GPU access to tiled buffers */ + if (IS_I965G(dev) || !old_obj_priv->active) break; + + /* find the seqno of the first available fence */ + this_seqno = old_obj_priv->last_rendering_seqno; + if (this_seqno != 0 && + reg->obj->write_domain == 0 && + i915_seqno_passed(seqno, this_seqno)) + seqno = this_seqno; } /* @@ -1606,15 +1632,25 @@ try_again: * objects to finish before trying again. */ if (i == dev_priv->num_fence_regs) { - ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); - if (ret) { - WARN(ret != -ERESTARTSYS, - "switch to GTT domain failed: %d\n", ret); - return ret; + if (seqno == dev_priv->mm.next_gem_seqno) { + i915_gem_flush(dev, + I915_GEM_GPU_DOMAINS, + I915_GEM_GPU_DOMAINS); + seqno = i915_add_request(dev, + I915_GEM_GPU_DOMAINS); + if (seqno == 0) + return -ENOMEM; } + + ret = i915_wait_request(dev, seqno); + if (ret) + return ret; goto try_again; } + BUG_ON(old_obj_priv->active || + (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); + /* * Zap this virtual mapping so we can set up a fence again * for this object next time we need it. @@ -1655,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) if (IS_I965G(dev)) I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); - else - I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); + else { + uint32_t fence_reg; + + if (obj_priv->fence_reg < 8) + fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; + else + fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - + 8) * 4; + + I915_WRITE(fence_reg, 0); + } dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; obj_priv->fence_reg = I915_FENCE_REG_NONE; @@ -2469,6 +2514,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_exec_object *exec_list = NULL; struct drm_gem_object **object_list = NULL; struct drm_gem_object *batch_obj; + struct drm_i915_gem_object *obj_priv; int ret, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains; @@ -2533,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ret = -EBADF; goto err; } + + obj_priv = object_list[i]->driver_private; + if (obj_priv->in_execbuffer) { + DRM_ERROR("Object %p appears more than once in object list\n", + object_list[i]); + ret = -EBADF; + goto err; + } + obj_priv->in_execbuffer = true; } /* Pin and relocate */ @@ -2674,8 +2729,13 @@ err: for (i = 0; i < pinned; i++) i915_gem_object_unpin(object_list[i]); - for (i = 0; i < args->buffer_count; i++) + for (i = 0; i < args->buffer_count; i++) { + if (object_list[i]) { + obj_priv = object_list[i]->driver_private; + obj_priv->in_execbuffer = false; + } drm_gem_object_unreference(object_list[i]); + } mutex_unlock(&dev->struct_mutex); @@ -2712,17 +2772,24 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) ret = i915_gem_object_bind_to_gtt(obj, alignment); if (ret != 0) { if (ret != -EBUSY && ret != -ERESTARTSYS) - DRM_ERROR("Failure to bind: %d", ret); + DRM_ERROR("Failure to bind: %d\n", ret); + return ret; + } + } + /* + * Pre-965 chips need a fence register set up in order to + * properly handle tiled surfaces. + */ + if (!IS_I965G(dev) && + obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) { + ret = i915_gem_object_get_fence_reg(obj, true); + if (ret != 0) { + if (ret != -EBUSY && ret != -ERESTARTSYS) + DRM_ERROR("Failure to install fence: %d\n", + ret); return ret; } - /* - * Pre-965 chips need a fence register set up in order to - * properly handle tiled surfaces. - */ - if (!IS_I965G(dev) && - obj_priv->fence_reg == I915_FENCE_REG_NONE && - obj_priv->tiling_mode != I915_TILING_NONE) - i915_gem_object_get_fence_reg(obj, true); } obj_priv->pin_count++; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 548ff2c6643..87b6b603469 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -383,12 +383,13 @@ int i915_irq_emit(struct drm_device *dev, void *data, drm_i915_irq_emit_t *emit = data; int result; - RING_LOCK_TEST_WITH_RETURN(dev, file_priv); - if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } + + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); + mutex_lock(&dev->struct_mutex); result = i915_emit_irq(dev); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d6539a868b..90600d89941 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -184,6 +184,7 @@ * Fence registers */ #define FENCE_REG_830_0 0x2000 +#define FENCE_REG_945_8 0x3000 #define I830_FENCE_START_MASK 0x07f80000 #define I830_FENCE_TILING_Y_SHIFT 12 #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5d84027ee8f..d669cc2b42c 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev) /* VGA color palette registers */ dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); - /* DACCRX automatically increments during read */ - I915_WRITE8(VGA_DACRX, 0); - /* Read 3 bytes of color data from each index */ - for (i = 0; i < 256 * 3; i++) - dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA); /* MSR bits */ dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); @@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev) /* VGA color palette registers */ I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); - /* DACCRX automatically increments during read */ - I915_WRITE8(VGA_DACWX, 0); - /* Read 3 bytes of color data from each index */ - for (i = 0; i < 256 * 3; i++) - I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]); - } int i915_save_state(struct drm_device *dev) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4940e4d70c2..1f5b5d4c3c3 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -306,7 +306,7 @@ static int hiddev_open(struct inode *inode, struct file *file) return 0; bail: file->private_data = NULL; - kfree(list->hiddev); + kfree(list); return res; } @@ -323,7 +323,7 @@ static ssize_t hiddev_write(struct file * file, const char __user * buffer, size */ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); struct hiddev_list *list = file->private_data; int event_size; int retval; diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b84bf066879..b4eea0292c1 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -543,8 +543,8 @@ config SENSORS_LM90 help If you say yes here you get support for National Semiconductor LM90, LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim - MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and - MAX6681 sensor chips. + MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, + MAX6680, MAX6681 and MAX6692 sensor chips. This driver can also be built as a module. If so, the module will be called lm90. diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index e52b38806d0..ad2b3431b72 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -760,8 +760,11 @@ static int abituguru3_read_increment_offset(struct abituguru3_data *data, for (i = 0; i < offset_count; i++) if ((x = abituguru3_read(data, bank, offset + i, count, - buf + i * count)) != count) - return i * count + (i && (x < 0)) ? 0 : x; + buf + i * count)) != count) { + if (x < 0) + return x; + return i * count + x; + } return i * count; } diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 1692de36996..18a1ba88816 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -617,7 +617,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct f75375_data *data = i2c_get_clientdata(client); + struct f75375_data *data; struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; int err; diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 95a99c590da..9157247fed8 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -213,7 +213,7 @@ static inline u16 FAN16_TO_REG(long rpm) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ ((val)+500)/1000),-128,127)) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) +#define TEMP_FROM_REG(val) ((val) * 1000) #define PWM_TO_REG(val) ((val) >> 1) #define PWM_FROM_REG(val) (((val)&0x7f) << 1) @@ -267,9 +267,9 @@ struct it87_data { u8 has_fan; /* Bitfield, fans enabled */ u16 fan[5]; /* Register values, possibly combined */ u16 fan_min[5]; /* Register values, possibly combined */ - u8 temp[3]; /* Register value */ - u8 temp_high[3]; /* Register value */ - u8 temp_low[3]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_high[3]; /* Register value */ + s8 temp_low[3]; /* Register value */ u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index cfc1ee90f5a..b251d8674b4 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -72,6 +72,7 @@ I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, #define LM85_COMPANY_SMSC 0x5c #define LM85_VERSTEP_VMASK 0xf0 #define LM85_VERSTEP_GENERIC 0x60 +#define LM85_VERSTEP_GENERIC2 0x70 #define LM85_VERSTEP_LM85C 0x60 #define LM85_VERSTEP_LM85B 0x62 #define LM85_VERSTEP_ADM1027 0x60 @@ -334,6 +335,7 @@ static struct lm85_data *lm85_update_device(struct device *dev); static const struct i2c_device_id lm85_id[] = { { "adm1027", adm1027 }, { "adt7463", adt7463 }, + { "adt7468", adt7468 }, { "lm85", any_chip }, { "lm85b", lm85b }, { "lm85c", lm85c }, @@ -408,7 +410,8 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, struct lm85_data *data = lm85_update_device(dev); int vid; - if (data->type == adt7463 && (data->vid & 0x80)) { + if ((data->type == adt7463 || data->type == adt7468) && + (data->vid & 0x80)) { /* 6-pin VID (VRM 10) */ vid = vid_from_reg(data->vid & 0x3f, data->vrm); } else { @@ -1153,7 +1156,8 @@ static int lm85_detect(struct i2c_client *client, int kind, address, company, verstep); /* All supported chips have the version in common */ - if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC) { + if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && + (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { dev_dbg(&adapter->dev, "Autodetection failed: " "unsupported version\n"); return -ENODEV; diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 96a70186672..1aff7575799 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -32,10 +32,10 @@ * supported by this driver. These chips lack the remote temperature * offset feature. * - * This driver also supports the MAX6646, MAX6647 and MAX6649 chips - * made by Maxim. These are again similar to the LM86, but they use - * unsigned temperature values and can report temperatures from 0 to - * 145 degrees. + * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and + * MAX6692 chips made by Maxim. These are again similar to the LM86, + * but they use unsigned temperature values and can report temperatures + * from 0 to 145 degrees. * * This driver also supports the MAX6680 and MAX6681, two other sensor * chips made by Maxim. These are quite similar to the other Maxim diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index eeda276f8f1..7f186bbcb99 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -482,7 +482,7 @@ mv64xxx_i2c_map_regs(struct platform_device *pd, return 0; } -static void __devexit +static void mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) { if (drv_data->reg_base) { @@ -577,7 +577,7 @@ mv64xxx_i2c_remove(struct platform_device *dev) static struct platform_driver mv64xxx_i2c_driver = { .probe = mv64xxx_i2c_probe, - .remove = mv64xxx_i2c_remove, + .remove = __devexit_p(mv64xxx_i2c_remove), .driver = { .owner = THIS_MODULE, .name = MV64XXX_I2C_CTLR_NAME, diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 3dad2299d9c..5ea3bfad172 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -46,7 +46,7 @@ menuconfig IDE SMART parameters from disk drives. To compile this driver as a module, choose M here: the - module will be called ide. + module will be called ide-core.ko. For further information, please read <file:Documentation/ide/ide.txt>. @@ -721,6 +721,11 @@ config BLK_DEV_IDE_TX4939 depends on SOC_TX4939 select BLK_DEV_IDEDMA_SFF +config BLK_DEV_IDE_AT91 + tristate "Atmel AT91 (SAM9, CAP9, AT572D940HF) IDE support" + depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40 + select IDE_TIMINGS + config IDE_ARM tristate "ARM IDE support" depends on ARM && (ARCH_RPC || ARCH_SHARK) diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0e3d7d5b46..1c326d94aa6 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -116,3 +116,4 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o +obj-$(CONFIG_BLK_DEV_IDE_AT91) += at91_ide.o diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 69660a431cd..77267c85996 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -166,7 +166,7 @@ static unsigned int init_chipset_amd74xx(struct pci_dev *dev) * Check for broken FIFO support. */ if (dev->vendor == PCI_VENDOR_ID_AMD && - dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411) + dev->device == PCI_DEVICE_ID_AMD_VIPER_7411) t &= 0x0f; else t |= 0xf0; diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c new file mode 100644 index 00000000000..1bb50f46388 --- /dev/null +++ b/drivers/ide/at91_ide.c @@ -0,0 +1,467 @@ +/* + * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller + * with Compact Flash True IDE logic + * + * Copyright (c) 2008, 2009 Kelvatek Ltd. + * + * 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. + * + */ + +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/ide.h> +#include <linux/platform_device.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9263.h> +#include <mach/at91sam9_smc.h> +#include <mach/at91sam9263_matrix.h> + +#define DRV_NAME "at91_ide" + +#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args) +#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args) + +/* + * Access to IDE device is possible through EBI Static Memory Controller + * with Compact Flash logic. For details see EBI and SMC datasheet sections + * of any microcontroller from AT91SAM9 family. + * + * Within SMC chip select address space, lines A[23:21] distinguish Compact + * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are: + * 0x00c0000 - True IDE + * 0x00e0000 - Alternate True IDE (Alt Status Register) + * + * On True IDE mode Task File and Data Register are mapped at the same address. + * To distinguish access between these two different bus data width is used: + * 8Bit for Task File, 16Bit for Data I/O. + * + * After initialization we do 8/16 bit flipping (changes in SMC MODE register) + * only inside IDE callback routines which are serialized by IDE layer, + * so no additional locking needed. + */ + +#define TASK_FILE 0x00c00000 +#define ALT_MODE 0x00e00000 +#define REGS_SIZE 8 + +#define enter_16bit(cs, mode) do { \ + mode = at91_sys_read(AT91_SMC_MODE(cs)); \ + at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16); \ +} while (0) + +#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode); + +static void set_smc_timings(const u8 chipselect, const u16 cycle, + const u16 setup, const u16 pulse, + const u16 data_float, int use_iordy) +{ + unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | + AT91_SMC_BAT_SELECT; + + /* disable or enable waiting for IORDY signal */ + if (use_iordy) + mode |= AT91_SMC_EXNWMODE_READY; + + /* add data float cycles if needed */ + if (data_float) + mode |= AT91_SMC_TDF_(data_float); + + at91_sys_write(AT91_SMC_MODE(chipselect), mode); + + /* setup timings in SMC */ + at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) | + AT91_SMC_NCS_WRSETUP_(0) | + AT91_SMC_NRDSETUP_(setup) | + AT91_SMC_NCS_RDSETUP_(0)); + at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) | + AT91_SMC_NCS_WRPULSE_(cycle) | + AT91_SMC_NRDPULSE_(pulse) | + AT91_SMC_NCS_RDPULSE_(cycle)); + at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) | + AT91_SMC_NRDCYCLE_(cycle)); +} + +static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz) +{ + u64 tmp = ns; + + tmp *= mck_hz; + tmp += 1000*1000*1000 - 1; /* round up */ + do_div(tmp, 1000*1000*1000); + return (unsigned int) tmp; +} + +static void apply_timings(const u8 chipselect, const u8 pio, + const struct ide_timing *timing, int use_iordy) +{ + unsigned int t0, t1, t2, t6z; + unsigned int cycle, setup, pulse, data_float; + unsigned int mck_hz; + struct clk *mck; + + /* see table 22 of Compact Flash standard 4.1 for the meaning, + * we do not stretch active (t2) time, so setup (t1) + hold time (th) + * assure at least minimal recovery (t2i) time */ + t0 = timing->cyc8b; + t1 = timing->setup; + t2 = timing->act8b; + t6z = (pio < 5) ? 30 : 20; + + pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z); + + mck = clk_get(NULL, "mck"); + BUG_ON(IS_ERR(mck)); + mck_hz = clk_get_rate(mck); + pdbg("mck_hz=%u\n", mck_hz); + + cycle = calc_mck_cycles(t0, mck_hz); + setup = calc_mck_cycles(t1, mck_hz); + pulse = calc_mck_cycles(t2, mck_hz); + data_float = calc_mck_cycles(t6z, mck_hz); + + pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n", + cycle, setup, pulse, data_float); + + set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy); +} + +static void at91_ide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + u8 chipselect = hwif->select_data; + unsigned long mode; + + pdbg("cs %u buf %p len %d\n", chipselect, buf, len); + + len++; + + enter_16bit(chipselect, mode); + __ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2); + leave_16bit(chipselect, mode); +} + +static void at91_ide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + u8 chipselect = hwif->select_data; + unsigned long mode; + + pdbg("cs %u buf %p len %d\n", chipselect, buf, len); + + enter_16bit(chipselect, mode); + __ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2); + leave_16bit(chipselect, mode); +} + +static u8 ide_mm_inb(unsigned long port) +{ + return readb((void __iomem *) port); +} + +static void ide_mm_outb(u8 value, unsigned long port) +{ + writeb(value, (void __iomem *) port); +} + +static void at91_ide_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + at91_ide_output_data(drive, NULL, &data, 2); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + ide_mm_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + ide_mm_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + ide_mm_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + ide_mm_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + ide_mm_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + ide_mm_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr); +} + +static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + at91_ide_input_data(drive, NULL, &data, 2); + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = ide_mm_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = ide_mm_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = ide_mm_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = ide_mm_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = ide_mm_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = ide_mm_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = ide_mm_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); + } +} + +static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + struct ide_timing *timing; + u8 chipselect = drive->hwif->select_data; + int use_iordy = 0; + + pdbg("chipselect %u pio %u\n", chipselect, pio); + + timing = ide_timing_find_mode(XFER_PIO_0 + pio); + BUG_ON(!timing); + + if ((pio > 2 || ata_id_has_iordy(drive->id)) && + !(ata_id_is_cfa(drive->id) && pio > 4)) + use_iordy = 1; + + apply_timings(chipselect, pio, timing, use_iordy); +} + +static const struct ide_tp_ops at91_ide_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .set_irq = ide_set_irq, + + .tf_load = at91_ide_tf_load, + .tf_read = at91_ide_tf_read, + + .input_data = at91_ide_input_data, + .output_data = at91_ide_output_data, +}; + +static const struct ide_port_ops at91_ide_port_ops = { + .set_pio_mode = at91_ide_set_pio_mode, +}; + +static const struct ide_port_info at91_ide_port_info __initdata = { + .port_ops = &at91_ide_port_ops, + .tp_ops = &at91_ide_tp_ops, + .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | + IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO5, +}; + +/* + * If interrupt is delivered through GPIO, IRQ are triggered on falling + * and rising edge of signal. Whereas IDE device request interrupt on high + * level (rising edge in our case). This mean we have fake interrupts, so + * we need to check interrupt pin and exit instantly from ISR when line + * is on low level. + */ + +irqreturn_t at91_irq_handler(int irq, void *dev_id) +{ + int ntries = 8; + int pin_val1, pin_val2; + + /* additional deglitch, line can be noisy in badly designed PCB */ + do { + pin_val1 = at91_get_gpio_value(irq); + pin_val2 = at91_get_gpio_value(irq); + } while (pin_val1 != pin_val2 && --ntries > 0); + + if (pin_val1 == 0 || ntries <= 0) + return IRQ_HANDLED; + + return ide_intr(irq, dev_id); +} + +static int __init at91_ide_probe(struct platform_device *pdev) +{ + int ret; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; + struct ide_host *host; + struct resource *res; + unsigned long tf_base = 0, ctl_base = 0; + struct at91_cf_data *board = pdev->dev.platform_data; + + if (!board) + return -ENODEV; + + if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) { + perr("no device detected\n"); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + perr("can't get memory resource\n"); + return -ENODEV; + } + + if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE, + REGS_SIZE, "ide") || + !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE, + REGS_SIZE, "alt")) { + perr("memory resources in use\n"); + return -EBUSY; + } + + pdbg("chipselect %u irq %u res %08lx\n", board->chipselect, + board->irq_pin, (unsigned long) res->start); + + tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE, + REGS_SIZE); + ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE, + REGS_SIZE); + if (!tf_base || !ctl_base) { + perr("can't map memory regions\n"); + return -EBUSY; + } + + memset(&hw, 0, sizeof(hw)); + + if (board->flags & AT91_IDE_SWAP_A0_A2) { + /* workaround for stupid hardware bug */ + hw.io_ports.data_addr = tf_base + 0; + hw.io_ports.error_addr = tf_base + 4; + hw.io_ports.nsect_addr = tf_base + 2; + hw.io_ports.lbal_addr = tf_base + 6; + hw.io_ports.lbam_addr = tf_base + 1; + hw.io_ports.lbah_addr = tf_base + 5; + hw.io_ports.device_addr = tf_base + 3; + hw.io_ports.command_addr = tf_base + 7; + hw.io_ports.ctl_addr = ctl_base + 3; + } else + ide_std_init_ports(&hw, tf_base, ctl_base + 6); + + hw.irq = board->irq_pin; + hw.chipset = ide_generic; + hw.dev = &pdev->dev; + + host = ide_host_alloc(&at91_ide_port_info, hws); + if (!host) { + perr("failed to allocate ide host\n"); + return -ENOMEM; + } + + /* setup Static Memory Controller - PIO 0 as default */ + apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0); + + /* with GPIO interrupt we have to do quirks in handler */ + if (board->irq_pin >= PIN_BASE) + host->irq_handler = at91_irq_handler; + + host->ports[0]->select_data = board->chipselect; + + ret = ide_host_register(host, &at91_ide_port_info, hws); + if (ret) { + perr("failed to register ide host\n"); + goto err_free_host; + } + platform_set_drvdata(pdev, host); + return 0; + +err_free_host: + ide_host_free(host); + return ret; +} + +static int __exit at91_ide_remove(struct platform_device *pdev) +{ + struct ide_host *host = platform_get_drvdata(pdev); + + ide_host_remove(host); + return 0; +} + +static struct platform_driver at91_ide_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(at91_ide_remove), +}; + +static int __init at91_ide_init(void) +{ + return platform_driver_probe(&at91_ide_driver, at91_ide_probe); +} + +static void __exit at91_ide_exit(void) +{ + platform_driver_unregister(&at91_ide_driver); +} + +module_init(at91_ide_init); +module_exit(at91_ide_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stanislaw Gruszka <stf_xl@wp.pl>"); + diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c index b2735d28f5c..ecd1e62ca91 100644 --- a/drivers/ide/atiixp.c +++ b/drivers/ide/atiixp.c @@ -52,7 +52,7 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio) { struct pci_dev *dev = to_pci_dev(drive->hwif->dev); unsigned long flags; - int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; + int timing_shift = (drive->dn ^ 1) * 8; u32 pio_timing_data; u16 pio_mode_data; @@ -85,7 +85,7 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed) { struct pci_dev *dev = to_pci_dev(drive->hwif->dev); unsigned long flags; - int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8; + int timing_shift = (drive->dn ^ 1) * 8; u32 tmp32; u16 tmp16; u16 udma_ctl = 0; diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e96c0126059..e9d042dba0e 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -140,6 +140,12 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, rq->cmd_flags |= REQ_PREEMPT; rq->buffer = (char *)pc; rq->rq_disk = disk; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; @@ -159,6 +165,12 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; rq->buffer = (char *)pc; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 0bfeb0c79d6..ddfbea41d29 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -55,7 +55,7 @@ static DEFINE_MUTEX(idecd_ref_mutex); -static void ide_cd_release(struct kref *); +static void ide_cd_release(struct device *); static struct cdrom_info *ide_cd_get(struct gendisk *disk) { @@ -67,7 +67,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk) if (ide_device_get(cd->drive)) cd = NULL; else - kref_get(&cd->kref); + get_device(&cd->dev); } mutex_unlock(&idecd_ref_mutex); @@ -79,7 +79,7 @@ static void ide_cd_put(struct cdrom_info *cd) ide_drive_t *drive = cd->drive; mutex_lock(&idecd_ref_mutex); - kref_put(&cd->kref, ide_cd_release); + put_device(&cd->dev); ide_device_put(drive); mutex_unlock(&idecd_ref_mutex); } @@ -194,6 +194,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, bio_sectors = max(bio_sectors(failed_command->bio), 4U); sector &= ~(bio_sectors - 1); + /* + * The SCSI specification allows for the value + * returned by READ CAPACITY to be up to 75 2K + * sectors past the last readable block. + * Therefore, if we hit a medium error within the + * last 75 2K sectors, we decrease the saved size + * value. + */ if (sector < get_capacity(info->disk) && drive->probed_capacity - sector < 4 * 75) set_capacity(info->disk, sector); @@ -1790,15 +1798,17 @@ static void ide_cd_remove(ide_drive_t *drive) ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); ide_proc_unregister_driver(drive, info->driver); - + device_del(&info->dev); del_gendisk(info->disk); - ide_cd_put(info); + mutex_lock(&idecd_ref_mutex); + put_device(&info->dev); + mutex_unlock(&idecd_ref_mutex); } -static void ide_cd_release(struct kref *kref) +static void ide_cd_release(struct device *dev) { - struct cdrom_info *info = to_ide_drv(kref, cdrom_info); + struct cdrom_info *info = to_ide_drv(dev, cdrom_info); struct cdrom_device_info *devinfo = &info->devinfo; ide_drive_t *drive = info->drive; struct gendisk *g = info->disk; @@ -1997,7 +2007,12 @@ static int ide_cd_probe(ide_drive_t *drive) ide_init_disk(g, drive); - kref_init(&info->kref); + info->dev.parent = &drive->gendev; + info->dev.release = ide_cd_release; + dev_set_name(&info->dev, dev_name(&drive->gendev)); + + if (device_register(&info->dev)) + goto out_free_disk; info->drive = drive; info->driver = &ide_cdrom_driver; @@ -2011,7 +2026,7 @@ static int ide_cd_probe(ide_drive_t *drive) g->driverfs_dev = &drive->gendev; g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { - ide_cd_release(&info->kref); + put_device(&info->dev); goto failed; } @@ -2021,6 +2036,8 @@ static int ide_cd_probe(ide_drive_t *drive) add_disk(g); return 0; +out_free_disk: + put_disk(g); out_free_cd: kfree(info); failed: diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index ac40d6cb90a..c878bfcf111 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -80,7 +80,7 @@ struct cdrom_info { ide_drive_t *drive; struct ide_driver *driver; struct gendisk *disk; - struct kref kref; + struct device dev; /* Buffer for table of contents. NULL if we haven't allocated a TOC buffer for this device yet. */ diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c index 1146f4204c6..1f86dcbd2b1 100644 --- a/drivers/ide/ide-disk_proc.c +++ b/drivers/ide/ide-disk_proc.c @@ -125,5 +125,5 @@ const struct ide_proc_devset ide_disk_settings[] = { IDE_PROC_DEVSET(multcount, 0, 16), IDE_PROC_DEVSET(nowerr, 0, 1), IDE_PROC_DEVSET(wcache, 0, 1), - { 0 }, + { NULL }, }; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 72ebab0bc75..059c90bb5ad 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -128,6 +128,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; + int i; ide_map_sg(drive, rq); @@ -136,8 +137,13 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) else hwif->sg_dma_direction = DMA_TO_DEVICE; - return dma_map_sg(hwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); + i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction); + if (i) { + hwif->orig_sg_nents = hwif->sg_nents; + hwif->sg_nents = i; + } + + return i; } EXPORT_SYMBOL_GPL(ide_build_sglist); @@ -156,7 +162,7 @@ void ide_destroy_dmatable(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents, + dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents, hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_destroy_dmatable); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 3eab1c6c9b3..317ec62c33d 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -327,8 +327,10 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, return ide_stopped; } - ide_init_sg_cmd(drive, rq); - ide_map_sg(drive, rq); + if (blk_fs_request(rq) || pc->req_xfer) { + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } pc->sg = hwif->sg_table; pc->sg_cnt = hwif->sg_nents; diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c index 3ec762cb60a..fcd4d8153df 100644 --- a/drivers/ide/ide-floppy_proc.c +++ b/drivers/ide/ide-floppy_proc.c @@ -29,5 +29,5 @@ const struct ide_proc_devset ide_floppy_settings[] = { IDE_PROC_DEVSET(bios_head, 0, 255), IDE_PROC_DEVSET(bios_sect, 0, 63), IDE_PROC_DEVSET(ticks, 0, 255), - { 0 }, + { NULL }, }; diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index 7857b209c6d..04710941990 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -25,7 +25,7 @@ module_param(debug_mask, ulong, 0644); static DEFINE_MUTEX(ide_disk_ref_mutex); -static void ide_disk_release(struct kref *); +static void ide_disk_release(struct device *); static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) { @@ -37,7 +37,7 @@ static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) if (ide_device_get(idkp->drive)) idkp = NULL; else - kref_get(&idkp->kref); + get_device(&idkp->dev); } mutex_unlock(&ide_disk_ref_mutex); return idkp; @@ -48,7 +48,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp) ide_drive_t *drive = idkp->drive; mutex_lock(&ide_disk_ref_mutex); - kref_put(&idkp->kref, ide_disk_release); + put_device(&idkp->dev); ide_device_put(drive); mutex_unlock(&ide_disk_ref_mutex); } @@ -66,17 +66,18 @@ static void ide_gd_remove(ide_drive_t *drive) struct gendisk *g = idkp->disk; ide_proc_unregister_driver(drive, idkp->driver); - + device_del(&idkp->dev); del_gendisk(g); - drive->disk_ops->flush(drive); - ide_disk_put(idkp); + mutex_lock(&ide_disk_ref_mutex); + put_device(&idkp->dev); + mutex_unlock(&ide_disk_ref_mutex); } -static void ide_disk_release(struct kref *kref) +static void ide_disk_release(struct device *dev) { - struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj); + struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj); ide_drive_t *drive = idkp->drive; struct gendisk *g = idkp->disk; @@ -348,7 +349,12 @@ static int ide_gd_probe(ide_drive_t *drive) ide_init_disk(g, drive); - kref_init(&idkp->kref); + idkp->dev.parent = &drive->gendev; + idkp->dev.release = ide_disk_release; + dev_set_name(&idkp->dev, dev_name(&drive->gendev)); + + if (device_register(&idkp->dev)) + goto out_free_disk; idkp->drive = drive; idkp->driver = &ide_gd_driver; @@ -373,6 +379,8 @@ static int ide_gd_probe(ide_drive_t *drive) add_disk(g); return 0; +out_free_disk: + put_disk(g); out_free_idkp: kfree(idkp); failed: diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h index a86779f0756..b604bdd318a 100644 --- a/drivers/ide/ide-gd.h +++ b/drivers/ide/ide-gd.h @@ -17,7 +17,7 @@ struct ide_disk_obj { ide_drive_t *drive; struct ide_driver *driver; struct gendisk *disk; - struct kref kref; + struct device dev; unsigned int openers; /* protected by BKL for now */ /* Last failed packet command */ diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 9ee51adf567..a9a6c208288 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -908,7 +908,7 @@ void ide_timer_expiry (unsigned long data) ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; unsigned long flags; - unsigned long wait = -1; + int wait = -1; int plug_device = 0; spin_lock_irqsave(&hwif->lock, flags); @@ -1162,6 +1162,7 @@ out_early: return irq_ret; } +EXPORT_SYMBOL_GPL(ide_intr); /** * ide_do_drive_cmd - issue IDE special command diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 753b92ebe0a..b1892bd95c6 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -315,6 +315,8 @@ void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, u8 io_32bit = drive->io_32bit; u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + len++; + if (io_32bit) { unsigned long uninitialized_var(flags); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ce0818a993f..ee8e3e7cad5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -950,6 +950,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) static int init_irq (ide_hwif_t *hwif) { struct ide_io_ports *io_ports = &hwif->io_ports; + irq_handler_t irq_handler; int sa = 0; mutex_lock(&ide_cfg_mtx); @@ -959,6 +960,10 @@ static int init_irq (ide_hwif_t *hwif) hwif->timer.function = &ide_timer_expiry; hwif->timer.data = (unsigned long)hwif; + irq_handler = hwif->host->irq_handler; + if (irq_handler == NULL) + irq_handler = ide_intr; + #if defined(__mc68000__) sa = IRQF_SHARED; #endif /* __mc68000__ */ @@ -969,7 +974,7 @@ static int init_irq (ide_hwif_t *hwif) if (io_ports->ctl_addr) hwif->tp_ops->set_irq(hwif, 1); - if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif)) + if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) goto out_up; if (!hwif->rqsize) { diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 1d8978b3314..a7b9287ee0d 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -231,7 +231,7 @@ static const struct ide_proc_devset ide_generic_settings[] = { IDE_PROC_DEVSET(pio_mode, 0, 255), IDE_PROC_DEVSET(unmaskirq, 0, 1), IDE_PROC_DEVSET(using_dma, 0, 1), - { 0 }, + { NULL }, }; static void proc_ide_settings_warn(void) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d7ecd3c7975..4e6181c7bbd 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -169,7 +169,7 @@ typedef struct ide_tape_obj { ide_drive_t *drive; struct ide_driver *driver; struct gendisk *disk; - struct kref kref; + struct device dev; /* * failed_pc points to the last failed packet command, or contains @@ -267,7 +267,7 @@ static DEFINE_MUTEX(idetape_ref_mutex); static struct class *idetape_sysfs_class; -static void ide_tape_release(struct kref *); +static void ide_tape_release(struct device *); static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) { @@ -279,7 +279,7 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) if (ide_device_get(tape->drive)) tape = NULL; else - kref_get(&tape->kref); + get_device(&tape->dev); } mutex_unlock(&idetape_ref_mutex); return tape; @@ -290,7 +290,7 @@ static void ide_tape_put(struct ide_tape_obj *tape) ide_drive_t *drive = tape->drive; mutex_lock(&idetape_ref_mutex); - kref_put(&tape->kref, ide_tape_release); + put_device(&tape->dev); ide_device_put(drive); mutex_unlock(&idetape_ref_mutex); } @@ -308,7 +308,7 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) mutex_lock(&idetape_ref_mutex); tape = idetape_devs[i]; if (tape) - kref_get(&tape->kref); + get_device(&tape->dev); mutex_unlock(&idetape_ref_mutex); return tape; } @@ -2166,7 +2166,7 @@ static const struct ide_proc_devset idetape_settings[] = { __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL), __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, mulf_tdsc, divf_tdsc), - { 0 }, + { NULL }, }; #endif @@ -2256,15 +2256,17 @@ static void ide_tape_remove(ide_drive_t *drive) idetape_tape_t *tape = drive->driver_data; ide_proc_unregister_driver(drive, tape->driver); - + device_del(&tape->dev); ide_unregister_region(tape->disk); - ide_tape_put(tape); + mutex_lock(&idetape_ref_mutex); + put_device(&tape->dev); + mutex_unlock(&idetape_ref_mutex); } -static void ide_tape_release(struct kref *kref) +static void ide_tape_release(struct device *dev) { - struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj); + struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj); ide_drive_t *drive = tape->drive; struct gendisk *g = tape->disk; @@ -2407,7 +2409,12 @@ static int ide_tape_probe(ide_drive_t *drive) ide_init_disk(g, drive); - kref_init(&tape->kref); + tape->dev.parent = &drive->gendev; + tape->dev.release = ide_tape_release; + dev_set_name(&tape->dev, dev_name(&drive->gendev)); + + if (device_register(&tape->dev)) + goto out_free_disk; tape->drive = drive; tape->driver = &idetape_driver; @@ -2436,6 +2443,8 @@ static int ide_tape_probe(ide_drive_t *drive) return 0; +out_free_disk: + put_disk(g); out_free_tape: kfree(tape); failed: diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 258805da15c..0920e3b0c96 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -337,6 +337,7 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) int a, b, i, j = 1; unsigned int *dev_param_mask = (unsigned int *)kp->arg; + /* controller . device (0 or 1) [ : 1 (set) | 0 (clear) ] */ if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 && sscanf(s, "%d.%d", &a, &b) != 2) return -EINVAL; @@ -349,7 +350,7 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) if (j) *dev_param_mask |= (1 << i); else - *dev_param_mask &= (1 << i); + *dev_param_mask &= ~(1 << i); return 0; } @@ -392,6 +393,8 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp) { int a, b, c = 0, h = 0, s = 0, i, j = 1; + /* controller . device (0 or 1) : Cylinders , Heads , Sectors */ + /* controller . device (0 or 1) : 1 (use CHS) | 0 (ignore CHS) */ if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 && sscanf(str, "%d.%d:%d", &a, &b, &j) != 3) return -EINVAL; @@ -407,7 +410,7 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp) if (j) ide_disks |= (1 << i); else - ide_disks &= (1 << i); + ide_disks &= ~(1 << i); ide_disks_chs[i].cyl = c; ide_disks_chs[i].head = h; @@ -469,6 +472,8 @@ static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) { int i, j = 1; + /* controller (ignore) */ + /* controller : 1 (ignore) | 0 (use) */ if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1) return -EINVAL; @@ -478,7 +483,7 @@ static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) if (j) ide_ignore_cable |= (1 << i); else - ide_ignore_cable &= (1 << i); + ide_ignore_cable &= ~(1 << i); return 0; } diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index e1c4f543739..13b8153112e 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c @@ -5,9 +5,8 @@ * May be copied or modified under the terms of the GNU General Public License * Based in part on the ITE vendor provided SCSI driver. * - * Documentation available from - * http://www.ite.com.tw/pc/IT8212F_V04.pdf - * Some other documents are NDA. + * Documentation: + * Datasheet is freely available, some other documents under NDA. * * The ITE8212 isn't exactly a standard IDE controller. It has two * modes. In pass through mode then it is an IDE controller. In its smart diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 1028e725a27..87233800372 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -1275,7 +1275,7 @@ static void __exit ieee1394_cleanup(void) unregister_chrdev_region(IEEE1394_CORE_DEV, 256); } -module_init(ieee1394_init); +fs_initcall(ieee1394_init); module_exit(ieee1394_cleanup); /* Exported symbols */ diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index a01b4488208..4a65b96db2c 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -2490,12 +2490,14 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) int ret = 0; struct nes_vnic *nesvnic; struct nes_device *nesdev; + struct nes_ib_device *nesibdev; nesvnic = to_nesvnic(nesqp->ibqp.device); if (!nesvnic) return -EINVAL; nesdev = nesvnic->nesdev; + nesibdev = nesvnic->nesibdev; nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", atomic_read(&nesvnic->netdev->refcnt)); @@ -2507,6 +2509,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) } else { /* Need to free the Last Streaming Mode Message */ if (nesqp->ietf_frame) { + if (nesqp->lsmm_mr) + nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr); pci_free_consistent(nesdev->pcidev, nesqp->private_data_len+sizeof(struct ietf_mpa_frame), nesqp->ietf_frame, nesqp->ietf_frame_pbase); @@ -2543,6 +2547,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) u32 crc_value; int ret; int passive_state; + struct nes_ib_device *nesibdev; + struct ib_mr *ibmr = NULL; + struct ib_phys_buf ibphysbuf; + struct nes_pd *nespd; + + ibqp = nes_get_qp(cm_id->device, conn_param->qpn); if (!ibqp) @@ -2601,6 +2611,26 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) { u64temp = (unsigned long)nesqp; + nesibdev = nesvnic->nesibdev; + nespd = nesqp->nespd; + ibphysbuf.addr = nesqp->ietf_frame_pbase; + ibphysbuf.size = conn_param->private_data_len + + sizeof(struct ietf_mpa_frame); + ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, + &ibphysbuf, 1, + IB_ACCESS_LOCAL_WRITE, + (u64 *)&nesqp->ietf_frame); + if (!ibmr) { + nes_debug(NES_DBG_CM, "Unable to register memory region" + "for lSMM for cm_node = %p \n", + cm_node); + return -ENOMEM; + } + + ibmr->pd = &nespd->ibpd; + ibmr->device = nespd->ibpd.device; + nesqp->lsmm_mr = ibmr; + u64temp |= NES_SW_CONTEXT_ALIGN>>1; set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, @@ -2611,14 +2641,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = - cpu_to_le32((u32)nesqp->ietf_frame_pbase); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = - cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); + set_wqe_64bit_value(wqe->wqe_words, + NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, + (u64)nesqp->ietf_frame); wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey; nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 4fdb72454f9..d93a6562817 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1360,8 +1360,10 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT); nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size << NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT); + if (!udata) { nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN); nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN); + } nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number + ((u32)nesqp->nesrcq->hw_cq.cq_number << 16)); u64temp = (u64)nesqp->hwqp.sq_pbase; diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 6c6b4da5184..ae0ca9bc83b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -134,6 +134,7 @@ struct nes_qp { struct ietf_mpa_frame *ietf_frame; dma_addr_t ietf_frame_pbase; wait_queue_head_t state_waitq; + struct ib_mr *lsmm_mr; unsigned long socket; struct nes_hw_qp hwqp; struct work_struct work; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index c3c8b9bc40a..45470f18d7e 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -839,7 +839,7 @@ static void atkbd_disconnect(struct serio *serio) */ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) { - const unsigned int forced_release_keys[] = { + static const unsigned int forced_release_keys[] = { 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, }; int i; @@ -856,7 +856,7 @@ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) */ static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) { - const unsigned int forced_release_keys[] = { + static const unsigned int forced_release_keys[] = { 0x94, }; int i; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 19284016e0f..ee855c5202e 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -209,8 +209,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) goto out; } - if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || - !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { + if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || + !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { printk(KERN_ERR DRV_NAME ": Invalid Debounce/Columdrive Time from pdata\n"); bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index c8ed065ea0c..abb04c82c62 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -288,7 +288,7 @@ static int corgikbd_resume(struct platform_device *dev) #define corgikbd_resume NULL #endif -static int __init corgikbd_probe(struct platform_device *pdev) +static int __devinit corgikbd_probe(struct platform_device *pdev) { struct corgikbd *corgikbd; struct input_dev *input_dev; @@ -368,7 +368,7 @@ static int __init corgikbd_probe(struct platform_device *pdev) return err; } -static int corgikbd_remove(struct platform_device *pdev) +static int __devexit corgikbd_remove(struct platform_device *pdev) { int i; struct corgikbd *corgikbd = platform_get_drvdata(pdev); @@ -388,7 +388,7 @@ static int corgikbd_remove(struct platform_device *pdev) static struct platform_driver corgikbd_driver = { .probe = corgikbd_probe, - .remove = corgikbd_remove, + .remove = __devexit_p(corgikbd_remove), .suspend = corgikbd_suspend, .resume = corgikbd_resume, .driver = { @@ -397,7 +397,7 @@ static struct platform_driver corgikbd_driver = { }, }; -static int __devinit corgikbd_init(void) +static int __init corgikbd_init(void) { return platform_driver_register(&corgikbd_driver); } diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3f3d1198cdb..058fa8b02c2 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -279,7 +279,7 @@ static int omap_kp_resume(struct platform_device *dev) #define omap_kp_resume NULL #endif -static int __init omap_kp_probe(struct platform_device *pdev) +static int __devinit omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; struct input_dev *input_dev; @@ -422,7 +422,7 @@ err1: return -EINVAL; } -static int omap_kp_remove(struct platform_device *pdev) +static int __devexit omap_kp_remove(struct platform_device *pdev) { struct omap_kp *omap_kp = platform_get_drvdata(pdev); @@ -454,7 +454,7 @@ static int omap_kp_remove(struct platform_device *pdev) static struct platform_driver omap_kp_driver = { .probe = omap_kp_probe, - .remove = omap_kp_remove, + .remove = __devexit_p(omap_kp_remove), .suspend = omap_kp_suspend, .resume = omap_kp_resume, .driver = { @@ -463,7 +463,7 @@ static struct platform_driver omap_kp_driver = { }, }; -static int __devinit omap_kp_init(void) +static int __init omap_kp_init(void) { printk(KERN_INFO "OMAP Keypad Driver\n"); return platform_driver_register(&omap_kp_driver); diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index c48b76a46a5..9d1781a618e 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -343,7 +343,7 @@ static int spitzkbd_resume(struct platform_device *dev) #define spitzkbd_resume NULL #endif -static int __init spitzkbd_probe(struct platform_device *dev) +static int __devinit spitzkbd_probe(struct platform_device *dev) { struct spitzkbd *spitzkbd; struct input_dev *input_dev; @@ -444,7 +444,7 @@ static int __init spitzkbd_probe(struct platform_device *dev) return err; } -static int spitzkbd_remove(struct platform_device *dev) +static int __devexit spitzkbd_remove(struct platform_device *dev) { int i; struct spitzkbd *spitzkbd = platform_get_drvdata(dev); @@ -470,7 +470,7 @@ static int spitzkbd_remove(struct platform_device *dev) static struct platform_driver spitzkbd_driver = { .probe = spitzkbd_probe, - .remove = spitzkbd_remove, + .remove = __devexit_p(spitzkbd_remove), .suspend = spitzkbd_suspend, .resume = spitzkbd_resume, .driver = { @@ -479,7 +479,7 @@ static struct platform_driver spitzkbd_driver = { }, }; -static int __devinit spitzkbd_init(void) +static int __init spitzkbd_init(void) { return platform_driver_register(&spitzkbd_driver); } diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 093c8c1bca7..9705f3a00a3 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS config MOUSE_PS2_LIFEBOOK bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED default y - depends on MOUSE_PS2 + depends on MOUSE_PS2 && X86 help Say Y here if you have a Fujitsu B-series Lifebook PS/2 TouchScreen connected to your system. diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b9a25d57bc5..6ab0eb1ada1 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -542,7 +542,7 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - pr_err("elantech.c: sending Elantech magic knock failed.\n"); + pr_debug("elantech.c: sending Elantech magic knock failed.\n"); return -1; } @@ -551,8 +551,27 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) * set of magic numbers */ if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { - pr_info("elantech.c: unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); + pr_debug("elantech.c: " + "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", + param[0], param[1], param[2]); + return -1; + } + + /* + * Query touchpad's firmware version and see if it reports known + * value to avoid mis-detection. Logitech mice are known to respond + * to Elantech magic knock and there might be more. + */ + if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { + pr_debug("elantech.c: failed to query firmware version.\n"); + return -1; + } + + pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", + param[0], param[1], param[2]); + + if (param[0] == 0 || param[1] != 0) { + pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); return -1; } @@ -600,8 +619,7 @@ int elantech_init(struct psmouse *psmouse) int i, error; unsigned char param[3]; - etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); - psmouse->private = etd; + psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); if (!etd) return -1; @@ -610,14 +628,12 @@ int elantech_init(struct psmouse *psmouse) etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; /* - * Find out what version hardware this is + * Do the version query again so we can store the result */ if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { pr_err("elantech.c: failed to query firmware version.\n"); goto init_fail; } - pr_info("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); etd->fw_version_maj = param[0]; etd->fw_version_min = param[2]; diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index d297accf9a7..1e827ad0afb 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -83,7 +83,7 @@ static int write_tbcr(struct pxa930_trkball *trkball, int v) __raw_writel(v, trkball->mmio_base + TBCR); - while (i--) { + while (--i) { if (__raw_readl(trkball->mmio_base + TBCR) == v) break; msleep(1); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 865fc69e9bc..f3e4f7b0240 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -182,11 +182,6 @@ static int synaptics_identify(struct psmouse *psmouse) static int synaptics_query_hardware(struct psmouse *psmouse) { - int retries = 0; - - while ((retries++ < 3) && psmouse_reset(psmouse)) - /* empty */; - if (synaptics_identify(psmouse)) return -1; if (synaptics_model_id(psmouse)) @@ -582,6 +577,8 @@ static int synaptics_reconnect(struct psmouse *psmouse) struct synaptics_data *priv = psmouse->private; struct synaptics_data old_priv = *priv; + psmouse_reset(psmouse); + if (synaptics_detect(psmouse, 0)) return -1; @@ -640,6 +637,8 @@ int synaptics_init(struct psmouse *psmouse) if (!priv) return -1; + psmouse_reset(psmouse); + if (synaptics_query_hardware(psmouse)) { printk(KERN_ERR "Unable to query Synaptics hardware.\n"); goto init_fail; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index b10ffae7c39..e29cdc13a19 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -57,7 +57,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val) struct amba_kmi_port *kmi = io->port_data; unsigned int timeleft = 10000; /* timeout in 100ms */ - while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) + while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft) udelay(10); if (timeleft) @@ -129,8 +129,8 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) io->write = amba_kmi_write; io->open = amba_kmi_open; io->close = amba_kmi_close; - strlcpy(io->name, dev->dev.bus_id, sizeof(io->name)); - strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys)); + strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name)); + strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys)); io->port_data = kmi; io->dev.parent = &dev->dev; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index adc3bd6e7f7..bd0f92d9f40 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -359,7 +359,7 @@ static int __init gscps2_probe(struct parisc_device *dev) snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); - strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); serio->id.type = SERIO_8042; serio->write = gscps2_write; serio->open = gscps2_open; diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 2ad88780a17..57953c0eb82 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -246,8 +246,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) serio->write = ps2_write; serio->open = ps2_open; serio->close = ps2_close; - strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name)); - strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name)); + strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); serio->port_data = ps2if; serio->dev.parent = &dev->dev; ps2if->io = serio; diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index a89a6a8f05e..055969e8be1 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -236,7 +236,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) ts_dev->bufferedmeasure = 0; snprintf(ts_dev->phys, sizeof(ts_dev->phys), - "%s/input0", pdev->dev.bus_id); + "%s/input0", dev_name(&pdev->dev)); input_dev->name = "atmel touch screen controller"; input_dev->phys = ts_dev->phys; diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 65202c9f63f..3fb51b54fe6 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c @@ -268,7 +268,7 @@ static int corgits_resume(struct platform_device *dev) #define corgits_resume NULL #endif -static int __init corgits_probe(struct platform_device *pdev) +static int __devinit corgits_probe(struct platform_device *pdev) { struct corgi_ts *corgi_ts; struct input_dev *input_dev; @@ -343,7 +343,7 @@ static int __init corgits_probe(struct platform_device *pdev) return err; } -static int corgits_remove(struct platform_device *pdev) +static int __devexit corgits_remove(struct platform_device *pdev) { struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); @@ -352,12 +352,13 @@ static int corgits_remove(struct platform_device *pdev) corgi_ts->machinfo->put_hsync(); input_unregister_device(corgi_ts->input); kfree(corgi_ts); + return 0; } static struct platform_driver corgits_driver = { .probe = corgits_probe, - .remove = corgits_remove, + .remove = __devexit_p(corgits_remove), .suspend = corgits_suspend, .resume = corgits_resume, .driver = { @@ -366,7 +367,7 @@ static struct platform_driver corgits_driver = { }, }; -static int __devinit corgits_init(void) +static int __init corgits_init(void) { return platform_driver_register(&corgits_driver); } diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index b75dc299057..4ab07024689 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -289,7 +289,8 @@ static int tsc2007_probe(struct i2c_client *client, pdata->init_platform_hw(); - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id); + snprintf(ts->phys, sizeof(ts->phys), + "%s/input0", dev_name(&client->dev)); input_dev->name = "TSC2007 Touchscreen"; input_dev->phys = ts->phys; diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 5080b26ba16..fb7cb9bdfbd 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -60,6 +60,10 @@ static int swap_xy; module_param(swap_xy, bool, 0644); MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); +static int hwcalib_xy; +module_param(hwcalib_xy, bool, 0644); +MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); + /* device specifc data/functions */ struct usbtouch_usb; struct usbtouch_device_info { @@ -118,6 +122,7 @@ enum { #define USB_DEVICE_HID_CLASS(vend, prod) \ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ + | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ | USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ .idProduct = (prod), \ @@ -260,8 +265,13 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) { - dev->x = (pkt[8] << 8) | pkt[7]; - dev->y = (pkt[10] << 8) | pkt[9]; + if (hwcalib_xy) { + dev->x = (pkt[4] << 8) | pkt[3]; + dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); + } else { + dev->x = (pkt[8] << 8) | pkt[7]; + dev->y = (pkt[10] << 8) | pkt[9]; + } dev->touch = (pkt[2] & 0x40) ? 1 : 0; return 1; @@ -294,6 +304,12 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) return ret; } + /* Default min/max xy are the raw values, override if using hw-calib */ + if (hwcalib_xy) { + input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); + input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); + } + return 0; } #endif diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 18dd8aacbe8..831ddce1467 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -46,6 +46,9 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); /* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ #define IF_WRITEBUF 264 +/* interrupt pipe message size according to ibid. ch. 2.2 */ +#define IP_MSGSIZE 3 + /* Values for the Gigaset 307x */ #define USB_GIGA_VENDOR_ID 0x0681 #define USB_3070_PRODUCT_ID 0x0001 @@ -110,7 +113,7 @@ struct bas_cardstate { unsigned char *rcvbuf; /* AT reply receive buffer */ struct urb *urb_int_in; /* URB for interrupt pipe */ - unsigned char int_in_buf[3]; + unsigned char *int_in_buf; spinlock_t lock; /* locks all following */ int basstate; /* bitmap (BS_*) */ @@ -657,7 +660,7 @@ static void read_int_callback(struct urb *urb) } /* drop incomplete packets even if the missing bytes wouldn't matter */ - if (unlikely(urb->actual_length < 3)) { + if (unlikely(urb->actual_length < IP_MSGSIZE)) { dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", urb->actual_length); goto resubmit; @@ -2127,6 +2130,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { /* timers, URBs and rcvbuf are disposed of in disconnect */ + kfree(cs->hw.bas->int_in_buf); kfree(cs->hw.bas); cs->hw.bas = NULL; } @@ -2140,6 +2144,12 @@ static int gigaset_initcshw(struct cardstate *cs) pr_err("out of memory\n"); return 0; } + ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL); + if (!ucs->int_in_buf) { + kfree(ucs); + pr_err("out of memory\n"); + return 0; + } ucs->urb_cmd_in = NULL; ucs->urb_cmd_out = NULL; @@ -2292,7 +2302,7 @@ static int gigaset_probe(struct usb_interface *interface, usb_fill_int_urb(ucs->urb_int_in, udev, usb_rcvintpipe(udev, (endpoint->bEndpointAddress) & 0x0f), - ucs->int_in_buf, 3, read_int_callback, cs, + ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, endpoint->bInterval); if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { dev_err(cs->dev, "could not submit interrupt URB: %s\n", diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index b4d44e571d7..8132533d71f 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -212,6 +212,9 @@ static void lg_notify(struct virtqueue *vq) hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0); } +/* An extern declaration inside a C file is bad form. Don't do it. */ +extern void lguest_setup_irq(unsigned int irq); + /* This routine finds the first virtqueue described in the configuration of * this device and sets it up. * @@ -266,6 +269,9 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, goto unmap; } + /* Make sure the interrupt is allocated. */ + lguest_setup_irq(lvq->config.irq); + /* Tell the interrupt for this virtqueue to go to the virtio_ring * interrupt handler. */ /* FIXME: We used to have a flag for the Host to tell us we could use diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 35bda49796f..bfefd079a95 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -60,6 +60,7 @@ struct dm_crypt_io { }; struct dm_crypt_request { + struct convert_context *ctx; struct scatterlist sg_in; struct scatterlist sg_out; }; @@ -335,6 +336,18 @@ static void crypt_convert_init(struct crypt_config *cc, init_completion(&ctx->restart); } +static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc, + struct ablkcipher_request *req) +{ + return (struct dm_crypt_request *)((char *)req + cc->dmreq_start); +} + +static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, + struct dm_crypt_request *dmreq) +{ + return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); +} + static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, struct ablkcipher_request *req) @@ -345,10 +358,11 @@ static int crypt_convert_block(struct crypt_config *cc, u8 *iv; int r = 0; - dmreq = (struct dm_crypt_request *)((char *)req + cc->dmreq_start); + dmreq = dmreq_of_req(cc, req); iv = (u8 *)ALIGN((unsigned long)(dmreq + 1), crypto_ablkcipher_alignmask(cc->tfm) + 1); + dmreq->ctx = ctx; sg_init_table(&dmreq->sg_in, 1); sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in); @@ -395,8 +409,9 @@ static void crypt_alloc_req(struct crypt_config *cc, cc->req = mempool_alloc(cc->req_pool, GFP_NOIO); ablkcipher_request_set_tfm(cc->req, cc->tfm); ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - kcryptd_async_done, ctx); + CRYPTO_TFM_REQ_MAY_SLEEP, + kcryptd_async_done, + dmreq_of_req(cc, cc->req)); } /* @@ -553,19 +568,22 @@ static void crypt_inc_pending(struct dm_crypt_io *io) static void crypt_dec_pending(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; + struct bio *base_bio = io->base_bio; + struct dm_crypt_io *base_io = io->base_io; + int error = io->error; if (!atomic_dec_and_test(&io->pending)) return; - if (likely(!io->base_io)) - bio_endio(io->base_bio, io->error); + mempool_free(io, cc->io_pool); + + if (likely(!base_io)) + bio_endio(base_bio, error); else { - if (io->error && !io->base_io->error) - io->base_io->error = io->error; - crypt_dec_pending(io->base_io); + if (error && !base_io->error) + base_io->error = error; + crypt_dec_pending(base_io); } - - mempool_free(io, cc->io_pool); } /* @@ -821,7 +839,8 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) static void kcryptd_async_done(struct crypto_async_request *async_req, int error) { - struct convert_context *ctx = async_req->data; + struct dm_crypt_request *dmreq = async_req->data; + struct convert_context *ctx = dmreq->ctx; struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); struct crypt_config *cc = io->target->private; @@ -830,7 +849,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, return; } - mempool_free(ablkcipher_request_cast(async_req), cc->req_pool); + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); if (!atomic_dec_and_test(&ctx->pending)) return; diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index f14813be4ef..36e2b5e46a6 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -292,6 +292,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, (PAGE_SIZE >> SECTOR_SHIFT)); num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs); + if (unlikely(num_bvecs > BIO_MAX_PAGES)) + num_bvecs = BIO_MAX_PAGES; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 54d0588fc1f..f01096549a9 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -704,7 +704,8 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) char *new_name = (char *) param + param->data_start; if (new_name < param->data || - invalid_str(new_name, (void *) param + param_size)) { + invalid_str(new_name, (void *) param + param_size) || + strlen(new_name) > DM_NAME_LEN - 1) { DMWARN("Invalid new logical volume name supplied."); return -EINVAL; } @@ -1063,7 +1064,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) r = populate_table(t, param, param_size); if (r) { - dm_table_put(t); + dm_table_destroy(t); goto out; } @@ -1071,7 +1072,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) hc = dm_get_mdptr(md); if (!hc || hc->md != md) { DMWARN("device has been removed from the dev hash table."); - dm_table_put(t); + dm_table_destroy(t); up_write(&_hash_lock); r = -ENXIO; goto out; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 51ba1db4b3e..8d40f27cce8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -525,9 +525,12 @@ static int __noflush_suspending(struct mapped_device *md) static void dec_pending(struct dm_io *io, int error) { unsigned long flags; + int io_error; + struct bio *bio; + struct mapped_device *md = io->md; /* Push-back supersedes any I/O errors */ - if (error && !(io->error > 0 && __noflush_suspending(io->md))) + if (error && !(io->error > 0 && __noflush_suspending(md))) io->error = error; if (atomic_dec_and_test(&io->io_count)) { @@ -537,24 +540,27 @@ static void dec_pending(struct dm_io *io, int error) * This must be handled before the sleeper on * suspend queue merges the pushback list. */ - spin_lock_irqsave(&io->md->pushback_lock, flags); - if (__noflush_suspending(io->md)) - bio_list_add(&io->md->pushback, io->bio); + spin_lock_irqsave(&md->pushback_lock, flags); + if (__noflush_suspending(md)) + bio_list_add(&md->pushback, io->bio); else /* noflush suspend was interrupted. */ io->error = -EIO; - spin_unlock_irqrestore(&io->md->pushback_lock, flags); + spin_unlock_irqrestore(&md->pushback_lock, flags); } end_io_acct(io); - if (io->error != DM_ENDIO_REQUEUE) { - trace_block_bio_complete(io->md->queue, io->bio); + io_error = io->error; + bio = io->bio; - bio_endio(io->bio, io->error); - } + free_io(md, io); + + if (io_error != DM_ENDIO_REQUEUE) { + trace_block_bio_complete(md->queue, bio); - free_io(io->md, io); + bio_endio(bio, io_error); + } } } @@ -562,6 +568,7 @@ static void clone_endio(struct bio *bio, int error) { int r = 0; struct dm_target_io *tio = bio->bi_private; + struct dm_io *io = tio->io; struct mapped_device *md = tio->io->md; dm_endio_fn endio = tio->ti->type->end_io; @@ -585,15 +592,14 @@ static void clone_endio(struct bio *bio, int error) } } - dec_pending(tio->io, error); - /* * Store md for cleanup instead of tio which is about to get freed. */ bio->bi_private = md->bs; - bio_put(bio); free_tio(md, tio); + bio_put(bio); + dec_pending(io, error); } static sector_t max_io_len(struct mapped_device *md, diff --git a/drivers/md/md.c b/drivers/md/md.c index 03b4cd0a634..a307f87eb90 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -214,12 +214,7 @@ static inline mddev_t *mddev_get(mddev_t *mddev) return mddev; } -static void mddev_delayed_delete(struct work_struct *ws) -{ - mddev_t *mddev = container_of(ws, mddev_t, del_work); - kobject_del(&mddev->kobj); - kobject_put(&mddev->kobj); -} +static void mddev_delayed_delete(struct work_struct *ws); static void mddev_put(mddev_t *mddev) { @@ -3542,6 +3537,21 @@ static struct kobj_type md_ktype = { int mdp_major = 0; +static void mddev_delayed_delete(struct work_struct *ws) +{ + mddev_t *mddev = container_of(ws, mddev_t, del_work); + + if (mddev->private == &md_redundancy_group) { + sysfs_remove_group(&mddev->kobj, &md_redundancy_group); + if (mddev->sysfs_action) + sysfs_put(mddev->sysfs_action); + mddev->sysfs_action = NULL; + mddev->private = NULL; + } + kobject_del(&mddev->kobj); + kobject_put(&mddev->kobj); +} + static int md_alloc(dev_t dev, char *name) { static DEFINE_MUTEX(disks_mutex); @@ -4033,13 +4043,9 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) mddev->queue->merge_bvec_fn = NULL; mddev->queue->unplug_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; - if (mddev->pers->sync_request) { - sysfs_remove_group(&mddev->kobj, &md_redundancy_group); - if (mddev->sysfs_action) - sysfs_put(mddev->sysfs_action); - mddev->sysfs_action = NULL; - } module_put(mddev->pers->owner); + if (mddev->pers->sync_request) + mddev->private = &md_redundancy_group; mddev->pers = NULL; /* tell userspace to handle 'inactive' */ sysfs_notify_dirent(mddev->sysfs_state); diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c index b386cc66c6b..451974ba32f 100644 --- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c +++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c @@ -192,6 +192,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d return 0; } +EXPORT_SYMBOL(flexcop_pid_feed_control); void flexcop_hw_filter_init(struct flexcop_device *fc) { diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 5b30dfc7846..76e37fd96bb 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -13,9 +13,9 @@ static int enable_pid_filtering = 1; module_param(enable_pid_filtering, int, 0444); MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); -static int irq_chk_intv; +static int irq_chk_intv = 100; module_param(irq_chk_intv, int, 0644); -MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging)."); +MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG #define dprintk(level,args...) \ @@ -34,7 +34,9 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); +MODULE_PARM_DESC(debug, + "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." + DEBSTATUS); #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" @@ -58,6 +60,8 @@ struct flexcop_pci { int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ int count; + int count_prev; + int stream_problem; spinlock_t irq_lock; @@ -103,18 +107,32 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) container_of(work, struct flexcop_pci, irq_check_work.work); struct flexcop_device *fc = fc_pci->fc_dev; - flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); - - flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); - - if (v.sram_dest_reg_714.net_ovflow_error) - deb_chk("sram net_ovflow_error\n"); - if (v.sram_dest_reg_714.media_ovflow_error) - deb_chk("sram media_ovflow_error\n"); - if (v.sram_dest_reg_714.cai_ovflow_error) - deb_chk("sram cai_ovflow_error\n"); - if (v.sram_dest_reg_714.cai_ovflow_error) - deb_chk("sram cai_ovflow_error\n"); + if (fc->feedcount) { + + if (fc_pci->count == fc_pci->count_prev) { + deb_chk("no IRQ since the last check\n"); + if (fc_pci->stream_problem++ == 3) { + struct dvb_demux_feed *feed; + + spin_lock_irq(&fc->demux.lock); + list_for_each_entry(feed, &fc->demux.feed_list, + list_head) { + flexcop_pid_feed_control(fc, feed, 0); + } + + list_for_each_entry(feed, &fc->demux.feed_list, + list_head) { + flexcop_pid_feed_control(fc, feed, 1); + } + spin_unlock_irq(&fc->demux.lock); + + fc_pci->stream_problem = 0; + } + } else { + fc_pci->stream_problem = 0; + fc_pci->count_prev = fc_pci->count; + } + } schedule_delayed_work(&fc_pci->irq_check_work, msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); @@ -216,16 +234,12 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); deb_irq("IRQ enabled\n"); + fc_pci->count_prev = fc_pci->count; + // fc_pci->active_dma1_addr = 0; // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); - if (irq_chk_intv > 0) - schedule_delayed_work(&fc_pci->irq_check_work, - msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); } else { - if (irq_chk_intv > 0) - cancel_delayed_work(&fc_pci->irq_check_work); - flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); deb_irq("IRQ disabled\n"); @@ -299,8 +313,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) goto err_pci_iounmap; - - fc_pci->init_state |= FC_PCI_INIT; return ret; @@ -375,6 +387,10 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); + if (irq_chk_intv > 0) + schedule_delayed_work(&fc_pci->irq_check_work, + msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); + return ret; err_fc_exit: @@ -393,6 +409,9 @@ static void flexcop_pci_remove(struct pci_dev *pdev) { struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); + if (irq_chk_intv > 0) + cancel_delayed_work(&fc_pci->irq_check_work); + flexcop_pci_dma_exit(fc_pci); flexcop_device_exit(fc_pci->fc_dev); flexcop_pci_exit(fc_pci); diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 676413a915b..91068952b50 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c @@ -212,8 +212,7 @@ void flexcop_reset_block_300(struct flexcop_device *fc) v210.sw_reset_210.Block_reset_enable = 0xb2; fc->write_ibi_reg(fc,sw_reset_210,v210); - msleep(1); - + udelay(1000); fc->write_ibi_reg(fc,ctrl_208,v208_save); } diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 29e8f1546ab..fec1d77fa85 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1683,7 +1683,7 @@ static int dst_tune_frontend(struct dvb_frontend* fe, static int dst_get_tuning_algo(struct dvb_frontend *fe) { - return dst_algo; + return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 84340778508..8dcb3fbf7ac 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1290,9 +1290,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe, dprintk("%s() Finalised property cache\n", __func__); dtv_property_cache_submit(fe); - /* Request the search algorithm to search */ - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; @@ -1717,6 +1714,10 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; fepriv->state = FESTATE_RETUNE; + + /* Request the search algorithm to search */ + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + dvb_frontend_wakeup(fe); dvb_frontend_add_event(fe, 0); fepriv->status = 0; diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index a67d1775a43..2da55ec2039 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c @@ -156,7 +156,7 @@ static void stb0899_first_subrange(struct stb0899_state *state) } if (range > 0) - internal->sub_range = MIN(internal->srch_range, range); + internal->sub_range = min(internal->srch_range, range); else internal->sub_range = 0; @@ -185,7 +185,7 @@ static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) timing = stb0899_read_reg(state, STB0899_RTF); if (lock >= 42) { - if ((lock > 48) && (ABS(timing) >= 110)) { + if ((lock > 48) && (abs(timing) >= 110)) { internal->status = ANALOGCARRIER; dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); } else { @@ -222,7 +222,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) index++; derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -298,7 +298,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) last_derot_freq = derot_freq; derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ - if(ABS(derot_freq) > derot_limit) + if(abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -400,7 +400,7 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -467,7 +467,7 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - internal->sub_range = MIN((internal->srch_range / 2) - + internal->sub_range = min((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); @@ -771,7 +771,7 @@ static long Log2Int(int number) int i; i = 0; - while ((1 << i) <= ABS(number)) + while ((1 << i) <= abs(number)) i++; if (number == 0) diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 10613acf18f..a04c782fff8 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -794,7 +794,7 @@ static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t reg = stb0899_read_reg(state, STB0899_DISCNTRL1); old_state = reg; /* set to burst mode */ - STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02); + STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); switch (burst) { diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb/frontends/stb0899_priv.h index 24619e3689d..82395b91281 100644 --- a/drivers/media/dvb/frontends/stb0899_priv.h +++ b/drivers/media/dvb/frontends/stb0899_priv.h @@ -59,10 +59,6 @@ #define MAKEWORD32(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) #define MAKEWORD16(a, b) (((a) << 8) | (b)) -#define MIN(x, y) ((x) <= (y) ? (x) : (y)) -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) -#define ABS(x) ((x) >= 0 ? (x) : -(x)) - #define LSB(x) ((x & 0xff)) #define MSB(y) ((y >> 8) & 0xff) @@ -168,10 +164,10 @@ struct stb0899_internal { u32 freq; /* Demod internal Frequency */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ - u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ + s32 srch_range; /* Demod internal Search Range */ + s32 sub_range; /* Demod current sub range (Hz) */ + s32 tuner_step; /* Tuner step (Hz) */ + s32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index ff39275ab49..1ed5a7db4c5 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -427,11 +427,11 @@ static int stb6100_init(struct dvb_frontend *fe) status->refclock = 27000000; /* Hz */ status->iqsense = 1; status->bandwidth = 36000; /* kHz */ - state->bandwidth = status->bandwidth * 1000; /* MHz */ + state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, status->bandwidth); + return stb6100_set_bandwidth(fe, state->bandwidth); } static int stb6100_get_state(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 170720b0281..b150ed30669 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -590,7 +590,7 @@ static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; - if (state->config.no_tuner) { + if (state->config.disable_i2c_gate_ctrl) { /* No tuner attached to the internal I2C bus */ /* If set enable I2C bridge, the main I2C bus stopped hardly */ return 0; diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index fdbb88ff75f..2287bac4624 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -38,6 +38,9 @@ struct zl10353_config /* set if parallel ts output is required */ int parallel_ts; + + /* set if i2c_gate_ctrl disable is required */ + u8 disable_i2c_gate_ctrl:1; }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 5d882a44e3e..2ac738fa6a0 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -463,6 +463,8 @@ static int em28xx_audio_init(struct em28xx *dev) pcm->info_flags = 0; pcm->private_data = dev; strcpy(pcm->name, "Empia 28xx Capture"); + + snd_card_set_dev(card, &dev->udev->dev); strcpy(card->driver, "Empia Em28xx Audio"); strcpy(card->shortname, "Em28xx Audio"); strcpy(card->longname, "Empia Em28xx Audio"); diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index e564a61a72d..48892b5715d 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -102,7 +102,11 @@ int s5k4aa_probe(struct sd *sd) } /* Test some registers, but we don't know their exact meaning yet */ - if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + if (m5602_read_sensor(sd, 0x00, prod_id, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) return -ENODEV; if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a1d6008efcb..07c334f25aa 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -1155,23 +1155,23 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; - const struct soc_camera_format_xlate *xlate; + const struct soc_camera_data_format *cam_fmt = NULL; + const struct soc_camera_format_xlate *xlate = NULL; struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; - int ret, buswidth; + int ret; - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } + if (pixfmt) { + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } - buswidth = xlate->buswidth; - host_fmt = xlate->host_fmt; - cam_fmt = xlate->cam_fmt; + cam_fmt = xlate->cam_fmt; + } /* If PCLK is used to latch data from the sensor, check sense */ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) @@ -1201,8 +1201,8 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, } if (pixfmt && !ret) { - icd->buswidth = buswidth; - icd->current_fmt = host_fmt; + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; } return ret; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 0776ecf56d2..b5370b3e1a3 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -860,6 +860,7 @@ static struct zl10353_config behold_h6_config = { .demod_address = 0x1e>>1, .no_tuner = 1, .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, }; /* ================================================================== diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9a2586b07a0..ddcb81d0b81 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -603,21 +603,18 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; int ret; + if (!pixfmt) + return icd->ops->set_fmt(icd, pixfmt, rect); + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(&ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } - switch (pixfmt) { - case 0: /* Only geometry change */ - ret = icd->ops->set_fmt(icd, pixfmt, rect); - break; - default: - ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); - } + ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); - if (pixfmt && !ret) { + if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; pcdev->camera_fmt = xlate->cam_fmt; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 5aeccb301ce..076ed5bf48b 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ /* our structs */ -#define MAXREGS 64 +#define MAXREGS 256 struct CHIPSTATE; typedef int (*getvalue)(int); diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index c1e4ae27c61..c705f248da8 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c @@ -46,8 +46,8 @@ static int uvc_input_init(struct uvc_device *dev) usb_to_input_id(udev, &input->id); input->dev.parent = &dev->intf->dev; - set_bit(EV_KEY, input->evbit); - set_bit(BTN_0, input->keybit); + __set_bit(EV_KEY, input->evbit); + __set_bit(KEY_CAMERA, input->keybit); if ((ret = input_register_device(input)) < 0) goto error; @@ -70,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev) static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, int value) { - if (dev->input) + if (dev->input) { input_report_key(dev->input, code, value); + input_sync(dev->input); + } } #else @@ -96,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) return; uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", data[1], data[3] ? "pressed" : "released", len); - uvc_input_report_key(dev, BTN_0, data[3]); + uvc_input_report_key(dev, KEY_CAMERA, data[3]); } else { uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " "len %d.\n", data[1], data[2], data[3], len); diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig index 4ea5fa71de8..8666e19f31a 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/video/zoran/Kconfig @@ -68,6 +68,7 @@ config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO help Support for the AverMedia 6 Eyes video surveillance card. diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 96ac88317b8..ea3aafbbda4 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -91,9 +91,9 @@ MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \ controllers (default=0)"); static int mpt_msi_enable_sas; -module_param(mpt_msi_enable_sas, int, 1); +module_param(mpt_msi_enable_sas, int, 0); MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ - controllers (default=1)"); + controllers (default=0)"); static int mpt_channel_mapping; diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 84d5ea1ec17..b457a05b28d 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -1383,6 +1383,11 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, wm8350->power.rev_g_coeff = 1; break; + case 1: + dev_info(wm8350->dev, "WM8351 Rev B\n"); + wm8350->power.rev_g_coeff = 1; + break; + default: dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n"); ret = -ENODEV; diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index f26667a7abf..cf991850f01 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -710,6 +710,7 @@ out: static struct pci_device_id ilo_devices[] = { { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) }, + { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3307) }, { } }; MODULE_DEVICE_TABLE(pci, ilo_devices); @@ -758,7 +759,7 @@ static void __exit ilo_exit(void) class_destroy(ilo_class); } -MODULE_VERSION("0.06"); +MODULE_VERSION("1.0"); MODULE_ALIAS(ILO_NAME); MODULE_DESCRIPTION(ILO_NAME); MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 9c50e6f1c23..34ce2703d29 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -248,12 +248,15 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, sg_init_one(&sg, data_buf, len); - /* - * The spec states that CSR and CID accesses have a timeout - * of 64 clock cycles. - */ - data.timeout_ns = 0; - data.timeout_clks = 64; + if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) { + /* + * The spec states that CSR and CID accesses have a timeout + * of 64 clock cycles. + */ + data.timeout_ns = 0; + data.timeout_clks = 64; + } else + mmc_set_data_timeout(&data, card); mmc_wait_for_req(host, &mrq); diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f4a67c65d30..2db166b7096 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -793,8 +793,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, host->mem->start + host->sdidata); if (!setup_ok) { - s3c2410_dma_config(host->dma, 4, - (S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI)); + s3c2410_dma_config(host->dma, 4, 0); s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback); s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8cff5f5e7f8..406da9a8d45 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -107,6 +107,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = { static const struct sdhci_pci_fixes sdhci_cafe = { .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | + SDHCI_QUIRK_NO_BUSY_IRQ | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, }; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f52f3053ed9..accb592764e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1291,8 +1291,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) if (host->cmd->data) DBG("Cannot wait for busy signal when also " "doing a data transfer"); - else + else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) return; + + /* The controller does not support the end-of-busy IRQ, + * fall through and take the SDHCI_INT_RESPONSE */ } if (intmask & SDHCI_INT_RESPONSE) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index ebb83657e27..43c37c68d07 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -208,6 +208,8 @@ struct sdhci_host { #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) /* Controller has an issue with buffer bits for small transfers */ #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) +/* Controller does not provide transfer-complete interrupt when not busy */ +#define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) int irq; /* Device IRQ */ void __iomem * ioaddr; /* Mapped address */ diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 821d0ed6bae..c76d6e5f47e 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c @@ -19,6 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static void maprom_nop (struct mtd_info *); static struct mtd_info *map_rom_probe(struct map_info *map); +static int maprom_erase (struct mtd_info *mtd, struct erase_info *info); static struct mtd_chip_driver maprom_chipdrv = { .probe = map_rom_probe, @@ -42,6 +43,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map) mtd->read = maprom_read; mtd->write = maprom_write; mtd->sync = maprom_nop; + mtd->erase = maprom_erase; mtd->flags = MTD_CAP_ROM; mtd->erasesize = map->size; mtd->writesize = 1; @@ -71,6 +73,12 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re return -EIO; } +static int maprom_erase (struct mtd_info *mtd, struct erase_info *info) +{ + /* We do our best 8) */ + return -EROFS; +} + static int __init map_rom_init(void) { register_mtd_chip_driver(&maprom_chipdrv); diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index bc33200535f..6fde0a2e356 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -120,13 +120,6 @@ config MTD_PHRAM doesn't have access to, memory beyond the mem=xxx limit, nvram, memory on the video card, etc... -config MTD_PS3VRAM - tristate "PS3 video RAM" - depends on FB_PS3 - help - This driver allows you to use excess PS3 video RAM as volatile - storage or system swap. - config MTD_LART tristate "28F160xx flash driver for LART" depends on SA1100_LART diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e51521df4e4..0993d5cf392 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -16,4 +16,3 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o -obj-$(CONFIG_MTD_PS3VRAM) += ps3vram.o diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index d44f741ae22..6d9f810565c 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -821,7 +821,8 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) if (!(info->flags & IS_POW2PS)) return info; } - } + } else + return info; } } diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c deleted file mode 100644 index d21e9beb7ed..00000000000 --- a/drivers/mtd/devices/ps3vram.c +++ /dev/null @@ -1,768 +0,0 @@ -/** - * ps3vram - Use extra PS3 video ram as MTD block device. - * - * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com> - * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr> - */ - -#include <linux/io.h> -#include <linux/mm.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/slab.h> -#include <linux/version.h> -#include <linux/gfp.h> -#include <linux/delay.h> -#include <linux/mtd/mtd.h> - -#include <asm/lv1call.h> -#include <asm/ps3.h> - -#define DEVICE_NAME "ps3vram" - -#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ -#define XDR_IOIF 0x0c000000 - -#define FIFO_BASE XDR_IOIF -#define FIFO_SIZE (64 * 1024) - -#define DMA_PAGE_SIZE (4 * 1024) - -#define CACHE_PAGE_SIZE (256 * 1024) -#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) - -#define CACHE_OFFSET CACHE_PAGE_SIZE -#define FIFO_OFFSET 0 - -#define CTRL_PUT 0x10 -#define CTRL_GET 0x11 -#define CTRL_TOP 0x15 - -#define UPLOAD_SUBCH 1 -#define DOWNLOAD_SUBCH 2 - -#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c -#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 - -#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 - -struct mtd_info ps3vram_mtd; - -#define CACHE_PAGE_PRESENT 1 -#define CACHE_PAGE_DIRTY 2 - -struct ps3vram_tag { - unsigned int address; - unsigned int flags; -}; - -struct ps3vram_cache { - unsigned int page_count; - unsigned int page_size; - struct ps3vram_tag *tags; -}; - -struct ps3vram_priv { - u64 memory_handle; - u64 context_handle; - u32 *ctrl; - u32 *reports; - u8 __iomem *ddr_base; - u8 *xdr_buf; - - u32 *fifo_base; - u32 *fifo_ptr; - - struct device *dev; - struct ps3vram_cache cache; - - /* Used to serialize cache/DMA operations */ - struct mutex lock; -}; - -#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ -#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ -#define DMA_NOTIFIER_SIZE 0x40 -#define NOTIFIER 7 /* notifier used for completion report */ - -/* A trailing '-' means to subtract off ps3fb_videomemory.size */ -char *size = "256M-"; -module_param(size, charp, 0); -MODULE_PARM_DESC(size, "memory size"); - -static u32 *ps3vram_get_notifier(u32 *reports, int notifier) -{ - return (void *) reports + - DMA_NOTIFIER_OFFSET_BASE + - DMA_NOTIFIER_SIZE * notifier; -} - -static void ps3vram_notifier_reset(struct mtd_info *mtd) -{ - int i; - - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - for (i = 0; i < 4; i++) - notify[i] = 0xffffffff; -} - -static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (!notify[3]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - return -ETIMEDOUT; -} - -static void ps3vram_init_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; -} - -static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__, - __LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], - priv->ctrl[CTRL_TOP]); - - return -ETIMEDOUT; -} - -static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) -{ - *(priv->fifo_ptr)++ = data; -} - -static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, - u32 tag, u32 size) -{ - ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); -} - -static void ps3vram_rewind_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - priv->fifo_ptr = priv->fifo_base; -} - -static void ps3vram_fire_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - mutex_lock(&ps3_gpu_mutex); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + - (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > - FIFO_SIZE - 1024) { - dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__, - __LINE__); - ps3vram_wait_ring(mtd, 200); - ps3vram_rewind_ring(mtd); - } - - mutex_unlock(&ps3_gpu_mutex); -} - -static void ps3vram_bind(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x31337303); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x3137c0de); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - - ps3vram_fire_ring(mtd); -} - -static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, XDR_IOIF + src_offset); - ps3vram_out_ring(priv, dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, src_offset); - ps3vram_out_ring(priv, XDR_IOIF + dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static void ps3vram_cache_evict(struct mtd_info *mtd, int entry) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) { - dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__, - __LINE__, entry, cache->tags[entry].address); - if (ps3vram_upload(mtd, - CACHE_OFFSET + entry * cache->page_size, - cache->tags[entry].address, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_dbg(priv->dev, "%s:%d: failed to upload from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, - entry * cache->page_size, - cache->tags[entry].address, cache->page_size); - } - cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; - } -} - -static void ps3vram_cache_load(struct mtd_info *mtd, int entry, - unsigned int address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__, - entry, address); - if (ps3vram_download(mtd, - address, - CACHE_OFFSET + entry * cache->page_size, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_err(priv->dev, "%s:%d: failed to download from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address, - entry * cache->page_size, cache->page_size); - } - - cache->tags[entry].address = address; - cache->tags[entry].flags |= CACHE_PAGE_PRESENT; -} - - -static void ps3vram_cache_flush(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - int i; - - dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__); - for (i = 0; i < cache->page_count; i++) { - ps3vram_cache_evict(mtd, i); - cache->tags[i].flags = 0; - } -} - -static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - unsigned int base; - unsigned int offset; - int i; - static int counter; - - offset = (unsigned int) (address & (cache->page_size - 1)); - base = (unsigned int) (address - offset); - - /* fully associative check */ - for (i = 0; i < cache->page_count; i++) { - if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && - cache->tags[i].address == base) { - dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n", - __func__, __LINE__, i, cache->tags[i].address); - return i; - } - } - - /* choose a random entry */ - i = (jiffies + (counter++)) % cache->page_count; - dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i); - - ps3vram_cache_evict(mtd, i); - ps3vram_cache_load(mtd, i, base); - - return i; -} - -static int ps3vram_cache_init(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->cache.page_count = CACHE_PAGE_COUNT; - priv->cache.page_size = CACHE_PAGE_SIZE; - priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * - CACHE_PAGE_COUNT, GFP_KERNEL); - if (priv->cache.tags == NULL) { - dev_err(priv->dev, "%s:%d: could not allocate cache tags\n", - __func__, __LINE__); - return -ENOMEM; - } - - dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n", - CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); - - return 0; -} - -static void ps3vram_cache_cleanup(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_cache_flush(mtd); - kfree(priv->cache.tags); -} - -static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct ps3vram_priv *priv = mtd->priv; - - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - mutex_lock(&priv->lock); - - ps3vram_cache_flush(mtd); - - /* Set bytes to 0xFF */ - memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len); - - mutex_unlock(&priv->lock); - - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - - return 0; -} - -static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__, - (unsigned int)from, len); - - if (from >= mtd->size) - return -EINVAL; - - if (len > mtd->size - from) - len = mtd->size - from; - - /* Copy from vram to buf */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (from & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, from); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)from, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(buf, priv->xdr_buf + cached, avail); - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - from += avail; - } - - *retlen = len; - return 0; -} - -static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - if (to >= mtd->size) - return -EINVAL; - - if (len > mtd->size - to) - len = mtd->size - to; - - /* Copy from buf to vram */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (to & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, to); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)to, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(priv->xdr_buf + cached, buf, avail); - - priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - to += avail; - } - - *retlen = len; - return 0; -} - -static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - int status; - u64 ddr_lpar; - u64 ctrl_lpar; - u64 info_lpar; - u64 reports_lpar; - u64 ddr_size; - u64 reports_size; - int ret = -ENOMEM; - char *rest; - - ret = -EIO; - ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL); - if (!ps3vram_mtd.priv) - goto out; - priv = ps3vram_mtd.priv; - - mutex_init(&priv->lock); - priv->dev = &dev->core; - - /* Allocate XDR buffer (1MiB aligned) */ - priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, - get_order(XDR_BUF_SIZE)); - if (priv->xdr_buf == NULL) { - dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_priv; - } - - /* Put FIFO at begginning of XDR buffer */ - priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); - priv->fifo_ptr = priv->fifo_base; - - /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ - if (ps3_open_hv_device(dev)) { - dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_close_gpu; - } - - /* Request memory */ - status = -1; - ddr_size = memparse(size, &rest); - if (*rest == '-') - ddr_size -= ps3fb_videomemory.size; - ddr_size = ALIGN(ddr_size, 1024*1024); - if (ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: specified size is too small\n", - __func__, __LINE__); - ret = -EINVAL; - goto out_close_gpu; - } - - while (ddr_size > 0) { - status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, - &priv->memory_handle, - &ddr_lpar); - if (!status) - break; - ddr_size -= 1024*1024; - } - if (status || ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_xdr_buf; - } - - /* Request context */ - status = lv1_gpu_context_allocate(priv->memory_handle, - 0, - &priv->context_handle, - &ctrl_lpar, - &info_lpar, - &reports_lpar, - &reports_size); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_memory; - } - - /* Map XDR buffer to RSX */ - status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, - ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), - XDR_BUF_SIZE, 0); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); - - if (!priv->ddr_base) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); - if (!priv->ctrl) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_vram; - } - - priv->reports = ioremap(reports_lpar, reports_size); - if (!priv->reports) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_ctrl; - } - - mutex_lock(&ps3_gpu_mutex); - ps3vram_init_ring(&ps3vram_mtd); - mutex_unlock(&ps3_gpu_mutex); - - ps3vram_mtd.name = "ps3vram"; - ps3vram_mtd.size = ddr_size; - ps3vram_mtd.flags = MTD_CAP_RAM; - ps3vram_mtd.erase = ps3vram_erase; - ps3vram_mtd.point = NULL; - ps3vram_mtd.unpoint = NULL; - ps3vram_mtd.read = ps3vram_read; - ps3vram_mtd.write = ps3vram_write; - ps3vram_mtd.owner = THIS_MODULE; - ps3vram_mtd.type = MTD_RAM; - ps3vram_mtd.erasesize = CACHE_PAGE_SIZE; - ps3vram_mtd.writesize = 1; - - ps3vram_bind(&ps3vram_mtd); - - mutex_lock(&ps3_gpu_mutex); - ret = ps3vram_wait_ring(&ps3vram_mtd, 100); - mutex_unlock(&ps3_gpu_mutex); - if (ret < 0) { - dev_err(&dev->core, "%s:%d: failed to initialize channels\n", - __func__, __LINE__); - ret = -ETIMEDOUT; - goto out_unmap_reports; - } - - ps3vram_cache_init(&ps3vram_mtd); - - if (add_mtd_device(&ps3vram_mtd)) { - dev_err(&dev->core, "%s:%d: add_mtd_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_cache_cleanup; - } - - dev_info(&dev->core, "reserved %u MiB of gpu memory\n", - (unsigned int)(ddr_size / 1024 / 1024)); - - return 0; - -out_cache_cleanup: - ps3vram_cache_cleanup(&ps3vram_mtd); -out_unmap_reports: - iounmap(priv->reports); -out_unmap_ctrl: - iounmap(priv->ctrl); -out_unmap_vram: - iounmap(priv->ddr_base); -out_free_context: - lv1_gpu_context_free(priv->context_handle); -out_free_memory: - lv1_gpu_memory_free(priv->memory_handle); -out_close_gpu: - ps3_close_hv_device(dev); -out_free_xdr_buf: - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); -out_free_priv: - kfree(ps3vram_mtd.priv); - ps3vram_mtd.priv = NULL; -out: - return ret; -} - -static int ps3vram_shutdown(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - - priv = ps3vram_mtd.priv; - - del_mtd_device(&ps3vram_mtd); - ps3vram_cache_cleanup(&ps3vram_mtd); - iounmap(priv->reports); - iounmap(priv->ctrl); - iounmap(priv->ddr_base); - lv1_gpu_context_free(priv->context_handle); - lv1_gpu_memory_free(priv->memory_handle); - ps3_close_hv_device(dev); - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); - kfree(priv); - return 0; -} - -static struct ps3_system_bus_driver ps3vram_driver = { - .match_id = PS3_MATCH_ID_GPU, - .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, - .core.name = DEVICE_NAME, - .core.owner = THIS_MODULE, - .probe = ps3vram_probe, - .remove = ps3vram_shutdown, - .shutdown = ps3vram_shutdown, -}; - -static int __init ps3vram_init(void) -{ - return ps3_system_bus_driver_register(&ps3vram_driver); -} - -static void __exit ps3vram_exit(void) -{ - ps3_system_bus_driver_unregister(&ps3vram_driver); -} - -module_init(ps3vram_init); -module_exit(ps3vram_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jim Paris <jim@jtan.com>"); -MODULE_DESCRIPTION("MTD driver for PS3 video RAM"); -MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index a425d09f35a..00248e81ecd 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -267,22 +267,28 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); devlength = handle_unit(devlength, buffer) - devstart; + if (devlength < devstart) + goto err_out; + + devlength -= devstart; } else { devlength = simple_strtoul(szlength + 1, &buffer, 0); devlength = handle_unit(devlength, buffer); } T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n", devname, devstart, devlength); - if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) { - E("slram: Illegal start / length parameter.\n"); - return(-EINVAL); - } + if (devlength % SLRAM_BLK_SZ != 0) + goto err_out; if ((devstart = register_device(devname, devstart, devlength))){ unregister_devices(); return((int)devstart); } return(0); + +err_out: + E("slram: Illegal length parameter.\n"); + return(-EINVAL); } #ifndef MODULE diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig index acd4ea9b227..5a401d8047a 100644 --- a/drivers/mtd/lpddr/Kconfig +++ b/drivers/mtd/lpddr/Kconfig @@ -12,6 +12,7 @@ config MTD_LPDDR DDR memories, intended for battery-operated systems. config MTD_QINFO_PROBE + depends on MTD_LPDDR tristate "Detect flash chips by QINFO probe" help Device Information for LPDDR chips is offered through the Overlay diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 0225cbbf22d..043d50fb6ef 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS config MTD_BFIN_ASYNC tristate "Blackfin BF533-STAMP Flash Chip Support" - depends on BFIN533_STAMP && MTD_CFI + depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS select MTD_PARTITIONS default y help diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 6fec86aaed7..576611f605d 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c @@ -152,14 +152,18 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) { pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin); + kfree(state); return -EBUSY; } gpio_direction_output(state->enet_flash_pin, 1); pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8); state->mtd = do_map_probe(memory->name, &state->map); - if (!state->mtd) + if (!state->mtd) { + gpio_free(state->enet_flash_pin); + kfree(state); return -ENXIO; + } #ifdef CONFIG_MTD_PARTITIONS ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 5f7a245ed13..424f17d6ffd 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = { { 0, } }; +#if 0 MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl); -#if 0 static struct pci_driver ck804xrom_driver = { .name = MOD_NAME, .id_table = ck804xrom_pci_tbl, diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 87743661d48..229718222db 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -29,6 +29,7 @@ struct physmap_flash_info { struct map_info map[MAX_RESOURCES]; #ifdef CONFIG_MTD_PARTITIONS int nr_parts; + struct mtd_partition *parts; #endif }; @@ -45,25 +46,29 @@ static int physmap_flash_remove(struct platform_device *dev) physmap_data = dev->dev.platform_data; -#ifdef CONFIG_MTD_CONCAT - if (info->cmtd != info->mtd[0]) { + if (info->cmtd) { +#ifdef CONFIG_MTD_PARTITIONS + if (info->nr_parts || physmap_data->nr_parts) + del_mtd_partitions(info->cmtd); + else + del_mtd_device(info->cmtd); +#else del_mtd_device(info->cmtd); - mtd_concat_destroy(info->cmtd); +#endif } +#ifdef CONFIG_MTD_PARTITIONS + if (info->nr_parts) + kfree(info->parts); #endif - for (i = 0; i < MAX_RESOURCES; i++) { - if (info->mtd[i] != NULL) { -#ifdef CONFIG_MTD_PARTITIONS - if (info->nr_parts || physmap_data->nr_parts) - del_mtd_partitions(info->mtd[i]); - else - del_mtd_device(info->mtd[i]); -#else - del_mtd_device(info->mtd[i]); +#ifdef CONFIG_MTD_CONCAT + if (info->cmtd != info->mtd[0]) + mtd_concat_destroy(info->cmtd); #endif + + for (i = 0; i < MAX_RESOURCES; i++) { + if (info->mtd[i] != NULL) map_destroy(info->mtd[i]); - } } return 0; } @@ -86,9 +91,6 @@ static int physmap_flash_probe(struct platform_device *dev) int err = 0; int i; int devices_found = 0; -#ifdef CONFIG_MTD_PARTITIONS - struct mtd_partition *parts; -#endif physmap_data = dev->dev.platform_data; if (physmap_data == NULL) @@ -167,10 +169,11 @@ static int physmap_flash_probe(struct platform_device *dev) goto err_out; #ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0); + err = parse_mtd_partitions(info->cmtd, part_probe_types, + &info->parts, 0); if (err > 0) { - add_mtd_partitions(info->cmtd, parts, err); - kfree(parts); + add_mtd_partitions(info->cmtd, info->parts, err); + info->nr_parts = err; return 0; } diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 917cf8d3ae9..c2dfd3ea353 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -149,7 +149,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) static struct platform_driver orion_nand_driver = { .probe = orion_nand_probe, - .remove = orion_nand_remove, + .remove = __devexit_p(orion_nand_remove), .driver = { .name = "orion_nand", .owner = THIS_MODULE, diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a2f185fd707..62d732a886f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1040,6 +1040,17 @@ config NI65 To compile this driver as a module, choose M here. The module will be called ni65. +config DNET + tristate "Dave ethernet support (DNET)" + depends on NET_ETHERNET && HAS_IOMEM + select PHYLIB + help + The Dave ethernet interface (DNET) is found on Qong Board FPGA. + Say Y to include support for the DNET chip. + + To compile this driver as a module, choose M here: the module + will be called dnet. + source "drivers/net/tulip/Kconfig" config AT1700 @@ -2619,6 +2630,8 @@ config QLGE source "drivers/net/sfc/Kconfig" +source "drivers/net/benet/Kconfig" + endif # NETDEV_10000 source "drivers/net/tokenring/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index aca8492db65..471baaff229 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_TEHUTI) += tehuti.o obj-$(CONFIG_ENIC) += enic/ obj-$(CONFIG_JME) += jme.o +obj-$(CONFIG_BE2NET) += benet/ gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ @@ -231,6 +232,7 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o +obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_MACB) += macb.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index c69c0cdba4a..811a3ccd14c 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile @@ -4,7 +4,7 @@ # obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o -obj-$(CONFIG_ARM_ETHERH) += etherh.o ../8390.o +obj-$(CONFIG_ARM_ETHERH) += etherh.o obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER1) += ether1.o obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 54b52e5b182..f52f668c49b 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -641,15 +641,15 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_open = etherh_open, .ndo_stop = etherh_close, .ndo_set_config = etherh_set_config, - .ndo_start_xmit = ei_start_xmit, - .ndo_tx_timeout = ei_tx_timeout, - .ndo_get_stats = ei_get_stats, - .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_start_xmit = __ei_start_xmit, + .ndo_tx_timeout = __ei_tx_timeout, + .ndo_get_stats = __ei_get_stats, + .ndo_set_multicast_list = __ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = __ei_poll, #endif }; diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 1cf2f949c0b..f3a12743489 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -560,7 +560,7 @@ ks8695_reset(struct ks8695_priv *ksp) msleep(1); } - if (reset_timeout == 0) { + if (reset_timeout < 0) { dev_crit(ksp->dev, "Timeout waiting for DMA engines to reset\n"); /* And blithely carry on */ diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c38512ebcea..dc5f051005f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1264,8 +1264,14 @@ static void b44_clear_stats(struct b44 *bp) static void b44_chip_reset(struct b44 *bp, int reset_kind) { struct ssb_device *sdev = bp->sdev; + bool was_enabled; - if (ssb_device_is_enabled(bp->sdev)) { + was_enabled = ssb_device_is_enabled(bp->sdev); + + ssb_device_enable(bp->sdev, 0); + ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); + + if (was_enabled) { bw32(bp, B44_RCV_LAZY, 0); bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1); @@ -1277,10 +1283,8 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind) } bw32(bp, B44_DMARX_CTRL, 0); bp->rx_prod = bp->rx_cons = 0; - } else - ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); + } - ssb_device_enable(bp->sdev, 0); b44_clear_stats(bp); /* @@ -2236,6 +2240,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev) struct net_device *dev = ssb_get_drvdata(sdev); unregister_netdev(dev); + ssb_device_disable(sdev, 0); ssb_bus_may_powerdown(sdev->bus); free_netdev(dev); ssb_pcihost_set_power_state(sdev, PCI_D3hot); diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig new file mode 100644 index 00000000000..c6934f179c0 --- /dev/null +++ b/drivers/net/benet/Kconfig @@ -0,0 +1,7 @@ +config BE2NET + tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" + depends on PCI && INET + select INET_LRO + help + This driver implements the NIC functionality for ServerEngines' + 10Gbps network adapter - BladeEngine 2. diff --git a/drivers/net/benet/Makefile b/drivers/net/benet/Makefile new file mode 100644 index 00000000000..a60cd805113 --- /dev/null +++ b/drivers/net/benet/Makefile @@ -0,0 +1,7 @@ +# +# Makefile to build the network driver for ServerEngine's BladeEngine. +# + +obj-$(CONFIG_BE2NET) += be2net.o + +be2net-y := be_main.o be_cmds.o be_ethtool.o diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h new file mode 100644 index 00000000000..f327be57ca9 --- /dev/null +++ b/drivers/net/benet/be.h @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#ifndef BE_H +#define BE_H + +#include <linux/pci.h> +#include <linux/etherdevice.h> +#include <linux/version.h> +#include <linux/delay.h> +#include <net/tcp.h> +#include <net/ip.h> +#include <net/ipv6.h> +#include <linux/if_vlan.h> +#include <linux/workqueue.h> +#include <linux/interrupt.h> +#include <linux/inet_lro.h> + +#include "be_hw.h" + +#define DRV_VER "2.0.348" +#define DRV_NAME "be2net" +#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" +#define DRV_DESC BE_NAME "Driver" + +/* Number of bytes of an RX frame that are copied to skb->data */ +#define BE_HDR_LEN 64 +#define BE_MAX_JUMBO_FRAME_SIZE 9018 +#define BE_MIN_MTU 256 + +#define BE_NUM_VLANS_SUPPORTED 64 +#define BE_MAX_EQD 96 +#define BE_MAX_TX_FRAG_COUNT 30 + +#define EVNT_Q_LEN 1024 +#define TX_Q_LEN 2048 +#define TX_CQ_LEN 1024 +#define RX_Q_LEN 1024 /* Does not support any other value */ +#define RX_CQ_LEN 1024 +#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ +#define MCC_CQ_LEN 256 + +#define BE_NAPI_WEIGHT 64 +#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ +#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) + +#define BE_MAX_LRO_DESCRIPTORS 16 +#define BE_MAX_FRAGS_PER_FRAME 16 + +struct be_dma_mem { + void *va; + dma_addr_t dma; + u32 size; +}; + +struct be_queue_info { + struct be_dma_mem dma_mem; + u16 len; + u16 entry_size; /* Size of an element in the queue */ + u16 id; + u16 tail, head; + bool created; + atomic_t used; /* Number of valid elements in the queue */ +}; + +struct be_ctrl_info { + u8 __iomem *csr; + u8 __iomem *db; /* Door Bell */ + u8 __iomem *pcicfg; /* PCI config space */ + int pci_func; + + /* Mbox used for cmd request/response */ + spinlock_t cmd_lock; /* For serializing cmds to BE card */ + struct be_dma_mem mbox_mem; + /* Mbox mem is adjusted to align to 16 bytes. The allocated addr + * is stored for freeing purpose */ + struct be_dma_mem mbox_mem_alloced; +}; + +#include "be_cmds.h" + +struct be_drvr_stats { + u32 be_tx_reqs; /* number of TX requests initiated */ + u32 be_tx_stops; /* number of times TX Q was stopped */ + u32 be_fwd_reqs; /* number of send reqs through forwarding i/f */ + u32 be_tx_wrbs; /* number of tx WRBs used */ + u32 be_tx_events; /* number of tx completion events */ + u32 be_tx_compl; /* number of tx completion entries processed */ + u64 be_tx_jiffies; + ulong be_tx_bytes; + ulong be_tx_bytes_prev; + u32 be_tx_rate; + + u32 cache_barrier[16]; + + u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */ + u32 be_polls; /* number of times NAPI called poll function */ + u32 be_rx_events; /* number of ucast rx completion events */ + u32 be_rx_compl; /* number of rx completion entries processed */ + u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */ + u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */ + u64 be_rx_jiffies; + ulong be_rx_bytes; + ulong be_rx_bytes_prev; + u32 be_rx_rate; + /* number of non ether type II frames dropped where + * frame len > length field of Mac Hdr */ + u32 be_802_3_dropped_frames; + /* number of non ether type II frames malformed where + * in frame len < length field of Mac Hdr */ + u32 be_802_3_malformed_frames; + u32 be_rxcp_err; /* Num rx completion entries w/ err set. */ + ulong rx_fps_jiffies; /* jiffies at last FPS calc */ + u32 be_rx_frags; + u32 be_prev_rx_frags; + u32 be_rx_fps; /* Rx frags per second */ +}; + +struct be_stats_obj { + struct be_drvr_stats drvr_stats; + struct net_device_stats net_stats; + struct be_dma_mem cmd; +}; + +struct be_eq_obj { + struct be_queue_info q; + char desc[32]; + + /* Adaptive interrupt coalescing (AIC) info */ + bool enable_aic; + u16 min_eqd; /* in usecs */ + u16 max_eqd; /* in usecs */ + u16 cur_eqd; /* in usecs */ + + struct napi_struct napi; +}; + +struct be_tx_obj { + struct be_queue_info q; + struct be_queue_info cq; + /* Remember the skbs that were transmitted */ + struct sk_buff *sent_skb_list[TX_Q_LEN]; +}; + +/* Struct to remember the pages posted for rx frags */ +struct be_rx_page_info { + struct page *page; + dma_addr_t bus; + u16 page_offset; + bool last_page_user; +}; + +struct be_rx_obj { + struct be_queue_info q; + struct be_queue_info cq; + struct be_rx_page_info page_info_tbl[RX_Q_LEN]; + struct net_lro_mgr lro_mgr; + struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; +}; + +#define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ +struct be_adapter { + struct pci_dev *pdev; + struct net_device *netdev; + + /* Mbox, pci config, csr address information */ + struct be_ctrl_info ctrl; + + struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS]; + bool msix_enabled; + bool isr_registered; + + /* TX Rings */ + struct be_eq_obj tx_eq; + struct be_tx_obj tx_obj; + + u32 cache_line_break[8]; + + /* Rx rings */ + struct be_eq_obj rx_eq; + struct be_rx_obj rx_obj; + u32 big_page_size; /* Compounded page size shared by rx wrbs */ + bool rx_post_starved; /* Zero rx frags have been posted to BE */ + + struct vlan_group *vlan_grp; + u16 num_vlans; + u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; + + struct be_stats_obj stats; + /* Work queue used to perform periodic tasks like getting statistics */ + struct delayed_work work; + + /* Ethtool knobs and info */ + bool rx_csum; /* BE card must perform rx-checksumming */ + u32 max_rx_coal; + char fw_ver[FW_VER_LEN]; + u32 if_handle; /* Used to configure filtering */ + u32 pmac_id; /* MAC addr handle used by BE card */ + + struct be_link_info link; + u32 port_num; +}; + +extern struct ethtool_ops be_ethtool_ops; + +#define drvr_stats(adapter) (&adapter->stats.drvr_stats) + +#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) + +static inline u32 MODULO(u16 val, u16 limit) +{ + BUG_ON(limit & (limit - 1)); + return val & (limit - 1); +} + +static inline void index_adv(u16 *index, u16 val, u16 limit) +{ + *index = MODULO((*index + val), limit); +} + +static inline void index_inc(u16 *index, u16 limit) +{ + *index = MODULO((*index + 1), limit); +} + +#define PAGE_SHIFT_4K 12 +#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) + +/* Returns number of pages spanned by the data starting at the given addr */ +#define PAGES_4K_SPANNED(_address, size) \ + ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ + (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) + +/* Byte offset into the page corresponding to given address */ +#define OFFSET_IN_PAGE(addr) \ + ((size_t)(addr) & (PAGE_SIZE_4K-1)) + +/* Returns bit offset within a DWORD of a bitfield */ +#define AMAP_BIT_OFFSET(_struct, field) \ + (((size_t)&(((_struct *)0)->field))%32) + +/* Returns the bit mask of the field that is NOT shifted into location. */ +static inline u32 amap_mask(u32 bitsize) +{ + return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1); +} + +static inline void +amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) +{ + u32 *dw = (u32 *) ptr + dw_offset; + *dw &= ~(mask << offset); + *dw |= (mask & value) << offset; +} + +#define AMAP_SET_BITS(_struct, field, ptr, val) \ + amap_set(ptr, \ + offsetof(_struct, field)/32, \ + amap_mask(sizeof(((_struct *)0)->field)), \ + AMAP_BIT_OFFSET(_struct, field), \ + val) + +static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) +{ + u32 *dw = (u32 *) ptr; + return mask & (*(dw + dw_offset) >> offset); +} + +#define AMAP_GET_BITS(_struct, field, ptr) \ + amap_get(ptr, \ + offsetof(_struct, field)/32, \ + amap_mask(sizeof(((_struct *)0)->field)), \ + AMAP_BIT_OFFSET(_struct, field)) + +#define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len) +#define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len) +static inline void swap_dws(void *wrb, int len) +{ +#ifdef __BIG_ENDIAN + u32 *dw = wrb; + BUG_ON(len % 4); + do { + *dw = cpu_to_le32(*dw); + dw++; + len -= 4; + } while (len); +#endif /* __BIG_ENDIAN */ +} + +static inline u8 is_tcp_pkt(struct sk_buff *skb) +{ + u8 val = 0; + + if (ip_hdr(skb)->version == 4) + val = (ip_hdr(skb)->protocol == IPPROTO_TCP); + else if (ip_hdr(skb)->version == 6) + val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_TCP); + + return val; +} + +static inline u8 is_udp_pkt(struct sk_buff *skb) +{ + u8 val = 0; + + if (ip_hdr(skb)->version == 4) + val = (ip_hdr(skb)->protocol == IPPROTO_UDP); + else if (ip_hdr(skb)->version == 6) + val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_UDP); + + return val; +} + +#endif /* BE_H */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c new file mode 100644 index 00000000000..d444aed962b --- /dev/null +++ b/drivers/net/benet/be_cmds.c @@ -0,0 +1,861 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" + +static int be_mbox_db_ready_wait(void __iomem *db) +{ + int cnt = 0, wait = 5; + u32 ready; + + do { + ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; + if (ready) + break; + + if (cnt > 200000) { + printk(KERN_WARNING DRV_NAME + ": mbox_db poll timed out\n"); + return -1; + } + + if (cnt > 50) + wait = 200; + cnt += wait; + udelay(wait); + } while (true); + + return 0; +} + +/* + * Insert the mailbox address into the doorbell in two steps + */ +static int be_mbox_db_ring(struct be_ctrl_info *ctrl) +{ + int status; + u16 compl_status, extd_status; + u32 val = 0; + void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; + struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; + struct be_mcc_mailbox *mbox = mbox_mem->va; + struct be_mcc_cq_entry *cqe = &mbox->cqe; + + memset(cqe, 0, sizeof(*cqe)); + + val &= ~MPU_MAILBOX_DB_RDY_MASK; + val |= MPU_MAILBOX_DB_HI_MASK; + /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ + val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; + iowrite32(val, db); + + /* wait for ready to be set */ + status = be_mbox_db_ready_wait(db); + if (status != 0) + return status; + + val = 0; + val &= ~MPU_MAILBOX_DB_RDY_MASK; + val &= ~MPU_MAILBOX_DB_HI_MASK; + /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ + val |= (u32)(mbox_mem->dma >> 4) << 2; + iowrite32(val, db); + + status = be_mbox_db_ready_wait(db); + if (status != 0) + return status; + + /* compl entry has been made now */ + be_dws_le_to_cpu(cqe, sizeof(*cqe)); + if (!(cqe->flags & CQE_FLAGS_VALID_MASK)) { + printk(KERN_WARNING DRV_NAME ": ERROR invalid mbox compl\n"); + return -1; + } + + compl_status = (cqe->status >> CQE_STATUS_COMPL_SHIFT) & + CQE_STATUS_COMPL_MASK; + if (compl_status != MCC_STATUS_SUCCESS) { + extd_status = (cqe->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + printk(KERN_WARNING DRV_NAME + ": ERROR in cmd compl. status(compl/extd)=%d/%d\n", + compl_status, extd_status); + } + + return compl_status; +} + +static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) +{ + u32 sem = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + + *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; + if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) + return -1; + else + return 0; +} + +static int be_POST_stage_poll(struct be_ctrl_info *ctrl, u16 poll_stage) +{ + u16 stage, cnt, error; + for (cnt = 0; cnt < 5000; cnt++) { + error = be_POST_stage_get(ctrl, &stage); + if (error) + return -1; + + if (stage == poll_stage) + break; + udelay(1000); + } + if (stage != poll_stage) + return -1; + return 0; +} + + +int be_cmd_POST(struct be_ctrl_info *ctrl) +{ + u16 stage, error; + + error = be_POST_stage_get(ctrl, &stage); + if (error) + goto err; + + if (stage == POST_STAGE_ARMFW_RDY) + return 0; + + if (stage != POST_STAGE_AWAITING_HOST_RDY) + goto err; + + /* On awaiting host rdy, reset and again poll on awaiting host rdy */ + iowrite32(POST_STAGE_BE_RESET, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + error = be_POST_stage_poll(ctrl, POST_STAGE_AWAITING_HOST_RDY); + if (error) + goto err; + + /* Now kickoff POST and poll on armfw ready */ + iowrite32(POST_STAGE_HOST_RDY, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + error = be_POST_stage_poll(ctrl, POST_STAGE_ARMFW_RDY); + if (error) + goto err; + + return 0; +err: + printk(KERN_WARNING DRV_NAME ": ERROR, stage=%d\n", stage); + return -1; +} + +static inline void *embedded_payload(struct be_mcc_wrb *wrb) +{ + return wrb->payload.embedded_payload; +} + +static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) +{ + return &wrb->payload.sgl[0]; +} + +/* Don't touch the hdr after it's prepared */ +static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, + bool embedded, u8 sge_cnt) +{ + if (embedded) + wrb->embedded |= MCC_WRB_EMBEDDED_MASK; + else + wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << + MCC_WRB_SGE_CNT_SHIFT; + wrb->payload_length = payload_len; + be_dws_cpu_to_le(wrb, 20); +} + +/* Don't touch the hdr after it's prepared */ +static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, + u8 subsystem, u8 opcode, int cmd_len) +{ + req_hdr->opcode = opcode; + req_hdr->subsystem = subsystem; + req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); +} + +static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, + struct be_dma_mem *mem) +{ + int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); + u64 dma = (u64)mem->dma; + + for (i = 0; i < buf_pages; i++) { + pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); + pages[i].hi = cpu_to_le32(upper_32_bits(dma)); + dma += PAGE_SIZE_4K; + } +} + +/* Converts interrupt delay in microseconds to multiplier value */ +static u32 eq_delay_to_mult(u32 usec_delay) +{ +#define MAX_INTR_RATE 651042 + const u32 round = 10; + u32 multiplier; + + if (usec_delay == 0) + multiplier = 0; + else { + u32 interrupt_rate = 1000000 / usec_delay; + /* Max delay, corresponding to the lowest interrupt rate */ + if (interrupt_rate == 0) + multiplier = 1023; + else { + multiplier = (MAX_INTR_RATE - interrupt_rate) * round; + multiplier /= interrupt_rate; + /* Round the multiplier to the closest value.*/ + multiplier = (multiplier + round/2) / round; + multiplier = min(multiplier, (u32)1023); + } + } + return multiplier; +} + +static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) +{ + return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; +} + +int be_cmd_eq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *eq, int eq_delay) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eq_create *req = embedded_payload(wrb); + struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); + struct be_dma_mem *q_mem = &eq->dma_mem; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_EQ_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_eq_context, func, req->context, + ctrl->pci_func); + AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); + /* 4byte eqe*/ + AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); + AMAP_SET_BITS(struct amap_eq_context, count, req->context, + __ilog2_u32(eq->len/256)); + AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, + eq_delay_to_mult(eq_delay)); + be_dws_cpu_to_le(req->context, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + eq->id = le16_to_cpu(resp->eq_id); + eq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, + u8 type, bool permanent, u32 if_handle) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_mac_query *req = embedded_payload(wrb); + struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req)); + + req->type = type; + if (permanent) { + req->permanent = 1; + } else { + req->if_id = cpu_to_le16((u16)if_handle); + req->permanent = 0; + } + + status = be_mbox_db_ring(ctrl); + if (!status) + memcpy(mac_addr, resp->mac.addr, ETH_ALEN); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, + u32 if_id, u32 *pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_pmac_add *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req)); + + req->if_id = cpu_to_le32(if_id); + memcpy(req->mac_address, mac_addr, ETH_ALEN); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); + *pmac_id = le32_to_cpu(resp->pmac_id); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_pmac_del *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req)); + + req->if_id = cpu_to_le32(if_id); + req->pmac_id = cpu_to_le32(pmac_id); + + status = be_mbox_db_ring(ctrl); + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_cq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *cq, struct be_queue_info *eq, + bool sol_evts, bool no_delay, int coalesce_wm) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_cq_create *req = embedded_payload(wrb); + struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); + struct be_dma_mem *q_mem = &cq->dma_mem; + void *ctxt = &req->context; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_CQ_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); + AMAP_SET_BITS(struct amap_cq_context, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 0); + AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + cq->id = le16_to_cpu(resp->cq_id); + cq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_txq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *txq, + struct be_queue_info *cq) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb); + struct be_dma_mem *q_mem = &txq->dma_mem; + void *ctxt = &req->context; + int status; + u32 len_encoded; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE, + sizeof(*req)); + + req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); + req->ulp_num = BE_ULP1_NUM; + req->type = BE_ETH_TX_RING_TYPE_STANDARD; + + len_encoded = fls(txq->len); /* log2(len) + 1 */ + if (len_encoded == 16) + len_encoded = 0; + AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded); + AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, + ctrl->pci_func); + AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); + AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); + txq->id = le16_to_cpu(resp->cid); + txq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_rxq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *rxq, u16 cq_id, u16 frag_size, + u16 max_frame_size, u32 if_id, u32 rss) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb); + struct be_dma_mem *q_mem = &rxq->dma_mem; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE, + sizeof(*req)); + + req->cq_id = cpu_to_le16(cq_id); + req->frag_size = fls(frag_size) - 1; + req->num_pages = 2; + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + req->interface_id = cpu_to_le32(if_id); + req->max_frame_size = cpu_to_le16(max_frame_size); + req->rss_queue = cpu_to_le32(rss); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); + rxq->id = le16_to_cpu(resp->id); + rxq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Generic destroyer function for all types of queues */ +int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, + int queue_type) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_q_destroy *req = embedded_payload(wrb); + u8 subsys = 0, opcode = 0; + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + switch (queue_type) { + case QTYPE_EQ: + subsys = CMD_SUBSYSTEM_COMMON; + opcode = OPCODE_COMMON_EQ_DESTROY; + break; + case QTYPE_CQ: + subsys = CMD_SUBSYSTEM_COMMON; + opcode = OPCODE_COMMON_CQ_DESTROY; + break; + case QTYPE_TXQ: + subsys = CMD_SUBSYSTEM_ETH; + opcode = OPCODE_ETH_TX_DESTROY; + break; + case QTYPE_RXQ: + subsys = CMD_SUBSYSTEM_ETH; + opcode = OPCODE_ETH_RX_DESTROY; + break; + default: + printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); + status = -1; + goto err; + } + be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); + req->id = cpu_to_le16(q->id); + + status = be_mbox_db_ring(ctrl); +err: + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Create an rx filtering policy configuration on an i/f */ +int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, + bool pmac_invalid, u32 *if_handle, u32 *pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_if_create *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req)); + + req->capability_flags = cpu_to_le32(flags); + req->enable_flags = cpu_to_le32(flags); + if (!pmac_invalid) + memcpy(req->mac_addr, mac, ETH_ALEN); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_if_create *resp = embedded_payload(wrb); + *if_handle = le32_to_cpu(resp->interface_id); + if (!pmac_invalid) + *pmac_id = le32_to_cpu(resp->pmac_id); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_if_destroy *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); + + req->interface_id = cpu_to_le32(interface_id); + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Get stats is a non embedded command: the request is not embedded inside + * WRB but is a separate dma memory block + */ +int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_stats *req = nonemb_cmd->va; + struct be_sge *sge = nonembedded_sgl(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + memset(req, 0, sizeof(*req)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_GET_STATISTICS, sizeof(*req)); + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_stats *resp = nonemb_cmd->va; + be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_link_status_query(struct be_ctrl_info *ctrl, + struct be_link_info *link) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_link_status *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_link_status *resp = embedded_payload(wrb); + link->speed = resp->mac_speed; + link->duplex = resp->mac_duplex; + link->fault = resp->mac_fault; + } else { + link->speed = PHY_LINK_SPEED_ZERO; + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); + strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +/* set the EQ delay interval of an EQ to specified value */ +int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); + + req->num_eq = cpu_to_le32(1); + req->delay[0].eq_id = cpu_to_le32(eq_id); + req->delay[0].phase = 0; + req->delay[0].delay_multiplier = cpu_to_le32(eqd); + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, + u32 num, bool untagged, bool promiscuous) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_vlan_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req)); + + req->interface_id = if_id; + req->promiscuous = promiscuous; + req->untagged = untagged; + req->num_vlan = num; + if (!promiscuous) { + memcpy(req->normal_vlan, vtag_array, + req->num_vlan * sizeof(vtag_array[0])); + } + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_PROMISCUOUS, sizeof(*req)); + + if (port_num) + req->port1_promiscuous = en; + else + req->port0_promiscuous = en; + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, + u32 num, bool promiscuous) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); + + req->interface_id = if_id; + req->promiscuous = promiscuous; + if (!promiscuous) { + req->num_mac = cpu_to_le16(num); + if (num) + memcpy(req->mac, mac_table, ETH_ALEN * num); + } + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req)); + + req->tx_flow_control = cpu_to_le16((u16)tx_fc); + req->rx_flow_control = cpu_to_le16((u16)rx_fc); + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_flow_control *resp = + embedded_payload(wrb); + *tx_fc = le16_to_cpu(resp->tx_flow_control); + *rx_fc = le16_to_cpu(resp->rx_flow_control); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); + *port_num = le32_to_cpu(resp->phys_port); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h new file mode 100644 index 00000000000..e499e2d5b8c --- /dev/null +++ b/drivers/net/benet/be_cmds.h @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +/* + * The driver sends configuration and managements command requests to the + * firmware in the BE. These requests are communicated to the processor + * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one + * WRB inside a MAILBOX. + * The commands are serviced by the ARM processor in the BladeEngine's MPU. + */ + +struct be_sge { + u32 pa_lo; + u32 pa_hi; + u32 len; +}; + +#define MCC_WRB_EMBEDDED_MASK 1 /* bit 0 of dword 0*/ +#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */ +#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */ +struct be_mcc_wrb { + u32 embedded; /* dword 0 */ + u32 payload_length; /* dword 1 */ + u32 tag0; /* dword 2 */ + u32 tag1; /* dword 3 */ + u32 rsvd; /* dword 4 */ + union { + u8 embedded_payload[236]; /* used by embedded cmds */ + struct be_sge sgl[19]; /* used by non-embedded cmds */ + } payload; +}; + +#define CQE_FLAGS_VALID_MASK (1 << 31) +#define CQE_FLAGS_ASYNC_MASK (1 << 30) +#define CQE_FLAGS_COMPLETED_MASK (1 << 28) +#define CQE_FLAGS_CONSUMED_MASK (1 << 27) + +/* Completion Status */ +enum { + MCC_STATUS_SUCCESS = 0x0, +/* The client does not have sufficient privileges to execute the command */ + MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1, +/* A parameter in the command was invalid. */ + MCC_STATUS_INVALID_PARAMETER = 0x2, +/* There are insufficient chip resources to execute the command */ + MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3, +/* The command is completing because the queue was getting flushed */ + MCC_STATUS_QUEUE_FLUSHING = 0x4, +/* The command is completing with a DMA error */ + MCC_STATUS_DMA_FAILED = 0x5 +}; + +#define CQE_STATUS_COMPL_MASK 0xFFFF +#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ +#define CQE_STATUS_EXTD_MASK 0xFFFF +#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ + +struct be_mcc_cq_entry { + u32 status; /* dword 0 */ + u32 tag0; /* dword 1 */ + u32 tag1; /* dword 2 */ + u32 flags; /* dword 3 */ +}; + +struct be_mcc_mailbox { + struct be_mcc_wrb wrb; + struct be_mcc_cq_entry cqe; +}; + +#define CMD_SUBSYSTEM_COMMON 0x1 +#define CMD_SUBSYSTEM_ETH 0x3 + +#define OPCODE_COMMON_NTWK_MAC_QUERY 1 +#define OPCODE_COMMON_NTWK_MAC_SET 2 +#define OPCODE_COMMON_NTWK_MULTICAST_SET 3 +#define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 +#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 +#define OPCODE_COMMON_CQ_CREATE 12 +#define OPCODE_COMMON_EQ_CREATE 13 +#define OPCODE_COMMON_MCC_CREATE 21 +#define OPCODE_COMMON_NTWK_RX_FILTER 34 +#define OPCODE_COMMON_GET_FW_VERSION 35 +#define OPCODE_COMMON_SET_FLOW_CONTROL 36 +#define OPCODE_COMMON_GET_FLOW_CONTROL 37 +#define OPCODE_COMMON_SET_FRAME_SIZE 39 +#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 +#define OPCODE_COMMON_FIRMWARE_CONFIG 42 +#define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50 +#define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51 +#define OPCODE_COMMON_CQ_DESTROY 54 +#define OPCODE_COMMON_EQ_DESTROY 55 +#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 +#define OPCODE_COMMON_NTWK_PMAC_ADD 59 +#define OPCODE_COMMON_NTWK_PMAC_DEL 60 + +#define OPCODE_ETH_ACPI_CONFIG 2 +#define OPCODE_ETH_PROMISCUOUS 3 +#define OPCODE_ETH_GET_STATISTICS 4 +#define OPCODE_ETH_TX_CREATE 7 +#define OPCODE_ETH_RX_CREATE 8 +#define OPCODE_ETH_TX_DESTROY 9 +#define OPCODE_ETH_RX_DESTROY 10 + +struct be_cmd_req_hdr { + u8 opcode; /* dword 0 */ + u8 subsystem; /* dword 0 */ + u8 port_number; /* dword 0 */ + u8 domain; /* dword 0 */ + u32 timeout; /* dword 1 */ + u32 request_length; /* dword 2 */ + u32 rsvd; /* dword 3 */ +}; + +#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ +#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */ +struct be_cmd_resp_hdr { + u32 info; /* dword 0 */ + u32 status; /* dword 1 */ + u32 response_length; /* dword 2 */ + u32 actual_resp_len; /* dword 3 */ +}; + +struct phys_addr { + u32 lo; + u32 hi; +}; + +/************************** + * BE Command definitions * + **************************/ + +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_eq_context { + u8 cidx[13]; /* dword 0*/ + u8 rsvd0[3]; /* dword 0*/ + u8 epidx[13]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 rsvd1; /* dword 0*/ + u8 size; /* dword 0*/ + u8 pidx[13]; /* dword 1*/ + u8 rsvd2[3]; /* dword 1*/ + u8 pd[10]; /* dword 1*/ + u8 count[3]; /* dword 1*/ + u8 solevent; /* dword 1*/ + u8 stalled; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd3[4]; /* dword 2*/ + u8 func[8]; /* dword 2*/ + u8 rsvd4; /* dword 2*/ + u8 delaymult[10]; /* dword 2*/ + u8 rsvd5[2]; /* dword 2*/ + u8 phase[2]; /* dword 2*/ + u8 nodelay; /* dword 2*/ + u8 rsvd6[4]; /* dword 2*/ + u8 rsvd7[32]; /* dword 3*/ +} __packed; + +struct be_cmd_req_eq_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; /* sword */ + u16 rsvd0; /* sword */ + u8 context[sizeof(struct amap_eq_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_eq_create { + struct be_cmd_resp_hdr resp_hdr; + u16 eq_id; /* sword */ + u16 rsvd0; /* sword */ +} __packed; + +/******************** Mac query ***************************/ +enum { + MAC_ADDRESS_TYPE_STORAGE = 0x0, + MAC_ADDRESS_TYPE_NETWORK = 0x1, + MAC_ADDRESS_TYPE_PD = 0x2, + MAC_ADDRESS_TYPE_MANAGEMENT = 0x3 +}; + +struct mac_addr { + u16 size_of_struct; + u8 addr[ETH_ALEN]; +} __packed; + +struct be_cmd_req_mac_query { + struct be_cmd_req_hdr hdr; + u8 type; + u8 permanent; + u16 if_id; +} __packed; + +struct be_cmd_resp_mac_query { + struct be_cmd_resp_hdr hdr; + struct mac_addr mac; +}; + +/******************** PMac Add ***************************/ +struct be_cmd_req_pmac_add { + struct be_cmd_req_hdr hdr; + u32 if_id; + u8 mac_address[ETH_ALEN]; + u8 rsvd0[2]; +} __packed; + +struct be_cmd_resp_pmac_add { + struct be_cmd_resp_hdr hdr; + u32 pmac_id; +}; + +/******************** PMac Del ***************************/ +struct be_cmd_req_pmac_del { + struct be_cmd_req_hdr hdr; + u32 if_id; + u32 pmac_id; +}; + +/******************** Create CQ ***************************/ +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_cq_context { + u8 cidx[11]; /* dword 0*/ + u8 rsvd0; /* dword 0*/ + u8 coalescwm[2]; /* dword 0*/ + u8 nodelay; /* dword 0*/ + u8 epidx[11]; /* dword 0*/ + u8 rsvd1; /* dword 0*/ + u8 count[2]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 solevent; /* dword 0*/ + u8 eventable; /* dword 0*/ + u8 pidx[11]; /* dword 1*/ + u8 rsvd2; /* dword 1*/ + u8 pd[10]; /* dword 1*/ + u8 eqid[8]; /* dword 1*/ + u8 stalled; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd3[4]; /* dword 2*/ + u8 func[8]; /* dword 2*/ + u8 rsvd4[20]; /* dword 2*/ + u8 rsvd5[32]; /* dword 3*/ +} __packed; + +struct be_cmd_req_cq_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; + u16 rsvd0; + u8 context[sizeof(struct amap_cq_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_cq_create { + struct be_cmd_resp_hdr hdr; + u16 cq_id; + u16 rsvd0; +} __packed; + +/******************** Create TxQ ***************************/ +#define BE_ETH_TX_RING_TYPE_STANDARD 2 +#define BE_ULP1_NUM 1 + +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_tx_context { + u8 rsvd0[16]; /* dword 0 */ + u8 tx_ring_size[4]; /* dword 0 */ + u8 rsvd1[26]; /* dword 0 */ + u8 pci_func_id[8]; /* dword 1 */ + u8 rsvd2[9]; /* dword 1 */ + u8 ctx_valid; /* dword 1 */ + u8 cq_id_send[16]; /* dword 2 */ + u8 rsvd3[16]; /* dword 2 */ + u8 rsvd4[32]; /* dword 3 */ + u8 rsvd5[32]; /* dword 4 */ + u8 rsvd6[32]; /* dword 5 */ + u8 rsvd7[32]; /* dword 6 */ + u8 rsvd8[32]; /* dword 7 */ + u8 rsvd9[32]; /* dword 8 */ + u8 rsvd10[32]; /* dword 9 */ + u8 rsvd11[32]; /* dword 10 */ + u8 rsvd12[32]; /* dword 11 */ + u8 rsvd13[32]; /* dword 12 */ + u8 rsvd14[32]; /* dword 13 */ + u8 rsvd15[32]; /* dword 14 */ + u8 rsvd16[32]; /* dword 15 */ +} __packed; + +struct be_cmd_req_eth_tx_create { + struct be_cmd_req_hdr hdr; + u8 num_pages; + u8 ulp_num; + u8 type; + u8 bound_port; + u8 context[sizeof(struct amap_tx_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_eth_tx_create { + struct be_cmd_resp_hdr hdr; + u16 cid; + u16 rsvd0; +} __packed; + +/******************** Create RxQ ***************************/ +struct be_cmd_req_eth_rx_create { + struct be_cmd_req_hdr hdr; + u16 cq_id; + u8 frag_size; + u8 num_pages; + struct phys_addr pages[2]; + u32 interface_id; + u16 max_frame_size; + u16 rsvd0; + u32 rss_queue; +} __packed; + +struct be_cmd_resp_eth_rx_create { + struct be_cmd_resp_hdr hdr; + u16 id; + u8 cpu_id; + u8 rsvd0; +} __packed; + +/******************** Q Destroy ***************************/ +/* Type of Queue to be destroyed */ +enum { + QTYPE_EQ = 1, + QTYPE_CQ, + QTYPE_TXQ, + QTYPE_RXQ +}; + +struct be_cmd_req_q_destroy { + struct be_cmd_req_hdr hdr; + u16 id; + u16 bypass_flush; /* valid only for rx q destroy */ +} __packed; + +/************ I/f Create (it's actually I/f Config Create)**********/ + +/* Capability flags for the i/f */ +enum be_if_flags { + BE_IF_FLAGS_RSS = 0x4, + BE_IF_FLAGS_PROMISCUOUS = 0x8, + BE_IF_FLAGS_BROADCAST = 0x10, + BE_IF_FLAGS_UNTAGGED = 0x20, + BE_IF_FLAGS_ULP = 0x40, + BE_IF_FLAGS_VLAN_PROMISCUOUS = 0x80, + BE_IF_FLAGS_VLAN = 0x100, + BE_IF_FLAGS_MCAST_PROMISCUOUS = 0x200, + BE_IF_FLAGS_PASS_L2_ERRORS = 0x400, + BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800 +}; + +/* An RX interface is an object with one or more MAC addresses and + * filtering capabilities. */ +struct be_cmd_req_if_create { + struct be_cmd_req_hdr hdr; + u32 version; /* ignore currntly */ + u32 capability_flags; + u32 enable_flags; + u8 mac_addr[ETH_ALEN]; + u8 rsvd0; + u8 pmac_invalid; /* if set, don't attach the mac addr to the i/f */ + u32 vlan_tag; /* not used currently */ +} __packed; + +struct be_cmd_resp_if_create { + struct be_cmd_resp_hdr hdr; + u32 interface_id; + u32 pmac_id; +}; + +/****** I/f Destroy(it's actually I/f Config Destroy )**********/ +struct be_cmd_req_if_destroy { + struct be_cmd_req_hdr hdr; + u32 interface_id; +}; + +/*************** HW Stats Get **********************************/ +struct be_port_rxf_stats { + u32 rx_bytes_lsd; /* dword 0*/ + u32 rx_bytes_msd; /* dword 1*/ + u32 rx_total_frames; /* dword 2*/ + u32 rx_unicast_frames; /* dword 3*/ + u32 rx_multicast_frames; /* dword 4*/ + u32 rx_broadcast_frames; /* dword 5*/ + u32 rx_crc_errors; /* dword 6*/ + u32 rx_alignment_symbol_errors; /* dword 7*/ + u32 rx_pause_frames; /* dword 8*/ + u32 rx_control_frames; /* dword 9*/ + u32 rx_in_range_errors; /* dword 10*/ + u32 rx_out_range_errors; /* dword 11*/ + u32 rx_frame_too_long; /* dword 12*/ + u32 rx_address_match_errors; /* dword 13*/ + u32 rx_vlan_mismatch; /* dword 14*/ + u32 rx_dropped_too_small; /* dword 15*/ + u32 rx_dropped_too_short; /* dword 16*/ + u32 rx_dropped_header_too_small; /* dword 17*/ + u32 rx_dropped_tcp_length; /* dword 18*/ + u32 rx_dropped_runt; /* dword 19*/ + u32 rx_64_byte_packets; /* dword 20*/ + u32 rx_65_127_byte_packets; /* dword 21*/ + u32 rx_128_256_byte_packets; /* dword 22*/ + u32 rx_256_511_byte_packets; /* dword 23*/ + u32 rx_512_1023_byte_packets; /* dword 24*/ + u32 rx_1024_1518_byte_packets; /* dword 25*/ + u32 rx_1519_2047_byte_packets; /* dword 26*/ + u32 rx_2048_4095_byte_packets; /* dword 27*/ + u32 rx_4096_8191_byte_packets; /* dword 28*/ + u32 rx_8192_9216_byte_packets; /* dword 29*/ + u32 rx_ip_checksum_errs; /* dword 30*/ + u32 rx_tcp_checksum_errs; /* dword 31*/ + u32 rx_udp_checksum_errs; /* dword 32*/ + u32 rx_non_rss_packets; /* dword 33*/ + u32 rx_ipv4_packets; /* dword 34*/ + u32 rx_ipv6_packets; /* dword 35*/ + u32 rx_ipv4_bytes_lsd; /* dword 36*/ + u32 rx_ipv4_bytes_msd; /* dword 37*/ + u32 rx_ipv6_bytes_lsd; /* dword 38*/ + u32 rx_ipv6_bytes_msd; /* dword 39*/ + u32 rx_chute1_packets; /* dword 40*/ + u32 rx_chute2_packets; /* dword 41*/ + u32 rx_chute3_packets; /* dword 42*/ + u32 rx_management_packets; /* dword 43*/ + u32 rx_switched_unicast_packets; /* dword 44*/ + u32 rx_switched_multicast_packets; /* dword 45*/ + u32 rx_switched_broadcast_packets; /* dword 46*/ + u32 tx_bytes_lsd; /* dword 47*/ + u32 tx_bytes_msd; /* dword 48*/ + u32 tx_unicastframes; /* dword 49*/ + u32 tx_multicastframes; /* dword 50*/ + u32 tx_broadcastframes; /* dword 51*/ + u32 tx_pauseframes; /* dword 52*/ + u32 tx_controlframes; /* dword 53*/ + u32 tx_64_byte_packets; /* dword 54*/ + u32 tx_65_127_byte_packets; /* dword 55*/ + u32 tx_128_256_byte_packets; /* dword 56*/ + u32 tx_256_511_byte_packets; /* dword 57*/ + u32 tx_512_1023_byte_packets; /* dword 58*/ + u32 tx_1024_1518_byte_packets; /* dword 59*/ + u32 tx_1519_2047_byte_packets; /* dword 60*/ + u32 tx_2048_4095_byte_packets; /* dword 61*/ + u32 tx_4096_8191_byte_packets; /* dword 62*/ + u32 tx_8192_9216_byte_packets; /* dword 63*/ + u32 rx_fifo_overflow; /* dword 64*/ + u32 rx_input_fifo_overflow; /* dword 65*/ +}; + +struct be_rxf_stats { + struct be_port_rxf_stats port[2]; + u32 rx_drops_no_pbuf; /* dword 132*/ + u32 rx_drops_no_txpb; /* dword 133*/ + u32 rx_drops_no_erx_descr; /* dword 134*/ + u32 rx_drops_no_tpre_descr; /* dword 135*/ + u32 management_rx_port_packets; /* dword 136*/ + u32 management_rx_port_bytes; /* dword 137*/ + u32 management_rx_port_pause_frames; /* dword 138*/ + u32 management_rx_port_errors; /* dword 139*/ + u32 management_tx_port_packets; /* dword 140*/ + u32 management_tx_port_bytes; /* dword 141*/ + u32 management_tx_port_pause; /* dword 142*/ + u32 management_rx_port_rxfifo_overflow; /* dword 143*/ + u32 rx_drops_too_many_frags; /* dword 144*/ + u32 rx_drops_invalid_ring; /* dword 145*/ + u32 forwarded_packets; /* dword 146*/ + u32 rx_drops_mtu; /* dword 147*/ + u32 rsvd0[15]; +}; + +struct be_erx_stats { + u32 rx_drops_no_fragments[44]; /* dwordS 0 to 43*/ + u32 debug_wdma_sent_hold; /* dword 44*/ + u32 debug_wdma_pbfree_sent_hold; /* dword 45*/ + u32 debug_wdma_zerobyte_pbfree_sent_hold; /* dword 46*/ + u32 debug_pmem_pbuf_dealloc; /* dword 47*/ +}; + +struct be_hw_stats { + struct be_rxf_stats rxf; + u32 rsvd[48]; + struct be_erx_stats erx; +}; + +struct be_cmd_req_get_stats { + struct be_cmd_req_hdr hdr; + u8 rsvd[sizeof(struct be_hw_stats)]; +}; + +struct be_cmd_resp_get_stats { + struct be_cmd_resp_hdr hdr; + struct be_hw_stats hw_stats; +}; + +struct be_cmd_req_vlan_config { + struct be_cmd_req_hdr hdr; + u8 interface_id; + u8 promiscuous; + u8 untagged; + u8 num_vlan; + u16 normal_vlan[64]; +} __packed; + +struct be_cmd_req_promiscuous_config { + struct be_cmd_req_hdr hdr; + u8 port0_promiscuous; + u8 port1_promiscuous; + u16 rsvd0; +} __packed; + +struct macaddr { + u8 byte[ETH_ALEN]; +}; + +struct be_cmd_req_mcast_mac_config { + struct be_cmd_req_hdr hdr; + u16 num_mac; + u8 promiscuous; + u8 interface_id; + struct macaddr mac[32]; +} __packed; + +static inline struct be_hw_stats * +hw_stats_from_cmd(struct be_cmd_resp_get_stats *cmd) +{ + return &cmd->hw_stats; +} + +/******************** Link Status Query *******************/ +struct be_cmd_req_link_status { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_link_info { + u8 duplex; + u8 speed; + u8 fault; +}; + +enum { + PHY_LINK_DUPLEX_NONE = 0x0, + PHY_LINK_DUPLEX_HALF = 0x1, + PHY_LINK_DUPLEX_FULL = 0x2 +}; + +enum { + PHY_LINK_SPEED_ZERO = 0x0, /* => No link */ + PHY_LINK_SPEED_10MBPS = 0x1, + PHY_LINK_SPEED_100MBPS = 0x2, + PHY_LINK_SPEED_1GBPS = 0x3, + PHY_LINK_SPEED_10GBPS = 0x4 +}; + +struct be_cmd_resp_link_status { + struct be_cmd_resp_hdr hdr; + u8 physical_port; + u8 mac_duplex; + u8 mac_speed; + u8 mac_fault; + u8 mgmt_mac_duplex; + u8 mgmt_mac_speed; + u16 rsvd0; +} __packed; + +/******************** Get FW Version *******************/ +#define FW_VER_LEN 32 +struct be_cmd_req_get_fw_version { + struct be_cmd_req_hdr hdr; + u8 rsvd0[FW_VER_LEN]; + u8 rsvd1[FW_VER_LEN]; +} __packed; + +struct be_cmd_resp_get_fw_version { + struct be_cmd_resp_hdr hdr; + u8 firmware_version_string[FW_VER_LEN]; + u8 fw_on_flash_version_string[FW_VER_LEN]; +} __packed; + +/******************** Set Flow Contrl *******************/ +struct be_cmd_req_set_flow_control { + struct be_cmd_req_hdr hdr; + u16 tx_flow_control; + u16 rx_flow_control; +} __packed; + +/******************** Get Flow Contrl *******************/ +struct be_cmd_req_get_flow_control { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_cmd_resp_get_flow_control { + struct be_cmd_resp_hdr hdr; + u16 tx_flow_control; + u16 rx_flow_control; +} __packed; + +/******************** Modify EQ Delay *******************/ +struct be_cmd_req_modify_eq_delay { + struct be_cmd_req_hdr hdr; + u32 num_eq; + struct { + u32 eq_id; + u32 phase; + u32 delay_multiplier; + } delay[8]; +} __packed; + +struct be_cmd_resp_modify_eq_delay { + struct be_cmd_resp_hdr hdr; + u32 rsvd0; +} __packed; + +/******************** Get FW Config *******************/ +struct be_cmd_req_query_fw_cfg { + struct be_cmd_req_hdr hdr; + u32 rsvd[30]; +}; + +struct be_cmd_resp_query_fw_cfg { + struct be_cmd_resp_hdr hdr; + u32 be_config_number; + u32 asic_revision; + u32 phys_port; + u32 function_mode; + u32 rsvd[26]; +}; + +extern int be_pci_fnum_get(struct be_ctrl_info *ctrl); +extern int be_cmd_POST(struct be_ctrl_info *ctrl); +extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, + u8 type, bool permanent, u32 if_handle); +extern int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, + u32 if_id, u32 *pmac_id); +extern int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id); +extern int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 if_flags, u8 *mac, + bool pmac_invalid, u32 *if_handle, u32 *pmac_id); +extern int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 if_handle); +extern int be_cmd_eq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *eq, int eq_delay); +extern int be_cmd_cq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *cq, struct be_queue_info *eq, + bool sol_evts, bool no_delay, + int num_cqe_dma_coalesce); +extern int be_cmd_txq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *txq, + struct be_queue_info *cq); +extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *rxq, u16 cq_id, + u16 frag_size, u16 max_frame_size, u32 if_id, + u32 rss); +extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, + int type); +extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, + struct be_link_info *link); +extern int be_cmd_reset(struct be_ctrl_info *ctrl); +extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, + struct be_dma_mem *nonemb_cmd); +extern int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver); + +extern int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd); +extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, + u16 *vtag_array, u32 num, bool untagged, + bool promiscuous); +extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, + u8 port_num, bool en); +extern int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, + u8 *mac_table, u32 num, bool promiscuous); +extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, + u32 tx_fc, u32 rx_fc); +extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, + u32 *tx_fc, u32 *rx_fc); +extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c new file mode 100644 index 00000000000..04f4b73fa8d --- /dev/null +++ b/drivers/net/benet/be_ethtool.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" +#include <linux/ethtool.h> + +struct be_ethtool_stat { + char desc[ETH_GSTRING_LEN]; + int type; + int size; + int offset; +}; + +enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT}; +#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \ + offsetof(_struct, field) +#define NETSTAT_INFO(field) #field, NETSTAT,\ + FIELDINFO(struct net_device_stats,\ + field) +#define DRVSTAT_INFO(field) #field, DRVSTAT,\ + FIELDINFO(struct be_drvr_stats, field) +#define MISCSTAT_INFO(field) #field, MISCSTAT,\ + FIELDINFO(struct be_rxf_stats, field) +#define PORTSTAT_INFO(field) #field, PORTSTAT,\ + FIELDINFO(struct be_port_rxf_stats, \ + field) +#define ERXSTAT_INFO(field) #field, ERXSTAT,\ + FIELDINFO(struct be_erx_stats, field) + +static const struct be_ethtool_stat et_stats[] = { + {NETSTAT_INFO(rx_packets)}, + {NETSTAT_INFO(tx_packets)}, + {NETSTAT_INFO(rx_bytes)}, + {NETSTAT_INFO(tx_bytes)}, + {NETSTAT_INFO(rx_errors)}, + {NETSTAT_INFO(tx_errors)}, + {NETSTAT_INFO(rx_dropped)}, + {NETSTAT_INFO(tx_dropped)}, + {DRVSTAT_INFO(be_tx_reqs)}, + {DRVSTAT_INFO(be_tx_stops)}, + {DRVSTAT_INFO(be_fwd_reqs)}, + {DRVSTAT_INFO(be_tx_wrbs)}, + {DRVSTAT_INFO(be_polls)}, + {DRVSTAT_INFO(be_tx_events)}, + {DRVSTAT_INFO(be_rx_events)}, + {DRVSTAT_INFO(be_tx_compl)}, + {DRVSTAT_INFO(be_rx_compl)}, + {DRVSTAT_INFO(be_ethrx_post_fail)}, + {DRVSTAT_INFO(be_802_3_dropped_frames)}, + {DRVSTAT_INFO(be_802_3_malformed_frames)}, + {DRVSTAT_INFO(be_tx_rate)}, + {DRVSTAT_INFO(be_rx_rate)}, + {PORTSTAT_INFO(rx_unicast_frames)}, + {PORTSTAT_INFO(rx_multicast_frames)}, + {PORTSTAT_INFO(rx_broadcast_frames)}, + {PORTSTAT_INFO(rx_crc_errors)}, + {PORTSTAT_INFO(rx_alignment_symbol_errors)}, + {PORTSTAT_INFO(rx_pause_frames)}, + {PORTSTAT_INFO(rx_control_frames)}, + {PORTSTAT_INFO(rx_in_range_errors)}, + {PORTSTAT_INFO(rx_out_range_errors)}, + {PORTSTAT_INFO(rx_frame_too_long)}, + {PORTSTAT_INFO(rx_address_match_errors)}, + {PORTSTAT_INFO(rx_vlan_mismatch)}, + {PORTSTAT_INFO(rx_dropped_too_small)}, + {PORTSTAT_INFO(rx_dropped_too_short)}, + {PORTSTAT_INFO(rx_dropped_header_too_small)}, + {PORTSTAT_INFO(rx_dropped_tcp_length)}, + {PORTSTAT_INFO(rx_dropped_runt)}, + {PORTSTAT_INFO(rx_fifo_overflow)}, + {PORTSTAT_INFO(rx_input_fifo_overflow)}, + {PORTSTAT_INFO(rx_ip_checksum_errs)}, + {PORTSTAT_INFO(rx_tcp_checksum_errs)}, + {PORTSTAT_INFO(rx_udp_checksum_errs)}, + {PORTSTAT_INFO(rx_non_rss_packets)}, + {PORTSTAT_INFO(rx_ipv4_packets)}, + {PORTSTAT_INFO(rx_ipv6_packets)}, + {PORTSTAT_INFO(tx_unicastframes)}, + {PORTSTAT_INFO(tx_multicastframes)}, + {PORTSTAT_INFO(tx_broadcastframes)}, + {PORTSTAT_INFO(tx_pauseframes)}, + {PORTSTAT_INFO(tx_controlframes)}, + {MISCSTAT_INFO(rx_drops_no_pbuf)}, + {MISCSTAT_INFO(rx_drops_no_txpb)}, + {MISCSTAT_INFO(rx_drops_no_erx_descr)}, + {MISCSTAT_INFO(rx_drops_no_tpre_descr)}, + {MISCSTAT_INFO(rx_drops_too_many_frags)}, + {MISCSTAT_INFO(rx_drops_invalid_ring)}, + {MISCSTAT_INFO(forwarded_packets)}, + {MISCSTAT_INFO(rx_drops_mtu)}, + {ERXSTAT_INFO(rx_drops_no_fragments)}, +}; +#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) + +static void +be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + strcpy(drvinfo->driver, DRV_NAME); + strcpy(drvinfo->version, DRV_VER); + strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN); + strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; +} + +static int +be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + + coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; + + coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; + coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; + coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; + + coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; + coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; + coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; + + coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; + coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; + + return 0; +} + +/* + * This routine is used to set interrup coalescing delay *as well as* + * the number of pkts to coalesce for LRO. + */ +static int +be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + u32 tx_max, tx_min, tx_cur; + u32 rx_max, rx_min, rx_cur; + int status = 0; + + if (coalesce->use_adaptive_tx_coalesce == 1) + return -EINVAL; + + adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; + if (adapter->max_rx_coal > MAX_SKB_FRAGS) + adapter->max_rx_coal = MAX_SKB_FRAGS - 1; + + /* if AIC is being turned on now, start with an EQD of 0 */ + if (rx_eq->enable_aic == 0 && + coalesce->use_adaptive_rx_coalesce == 1) { + rx_eq->cur_eqd = 0; + } + rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; + + rx_max = coalesce->rx_coalesce_usecs_high; + rx_min = coalesce->rx_coalesce_usecs_low; + rx_cur = coalesce->rx_coalesce_usecs; + + tx_max = coalesce->tx_coalesce_usecs_high; + tx_min = coalesce->tx_coalesce_usecs_low; + tx_cur = coalesce->tx_coalesce_usecs; + + if (tx_cur > BE_MAX_EQD) + tx_cur = BE_MAX_EQD; + if (tx_eq->cur_eqd != tx_cur) { + status = be_cmd_modify_eqd(ctrl, tx_eq->q.id, tx_cur); + if (!status) + tx_eq->cur_eqd = tx_cur; + } + + if (rx_eq->enable_aic) { + if (rx_max > BE_MAX_EQD) + rx_max = BE_MAX_EQD; + if (rx_min > rx_max) + rx_min = rx_max; + rx_eq->max_eqd = rx_max; + rx_eq->min_eqd = rx_min; + if (rx_eq->cur_eqd > rx_max) + rx_eq->cur_eqd = rx_max; + if (rx_eq->cur_eqd < rx_min) + rx_eq->cur_eqd = rx_min; + } else { + if (rx_cur > BE_MAX_EQD) + rx_cur = BE_MAX_EQD; + if (rx_eq->cur_eqd != rx_cur) { + status = be_cmd_modify_eqd(ctrl, rx_eq->q.id, rx_cur); + if (!status) + rx_eq->cur_eqd = rx_cur; + } + } + return 0; +} + +static u32 be_get_rx_csum(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + return adapter->rx_csum; +} + +static int be_set_rx_csum(struct net_device *netdev, uint32_t data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (data) + adapter->rx_csum = true; + else + adapter->rx_csum = false; + + return 0; +} + +static void +be_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats; + struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); + struct be_rxf_stats *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats *port_stats = + &rxf_stats->port[adapter->port_num]; + struct net_device_stats *net_stats = &adapter->stats.net_stats; + struct be_erx_stats *erx_stats = &hw_stats->erx; + void *p = NULL; + int i; + + for (i = 0; i < ETHTOOL_STATS_NUM; i++) { + switch (et_stats[i].type) { + case NETSTAT: + p = net_stats; + break; + case DRVSTAT: + p = drvr_stats; + break; + case PORTSTAT: + p = port_stats; + break; + case MISCSTAT: + p = rxf_stats; + break; + case ERXSTAT: /* Currently only one ERX stat is provided */ + p = (u32 *)erx_stats + adapter->rx_obj.q.id; + break; + } + + p = (u8 *)p + et_stats[i].offset; + data[i] = (et_stats[i].size == sizeof(u64)) ? + *(u64 *)p: *(u32 *)p; + } + + return; +} + +static void +be_get_stat_strings(struct net_device *netdev, uint32_t stringset, + uint8_t *data) +{ + int i; + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ETHTOOL_STATS_NUM; i++) { + memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + break; + } +} + +static int be_get_stats_count(struct net_device *netdev) +{ + return ETHTOOL_STATS_NUM; +} + +static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_DISABLE; + return 0; +} + +static void +be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + ring->rx_max_pending = adapter->rx_obj.q.len; + ring->tx_max_pending = adapter->tx_obj.q.len; + + ring->rx_pending = atomic_read(&adapter->rx_obj.q.used); + ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); +} + +static void +be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + be_cmd_get_flow_control(&adapter->ctrl, &ecmd->tx_pause, + &ecmd->rx_pause); + ecmd->autoneg = AUTONEG_ENABLE; +} + +static int +be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int status; + + if (ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + status = be_cmd_set_flow_control(&adapter->ctrl, ecmd->tx_pause, + ecmd->rx_pause); + if (!status) + dev_warn(&adapter->pdev->dev, "Pause param set failed.\n"); + + return status; +} + +struct ethtool_ops be_ethtool_ops = { + .get_settings = be_get_settings, + .get_drvinfo = be_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_coalesce = be_get_coalesce, + .set_coalesce = be_set_coalesce, + .get_ringparam = be_get_ringparam, + .get_pauseparam = be_get_pauseparam, + .set_pauseparam = be_set_pauseparam, + .get_rx_csum = be_get_rx_csum, + .set_rx_csum = be_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, + .set_tso = ethtool_op_set_tso, + .get_strings = be_get_stat_strings, + .get_stats_count = be_get_stats_count, + .get_ethtool_stats = be_get_ethtool_stats, +}; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h new file mode 100644 index 00000000000..b132aa4893c --- /dev/null +++ b/drivers/net/benet/be_hw.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +/********* Mailbox door bell *************/ +/* Used for driver communication with the FW. + * The software must write this register twice to post any command. First, + * it writes the register with hi=1 and the upper bits of the physical address + * for the MAILBOX structure. Software must poll the ready bit until this + * is acknowledged. Then, sotware writes the register with hi=0 with the lower + * bits in the address. It must poll the ready bit until the command is + * complete. Upon completion, the MAILBOX will contain a valid completion + * queue entry. + */ +#define MPU_MAILBOX_DB_OFFSET 0x160 +#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ +#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ + +#define MPU_EP_CONTROL 0 + +/********** MPU semphore ******************/ +#define MPU_EP_SEMAPHORE_OFFSET 0xac +#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF +#define EP_SEMAPHORE_POST_ERR_MASK 0x1 +#define EP_SEMAPHORE_POST_ERR_SHIFT 31 +/* MPU semphore POST stage values */ +#define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ +#define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */ +#define POST_STAGE_BE_RESET 0x3 /* Host wants to reset chip */ +#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ + +/********* Memory BAR register ************/ +#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc +/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt + * Disable" may still globally block interrupts in addition to individual + * interrupt masks; a mechanism for the device driver to block all interrupts + * atomically without having to arbitrate for the PCI Interrupt Disable bit + * with the OS. + */ +#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ +/* PCI physical function number */ +#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ +#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 + +/********* Event Q door bell *************/ +#define DB_EQ_OFFSET DB_CQ_OFFSET +#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ +/* Clear the interrupt for this eq */ +#define DB_EQ_CLR_SHIFT (9) /* bit 9 */ +/* Must be 1 */ +#define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ +/* Number of event entries processed */ +#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +/* Rearm bit */ +#define DB_EQ_REARM_SHIFT (29) /* bit 29 */ + +/********* Compl Q door bell *************/ +#define DB_CQ_OFFSET 0x120 +#define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +/* Number of event entries processed */ +#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +/* Rearm bit */ +#define DB_CQ_REARM_SHIFT (29) /* bit 29 */ + +/********** TX ULP door bell *************/ +#define DB_TXULP1_OFFSET 0x60 +#define DB_TXULP_RING_ID_MASK 0x7FF /* bits 0 - 10 */ +/* Number of tx entries posted */ +#define DB_TXULP_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ +#define DB_TXULP_NUM_POSTED_MASK 0x3FFF /* bits 16 - 29 */ + +/********** RQ(erx) door bell ************/ +#define DB_RQ_OFFSET 0x100 +#define DB_RQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +/* Number of rx frags posted */ +#define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */ + +/* + * BE descriptors: host memory data structures whose formats + * are hardwired in BE silicon. + */ +/* Event Queue Descriptor */ +#define EQ_ENTRY_VALID_MASK 0x1 /* bit 0 */ +#define EQ_ENTRY_RES_ID_MASK 0xFFFF /* bits 16 - 31 */ +#define EQ_ENTRY_RES_ID_SHIFT 16 +struct be_eq_entry { + u32 evt; +}; + +/* TX Queue Descriptor */ +#define ETH_WRB_FRAG_LEN_MASK 0xFFFF +struct be_eth_wrb { + u32 frag_pa_hi; /* dword 0 */ + u32 frag_pa_lo; /* dword 1 */ + u32 rsvd0; /* dword 2 */ + u32 frag_len; /* dword 3: bits 0 - 15 */ +} __packed; + +/* Pseudo amap definition for eth_hdr_wrb in which each bit of the + * actual structure is defined as a byte : used to calculate + * offset/shift/mask of each field */ +struct amap_eth_hdr_wrb { + u8 rsvd0[32]; /* dword 0 */ + u8 rsvd1[32]; /* dword 1 */ + u8 complete; /* dword 2 */ + u8 event; + u8 crc; + u8 forward; + u8 ipsec; + u8 mgmt; + u8 ipcs; + u8 udpcs; + u8 tcpcs; + u8 lso; + u8 vlan; + u8 gso[2]; + u8 num_wrb[5]; + u8 lso_mss[14]; + u8 len[16]; /* dword 3 */ + u8 vlan_tag[16]; +} __packed; + +struct be_eth_hdr_wrb { + u32 dw[4]; +}; + +/* TX Compl Queue Descriptor */ + +/* Pseudo amap definition for eth_tx_compl in which each bit of the + * actual structure is defined as a byte: used to calculate + * offset/shift/mask of each field */ +struct amap_eth_tx_compl { + u8 wrb_index[16]; /* dword 0 */ + u8 ct[2]; /* dword 0 */ + u8 port[2]; /* dword 0 */ + u8 rsvd0[8]; /* dword 0 */ + u8 status[4]; /* dword 0 */ + u8 user_bytes[16]; /* dword 1 */ + u8 nwh_bytes[8]; /* dword 1 */ + u8 lso; /* dword 1 */ + u8 cast_enc[2]; /* dword 1 */ + u8 rsvd1[5]; /* dword 1 */ + u8 rsvd2[32]; /* dword 2 */ + u8 pkts[16]; /* dword 3 */ + u8 ringid[11]; /* dword 3 */ + u8 hash_val[4]; /* dword 3 */ + u8 valid; /* dword 3 */ +} __packed; + +struct be_eth_tx_compl { + u32 dw[4]; +}; + +/* RX Queue Descriptor */ +struct be_eth_rx_d { + u32 fragpa_hi; + u32 fragpa_lo; +}; + +/* RX Compl Queue Descriptor */ + +/* Pseudo amap definition for eth_rx_compl in which each bit of the + * actual structure is defined as a byte: used to calculate + * offset/shift/mask of each field */ +struct amap_eth_rx_compl { + u8 vlan_tag[16]; /* dword 0 */ + u8 pktsize[14]; /* dword 0 */ + u8 port; /* dword 0 */ + u8 ip_opt; /* dword 0 */ + u8 err; /* dword 1 */ + u8 rsshp; /* dword 1 */ + u8 ipf; /* dword 1 */ + u8 tcpf; /* dword 1 */ + u8 udpf; /* dword 1 */ + u8 ipcksm; /* dword 1 */ + u8 l4_cksm; /* dword 1 */ + u8 ip_version; /* dword 1 */ + u8 macdst[6]; /* dword 1 */ + u8 vtp; /* dword 1 */ + u8 rsvd0; /* dword 1 */ + u8 fragndx[10]; /* dword 1 */ + u8 ct[2]; /* dword 1 */ + u8 sw; /* dword 1 */ + u8 numfrags[3]; /* dword 1 */ + u8 rss_flush; /* dword 2 */ + u8 cast_enc[2]; /* dword 2 */ + u8 qnq; /* dword 2 */ + u8 rss_bank; /* dword 2 */ + u8 rsvd1[23]; /* dword 2 */ + u8 lro_pkt; /* dword 2 */ + u8 rsvd2[2]; /* dword 2 */ + u8 valid; /* dword 2 */ + u8 rsshash[32]; /* dword 3 */ +} __packed; + +struct be_eth_rx_compl { + u32 dw[4]; +}; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c new file mode 100644 index 00000000000..0ecaffb70e5 --- /dev/null +++ b/drivers/net/benet/be_main.c @@ -0,0 +1,1911 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" + +MODULE_VERSION(DRV_VER); +MODULE_DEVICE_TABLE(pci, be_dev_ids); +MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); +MODULE_AUTHOR("ServerEngines Corporation"); +MODULE_LICENSE("GPL"); + +static unsigned int rx_frag_size = 2048; +module_param(rx_frag_size, uint, S_IRUGO); +MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); + +#define BE_VENDOR_ID 0x19a2 +#define BE2_DEVICE_ID_1 0x0211 +static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, BE2_DEVICE_ID_1) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, be_dev_ids); + +static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) +{ + struct be_dma_mem *mem = &q->dma_mem; + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); +} + +static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, + u16 len, u16 entry_size) +{ + struct be_dma_mem *mem = &q->dma_mem; + + memset(q, 0, sizeof(*q)); + q->len = len; + q->entry_size = entry_size; + mem->size = len * entry_size; + mem->va = pci_alloc_consistent(adapter->pdev, mem->size, &mem->dma); + if (!mem->va) + return -1; + memset(mem->va, 0, mem->size); + return 0; +} + +static inline void *queue_head_node(struct be_queue_info *q) +{ + return q->dma_mem.va + q->head * q->entry_size; +} + +static inline void *queue_tail_node(struct be_queue_info *q) +{ + return q->dma_mem.va + q->tail * q->entry_size; +} + +static inline void queue_head_inc(struct be_queue_info *q) +{ + index_inc(&q->head, q->len); +} + +static inline void queue_tail_inc(struct be_queue_info *q) +{ + index_inc(&q->tail, q->len); +} + +static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) +{ + u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; + u32 reg = ioread32(addr); + u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + if (!enabled && enable) { + reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + } else if (enabled && !enable) { + reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + } else { + printk(KERN_WARNING DRV_NAME + ": bad value in membar_int_ctrl reg=0x%x\n", reg); + return; + } + iowrite32(reg, addr); +} + +static void be_rxq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +{ + u32 val = 0; + val |= qid & DB_RQ_RING_ID_MASK; + val |= posted << DB_RQ_NUM_POSTED_SHIFT; + iowrite32(val, ctrl->db + DB_RQ_OFFSET); +} + +static void be_txq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +{ + u32 val = 0; + val |= qid & DB_TXULP_RING_ID_MASK; + val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; + iowrite32(val, ctrl->db + DB_TXULP1_OFFSET); +} + +static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, + bool arm, bool clear_int, u16 num_popped) +{ + u32 val = 0; + val |= qid & DB_EQ_RING_ID_MASK; + if (arm) + val |= 1 << DB_EQ_REARM_SHIFT; + if (clear_int) + val |= 1 << DB_EQ_CLR_SHIFT; + val |= 1 << DB_EQ_EVNT_SHIFT; + val |= num_popped << DB_EQ_NUM_POPPED_SHIFT; + iowrite32(val, ctrl->db + DB_EQ_OFFSET); +} + +static void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, + bool arm, u16 num_popped) +{ + u32 val = 0; + val |= qid & DB_CQ_RING_ID_MASK; + if (arm) + val |= 1 << DB_CQ_REARM_SHIFT; + val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; + iowrite32(val, ctrl->db + DB_CQ_OFFSET); +} + + +static int be_mac_addr_set(struct net_device *netdev, void *p) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + int status = 0; + + if (netif_running(netdev)) { + status = be_cmd_pmac_del(&adapter->ctrl, adapter->if_handle, + adapter->pmac_id); + if (status) + return status; + + status = be_cmd_pmac_add(&adapter->ctrl, (u8 *)addr->sa_data, + adapter->if_handle, &adapter->pmac_id); + } + + if (!status) + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + + return status; +} + +static void netdev_stats_update(struct be_adapter *adapter) +{ + struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); + struct be_rxf_stats *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats *port_stats = + &rxf_stats->port[adapter->port_num]; + struct net_device_stats *dev_stats = &adapter->stats.net_stats; + + dev_stats->rx_packets = port_stats->rx_total_frames; + dev_stats->tx_packets = port_stats->tx_unicastframes + + port_stats->tx_multicastframes + port_stats->tx_broadcastframes; + dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 | + (u64) port_stats->rx_bytes_lsd; + dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 | + (u64) port_stats->tx_bytes_lsd; + + /* bad pkts received */ + 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; + + /* 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; + + /* 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; + /* 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 + + port_stats->rx_input_fifo_overflow + + rxf_stats->rx_drops_no_pbuf; + /* receiver missed packetd */ + dev_stats->rx_missed_errors = 0; + /* detailed tx_errors */ + dev_stats->tx_aborted_errors = 0; + dev_stats->tx_carrier_errors = 0; + dev_stats->tx_fifo_errors = 0; + dev_stats->tx_heartbeat_errors = 0; + dev_stats->tx_window_errors = 0; +} + +static void be_link_status_update(struct be_adapter *adapter) +{ + struct be_link_info *prev = &adapter->link; + struct be_link_info now = { 0 }; + struct net_device *netdev = adapter->netdev; + + be_cmd_link_status_query(&adapter->ctrl, &now); + + /* If link came up or went down */ + if (now.speed != prev->speed && (now.speed == PHY_LINK_SPEED_ZERO || + prev->speed == PHY_LINK_SPEED_ZERO)) { + if (now.speed == PHY_LINK_SPEED_ZERO) { + netif_stop_queue(netdev); + netif_carrier_off(netdev); + printk(KERN_INFO "%s: Link down\n", netdev->name); + } else { + netif_start_queue(netdev); + netif_carrier_on(netdev); + printk(KERN_INFO "%s: Link up\n", netdev->name); + } + } + *prev = now; +} + +/* Update the EQ delay n BE based on the RX frags consumed / sec */ +static void be_rx_eqd_update(struct be_adapter *adapter) +{ + u32 eqd; + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + + /* Update once a second */ + if (((jiffies - stats->rx_fps_jiffies) < HZ) || rx_eq->enable_aic == 0) + return; + + stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) / + ((jiffies - stats->rx_fps_jiffies) / HZ); + + stats->rx_fps_jiffies = jiffies; + stats->be_prev_rx_frags = stats->be_rx_frags; + eqd = stats->be_rx_fps / 110000; + eqd = eqd << 3; + if (eqd > rx_eq->max_eqd) + eqd = rx_eq->max_eqd; + if (eqd < rx_eq->min_eqd) + eqd = rx_eq->min_eqd; + if (eqd < 10) + eqd = 0; + if (eqd != rx_eq->cur_eqd) + be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd); + + rx_eq->cur_eqd = eqd; +} + +static struct net_device_stats *be_get_stats(struct net_device *dev) +{ + struct be_adapter *adapter = netdev_priv(dev); + + return &adapter->stats.net_stats; +} + +static void be_tx_stats_update(struct be_adapter *adapter, + u32 wrb_cnt, u32 copied, bool stopped) +{ + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + stats->be_tx_reqs++; + stats->be_tx_wrbs += wrb_cnt; + stats->be_tx_bytes += copied; + if (stopped) + stats->be_tx_stops++; + + /* Update tx rate once in two seconds */ + if ((jiffies - stats->be_tx_jiffies) > 2 * HZ) { + u32 r; + r = (stats->be_tx_bytes - stats->be_tx_bytes_prev) / + ((u32) (jiffies - stats->be_tx_jiffies) / HZ); + r = (r / 1000000); /* M bytes/s */ + stats->be_tx_rate = (r * 8); /* M bits/s */ + stats->be_tx_jiffies = jiffies; + stats->be_tx_bytes_prev = stats->be_tx_bytes; + } +} + +/* 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; + } + /* to account for hdr wrb */ + cnt++; + if (cnt & 1) { + /* add a dummy to make it an even num */ + cnt++; + *dummy = true; + } else + *dummy = false; + BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); + return cnt; +} + +static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) +{ + wrb->frag_pa_hi = upper_32_bits(addr); + wrb->frag_pa_lo = addr & 0xFFFFFFFF; + wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; +} + +static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, + bool vlan, u32 wrb_cnt, u32 len) +{ + memset(hdr, 0, sizeof(*hdr)); + + AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1); + + if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, + hdr, skb_shinfo(skb)->gso_size); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (is_tcp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); + else if (is_udp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1); + } + + if (vlan && vlan_tx_tag_present(skb)) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, + hdr, vlan_tx_tag_get(skb)); + } + + AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, num_wrb, hdr, wrb_cnt); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len); +} + + +static int make_tx_wrbs(struct be_adapter *adapter, + struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb) +{ + u64 busaddr; + u32 i, copied = 0; + struct pci_dev *pdev = adapter->pdev; + struct sk_buff *first_skb = skb; + struct be_queue_info *txq = &adapter->tx_obj.q; + struct be_eth_wrb *wrb; + struct be_eth_hdr_wrb *hdr; + + atomic_add(wrb_cnt, &txq->used); + 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; + } + + 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; + } + + if (dummy_wrb) { + wrb = queue_head_node(txq); + wrb_fill(wrb, 0, 0); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + } + + wrb_fill_hdr(hdr, first_skb, adapter->vlan_grp ? true : false, + wrb_cnt, copied); + be_dws_cpu_to_le(hdr, sizeof(*hdr)); + + return copied; +} + +static int be_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_tx_obj *tx_obj = &adapter->tx_obj; + struct be_queue_info *txq = &tx_obj->q; + u32 wrb_cnt = 0, copied = 0; + u32 start = txq->head; + bool dummy_wrb, stopped = false; + + wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb); + + copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); + + /* record the sent skb in the sent_skb table */ + BUG_ON(tx_obj->sent_skb_list[start]); + tx_obj->sent_skb_list[start] = skb; + + /* Ensure that txq has space for the next skb; Else stop the queue + * *BEFORE* ringing the tx doorbell, so that we serialze the + * tx compls of the current transmit which'll wake up the queue + */ + if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) { + netif_stop_queue(netdev); + stopped = true; + } + + 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; +} + +static int be_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct be_adapter *adapter = netdev_priv(netdev); + if (new_mtu < BE_MIN_MTU || + new_mtu > BE_MAX_JUMBO_FRAME_SIZE) { + dev_info(&adapter->pdev->dev, + "MTU must be between %d and %d bytes\n", + BE_MIN_MTU, BE_MAX_JUMBO_FRAME_SIZE); + return -EINVAL; + } + dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", + netdev->mtu, new_mtu); + netdev->mtu = new_mtu; + return 0; +} + +/* + * if there are BE_NUM_VLANS_SUPPORTED or lesser number of VLANS configured, + * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, + * set the BE in promiscuous VLAN mode. + */ +static void be_vid_config(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + u16 vtag[BE_NUM_VLANS_SUPPORTED]; + u16 ntags = 0, i; + + if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { + /* Construct VLAN Table to give to HW */ + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (adapter->vlan_tag[i]) { + vtag[ntags] = cpu_to_le16(i); + ntags++; + } + } + be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, + vtag, ntags, 1, 0); + } else { + be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, + NULL, 0, 1, 1); + } +} + +static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_ctrl_info *ctrl = &adapter->ctrl; + + be_eq_notify(ctrl, rx_eq->q.id, false, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, false, false, 0); + adapter->vlan_grp = grp; + be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); +} + +static void be_vlan_add_vid(struct net_device *netdev, u16 vid) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->num_vlans++; + adapter->vlan_tag[vid] = 1; + + be_vid_config(netdev); +} + +static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->num_vlans--; + adapter->vlan_tag[vid] = 0; + + vlan_group_set_device(adapter->vlan_grp, vid, NULL); + be_vid_config(netdev); +} + +static void be_set_multicast_filter(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct dev_mc_list *mc_ptr; + u8 mac_addr[32][ETH_ALEN]; + int i = 0; + + if (netdev->flags & IFF_ALLMULTI) { + /* set BE in Multicast promiscuous */ + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, NULL, 0, true); + return; + } + + for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); + if (++i >= 32) { + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, &mac_addr[0][0], i, false); + i = 0; + } + + } + + if (i) { + /* reset the promiscuous mode also. */ + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, &mac_addr[0][0], i, false); + } +} + +static void be_set_multicast_list(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (netdev->flags & IFF_PROMISC) { + be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 1); + } else { + be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 0); + be_set_multicast_filter(netdev); + } +} + +static void be_rx_rate_update(struct be_adapter *adapter, u32 pktsize, + u16 numfrags) +{ + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + u32 rate; + + stats->be_rx_compl++; + stats->be_rx_frags += numfrags; + stats->be_rx_bytes += pktsize; + + /* Update the rate once in two seconds */ + if ((jiffies - stats->be_rx_jiffies) < 2 * HZ) + return; + + rate = (stats->be_rx_bytes - stats->be_rx_bytes_prev) / + ((u32) (jiffies - stats->be_rx_jiffies) / HZ); + rate = (rate / 1000000); /* MB/Sec */ + stats->be_rx_rate = (rate * 8); /* Mega Bits/Sec */ + stats->be_rx_jiffies = jiffies; + stats->be_rx_bytes_prev = stats->be_rx_bytes; +} + +static struct be_rx_page_info * +get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) +{ + struct be_rx_page_info *rx_page_info; + struct be_queue_info *rxq = &adapter->rx_obj.q; + + rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; + BUG_ON(!rx_page_info->page); + + if (rx_page_info->last_page_user) + pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), + adapter->big_page_size, PCI_DMA_FROMDEVICE); + + atomic_dec(&rxq->used); + return rx_page_info; +} + +/* Throwaway the data in the Rx completion */ +static void be_rx_compl_discard(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_rx_page_info *page_info; + u16 rxq_idx, i, num_rcvd; + + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + + for (i = 0; i < num_rcvd; i++) { + page_info = get_rx_page_info(adapter, rxq_idx); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + index_inc(&rxq_idx, rxq->len); + } +} + +/* + * skb_fill_rx_data forms a complete skb for an ether frame + * indicated by rxcp. + */ +static void skb_fill_rx_data(struct be_adapter *adapter, + struct sk_buff *skb, struct be_eth_rx_compl *rxcp) +{ + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_rx_page_info *page_info; + u16 rxq_idx, i, num_rcvd; + u32 pktsize, hdr_len, curr_frag_len; + u8 *start; + + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + + page_info = get_rx_page_info(adapter, rxq_idx); + + start = page_address(page_info->page) + page_info->page_offset; + prefetch(start); + + /* Copy data in the first descriptor of this completion */ + curr_frag_len = min(pktsize, rx_frag_size); + + /* Copy the header portion into skb_data */ + hdr_len = min((u32)BE_HDR_LEN, curr_frag_len); + memcpy(skb->data, start, hdr_len); + skb->len = curr_frag_len; + if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */ + /* Complete packet has now been moved to data */ + put_page(page_info->page); + skb->data_len = 0; + skb->tail += curr_frag_len; + } else { + skb_shinfo(skb)->nr_frags = 1; + skb_shinfo(skb)->frags[0].page = page_info->page; + skb_shinfo(skb)->frags[0].page_offset = + page_info->page_offset + hdr_len; + skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len; + skb->data_len = curr_frag_len - hdr_len; + skb->tail += hdr_len; + } + memset(page_info, 0, sizeof(*page_info)); + + if (pktsize <= rx_frag_size) { + BUG_ON(num_rcvd != 1); + return; + } + + /* More frags present for this completion */ + pktsize -= curr_frag_len; /* account for above copied frag */ + for (i = 1; i < num_rcvd; i++) { + index_inc(&rxq_idx, rxq->len); + page_info = get_rx_page_info(adapter, rxq_idx); + + curr_frag_len = min(pktsize, rx_frag_size); + + skb_shinfo(skb)->frags[i].page = page_info->page; + skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset; + skb_shinfo(skb)->frags[i].size = curr_frag_len; + skb->len += curr_frag_len; + skb->data_len += curr_frag_len; + skb_shinfo(skb)->nr_frags++; + pktsize -= curr_frag_len; + + memset(page_info, 0, sizeof(*page_info)); + } + + be_rx_rate_update(adapter, pktsize, num_rcvd); + return; +} + +/* Process the RX completion indicated by rxcp when LRO is disabled */ +static void be_rx_compl_process(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + 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); + if (!skb) { + if (net_ratelimit()) + dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); + be_rx_compl_discard(adapter, rxcp); + return; + } + + skb_reserve(skb, NET_IP_ALIGN); + + skb_fill_rx_data(adapter, skb, rxcp); + + if (l4_cksm && adapter->rx_csum) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + skb->truesize = skb->len + sizeof(struct sk_buff); + skb->protocol = eth_type_trans(skb, adapter->netdev); + skb->dev = adapter->netdev; + + if (vtp) { + if (!adapter->vlan_grp || adapter->num_vlans == 0) { + kfree_skb(skb); + return; + } + vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); + vid = be16_to_cpu(vid); + vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid); + } else { + netif_receive_skb(skb); + } + + adapter->netdev->last_rx = jiffies; + + return; +} + +/* Process the RX completion indicated by rxcp when LRO is enabled */ +static void be_rx_compl_process_lro(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct be_rx_page_info *page_info; + struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; + struct be_queue_info *rxq = &adapter->rx_obj.q; + u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; + u16 i, rxq_idx = 0, vid; + + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + + remaining = pkt_size; + for (i = 0; i < num_rcvd; i++) { + page_info = get_rx_page_info(adapter, rxq_idx); + + curr_frag_len = min(remaining, rx_frag_size); + + rx_frags[i].page = page_info->page; + rx_frags[i].page_offset = page_info->page_offset; + rx_frags[i].size = curr_frag_len; + remaining -= curr_frag_len; + + index_inc(&rxq_idx, rxq->len); + + memset(page_info, 0, sizeof(*page_info)); + } + + if (likely(!vlanf)) { + lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, + pkt_size, NULL, 0); + } else { + vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); + vid = be16_to_cpu(vid); + + if (!adapter->vlan_grp || adapter->num_vlans == 0) + return; + + lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr, + rx_frags, pkt_size, pkt_size, adapter->vlan_grp, + vid, NULL, 0); + } + + be_rx_rate_update(adapter, pkt_size, num_rcvd); + return; +} + +static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) +{ + struct be_eth_rx_compl *rxcp = queue_tail_node(&adapter->rx_obj.cq); + + if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0) + return NULL; + + 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; +} + +static inline struct page *be_alloc_pages(u32 size) +{ + gfp_t alloc_flags = GFP_ATOMIC; + u32 order = get_order(size); + if (order > 0) + alloc_flags |= __GFP_COMP; + return alloc_pages(alloc_flags, order); +} + +/* + * Allocate a page, split it to fragments of size rx_frag_size and post as + * receive buffers to BE + */ +static void be_post_rx_frags(struct be_adapter *adapter) +{ + struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; + struct be_rx_page_info *page_info = NULL; + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct page *pagep = NULL; + struct be_eth_rx_d *rxd; + u64 page_dmaaddr = 0, frag_dmaaddr; + u32 posted, page_offset = 0; + + + page_info = &page_info_tbl[rxq->head]; + for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) { + if (!pagep) { + pagep = be_alloc_pages(adapter->big_page_size); + if (unlikely(!pagep)) { + drvr_stats(adapter)->be_ethrx_post_fail++; + break; + } + page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0, + adapter->big_page_size, + PCI_DMA_FROMDEVICE); + page_info->page_offset = 0; + } else { + get_page(pagep); + page_info->page_offset = page_offset + rx_frag_size; + } + page_offset = page_info->page_offset; + page_info->page = pagep; + pci_unmap_addr_set(page_info, bus, page_dmaaddr); + frag_dmaaddr = page_dmaaddr + page_info->page_offset; + + rxd = queue_head_node(rxq); + rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); + rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); + queue_head_inc(rxq); + + /* Any space left in the current big page for another frag? */ + if ((page_offset + rx_frag_size + rx_frag_size) > + adapter->big_page_size) { + pagep = NULL; + page_info->last_page_user = true; + } + page_info = &page_info_tbl[rxq->head]; + } + if (pagep) + page_info->last_page_user = true; + + if (posted) { + atomic_add(posted, &rxq->used); + be_rxq_notify(&adapter->ctrl, rxq->id, posted); + } else if (atomic_read(&rxq->used) == 0) { + /* Let be_worker replenish when memory is available */ + adapter->rx_post_starved = true; + } + + return; +} + +static struct be_eth_tx_compl * +be_tx_compl_get(struct be_adapter *adapter) +{ + struct be_queue_info *tx_cq = &adapter->tx_obj.cq; + struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq); + + if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) + return NULL; + + be_dws_le_to_cpu(txcp, sizeof(*txcp)); + + txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] = 0; + + queue_tail_inc(tx_cq); + return txcp; +} + +static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) +{ + struct be_queue_info *txq = &adapter->tx_obj.q; + struct be_eth_wrb *wrb; + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + u64 busaddr; + u16 cur_index, num_wrbs = 0; + + cur_index = txq->tail; + sent_skb = sent_skbs[cur_index]; + BUG_ON(!sent_skb); + sent_skbs[cur_index] = NULL; + + do { + cur_index = txq->tail; + wrb = queue_tail_node(txq); + be_dws_le_to_cpu(wrb, sizeof(*wrb)); + busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo; + if (busaddr != 0) { + pci_unmap_single(adapter->pdev, busaddr, + wrb->frag_len, PCI_DMA_TODEVICE); + } + num_wrbs++; + queue_tail_inc(txq); + } while (cur_index != last_index); + + atomic_sub(num_wrbs, &txq->used); + + kfree_skb(sent_skb); +} + +static void be_rx_q_clean(struct be_adapter *adapter) +{ + struct be_rx_page_info *page_info; + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_queue_info *rx_cq = &adapter->rx_obj.cq; + struct be_eth_rx_compl *rxcp; + u16 tail; + + /* First cleanup pending rx completions */ + while ((rxcp = be_rx_compl_get(adapter)) != NULL) { + be_rx_compl_discard(adapter, rxcp); + be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1); + } + + /* Then free posted rx buffer that were not used */ + tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; + for (; tail != rxq->head; index_inc(&tail, rxq->len)) { + page_info = get_rx_page_info(adapter, tail); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + } + BUG_ON(atomic_read(&rxq->used)); +} + +static void be_tx_q_clean(struct be_adapter *adapter) +{ + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + struct be_queue_info *txq = &adapter->tx_obj.q; + u16 last_index; + bool dummy_wrb; + + while (atomic_read(&txq->used)) { + sent_skb = sent_skbs[txq->tail]; + last_index = txq->tail; + index_adv(&last_index, + wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); + be_tx_compl_process(adapter, last_index); + } +} + +static void be_tx_queues_destroy(struct be_adapter *adapter) +{ + struct be_queue_info *q; + + q = &adapter->tx_obj.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ); + be_queue_free(adapter, q); + + q = &adapter->tx_obj.cq; + if (q->created) + 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); + be_queue_free(adapter, q); +} + +static int be_tx_queues_create(struct be_adapter *adapter) +{ + struct be_queue_info *eq, *q, *cq; + + adapter->tx_eq.max_eqd = 0; + adapter->tx_eq.min_eqd = 0; + adapter->tx_eq.cur_eqd = 96; + adapter->tx_eq.enable_aic = false; + /* Alloc Tx Event queue */ + eq = &adapter->tx_eq.q; + if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry))) + return -1; + + /* Ask BE to create Tx Event queue */ + if (be_cmd_eq_create(&adapter->ctrl, eq, adapter->tx_eq.cur_eqd)) + goto tx_eq_free; + /* Alloc TX eth compl queue */ + cq = &adapter->tx_obj.cq; + if (be_queue_alloc(adapter, cq, TX_CQ_LEN, + sizeof(struct be_eth_tx_compl))) + goto tx_eq_destroy; + + /* Ask BE to create Tx eth compl queue */ + if (be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3)) + goto tx_cq_free; + + /* Alloc TX eth queue */ + q = &adapter->tx_obj.q; + if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb))) + goto tx_cq_destroy; + + /* Ask BE to create Tx eth queue */ + if (be_cmd_txq_create(&adapter->ctrl, q, cq)) + goto tx_q_free; + return 0; + +tx_q_free: + be_queue_free(adapter, q); +tx_cq_destroy: + be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); +tx_cq_free: + be_queue_free(adapter, cq); +tx_eq_destroy: + be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); +tx_eq_free: + be_queue_free(adapter, eq); + return -1; +} + +static void be_rx_queues_destroy(struct be_adapter *adapter) +{ + struct be_queue_info *q; + + q = &adapter->rx_obj.q; + if (q->created) { + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_RXQ); + be_rx_q_clean(adapter); + } + be_queue_free(adapter, q); + + q = &adapter->rx_obj.cq; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_queue_free(adapter, q); + + q = &adapter->rx_eq.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_queue_free(adapter, q); +} + +static int be_rx_queues_create(struct be_adapter *adapter) +{ + struct be_queue_info *eq, *q, *cq; + int rc; + + adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; + adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; + adapter->rx_eq.max_eqd = BE_MAX_EQD; + adapter->rx_eq.min_eqd = 0; + adapter->rx_eq.cur_eqd = 0; + adapter->rx_eq.enable_aic = true; + + /* Alloc Rx Event queue */ + eq = &adapter->rx_eq.q; + rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, + sizeof(struct be_eq_entry)); + if (rc) + return rc; + + /* Ask BE to create Rx Event queue */ + rc = be_cmd_eq_create(&adapter->ctrl, eq, adapter->rx_eq.cur_eqd); + if (rc) + goto rx_eq_free; + + /* Alloc RX eth compl queue */ + cq = &adapter->rx_obj.cq; + rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, + sizeof(struct be_eth_rx_compl)); + if (rc) + goto rx_eq_destroy; + + /* Ask BE to create Rx eth compl queue */ + rc = be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3); + if (rc) + goto rx_cq_free; + + /* Alloc RX eth queue */ + q = &adapter->rx_obj.q; + rc = be_queue_alloc(adapter, q, RX_Q_LEN, sizeof(struct be_eth_rx_d)); + if (rc) + goto rx_cq_destroy; + + /* Ask BE to create Rx eth queue */ + rc = be_cmd_rxq_create(&adapter->ctrl, q, cq->id, rx_frag_size, + BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false); + if (rc) + goto rx_q_free; + + return 0; +rx_q_free: + be_queue_free(adapter, q); +rx_cq_destroy: + be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); +rx_cq_free: + be_queue_free(adapter, cq); +rx_eq_destroy: + be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); +rx_eq_free: + be_queue_free(adapter, eq); + return rc; +} +static bool event_get(struct be_eq_obj *eq_obj, u16 *rid) +{ + struct be_eq_entry *entry = queue_tail_node(&eq_obj->q); + u32 evt = entry->evt; + + if (!evt) + return false; + + evt = le32_to_cpu(evt); + *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK; + entry->evt = 0; + queue_tail_inc(&eq_obj->q); + return true; +} + +static int event_handle(struct be_ctrl_info *ctrl, + struct be_eq_obj *eq_obj) +{ + u16 rid = 0, num = 0; + + while (event_get(eq_obj, &rid)) + num++; + + /* We can see an interrupt and no event */ + be_eq_notify(ctrl, eq_obj->q.id, true, true, num); + if (num) + napi_schedule(&eq_obj->napi); + + return num; +} + +static irqreturn_t be_intx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + struct be_ctrl_info *ctrl = &adapter->ctrl; + int rx, tx; + + tx = event_handle(ctrl, &adapter->tx_eq); + rx = event_handle(ctrl, &adapter->rx_eq); + + if (rx || tx) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static irqreturn_t be_msix_rx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + + event_handle(&adapter->ctrl, &adapter->rx_eq); + + return IRQ_HANDLED; +} + +static irqreturn_t be_msix_tx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + + event_handle(&adapter->ctrl, &adapter->tx_eq); + + return IRQ_HANDLED; +} + +static inline bool do_lro(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); + int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); + + if (err) + drvr_stats(adapter)->be_rxcp_err++; + + return (!tcp_frame || err || (adapter->max_rx_coal <= 1)) ? + false : true; +} + +int be_poll_rx(struct napi_struct *napi, int budget) +{ + struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(rx_eq, struct be_adapter, rx_eq); + struct be_queue_info *rx_cq = &adapter->rx_obj.cq; + struct be_eth_rx_compl *rxcp; + u32 work_done; + + for (work_done = 0; work_done < budget; work_done++) { + rxcp = be_rx_compl_get(adapter); + if (!rxcp) + break; + + if (do_lro(adapter, rxcp)) + be_rx_compl_process_lro(adapter, rxcp); + else + be_rx_compl_process(adapter, rxcp); + } + + lro_flush_all(&adapter->rx_obj.lro_mgr); + + /* Refill the queue */ + if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM) + be_post_rx_frags(adapter); + + /* All consumed */ + if (work_done < budget) { + napi_complete(napi); + be_cq_notify(&adapter->ctrl, rx_cq->id, true, work_done); + } else { + /* More to be consumed; continue with interrupts disabled */ + be_cq_notify(&adapter->ctrl, rx_cq->id, false, work_done); + } + return work_done; +} + +/* For TX we don't honour budget; consume everything */ +int be_poll_tx(struct napi_struct *napi, int budget) +{ + struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(tx_eq, struct be_adapter, tx_eq); + struct be_tx_obj *tx_obj = &adapter->tx_obj; + struct be_queue_info *tx_cq = &tx_obj->cq; + struct be_queue_info *txq = &tx_obj->q; + struct be_eth_tx_compl *txcp; + u32 num_cmpl = 0; + u16 end_idx; + + while ((txcp = be_tx_compl_get(adapter))) { + end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, + wrb_index, txcp); + be_tx_compl_process(adapter, end_idx); + num_cmpl++; + } + + /* As Tx wrbs have been freed up, wake up netdev queue if + * it was stopped due to lack of tx wrbs. + */ + if (netif_queue_stopped(adapter->netdev) && + atomic_read(&txq->used) < txq->len / 2) { + netif_wake_queue(adapter->netdev); + } + + napi_complete(napi); + + be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); + + drvr_stats(adapter)->be_tx_events++; + drvr_stats(adapter)->be_tx_compl += num_cmpl; + + return 1; +} + +static void be_worker(struct work_struct *work) +{ + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + int status; + + /* Check link */ + be_link_status_update(adapter); + + /* Get Stats */ + status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); + if (!status) + netdev_stats_update(adapter); + + /* Set EQ delay */ + be_rx_eqd_update(adapter); + + if (adapter->rx_post_starved) { + adapter->rx_post_starved = false; + be_post_rx_frags(adapter); + } + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} + +static void be_msix_enable(struct be_adapter *adapter) +{ + int i, status; + + for (i = 0; i < BE_NUM_MSIX_VECTORS; i++) + adapter->msix_entries[i].entry = i; + + status = pci_enable_msix(adapter->pdev, adapter->msix_entries, + BE_NUM_MSIX_VECTORS); + if (status == 0) + adapter->msix_enabled = true; + return; +} + +static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id) +{ + return adapter->msix_entries[eq_id - + 8 * adapter->ctrl.pci_func].vector; +} + +static int be_msix_register(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + int status, vec; + + sprintf(tx_eq->desc, "%s-tx", netdev->name); + vec = be_msix_vec_get(adapter, tx_eq->q.id); + status = request_irq(vec, be_msix_tx, 0, tx_eq->desc, adapter); + if (status) + goto err; + + sprintf(rx_eq->desc, "%s-rx", netdev->name); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + status = request_irq(vec, be_msix_rx, 0, rx_eq->desc, adapter); + if (status) { /* Free TX IRQ */ + vec = be_msix_vec_get(adapter, tx_eq->q.id); + free_irq(vec, adapter); + goto err; + } + return 0; +err: + dev_warn(&adapter->pdev->dev, + "MSIX Request IRQ failed - err %d\n", status); + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + return status; +} + +static int be_irq_register(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int status; + + if (adapter->msix_enabled) { + status = be_msix_register(adapter); + if (status == 0) + goto done; + } + + /* INTx */ + netdev->irq = adapter->pdev->irq; + status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name, + adapter); + if (status) { + dev_err(&adapter->pdev->dev, + "INTx request IRQ failed - err %d\n", status); + return status; + } +done: + adapter->isr_registered = true; + return 0; +} + +static void be_irq_unregister(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int vec; + + if (!adapter->isr_registered) + return; + + /* INTx */ + if (!adapter->msix_enabled) { + free_irq(netdev->irq, adapter); + goto done; + } + + /* MSIx */ + vec = be_msix_vec_get(adapter, adapter->tx_eq.q.id); + free_irq(vec, adapter); + vec = be_msix_vec_get(adapter, adapter->rx_eq.q.id); + free_irq(vec, adapter); +done: + adapter->isr_registered = false; + return; +} + +static int be_open(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + u32 if_flags; + int status; + + if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS | + BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_PASS_L3L4_ERRORS; + status = be_cmd_if_create(ctrl, if_flags, netdev->dev_addr, + false/* pmac_invalid */, &adapter->if_handle, + &adapter->pmac_id); + if (status != 0) + goto do_none; + + be_vid_config(netdev); + + status = be_cmd_set_flow_control(ctrl, true, true); + if (status != 0) + goto if_destroy; + + status = be_tx_queues_create(adapter); + if (status != 0) + goto if_destroy; + + status = be_rx_queues_create(adapter); + if (status != 0) + goto tx_qs_destroy; + + /* First time posting */ + be_post_rx_frags(adapter); + + napi_enable(&rx_eq->napi); + napi_enable(&tx_eq->napi); + + be_irq_register(adapter); + + be_intr_set(ctrl, true); + + /* The evt queues are created in the unarmed state; arm them */ + be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); + + /* The compl queues are created in the unarmed state; arm them */ + be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); + be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0); + + be_link_status_update(adapter); + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + +tx_qs_destroy: + be_tx_queues_destroy(adapter); +if_destroy: + be_cmd_if_destroy(ctrl, adapter->if_handle); +do_none: + return status; +} + +static int be_close(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + int vec; + + cancel_delayed_work(&adapter->work); + + netif_stop_queue(netdev); + netif_carrier_off(netdev); + adapter->link.speed = PHY_LINK_SPEED_ZERO; + + be_intr_set(ctrl, false); + + if (adapter->msix_enabled) { + vec = be_msix_vec_get(adapter, tx_eq->q.id); + synchronize_irq(vec); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + synchronize_irq(vec); + } else { + synchronize_irq(netdev->irq); + } + be_irq_unregister(adapter); + + napi_disable(&rx_eq->napi); + napi_disable(&tx_eq->napi); + + be_rx_queues_destroy(adapter); + be_tx_queues_destroy(adapter); + + be_cmd_if_destroy(ctrl, adapter->if_handle); + return 0; +} + +static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, + void **ip_hdr, void **tcpudp_hdr, + u64 *hdr_flags, void *priv) +{ + struct ethhdr *eh; + struct vlan_ethhdr *veh; + struct iphdr *iph; + u8 *va = page_address(frag->page) + frag->page_offset; + unsigned long ll_hlen; + + prefetch(va); + eh = (struct ethhdr *)va; + *mac_hdr = eh; + ll_hlen = ETH_HLEN; + if (eh->h_proto != htons(ETH_P_IP)) { + if (eh->h_proto == htons(ETH_P_8021Q)) { + veh = (struct vlan_ethhdr *)va; + if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) + return -1; + + ll_hlen += VLAN_HLEN; + } else { + return -1; + } + } + *hdr_flags = LRO_IPV4; + iph = (struct iphdr *)(va + ll_hlen); + *ip_hdr = iph; + if (iph->protocol != IPPROTO_TCP) + return -1; + *hdr_flags |= LRO_TCP; + *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); + + return 0; +} + +static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev) +{ + struct net_lro_mgr *lro_mgr; + + lro_mgr = &adapter->rx_obj.lro_mgr; + lro_mgr->dev = netdev; + lro_mgr->features = LRO_F_NAPI; + lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; + lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; + lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; + lro_mgr->lro_arr = adapter->rx_obj.lro_desc; + lro_mgr->get_frag_header = be_get_frag_header; + lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME; +} + +static struct net_device_ops be_netdev_ops = { + .ndo_open = be_open, + .ndo_stop = be_close, + .ndo_start_xmit = be_xmit, + .ndo_get_stats = be_get_stats, + .ndo_set_rx_mode = be_set_multicast_list, + .ndo_set_mac_address = be_mac_addr_set, + .ndo_change_mtu = be_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_vlan_rx_register = be_vlan_register, + .ndo_vlan_rx_add_vid = be_vlan_add_vid, + .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, +}; + +static void be_netdev_init(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(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; + + netdev->flags |= IFF_MULTICAST; + + BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); + + SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); + + be_lro_init(adapter, netdev); + + netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, + BE_NAPI_WEIGHT); + netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx, + BE_NAPI_WEIGHT); + + netif_carrier_off(netdev); + netif_stop_queue(netdev); +} + +static void be_unmap_pci_bars(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + if (ctrl->csr) + iounmap(ctrl->csr); + if (ctrl->db) + iounmap(ctrl->db); + if (ctrl->pcicfg) + iounmap(ctrl->pcicfg); +} + +static int be_map_pci_bars(struct be_adapter *adapter) +{ + u8 __iomem *addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), + pci_resource_len(adapter->pdev, 2)); + if (addr == NULL) + return -ENOMEM; + adapter->ctrl.csr = addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 4), + 128 * 1024); + if (addr == NULL) + goto pci_map_err; + adapter->ctrl.db = addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), + pci_resource_len(adapter->pdev, 1)); + if (addr == NULL) + goto pci_map_err; + adapter->ctrl.pcicfg = addr; + + return 0; +pci_map_err: + be_unmap_pci_bars(adapter); + return -ENOMEM; +} + + +static void be_ctrl_cleanup(struct be_adapter *adapter) +{ + struct be_dma_mem *mem = &adapter->ctrl.mbox_mem_alloced; + + be_unmap_pci_bars(adapter); + + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); +} + +/* Initialize the mbox required to send cmds to BE */ +static int be_ctrl_init(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced; + struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem; + int status; + u32 val; + + status = be_map_pci_bars(adapter); + if (status) + return status; + + mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; + mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev, + mbox_mem_alloc->size, &mbox_mem_alloc->dma); + if (!mbox_mem_alloc->va) { + be_unmap_pci_bars(adapter); + return -1; + } + mbox_mem_align->size = sizeof(struct be_mcc_mailbox); + mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); + mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); + memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); + spin_lock_init(&ctrl->cmd_lock); + + val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); + ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & + MEMBAR_CTRL_INT_CTRL_PFUNC_MASK; + return 0; +} + +static void be_stats_cleanup(struct be_adapter *adapter) +{ + struct be_stats_obj *stats = &adapter->stats; + struct be_dma_mem *cmd = &stats->cmd; + + if (cmd->va) + pci_free_consistent(adapter->pdev, cmd->size, + cmd->va, cmd->dma); +} + +static int be_stats_init(struct be_adapter *adapter) +{ + struct be_stats_obj *stats = &adapter->stats; + struct be_dma_mem *cmd = &stats->cmd; + + cmd->size = sizeof(struct be_cmd_req_get_stats); + cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); + if (cmd->va == NULL) + return -1; + return 0; +} + +static void __devexit be_remove(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + if (!adapter) + return; + + unregister_netdev(adapter->netdev); + + be_stats_cleanup(adapter); + + be_ctrl_cleanup(adapter); + + if (adapter->msix_enabled) { + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + } + + pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); + pci_disable_device(pdev); + + free_netdev(adapter->netdev); +} + +static int be_hw_up(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + int status; + + status = be_cmd_POST(ctrl); + if (status) + return status; + + status = be_cmd_get_fw_ver(ctrl, adapter->fw_ver); + if (status) + return status; + + status = be_cmd_query_fw_cfg(ctrl, &adapter->port_num); + return status; +} + +static int __devinit be_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) +{ + int status = 0; + struct be_adapter *adapter; + struct net_device *netdev; + struct be_ctrl_info *ctrl; + u8 mac[ETH_ALEN]; + + status = pci_enable_device(pdev); + if (status) + goto do_none; + + status = pci_request_regions(pdev, DRV_NAME); + if (status) + goto disable_dev; + pci_set_master(pdev); + + netdev = alloc_etherdev(sizeof(struct be_adapter)); + if (netdev == NULL) { + status = -ENOMEM; + goto rel_reg; + } + adapter = netdev_priv(netdev); + adapter->pdev = pdev; + pci_set_drvdata(pdev, adapter); + adapter->netdev = netdev; + + be_msix_enable(adapter); + + status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (!status) { + netdev->features |= NETIF_F_HIGHDMA; + } else { + status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (status) { + dev_err(&pdev->dev, "Could not set PCI DMA Mask\n"); + goto free_netdev; + } + } + + ctrl = &adapter->ctrl; + status = be_ctrl_init(adapter); + if (status) + goto free_netdev; + + status = be_stats_init(adapter); + if (status) + goto ctrl_clean; + + status = be_hw_up(adapter); + if (status) + goto stats_clean; + + status = be_cmd_mac_addr_query(ctrl, mac, MAC_ADDRESS_TYPE_NETWORK, + true /* permanent */, 0); + if (status) + goto stats_clean; + memcpy(netdev->dev_addr, mac, ETH_ALEN); + + INIT_DELAYED_WORK(&adapter->work, be_worker); + be_netdev_init(netdev); + SET_NETDEV_DEV(netdev, &adapter->pdev->dev); + + status = register_netdev(netdev); + if (status != 0) + goto stats_clean; + + dev_info(&pdev->dev, BE_NAME " port %d\n", adapter->port_num); + return 0; + +stats_clean: + be_stats_cleanup(adapter); +ctrl_clean: + be_ctrl_cleanup(adapter); +free_netdev: + free_netdev(adapter->netdev); +rel_reg: + pci_release_regions(pdev); +disable_dev: + pci_disable_device(pdev); +do_none: + dev_warn(&pdev->dev, BE_NAME " initialization failed\n"); + return status; +} + +static int be_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + if (netif_running(netdev)) { + rtnl_lock(); + be_close(netdev); + rtnl_unlock(); + } + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int be_resume(struct pci_dev *pdev) +{ + int status = 0; + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + + status = pci_enable_device(pdev); + if (status) + return status; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + if (netif_running(netdev)) { + rtnl_lock(); + be_open(netdev); + rtnl_unlock(); + } + netif_device_attach(netdev); + return 0; +} + +static struct pci_driver be_driver = { + .name = DRV_NAME, + .id_table = be_dev_ids, + .probe = be_probe, + .remove = be_remove, + .suspend = be_suspend, + .resume = be_resume +}; + +static int __init be_init_module(void) +{ + if (rx_frag_size != 8192 && rx_frag_size != 4096 + && rx_frag_size != 2048) { + printk(KERN_WARNING DRV_NAME + " : Module param rx_frag_size must be 2048/4096/8192." + " Using 2048\n"); + rx_frag_size = 2048; + } + /* Ensure rx_frag_size is aligned to chache line */ + if (SKB_DATA_ALIGN(rx_frag_size) != rx_frag_size) { + printk(KERN_WARNING DRV_NAME + " : Bad module param rx_frag_size. Using 2048\n"); + rx_frag_size = 2048; + } + + return pci_register_driver(&be_driver); +} +module_init(be_init_module); + +static void __exit be_exit_module(void) +{ + pci_unregister_driver(&be_driver); +} +module_exit(be_exit_module); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 6500b7c4739..6b6530ffdf1 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.9.2" -#define DRV_MODULE_RELDATE "Feb 11, 2009" +#define DRV_MODULE_VERSION "1.9.3" +#define DRV_MODULE_RELDATE "March 17, 2009" #define RUN_AT(x) (jiffies + (x)) @@ -5843,9 +5843,6 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { msix_ent[i].entry = i; msix_ent[i].vector = 0; - - snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); - bp->irq_tbl[i].handler = bnx2_msi_1shot; } rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC); @@ -5854,8 +5851,11 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) bp->irq_nvecs = msix_vecs; bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI; - for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) + for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { bp->irq_tbl[i].vector = msix_ent[i].vector; + snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); + bp->irq_tbl[i].handler = bnx2_msi_1shot; + } } static void diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 15a5cf0f676..3cf2b92eef3 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -152,7 +152,7 @@ struct sw_rx_page { #define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT) #define SGE_PAGE_SIZE PAGE_SIZE #define SGE_PAGE_SHIFT PAGE_SHIFT -#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr) +#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))addr) #define BCM_RX_ETH_PAYLOAD_ALIGN 64 diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index a6c0b3abba2..3b0c2499ef1 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -150,7 +150,6 @@ static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) { -#ifdef USE_DMAE int offset = 0; if (bp->dmae_ready) { @@ -164,9 +163,6 @@ static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) addr + offset, len); } else bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -#else - bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -#endif } static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d3e7775a9cc..2e346a5e98c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,7 +57,7 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.26" +#define DRV_MODULE_VERSION "1.45.27" #define DRV_MODULE_RELDATE "2009/01/26" #define BNX2X_BC_VER 0x040200 @@ -4035,10 +4035,10 @@ static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id) { int port = BP_PORT(bp); - bnx2x_init_fill(bp, BAR_USTRORM_INTMEM + + bnx2x_init_fill(bp, USTORM_INTMEM_ADDR + USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0, sizeof(struct ustorm_status_block)/4); - bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM + + bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR + CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0, sizeof(struct cstorm_status_block)/4); } @@ -4092,18 +4092,18 @@ static void bnx2x_zero_def_sb(struct bnx2x *bp) { int func = BP_FUNC(bp); - bnx2x_init_fill(bp, BAR_USTRORM_INTMEM + + bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR + + TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, + sizeof(struct tstorm_def_status_block)/4); + bnx2x_init_fill(bp, USTORM_INTMEM_ADDR + USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct ustorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM + + bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR + CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct cstorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_XSTRORM_INTMEM + + bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR + XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct xstorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_TSTRORM_INTMEM + - TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, - sizeof(struct tstorm_def_status_block)/4); } static void bnx2x_init_def_sb(struct bnx2x *bp, @@ -4518,7 +4518,8 @@ static void bnx2x_init_context(struct bnx2x *bp) (USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA | USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING); context->ustorm_st_context.common.sge_buff_size = - (u16)(BCM_PAGE_SIZE*PAGES_PER_SGE); + (u16)min((u32)SGE_PAGE_SIZE*PAGES_PER_SGE, + (u32)0xffff); context->ustorm_st_context.common.sge_page_base_hi = U64_HI(fp->rx_sge_mapping); context->ustorm_st_context.common.sge_page_base_lo = diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 9fb388388fb..3d76686dcec 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3537,11 +3537,26 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave } break; case NETDEV_CHANGE: - /* - * TODO: is this what we get if somebody - * sets up a hierarchical bond, then rmmod's - * one of the slave bonding devices? - */ + if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) { + struct slave *slave; + + slave = bond_get_slave_by_dev(bond, slave_dev); + if (slave) { + u16 old_speed = slave->speed; + u16 old_duplex = slave->duplex; + + bond_update_speed_duplex(slave); + + if (bond_is_lb(bond)) + break; + + if (old_speed != slave->speed) + bond_3ad_adapter_speed_changed(slave); + if (old_duplex != slave->duplex) + bond_3ad_adapter_duplex_changed(slave); + } + } + break; case NETDEV_DOWN: /* @@ -4113,7 +4128,7 @@ static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms) const struct net_device_ops *slave_ops = slave->dev->netdev_ops; if (slave_ops->ndo_neigh_setup) - return slave_ops->ndo_neigh_setup(dev, parms); + return slave_ops->ndo_neigh_setup(slave->dev, parms); } return 0; } diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index bcf92917bbf..254ec62b5f5 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -930,13 +930,15 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; board_info_t *db = netdev_priv(dev); int int_status; + unsigned long flags; u8 reg_save; dm9000_dbg(db, 3, "entering %s\n", __func__); /* A real interrupt coming */ - spin_lock(&db->lock); + /* holders of db->lock must always block IRQs */ + spin_lock_irqsave(&db->lock, flags); /* Save previous register address */ reg_save = readb(db->io_addr); @@ -972,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) /* Restore previous register address */ writeb(reg_save, db->io_addr); - spin_unlock(&db->lock); + spin_unlock_irqrestore(&db->lock, flags); return IRQ_HANDLED; } diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c new file mode 100644 index 00000000000..1b4063222a8 --- /dev/null +++ b/drivers/net/dnet.c @@ -0,0 +1,994 @@ +/* + * Dave DNET Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. <www.dave.eu> + * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/version.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/phy.h> +#include <linux/platform_device.h> + +#include "dnet.h" + +#undef DEBUG + +/* function for reading internal MAC register */ +u16 dnet_readw_mac(struct dnet *bp, u16 reg) +{ + u16 data_read; + + /* issue a read */ + dnet_writel(bp, reg, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before reading the data */ + ndelay(500); + + /* read data read from the MAC register */ + data_read = dnet_readl(bp, MACREG_DATA); + + /* all done */ + return data_read; +} + +/* function for writing internal MAC register */ +void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val) +{ + /* load data to write */ + dnet_writel(bp, val, MACREG_DATA); + + /* issue a write */ + dnet_writel(bp, reg | DNET_INTERNAL_WRITE, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before exiting */ + ndelay(500); +} + +static void __dnet_set_hwaddr(struct dnet *bp) +{ + u16 tmp; + + tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr)); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2))); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4))); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); +} + +static void __devinit dnet_get_hwaddr(struct dnet *bp) +{ + u16 tmp; + u8 addr[6]; + + /* + * from MAC docs: + * "Note that the MAC address is stored in the registers in Hexadecimal + * form. For example, to set the MAC Address to: AC-DE-48-00-00-80 + * would require writing 0xAC (octet 0) to address 0x0B (high byte of + * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of + * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of + * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of + * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of + * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of + * Mac_addr[15:0]). + */ + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG); + *((u16 *) addr) = be16_to_cpu(tmp); + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG); + *((u16 *) (addr + 2)) = be16_to_cpu(tmp); + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG); + *((u16 *) (addr + 4)) = be16_to_cpu(tmp); + + if (is_valid_ether_addr(addr)) + memcpy(bp->dev->dev_addr, addr, sizeof(addr)); +} + +static int dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct dnet *bp = bus->priv; + u16 value; + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + /* only 5 bits allowed for phy-addr and reg_offset */ + mii_id &= 0x1f; + regnum &= 0x1f; + + /* prepare reg_value for a read */ + value = (mii_id << 8); + value |= regnum; + + /* write control word */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value); + + /* wait for end of transfer */ + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG); + + pr_debug("mdio_read %02x:%02x <- %04x\n", mii_id, regnum, value); + + return value; +} + +static int dnet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + u16 value) +{ + struct dnet *bp = bus->priv; + u16 tmp; + + pr_debug("mdio_write %02x:%02x <- %04x\n", mii_id, regnum, value); + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + /* prepare for a write operation */ + tmp = (1 << 13); + + /* only 5 bits allowed for phy-addr and reg_offset */ + mii_id &= 0x1f; + regnum &= 0x1f; + + /* only 16 bits on data */ + value &= 0xffff; + + /* prepare reg_value for a write */ + tmp |= (mii_id << 8); + tmp |= regnum; + + /* write data to write first */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG, value); + + /* write control word */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp); + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + return 0; +} + +static int dnet_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static void dnet_handle_link_change(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + unsigned long flags; + u32 mode_reg, ctl_reg; + + int status_change = 0; + + spin_lock_irqsave(&bp->lock, flags); + + mode_reg = dnet_readw_mac(bp, DNET_INTERNAL_MODE_REG); + ctl_reg = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (phydev->link) { + if (bp->duplex != phydev->duplex) { + if (phydev->duplex) + ctl_reg &= + ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP); + else + ctl_reg |= + DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP; + + bp->duplex = phydev->duplex; + status_change = 1; + } + + if (bp->speed != phydev->speed) { + status_change = 1; + switch (phydev->speed) { + case 1000: + mode_reg |= DNET_INTERNAL_MODE_GBITEN; + break; + case 100: + case 10: + mode_reg &= ~DNET_INTERNAL_MODE_GBITEN; + break; + default: + printk(KERN_WARNING + "%s: Ack! Speed (%d) is not " + "10/100/1000!\n", dev->name, + phydev->speed); + break; + } + bp->speed = phydev->speed; + } + } + + if (phydev->link != bp->link) { + if (phydev->link) { + mode_reg |= + (DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN); + } else { + mode_reg &= + ~(DNET_INTERNAL_MODE_RXEN | + DNET_INTERNAL_MODE_TXEN); + bp->speed = 0; + bp->duplex = -1; + } + bp->link = phydev->link; + + status_change = 1; + } + + if (status_change) { + dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg); + dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, mode_reg); + } + + spin_unlock_irqrestore(&bp->lock, flags); + + if (status_change) { + if (phydev->link) + printk(KERN_INFO "%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); + else + printk(KERN_INFO "%s: link down\n", dev->name); + } +} + +static int dnet_mii_probe(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = NULL; + int phy_addr; + + /* find the first phy */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + if (bp->mii_bus->phy_map[phy_addr]) { + phydev = bp->mii_bus->phy_map[phy_addr]; + break; + } + } + + if (!phydev) { + printk(KERN_ERR "%s: no PHY found\n", dev->name); + return -ENODEV; + } + + /* TODO : add pin_irq */ + + /* attach the mac to the phy */ + if (bp->capabilities & DNET_HAS_RMII) { + phydev = phy_connect(dev, dev_name(&phydev->dev), + &dnet_handle_link_change, 0, + PHY_INTERFACE_MODE_RMII); + } else { + phydev = phy_connect(dev, dev_name(&phydev->dev), + &dnet_handle_link_change, 0, + PHY_INTERFACE_MODE_MII); + } + + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + return PTR_ERR(phydev); + } + + /* mask with MAC supported features */ + if (bp->capabilities & DNET_HAS_GIGABIT) + phydev->supported &= PHY_GBIT_FEATURES; + else + phydev->supported &= PHY_BASIC_FEATURES; + + phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause; + + phydev->advertising = phydev->supported; + + bp->link = 0; + bp->speed = 0; + bp->duplex = -1; + bp->phy_dev = phydev; + + return 0; +} + +static int dnet_mii_init(struct dnet *bp) +{ + int err, i; + + bp->mii_bus = mdiobus_alloc(); + if (bp->mii_bus == NULL) + return -ENOMEM; + + bp->mii_bus->name = "dnet_mii_bus"; + bp->mii_bus->read = &dnet_mdio_read; + bp->mii_bus->write = &dnet_mdio_write; + bp->mii_bus->reset = &dnet_mdio_reset; + + snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + + bp->mii_bus->priv = bp; + + bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!bp->mii_bus->irq) { + err = -ENOMEM; + goto err_out; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + bp->mii_bus->irq[i] = PHY_POLL; + + platform_set_drvdata(bp->dev, bp->mii_bus); + + if (mdiobus_register(bp->mii_bus)) { + err = -ENXIO; + goto err_out_free_mdio_irq; + } + + if (dnet_mii_probe(bp->dev) != 0) { + err = -ENXIO; + goto err_out_unregister_bus; + } + + return 0; + +err_out_unregister_bus: + mdiobus_unregister(bp->mii_bus); +err_out_free_mdio_irq: + kfree(bp->mii_bus->irq); +err_out: + mdiobus_free(bp->mii_bus); + return err; +} + +/* For Neptune board: LINK1000 as Link LED and TX as activity LED */ +int dnet_phy_marvell_fixup(struct phy_device *phydev) +{ + return phy_write(phydev, 0x18, 0x4148); +} + +static void dnet_update_stats(struct dnet *bp) +{ + u32 __iomem *reg = bp->regs + DNET_RX_PKT_IGNR_CNT; + u32 *p = &bp->hw_stats.rx_pkt_ignr; + u32 *end = &bp->hw_stats.rx_byte + 1; + + WARN_ON((unsigned long)(end - p - 1) != + (DNET_RX_BYTE_CNT - DNET_RX_PKT_IGNR_CNT) / 4); + + for (; p < end; p++, reg++) + *p += readl(reg); + + reg = bp->regs + DNET_TX_UNICAST_CNT; + p = &bp->hw_stats.tx_unicast; + end = &bp->hw_stats.tx_byte + 1; + + WARN_ON((unsigned long)(end - p - 1) != + (DNET_TX_BYTE_CNT - DNET_TX_UNICAST_CNT) / 4); + + for (; p < end; p++, reg++) + *p += readl(reg); +} + +static int dnet_poll(struct napi_struct *napi, int budget) +{ + struct dnet *bp = container_of(napi, struct dnet, napi); + struct net_device *dev = bp->dev; + int npackets = 0; + unsigned int pkt_len; + struct sk_buff *skb; + unsigned int *data_ptr; + u32 int_enable; + u32 cmd_word; + int i; + + while (npackets < budget) { + /* + * break out of while loop if there are no more + * packets waiting + */ + if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { + napi_complete(napi); + int_enable = dnet_readl(bp, INTR_ENB); + int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + return 0; + } + + cmd_word = dnet_readl(bp, RX_LEN_FIFO); + pkt_len = cmd_word & 0xFFFF; + + if (cmd_word & 0xDF180000) + printk(KERN_ERR "%s packet receive error %x\n", + __func__, cmd_word); + + skb = dev_alloc_skb(pkt_len + 5); + if (skb != NULL) { + /* Align IP on 16 byte boundaries */ + skb_reserve(skb, 2); + /* + * 'skb_put()' points to the start of sk_buff + * data area. + */ + data_ptr = (unsigned int *)skb_put(skb, pkt_len); + for (i = 0; i < (pkt_len + 3) >> 2; i++) + *data_ptr++ = dnet_readl(bp, RX_DATA_FIFO); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + npackets++; + } else + printk(KERN_NOTICE + "%s: No memory to allocate a sk_buff of " + "size %u.\n", dev->name, pkt_len); + } + + budget -= npackets; + + if (npackets < budget) { + /* We processed all packets available. Tell NAPI it can + * stop polling then re-enable rx interrupts */ + napi_complete(napi); + int_enable = dnet_readl(bp, INTR_ENB); + int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + return 0; + } + + /* There are still packets waiting */ + return 1; +} + +static irqreturn_t dnet_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct dnet *bp = netdev_priv(dev); + u32 int_src, int_enable, int_current; + unsigned long flags; + unsigned int handled = 0; + + spin_lock_irqsave(&bp->lock, flags); + + /* read and clear the DNET irq (clear on read) */ + int_src = dnet_readl(bp, INTR_SRC); + int_enable = dnet_readl(bp, INTR_ENB); + int_current = int_src & int_enable; + + /* restart the queue if we had stopped it for TX fifo almost full */ + if (int_current & DNET_INTR_SRC_TX_FIFOAE) { + int_enable = dnet_readl(bp, INTR_ENB); + int_enable &= ~DNET_INTR_ENB_TX_FIFOAE; + dnet_writel(bp, int_enable, INTR_ENB); + netif_wake_queue(dev); + handled = 1; + } + + /* RX FIFO error checking */ + if (int_current & + (DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) { + printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__, + dnet_readl(bp, RX_STATUS), int_current); + /* we can only flush the RX FIFOs */ + dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL); + ndelay(500); + dnet_writel(bp, 0, SYS_CTL); + handled = 1; + } + + /* TX FIFO error checking */ + if (int_current & + (DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) { + printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__, + dnet_readl(bp, TX_STATUS), int_current); + /* we can only flush the TX FIFOs */ + dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL); + ndelay(500); + dnet_writel(bp, 0, SYS_CTL); + handled = 1; + } + + if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { + if (napi_schedule_prep(&bp->napi)) { + /* + * There's no point taking any more interrupts + * until we have processed the buffers + */ + /* Disable Rx interrupts and schedule NAPI poll */ + int_enable = dnet_readl(bp, INTR_ENB); + int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + __napi_schedule(&bp->napi); + } + handled = 1; + } + + if (!handled) + pr_debug("%s: irq %x remains\n", __func__, int_current); + + spin_unlock_irqrestore(&bp->lock, flags); + + return IRQ_RETVAL(handled); +} + +#ifdef DEBUG +static inline void dnet_print_skb(struct sk_buff *skb) +{ + int k; + printk(KERN_DEBUG PFX "data:"); + for (k = 0; k < skb->len; k++) + printk(" %02x", (unsigned int)skb->data[k]); + printk("\n"); +} +#else +#define dnet_print_skb(skb) do {} while (0) +#endif + +static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + + struct dnet *bp = netdev_priv(dev); + u32 tx_status, irq_enable; + unsigned int len, i, tx_cmd, wrsz; + unsigned long flags; + unsigned int *bufp; + + tx_status = dnet_readl(bp, TX_STATUS); + + pr_debug("start_xmit: len %u head %p data %p\n", + skb->len, skb->head, skb->data); + dnet_print_skb(skb); + + /* frame size (words) */ + len = (skb->len + 3) >> 2; + + spin_lock_irqsave(&bp->lock, flags); + + tx_status = dnet_readl(bp, TX_STATUS); + + bufp = (unsigned int *)(((unsigned long) skb->data) & ~0x3UL); + wrsz = (u32) skb->len + 3; + wrsz += ((unsigned long) skb->data) & 0x3; + wrsz >>= 2; + tx_cmd = ((((unsigned long)(skb->data)) & 0x03) << 16) | (u32) skb->len; + + /* check if there is enough room for the current frame */ + if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { + for (i = 0; i < wrsz; i++) + dnet_writel(bp, *bufp++, TX_DATA_FIFO); + + /* + * inform MAC that a packet's written and ready to be + * shipped out + */ + dnet_writel(bp, tx_cmd, TX_LEN_FIFO); + } + + if (dnet_readl(bp, TX_FIFO_WCNT) > DNET_FIFO_TX_DATA_AF_TH) { + netif_stop_queue(dev); + tx_status = dnet_readl(bp, INTR_SRC); + irq_enable = dnet_readl(bp, INTR_ENB); + irq_enable |= DNET_INTR_ENB_TX_FIFOAE; + dnet_writel(bp, irq_enable, INTR_ENB); + } + + /* free the buffer */ + dev_kfree_skb(skb); + + spin_unlock_irqrestore(&bp->lock, flags); + + dev->trans_start = jiffies; + + return 0; +} + +static void dnet_reset_hw(struct dnet *bp) +{ + /* put ts_mac in IDLE state i.e. disable rx/tx */ + dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN); + + /* + * RX FIFO almost full threshold: only cmd FIFO almost full is + * implemented for RX side + */ + dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH); + /* + * TX FIFO almost empty threshold: only data FIFO almost empty + * is implemented for TX side + */ + dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH); + + /* flush rx/tx fifos */ + dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH, + SYS_CTL); + msleep(1); + dnet_writel(bp, 0, SYS_CTL); +} + +static void dnet_init_hw(struct dnet *bp) +{ + u32 config; + + dnet_reset_hw(bp); + __dnet_set_hwaddr(bp); + + config = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (bp->dev->flags & IFF_PROMISC) + /* Copy All Frames */ + config |= DNET_INTERNAL_RXTX_CONTROL_ENPROMISC; + if (!(bp->dev->flags & IFF_BROADCAST)) + /* No BroadCast */ + config |= DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST; + + config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE | + DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST | + DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL | + DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS; + + dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, config); + + /* clear irq before enabling them */ + config = dnet_readl(bp, INTR_SRC); + + /* enable RX/TX interrupt, recv packet ready interrupt */ + dnet_writel(bp, DNET_INTR_ENB_GLOBAL_ENABLE | DNET_INTR_ENB_RX_SUMMARY | + DNET_INTR_ENB_TX_SUMMARY | DNET_INTR_ENB_RX_FIFOERR | + DNET_INTR_ENB_RX_ERROR | DNET_INTR_ENB_RX_FIFOFULL | + DNET_INTR_ENB_TX_FIFOFULL | DNET_INTR_ENB_TX_DISCFRM | + DNET_INTR_ENB_RX_PKTRDY, INTR_ENB); +} + +static int dnet_open(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + + /* if the phy is not yet register, retry later */ + if (!bp->phy_dev) + return -EAGAIN; + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + napi_enable(&bp->napi); + dnet_init_hw(bp); + + phy_start_aneg(bp->phy_dev); + + /* schedule a link state check */ + phy_start(bp->phy_dev); + + netif_start_queue(dev); + + return 0; +} + +static int dnet_close(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + + netif_stop_queue(dev); + napi_disable(&bp->napi); + + if (bp->phy_dev) + phy_stop(bp->phy_dev); + + dnet_reset_hw(bp); + netif_carrier_off(dev); + + return 0; +} + +static inline void dnet_print_pretty_hwstats(struct dnet_stats *hwstat) +{ + pr_debug("%s\n", __func__); + pr_debug("----------------------------- RX statistics " + "-------------------------------\n"); + pr_debug("RX_PKT_IGNR_CNT %-8x\n", hwstat->rx_pkt_ignr); + pr_debug("RX_LEN_CHK_ERR_CNT %-8x\n", hwstat->rx_len_chk_err); + pr_debug("RX_LNG_FRM_CNT %-8x\n", hwstat->rx_lng_frm); + pr_debug("RX_SHRT_FRM_CNT %-8x\n", hwstat->rx_shrt_frm); + pr_debug("RX_IPG_VIOL_CNT %-8x\n", hwstat->rx_ipg_viol); + pr_debug("RX_CRC_ERR_CNT %-8x\n", hwstat->rx_crc_err); + pr_debug("RX_OK_PKT_CNT %-8x\n", hwstat->rx_ok_pkt); + pr_debug("RX_CTL_FRM_CNT %-8x\n", hwstat->rx_ctl_frm); + pr_debug("RX_PAUSE_FRM_CNT %-8x\n", hwstat->rx_pause_frm); + pr_debug("RX_MULTICAST_CNT %-8x\n", hwstat->rx_multicast); + pr_debug("RX_BROADCAST_CNT %-8x\n", hwstat->rx_broadcast); + pr_debug("RX_VLAN_TAG_CNT %-8x\n", hwstat->rx_vlan_tag); + pr_debug("RX_PRE_SHRINK_CNT %-8x\n", hwstat->rx_pre_shrink); + pr_debug("RX_DRIB_NIB_CNT %-8x\n", hwstat->rx_drib_nib); + pr_debug("RX_UNSUP_OPCD_CNT %-8x\n", hwstat->rx_unsup_opcd); + pr_debug("RX_BYTE_CNT %-8x\n", hwstat->rx_byte); + pr_debug("----------------------------- TX statistics " + "-------------------------------\n"); + pr_debug("TX_UNICAST_CNT %-8x\n", hwstat->tx_unicast); + pr_debug("TX_PAUSE_FRM_CNT %-8x\n", hwstat->tx_pause_frm); + pr_debug("TX_MULTICAST_CNT %-8x\n", hwstat->tx_multicast); + pr_debug("TX_BRDCAST_CNT %-8x\n", hwstat->tx_brdcast); + pr_debug("TX_VLAN_TAG_CNT %-8x\n", hwstat->tx_vlan_tag); + pr_debug("TX_BAD_FCS_CNT %-8x\n", hwstat->tx_bad_fcs); + pr_debug("TX_JUMBO_CNT %-8x\n", hwstat->tx_jumbo); + pr_debug("TX_BYTE_CNT %-8x\n", hwstat->tx_byte); +} + +static struct net_device_stats *dnet_get_stats(struct net_device *dev) +{ + + struct dnet *bp = netdev_priv(dev); + struct net_device_stats *nstat = &dev->stats; + struct dnet_stats *hwstat = &bp->hw_stats; + + /* read stats from hardware */ + dnet_update_stats(bp); + + /* Convert HW stats into netdevice stats */ + nstat->rx_errors = (hwstat->rx_len_chk_err + + hwstat->rx_lng_frm + hwstat->rx_shrt_frm + + /* ignore IGP violation error + hwstat->rx_ipg_viol + */ + hwstat->rx_crc_err + + hwstat->rx_pre_shrink + + hwstat->rx_drib_nib + hwstat->rx_unsup_opcd); + nstat->tx_errors = hwstat->tx_bad_fcs; + nstat->rx_length_errors = (hwstat->rx_len_chk_err + + hwstat->rx_lng_frm + + hwstat->rx_shrt_frm + hwstat->rx_pre_shrink); + nstat->rx_crc_errors = hwstat->rx_crc_err; + nstat->rx_frame_errors = hwstat->rx_pre_shrink + hwstat->rx_drib_nib; + nstat->rx_packets = hwstat->rx_ok_pkt; + nstat->tx_packets = (hwstat->tx_unicast + + hwstat->tx_multicast + hwstat->tx_brdcast); + nstat->rx_bytes = hwstat->rx_byte; + nstat->tx_bytes = hwstat->tx_byte; + nstat->multicast = hwstat->rx_multicast; + nstat->rx_missed_errors = hwstat->rx_pkt_ignr; + + dnet_print_pretty_hwstats(hwstat); + + return nstat; +} + +static int dnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_gset(phydev, cmd); +} + +static int dnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_sset(phydev, cmd); +} + +static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!netif_running(dev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, if_mii(rq), cmd); +} + +static void dnet_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, "0"); +} + +static const struct ethtool_ops dnet_ethtool_ops = { + .get_settings = dnet_get_settings, + .set_settings = dnet_set_settings, + .get_drvinfo = dnet_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + +static const struct net_device_ops dnet_netdev_ops = { + .ndo_open = dnet_open, + .ndo_stop = dnet_close, + .ndo_get_stats = dnet_get_stats, + .ndo_start_xmit = dnet_start_xmit, + .ndo_do_ioctl = dnet_ioctl, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, +}; + +static int __devinit dnet_probe(struct platform_device *pdev) +{ + struct resource *res; + struct net_device *dev; + struct dnet *bp; + struct phy_device *phydev; + int err = -ENXIO; + unsigned int mem_base, mem_size, irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no mmio resource defined\n"); + goto err_out; + } + mem_base = res->start; + mem_size = resource_size(res); + irq = platform_get_irq(pdev, 0); + + if (!request_mem_region(mem_base, mem_size, DRV_NAME)) { + dev_err(&pdev->dev, "no memory region available\n"); + err = -EBUSY; + goto err_out; + } + + err = -ENOMEM; + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) { + dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); + goto err_out; + } + + /* TODO: Actually, we have some interesting features... */ + dev->features |= 0; + + bp = netdev_priv(dev); + bp->dev = dev; + + SET_NETDEV_DEV(dev, &pdev->dev); + + spin_lock_init(&bp->lock); + + bp->regs = ioremap(mem_base, mem_size); + if (!bp->regs) { + dev_err(&pdev->dev, "failed to map registers, aborting.\n"); + err = -ENOMEM; + goto err_out_free_dev; + } + + dev->irq = irq; + err = request_irq(dev->irq, dnet_interrupt, 0, DRV_NAME, dev); + if (err) { + dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", + irq, err); + goto err_out_iounmap; + } + + dev->netdev_ops = &dnet_netdev_ops; + netif_napi_add(dev, &bp->napi, dnet_poll, 64); + dev->ethtool_ops = &dnet_ethtool_ops; + + dev->base_addr = (unsigned long)bp->regs; + + bp->capabilities = dnet_readl(bp, VERCAPS) & DNET_CAPS_MASK; + + dnet_get_hwaddr(bp); + + if (!is_valid_ether_addr(dev->dev_addr)) { + /* choose a random ethernet address */ + random_ether_addr(dev->dev_addr); + __dnet_set_hwaddr(bp); + } + + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); + goto err_out_free_irq; + } + + /* register the PHY board fixup (for Marvell 88E1111) */ + err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0, + dnet_phy_marvell_fixup); + /* we can live without it, so just issue a warning */ + if (err) + dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n"); + + if (dnet_mii_init(bp) != 0) + goto err_out_unregister_netdev; + + dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n", + bp->regs, mem_base, dev->irq, dev->dev_addr); + dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma \n", + (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ", + (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ", + (bp->capabilities & DNET_HAS_GIGABIT) ? "" : "no ", + (bp->capabilities & DNET_HAS_DMA) ? "" : "no "); + phydev = bp->phy_dev; + dev_info(&pdev->dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); + + return 0; + +err_out_unregister_netdev: + unregister_netdev(dev); +err_out_free_irq: + free_irq(dev->irq, dev); +err_out_iounmap: + iounmap(bp->regs); +err_out_free_dev: + free_netdev(dev); +err_out: + return err; +} + +static int __devexit dnet_remove(struct platform_device *pdev) +{ + + struct net_device *dev; + struct dnet *bp; + + dev = platform_get_drvdata(pdev); + + if (dev) { + bp = netdev_priv(dev); + if (bp->phy_dev) + phy_disconnect(bp->phy_dev); + mdiobus_unregister(bp->mii_bus); + kfree(bp->mii_bus->irq); + mdiobus_free(bp->mii_bus); + unregister_netdev(dev); + free_irq(dev->irq, dev); + iounmap(bp->regs); + free_netdev(dev); + } + + return 0; +} + +static struct platform_driver dnet_driver = { + .probe = dnet_probe, + .remove = __devexit_p(dnet_remove), + .driver = { + .name = "dnet", + }, +}; + +static int __init dnet_init(void) +{ + return platform_driver_register(&dnet_driver); +} + +static void __exit dnet_exit(void) +{ + platform_driver_unregister(&dnet_driver); +} + +module_init(dnet_init); +module_exit(dnet_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Dave DNET Ethernet driver"); +MODULE_AUTHOR("Ilya Yanok <yanok@emcraft.com>, " + "Matteo Vit <matteo.vit@dave.eu>"); diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h new file mode 100644 index 00000000000..37f5b30fa78 --- /dev/null +++ b/drivers/net/dnet.h @@ -0,0 +1,225 @@ +/* + * Dave DNET Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. <www.dave.eu> + * + * 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 _DNET_H +#define _DNET_H + +#define DRV_NAME "dnet" +#define DRV_VERSION "0.9.1" +#define PFX DRV_NAME ": " + +/* Register access macros */ +#define dnet_writel(port, value, reg) \ + writel((value), (port)->regs + DNET_##reg) +#define dnet_readl(port, reg) readl((port)->regs + DNET_##reg) + +/* ALL DNET FIFO REGISTERS */ +#define DNET_RX_LEN_FIFO 0x000 /* RX_LEN_FIFO */ +#define DNET_RX_DATA_FIFO 0x004 /* RX_DATA_FIFO */ +#define DNET_TX_LEN_FIFO 0x008 /* TX_LEN_FIFO */ +#define DNET_TX_DATA_FIFO 0x00C /* TX_DATA_FIFO */ + +/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */ +#define DNET_VERCAPS 0x100 /* VERCAPS */ +#define DNET_INTR_SRC 0x104 /* INTR_SRC */ +#define DNET_INTR_ENB 0x108 /* INTR_ENB */ +#define DNET_RX_STATUS 0x10C /* RX_STATUS */ +#define DNET_TX_STATUS 0x110 /* TX_STATUS */ +#define DNET_RX_FRAMES_CNT 0x114 /* RX_FRAMES_CNT */ +#define DNET_TX_FRAMES_CNT 0x118 /* TX_FRAMES_CNT */ +#define DNET_RX_FIFO_TH 0x11C /* RX_FIFO_TH */ +#define DNET_TX_FIFO_TH 0x120 /* TX_FIFO_TH */ +#define DNET_SYS_CTL 0x124 /* SYS_CTL */ +#define DNET_PAUSE_TMR 0x128 /* PAUSE_TMR */ +#define DNET_RX_FIFO_WCNT 0x12C /* RX_FIFO_WCNT */ +#define DNET_TX_FIFO_WCNT 0x130 /* TX_FIFO_WCNT */ + +/* ALL DNET MAC REGISTERS */ +#define DNET_MACREG_DATA 0x200 /* Mac-Reg Data */ +#define DNET_MACREG_ADDR 0x204 /* Mac-Reg Addr */ + +/* ALL DNET RX STATISTICS COUNTERS */ +#define DNET_RX_PKT_IGNR_CNT 0x300 +#define DNET_RX_LEN_CHK_ERR_CNT 0x304 +#define DNET_RX_LNG_FRM_CNT 0x308 +#define DNET_RX_SHRT_FRM_CNT 0x30C +#define DNET_RX_IPG_VIOL_CNT 0x310 +#define DNET_RX_CRC_ERR_CNT 0x314 +#define DNET_RX_OK_PKT_CNT 0x318 +#define DNET_RX_CTL_FRM_CNT 0x31C +#define DNET_RX_PAUSE_FRM_CNT 0x320 +#define DNET_RX_MULTICAST_CNT 0x324 +#define DNET_RX_BROADCAST_CNT 0x328 +#define DNET_RX_VLAN_TAG_CNT 0x32C +#define DNET_RX_PRE_SHRINK_CNT 0x330 +#define DNET_RX_DRIB_NIB_CNT 0x334 +#define DNET_RX_UNSUP_OPCD_CNT 0x338 +#define DNET_RX_BYTE_CNT 0x33C + +/* DNET TX STATISTICS COUNTERS */ +#define DNET_TX_UNICAST_CNT 0x400 +#define DNET_TX_PAUSE_FRM_CNT 0x404 +#define DNET_TX_MULTICAST_CNT 0x408 +#define DNET_TX_BRDCAST_CNT 0x40C +#define DNET_TX_VLAN_TAG_CNT 0x410 +#define DNET_TX_BAD_FCS_CNT 0x414 +#define DNET_TX_JUMBO_CNT 0x418 +#define DNET_TX_BYTE_CNT 0x41C + +/* SOME INTERNAL MAC-CORE REGISTER */ +#define DNET_INTERNAL_MODE_REG 0x0 +#define DNET_INTERNAL_RXTX_CONTROL_REG 0x2 +#define DNET_INTERNAL_MAX_PKT_SIZE_REG 0x4 +#define DNET_INTERNAL_IGP_REG 0x8 +#define DNET_INTERNAL_MAC_ADDR_0_REG 0xa +#define DNET_INTERNAL_MAC_ADDR_1_REG 0xc +#define DNET_INTERNAL_MAC_ADDR_2_REG 0xe +#define DNET_INTERNAL_TX_RX_STS_REG 0x12 +#define DNET_INTERNAL_GMII_MNG_CTL_REG 0x14 +#define DNET_INTERNAL_GMII_MNG_DAT_REG 0x16 + +#define DNET_INTERNAL_GMII_MNG_CMD_FIN (1 << 14) + +#define DNET_INTERNAL_WRITE (1 << 31) + +/* MAC-CORE REGISTER FIELDS */ + +/* MAC-CORE MODE REGISTER FIELDS */ +#define DNET_INTERNAL_MODE_GBITEN (1 << 0) +#define DNET_INTERNAL_MODE_FCEN (1 << 1) +#define DNET_INTERNAL_MODE_RXEN (1 << 2) +#define DNET_INTERNAL_MODE_TXEN (1 << 3) + +/* MAC-CORE RXTX CONTROL REGISTER FIELDS */ +#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME (1 << 8) +#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST (1 << 7) +#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST (1 << 4) +#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE (1 << 3) +#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS (1 << 2) +#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS (1 << 1) +#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC (1 << 0) +#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL (1 << 6) +#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP (1 << 5) + +/* SYSTEM CONTROL REGISTER FIELDS */ +#define DNET_SYS_CTL_IGNORENEXTPKT (1 << 0) +#define DNET_SYS_CTL_SENDPAUSE (1 << 2) +#define DNET_SYS_CTL_RXFIFOFLUSH (1 << 3) +#define DNET_SYS_CTL_TXFIFOFLUSH (1 << 4) + +/* TX STATUS REGISTER FIELDS */ +#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY (1 << 2) +#define DNET_TX_STATUS_FIFO_ALMOST_FULL (1 << 1) + +/* INTERRUPT SOURCE REGISTER FIELDS */ +#define DNET_INTR_SRC_TX_PKTSENT (1 << 0) +#define DNET_INTR_SRC_TX_FIFOAF (1 << 1) +#define DNET_INTR_SRC_TX_FIFOAE (1 << 2) +#define DNET_INTR_SRC_TX_DISCFRM (1 << 3) +#define DNET_INTR_SRC_TX_FIFOFULL (1 << 4) +#define DNET_INTR_SRC_RX_CMDFIFOAF (1 << 8) +#define DNET_INTR_SRC_RX_CMDFIFOFF (1 << 9) +#define DNET_INTR_SRC_RX_DATAFIFOFF (1 << 10) +#define DNET_INTR_SRC_TX_SUMMARY (1 << 16) +#define DNET_INTR_SRC_RX_SUMMARY (1 << 17) +#define DNET_INTR_SRC_PHY (1 << 19) + +/* INTERRUPT ENABLE REGISTER FIELDS */ +#define DNET_INTR_ENB_TX_PKTSENT (1 << 0) +#define DNET_INTR_ENB_TX_FIFOAF (1 << 1) +#define DNET_INTR_ENB_TX_FIFOAE (1 << 2) +#define DNET_INTR_ENB_TX_DISCFRM (1 << 3) +#define DNET_INTR_ENB_TX_FIFOFULL (1 << 4) +#define DNET_INTR_ENB_RX_PKTRDY (1 << 8) +#define DNET_INTR_ENB_RX_FIFOAF (1 << 9) +#define DNET_INTR_ENB_RX_FIFOERR (1 << 10) +#define DNET_INTR_ENB_RX_ERROR (1 << 11) +#define DNET_INTR_ENB_RX_FIFOFULL (1 << 12) +#define DNET_INTR_ENB_RX_FIFOAE (1 << 13) +#define DNET_INTR_ENB_TX_SUMMARY (1 << 16) +#define DNET_INTR_ENB_RX_SUMMARY (1 << 17) +#define DNET_INTR_ENB_GLOBAL_ENABLE (1 << 18) + +/* default values: + * almost empty = less than one full sized ethernet frame (no jumbo) inside + * the fifo almost full = can write less than one full sized ethernet frame + * (no jumbo) inside the fifo + */ +#define DNET_CFG_TX_FIFO_FULL_THRES 25 +#define DNET_CFG_RX_FIFO_FULL_THRES 20 + +/* + * Capabilities. Used by the driver to know the capabilities that the ethernet + * controller inside the FPGA have. + */ + +#define DNET_HAS_MDIO (1 << 0) +#define DNET_HAS_IRQ (1 << 1) +#define DNET_HAS_GIGABIT (1 << 2) +#define DNET_HAS_DMA (1 << 3) + +#define DNET_HAS_MII (1 << 4) /* or GMII */ +#define DNET_HAS_RMII (1 << 5) /* or RGMII */ + +#define DNET_CAPS_MASK 0xFFFF + +#define DNET_FIFO_SIZE 1024 /* 1K x 32 bit */ +#define DNET_FIFO_TX_DATA_AF_TH (DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */ +#define DNET_FIFO_TX_DATA_AE_TH 384 + +#define DNET_FIFO_RX_CMD_AF_TH (1 << 16) /* just one frame inside the FIFO */ + +/* + * Hardware-collected statistics. + */ +struct dnet_stats { + u32 rx_pkt_ignr; + u32 rx_len_chk_err; + u32 rx_lng_frm; + u32 rx_shrt_frm; + u32 rx_ipg_viol; + u32 rx_crc_err; + u32 rx_ok_pkt; + u32 rx_ctl_frm; + u32 rx_pause_frm; + u32 rx_multicast; + u32 rx_broadcast; + u32 rx_vlan_tag; + u32 rx_pre_shrink; + u32 rx_drib_nib; + u32 rx_unsup_opcd; + u32 rx_byte; + u32 tx_unicast; + u32 tx_pause_frm; + u32 tx_multicast; + u32 tx_brdcast; + u32 tx_vlan_tag; + u32 tx_bad_fcs; + u32 tx_jumbo; + u32 tx_byte; +}; + +struct dnet { + void __iomem *regs; + spinlock_t lock; + struct platform_device *pdev; + struct net_device *dev; + struct dnet_stats hw_stats; + unsigned int capabilities; /* read from FPGA */ + struct napi_struct napi; + + /* PHY stuff */ + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + unsigned int link; + unsigned int speed; + unsigned int duplex; +}; + +#endif /* _DNET_H */ diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 9b12a13a640..9831b3f408a 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1284,7 +1284,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->txlock, flags); /* check if there is space to queue this packet */ - if (nr_frags > priv->num_txbdfree) { + if ((nr_frags+1) > priv->num_txbdfree) { /* no space, stop the queue */ netif_stop_queue(dev); dev->stats.tx_fifo_errors++; diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 5e070f44663..0486cbe01ad 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -467,7 +467,7 @@ init_module(void) if (this_dev != 0) break; /* only autoprobe 1st one */ printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); } - dev = alloc_ei_netdev(); + dev = alloc_eip_netdev(); if (!dev) break; dev->irq = irq[this_dev]; diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 87a706694fb..6fd7aa61736 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2594,6 +2594,9 @@ static int __devinit emac_init_config(struct emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-460ex") || of_device_is_compatible(np, "ibm,emac-460gt")) dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX; + if (of_device_is_compatible(np, "ibm,emac-405ex") || + of_device_is_compatible(np, "ibm,emac-405exr")) + dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; } else if (of_device_is_compatible(np, "ibm,emac4")) { dev->features |= EMAC_FTR_EMAC4; if (of_device_is_compatible(np, "ibm,emac-440gx")) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a50db5398fa..9dd13ad12ce 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1023,11 +1023,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, struct net_device *netdev; struct igb_adapter *adapter; struct e1000_hw *hw; - struct pci_dev *us_dev; const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; unsigned long mmio_start, mmio_len; - int i, err, pci_using_dac, pos; - u16 eeprom_data = 0, state = 0; + int i, err, pci_using_dac; + u16 eeprom_data = 0; u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; int bars, need_ioport; @@ -1062,27 +1061,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, } } - /* 82575 requires that the pci-e link partner disable the L0s state */ - switch (pdev->device) { - case E1000_DEV_ID_82575EB_COPPER: - case E1000_DEV_ID_82575EB_FIBER_SERDES: - case E1000_DEV_ID_82575GB_QUAD_COPPER: - us_dev = pdev->bus->self; - pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP); - if (pos) { - pci_read_config_word(us_dev, pos + PCI_EXP_LNKCTL, - &state); - state &= ~PCIE_LINK_STATE_L0S; - pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, - state); - dev_info(&pdev->dev, - "Disabling ASPM L0s upstream switch port %s\n", - pci_name(us_dev)); - } - default: - break; - } - err = pci_request_selected_regions(pdev, bars, igb_driver_name); if (err) goto err_pci_reg; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d2f4d5f508b..5d364a96e35 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3973,6 +3973,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_stop = ixgbe_close, .ndo_start_xmit = ixgbe_xmit_frame, .ndo_get_stats = ixgbe_get_stats, + .ndo_set_rx_mode = ixgbe_set_rx_mode, .ndo_set_multicast_list = ixgbe_set_rx_mode, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ixgbe_set_mac, diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 08b34051c64..a6e1a35a13c 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -957,13 +957,14 @@ jme_process_receive(struct jme_adapter *jme, int limit) goto out_inc; i = atomic_read(&rxring->next_to_clean); - while (limit-- > 0) { + while (limit > 0) { rxdesc = rxring->desc; rxdesc += i; if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) || !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL)) goto out; + --limit; desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 13f11f402a9..b0bc3bc18e9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2030,11 +2030,6 @@ static void port_start(struct mv643xx_eth_private *mp) } /* - * Add configured unicast address to address filter table. - */ - mv643xx_eth_program_unicast_filter(mp->dev); - - /* * Receive all unmatched unicast, TCP, UDP, BPDU and broadcast * frames to RX queue #0, and include the pseudo-header when * calculating receive checksums. @@ -2047,6 +2042,11 @@ static void port_start(struct mv643xx_eth_private *mp) wrlp(mp, PORT_CONFIG_EXT, 0x00000000); /* + * Add configured unicast addresses to address filter table. + */ + mv643xx_eth_program_unicast_filter(mp->dev); + + /* * Enable the receive queues. */ for (i = 0; i < mp->rxq_count; i++) { diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f4dd9acb687..1ff066b2281 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1595,7 +1595,6 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) } -int netxen_is_flash_supported(struct netxen_adapter *adapter); int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); extern void netxen_change_ringparam(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 821cff68b3f..7fea7708810 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -706,28 +706,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) return rc; } -int netxen_is_flash_supported(struct netxen_adapter *adapter) -{ - const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 }; - int addr, val01, val02, i, j; - - /* if the flash size less than 4Mb, make huge war cry and die */ - for (j = 1; j < 4; j++) { - addr = j * NETXEN_NIC_WINDOW_MARGIN; - for (i = 0; i < ARRAY_SIZE(locs); i++) { - if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0 - && netxen_rom_fast_read(adapter, (addr + locs[i]), - &val02) == 0) { - if (val01 == val02) - return -1; - } else - return -1; - } - } - - return 0; -} - static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, int size, __le32 * buf) { diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9f33e442f40..c172b6e24a9 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -405,9 +405,6 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - if (netxen_is_flash_supported(adapter) != 0) - return -EIO; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0) return -EIO; @@ -588,7 +585,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; - mem_ptr0 = ioremap(mem_base, mem_len); + mem_ptr0 = pci_ioremap_bar(pdev, 0); + if (mem_ptr0 == NULL) { + dev_err(&pdev->dev, "failed to map PCI bar 0\n"); + return -EIO; + } + pci_len0 = mem_len; first_page_group_start = 0; first_page_group_end = 0; @@ -795,9 +797,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * See if the firmware gave us a virtual-physical port mapping. */ adapter->physical_port = adapter->portnum; - i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum)); - if (i != 0x55555555) - adapter->physical_port = i; + if (adapter->fw_major < 4) { + i = adapter->pci_read_normalize(adapter, + CRB_V2P(adapter->portnum)); + if (i != 0x55555555) + adapter->physical_port = i; + } adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index e5cb6b1f0eb..2404a838b1f 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -1035,7 +1035,8 @@ static int el3_rx(struct net_device *dev, int worklimit) DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) && - (--worklimit >= 0)) { + worklimit > 0) { + worklimit--; if (rx_status & 0x4000) { /* Error, update stats. */ short error = rx_status & 0x3800; dev->stats.rx_errors++; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 73ecc657999..1e01b8a6dbf 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -857,7 +857,8 @@ static int el3_rx(struct net_device *dev) DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) && - (--worklimit >= 0)) { + worklimit > 0) { + worklimit--; if (rx_status & 0x4000) { /* Error, update stats. */ short error = rx_status & 0x3800; dev->stats.rx_errors++; diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index e6fdce9206c..aff9c5fec73 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -927,6 +927,7 @@ struct ib_mac_iocb_rsp { u8 flags1; #define IB_MAC_IOCB_RSP_OI 0x01 /* Overide intr delay */ #define IB_MAC_IOCB_RSP_I 0x02 /* Disble Intr Generation */ +#define IB_MAC_CSUM_ERR_MASK 0x1c /* A mask to use for csum errs */ #define IB_MAC_IOCB_RSP_TE 0x04 /* Checksum error */ #define IB_MAC_IOCB_RSP_NU 0x08 /* No checksum rcvd */ #define IB_MAC_IOCB_RSP_IE 0x10 /* IPv4 checksum error */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8ea72dc60f7..91191f761fb 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1436,18 +1436,32 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); } - if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) { - QPRINTK(qdev, RX_STATUS, ERR, - "Bad checksum for this %s packet.\n", - ((ib_mac_rsp-> - flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP")); - skb->ip_summed = CHECKSUM_NONE; - } else if (qdev->rx_csum && - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) || - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && - !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) { - QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n"); - skb->ip_summed = CHECKSUM_UNNECESSARY; + + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * 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) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } } qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; @@ -1927,6 +1941,9 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring = &qdev->tx_ring[tx_ring_idx]; + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", @@ -2970,9 +2987,9 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) mask = value << 16; ql_write32(qdev, SYS, mask | value); - /* Set the default queue. */ - value = NIC_RCV_CFG_DFQ; - mask = NIC_RCV_CFG_DFQ_MASK; + /* Set the default queue, and VLAN behavior. */ + value = NIC_RCV_CFG_DFQ | NIC_RCV_CFG_RV; + mask = NIC_RCV_CFG_DFQ_MASK | (NIC_RCV_CFG_RV << 16); ql_write32(qdev, NIC_RCV_CFG, (mask | value)); /* Set the MPI interrupt to enabled. */ @@ -3149,6 +3166,11 @@ static int ql_adapter_down(struct ql_adapter *qdev) ql_tx_ring_clean(qdev); + /* Call netif_napi_del() from common point. + */ + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + spin_lock(&qdev->hw_lock); status = ql_adapter_reset(qdev); if (status) @@ -3853,7 +3875,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); - int err, i; + int err; netif_device_detach(ndev); @@ -3863,9 +3885,6 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } - for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) - netif_napi_del(&qdev->rx_ring[i].napi); - err = pci_save_state(pdev); if (err) return err; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0771eb6fc6e..43fedb9eced 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3253,13 +3253,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) opts1 |= FirstFrag; } else { len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - opts1 |= FirstFrag | LastFrag; tp->tx_skb[entry].skb = skb; } @@ -3297,7 +3290,6 @@ out: err_stop: netif_stop_queue(dev); ret = NETDEV_TX_BUSY; -err_update_stats: dev->stats.tx_dropped++; goto out; } diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 7f8e514eb5e..7b1882765a0 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -687,6 +687,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) { struct net_device *ndev = netdev; struct sh_eth_private *mdp = netdev_priv(ndev); + irqreturn_t ret = IRQ_NONE; u32 ioaddr, boguscnt = RX_RING_SIZE; u32 intr_status = 0; @@ -696,7 +697,13 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) /* Get interrpt stat */ intr_status = ctrl_inl(ioaddr + EESR); /* Clear interrupt */ - ctrl_outl(intr_status, ioaddr + EESR); + if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | + EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | + TX_CHECK | EESR_ERR_CHECK)) { + ctrl_outl(intr_status, ioaddr + EESR); + ret = IRQ_HANDLED; + } else + goto other_irq; if (intr_status & (EESR_FRC | /* Frame recv*/ EESR_RMAF | /* Multi cast address recv*/ @@ -723,9 +730,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ndev->name, intr_status); } +other_irq: spin_unlock(&mdp->lock); - return IRQ_HANDLED; + return ret; } static void sh_eth_timer(unsigned long data) @@ -844,7 +852,13 @@ static int sh_eth_open(struct net_device *ndev) int ret = 0; struct sh_eth_private *mdp = netdev_priv(ndev); - ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev); + ret = request_irq(ndev->irq, &sh_eth_interrupt, +#if defined(CONFIG_CPU_SUBTYPE_SH7763) || defined(CONFIG_CPU_SUBTYPE_SH7764) + IRQF_SHARED, +#else + 0, +#endif + ndev->name, ndev); if (ret) { printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME); return ret; diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 73bc7181cc1..1537e13e623 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -43,8 +43,8 @@ #define SH7763_SKB_ALIGN 32 /* Chip Base Address */ -# define SH_TSU_ADDR 0xFFE01800 -# define ARSTR 0xFFE01800 +# define SH_TSU_ADDR 0xFEE01800 +# define ARSTR SH_TSU_ADDR /* Chip Registers */ /* E-DMAC */ diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 870b4c33f10..a45952e7201 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -42,6 +42,16 @@ #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW +#elif defined(CONFIG_ARCH_OMAP34XX) + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 + #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW + #define SMC_MEM_RESERVED 1 +#elif defined(CONFIG_ARCH_OMAP24XX) + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 + #define SMC_IRQ_SENSE IRQF_TRIGGER_LOW + #define SMC_MEM_RESERVED 1 #else /* * Default configuration @@ -675,6 +685,7 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr, #define CHIP_9116 0x0116 #define CHIP_9117 0x0117 #define CHIP_9118 0x0118 +#define CHIP_9211 0x9211 #define CHIP_9215 0x115A #define CHIP_9217 0x117A #define CHIP_9218 0x118A @@ -689,6 +700,7 @@ static const struct chip_id chip_ids[] = { { CHIP_9116, "LAN9116" }, { CHIP_9117, "LAN9117" }, { CHIP_9118, "LAN9118" }, + { CHIP_9211, "LAN9211" }, { CHIP_9215, "LAN9215" }, { CHIP_9217, "LAN9217" }, { CHIP_9218, "LAN9218" }, diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a78daec2fe..d1590ac55e4 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1225,6 +1225,10 @@ static int smsc911x_open(struct net_device *dev) dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n", (unsigned long)pdata->ioaddr, dev->irq); + /* Reset the last known duplex and carrier */ + pdata->last_duplex = -1; + pdata->last_carrier = -1; + /* Bring the PHY up */ phy_start(pdata->phy_dev); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 8d64b1da046..c9c7650826c 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1229,7 +1229,7 @@ static void gem_reset(struct gem *gp) break; } while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST)); - if (limit <= 0) + if (limit < 0) printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes) @@ -2998,8 +2998,11 @@ static const struct net_device_ops gem_netdev_ops = { .ndo_do_ioctl = gem_ioctl, .ndo_tx_timeout = gem_tx_timeout, .ndo_change_mtu = gem_change_mtu, - .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = gem_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gem_poll_controller, +#endif }; static int __devinit gem_init_one(struct pci_dev *pdev, @@ -3161,10 +3164,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev->watchdog_timeo = 5 * HZ; dev->irq = pdev->irq; dev->dma = 0; - dev->set_mac_address = gem_set_mac_address; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = gem_poll_controller; -#endif /* Set that now, in case PM kicks in now */ pci_set_drvdata(pdev, dev); diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index d4fb4acdbeb..4e9bd380a5c 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2649,8 +2649,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) int err = -ENODEV; sbus_dp = to_of_device(op->dev.parent)->node; - if (is_qfe) - sbus_dp = to_of_device(op->dev.parent->parent)->node; /* We can match PCI devices too, do not accept those here. */ if (strcmp(sbus_dp->name, "sbus")) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b080f9493d8..dabdf59f801 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1473,7 +1473,8 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) { u32 reg; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) return; reg = MII_TG3_MISC_SHDW_WREN | diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c index 5f601773c26..e2150b3c83d 100644 --- a/drivers/net/tokenring/tmspci.c +++ b/drivers/net/tokenring/tmspci.c @@ -121,11 +121,6 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic goto err_out_trdev; } - ret = request_irq(pdev->irq, tms380tr_interrupt, IRQF_SHARED, - dev->name, dev); - if (ret) - goto err_out_region; - dev->base_addr = pci_ioaddr; dev->irq = pci_irq_line; dev->dma = 0; @@ -142,7 +137,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic ret = tmsdev_init(dev, &pdev->dev); if (ret) { printk("%s: unable to get memory for dev->priv.\n", dev->name); - goto err_out_irq; + goto err_out_region; } tp = netdev_priv(dev); @@ -157,6 +152,11 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic tp->tmspriv = cardinfo; + ret = request_irq(pdev->irq, tms380tr_interrupt, IRQF_SHARED, + dev->name, dev); + if (ret) + goto err_out_tmsdev; + dev->open = tms380tr_open; dev->stop = tms380tr_close; pci_set_drvdata(pdev, dev); @@ -164,15 +164,15 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic ret = register_netdev(dev); if (ret) - goto err_out_tmsdev; + goto err_out_irq; return 0; +err_out_irq: + free_irq(pdev->irq, dev); err_out_tmsdev: pci_set_drvdata(pdev, NULL); tmsdev_term(dev); -err_out_irq: - free_irq(pdev->irq, dev); err_out_region: release_region(pci_ioaddr, TMS_PCI_IO_EXTENT); err_out_trdev: diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index bee75fa87a9..2abb5d3becc 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -255,6 +255,7 @@ const char tulip_media_cap[32] = static void tulip_tx_timeout(struct net_device *dev); static void tulip_init_ring(struct net_device *dev); +static void tulip_free_ring(struct net_device *dev); static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev); static int tulip_open(struct net_device *dev); static int tulip_close(struct net_device *dev); @@ -502,16 +503,21 @@ tulip_open(struct net_device *dev) { int retval; - if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) - return retval; - tulip_init_ring (dev); + retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev); + if (retval) + goto free_ring; + tulip_up (dev); netif_start_queue (dev); return 0; + +free_ring: + tulip_free_ring (dev); + return retval; } @@ -768,23 +774,11 @@ static void tulip_down (struct net_device *dev) tulip_set_power_state (tp, 0, 1); } - -static int tulip_close (struct net_device *dev) +static void tulip_free_ring (struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->base_addr; int i; - netif_stop_queue (dev); - - tulip_down (dev); - - if (tulip_debug > 1) - printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, ioread32 (ioaddr + CSR5)); - - free_irq (dev->irq, dev); - /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = tp->rx_buffers[i].skb; @@ -803,6 +797,7 @@ static int tulip_close (struct net_device *dev) dev_kfree_skb (skb); } } + for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = tp->tx_buffers[i].skb; @@ -814,6 +809,24 @@ static int tulip_close (struct net_device *dev) tp->tx_buffers[i].skb = NULL; tp->tx_buffers[i].mapping = 0; } +} + +static int tulip_close (struct net_device *dev) +{ + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + netif_stop_queue (dev); + + tulip_down (dev); + + if (tulip_debug > 1) + printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, ioread32 (ioaddr + CSR5)); + + free_irq (dev->irq, dev); + + tulip_free_ring (dev); return 0; } diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index e87986867ba..1f61e42c641 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1536,32 +1536,15 @@ static void adjust_link(struct net_device *dev) static int init_phy(struct net_device *dev) { struct ucc_geth_private *priv = netdev_priv(dev); - struct device_node *np = priv->node; - struct device_node *phy, *mdio; - const phandle *ph; - char bus_name[MII_BUS_ID_SIZE]; - const unsigned int *id; + struct ucc_geth_info *ug_info = priv->ug_info; struct phy_device *phydev; - char phy_id[BUS_ID_SIZE]; priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); - mdio = of_get_parent(phy); - - id = of_get_property(phy, "reg", NULL); - - of_node_put(phy); - of_node_put(mdio); - - uec_mdio_bus_name(bus_name, mdio); - snprintf(phy_id, sizeof(phy_id), "%s:%02x", - bus_name, *id); - - phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); + phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0, + priv->phy_interface); if (IS_ERR(phydev)) { printk("%s: Could not attach to PHY\n", dev->name); @@ -3629,10 +3612,12 @@ 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->mdio_bus, MII_BUS_ID_SIZE, "0"); - ug_info->phy_address = fixed_link[0]; + 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); @@ -3643,7 +3628,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma prop = of_get_property(phy, "reg", NULL); if (prop == NULL) return -1; - ug_info->phy_address = *prop; /* Set the bus id */ mdio = of_get_parent(phy); @@ -3657,7 +3641,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (err) return -1; - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start); + uec_mdio_bus_name(bus_name, mdio); + snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), + "%s:%02x", bus_name, *prop); } /* get the phy interface type, or default to MII */ diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 16cbe42ba43..611bdef2402 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -1091,8 +1091,7 @@ struct ucc_geth_info { u32 eventRegMask; u16 pausePeriod; u16 extensionField; - u8 phy_address; - char mdio_bus[MII_BUS_ID_SIZE]; + char phy_bus_id[BUS_ID_SIZE]; u8 weightfactor[NUM_TX_QUEUES]; u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index 54635911305..0ada4edd56e 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c @@ -107,7 +107,7 @@ int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum) static int uec_mdio_reset(struct mii_bus *bus) { struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; - unsigned int timeout = PHY_INIT_TIMEOUT; + int timeout = PHY_INIT_TIMEOUT; mutex_lock(&bus->mdio_lock); @@ -123,7 +123,7 @@ static int uec_mdio_reset(struct mii_bus *bus) mutex_unlock(&bus->mdio_lock); - if (timeout <= 0) { + if (timeout < 0) { printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); return -EBUSY; } diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e009481c606..396f821b5ff 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1451,6 +1451,14 @@ static const struct usb_device_id products [] = { // Cables-to-Go USB Ethernet Adapter USB_DEVICE(0x0b95, 0x772a), .driver_info = (unsigned long) &ax88772_info, +}, { + // ABOCOM for pci + USB_DEVICE(0x14ea, 0xab11), + .driver_info = (unsigned long) &ax88178_info, +}, { + // ASIX 88772a + USB_DEVICE(0x0db0, 0xa877), + .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 0e061dfea78..55e8ecc3a9e 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -559,6 +559,11 @@ static const struct usb_device_id products [] = { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, +}, { + /* Ericsson F3507g */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, }, { }, // END }; diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 5b67bbf1987..81682c6defa 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -635,6 +635,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0a47, 0x9601), /* Hirose USB-100 */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0fe6, 0x8101), /* DM9601 USB to Fast Ethernet Adapter */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index aa314907888..c32284ff3f5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -723,8 +723,8 @@ u32 usbnet_get_link (struct net_device *net) if (dev->mii.mdio_read) return mii_link_ok(&dev->mii); - /* Otherwise, say we're up (to avoid breaking scripts) */ - return 1; + /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */ + return ethtool_op_get_link(net); } EXPORT_SYMBOL_GPL(usbnet_get_link); diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index e24f7b3ace4..04882c8f9bf 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -341,6 +341,11 @@ static const struct usb_device_id products [] = { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &bogus_mdlm_info, +}, { + /* Motorola MOTOMAGX phones */ + USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &bogus_mdlm_info, }, /* Olympus has some models with a Zaurus-compatible option. diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 108bbbeacfb..124fe75b8a8 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -239,6 +239,16 @@ static int veth_open(struct net_device *dev) return 0; } +static int veth_close(struct net_device *dev) +{ + struct veth_priv *priv = netdev_priv(dev); + + netif_carrier_off(dev); + netif_carrier_off(priv->peer); + + return 0; +} + static int veth_dev_init(struct net_device *dev) { struct veth_net_stats *stats; @@ -265,6 +275,7 @@ static void veth_dev_free(struct net_device *dev) static const struct net_device_ops veth_netdev_ops = { .ndo_init = veth_dev_init, .ndo_open = veth_open, + .ndo_stop = veth_close, .ndo_start_xmit = veth_xmit, .ndo_get_stats = veth_get_stats, .ndo_set_mac_address = eth_mac_addr, @@ -280,44 +291,6 @@ static void veth_setup(struct net_device *dev) dev->destructor = veth_dev_free; } -static void veth_change_state(struct net_device *dev) -{ - struct net_device *peer; - struct veth_priv *priv; - - priv = netdev_priv(dev); - peer = priv->peer; - - if (netif_carrier_ok(peer)) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else { - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); - } -} - -static int veth_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - - if (dev->netdev_ops->ndo_open != veth_open) - goto out; - - switch (event) { - case NETDEV_CHANGE: - veth_change_state(dev); - break; - } -out: - return NOTIFY_DONE; -} - -static struct notifier_block veth_notifier_block __read_mostly = { - .notifier_call = veth_device_event, -}; - /* * netlink interface */ @@ -468,14 +441,12 @@ static struct rtnl_link_ops veth_link_ops = { static __init int veth_init(void) { - register_netdevice_notifier(&veth_notifier_block); return rtnl_link_register(&veth_link_ops); } static __exit void veth_exit(void) { rtnl_link_unregister(&veth_link_ops); - unregister_netdevice_notifier(&veth_notifier_block); } module_init(veth_init); diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index c5691fdb707..fb53ef872df 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1838,17 +1838,19 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_ { struct sk_buff *skb = tdinfo->skb; int i; + int pktlen; /* * Don't unmap the pre-allocated tx_bufs */ if (tdinfo->skb_dma) { + pktlen = (skb->len > ETH_ZLEN ? : ETH_ZLEN); for (i = 0; i < tdinfo->nskb_dma; i++) { #ifdef VELOCITY_ZERO_COPY_SUPPORT pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE); #else - pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE); #endif tdinfo->skb_dma[i] = 0; } @@ -2080,17 +2082,14 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) struct tx_desc *td_ptr; struct velocity_td_info *tdinfo; unsigned long flags; - int pktlen = skb->len; + int pktlen; __le16 len; int index; - - if (skb->len < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - goto out; - pktlen = ETH_ZLEN; - } + if (skb_padto(skb, ETH_ZLEN)) + goto out; + pktlen = max_t(unsigned int, skb->len, ETH_ZLEN); len = cpu_to_le16(pktlen); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c68808336c8..e67d16c2e5f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -612,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, + .get_link = ethtool_op_get_link, }; #define MIN_MTU 68 @@ -739,6 +740,8 @@ static int virtnet_probe(struct virtio_device *vdev) goto unregister; } + netif_carrier_on(dev); + pr_debug("virtnet: registered device %s\n", dev->name); return 0; diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d2781350295..6650f609ece 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -587,8 +587,8 @@ struct ath9k_country_entry { u8 iso[3]; }; -#define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) -#define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) +#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) +#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ca2aed236e..139566cbbf6 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -701,6 +701,7 @@ struct ath_softc { struct ath_hal *sc_ah; void __iomem *mem; spinlock_t sc_resetlock; + spinlock_t sc_serial_rw; struct mutex mutex; u8 sc_curbssid[ETH_ALEN]; @@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); +/* + * 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_hal *ah, u32 reg_offset, u32 val) +{ + if (ah->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_hal *ah, u32 reg_offset) +{ + u32 val; + if (ah->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; +} + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 34474edefc9..c38a00bbce6 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) } ah->ah_config.intr_mitigation = 1; + + /* + * We need this for PCI devices only (Cardbus, PCI, miniPCI) + * _and_ if on non-uniprocessor systems (Multiprocessor/HT). + * This means we use it for all AR5416 devices, and the few + * minor PCI AR9280 devices out there. + * + * Serialization is required because these devices do not handle + * well the case of two concurrent reads/writes due to the latency + * involved. During one read/write another read/write can be issued + * on another CPU while the previous read/write may still be working + * on our hardware, if we hit this case the hardware poops in a loop. + * We prevent this by serializing reads and writes. + * + * This issue is not present on PCI-Express devices or pre-AR5416 + * devices (legacy, 802.11abg). + */ + if (num_possible_cpus() > 1) + ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO; } static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, @@ -668,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, } if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { - if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { + if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI || + (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) { ah->ah_config.serialize_regmode = SER_REG_MODE_ON; } else { diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 727f067aca4..3c04044a60b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) printk(KERN_ERR "Unable to create debugfs files\n"); spin_lock_init(&sc->sc_resetlock); + spin_lock_init(&sc->sc_serial_rw); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, @@ -1538,6 +1539,7 @@ bad2: bad: if (ah) ath9k_hw_detach(ah); + ath9k_exit_debug(sc); return error; } @@ -1545,7 +1547,7 @@ bad: static int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; - int error = 0; + int error = 0, i; DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); @@ -1589,11 +1591,11 @@ static int ath_attach(u16 devid, struct ath_softc *sc) /* initialize tx/rx engine */ error = ath_tx_init(sc, ATH_TXBUF); if (error != 0) - goto detach; + goto error_attach; error = ath_rx_init(sc, ATH_RXBUF); if (error != 0) - goto detach; + goto error_attach; #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) /* Initialze h/w Rfkill */ @@ -1601,8 +1603,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc) INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); /* Initialize s/w rfkill */ - if (ath_init_sw_rfkill(sc)) - goto detach; + error = ath_init_sw_rfkill(sc); + if (error) + goto error_attach; #endif error = ieee80211_register_hw(hw); @@ -1611,8 +1614,16 @@ static int ath_attach(u16 devid, struct ath_softc *sc) ath_init_leds(sc); return 0; -detach: - ath_detach(sc); + +error_attach: + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + ath9k_hw_detach(sc->sc_ah); + ath9k_exit_debug(sc); + return error; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 36bafeb353c..129e2d330ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3868,7 +3868,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } err = iwl_eeprom_check_version(priv); if (err) - goto out_iounmap; + goto out_free_eeprom; /* extract MAC Address */ iwl_eeprom_get_mac(priv, priv->mac_addr); @@ -3945,6 +3945,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; out_remove_sysfs: + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); out_uninit_drv: iwl_uninit_drv(priv); @@ -3953,8 +3955,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_iounmap: pci_iounmap(pdev, priv->hw_base); out_pci_release_regions: - pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); out_pci_disable_device: pci_disable_device(pdev); out_ieee80211_free_hw: diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 93be74a1f13..57dd34e256d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7911,7 +7911,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (err < 0) { IWL_DEBUG_INFO("Failed to init the card\n"); - goto out_remove_sysfs; + goto out_iounmap; } /*********************** @@ -7921,7 +7921,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl3945_eeprom_init(priv); if (err) { IWL_ERROR("Unable to init EEPROM\n"); - goto out_remove_sysfs; + goto out_iounmap; } /* MAC Address location in EEPROM same for 3945/4965 */ get_eeprom_mac(priv, priv->mac_addr); @@ -7975,7 +7975,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl3945_init_channel_map(priv); if (err) { IWL_ERROR("initializing regulatory failed: %d\n", err); - goto out_release_irq; + goto out_unset_hw_setting; } err = iwl3945_init_geos(priv); @@ -8045,25 +8045,22 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return 0; out_remove_sysfs: + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); out_free_geos: iwl3945_free_geos(priv); out_free_channel_map: iwl3945_free_channel_map(priv); - - - out_release_irq: - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; + out_unset_hw_setting: iwl3945_unset_hw_setting(priv); - out_iounmap: pci_iounmap(pdev, priv->hw_base); out_pci_release_regions: pci_release_regions(pdev); out_pci_disable_device: - pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); + pci_disable_device(pdev); out_ieee80211_free_hw: ieee80211_free_hw(priv->hw); out: diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 61d2f50470c..b118a35ec60 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -23,7 +23,7 @@ static const char * mesh_stat_strings[]= { static void lbs_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; snprintf(info->fw_version, 32, "%u.%u.%u.p%u", priv->fwrelease >> 24 & 0xff, @@ -47,7 +47,7 @@ static int lbs_ethtool_get_eeprom_len(struct net_device *dev) static int lbs_ethtool_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 * bytes) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct cmd_ds_802_11_eeprom_access cmd; int ret; @@ -76,7 +76,7 @@ out: static void lbs_ethtool_get_stats(struct net_device *dev, struct ethtool_stats *stats, uint64_t *data) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; @@ -113,7 +113,7 @@ static void lbs_ethtool_get_stats(struct net_device *dev, static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; if (sset == ETH_SS_STATS && dev == priv->mesh_dev) return MESH_STATS_NUM; @@ -143,7 +143,7 @@ static void lbs_ethtool_get_strings(struct net_device *dev, static void lbs_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; if (priv->wol_criteria == 0xffffffff) { /* Interface driver didn't configure wake */ @@ -166,7 +166,7 @@ static void lbs_ethtool_get_wol(struct net_device *dev, static int lbs_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; uint32_t criteria = 0; if (priv->wol_criteria == 0xffffffff && wol->wolopts) diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 2fc637ad85c..ea3dc038be7 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -59,7 +59,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); static ssize_t if_usb_firmware_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct if_usb_card *cardp = priv->card; char fwname[FIRMWARE_NAME_MAX]; int ret; @@ -86,7 +86,7 @@ static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); static ssize_t if_usb_boot2_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct if_usb_card *cardp = priv->card; char fwname[FIRMWARE_NAME_MAX]; int ret; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4e0007d2003..f76623e0ff9 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -222,7 +222,7 @@ u8 lbs_data_rate_to_fw_index(u32 rate) static ssize_t lbs_anycast_get(struct device *dev, struct device_attribute *attr, char * buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; @@ -241,7 +241,7 @@ static ssize_t lbs_anycast_get(struct device *dev, static ssize_t lbs_anycast_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; uint32_t datum; int ret; @@ -263,7 +263,7 @@ static ssize_t lbs_anycast_set(struct device *dev, static ssize_t lbs_prb_rsp_limit_get(struct device *dev, struct device_attribute *attr, char *buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; u32 retry_limit; @@ -286,7 +286,7 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, static ssize_t lbs_prb_rsp_limit_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_access mesh_access; int ret; unsigned long retry_limit; @@ -321,7 +321,7 @@ static void lbs_remove_mesh(struct lbs_private *priv); static ssize_t lbs_rtap_get(struct device *dev, struct device_attribute *attr, char * buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; return snprintf(buf, 5, "0x%X\n", priv->monitormode); } @@ -332,7 +332,7 @@ static ssize_t lbs_rtap_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { int monitor_mode; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; sscanf(buf, "%x", &monitor_mode); if (monitor_mode) { @@ -383,7 +383,7 @@ static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); static ssize_t lbs_mesh_get(struct device *dev, struct device_attribute *attr, char * buf) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); } @@ -393,7 +393,7 @@ static ssize_t lbs_mesh_get(struct device *dev, static ssize_t lbs_mesh_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; int enable; int ret, action = CMD_ACT_MESH_CONFIG_STOP; @@ -452,7 +452,7 @@ static struct attribute_group lbs_mesh_attr_group = { */ static int lbs_dev_open(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev) ; + struct lbs_private *priv = dev->ml_priv; int ret = 0; lbs_deb_enter(LBS_DEB_NET); @@ -521,7 +521,7 @@ static int lbs_mesh_stop(struct net_device *dev) */ static int lbs_eth_stop(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_NET); @@ -538,7 +538,7 @@ static int lbs_eth_stop(struct net_device *dev) static void lbs_tx_timeout(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_TX); @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(lbs_host_to_card_done); */ static struct net_device_stats *lbs_get_stats(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_NET); return &priv->stats; @@ -599,7 +599,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev) static int lbs_set_mac_address(struct net_device *dev, void *addr) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct sockaddr *phwaddr = addr; struct cmd_ds_802_11_mac_address cmd; @@ -732,7 +732,7 @@ static void lbs_set_mcast_worker(struct work_struct *work) static void lbs_set_multicast_list(struct net_device *dev) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; schedule_work(&priv->mcast_work); } @@ -748,7 +748,7 @@ static void lbs_set_multicast_list(struct net_device *dev) static int lbs_thread(void *data) { struct net_device *dev = data; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; wait_queue_t wait; lbs_deb_enter(LBS_DEB_THREAD); @@ -1184,6 +1184,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) goto done; } priv = netdev_priv(dev); + dev->ml_priv = priv; if (lbs_init_adapter(priv)) { lbs_pr_err("failed to initialize adapter structure.\n"); diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c index d42b7a5a1b3..18fe29faf99 100644 --- a/drivers/net/wireless/libertas/persistcfg.c +++ b/drivers/net/wireless/libertas/persistcfg.c @@ -18,7 +18,7 @@ static int mesh_get_default_parameters(struct device *dev, struct mrvl_mesh_defaults *defs) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; int ret; @@ -57,7 +57,7 @@ static ssize_t bootflag_get(struct device *dev, static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; uint32_t datum; int ret; @@ -100,7 +100,7 @@ static ssize_t boottime_get(struct device *dev, static ssize_t boottime_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; uint32_t datum; int ret; @@ -152,7 +152,7 @@ static ssize_t channel_get(struct device *dev, static ssize_t channel_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; struct cmd_ds_mesh_config cmd; uint32_t datum; int ret; @@ -210,7 +210,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; int len; int ret; @@ -269,7 +269,7 @@ static ssize_t protocol_id_set(struct device *dev, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; uint32_t datum; int ret; @@ -323,7 +323,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; uint32_t datum; int ret; @@ -377,7 +377,7 @@ static ssize_t capability_set(struct device *dev, struct device_attribute *attr, struct cmd_ds_mesh_config cmd; struct mrvl_mesh_defaults defs; struct mrvl_meshie *ie; - struct lbs_private *priv = netdev_priv(to_net_dev(dev)); + struct lbs_private *priv = to_net_dev(dev)->ml_priv; uint32_t datum; int ret; diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 57f6c12cda2..9014950f432 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -945,7 +945,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { DECLARE_SSID_BUF(ssid); - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; lbs_deb_enter(LBS_DEB_WEXT); @@ -1008,7 +1008,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { #define SCAN_ITEM_SIZE 128 - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int err = 0; char *ev = extra; char *stop = ev + dwrq->length; diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index dac46264117..68bec31ae03 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -60,7 +60,7 @@ static u32 convert_radiotap_rate_to_mv(u8 rate) int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned long flags; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct txpd *txpd; char *p802x_hdr; uint16_t pkt_len; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c6102e08179..f16d136ab4b 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -163,7 +163,7 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info, static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct chan_freq_power *cfp; lbs_deb_enter(LBS_DEB_WEXT); @@ -189,7 +189,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -207,7 +207,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -231,7 +231,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -248,7 +248,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -273,7 +273,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; u32 val = vwrq->value; lbs_deb_enter(LBS_DEB_WEXT); @@ -293,7 +293,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 val = 0; @@ -315,7 +315,7 @@ out: static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u32 val = vwrq->value; @@ -336,7 +336,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 val = 0; @@ -359,7 +359,7 @@ out: static int lbs_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -385,7 +385,7 @@ static int lbs_get_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; s16 curlevel = 0; int ret = 0; @@ -418,7 +418,7 @@ out: static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 slimit = 0, llimit = 0; @@ -466,7 +466,7 @@ out: static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u16 val = 0; @@ -542,7 +542,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int i, j; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct iw_range *range = (struct iw_range *)extra; struct chan_freq_power *cfp; u8 rates[MAX_RATES + 1]; @@ -708,7 +708,7 @@ out: static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -758,7 +758,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -781,7 +781,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) EXCELLENT = 95, PERFECT = 100 }; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; u32 rssi_qual; u32 tx_qual; u32 quality = 0; @@ -886,7 +886,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { int ret = -EINVAL; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct chan_freq_power *cfp; struct assoc_request * assoc_req; @@ -943,7 +943,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct chan_freq_power *cfp; int ret = -EINVAL; @@ -994,7 +994,7 @@ out: static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; u8 new_rate = 0; int ret = -EINVAL; u8 rates[MAX_RATES + 1]; @@ -1054,7 +1054,7 @@ out: static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1079,7 +1079,7 @@ static int lbs_set_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; lbs_deb_enter(LBS_DEB_WEXT); @@ -1124,7 +1124,7 @@ static int lbs_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, u8 * extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; lbs_deb_enter(LBS_DEB_WEXT); @@ -1319,7 +1319,7 @@ static int lbs_set_encode(struct net_device *dev, struct iw_point *dwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; u16 is_default = 0, index = 0, set_tx_key = 0; @@ -1395,7 +1395,7 @@ static int lbs_get_encodeext(struct net_device *dev, char *extra) { int ret = -EINVAL; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int index, max_key_len; @@ -1501,7 +1501,7 @@ static int lbs_set_encodeext(struct net_device *dev, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int alg = ext->alg; struct assoc_request * assoc_req; @@ -1639,7 +1639,7 @@ static int lbs_set_genie(struct net_device *dev, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; struct assoc_request * assoc_req; @@ -1685,7 +1685,7 @@ static int lbs_get_genie(struct net_device *dev, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1713,7 +1713,7 @@ static int lbs_set_auth(struct net_device *dev, struct iw_param *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; int ret = 0; int updated = 0; @@ -1816,7 +1816,7 @@ static int lbs_get_auth(struct net_device *dev, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1857,7 +1857,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; s16 dbm = (s16) vwrq->value; lbs_deb_enter(LBS_DEB_WEXT); @@ -1936,7 +1936,7 @@ out: static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -1971,7 +1971,7 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; u8 ssid[IW_ESSID_MAX_SIZE]; u8 ssid_len = 0; @@ -2040,7 +2040,7 @@ static int lbs_mesh_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; lbs_deb_enter(LBS_DEB_WEXT); @@ -2058,7 +2058,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; int ret = 0; lbs_deb_enter(LBS_DEB_WEXT); @@ -2102,7 +2102,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra) { - struct lbs_private *priv = netdev_priv(dev); + struct lbs_private *priv = dev->ml_priv; struct assoc_request * assoc_req; int ret = 0; diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 45a04faa781..067d1a9c728 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -3157,8 +3157,20 @@ static int orinoco_pm_notifier(struct notifier_block *notifier, return NOTIFY_DONE; } + +static void orinoco_register_pm_notifier(struct orinoco_private *priv) +{ + priv->pm_notifier.notifier_call = orinoco_pm_notifier; + register_pm_notifier(&priv->pm_notifier); +} + +static void orinoco_unregister_pm_notifier(struct orinoco_private *priv) +{ + unregister_pm_notifier(&priv->pm_notifier); +} #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ -#define orinoco_pm_notifier NULL +#define orinoco_register_pm_notifier(priv) do { } while(0) +#define orinoco_unregister_pm_notifier(priv) do { } while(0) #endif /********************************************************************/ @@ -3648,8 +3660,7 @@ struct net_device priv->cached_fw = NULL; /* Register PM notifiers */ - priv->pm_notifier.notifier_call = orinoco_pm_notifier; - register_pm_notifier(&priv->pm_notifier); + orinoco_register_pm_notifier(priv); return dev; } @@ -3673,7 +3684,7 @@ void free_orinocodev(struct net_device *dev) kfree(rx_data); } - unregister_pm_notifier(&priv->pm_notifier); + orinoco_unregister_pm_notifier(priv); orinoco_uncache_fw(priv); priv->wpa_ie_len = 0; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 34561e6e816..f170106bf0a 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -710,10 +710,11 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev, __le32 req_id) { struct p54_common *priv = dev->priv; - struct sk_buff *entry = priv->tx_queue.next; + struct sk_buff *entry; unsigned long flags; spin_lock_irqsave(&priv->tx_queue.lock, flags); + entry = priv->tx_queue.next; while (entry != (struct sk_buff *)&priv->tx_queue) { struct p54_hdr *hdr = (struct p54_hdr *) entry->data; @@ -732,7 +733,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_common *priv = dev->priv; struct p54_hdr *hdr = (struct p54_hdr *) skb->data; struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data; - struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next; + struct sk_buff *entry; u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom; struct memrecord *range = NULL; u32 freed = 0; @@ -741,6 +742,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) int count, idx; spin_lock_irqsave(&priv->tx_queue.lock, flags); + entry = (struct sk_buff *) priv->tx_queue.next; while (entry != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); struct p54_hdr *entry_hdr; @@ -976,7 +978,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, struct p54_hdr *data, u32 len) { struct p54_common *priv = dev->priv; - struct sk_buff *entry = priv->tx_queue.next; + struct sk_buff *entry; struct sk_buff *target_skb = NULL; struct ieee80211_tx_info *info; struct memrecord *range; @@ -1014,6 +1016,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, } } + entry = priv->tx_queue.next; while (left--) { u32 hole_size; info = IEEE80211_SKB_CB(entry); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index af6b5847be5..3e2ac2bbb12 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1952,6 +1952,8 @@ static struct usb_device_id rt2500usb_device_table[] = { { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* CNet */ + { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, /* D-LINK */ @@ -1976,14 +1978,20 @@ static struct usb_device_id rt2500usb_device_table[] = { { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* Sagem */ + { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Siemens */ { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, /* SMC */ { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Spairon */ { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* SURECOM */ + { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Trust */ { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* VTech */ + { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, { 0, } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 96a8d69f879..cefee1b26cd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2281,7 +2281,18 @@ static const struct rt2x00_ops rt73usb_ops = { */ static struct usb_device_id rt73usb_device_table[] = { /* AboCom */ + { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) }, + /* AL */ + { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Amigo */ + { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, + /* AMIT */ + { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) }, /* Askey */ { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) }, /* ASUS */ @@ -2294,7 +2305,9 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, /* Billionton */ { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, /* Buffalo */ + { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, @@ -2308,6 +2321,11 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Edimax */ + { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) }, + /* EnGenius */ + { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, /* Gigabyte */ @@ -2328,22 +2346,34 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ralink */ + { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Samsung */ + { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) }, /* Senao */ { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, /* Surecom */ { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Philips */ + { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, /* Planex */ { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Zcom */ + { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, + /* ZyXEL */ + { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) }, { 0, } }; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 22bc07ef2f3..f4747a1134b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -48,6 +48,10 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, + /* Surecom */ + {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, + /* Logitech */ + {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, /* Netgear */ {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, @@ -57,8 +61,16 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, + /* Sphairon Access Systems GmbH */ + {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, + /* Dick Smith Electronics */ + {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, /* Abocom */ {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, + /* Qcom */ + {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, + /* AirLive */ + {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, {} }; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a611ad85798..847057d682b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) r = fill_ctrlset(mac, skb); if (r) - return r; + goto fail; info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) - return r; + goto fail; + return 0; + +fail: + dev_kfree_skb(skb); return 0; } diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index d539d9df88e..bb5a1c9597c 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -479,7 +479,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", - bus->bridge->bus_id); + dev_name(bus->bridge)); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); @@ -493,7 +493,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) struct list_head *ln, *tmp_ln; printk(KERN_ERR "Dino: cannot attach bus %s\n", - bus->bridge->bus_id); + dev_name(bus->bridge)); /* kill the bus, we can't do anything with it */ list_for_each_safe(ln, tmp_ln, &bus->devices) { struct pci_dev *dev = pci_dev_b(ln); @@ -587,7 +587,7 @@ dino_fixup_bus(struct pci_bus *bus) bus->resource[i+1] = &res[i]; } - } else if(bus->self) { + } else if (bus->parent) { int i; pci_read_bridge_bases(bus); @@ -611,12 +611,12 @@ dino_fixup_bus(struct pci_bus *bus) } DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); pci_assign_resource(bus->self, i); DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); } @@ -1026,7 +1026,8 @@ static int __init dino_probe(struct parisc_device *dev) dino_current_bus = bus->subordinate + 1; pci_bus_assign_resources(bus); } else { - printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus); + printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", + dev_name(&dev->dev), dino_current_bus); /* increment the bus number in case of duplicates */ dino_current_bus++; } diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index e76db9e4d50..d3363291769 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -186,29 +186,34 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp) *irqp = irq; } -static struct device *next_device(struct klist_iter *i) +struct gsc_fixup_struct { + void (*choose_irq)(struct parisc_device *, void *); + void *ctrl; +}; + +static int gsc_fixup_irqs_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct parisc_device *padev = to_parisc_device(dev); + struct gsc_fixup_struct *gf = data; + + /* work-around for 715/64 and others which have parent + at path [5] and children at path [5/0/x] */ + if (padev->id.hw_type == HPHW_FAULTY) + gsc_fixup_irqs(padev, gf->ctrl, gf->choose_irq); + gf->choose_irq(padev, gf->ctrl); + + return 0; } void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose_irq)(struct parisc_device *, void *)) { - struct device *dev; - struct klist_iter i; - - klist_iter_init(&parent->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - - /* work-around for 715/64 and others which have parent - at path [5] and children at path [5/0/x] */ - if (padev->id.hw_type == HPHW_FAULTY) - return gsc_fixup_irqs(padev, ctrl, choose_irq); - choose_irq(padev, ctrl); - } - klist_iter_exit(&i); + struct gsc_fixup_struct data = { + .choose_irq = choose_irq, + .ctrl = ctrl, + }; + + device_for_each_child(&parent->dev, &data, gsc_fixup_irqs_callback); } int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 0797659ee01..501aaf1f253 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -487,7 +487,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) } /* Check if pcidev behind a PPB */ - if (NULL != pcidev->bus->self) { + if (pcidev->bus->parent) { /* Convert pcidev INTR_PIN into something we ** can lookup in the IRT. */ @@ -523,10 +523,9 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) #endif /* PCI_BRIDGE_FUNCS */ /* - ** Locate the host slot the PPB nearest the Host bus - ** adapter. - */ - while (NULL != p->parent->self) + * Locate the host slot of the PPB. + */ + while (p->parent->parent) p = p->parent; intr_slot = PCI_SLOT(p->self->devfn); @@ -709,11 +708,14 @@ static void iosapic_set_affinity_irq(unsigned int irq, struct vector_info *vi = iosapic_get_vector(irq); u32 d0, d1, dummy_d0; unsigned long flags; + int dest_cpu; - if (cpu_check_affinity(irq, dest)) + dest_cpu = cpu_check_affinity(irq, dest); + if (dest_cpu < 0) return; - vi->txn_addr = txn_affinity_addr(irq, cpumask_first(dest)); + irq_desc[irq].affinity = cpumask_of_cpu(dest_cpu); + vi->txn_addr = txn_affinity_addr(irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); /* d1 contains the destination CPU, so only want to set that diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index d8233de8c75..59fbbf12836 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -644,7 +644,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Properly Setup MMIO resources for this bus. ** pci_alloc_primary_bus() mangles this. */ - if (bus->self) { + if (bus->parent) { int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); @@ -802,7 +802,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Can't fixup here anyway....garr... */ if (fbb_enable) { - if (bus->self) { + if (bus->parent) { u8 control; /* enable on PPB */ (void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index a70cf16ee1a..e5999c4cedc 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1206,30 +1206,48 @@ sba_alloc_pdir(unsigned int pdir_size) return (void *) pdir_base; } -static struct device *next_device(struct klist_iter *i) +struct ibase_data_struct { + struct ioc *ioc; + int ioc_num; +}; + +static int setup_ibase_imask_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); + struct parisc_device *lba = to_parisc_device(dev); + struct ibase_data_struct *ibd = data; + int rope_num = (lba->hpa.start >> 13) & 0xf; + if (rope_num >> 3 == ibd->ioc_num) + lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask); + return 0; } /* setup Mercury or Elroy IBASE/IMASK registers. */ static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); - struct device *dev; - struct klist_iter i; - - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - int rope_num = (lba->hpa.start >> 13) & 0xf; - if (rope_num >> 3 == ioc_num) - lba_set_iregs(lba, ioc->ibase, ioc->imask); - } - klist_iter_exit(&i); + struct ibase_data_struct ibase_data = { + .ioc = ioc, + .ioc_num = ioc_num, + }; + + device_for_each_child(&sba->dev, &ibase_data, + setup_ibase_imask_callback); +} + +#ifdef SBA_AGP_SUPPORT +static int +sba_ioc_find_quicksilver(struct device *dev, void *data) +{ + int *agp_found = data; + struct parisc_device *lba = to_parisc_device(dev); + + if (IS_QUICKSILVER(lba)) + *agp_found = 1; + return 0; } +#endif static void sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) @@ -1332,9 +1350,6 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM); #ifdef SBA_AGP_SUPPORT -{ - struct klist_iter i; - struct device *dev = NULL; /* ** If an AGP device is present, only use half of the IOV space @@ -1344,13 +1359,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - if (IS_QUICKSILVER(lba)) - agp_found = 1; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver); if (agp_found && sba_reserve_agpgart) { printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", @@ -1358,9 +1367,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size /= 2; ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } -} #endif /*SBA_AGP_SUPPORT*/ - } static void diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index eacfb13998b..9aa4fe100a0 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -143,7 +143,7 @@ config HOTPLUG_PCI_SHPC config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" - depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE + depends on PPC_PSERIES && EEH && !HOTPLUG_PCI_FAKE help Say Y here if you have a RPA system that supports PCI Hotplug. diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index db85284ffb6..39ae37589fd 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -111,6 +111,7 @@ struct controller { int cmd_busy; unsigned int no_cmd_complete:1; unsigned int link_active_reporting:1; + unsigned int notification_enabled:1; }; #define INT_BUTTON_IGNORE 0 @@ -170,6 +171,7 @@ extern int pciehp_configure_device(struct slot *p_slot); extern int pciehp_unconfigure_device(struct slot *p_slot); extern void pciehp_queue_pushbutton_work(struct work_struct *work); struct controller *pcie_init(struct pcie_device *dev); +int pcie_init_notification(struct controller *ctrl); int pciehp_enable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot); int pcie_enable_notification(struct controller *ctrl); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index c2485542f54..681e3912b82 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -434,6 +434,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ goto err_out_release_ctlr; } + /* Enable events after we have setup the data structures */ + rc = pcie_init_notification(ctrl); + if (rc) { + ctrl_err(ctrl, "Notification initialization failed\n"); + goto err_out_release_ctlr; + } + /* Check if slot is occupied */ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); t_slot->hpc_ops->get_adapter_status(t_slot, &value); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 71a8012886b..7a16c6897bb 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -934,7 +934,7 @@ static void pcie_disable_notification(struct controller *ctrl) ctrl_warn(ctrl, "Cannot disable software notification\n"); } -static int pcie_init_notification(struct controller *ctrl) +int pcie_init_notification(struct controller *ctrl) { if (pciehp_request_irq(ctrl)) return -1; @@ -942,13 +942,17 @@ static int pcie_init_notification(struct controller *ctrl) pciehp_free_irq(ctrl); return -1; } + ctrl->notification_enabled = 1; return 0; } static void pcie_shutdown_notification(struct controller *ctrl) { - pcie_disable_notification(ctrl); - pciehp_free_irq(ctrl); + if (ctrl->notification_enabled) { + pcie_disable_notification(ctrl); + pciehp_free_irq(ctrl); + ctrl->notification_enabled = 0; + } } static int pcie_init_slot(struct controller *ctrl) @@ -1110,13 +1114,8 @@ struct controller *pcie_init(struct pcie_device *dev) if (pcie_init_slot(ctrl)) goto abort_ctrl; - if (pcie_init_notification(ctrl)) - goto abort_slot; - return ctrl; -abort_slot: - pcie_cleanup_slot(ctrl); abort_ctrl: kfree(ctrl); abort: diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index deea8a187eb..368ca72dffb 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -386,12 +386,12 @@ static int __init acpi_pci_init(void) { int ret; - if (acpi_gbl_FADT.boot_flags & BAF_MSI_NOT_SUPPORTED) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) { printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n"); pci_no_msi(); } - if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); pcie_no_aspm(); } diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index aac7006949f..38257500738 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -108,6 +108,37 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev) } #endif /* 0 */ + +static void set_device_error_reporting(struct pci_dev *dev, void *data) +{ + bool enable = *((bool *)data); + + if (dev->pcie_type != PCIE_RC_PORT && + dev->pcie_type != PCIE_SW_UPSTREAM_PORT && + dev->pcie_type != PCIE_SW_DOWNSTREAM_PORT) + return; + + if (enable) + pci_enable_pcie_error_reporting(dev); + else + pci_disable_pcie_error_reporting(dev); +} + +/** + * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports. + * @dev: pointer to root port's pci_dev data structure + * @enable: true = enable error reporting, false = disable error reporting. + */ +static void set_downstream_devices_error_reporting(struct pci_dev *dev, + bool enable) +{ + set_device_error_reporting(dev, &enable); + + if (!dev->subordinate) + return; + pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); +} + static int find_device_iter(struct device *device, void *data) { struct pci_dev *dev; @@ -525,15 +556,11 @@ void aer_enable_rootport(struct aer_rpc *rpc) pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32); pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32); - /* Enable Root Port device reporting error itself */ - pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, ®16); - reg16 = reg16 | - PCI_EXP_DEVCTL_CERE | - PCI_EXP_DEVCTL_NFERE | - PCI_EXP_DEVCTL_FERE | - PCI_EXP_DEVCTL_URRE; - pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL, - reg16); + /* + * Enable error reporting for the root port device and downstream port + * devices. + */ + set_downstream_devices_error_reporting(pdev, true); /* Enable Root Port's interrupt in response to error messages */ pci_write_config_dword(pdev, @@ -553,6 +580,12 @@ static void disable_root_aer(struct aer_rpc *rpc) u32 reg32; int pos; + /* + * Disable error reporting for the root port device and downstream port + * devices. + */ + set_downstream_devices_error_reporting(pdev, false); + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); /* Disable Root's interrupt in response to error messages */ pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0); diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index f9b874eaeb9..5ea566e20b3 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -97,14 +97,13 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, pcie_portdrv_save_config(dev); - pci_enable_pcie_error_reporting(dev); - return 0; } static void pcie_portdrv_remove (struct pci_dev *dev) { pcie_port_device_remove(dev); + pci_disable_device(dev); kfree(pci_get_drvdata(dev)); } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index baad093aafe..92b9efe9bca 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -23,6 +23,7 @@ #include <linux/acpi.h> #include <linux/kallsyms.h> #include <linux/dmi.h> +#include <linux/pci-aspm.h> #include "pci.h" int isa_dma_bridge_buggy; @@ -1584,6 +1585,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_ */ #define AMD_813X_MISC 0x40 #define AMD_813X_NOIOAMODE (1<<0) +#define AMD_813X_REV_B2 0x13 static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) { @@ -1591,6 +1593,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) if (noioapicquirk) return; + if (dev->revision == AMD_813X_REV_B2) + return; pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); pci_config_dword &= ~AMD_813X_NOIOAMODE; @@ -1746,6 +1750,30 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt); +/* + * The 82575 and 82598 may experience data corruption issues when transitioning + * out of L0S. To prevent this we need to disable L0S on the pci-e link + */ +static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev) +{ + dev_info(&dev->dev, "Disabling L0s\n"); + pci_disable_link_state(dev, PCIE_LINK_STATE_L0S); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a7, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a9, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10b6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c7, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c8, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10d6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10db, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10dd, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10e1, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10ec, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s); + static void __devinit fixup_rev1_53c810(struct pci_dev* dev) { /* rev 1 ncr53c810 chips don't set the class at all which means @@ -1981,7 +2009,6 @@ static void __devinit quirk_msi_ht_cap(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE, quirk_msi_ht_cap); - /* The nVidia CK804 chipset may have 2 HT MSI mappings. * MSI are supported if the MSI capability set in any of these mappings. */ @@ -2032,6 +2059,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, ht_enable_msi_mapping); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, + ht_enable_msi_mapping); + /* The P5N32-SLI Premium motherboard from Asus has a problem with msi * for the MCP55 NIC. It is not yet determined whether the msi problem * also affects other devices. As for now, turn off msi for this device. @@ -2048,11 +2078,105 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15, nvenet_msi_disable); -static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) +static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) { struct pci_dev *host_bridge; + int pos; + int i, dev_no; + int found = 0; + + dev_no = dev->devfn >> 3; + for (i = dev_no; i >= 0; i--) { + host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0)); + if (!host_bridge) + continue; + + pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); + if (pos != 0) { + found = 1; + break; + } + pci_dev_put(host_bridge); + } + + if (!found) + return; + + /* root did that ! */ + if (msi_ht_cap_enabled(host_bridge)) + goto out; + + ht_enable_msi_mapping(dev); + +out: + pci_dev_put(host_bridge); +} + +static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) +{ int pos, ttl = 48; + pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); + while (pos && ttl--) { + u8 flags; + + if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, + &flags) == 0) { + dev_info(&dev->dev, "Disabling HT MSI Mapping\n"); + + pci_write_config_byte(dev, pos + HT_MSI_FLAGS, + flags & ~HT_MSI_FLAGS_ENABLE); + } + pos = pci_find_next_ht_capability(dev, pos, + HT_CAPTYPE_MSI_MAPPING); + } +} + +static int __devinit ht_check_msi_mapping(struct pci_dev *dev) +{ + int pos, ttl = 48; + int found = 0; + + /* check if there is HT MSI cap or enabled on this device */ + pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); + while (pos && ttl--) { + u8 flags; + + if (found < 1) + found = 1; + if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, + &flags) == 0) { + if (flags & HT_MSI_FLAGS_ENABLE) { + if (found < 2) { + found = 2; + break; + } + } + } + pos = pci_find_next_ht_capability(dev, pos, + HT_CAPTYPE_MSI_MAPPING); + } + + return found; +} + +static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) +{ + struct pci_dev *host_bridge; + int pos; + int found; + + /* Enabling HT MSI mapping on this device breaks MCP51 */ + if (dev->device == 0x270) + return; + + /* check if there is HT MSI cap or enabled on this device */ + found = ht_check_msi_mapping(dev); + + /* no HT MSI CAP */ + if (found == 0) + return; + /* * HT MSI mapping should be disabled on devices that are below * a non-Hypertransport host bridge. Locate the host bridge... @@ -2067,24 +2191,19 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); if (pos != 0) { /* Host bridge is to HT */ - ht_enable_msi_mapping(dev); + if (found == 1) { + /* it is not enabled, try to enable it */ + nv_ht_enable_msi_mapping(dev); + } return; } - /* Host bridge is not to HT, disable HT MSI mapping on this device */ - pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); - while (pos && ttl--) { - u8 flags; + /* HT MSI is not enabled */ + if (found == 1) + return; - if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, - &flags) == 0) { - dev_info(&dev->dev, "Disabling HT MSI mapping"); - pci_write_config_byte(dev, pos + HT_MSI_FLAGS, - flags & ~HT_MSI_FLAGS_ENABLE); - } - pos = pci_find_next_ht_capability(dev, pos, - HT_CAPTYPE_MSI_MAPPING); - } + /* Host bridge is not to HT, disable HT MSI mapping on this device */ + ht_disable_msi_mapping(dev); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b3866ad5022..3608081bc3e 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -15,8 +15,7 @@ menuconfig X86_PLATFORM_DEVICES if X86_PLATFORM_DEVICES config ACER_WMI - tristate "Acer WMI Laptop Extras (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Acer WMI Laptop Extras" depends on ACPI depends on LEDS_CLASS depends on NEW_LEDS @@ -39,9 +38,9 @@ config ASUS_LAPTOP tristate "Asus Laptop Extras (EXPERIMENTAL)" depends on ACPI depends on EXPERIMENTAL && !ACPI_ASUS - depends on LEDS_CLASS - depends on NEW_LEDS - depends on BACKLIGHT_CLASS_DEVICE + select LEDS_CLASS + select NEW_LEDS + select BACKLIGHT_CLASS_DEVICE depends on INPUT ---help--- This is the new Linux driver for Asus laptops. It may also support some @@ -185,11 +184,11 @@ config SONYPI_COMPAT config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on ACPI + depends on INPUT select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE select HWMON select NVRAM - select INPUT select NEW_LEDS select LEDS_CLASS select NET @@ -315,9 +314,8 @@ config EEEPC_LAPTOP config ACPI_WMI - tristate "WMI (EXPERIMENTAL)" + tristate "WMI" depends on ACPI - depends on EXPERIMENTAL help This driver adds support for the ACPI-WMI (Windows Management Instrumentation) mapper device (PNP0C14) found on some systems. diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 94c9f911824..a6a42e8c060 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1026,7 +1026,7 @@ static void acer_rfkill_exit(void) kfree(wireless_rfkill->data); rfkill_unregister(wireless_rfkill); if (has_cap(ACER_CAP_BLUETOOTH)) { - kfree(wireless_rfkill->data); + kfree(bluetooth_rfkill->data); rfkill_unregister(bluetooth_rfkill); } return; @@ -1297,7 +1297,7 @@ static int __init acer_wmi_init(void) set_quirks(); - if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { + if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { interface->capability &= ~ACER_CAP_BRIGHTNESS; printk(ACER_INFO "Brightness must be controlled by " "generic video driver\n"); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 56af6cf385b..eeafc6c0160 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -815,6 +815,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; /* TODO Find a better way to handle events count. */ if (!hotk) @@ -832,9 +833,11 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } + count = hotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(hotk->device, event, count); acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, dev_name(&hotk->device->dev), event, - hotk->event_count[event % 128]++); + count); if (hotk->inputdev) { key = asus_get_entry_by_scancode(event); diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 786ed8661cb..6f54fd1757c 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -557,13 +557,17 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; + if (!ehotk) return; if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); + count = ehotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(ehotk->device, event, count); acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, dev_name(&ehotk->device->dev), event, - ehotk->event_count[event % 128]++); + count); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index bcbc05107ba..d2433204a40 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -7532,7 +7532,7 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); * if it is not there yet. */ #define IBM_BIOS_MODULE_ALIAS(__type) \ - MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") + MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*") /* Non-ancient thinkpads */ MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); @@ -7541,9 +7541,9 @@ MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); /* Ancient thinkpad BIOSes have to be identified by * BIOS type or model number, and there are far less * BIOS types than model numbers... */ -IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); -IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); -IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); +IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]"); +IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]"); +IBM_BIOS_MODULE_ALIAS("K[UX-Z]"); MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); MODULE_DESCRIPTION(TPACPI_DESC); diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 8a8b377712c..2f269e117b8 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -708,7 +708,7 @@ static int __init acpi_wmi_add(struct acpi_device *device) static int __init acpi_wmi_init(void) { - acpi_status result; + int result; INIT_LIST_HEAD(&wmi_blocks.list); diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 1d768928e0b..a52d4a11652 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c @@ -180,10 +180,13 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) di->empty_uAh = battery_interpolate(scale, di->temp_C / 10); di->empty_uAh *= 1000; /* convert to µAh */ - /* From Maxim Application Note 131: remaining capacity = - * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */ - di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) / - (di->full_active_uAh - di->empty_uAh); + if (di->full_active_uAh == di->empty_uAh) + di->rem_capacity = 0; + else + /* From Maxim Application Note 131: remaining capacity = + * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */ + di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) / + (di->full_active_uAh - di->empty_uAh); if (di->rem_capacity < 0) di->rem_capacity = 0; diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index f08e169ba1b..7e30e5f6e03 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -129,7 +129,7 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status) bp->waiting = 1; add_wait_queue(&bp->wq, &wait); while (limit-- > 0) { - unsigned long val; + long val; val = wait_event_interruptible_timeout( bp->wq, diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index a9a9893a5f9..e6d1fc8c54f 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -38,9 +38,6 @@ #include <linux/string.h> #include <linux/genhd.h> #include <linux/blkdev.h> - -#define MAJOR_NR JSFD_MAJOR - #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 29dc735e1a2..124f660a038 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -51,6 +51,7 @@ MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@sk MODULE_DESCRIPTION("OPENPROM Configuration Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); +MODULE_ALIAS_MISCDEV(SUN_OPENPROM_MINOR); /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h index fde6e4c634e..a7cf550b9cc 100644 --- a/drivers/scsi/cxgb3i/cxgb3i.h +++ b/drivers/scsi/cxgb3i/cxgb3i.h @@ -20,6 +20,7 @@ #include <linux/list.h> #include <linux/netdevice.h> #include <linux/scatterlist.h> +#include <linux/skbuff.h> #include <scsi/libiscsi_tcp.h> /* from cxgb3 LLD */ @@ -113,6 +114,26 @@ struct cxgb3i_endpoint { struct cxgb3i_conn *cconn; }; +/** + * struct cxgb3i_task_data - private iscsi task data + * + * @nr_frags: # of coalesced page frags (from scsi sgl) + * @frags: coalesced page frags (from scsi sgl) + * @skb: tx pdu skb + * @offset: data offset for the next pdu + * @count: max. possible pdu payload + * @sgoffset: offset to the first sg entry for a given offset + */ +#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512) +struct cxgb3i_task_data { + unsigned short nr_frags; + skb_frag_t frags[MAX_PDU_FRAGS]; + struct sk_buff *skb; + unsigned int offset; + unsigned int count; + unsigned int sgoffset; +}; + int cxgb3i_iscsi_init(void); void cxgb3i_iscsi_cleanup(void); diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 08f3a09d923..a83d36e4926 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -639,10 +639,11 @@ static int ddp_init(struct t3cdev *tdev) write_unlock(&cxgb3i_ddp_rwlock); ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x " - "pkt %u,%u.\n", + "pkt %u/%u, %u/%u.\n", ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits, ddp->idx_mask, ddp->rsvd_tag_mask, - ddp->max_txsz, ddp->max_rxsz); + ddp->max_txsz, uinfo.max_txsz, + ddp->max_rxsz, uinfo.max_rxsz); return 0; free_ddp_map: @@ -654,8 +655,8 @@ free_ddp_map: * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource * @tdev: t3cdev adapter * @tformat: tag format - * @txsz: max tx pkt size, filled in by this func. - * @rxsz: max rx pkt size, filled in by this func. + * @txsz: max tx pdu payload size, filled in by this func. + * @rxsz: max rx pdu payload size, filled in by this func. * initialize the ddp pagepod manager for a given adapter if needed and * setup the tag format for a given iscsi entity */ @@ -685,10 +686,12 @@ int cxgb3i_adapter_ddp_init(struct t3cdev *tdev, tformat->sw_bits, tformat->rsvd_bits, tformat->rsvd_shift, tformat->rsvd_mask); - *txsz = ddp->max_txsz; - *rxsz = ddp->max_rxsz; - ddp_log_info("ddp max pkt size: %u, %u.\n", - ddp->max_txsz, ddp->max_rxsz); + *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, + ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN); + *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, + ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN); + ddp_log_info("max payload size: %u/%u, %u/%u.\n", + *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz); return 0; } EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init); diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 5c7c4d95c49..3faae7831c8 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h @@ -13,6 +13,8 @@ #ifndef __CXGB3I_ULP2_DDP_H__ #define __CXGB3I_ULP2_DDP_H__ +#include <linux/vmalloc.h> + /** * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity * @@ -85,8 +87,9 @@ struct cxgb3i_ddp_info { struct sk_buff **gl_skb; }; +#define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */ #define ULP2_MAX_PKT_SIZE 16224 -#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_MAX) +#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN) #define PPOD_PAGES_MAX 4 #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */ diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c index 091ecb4d9f3..1ce9f244e46 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_init.c +++ b/drivers/scsi/cxgb3i/cxgb3i_init.c @@ -12,8 +12,8 @@ #include "cxgb3i.h" #define DRV_MODULE_NAME "cxgb3i" -#define DRV_MODULE_VERSION "1.0.0" -#define DRV_MODULE_RELDATE "Jun. 1, 2008" +#define DRV_MODULE_VERSION "1.0.1" +#define DRV_MODULE_RELDATE "Jan. 2009" static char version[] = "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index d83464b9b3f..fa2a44f37b3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -364,7 +364,8 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, cmds_max, - sizeof(struct iscsi_tcp_task), + sizeof(struct iscsi_tcp_task) + + sizeof(struct cxgb3i_task_data), initial_cmdsn, ISCSI_MAX_TARGET); if (!cls_session) return NULL; @@ -402,17 +403,15 @@ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct cxgb3i_conn *cconn = tcp_conn->dd_data; - unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, - cconn->hba->snic->tx_max_size - - ISCSI_PDU_NONPAYLOAD_MAX); + unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM); + max = min(cconn->hba->snic->tx_max_size, max); if (conn->max_xmit_dlength) - conn->max_xmit_dlength = min_t(unsigned int, - conn->max_xmit_dlength, max); + conn->max_xmit_dlength = min(conn->max_xmit_dlength, max); else conn->max_xmit_dlength = max; align_pdu_size(conn->max_xmit_dlength); - cxgb3i_log_info("conn 0x%p, max xmit %u.\n", + cxgb3i_api_debug("conn 0x%p, max xmit %u.\n", conn, conn->max_xmit_dlength); return 0; } @@ -427,9 +426,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct cxgb3i_conn *cconn = tcp_conn->dd_data; - unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, - cconn->hba->snic->rx_max_size - - ISCSI_PDU_NONPAYLOAD_MAX); + unsigned int max = cconn->hba->snic->rx_max_size; align_pdu_size(max); if (conn->max_recv_dlength) { @@ -439,8 +436,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) conn->max_recv_dlength, max); return -EINVAL; } - conn->max_recv_dlength = min_t(unsigned int, - conn->max_recv_dlength, max); + conn->max_recv_dlength = min(conn->max_recv_dlength, max); align_pdu_size(conn->max_recv_dlength); } else conn->max_recv_dlength = max; @@ -844,7 +840,7 @@ static struct scsi_host_template cxgb3i_host_template = { .proc_name = "cxgb3i", .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, - .can_queue = 128 * (ISCSI_DEF_XMIT_CMDS_MAX - 1), + .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index a865f1fefe8..de3b3b614cc 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -23,19 +23,19 @@ #include "cxgb3i_ddp.h" #ifdef __DEBUG_C3CN_CONN__ -#define c3cn_conn_debug cxgb3i_log_info +#define c3cn_conn_debug cxgb3i_log_debug #else #define c3cn_conn_debug(fmt...) #endif #ifdef __DEBUG_C3CN_TX__ -#define c3cn_tx_debug cxgb3i_log_debug +#define c3cn_tx_debug cxgb3i_log_debug #else #define c3cn_tx_debug(fmt...) #endif #ifdef __DEBUG_C3CN_RX__ -#define c3cn_rx_debug cxgb3i_log_debug +#define c3cn_rx_debug cxgb3i_log_debug #else #define c3cn_rx_debug(fmt...) #endif @@ -47,9 +47,9 @@ static int cxgb3_rcv_win = 256 * 1024; module_param(cxgb3_rcv_win, int, 0644); MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)"); -static int cxgb3_snd_win = 64 * 1024; +static int cxgb3_snd_win = 128 * 1024; module_param(cxgb3_snd_win, int, 0644); -MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=64KB)"); +MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)"); static int cxgb3_rx_credit_thres = 10 * 1024; module_param(cxgb3_rx_credit_thres, int, 0644); @@ -301,8 +301,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb) static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb, int flags) { - CXGB3_SKB_CB(skb)->seq = c3cn->write_seq; - CXGB3_SKB_CB(skb)->flags = flags; + skb_tcp_seq(skb) = c3cn->write_seq; + skb_flags(skb) = flags; __skb_queue_tail(&c3cn->write_queue, skb); } @@ -457,12 +457,9 @@ static unsigned int wrlen __read_mostly; * The number of WRs needed for an skb depends on the number of fragments * in the skb and whether it has any payload in its main body. This maps the * length of the gather list represented by an skb into the # of necessary WRs. - * - * The max. length of an skb is controlled by the max pdu size which is ~16K. - * Also, assume the min. fragment length is the sector size (512), then add - * extra fragment counts for iscsi bhs and payload padding. + * The extra two fragments are for iscsi bhs and payload padding. */ -#define SKB_WR_LIST_SIZE (16384/512 + 3) +#define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2) static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly; static void s3_init_wr_tab(unsigned int wr_len) @@ -485,7 +482,7 @@ static void s3_init_wr_tab(unsigned int wr_len) static inline void reset_wr_list(struct s3_conn *c3cn) { - c3cn->wr_pending_head = NULL; + c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL; } /* @@ -496,7 +493,7 @@ static inline void reset_wr_list(struct s3_conn *c3cn) static inline void enqueue_wr(struct s3_conn *c3cn, struct sk_buff *skb) { - skb_wr_data(skb) = NULL; + skb_tx_wr_next(skb) = NULL; /* * We want to take an extra reference since both us and the driver @@ -509,10 +506,22 @@ static inline void enqueue_wr(struct s3_conn *c3cn, if (!c3cn->wr_pending_head) c3cn->wr_pending_head = skb; else - skb_wr_data(skb) = skb; + skb_tx_wr_next(c3cn->wr_pending_tail) = skb; c3cn->wr_pending_tail = skb; } +static int count_pending_wrs(struct s3_conn *c3cn) +{ + int n = 0; + const struct sk_buff *skb = c3cn->wr_pending_head; + + while (skb) { + n += skb->csum; + skb = skb_tx_wr_next(skb); + } + return n; +} + static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn) { return c3cn->wr_pending_head; @@ -529,8 +538,8 @@ static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn) if (likely(skb)) { /* Don't bother clearing the tail */ - c3cn->wr_pending_head = skb_wr_data(skb); - skb_wr_data(skb) = NULL; + c3cn->wr_pending_head = skb_tx_wr_next(skb); + skb_tx_wr_next(skb) = NULL; } return skb; } @@ -543,13 +552,14 @@ static void purge_wr_queue(struct s3_conn *c3cn) } static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb, - int len) + int len, int req_completion) { struct tx_data_wr *req; skb_reset_transport_header(skb); req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req)); - req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)); + req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) | + (req_completion ? F_WR_COMPL : 0)); req->wr_lo = htonl(V_WR_TID(c3cn->tid)); req->sndseq = htonl(c3cn->snd_nxt); /* len includes the length of any HW ULP additions */ @@ -592,7 +602,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) if (unlikely(c3cn->state == C3CN_STATE_CONNECTING || c3cn->state == C3CN_STATE_CLOSE_WAIT_1 || - c3cn->state == C3CN_STATE_ABORTING)) { + c3cn->state >= C3CN_STATE_ABORTING)) { c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n", c3cn, c3cn->state); return 0; @@ -615,7 +625,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) if (c3cn->wr_avail < wrs_needed) { c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, " "wr %d < %u.\n", - c3cn, skb->len, skb->datalen, frags, + c3cn, skb->len, skb->data_len, frags, wrs_needed, c3cn->wr_avail); break; } @@ -627,20 +637,24 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) c3cn->wr_unacked += wrs_needed; enqueue_wr(c3cn, skb); - if (likely(CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_NEED_HDR)) { - len += ulp_extra_len(skb); - make_tx_data_wr(c3cn, skb, len); - c3cn->snd_nxt += len; - if ((req_completion - && c3cn->wr_unacked == wrs_needed) - || (CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_COMPL) - || c3cn->wr_unacked >= c3cn->wr_max / 2) { - struct work_request_hdr *wr = cplhdr(skb); + c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, " + "wr %d, left %u, unack %u.\n", + c3cn, skb->len, skb->data_len, frags, + wrs_needed, c3cn->wr_avail, c3cn->wr_unacked); + - wr->wr_hi |= htonl(F_WR_COMPL); + if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) { + if ((req_completion && + c3cn->wr_unacked == wrs_needed) || + (skb_flags(skb) & C3CB_FLAG_COMPL) || + c3cn->wr_unacked >= c3cn->wr_max / 2) { + req_completion = 1; c3cn->wr_unacked = 0; } - CXGB3_SKB_CB(skb)->flags &= ~C3CB_FLAG_NEED_HDR; + len += ulp_extra_len(skb); + make_tx_data_wr(c3cn, skb, len, req_completion); + c3cn->snd_nxt += len; + skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR; } total_size += skb->truesize; @@ -735,8 +749,11 @@ static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb) if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED))) /* upper layer has requested closing */ send_abort_req(c3cn); - else if (c3cn_push_tx_frames(c3cn, 1)) + else { + if (skb_queue_len(&c3cn->write_queue)) + c3cn_push_tx_frames(c3cn, 1); cxgb3i_conn_tx_open(c3cn); + } } static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, @@ -1082,8 +1099,8 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) return; } - CXGB3_SKB_CB(skb)->seq = ntohl(hdr_cpl->seq); - CXGB3_SKB_CB(skb)->flags = 0; + skb_tcp_seq(skb) = ntohl(hdr_cpl->seq); + skb_flags(skb) = 0; skb_reset_transport_header(skb); __skb_pull(skb, sizeof(struct cpl_iscsi_hdr)); @@ -1103,12 +1120,12 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) goto abort_conn; skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY; - skb_ulp_pdulen(skb) = ntohs(ddp_cpl.len); - skb_ulp_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); + skb_rx_pdulen(skb) = ntohs(ddp_cpl.len); + skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); status = ntohl(ddp_cpl.ddp_status); c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n", - skb, skb->len, skb_ulp_pdulen(skb), status); + skb, skb->len, skb_rx_pdulen(skb), status); if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT)) skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR; @@ -1126,7 +1143,7 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT)) skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED; - c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_ulp_pdulen(skb); + c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb); __pskb_trim(skb, len); __skb_queue_tail(&c3cn->receive_queue, skb); cxgb3i_conn_pdu_ready(c3cn); @@ -1151,12 +1168,27 @@ static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx) * Process an acknowledgment of WR completion. Advance snd_una and send the * next batch of work requests from the write queue. */ +static void check_wr_invariants(struct s3_conn *c3cn) +{ + int pending = count_pending_wrs(c3cn); + + if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max)) + cxgb3i_log_error("TID %u: credit imbalance: avail %u, " + "pending %u, total should be %u\n", + c3cn->tid, c3cn->wr_avail, pending, + c3cn->wr_max); +} + static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) { struct cpl_wr_ack *hdr = cplhdr(skb); unsigned int credits = ntohs(hdr->credits); u32 snd_una = ntohl(hdr->snd_una); + c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n", + credits, c3cn->wr_avail, c3cn->wr_unacked, + c3cn->tid, c3cn->state); + c3cn->wr_avail += credits; if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail) c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail; @@ -1171,6 +1203,17 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) break; } if (unlikely(credits < p->csum)) { + struct tx_data_wr *w = cplhdr(p); + cxgb3i_log_error("TID %u got %u WR credits need %u, " + "len %u, main body %u, frags %u, " + "seq # %u, ACK una %u, ACK nxt %u, " + "WR_AVAIL %u, WRs pending %u\n", + c3cn->tid, credits, p->csum, p->len, + p->len - p->data_len, + skb_shinfo(p)->nr_frags, + ntohl(w->sndseq), snd_una, + ntohl(hdr->snd_nxt), c3cn->wr_avail, + count_pending_wrs(c3cn) - credits); p->csum -= credits; break; } else { @@ -1180,15 +1223,24 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) } } - if (unlikely(before(snd_una, c3cn->snd_una))) + check_wr_invariants(c3cn); + + if (unlikely(before(snd_una, c3cn->snd_una))) { + cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK " + "snd_una %u\n", + c3cn->tid, snd_una, c3cn->snd_una); goto out_free; + } if (c3cn->snd_una != snd_una) { c3cn->snd_una = snd_una; dst_confirm(c3cn->dst_cache); } - if (skb_queue_len(&c3cn->write_queue) && c3cn_push_tx_frames(c3cn, 0)) + if (skb_queue_len(&c3cn->write_queue)) { + if (c3cn_push_tx_frames(c3cn, 0)) + cxgb3i_conn_tx_open(c3cn); + } else cxgb3i_conn_tx_open(c3cn); out_free: __kfree_skb(skb); @@ -1452,7 +1504,7 @@ static void init_offload_conn(struct s3_conn *c3cn, struct dst_entry *dst) { BUG_ON(c3cn->cdev != cdev); - c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs; + c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1; c3cn->wr_unacked = 0; c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst)); @@ -1671,9 +1723,17 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb) goto out_err; } - err = -EPIPE; if (c3cn->err) { c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err); + err = -EPIPE; + goto out_err; + } + + if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) { + c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n", + c3cn, c3cn->write_seq, c3cn->snd_una, + cxgb3_snd_win); + err = -EAGAIN; goto out_err; } diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h index d23156907ff..6344b9eb258 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.h +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h @@ -178,25 +178,33 @@ void cxgb3i_c3cn_release(struct s3_conn *); * @flag: see C3CB_FLAG_* below * @ulp_mode: ULP mode/submode of sk_buff * @seq: tcp sequence number - * @ddigest: pdu data digest - * @pdulen: recovered pdu length - * @wr_data: scratch area for tx wr */ +struct cxgb3_skb_rx_cb { + __u32 ddigest; /* data digest */ + __u32 pdulen; /* recovered pdu length */ +}; + +struct cxgb3_skb_tx_cb { + struct sk_buff *wr_next; /* next wr */ +}; + struct cxgb3_skb_cb { __u8 flags; __u8 ulp_mode; __u32 seq; - __u32 ddigest; - __u32 pdulen; - struct sk_buff *wr_data; + union { + struct cxgb3_skb_rx_cb rx; + struct cxgb3_skb_tx_cb tx; + }; }; #define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0])) - +#define skb_flags(skb) (CXGB3_SKB_CB(skb)->flags) #define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode) -#define skb_ulp_ddigest(skb) (CXGB3_SKB_CB(skb)->ddigest) -#define skb_ulp_pdulen(skb) (CXGB3_SKB_CB(skb)->pdulen) -#define skb_wr_data(skb) (CXGB3_SKB_CB(skb)->wr_data) +#define skb_tcp_seq(skb) (CXGB3_SKB_CB(skb)->seq) +#define skb_rx_ddigest(skb) (CXGB3_SKB_CB(skb)->rx.ddigest) +#define skb_rx_pdulen(skb) (CXGB3_SKB_CB(skb)->rx.pdulen) +#define skb_tx_wr_next(skb) (CXGB3_SKB_CB(skb)->tx.wr_next) enum c3cb_flags { C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */ @@ -217,6 +225,7 @@ struct sge_opaque_hdr { /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ #define TX_HEADER_LEN \ (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr)) +#define SKB_TX_HEADROOM SKB_MAX_HEAD(TX_HEADER_LEN) /* * get and set private ip for iscsi traffic diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index ce7ce8c6094..17115c230d6 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c @@ -32,6 +32,10 @@ #define cxgb3i_tx_debug(fmt...) #endif +/* always allocate rooms for AHS */ +#define SKB_TX_PDU_HEADER_LEN \ + (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE) +static unsigned int skb_extra_headroom; static struct page *pad_page; /* @@ -146,12 +150,13 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc) void cxgb3i_conn_cleanup_task(struct iscsi_task *task) { - struct iscsi_tcp_task *tcp_task = task->dd_data; + struct cxgb3i_task_data *tdata = task->dd_data + + sizeof(struct iscsi_tcp_task); /* never reached the xmit task callout */ - if (tcp_task->dd_data) - kfree_skb(tcp_task->dd_data); - tcp_task->dd_data = NULL; + if (tdata->skb) + __kfree_skb(tdata->skb); + memset(tdata, 0, sizeof(struct cxgb3i_task_data)); /* MNC - Do we need a check in case this is called but * cxgb3i_conn_alloc_pdu has never been called on the task */ @@ -159,28 +164,102 @@ void cxgb3i_conn_cleanup_task(struct iscsi_task *task) iscsi_tcp_cleanup_task(task); } -/* - * We do not support ahs yet - */ +static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt, + unsigned int offset, unsigned int *off, + struct scatterlist **sgp) +{ + int i; + struct scatterlist *sg; + + for_each_sg(sgl, sg, sgcnt, i) { + if (offset < sg->length) { + *off = offset; + *sgp = sg; + return 0; + } + offset -= sg->length; + } + return -EFAULT; +} + +static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, + unsigned int dlen, skb_frag_t *frags, + int frag_max) +{ + unsigned int datalen = dlen; + unsigned int sglen = sg->length - sgoffset; + struct page *page = sg_page(sg); + int i; + + i = 0; + do { + unsigned int copy; + + if (!sglen) { + sg = sg_next(sg); + if (!sg) { + cxgb3i_log_error("%s, sg NULL, len %u/%u.\n", + __func__, datalen, dlen); + return -EINVAL; + } + sgoffset = 0; + sglen = sg->length; + page = sg_page(sg); + + } + copy = min(datalen, sglen); + if (i && page == frags[i - 1].page && + sgoffset + sg->offset == + frags[i - 1].page_offset + frags[i - 1].size) { + frags[i - 1].size += copy; + } else { + if (i >= frag_max) { + cxgb3i_log_error("%s, too many pages %u, " + "dlen %u.\n", __func__, + frag_max, dlen); + return -EINVAL; + } + + frags[i].page = page; + frags[i].page_offset = sg->offset + sgoffset; + frags[i].size = copy; + i++; + } + datalen -= copy; + sgoffset += copy; + sglen -= copy; + } while (datalen); + + return i; +} + int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) { + struct iscsi_conn *conn = task->conn; struct iscsi_tcp_task *tcp_task = task->dd_data; - struct sk_buff *skb; + struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task); + struct scsi_cmnd *sc = task->sc; + int headroom = SKB_TX_PDU_HEADER_LEN; + tcp_task->dd_data = tdata; task->hdr = NULL; - /* always allocate rooms for AHS */ - skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + - TX_HEADER_LEN, GFP_ATOMIC); - if (!skb) + + /* write command, need to send data pdus */ + if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT || + (opcode == ISCSI_OP_SCSI_CMD && + (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE)))) + headroom += min(skb_extra_headroom, conn->max_xmit_dlength); + + tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC); + if (!tdata->skb) return -ENOMEM; + skb_reserve(tdata->skb, TX_HEADER_LEN); cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n", - task, opcode, skb); + task, opcode, tdata->skb); - tcp_task->dd_data = skb; - skb_reserve(skb, TX_HEADER_LEN); - task->hdr = (struct iscsi_hdr *)skb->data; - task->hdr_max = sizeof(struct iscsi_hdr); + task->hdr = (struct iscsi_hdr *)tdata->skb->data; + task->hdr_max = SKB_TX_PDU_HEADER_LEN; /* data_out uses scsi_cmd's itt */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) @@ -192,13 +271,13 @@ int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, unsigned int count) { - struct iscsi_tcp_task *tcp_task = task->dd_data; - struct sk_buff *skb = tcp_task->dd_data; struct iscsi_conn *conn = task->conn; - struct page *pg; + struct iscsi_tcp_task *tcp_task = task->dd_data; + struct cxgb3i_task_data *tdata = tcp_task->dd_data; + struct sk_buff *skb = tdata->skb; unsigned int datalen = count; int i, padlen = iscsi_padding(count); - skb_frag_t *frag; + struct page *pg; cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n", task, task->sc, offset, count, skb); @@ -209,90 +288,94 @@ int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, return 0; if (task->sc) { - struct scatterlist *sg; - struct scsi_data_buffer *sdb; - unsigned int sgoffset = offset; - struct page *sgpg; - unsigned int sglen; - - sdb = scsi_out(task->sc); - sg = sdb->table.sgl; - - for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { - cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n", - i, sg_page(sg), sg->length, sg->offset); - - if (sgoffset < sg->length) - break; - sgoffset -= sg->length; + struct scsi_data_buffer *sdb = scsi_out(task->sc); + struct scatterlist *sg = NULL; + int err; + + tdata->offset = offset; + tdata->count = count; + err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents, + tdata->offset, &tdata->sgoffset, &sg); + if (err < 0) { + cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n", + sdb->table.nents, tdata->offset, + sdb->length); + return err; } - sgpg = sg_page(sg); - sglen = sg->length - sgoffset; - - do { - int j = skb_shinfo(skb)->nr_frags; - unsigned int copy; - - if (!sglen) { - sg = sg_next(sg); - sgpg = sg_page(sg); - sgoffset = 0; - sglen = sg->length; - ++i; + err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count, + tdata->frags, MAX_PDU_FRAGS); + if (err < 0) { + cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n", + sdb->table.nents, tdata->offset, + tdata->count); + return err; + } + tdata->nr_frags = err; + + if (tdata->nr_frags > MAX_SKB_FRAGS || + (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) { + char *dst = skb->data + task->hdr_len; + skb_frag_t *frag = tdata->frags; + + /* data fits in the skb's headroom */ + for (i = 0; i < tdata->nr_frags; i++, frag++) { + char *src = kmap_atomic(frag->page, + KM_SOFTIRQ0); + + memcpy(dst, src+frag->page_offset, frag->size); + dst += frag->size; + kunmap_atomic(src, KM_SOFTIRQ0); } - copy = min(sglen, datalen); - if (j && skb_can_coalesce(skb, j, sgpg, - sg->offset + sgoffset)) { - skb_shinfo(skb)->frags[j - 1].size += copy; - } else { - get_page(sgpg); - skb_fill_page_desc(skb, j, sgpg, - sg->offset + sgoffset, copy); + if (padlen) { + memset(dst, 0, padlen); + padlen = 0; } - sgoffset += copy; - sglen -= copy; - datalen -= copy; - } while (datalen); + skb_put(skb, count + padlen); + } else { + /* data fit into frag_list */ + for (i = 0; i < tdata->nr_frags; i++) + get_page(tdata->frags[i].page); + + memcpy(skb_shinfo(skb)->frags, tdata->frags, + sizeof(skb_frag_t) * tdata->nr_frags); + skb_shinfo(skb)->nr_frags = tdata->nr_frags; + skb->len += count; + skb->data_len += count; + skb->truesize += count; + } + } else { pg = virt_to_page(task->data); - while (datalen) { - i = skb_shinfo(skb)->nr_frags; - frag = &skb_shinfo(skb)->frags[i]; - - get_page(pg); - frag->page = pg; - frag->page_offset = 0; - frag->size = min((unsigned int)PAGE_SIZE, datalen); - - skb_shinfo(skb)->nr_frags++; - datalen -= frag->size; - pg++; - } + get_page(pg); + skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data), + count); + skb->len += count; + skb->data_len += count; + skb->truesize += count; } if (padlen) { i = skb_shinfo(skb)->nr_frags; - frag = &skb_shinfo(skb)->frags[i]; - frag->page = pad_page; - frag->page_offset = 0; - frag->size = padlen; - skb_shinfo(skb)->nr_frags++; + get_page(pad_page); + skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0, + padlen); + + skb->data_len += padlen; + skb->truesize += padlen; + skb->len += padlen; } - datalen = count + padlen; - skb->data_len += datalen; - skb->truesize += datalen; - skb->len += datalen; return 0; } int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) { - struct iscsi_tcp_task *tcp_task = task->dd_data; - struct sk_buff *skb = tcp_task->dd_data; struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; struct cxgb3i_conn *cconn = tcp_conn->dd_data; + struct iscsi_tcp_task *tcp_task = task->dd_data; + struct cxgb3i_task_data *tdata = tcp_task->dd_data; + struct sk_buff *skb = tdata->skb; unsigned int datalen; int err; @@ -300,13 +383,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) return 0; datalen = skb->data_len; - tcp_task->dd_data = NULL; + tdata->skb = NULL; err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb); - cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", - task, skb, skb->len, skb->data_len, err); if (err > 0) { int pdulen = err; + cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", + task, skb, skb->len, skb->data_len, err); + if (task->conn->hdrdgst_en) pdulen += ISCSI_DIGEST_SIZE; if (datalen && task->conn->datadgst_en) @@ -325,12 +409,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) return err; } /* reset skb to send when we are called again */ - tcp_task->dd_data = skb; + tdata->skb = skb; return -EAGAIN; } int cxgb3i_pdu_init(void) { + if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS)) + skb_extra_headroom = SKB_TX_HEADROOM; pad_page = alloc_page(GFP_KERNEL); if (!pad_page) return -ENOMEM; @@ -366,7 +452,9 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) skb = skb_peek(&c3cn->receive_queue); while (!err && skb) { __skb_unlink(skb, &c3cn->receive_queue); - read += skb_ulp_pdulen(skb); + read += skb_rx_pdulen(skb); + cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n", + conn, c3cn, skb, skb_rx_pdulen(skb)); err = cxgb3i_conn_read_pdu_skb(conn, skb); __kfree_skb(skb); skb = skb_peek(&c3cn->receive_queue); @@ -377,6 +465,11 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) cxgb3i_c3cn_rx_credits(c3cn, read); } conn->rxdata_octets += read; + + if (err) { + cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } } void cxgb3i_conn_tx_open(struct s3_conn *c3cn) diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h index a3f685cc236..0770b23d90d 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.h @@ -53,7 +53,7 @@ struct cpl_rx_data_ddp_norss { #define ULP2_FLAG_DCRC_ERROR 0x20 #define ULP2_FLAG_PAD_ERROR 0x40 -void cxgb3i_conn_closing(struct s3_conn *); +void cxgb3i_conn_closing(struct s3_conn *c3cn); void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn); void cxgb3i_conn_tx_open(struct s3_conn *c3cn); #endif diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index bf7fe6fc082..8862758006c 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -33,19 +33,19 @@ static LIST_HEAD(fcoe_transports); static DEFINE_MUTEX(fcoe_transports_lock); /** - * fcoe_transport_default - returns ptr to the default transport fcoe_sw - **/ + * fcoe_transport_default() - Returns ptr to the default transport fcoe_sw + */ struct fcoe_transport *fcoe_transport_default(void) { return &fcoe_sw_transport; } /** - * fcoe_transport_to_pcidev - get the pci dev from a netdev + * fcoe_transport_to_pcidev() - get the pci dev from a netdev * @netdev: the netdev that pci dev will be retrived from * * Returns: NULL or the corrsponding pci_dev - **/ + */ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) { if (!netdev->dev.parent) @@ -54,18 +54,17 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) } /** - * fcoe_transport_device_lookup - find out netdev is managed by the - * transport - * assign a transport to a device + * fcoe_transport_device_lookup() - Lookup a transport * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ -static struct fcoe_transport_internal *fcoe_transport_device_lookup( - struct fcoe_transport *t, struct net_device *netdev) + */ +static struct fcoe_transport_internal * +fcoe_transport_device_lookup(struct fcoe_transport *t, + struct net_device *netdev) { struct fcoe_transport_internal *ti; @@ -81,14 +80,14 @@ static struct fcoe_transport_internal *fcoe_transport_device_lookup( return NULL; } /** - * fcoe_transport_device_add - assign a transport to a device + * fcoe_transport_device_add() - Assign a transport to a device * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_add(struct fcoe_transport *t, struct net_device *netdev) { @@ -123,14 +122,14 @@ static int fcoe_transport_device_add(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove - remove a device from its transport + * fcoe_transport_device_remove() - Remove a device from its transport * @netdev: the netdev the transport to be attached to * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_remove(struct fcoe_transport *t, struct net_device *netdev) { @@ -155,13 +154,13 @@ static int fcoe_transport_device_remove(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove_all - remove all from transport devlist + * fcoe_transport_device_remove_all() - Remove all from transport devlist * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) { struct fcoe_transport_internal *ti, *tmp; @@ -175,18 +174,18 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) } /** - * fcoe_transport_match - use the bus device match function to match the hw - * @t: the fcoe transport - * @netdev: + * fcoe_transport_match() - Use the bus device match function to match the hw + * @t: The fcoe transport to check + * @netdev: The netdev to match against * - * This function is used to check if the givne transport wants to manage the + * This function is used to check if the given transport wants to manage the * input netdev. if the transports implements the match function, it will be * called, o.w. we just compare the pci vendor and device id. * * Returns: true for match up - **/ + */ static bool fcoe_transport_match(struct fcoe_transport *t, - struct net_device *netdev) + struct net_device *netdev) { /* match transport by vendor and device id */ struct pci_dev *pci; @@ -210,17 +209,17 @@ static bool fcoe_transport_match(struct fcoe_transport *t, } /** - * fcoe_transport_lookup - check if the transport is already registered + * fcoe_transport_lookup() - Check if the transport is already registered * @t: the transport to be looked up * * This compares the parent device (pci) vendor and device id * * Returns: NULL if not found * - * TODO - return default sw transport if no other transport is found - **/ -static struct fcoe_transport *fcoe_transport_lookup( - struct net_device *netdev) + * TODO: return default sw transport if no other transport is found + */ +static struct fcoe_transport * +fcoe_transport_lookup(struct net_device *netdev) { struct fcoe_transport *t; @@ -239,11 +238,11 @@ static struct fcoe_transport *fcoe_transport_lookup( } /** - * fcoe_transport_register - adds a fcoe transport to the fcoe transports list + * fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list * @t: ptr to the fcoe transport to be added * * Returns: 0 for success - **/ + */ int fcoe_transport_register(struct fcoe_transport *t) { struct fcoe_transport *tt; @@ -259,9 +258,6 @@ int fcoe_transport_register(struct fcoe_transport *t) list_add_tail(&t->list, &fcoe_transports); mutex_unlock(&fcoe_transports_lock); - mutex_init(&t->devlock); - INIT_LIST_HEAD(&t->devlist); - printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name); return 0; @@ -269,11 +265,11 @@ int fcoe_transport_register(struct fcoe_transport *t) EXPORT_SYMBOL_GPL(fcoe_transport_register); /** - * fcoe_transport_unregister - remove the tranport fro the fcoe transports list + * fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list * @t: ptr to the fcoe transport to be removed * * Returns: 0 for success - **/ + */ int fcoe_transport_unregister(struct fcoe_transport *t) { struct fcoe_transport *tt, *tmp; @@ -294,8 +290,8 @@ int fcoe_transport_unregister(struct fcoe_transport *t) } EXPORT_SYMBOL_GPL(fcoe_transport_unregister); -/* - * fcoe_load_transport_driver - load an offload driver by alias name +/** + * fcoe_load_transport_driver() - Load an offload driver by alias name * @netdev: the target net device * * Requests for an offload driver module as the fcoe transport, if fails, it @@ -307,7 +303,7 @@ EXPORT_SYMBOL_GPL(fcoe_transport_unregister); * 3. pure hw fcoe hba may not have netdev * * Returns: 0 for success - **/ + */ int fcoe_load_transport_driver(struct net_device *netdev) { struct pci_dev *pci; @@ -335,14 +331,14 @@ int fcoe_load_transport_driver(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_load_transport_driver); /** - * fcoe_transport_attach - load transport to fcoe + * fcoe_transport_attach() - Load transport to fcoe * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ int fcoe_transport_attach(struct net_device *netdev) { struct fcoe_transport *t; @@ -373,11 +369,11 @@ int fcoe_transport_attach(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_attach); /** - * fcoe_transport_release - unload transport from fcoe + * fcoe_transport_release() - Unload transport from fcoe * @netdev: the net device on which fcoe is to be released * * Returns: 0 for success - **/ + */ int fcoe_transport_release(struct net_device *netdev) { struct fcoe_transport *t; @@ -410,12 +406,12 @@ int fcoe_transport_release(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_release); /** - * fcoe_transport_init - initializes fcoe transport layer + * fcoe_transport_init() - Initializes fcoe transport layer * * This prepares for the fcoe transport layer * * Returns: none - **/ + */ int __init fcoe_transport_init(void) { INIT_LIST_HEAD(&fcoe_transports); @@ -424,12 +420,13 @@ int __init fcoe_transport_init(void) } /** - * fcoe_transport_exit - cleans up the fcoe transport layer + * fcoe_transport_exit() - Cleans up the fcoe transport layer + * * This cleans up the fcoe transport layer. removing any transport on the list, * note that the transport destroy func is not called here. * * Returns: none - **/ + */ int __exit fcoe_transport_exit(void) { struct fcoe_transport *t, *tmp; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index dc4cd5e2576..da210eba194 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -104,19 +104,19 @@ static struct scsi_host_template fcoe_sw_shost_template = { .max_sectors = 0xffff, }; -/* - * fcoe_sw_lport_config - sets up the fc_lport +/** + * fcoe_sw_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport * @shost: ptr to the parent scsi host * * Returns: 0 for success - * */ static int fcoe_sw_lport_config(struct fc_lport *lp) { int i = 0; - lp->link_status = 0; + lp->link_up = 0; + lp->qfull = 0; lp->max_retry_count = 3; lp->e_d_tov = 2 * 1000; /* FC-FS default */ lp->r_a_tov = 2 * 2 * 1000; @@ -136,16 +136,14 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network - * related properties +/** + * fcoe_sw_netdev_config() - Set up netdev for SW FCoE * @lp : ptr to the fc_lport * @netdev : ptr to the associated netdevice struct * * Must be called after fcoe_sw_lport_config() as it will use lport mutex * * Returns : 0 for success - * */ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) { @@ -181,9 +179,8 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) if (fc_set_mfs(lp, mfs)) return -EINVAL; - lp->link_status = ~FC_PAUSE & ~FC_LINK_UP; if (!fcoe_link_ok(lp)) - lp->link_status |= FC_LINK_UP; + lp->link_up = 1; /* offload features support */ if (fc->real_dev->features & NETIF_F_SG) @@ -191,6 +188,7 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) skb_queue_head_init(&fc->fcoe_pending_queue); + fc->fcoe_pending_queue_active = 0; /* setup Source Mac Address */ memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr, @@ -224,16 +222,15 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) return 0; } -/* - * fcoe_sw_shost_config - sets up fc_lport->host +/** + * fcoe_sw_shost_config() - Sets up fc_lport->host * @lp : ptr to the fc_lport * @shost : ptr to the associated scsi host * @dev : device associated to scsi host * - * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config() + * Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config() * * Returns : 0 for success - * */ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, struct device *dev) @@ -261,8 +258,8 @@ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, return 0; } -/* - * fcoe_sw_em_config - allocates em for this lport +/** + * fcoe_sw_em_config() - allocates em for this lport * @lp: the port that em is to allocated for * * Returns : 0 on success @@ -279,8 +276,8 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_destroy - FCoE software HBA tear-down function +/** + * fcoe_sw_destroy() - FCoE software HBA tear-down function * @netdev: ptr to the associated net_device * * Returns: 0 if link is OK for use by FCoE. @@ -301,7 +298,7 @@ static int fcoe_sw_destroy(struct net_device *netdev) if (!lp) return -ENODEV; - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* Logout of the fabric */ fc_fabric_logoff(lp); @@ -353,8 +350,8 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = { .frame_send = fcoe_xmit, }; -/* - * fcoe_sw_create - this function creates the fcoe interface +/** + * fcoe_sw_create() - this function creates the fcoe interface * @netdev: pointer the associated netdevice * * Creates fc_lport struct and scsi_host for lport, configures lport @@ -440,8 +437,8 @@ out_host_put: return rc; } -/* - * fcoe_sw_match - the fcoe sw transport match function +/** + * fcoe_sw_match() - The FCoE SW transport match function * * Returns : false always */ @@ -461,8 +458,8 @@ struct fcoe_transport fcoe_sw_transport = { .device = 0xffff, }; -/* - * fcoe_sw_init - registers fcoe_sw_transport +/** + * fcoe_sw_init() - Registers fcoe_sw_transport * * Returns : 0 on success */ @@ -471,17 +468,22 @@ int __init fcoe_sw_init(void) /* attach to scsi transport */ scsi_transport_fcoe_sw = fc_attach_transport(&fcoe_sw_transport_function); + if (!scsi_transport_fcoe_sw) { printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n"); return -ENODEV; } + + mutex_init(&fcoe_sw_transport.devlock); + INIT_LIST_HEAD(&fcoe_sw_transport.devlist); + /* register sw transport */ fcoe_transport_register(&fcoe_sw_transport); return 0; } -/* - * fcoe_sw_exit - unregisters fcoe_sw_transport +/** + * fcoe_sw_exit() - Unregisters fcoe_sw_transport * * Returns : 0 on success */ diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index e419f486cdb..5548bf3bb58 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -49,6 +49,7 @@ static int debug_fcoe; #define FCOE_MAX_QUEUE_DEPTH 256 +#define FCOE_LOW_QUEUE_DEPTH 32 /* destination address mode */ #define FCOE_GW_ADDR_MODE 0x00 @@ -69,8 +70,6 @@ struct fcoe_percpu_s *fcoe_percpu[NR_CPUS]; /* Function Prototyes */ static int fcoe_check_wait_queue(struct fc_lport *); -static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *); -static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *); static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *); #ifdef CONFIG_HOTPLUG_CPU static int fcoe_cpu_callback(struct notifier_block *, ulong, void *); @@ -91,13 +90,13 @@ static struct notifier_block fcoe_cpu_notifier = { }; /** - * fcoe_create_percpu_data - creates the associated cpu data + * fcoe_create_percpu_data() - creates the associated cpu data * @cpu: index for the cpu where fcoe cpu data will be created * * create percpu stats block, from cpu add notifier * * Returns: none - **/ + */ static void fcoe_create_percpu_data(int cpu) { struct fc_lport *lp; @@ -115,13 +114,13 @@ static void fcoe_create_percpu_data(int cpu) } /** - * fcoe_destroy_percpu_data - destroys the associated cpu data + * fcoe_destroy_percpu_data() - destroys the associated cpu data * @cpu: index for the cpu where fcoe cpu data will destroyed * * destroy percpu stats block called by cpu add/remove notifier * * Retuns: none - **/ + */ static void fcoe_destroy_percpu_data(int cpu) { struct fc_lport *lp; @@ -137,7 +136,7 @@ static void fcoe_destroy_percpu_data(int cpu) } /** - * fcoe_cpu_callback - fcoe cpu hotplug event callback + * fcoe_cpu_callback() - fcoe cpu hotplug event callback * @nfb: callback data block * @action: event triggering the callback * @hcpu: index for the cpu of this event @@ -145,7 +144,7 @@ static void fcoe_destroy_percpu_data(int cpu) * this creates or destroys per cpu data for fcoe * * Returns NOTIFY_OK always. - **/ + */ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -166,7 +165,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, #endif /* CONFIG_HOTPLUG_CPU */ /** - * fcoe_rcv - this is the fcoe receive function called by NET_RX_SOFTIRQ + * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ * @skb: the receive skb * @dev: associated net device * @ptype: context @@ -175,7 +174,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, * this function will receive the packet and build fc frame and pass it up * * Returns: 0 for success - **/ + */ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *olddev) { @@ -265,11 +264,11 @@ err2: EXPORT_SYMBOL_GPL(fcoe_rcv); /** - * fcoe_start_io - pass to netdev to start xmit for fcoe + * fcoe_start_io() - pass to netdev to start xmit for fcoe * @skb: the skb to be xmitted * * Returns: 0 for success - **/ + */ static inline int fcoe_start_io(struct sk_buff *skb) { int rc; @@ -283,12 +282,12 @@ static inline int fcoe_start_io(struct sk_buff *skb) } /** - * fcoe_get_paged_crc_eof - in case we need alloc a page for crc_eof + * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof * @skb: the skb to be xmitted * @tlen: total len * * Returns: 0 for success - **/ + */ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) { struct fcoe_percpu_s *fps; @@ -326,13 +325,12 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) } /** - * fcoe_fc_crc - calculates FC CRC in this fcoe skb + * fcoe_fc_crc() - calculates FC CRC in this fcoe skb * @fp: the fc_frame containg data to be checksummed * * This uses crc32() to calculate the crc for fc frame * Return : 32 bit crc - * - **/ + */ u32 fcoe_fc_crc(struct fc_frame *fp) { struct sk_buff *skb = fp_skb(fp); @@ -363,13 +361,12 @@ u32 fcoe_fc_crc(struct fc_frame *fp) EXPORT_SYMBOL_GPL(fcoe_fc_crc); /** - * fcoe_xmit - FCoE frame transmit function + * fcoe_xmit() - FCoE frame transmit function * @lp: the associated local port * @fp: the fc_frame to be transmitted * * Return : 0 for success - * - **/ + */ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) { int wlen, rc = 0; @@ -389,7 +386,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) WARN_ON((fr_len(fp) % sizeof(u32)) != 0); - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* * if it is a flogi then we need to learn gw-addr * and my own fcid @@ -439,7 +436,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (skb_is_nonlinear(skb)) { skb_frag_t *frag; if (fcoe_get_paged_crc_eof(skb, tlen)) { - kfree(skb); + kfree_skb(skb); return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; @@ -502,21 +499,22 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) rc = fcoe_start_io(skb); if (rc) { - fcoe_insert_wait_queue(lp, skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + __skb_queue_tail(&fc->fcoe_pending_queue, skb); + spin_unlock_bh(&fc->fcoe_pending_queue.lock); if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - fc_pause(lp); + lp->qfull = 1; } return 0; } EXPORT_SYMBOL_GPL(fcoe_xmit); -/* - * fcoe_percpu_receive_thread - recv thread per cpu +/** + * fcoe_percpu_receive_thread() - recv thread per cpu * @arg: ptr to the fcoe per cpu struct * * Return: 0 for success - * */ int fcoe_percpu_receive_thread(void *arg) { @@ -533,7 +531,7 @@ int fcoe_percpu_receive_thread(void *arg) struct fcoe_softc *fc; struct fcoe_hdr *hp; - set_user_nice(current, 19); + set_user_nice(current, -20); while (!kthread_should_stop()) { @@ -658,7 +656,7 @@ int fcoe_percpu_receive_thread(void *arg) } /** - * fcoe_recv_flogi - flogi receive function + * fcoe_recv_flogi() - flogi receive function * @fc: associated fcoe_softc * @fp: the recieved frame * @sa: the source address of this flogi @@ -667,7 +665,7 @@ int fcoe_percpu_receive_thread(void *arg) * mac address for the initiator, eitehr OUI based or GW based. * * Returns: none - **/ + */ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) { struct fc_frame_header *fh; @@ -715,32 +713,23 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) } /** - * fcoe_watchdog - fcoe timer callback + * fcoe_watchdog() - fcoe timer callback * @vp: * - * This checks the pending queue length for fcoe and put fcoe to be paused state + * This checks the pending queue length for fcoe and set lport qfull * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the * fcoe_hostlist. * * Returns: 0 for success - **/ + */ void fcoe_watchdog(ulong vp) { - struct fc_lport *lp; struct fcoe_softc *fc; - int paused = 0; read_lock(&fcoe_hostlist_lock); list_for_each_entry(fc, &fcoe_hostlist, list) { - lp = fc->lp; - if (lp) { - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - paused = 1; - if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) { - if (paused) - fc_unpause(lp); - } - } + if (fc->lp) + fcoe_check_wait_queue(fc->lp); } read_unlock(&fcoe_hostlist_lock); @@ -750,96 +739,64 @@ void fcoe_watchdog(ulong vp) /** - * fcoe_check_wait_queue - put the skb into fcoe pending xmit queue + * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * This empties the wait_queue, dequeue the head of the wait_queue queue * and calls fcoe_start_io() for each packet, if all skb have been - * transmitted, return 0 if a error occurs, then restore wait_queue and - * try again later. + * transmitted, return qlen or -1 if a error occurs, then restore + * wait_queue and try again later. * * The wait_queue is used when the skb transmit fails. skb will go * in the wait_queue which will be emptied by the time function OR * by the next skb transmit. * * Returns: 0 for success - **/ + */ static int fcoe_check_wait_queue(struct fc_lport *lp) { - int rc, unpause = 0; - int paused = 0; + struct fcoe_softc *fc = lport_priv(lp); struct sk_buff *skb; - struct fcoe_softc *fc; + int rc = -1; - fc = fcoe_softc(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); + if (fc->fcoe_pending_queue_active) + goto out; + fc->fcoe_pending_queue_active = 1; - /* - * is this interface paused? - */ - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - paused = 1; - if (fc->fcoe_pending_queue.qlen) { - while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { - spin_unlock_bh(&fc->fcoe_pending_queue.lock); - rc = fcoe_start_io(skb); - if (rc) { - fcoe_insert_wait_queue_head(lp, skb); - return rc; - } - spin_lock_bh(&fc->fcoe_pending_queue.lock); - } - if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH) - unpause = 1; - } - spin_unlock_bh(&fc->fcoe_pending_queue.lock); - if ((unpause) && (paused)) - fc_unpause(lp); - return fc->fcoe_pending_queue.qlen; -} - -/** - * fcoe_insert_wait_queue_head - puts skb to fcoe pending queue head - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - **/ -static void fcoe_insert_wait_queue_head(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; + while (fc->fcoe_pending_queue.qlen) { + /* keep qlen > 0 until fcoe_start_io succeeds */ + fc->fcoe_pending_queue.qlen++; + skb = __skb_dequeue(&fc->fcoe_pending_queue); - fc = fcoe_softc(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_head(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} + spin_unlock_bh(&fc->fcoe_pending_queue.lock); + rc = fcoe_start_io(skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); -/** - * fcoe_insert_wait_queue - put the skb into fcoe pending queue tail - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - **/ -static void fcoe_insert_wait_queue(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; + if (rc) { + __skb_queue_head(&fc->fcoe_pending_queue, skb); + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; + break; + } + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; + } - fc = fcoe_softc(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_tail(&fc->fcoe_pending_queue, skb); + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) + lp->qfull = 0; + fc->fcoe_pending_queue_active = 0; + rc = fc->fcoe_pending_queue.qlen; +out: spin_unlock_bh(&fc->fcoe_pending_queue.lock); + return rc; } /** - * fcoe_dev_setup - setup link change notification interface - * - **/ -static void fcoe_dev_setup(void) + * fcoe_dev_setup() - setup link change notification interface + */ +static void fcoe_dev_setup() { /* * here setup a interface specific wd time to @@ -849,15 +806,15 @@ static void fcoe_dev_setup(void) } /** - * fcoe_dev_setup - cleanup link change notification interface - **/ + * fcoe_dev_setup() - cleanup link change notification interface + */ static void fcoe_dev_cleanup(void) { unregister_netdevice_notifier(&fcoe_notifier); } /** - * fcoe_device_notification - netdev event notification callback + * fcoe_device_notification() - netdev event notification callback * @notifier: context of the notification * @event: type of event * @ptr: fixed array for output parsed ifname @@ -865,7 +822,7 @@ static void fcoe_dev_cleanup(void) * This function is called by the ethernet driver in case of link change event * * Returns: 0 for success - **/ + */ static int fcoe_device_notification(struct notifier_block *notifier, ulong event, void *ptr) { @@ -873,7 +830,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, struct net_device *real_dev = ptr; struct fcoe_softc *fc; struct fcoe_dev_stats *stats; - u16 new_status; + u32 new_link_up; u32 mfs; int rc = NOTIFY_OK; @@ -890,17 +847,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, goto out; } - new_status = lp->link_status; + new_link_up = lp->link_up; switch (event) { case NETDEV_DOWN: case NETDEV_GOING_DOWN: - new_status &= ~FC_LINK_UP; + new_link_up = 0; break; case NETDEV_UP: case NETDEV_CHANGE: - new_status &= ~FC_LINK_UP; - if (!fcoe_link_ok(lp)) - new_status |= FC_LINK_UP; + new_link_up = !fcoe_link_ok(lp); break; case NETDEV_CHANGEMTU: mfs = fc->real_dev->mtu - @@ -908,17 +863,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, sizeof(struct fcoe_crc_eof)); if (mfs >= FC_MIN_MAX_FRAME) fc_set_mfs(lp, mfs); - new_status &= ~FC_LINK_UP; - if (!fcoe_link_ok(lp)) - new_status |= FC_LINK_UP; + new_link_up = !fcoe_link_ok(lp); break; case NETDEV_REGISTER: break; default: FC_DBG("unknown event %ld call", event); } - if (lp->link_status != new_status) { - if ((new_status & FC_LINK_UP) == FC_LINK_UP) + if (lp->link_up != new_link_up) { + if (new_link_up) fc_linkup(lp); else { stats = lp->dev_stats[smp_processor_id()]; @@ -933,12 +886,12 @@ out: } /** - * fcoe_if_to_netdev - parse a name buffer to get netdev + * fcoe_if_to_netdev() - parse a name buffer to get netdev * @ifname: fixed array for output parsed ifname * @buffer: incoming buffer to be copied * * Returns: NULL or ptr to netdeive - **/ + */ static struct net_device *fcoe_if_to_netdev(const char *buffer) { char *cp; @@ -955,13 +908,13 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) } /** - * fcoe_netdev_to_module_owner - finds out the nic drive moddule of the netdev + * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev * @netdev: the target netdev * * Returns: ptr to the struct module, NULL for failure - **/ -static struct module *fcoe_netdev_to_module_owner( - const struct net_device *netdev) + */ +static struct module * +fcoe_netdev_to_module_owner(const struct net_device *netdev) { struct device *dev; @@ -979,12 +932,14 @@ static struct module *fcoe_netdev_to_module_owner( } /** - * fcoe_ethdrv_get - holds the nic driver module by try_module_get() for - * the corresponding netdev. + * fcoe_ethdrv_get() - Hold the Ethernet driver * @netdev: the target netdev * + * Holds the Ethernet driver module by try_module_get() for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_get(const struct net_device *netdev) { struct module *owner; @@ -999,12 +954,14 @@ static int fcoe_ethdrv_get(const struct net_device *netdev) } /** - * fcoe_ethdrv_get - releases the nic driver module by module_put for - * the corresponding netdev. + * fcoe_ethdrv_put() - Release the Ethernet driver * @netdev: the target netdev * + * Releases the Ethernet driver module by module_put for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_put(const struct net_device *netdev) { struct module *owner; @@ -1020,12 +977,12 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) } /** - * fcoe_destroy- handles the destroy from sysfs + * fcoe_destroy() - handles the destroy from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) { int rc; @@ -1058,12 +1015,12 @@ out_nodev: } /** - * fcoe_create - handles the create call from sysfs + * fcoe_create() - Handles the create call from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_create(const char *buffer, struct kernel_param *kp) { int rc; @@ -1104,8 +1061,8 @@ module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); __MODULE_PARM_TYPE(destroy, "string"); MODULE_PARM_DESC(destroy, "Destroy fcoe port"); -/* - * fcoe_link_ok - check if link is ok for the fc_lport +/** + * fcoe_link_ok() - Check if link is ok for the fc_lport * @lp: ptr to the fc_lport * * Any permanently-disqualifying conditions have been previously checked. @@ -1120,7 +1077,7 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port"); */ int fcoe_link_ok(struct fc_lport *lp) { - struct fcoe_softc *fc = fcoe_softc(lp); + struct fcoe_softc *fc = lport_priv(lp); struct net_device *dev = fc->real_dev; struct ethtool_cmd ecmd = { ETHTOOL_GSET }; int rc = 0; @@ -1149,9 +1106,8 @@ int fcoe_link_ok(struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_link_ok); -/* - * fcoe_percpu_clean - frees skb of the corresponding lport from the per - * cpu queue. +/** + * fcoe_percpu_clean() - Clear the pending skbs for an lport * @lp: the fc_lport */ void fcoe_percpu_clean(struct fc_lport *lp) @@ -1185,11 +1141,11 @@ void fcoe_percpu_clean(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_percpu_clean); /** - * fcoe_clean_pending_queue - dequeue skb and free it + * fcoe_clean_pending_queue() - Dequeue a skb and free it * @lp: the corresponding fc_lport * * Returns: none - **/ + */ void fcoe_clean_pending_queue(struct fc_lport *lp) { struct fcoe_softc *fc = lport_priv(lp); @@ -1206,21 +1162,21 @@ void fcoe_clean_pending_queue(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); /** - * libfc_host_alloc - allocate a Scsi_Host with room for the fc_lport + * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * * Returns: ptr to Scsi_Host - * TODO - to libfc? + * TODO: to libfc? */ -static inline struct Scsi_Host *libfc_host_alloc( - struct scsi_host_template *sht, int priv_size) +static inline struct Scsi_Host * +libfc_host_alloc(struct scsi_host_template *sht, int priv_size) { return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size); } /** - * fcoe_host_alloc - allocate a Scsi_Host with room for the fcoe_softc + * fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * @@ -1232,8 +1188,8 @@ struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *sht, int priv_size) } EXPORT_SYMBOL_GPL(fcoe_host_alloc); -/* - * fcoe_reset - resets the fcoe +/** + * fcoe_reset() - Resets the fcoe * @shost: shost the reset is from * * Returns: always 0 @@ -1246,8 +1202,8 @@ int fcoe_reset(struct Scsi_Host *shost) } EXPORT_SYMBOL_GPL(fcoe_reset); -/* - * fcoe_wwn_from_mac - converts 48-bit IEEE MAC address to 64-bit FC WWN. +/** + * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN. * @mac: mac address * @scheme: check port * @port: port indicator for converting @@ -1286,14 +1242,15 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], return wwn; } EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); -/* - * fcoe_hostlist_lookup_softc - find the corresponding lport by a given device + +/** + * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device * @device: this is currently ptr to net_device * * Returns: NULL or the located fcoe_softc */ -static struct fcoe_softc *fcoe_hostlist_lookup_softc( - const struct net_device *dev) +static struct fcoe_softc * +fcoe_hostlist_lookup_softc(const struct net_device *dev) { struct fcoe_softc *fc; @@ -1308,8 +1265,8 @@ static struct fcoe_softc *fcoe_hostlist_lookup_softc( return NULL; } -/* - * fcoe_hostlist_lookup - find the corresponding lport by netdev +/** + * fcoe_hostlist_lookup() - Find the corresponding lport by netdev * @netdev: ptr to net_device * * Returns: 0 for success @@ -1324,8 +1281,8 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) } EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup); -/* - * fcoe_hostlist_add - add a lport to lports list +/** + * fcoe_hostlist_add() - Add a lport to lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1336,7 +1293,7 @@ int fcoe_hostlist_add(const struct fc_lport *lp) fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); if (!fc) { - fc = fcoe_softc(lp); + fc = lport_priv(lp); write_lock_bh(&fcoe_hostlist_lock); list_add_tail(&fc->list, &fcoe_hostlist); write_unlock_bh(&fcoe_hostlist_lock); @@ -1345,8 +1302,8 @@ int fcoe_hostlist_add(const struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_hostlist_add); -/* - * fcoe_hostlist_remove - remove a lport from lports list +/** + * fcoe_hostlist_remove() - remove a lport from lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1366,12 +1323,12 @@ int fcoe_hostlist_remove(const struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_hostlist_remove); /** - * fcoe_libfc_config - sets up libfc related properties for lport + * fcoe_libfc_config() - sets up libfc related properties for lport * @lp: ptr to the fc_lport * @tt: libfc function template * * Returns : 0 for success - **/ + */ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) { /* Set the function pointers set by the LLDD */ @@ -1389,14 +1346,14 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) EXPORT_SYMBOL_GPL(fcoe_libfc_config); /** - * fcoe_init - fcoe module loading initialization + * fcoe_init() - fcoe module loading initialization * * Initialization routine * 1. Will create fc transport software structure * 2. initialize the link list of port information structure * * Returns 0 on success, negative on failure - **/ + */ static int __init fcoe_init(void) { int cpu; @@ -1433,7 +1390,6 @@ static int __init fcoe_init(void) } else { fcoe_percpu[cpu] = NULL; kfree(p); - } } } @@ -1443,11 +1399,9 @@ static int __init fcoe_init(void) */ fcoe_dev_setup(); - init_timer(&fcoe_timer); - fcoe_timer.data = 0; - fcoe_timer.function = fcoe_watchdog; - fcoe_timer.expires = (jiffies + (10 * HZ)); - add_timer(&fcoe_timer); + setup_timer(&fcoe_timer, fcoe_watchdog, 0); + + mod_timer(&fcoe_timer, jiffies + (10 * HZ)); /* initiatlize the fcoe transport */ fcoe_transport_init(); @@ -1459,10 +1413,10 @@ static int __init fcoe_init(void) module_init(fcoe_init); /** - * fcoe_exit - fcoe module unloading cleanup + * fcoe_exit() - fcoe module unloading cleanup * * Returns 0 on success, negative on failure - **/ + */ static void __exit fcoe_exit(void) { u32 idx; @@ -1483,7 +1437,7 @@ static void __exit fcoe_exit(void) */ del_timer_sync(&fcoe_timer); - /* releases the assocaited fcoe transport for each lport */ + /* releases the associated fcoe transport for each lport */ list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) fcoe_transport_release(fc->real_dev); diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index a48e4990fe1..34be88d7afa 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1251,6 +1251,7 @@ static struct pci_device_id hptiop_id_table[] = { { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, + { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 4a4e6954ec7..f23c4ca9a2e 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -103,7 +103,7 @@ lasi700_probe(struct parisc_device *dev) hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); if (!hostdata) { - dev_printk(KERN_ERR, dev, "Failed to allocate host data\n"); + dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n"); return -ENOMEM; } diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index dd1564c9e04..e57556ea5b4 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -64,7 +64,7 @@ static void fc_disc_single(struct fc_disc *, struct fc_disc_port *); static void fc_disc_restart(struct fc_disc *); /** - * fc_disc_lookup_rport - lookup a remote port by port_id + * fc_disc_lookup_rport() - lookup a remote port by port_id * @lport: Fibre Channel host port instance * @port_id: remote port port_id to match */ @@ -92,7 +92,7 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport, } /** - * fc_disc_stop_rports - delete all the remote ports associated with the lport + * fc_disc_stop_rports() - delete all the remote ports associated with the lport * @disc: The discovery job to stop rports on * * Locking Note: This function expects that the lport mutex is locked before @@ -117,7 +117,7 @@ void fc_disc_stop_rports(struct fc_disc *disc) } /** - * fc_disc_rport_callback - Event handler for rport events + * fc_disc_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -151,7 +151,7 @@ static void fc_disc_rport_callback(struct fc_lport *lport, } /** - * fc_disc_recv_rscn_req - Handle Registered State Change Notification (RSCN) + * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) * @sp: Current sequence of the RSCN exchange * @fp: RSCN Frame * @lport: Fibre Channel host port instance @@ -246,7 +246,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, list_del(&dp->peers); rport = lport->tt.rport_lookup(lport, dp->ids.port_id); if (rport) { - rdata = RPORT_TO_PRIV(rport); + rdata = rport->dd_data; list_del(&rdata->peers); lport->tt.rport_logoff(rport); } @@ -265,7 +265,7 @@ reject: } /** - * fc_disc_recv_req - Handle incoming requests + * fc_disc_recv_req() - Handle incoming requests * @sp: Current sequence of the request exchange * @fp: The frame * @lport: The FC local port @@ -294,7 +294,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_restart - Restart discovery + * fc_disc_restart() - Restart discovery * @lport: FC discovery context * * Locking Note: This function expects that the disc mutex @@ -322,7 +322,7 @@ static void fc_disc_restart(struct fc_disc *disc) } /** - * fc_disc_start - Fibre Channel Target discovery + * fc_disc_start() - Fibre Channel Target discovery * @lport: FC local port * * Returns non-zero if discovery cannot be started. @@ -383,7 +383,7 @@ static struct fc_rport_operations fc_disc_rport_ops = { }; /** - * fc_disc_new_target - Handle new target found by discovery + * fc_disc_new_target() - Handle new target found by discovery * @lport: FC local port * @rport: The previous FC remote port (NULL if new remote port) * @ids: Identifiers for the new FC remote port @@ -396,7 +396,7 @@ static int fc_disc_new_target(struct fc_disc *disc, struct fc_rport_identifiers *ids) { struct fc_lport *lport = disc->lport; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rdata; int error = 0; if (rport && ids->port_name) { @@ -430,15 +430,15 @@ static int fc_disc_new_target(struct fc_disc *disc, dp.ids.port_name = ids->port_name; dp.ids.node_name = ids->node_name; dp.ids.roles = ids->roles; - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); } if (!rport) error = -ENOMEM; } if (rport) { - rp = rport->dd_data; - rp->ops = &fc_disc_rport_ops; - rp->rp_state = RPORT_ST_INIT; + rdata = rport->dd_data; + rdata->ops = &fc_disc_rport_ops; + rdata->rp_state = RPORT_ST_INIT; lport->tt.rport_login(rport); } } @@ -446,20 +446,20 @@ static int fc_disc_new_target(struct fc_disc *disc, } /** - * fc_disc_del_target - Delete a target + * fc_disc_del_target() - Delete a target * @disc: FC discovery context * @rport: The remote port to be removed */ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) { struct fc_lport *lport = disc->lport; - struct fc_rport_libfc_priv *rdata = RPORT_TO_PRIV(rport); + struct fc_rport_libfc_priv *rdata = rport->dd_data; list_del(&rdata->peers); lport->tt.rport_logoff(rport); } /** - * fc_disc_done - Discovery has been completed + * fc_disc_done() - Discovery has been completed * @disc: FC discovery context */ static void fc_disc_done(struct fc_disc *disc) @@ -479,7 +479,7 @@ static void fc_disc_done(struct fc_disc *disc) } /** - * fc_disc_error - Handle error on dNS request + * fc_disc_error() - Handle error on dNS request * @disc: FC discovery context * @fp: The frame pointer */ @@ -519,7 +519,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) } /** - * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request + * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request * @lport: FC discovery context * * Locking Note: This function expects that the disc_mutex is locked @@ -553,7 +553,7 @@ err: } /** - * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request + * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request * @lport: Fibre Channel host port instance * @buf: GPN_FT response buffer * @len: size of response buffer @@ -617,7 +617,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) if ((dp.ids.port_id != fc_host_port_id(lport->host)) && (dp.ids.port_name != lport->wwpn)) { - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); if (rport) { rdata = rport->dd_data; rdata->ops = &fc_disc_rport_ops; @@ -658,7 +658,10 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) return error; } -/* +/** + * fc_disc_timeout() - Retry handler for the disc component + * @work: Structure holding disc obj that needs retry discovery + * * Handle retry of memory allocation for remote ports. */ static void fc_disc_timeout(struct work_struct *work) @@ -673,7 +676,7 @@ static void fc_disc_timeout(struct work_struct *work) } /** - * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT) + * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT) * @sp: Current sequence of GPN_FT exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -712,9 +715,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, fr_len(fp)); } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { - /* - * Accepted. Parse response. - */ + /* Accepted, parse the response. */ buf = cp + 1; len -= sizeof(*cp); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { @@ -746,7 +747,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_single - Discover the directory information for a single target + * fc_disc_single() - Discover the directory information for a single target * @lport: FC local port * @dp: The port to rediscover * @@ -769,7 +770,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) if (rport) fc_disc_del_target(disc, rport); - new_rport = fc_rport_rogue_create(dp); + new_rport = lport->tt.rport_create(dp); if (new_rport) { rdata = new_rport->dd_data; rdata->ops = &fc_disc_rport_ops; @@ -782,7 +783,7 @@ out: } /** - * fc_disc_stop - Stop discovery for a given lport + * fc_disc_stop() - Stop discovery for a given lport * @lport: The lport that discovery should stop for */ void fc_disc_stop(struct fc_lport *lport) @@ -796,7 +797,7 @@ void fc_disc_stop(struct fc_lport *lport) } /** - * fc_disc_stop_final - Stop discovery for a given lport + * fc_disc_stop_final() - Stop discovery for a given lport * @lport: The lport that discovery should stop for * * This function will block until discovery has been @@ -809,7 +810,7 @@ void fc_disc_stop_final(struct fc_lport *lport) } /** - * fc_disc_init - Initialize the discovery block + * fc_disc_init() - Initialize the discovery block * @lport: FC local port */ int fc_disc_init(struct fc_lport *lport) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 66db08a5f27..505825b6124 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -32,8 +32,6 @@ #include <scsi/libfc.h> #include <scsi/fc_encode.h> -#define FC_DEF_R_A_TOV (10 * 1000) /* resource allocation timeout */ - /* * fc_exch_debug can be set in debugger or at compile time to get more logs. */ @@ -627,7 +625,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) { struct fc_exch *ep; struct fc_frame_header *fh; - u16 rxid; ep = mp->lp->tt.exch_get(mp->lp, fp); if (ep) { @@ -654,18 +651,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0) ep->esb_stat &= ~ESB_ST_SEQ_INIT; - /* - * Set the responder ID in the frame header. - * The old one should've been 0xffff. - * If it isn't, don't assign one. - * Incoming basic link service frames may specify - * a referenced RX_ID. - */ - if (fh->fh_type != FC_TYPE_BLS) { - rxid = ntohs(fh->fh_rx_id); - WARN_ON(rxid != FC_XID_UNKNOWN); - fh->fh_rx_id = htons(ep->rxid); - } fc_exch_hold(ep); /* hold for caller */ spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */ } @@ -677,8 +662,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold * on the ep that should be released by the caller. */ -static enum fc_pf_rjt_reason -fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp) +static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp, + struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_exch *ep = NULL; @@ -996,9 +981,9 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) * Send BLS Reject. * This is for rejecting BA_ABTS only. */ -static void -fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason, - enum fc_ba_rjt_explan explan) +static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, + enum fc_ba_rjt_reason reason, + enum fc_ba_rjt_explan explan) { struct fc_frame *fp; struct fc_frame_header *rx_fh; @@ -1096,7 +1081,7 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) ap->ba_high_seq_cnt = fh->fh_seq_cnt; ap->ba_low_seq_cnt = htons(sp->cnt); } - sp = fc_seq_start_next(sp); + sp = fc_seq_start_next_locked(sp); spin_unlock_bh(&ep->ex_lock); fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); fc_frame_free(rx_fp); @@ -1480,10 +1465,11 @@ static void fc_exch_reset(struct fc_exch *ep) * If sid is non-zero, reset only exchanges we source from that FID. * If did is non-zero, reset only exchanges destined to that FID. */ -void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, u32 did) +void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did) { struct fc_exch *ep; struct fc_exch *next; + struct fc_exch_mgr *mp = lp->emp; spin_lock_bh(&mp->em_lock); restart: @@ -1607,7 +1593,7 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) if (IS_ERR(fp)) { int err = PTR_ERR(fp); - if (err == -FC_EX_CLOSED) + if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT) goto cleanup; FC_DBG("Cannot process RRQ, because of frame error %d\n", err); return; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 404e63ff46b..2a631d7dbce 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -161,7 +161,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp) } /** - * fc_fcp_pkt_release - release hold on scsi_pkt packet + * fc_fcp_pkt_release() - release hold on scsi_pkt packet * @fsp: fcp packet struct * * This is used by upper layer scsi driver. @@ -183,8 +183,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_pkt_destory - release hold on scsi_pkt packet - * + * fc_fcp_pkt_destory() - release hold on scsi_pkt packet * @seq: exchange sequence * @fsp: fcp packet struct * @@ -199,7 +198,7 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp) } /** - * fc_fcp_lock_pkt - lock a packet and get a ref to it. + * fc_fcp_lock_pkt() - lock a packet and get a ref to it. * @fsp: fcp packet * * We should only return error if we return a command to scsi-ml before @@ -291,9 +290,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) buf = fc_frame_payload_get(fp, 0); if (offset + len > fsp->data_len) { - /* - * this should never happen - */ + /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && fc_frame_crc_check(fp)) goto crc_err; @@ -387,8 +384,8 @@ crc_err: fc_fcp_complete_locked(fsp); } -/* - * fc_fcp_send_data - Send SCSI data to target. +/** + * fc_fcp_send_data() - Send SCSI data to target. * @fsp: ptr to fc_fcp_pkt * @sp: ptr to this sequence * @offset: starting offset for this data request @@ -610,8 +607,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } } -/* - * fc_fcp_reduce_can_queue - drop can_queue +/** + * fc_fcp_reduce_can_queue() - drop can_queue * @lp: lport to drop queueing for * * If we are getting memory allocation failures, then we may @@ -642,9 +639,11 @@ done: spin_unlock_irqrestore(lp->host->host_lock, flags); } -/* - * exch mgr calls this routine to process scsi - * exchanges. +/** + * fc_fcp_recv() - Reveive FCP frames + * @seq: The sequence the frame is on + * @fp: The FC frame + * @arg: The related FCP packet * * Return : None * Context : called from Soft IRQ context @@ -832,7 +831,7 @@ err: } /** - * fc_fcp_complete_locked - complete processing of a fcp packet + * fc_fcp_complete_locked() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a timer is pending. The packet lock must be @@ -900,7 +899,7 @@ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) } /** - * fc_fcp_cleanup_each_cmd - run fn on each active command + * fc_fcp_cleanup_each_cmd() - Cleanup active commads * @lp: logical port * @id: target id * @lun: lun @@ -952,7 +951,7 @@ static void fc_fcp_abort_io(struct fc_lport *lp) } /** - * fc_fcp_pkt_send - send a fcp packet to the lower level. + * fc_fcp_pkt_send() - send a fcp packet to the lower level. * @lp: fc lport * @fsp: fc packet. * @@ -1621,7 +1620,7 @@ out: static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp) { /* lock ? */ - return (lp->state == LPORT_ST_READY) && (lp->link_status & FC_LINK_UP); + return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull; } /** @@ -1727,7 +1726,7 @@ out: EXPORT_SYMBOL(fc_queuecommand); /** - * fc_io_compl - Handle responses for completed commands + * fc_io_compl() - Handle responses for completed commands * @fsp: scsi packet * * Translates a error to a Linux SCSI error. @@ -1810,12 +1809,12 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = DID_ERROR << 16; break; case FC_DATA_UNDRUN: - if (fsp->cdb_status == 0) { + if ((fsp->cdb_status == 0) && !(fsp->req_flags & FC_SRB_READ)) { /* * scsi status is good but transport level - * underrun. for read it should be an error?? + * underrun. */ - sc_cmd->result = (DID_OK << 16) | fsp->cdb_status; + sc_cmd->result = DID_OK << 16; } else { /* * scsi got underrun, this is an error @@ -1857,7 +1856,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_complete - complete processing of a fcp packet + * fc_fcp_complete() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a fsp timer is pending. @@ -1874,9 +1873,10 @@ void fc_fcp_complete(struct fc_fcp_pkt *fsp) EXPORT_SYMBOL(fc_fcp_complete); /** - * fc_eh_abort - Abort a command...from scsi host template + * fc_eh_abort() - Abort a command * @sc_cmd: scsi command to abort * + * From scsi host template. * send ABTS to the target device and wait for the response * sc_cmd is the pointer to the command to be aborted. */ @@ -1890,7 +1890,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd) lp = shost_priv(sc_cmd->device->host); if (lp->state != LPORT_ST_READY) return rc; - else if (!(lp->link_status & FC_LINK_UP)) + else if (!lp->link_up) return rc; spin_lock_irqsave(lp->host->host_lock, flags); @@ -1920,7 +1920,7 @@ release_pkt: EXPORT_SYMBOL(fc_eh_abort); /** - * fc_eh_device_reset: Reset a single LUN + * fc_eh_device_reset() Reset a single LUN * @sc_cmd: scsi command * * Set from scsi host template to send tm cmd to the target and wait for the @@ -1973,7 +1973,7 @@ out: EXPORT_SYMBOL(fc_eh_device_reset); /** - * fc_eh_host_reset - The reset function will reset the ports on the host. + * fc_eh_host_reset() - The reset function will reset the ports on the host. * @sc_cmd: scsi command */ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) @@ -1999,7 +1999,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) EXPORT_SYMBOL(fc_eh_host_reset); /** - * fc_slave_alloc - configure queue depth + * fc_slave_alloc() - configure queue depth * @sdev: scsi device * * Configures queue depth based on host's cmd_per_len. If not set diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 0b9bdb1fb80..2ae50a1188e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -139,7 +139,7 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rport_callback - Event handler for rport events + * fc_lport_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -195,7 +195,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, } /** - * fc_lport_state - Return a string which represents the lport's state + * fc_lport_state() - Return a string which represents the lport's state * @lport: The lport whose state is to converted to a string */ static const char *fc_lport_state(struct fc_lport *lport) @@ -209,7 +209,7 @@ static const char *fc_lport_state(struct fc_lport *lport) } /** - * fc_lport_ptp_setup - Create an rport for point-to-point mode + * fc_lport_ptp_setup() - Create an rport for point-to-point mode * @lport: The lport to attach the ptp rport to * @fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport @@ -232,7 +232,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, lport->ptp_rp = NULL; } - lport->ptp_rp = fc_rport_rogue_create(&dp); + lport->ptp_rp = lport->tt.rport_create(&dp); lport->tt.rport_login(lport->ptp_rp); @@ -250,7 +250,7 @@ void fc_get_host_port_state(struct Scsi_Host *shost) { struct fc_lport *lp = shost_priv(shost); - if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP) + if (lp->link_up) fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; else fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; @@ -351,7 +351,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) } /** - * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report. + * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. * @lport: Fibre Channel local port recieving the RLIR * @sp: current sequence in the RLIR exchange * @fp: RLIR request frame @@ -370,7 +370,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_lport_recv_echo_req - Handle received ECHO request + * fc_lport_recv_echo_req() - Handle received ECHO request * @lport: Fibre Channel local port recieving the ECHO * @sp: current sequence in the ECHO exchange * @fp: ECHO request frame @@ -412,7 +412,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_echo_req - Handle received Request Node ID data request + * fc_lport_recv_echo_req() - Handle received Request Node ID data request * @lport: Fibre Channel local port recieving the RNID * @sp: current sequence in the RNID exchange * @fp: RNID request frame @@ -479,7 +479,7 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_adisc_req - Handle received Address Discovery Request + * fc_lport_recv_adisc_req() - Handle received Address Discovery Request * @lport: Fibre Channel local port recieving the ADISC * @sp: current sequence in the ADISC exchange * @fp: ADISC request frame @@ -529,7 +529,7 @@ static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_logo_req - Handle received fabric LOGO request + * fc_lport_recv_logo_req() - Handle received fabric LOGO request * @lport: Fibre Channel local port recieving the LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame @@ -546,7 +546,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_fabric_login - Start the lport state machine + * fc_fabric_login() - Start the lport state machine * @lport: The lport that should log into the fabric * * Locking Note: This function should not be called @@ -568,7 +568,7 @@ int fc_fabric_login(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_login); /** - * fc_linkup - Handler for transport linkup events + * fc_linkup() - Handler for transport linkup events * @lport: The lport whose link is up */ void fc_linkup(struct fc_lport *lport) @@ -577,8 +577,8 @@ void fc_linkup(struct fc_lport *lport) fc_host_port_id(lport->host)); mutex_lock(&lport->lp_mutex); - if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) { - lport->link_status |= FC_LINK_UP; + if (!lport->link_up) { + lport->link_up = 1; if (lport->state == LPORT_ST_RESET) fc_lport_enter_flogi(lport); @@ -588,7 +588,7 @@ void fc_linkup(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkup); /** - * fc_linkdown - Handler for transport linkdown events + * fc_linkdown() - Handler for transport linkdown events * @lport: The lport whose link is down */ void fc_linkdown(struct fc_lport *lport) @@ -597,8 +597,8 @@ void fc_linkdown(struct fc_lport *lport) FC_DEBUG_LPORT("Link is down for port (%6x)\n", fc_host_port_id(lport->host)); - if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) { - lport->link_status &= ~(FC_LINK_UP); + if (lport->link_up) { + lport->link_up = 0; fc_lport_enter_reset(lport); lport->tt.fcp_cleanup(lport); } @@ -607,48 +607,25 @@ void fc_linkdown(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkdown); /** - * fc_pause - Pause the flow of frames - * @lport: The lport to be paused - */ -void fc_pause(struct fc_lport *lport) -{ - mutex_lock(&lport->lp_mutex); - lport->link_status |= FC_PAUSE; - mutex_unlock(&lport->lp_mutex); -} -EXPORT_SYMBOL(fc_pause); - -/** - * fc_unpause - Unpause the flow of frames - * @lport: The lport to be unpaused - */ -void fc_unpause(struct fc_lport *lport) -{ - mutex_lock(&lport->lp_mutex); - lport->link_status &= ~(FC_PAUSE); - mutex_unlock(&lport->lp_mutex); -} -EXPORT_SYMBOL(fc_unpause); - -/** - * fc_fabric_logoff - Logout of the fabric + * fc_fabric_logoff() - Logout of the fabric * @lport: fc_lport pointer to logoff the fabric * * Return value: * 0 for success, -1 for failure - **/ + */ int fc_fabric_logoff(struct fc_lport *lport) { lport->tt.disc_stop_final(lport); mutex_lock(&lport->lp_mutex); fc_lport_enter_logo(lport); mutex_unlock(&lport->lp_mutex); + cancel_delayed_work_sync(&lport->retry_work); return 0; } EXPORT_SYMBOL(fc_fabric_logoff); /** - * fc_lport_destroy - unregister a fc_lport + * fc_lport_destroy() - unregister a fc_lport * @lport: fc_lport pointer to unregister * * Return value: @@ -658,26 +635,25 @@ EXPORT_SYMBOL(fc_fabric_logoff); * clean-up all the allocated memory * and free up other system resources. * - **/ + */ int fc_lport_destroy(struct fc_lport *lport) { lport->tt.frame_send = fc_frame_drop; lport->tt.fcp_abort_io(lport); - lport->tt.exch_mgr_reset(lport->emp, 0, 0); + lport->tt.exch_mgr_reset(lport, 0, 0); return 0; } EXPORT_SYMBOL(fc_lport_destroy); /** - * fc_set_mfs - sets up the mfs for the corresponding fc_lport + * fc_set_mfs() - sets up the mfs for the corresponding fc_lport * @lport: fc_lport pointer to unregister * @mfs: the new mfs for fc_lport * * Set mfs for the given fc_lport to the new mfs. * * Return: 0 for success - * - **/ + */ int fc_set_mfs(struct fc_lport *lport, u32 mfs) { unsigned int old_mfs; @@ -706,7 +682,7 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs) EXPORT_SYMBOL(fc_set_mfs); /** - * fc_lport_disc_callback - Callback for discovery events + * fc_lport_disc_callback() - Callback for discovery events * @lport: FC local port * @event: The discovery event */ @@ -731,7 +707,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) } /** - * fc_rport_enter_ready - Enter the ready state and start discovery + * fc_rport_enter_ready() - Enter the ready state and start discovery * @lport: Fibre Channel local port that is ready * * Locking Note: The lport lock is expected to be held before calling @@ -748,7 +724,7 @@ static void fc_lport_enter_ready(struct fc_lport *lport) } /** - * fc_lport_recv_flogi_req - Receive a FLOGI request + * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on * @rx_fp: The frame the FLOGI is in * @lport: The lport that recieved the request @@ -838,7 +814,7 @@ out: } /** - * fc_lport_recv_req - The generic lport request handler + * fc_lport_recv_req() - The generic lport request handler * @lport: The lport that received the request * @sp: The sequence the request is on * @fp: The frame the request is in @@ -934,7 +910,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, } /** - * fc_lport_reset - Reset an lport + * fc_lport_reset() - Reset an lport * @lport: The lport which should be reset * * Locking Note: This functions should not be called with the @@ -942,6 +918,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, */ int fc_lport_reset(struct fc_lport *lport) { + cancel_delayed_work_sync(&lport->retry_work); mutex_lock(&lport->lp_mutex); fc_lport_enter_reset(lport); mutex_unlock(&lport->lp_mutex); @@ -950,7 +927,7 @@ int fc_lport_reset(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_reset); /** - * fc_rport_enter_reset - Reset the local port + * fc_rport_enter_reset() - Reset the local port * @lport: Fibre Channel local port to be reset * * Locking Note: The lport lock is expected to be held before calling @@ -973,16 +950,16 @@ static void fc_lport_enter_reset(struct fc_lport *lport) lport->tt.disc_stop(lport); - lport->tt.exch_mgr_reset(lport->emp, 0, 0); + lport->tt.exch_mgr_reset(lport, 0, 0); fc_host_fabric_name(lport->host) = 0; fc_host_port_id(lport->host) = 0; - if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) + if (lport->link_up) fc_lport_enter_flogi(lport); } /** - * fc_lport_error - Handler for any errors + * fc_lport_error() - Handler for any errors * @lport: The fc_lport object * @fp: The frame pointer * @@ -1029,8 +1006,8 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rft_id_resp - Handle response to Register Fibre - * Channel Types by ID (RPN_ID) request + * fc_lport_rft_id_resp() - Handle response to Register Fibre + * Channel Types by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1053,17 +1030,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RFT_ID response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_RFT_ID) { FC_DBG("Received a RFT_ID response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); @@ -1081,8 +1058,8 @@ err: } /** - * fc_lport_rpn_id_resp - Handle response to Register Port - * Name by ID (RPN_ID) request + * fc_lport_rpn_id_resp() - Handle response to Register Port + * Name by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1105,17 +1082,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RPN_ID response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_RPN_ID) { FC_DBG("Received a RPN_ID response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); if (fh && ct && fh->fh_type == FC_TYPE_CT && @@ -1133,7 +1110,7 @@ err: } /** - * fc_lport_scr_resp - Handle response to State Change Register (SCR) request + * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request * @sp: current sequence in SCR exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the registration request @@ -1155,17 +1132,17 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a SCR response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_SCR) { FC_DBG("Received a SCR response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_ready(lport); @@ -1179,7 +1156,7 @@ err: } /** - * fc_lport_enter_scr - Send a State Change Register (SCR) request + * fc_lport_enter_scr() - Send a State Change Register (SCR) request * @lport: Fibre Channel local port to register for state changes * * Locking Note: The lport lock is expected to be held before calling @@ -1206,7 +1183,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport) } /** - * fc_lport_enter_rft_id - Register FC4-types with the name server + * fc_lport_enter_rft_id() - Register FC4-types with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1248,7 +1225,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) } /** - * fc_rport_enter_rft_id - Register port name with the name server + * fc_rport_enter_rft_id() - Register port name with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1281,7 +1258,7 @@ static struct fc_rport_operations fc_lport_rport_ops = { }; /** - * fc_rport_enter_dns - Create a rport to the name server + * fc_rport_enter_dns() - Create a rport to the name server * @lport: Fibre Channel local port requesting a rport for the name server * * Locking Note: The lport lock is expected to be held before calling @@ -1304,7 +1281,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_DNS); - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); if (!rport) goto err; @@ -1318,7 +1295,7 @@ err: } /** - * fc_lport_timeout - Handler for the retry_work timer. + * fc_lport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_lport */ static void fc_lport_timeout(struct work_struct *work) @@ -1359,7 +1336,7 @@ static void fc_lport_timeout(struct work_struct *work) } /** - * fc_lport_logo_resp - Handle response to LOGO request + * fc_lport_logo_resp() - Handle response to LOGO request * @sp: current sequence in LOGO exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the LOGO request @@ -1381,17 +1358,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a LOGO response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_LOGO) { FC_DBG("Received a LOGO response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_reset(lport); @@ -1405,7 +1382,7 @@ err: } /** - * fc_rport_enter_logo - Logout of the fabric + * fc_rport_enter_logo() - Logout of the fabric * @lport: Fibre Channel local port to be logged out * * Locking Note: The lport lock is expected to be held before calling @@ -1437,7 +1414,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) } /** - * fc_lport_flogi_resp - Handle response to FLOGI request + * fc_lport_flogi_resp() - Handle response to FLOGI request * @sp: current sequence in FLOGI exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request @@ -1465,17 +1442,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a FLOGI response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_FLOGI) { FC_DBG("Received a FLOGI response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); did = ntoh24(fh->fh_d_id); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { @@ -1532,7 +1509,7 @@ err: } /** - * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager + * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager * @lport: Fibre Channel local port to be logged in to the fabric * * Locking Note: The lport lock is expected to be held before calling diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index e780d8caf70..dae65133a83 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -81,6 +81,7 @@ static void fc_rport_recv_logo_req(struct fc_rport *, struct fc_seq *, struct fc_frame *); static void fc_rport_timeout(struct work_struct *); static void fc_rport_error(struct fc_rport *, struct fc_frame *); +static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *); static void fc_rport_work(struct work_struct *); static const char *fc_rport_state_names[] = { @@ -145,7 +146,7 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp) } /** - * fc_rport_state - return a string for the state the rport is in + * fc_rport_state() - return a string for the state the rport is in * @rport: The rport whose state we want to get a string for */ static const char *fc_rport_state(struct fc_rport *rport) @@ -160,7 +161,7 @@ static const char *fc_rport_state(struct fc_rport *rport) } /** - * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds. + * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. * @rport: Pointer to Fibre Channel remote port structure * @timeout: timeout in seconds */ @@ -174,12 +175,12 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) EXPORT_SYMBOL(fc_set_rport_loss_tmo); /** - * fc_plogi_get_maxframe - Get max payload from the common service parameters + * fc_plogi_get_maxframe() - Get max payload from the common service parameters * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ -static unsigned int -fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) +static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, + unsigned int maxval) { unsigned int mfs; @@ -197,7 +198,7 @@ fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) } /** - * fc_rport_state_enter - Change the rport's state + * fc_rport_state_enter() - Change the rport's state * @rport: The rport whose state should change * @new: The new state of the rport * @@ -214,6 +215,7 @@ static void fc_rport_state_enter(struct fc_rport *rport, static void fc_rport_work(struct work_struct *work) { + u32 port_id; struct fc_rport_libfc_priv *rdata = container_of(work, struct fc_rport_libfc_priv, event_work); enum fc_rport_event event; @@ -279,14 +281,18 @@ static void fc_rport_work(struct work_struct *work) rport_ops->event_callback(lport, rport, event); if (trans_state == FC_PORTSTATE_ROGUE) put_device(&rport->dev); - else + else { + port_id = rport->port_id; fc_remote_port_delete(rport); + lport->tt.exch_mgr_reset(lport, 0, port_id); + lport->tt.exch_mgr_reset(lport, port_id, 0); + } } else mutex_unlock(&rdata->rp_mutex); } /** - * fc_rport_login - Start the remote port login state machine + * fc_rport_login() - Start the remote port login state machine * @rport: Fibre Channel remote port * * Locking Note: Called without the rport lock held. This @@ -309,7 +315,7 @@ int fc_rport_login(struct fc_rport *rport) } /** - * fc_rport_logoff - Logoff and remove an rport + * fc_rport_logoff() - Logoff and remove an rport * @rport: Fibre Channel remote port to be removed * * Locking Note: Called without the rport lock held. This @@ -347,7 +353,7 @@ int fc_rport_logoff(struct fc_rport *rport) } /** - * fc_rport_enter_ready - The rport is ready + * fc_rport_enter_ready() - The rport is ready * @rport: Fibre Channel remote port that is ready * * Locking Note: The rport lock is expected to be held before calling @@ -366,7 +372,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport) } /** - * fc_rport_timeout - Handler for the retry_work timer. + * fc_rport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_rport_libfc_priv * * Locking Note: Called without the rport lock held. This @@ -405,59 +411,75 @@ static void fc_rport_timeout(struct work_struct *work) } /** - * fc_rport_error - Handler for any errors + * fc_rport_error() - Error handler, called once retries have been exhausted * @rport: The fc_rport object * @fp: The frame pointer * - * If the error was caused by a resource allocation failure - * then wait for half a second and retry, otherwise retry - * immediately. - * * Locking Note: The rport lock is expected to be held before * calling this routine */ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) { struct fc_rport_libfc_priv *rdata = rport->dd_data; - unsigned long delay = 0; FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n", PTR_ERR(fp), fc_rport_state(rport), rdata->retries); - if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { - /* - * Memory allocation failure, or the exchange timed out. - * Retry after delay - */ - if (rdata->retries < rdata->local_port->max_retry_count) { - rdata->retries++; - if (!fp) - delay = msecs_to_jiffies(500); - get_device(&rport->dev); - schedule_delayed_work(&rdata->retry_work, delay); - } else { - switch (rdata->rp_state) { - case RPORT_ST_PLOGI: - case RPORT_ST_PRLI: - case RPORT_ST_LOGO: - rdata->event = RPORT_EV_FAILED; - queue_work(rport_event_queue, - &rdata->event_work); - break; - case RPORT_ST_RTV: - fc_rport_enter_ready(rport); - break; - case RPORT_ST_NONE: - case RPORT_ST_READY: - case RPORT_ST_INIT: - break; - } - } + switch (rdata->rp_state) { + case RPORT_ST_PLOGI: + case RPORT_ST_PRLI: + case RPORT_ST_LOGO: + rdata->event = RPORT_EV_FAILED; + queue_work(rport_event_queue, + &rdata->event_work); + break; + case RPORT_ST_RTV: + fc_rport_enter_ready(rport); + break; + case RPORT_ST_NONE: + case RPORT_ST_READY: + case RPORT_ST_INIT: + break; } } /** - * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response + * fc_rport_error_retry() - Error handler when retries are desired + * @rport: The fc_rport object + * @fp: The frame pointer + * + * If the error was an exchange timeout retry immediately, + * otherwise wait for E_D_TOV. + * + * Locking Note: The rport lock is expected to be held before + * calling this routine + */ +static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) +{ + struct fc_rport_libfc_priv *rdata = rport->dd_data; + unsigned long delay = FC_DEF_E_D_TOV; + + /* make sure this isn't an FC_EX_CLOSED error, never retry those */ + if (PTR_ERR(fp) == -FC_EX_CLOSED) + return fc_rport_error(rport, fp); + + if (rdata->retries < rdata->local_port->max_retry_count) { + FC_DEBUG_RPORT("Error %ld in state %s, retrying\n", + PTR_ERR(fp), fc_rport_state(rport)); + rdata->retries++; + /* no additional delay on exchange timeouts */ + if (PTR_ERR(fp) == -FC_EX_TIMEOUT) + delay = 0; + get_device(&rport->dev); + schedule_delayed_work(&rdata->retry_work, delay); + return; + } + + return fc_rport_error(rport, fp); +} + +/** + * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -483,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_PLOGI) { FC_DBG("Received a PLOGI response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC && (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { @@ -522,7 +544,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, else fc_rport_enter_prli(rport); } else - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); out: fc_frame_free(fp); @@ -532,7 +554,7 @@ err: } /** - * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer + * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer * @rport: Fibre Channel remote port to send PLOGI to * * Locking Note: The rport lock is expected to be held before calling @@ -552,20 +574,20 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) rport->maxframe_size = FC_MIN_MAX_PAYLOAD; fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } rdata->e_d_tov = lport->e_d_tov; if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI, fc_rport_plogi_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } /** - * fc_rport_prli_resp - Process Login (PRLI) response handler + * fc_rport_prli_resp() - Process Login (PRLI) response handler * @sp: current sequence in the PRLI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -592,17 +614,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_PRLI) { FC_DBG("Received a PRLI response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { pp = fc_frame_payload_get(fp, sizeof(*pp)); @@ -635,7 +657,7 @@ err: } /** - * fc_rport_logo_resp - Logout (LOGO) response handler + * fc_rport_logo_resp() - Logout (LOGO) response handler * @sp: current sequence in the LOGO exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -657,7 +679,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, rport->port_id); if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -684,7 +706,7 @@ err: } /** - * fc_rport_enter_prli - Send Process Login (PRLI) request to peer + * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer * @rport: Fibre Channel remote port to send PRLI to * * Locking Note: The rport lock is expected to be held before calling @@ -707,19 +729,19 @@ static void fc_rport_enter_prli(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(*pp)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI, fc_rport_prli_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } /** - * fc_rport_els_rtv_resp - Request Timeout Value response handler + * fc_rport_els_rtv_resp() - Request Timeout Value response handler * @sp: current sequence in the RTV exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -742,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_RTV) { FC_DBG("Received a RTV response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { struct fc_els_rtv_acc *rtv; @@ -785,7 +807,7 @@ err: } /** - * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer + * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer * @rport: Fibre Channel remote port to send RTV to * * Locking Note: The rport lock is expected to be held before calling @@ -804,19 +826,19 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV, fc_rport_rtv_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } /** - * fc_rport_enter_logo - Send Logout (LOGO) request to peer + * fc_rport_enter_logo() - Send Logout (LOGO) request to peer * @rport: Fibre Channel remote port to send LOGO to * * Locking Note: The rport lock is expected to be held before calling @@ -835,20 +857,20 @@ static void fc_rport_enter_logo(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO, fc_rport_logo_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } /** - * fc_rport_recv_req - Receive a request from a rport + * fc_rport_recv_req() - Receive a request from a rport * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -909,7 +931,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_rport_recv_plogi_req - Handle incoming Port Login (PLOGI) request + * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request * @rport: Fibre Channel remote port that initiated PLOGI * @sp: current sequence in the PLOGI exchange * @fp: PLOGI request frame @@ -1031,7 +1053,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, } /** - * fc_rport_recv_prli_req - Handle incoming Process Login (PRLI) request + * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request * @rport: Fibre Channel remote port that initiated PRLI * @sp: current sequence in the PRLI exchange * @fp: PRLI request frame @@ -1182,7 +1204,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, } /** - * fc_rport_recv_prlo_req - Handle incoming Process Logout (PRLO) request + * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request * @rport: Fibre Channel remote port that initiated PRLO * @sp: current sequence in the PRLO exchange * @fp: PRLO request frame @@ -1213,7 +1235,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, } /** - * fc_rport_recv_logo_req - Handle incoming Logout (LOGO) request + * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request * @rport: Fibre Channel remote port that initiated LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame @@ -1249,6 +1271,9 @@ static void fc_rport_flush_queue(void) int fc_rport_init(struct fc_lport *lport) { + if (!lport->tt.rport_create) + lport->tt.rport_create = fc_rport_rogue_create; + if (!lport->tt.rport_login) lport->tt.rport_login = fc_rport_login; @@ -1285,7 +1310,7 @@ void fc_rport_terminate_io(struct fc_rport *rport) struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_lport *lport = rdata->local_port; - lport->tt.exch_mgr_reset(lport->emp, 0, rport->port_id); - lport->tt.exch_mgr_reset(lport->emp, rport->port_id, 0); + lport->tt.exch_mgr_reset(lport, 0, rport->port_id); + lport->tt.exch_mgr_reset(lport, rport->port_id, 0); } EXPORT_SYMBOL(fc_rport_terminate_io); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index f4c57227ec1..ee9d4015243 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -244,12 +244,6 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (ha->optrom_state != QLA_SWAITING) break; - if (start & 0xfff) { - qla_printk(KERN_WARNING, ha, - "Invalid start region 0x%x/0x%x.\n", start, size); - return -EINVAL; - } - ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? ha->optrom_size - start : size; @@ -303,8 +297,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && - start == (ha->flt_region_vpd_nvram * 4)) + else if (IS_QLA25XX(ha) || IS_QLA81XX(ha)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 986501759ad..87f9abc7146 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1308,8 +1308,12 @@ qla2x00_init_rings(scsi_qla_host_t *vha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no)); - if (ha->flags.npiv_supported) + if (ha->flags.npiv_supported) { + if (ha->operating_mode == LOOP) + ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1; mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports); + } + mid_init_cb->options = __constant_cpu_to_le16(BIT_1); @@ -2610,6 +2614,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, port_id_t wrap, nxt_d_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2709,7 +2714,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, /* Bypass virtual ports of the same host. */ found = 0; if (ha->num_vhosts) { - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (new_fcport->d_id.b24 == vp->d_id.b24) { found = 1; break; @@ -2832,6 +2837,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) uint16_t first_loop_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2856,7 +2862,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) /* Check for loop ID being already in use. */ found = 0; fcport = NULL; - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { list_for_each_entry(fcport, &vp->vp_fcports, list) { if (fcport->loop_id == dev->loop_id && fcport != dev) { @@ -3291,6 +3297,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) uint8_t status = 0; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; struct req_que *req = ha->req_q_map[0]; if (vha->flags.online) { @@ -3306,7 +3313,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(vha, 0); - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) qla2x00_mark_all_devices_lost(vp, 0); } else { if (!atomic_read(&vha->loop_down_timer)) @@ -3403,7 +3410,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) DEBUG(printk(KERN_INFO "qla2x00_abort_isp(%ld): succeeded.\n", vha->host_no)); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) qla2x00_vp_abort_isp(vp); } @@ -3428,7 +3435,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) static int qla2x00_restart_isp(scsi_qla_host_t *vha) { - uint8_t status = 0; + int status = 0; uint32_t wait_time; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 4c7504cb399..4aab7acf752 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2685,6 +2685,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + scsi_qla_host_t *tvp; if (rptid_entry->entry_status != 0) return; @@ -2710,7 +2711,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (MSB(stat) == 1) return; - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) if (vp_idx == vp->vp_idx) break; if (!vp) diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 3f23932210c..785c61279e6 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -69,9 +69,10 @@ static scsi_qla_host_t * qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) { scsi_qla_host_t *vha; + struct scsi_qla_host *tvha; /* Locate matching device in database. */ - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (!memcmp(port_name, vha->port_name, WWN_SIZE)) return vha; } @@ -194,11 +195,11 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) void qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) { - scsi_qla_host_t *vha; + scsi_qla_host_t *vha, *tvha; struct qla_hw_data *ha = rsp->hw; int i = 0; - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (vha->vp_idx) { switch (mb[0]) { case MBA_LIP_OCCURRED: @@ -300,6 +301,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) int ret; struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + struct scsi_qla_host *tvp; if (vha->vp_idx) return; @@ -308,7 +310,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) clear_bit(VP_DPC_NEEDED, &vha->dpc_flags); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) ret = qla2x00_do_dpc_vp(vp); } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2f5f72531e2..3ddfa889e94 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2222,10 +2222,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, { char name[16]; - ha->init_cb_size = sizeof(init_cb_t); - if (IS_QLA2XXX_MIDTYPE(ha)) - ha->init_cb_size = sizeof(struct mid_init_cb_24xx); - ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); if (!ha->init_cb) @@ -2568,7 +2564,7 @@ qla2x00_do_work(struct scsi_qla_host *vha) void qla2x00_relogin(struct scsi_qla_host *vha) { fc_port_t *fcport; - uint8_t status; + int status; uint16_t next_loopid = 0; struct qla_hw_data *ha = vha->hw; diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 79f7053da99..a772eab2f0e 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.00-k3" +#define QLA2XXX_VERSION "8.03.00-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 940dc32ff0d..b82ffd90632 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1040,12 +1040,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_FAIL; break; case ABORTED_COMMAND: + action = ACTION_FAIL; if (sshdr.asc == 0x10) { /* DIF */ description = "Target Data Integrity Failure"; - action = ACTION_FAIL; error = -EILSEQ; - } else - action = ACTION_RETRY; + } break; case NOT_READY: /* If the device is in the process of becoming diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d57566b8be0..4970ae4a62d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev); static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); static void sd_print_result(struct scsi_disk *, int); +static DEFINE_SPINLOCK(sd_index_lock); static DEFINE_IDA(sd_index_ida); /* This semaphore is used to mediate the 0->1 reference get in the @@ -1166,23 +1167,19 @@ sd_spinup_disk(struct scsi_disk *sdkp) /* * The device does not want the automatic start to be issued. */ - if (sdkp->device->no_start_on_add) { + if (sdkp->device->no_start_on_add) break; - } - - /* - * If manual intervention is required, or this is an - * absent USB storage device, a spinup is meaningless. - */ - if (sense_valid && - sshdr.sense_key == NOT_READY && - sshdr.asc == 4 && sshdr.ascq == 3) { - break; /* manual intervention required */ - /* - * Issue command to spin up drive when not ready - */ - } else if (sense_valid && sshdr.sense_key == NOT_READY) { + if (sense_valid && sshdr.sense_key == NOT_READY) { + if (sshdr.asc == 4 && sshdr.ascq == 3) + break; /* manual intervention required */ + if (sshdr.asc == 4 && sshdr.ascq == 0xb) + break; /* standby */ + if (sshdr.asc == 4 && sshdr.ascq == 0xc) + break; /* unavailable */ + /* + * Issue command to spin up drive when not ready + */ if (!spintime) { sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); cmd[0] = START_STOP; @@ -1914,7 +1911,9 @@ static int sd_probe(struct device *dev) if (!ida_pre_get(&sd_index_ida, GFP_KERNEL)) goto out_put; + spin_lock(&sd_index_lock); error = ida_get_new(&sd_index_ida, &index); + spin_unlock(&sd_index_lock); } while (error == -EAGAIN); if (error) @@ -1936,7 +1935,9 @@ static int sd_probe(struct device *dev) return 0; out_free_index: + spin_lock(&sd_index_lock); ida_remove(&sd_index_ida, index); + spin_unlock(&sd_index_lock); out_put: put_disk(gd); out_free: @@ -1986,7 +1987,9 @@ static void scsi_disk_release(struct device *dev) struct scsi_disk *sdkp = to_scsi_disk(dev); struct gendisk *disk = sdkp->disk; + spin_lock(&sd_index_lock); ida_remove(&sd_index_ida, sdkp->index); + spin_unlock(&sd_index_lock); disk->private_data = NULL; put_disk(disk); diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index a8d61a62522..97f3158fa7b 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -137,7 +137,7 @@ zalon_probe(struct parisc_device *dev) goto fail; if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { - dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ", + dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", dev->irq); goto fail; } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 3599828b976..022e89ffec1 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -133,7 +133,7 @@ # define SCSPTR3 0xffed0024 /* 16 bit SCIF */ # define SCSPTR4 0xffee0024 /* 16 bit SCIF */ # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ -# define SCIF_OPER 0x0001 /* Overrun error bit */ +# define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ defined(CONFIG_CPU_SUBTYPE_SH7203) || \ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce6badded47..211af86a6c5 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -73,8 +73,6 @@ source "drivers/staging/rt2860/Kconfig" source "drivers/staging/rt2870/Kconfig" -source "drivers/staging/benet/Kconfig" - source "drivers/staging/comedi/Kconfig" source "drivers/staging/asus_oled/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9ddcc2bb336..47a56f5ffab 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_AGNX) += agnx/ obj-$(CONFIG_OTUS) += otus/ obj-$(CONFIG_RT2860) += rt2860/ obj-$(CONFIG_RT2870) += rt2870/ -obj-$(CONFIG_BENET) += benet/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ diff --git a/drivers/staging/benet/Kconfig b/drivers/staging/benet/Kconfig deleted file mode 100644 index f6806074f99..00000000000 --- a/drivers/staging/benet/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config BENET - tristate "ServerEngines 10Gb NIC - BladeEngine" - depends on PCI && INET - select INET_LRO - help - This driver implements the NIC functionality for ServerEngines - 10Gb network adapter BladeEngine (EC 3210). diff --git a/drivers/staging/benet/MAINTAINERS b/drivers/staging/benet/MAINTAINERS deleted file mode 100644 index d5ce340218b..00000000000 --- a/drivers/staging/benet/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -SERVER ENGINES 10Gbe NIC - BLADE-ENGINE -P: Subbu Seetharaman -M: subbus@serverengines.com -L: netdev@vger.kernel.org -W: http://www.serverengines.com -S: Supported diff --git a/drivers/staging/benet/Makefile b/drivers/staging/benet/Makefile deleted file mode 100644 index 460b923b99b..00000000000 --- a/drivers/staging/benet/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile to build the network driver for ServerEngine's BladeEngine -# -obj-$(CONFIG_BENET) += benet.o - -benet-y := be_init.o \ - be_int.o \ - be_netif.o \ - be_ethtool.o \ - funcobj.o \ - cq.o \ - eq.o \ - mpu.o \ - eth.o diff --git a/drivers/staging/benet/TODO b/drivers/staging/benet/TODO deleted file mode 100644 index a51dfb59a62..00000000000 --- a/drivers/staging/benet/TODO +++ /dev/null @@ -1,6 +0,0 @@ -TODO: - - remove wrappers around common iowrite functions - - full netdev audit of common problems/issues - -Please send all patches and questions to Subbu Seetharaman -<subbus@serverengines.com> and Greg Kroah-Hartman <greg@kroah.com> diff --git a/drivers/staging/benet/asyncmesg.h b/drivers/staging/benet/asyncmesg.h deleted file mode 100644 index d1e779adb84..00000000000 --- a/drivers/staging/benet/asyncmesg.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __asyncmesg_amap_h__ -#define __asyncmesg_amap_h__ -#include "fwcmd_common.h" - -/* --- ASYNC_EVENT_CODES --- */ -#define ASYNC_EVENT_CODE_LINK_STATE (1) -#define ASYNC_EVENT_CODE_ISCSI (2) - -/* --- ASYNC_LINK_STATES --- */ -#define ASYNC_EVENT_LINK_DOWN (0) /* Link Down on a port */ -#define ASYNC_EVENT_LINK_UP (1) /* Link Up on a port */ - -/* - * The last 4 bytes of the async events have this common format. It allows - * the driver to distinguish [link]MCC_CQ_ENTRY[/link] structs from - * asynchronous events. Both arrive on the same completion queue. This - * structure also contains the common fields used to decode the async event. - */ -struct BE_ASYNC_EVENT_TRAILER_AMAP { - u8 rsvd0[8]; /* DWORD 0 */ - u8 event_code[8]; /* DWORD 0 */ - u8 event_type[8]; /* DWORD 0 */ - u8 rsvd1[6]; /* DWORD 0 */ - u8 async_event; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ -} __packed; -struct ASYNC_EVENT_TRAILER_AMAP { - u32 dw[1]; -}; - -/* - * Applicable in Initiator, Target and NIC modes. - * A link state async event is seen by all device drivers as soon they - * create an MCC ring. Thereafter, anytime the link status changes the - * drivers will receive a link state async event. Notifications continue to - * be sent until a driver destroys its MCC ring. A link down event is - * reported when either port loses link. A link up event is reported - * when either port regains link. When BE's failover mechanism is enabled, a - * link down on the active port causes traffic to be diverted to the standby - * port by the BE's ARM firmware (assuming the standby port has link). In - * this case, the standy port assumes the active status. Note: when link is - * restored on the failed port, traffic continues on the currently active - * port. The ARM firmware does not attempt to 'fail back' traffic to - * the restored port. - */ -struct BE_ASYNC_EVENT_LINK_STATE_AMAP { - u8 port0_link_status[8]; - u8 port1_link_status[8]; - u8 active_port[8]; - u8 rsvd0[8]; /* DWORD 0 */ - u8 port0_duplex[8]; - u8 port0_speed[8]; - u8 port1_duplex[8]; - u8 port1_speed[8]; - u8 port0_fault[8]; - u8 port1_fault[8]; - u8 rsvd1[2][8]; /* DWORD 2 */ - struct BE_ASYNC_EVENT_TRAILER_AMAP trailer; -} __packed; -struct ASYNC_EVENT_LINK_STATE_AMAP { - u32 dw[4]; -}; -#endif /* __asyncmesg_amap_h__ */ diff --git a/drivers/staging/benet/be_cm.h b/drivers/staging/benet/be_cm.h deleted file mode 100644 index b7a1dfd20c3..00000000000 --- a/drivers/staging/benet/be_cm.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_cm_amap_h__ -#define __be_cm_amap_h__ -#include "be_common.h" -#include "etx_context.h" -#include "mpu_context.h" - -/* - * --- CEV_WATERMARK_ENUM --- - * CQ/EQ Watermark Encodings. Encoded as number of free entries in - * Queue when Watermark is reached. - */ -#define CEV_WMARK_0 (0) /* Watermark when Queue full */ -#define CEV_WMARK_16 (1) /* Watermark at 16 free entries */ -#define CEV_WMARK_32 (2) /* Watermark at 32 free entries */ -#define CEV_WMARK_48 (3) /* Watermark at 48 free entries */ -#define CEV_WMARK_64 (4) /* Watermark at 64 free entries */ -#define CEV_WMARK_80 (5) /* Watermark at 80 free entries */ -#define CEV_WMARK_96 (6) /* Watermark at 96 free entries */ -#define CEV_WMARK_112 (7) /* Watermark at 112 free entries */ -#define CEV_WMARK_128 (8) /* Watermark at 128 free entries */ -#define CEV_WMARK_144 (9) /* Watermark at 144 free entries */ -#define CEV_WMARK_160 (10) /* Watermark at 160 free entries */ -#define CEV_WMARK_176 (11) /* Watermark at 176 free entries */ -#define CEV_WMARK_192 (12) /* Watermark at 192 free entries */ -#define CEV_WMARK_208 (13) /* Watermark at 208 free entries */ -#define CEV_WMARK_224 (14) /* Watermark at 224 free entries */ -#define CEV_WMARK_240 (15) /* Watermark at 240 free entries */ - -/* - * --- CQ_CNT_ENUM --- - * Completion Queue Count Encodings. - */ -#define CEV_CQ_CNT_256 (0) /* CQ has 256 entries */ -#define CEV_CQ_CNT_512 (1) /* CQ has 512 entries */ -#define CEV_CQ_CNT_1024 (2) /* CQ has 1024 entries */ - -/* - * --- EQ_CNT_ENUM --- - * Event Queue Count Encodings. - */ -#define CEV_EQ_CNT_256 (0) /* EQ has 256 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_512 (1) /* EQ has 512 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_1024 (2) /* EQ has 1024 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_2048 (3) /* EQ has 2048 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_4096 (4) /* EQ has 4096 entries (4-byte EQEs only) */ - -/* - * --- EQ_SIZE_ENUM --- - * Event Queue Entry Size Encoding. - */ -#define CEV_EQ_SIZE_4 (0) /* EQE is 4 bytes */ -#define CEV_EQ_SIZE_16 (1) /* EQE is 16 bytes */ - -/* - * Completion Queue Context Table Entry. Contains the state of a CQ. - * Located in RAM within the CEV block. - */ -struct BE_CQ_CONTEXT_AMAP { - u8 Cidx[11]; /* DWORD 0 */ - u8 Watermark[4]; /* DWORD 0 */ - u8 NoDelay; /* DWORD 0 */ - u8 EPIdx[11]; /* DWORD 0 */ - u8 Count[2]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 SolEvent; /* DWORD 0 */ - u8 Eventable; /* DWORD 0 */ - u8 Pidx[11]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 EQID[7]; /* DWORD 1 */ - u8 Func; /* DWORD 1 */ - u8 WME; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ -} __packed; -struct CQ_CONTEXT_AMAP { - u32 dw[2]; -}; - -/* - * Event Queue Context Table Entry. Contains the state of an EQ. - * Located in RAM in the CEV block. - */ -struct BE_EQ_CONTEXT_AMAP { - u8 Cidx[13]; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 Func; /* DWORD 0 */ - u8 EPIdx[13]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 rsvd1; /* DWORD 0 */ - u8 Size; /* DWORD 0 */ - u8 Pidx[13]; /* DWORD 1 */ - u8 rsvd2[3]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 Count[3]; /* DWORD 1 */ - u8 SolEvent; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ - u8 Watermark[4]; /* DWORD 2 */ - u8 WME; /* DWORD 2 */ - u8 rsvd3[3]; /* DWORD 2 */ - u8 EventVect[6]; /* DWORD 2 */ - u8 rsvd4[2]; /* DWORD 2 */ - u8 Delay[8]; /* DWORD 2 */ - u8 rsvd5[6]; /* DWORD 2 */ - u8 TMR; /* DWORD 2 */ - u8 rsvd6; /* DWORD 2 */ - u8 rsvd7[32]; /* DWORD 3 */ -} __packed; -struct EQ_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __be_cm_amap_h__ */ diff --git a/drivers/staging/benet/be_common.h b/drivers/staging/benet/be_common.h deleted file mode 100644 index 7e63dc5e334..00000000000 --- a/drivers/staging/benet/be_common.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_common_amap_h__ -#define __be_common_amap_h__ - -/* Physical Address. */ -struct BE_PHYS_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct PHYS_ADDR_AMAP { - u32 dw[2]; -}; - -/* Virtual Address. */ -struct BE_VIRT_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct VIRT_ADDR_AMAP { - u32 dw[2]; -}; - -/* Scatter gather element. */ -struct BE_SGE_AMAP { - u8 addr_hi[32]; /* DWORD 0 */ - u8 addr_lo[32]; /* DWORD 1 */ - u8 rsvd0[32]; /* DWORD 2 */ - u8 len[16]; /* DWORD 3 */ - u8 rsvd1[16]; /* DWORD 3 */ -} __packed; -struct SGE_AMAP { - u32 dw[4]; -}; - -#endif /* __be_common_amap_h__ */ diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c deleted file mode 100644 index 027af85707a..00000000000 --- a/drivers/staging/benet/be_ethtool.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_ethtool.c - * - * This file contains various functions that ethtool can use - * to talk to the driver and the BE H/W. - */ - -#include "benet.h" - -#include <linux/ethtool.h> - -static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = { -/* net_device_stats */ - "rx_packets", - "tx_packets", - "rx_bytes", - "tx_bytes", - "rx_errors", - "tx_errors", - "rx_dropped", - "tx_dropped", - "multicast", - "collisions", - "rx_length_errors", - "rx_over_errors", - "rx_crc_errors", - "rx_frame_errors", - "rx_fifo_errors", - "rx_missed_errors", - "tx_aborted_errors", - "tx_carrier_errors", - "tx_fifo_errors", - "tx_heartbeat_errors", - "tx_window_errors", - "rx_compressed", - "tc_compressed", -/* BE driver Stats */ - "bes_tx_reqs", - "bes_tx_fails", - "bes_fwd_reqs", - "bes_tx_wrbs", - "bes_interrupts", - "bes_events", - "bes_tx_events", - "bes_rx_events", - "bes_tx_compl", - "bes_rx_compl", - "bes_ethrx_post_fail", - "bes_802_3_dropped_frames", - "bes_802_3_malformed_frames", - "bes_rx_misc_pkts", - "bes_eth_tx_rate", - "bes_eth_rx_rate", - "Num Packets collected", - "Num Times Flushed", -}; - -#define NET_DEV_STATS_LEN \ - (sizeof(struct net_device_stats)/sizeof(unsigned long)) - -#define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats) - -static void -be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - strncpy(drvinfo->driver, be_driver_name, 32); - strncpy(drvinfo->version, be_drvr_ver, 32); - strncpy(drvinfo->fw_version, be_fw_ver, 32); - strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; -} - -static int -be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; - - coalesce->rx_coalesce_usecs = adapter->cur_eqd; - coalesce->rx_coalesce_usecs_high = adapter->max_eqd; - coalesce->rx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->tx_coalesce_usecs = adapter->cur_eqd; - coalesce->tx_coalesce_usecs_high = adapter->max_eqd; - coalesce->tx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->use_adaptive_rx_coalesce = adapter->enable_aic; - coalesce->use_adaptive_tx_coalesce = adapter->enable_aic; - - return 0; -} - -/* - * This routine is used to set interrup coalescing delay *as well as* - * the number of pkts to coalesce for LRO. - */ -static int -be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct be_eq_object *eq_objectp; - u32 max, min, cur; - int status; - - adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; - if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS) - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - if (adapter->enable_aic == 0 && - coalesce->use_adaptive_rx_coalesce == 1) { - /* if AIC is being turned on now, start with an EQD of 0 */ - adapter->cur_eqd = 0; - } - adapter->enable_aic = coalesce->use_adaptive_rx_coalesce; - - /* round off to nearest multiple of 8 */ - max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3); - min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3); - cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3); - - if (adapter->enable_aic) { - /* accept low and high if AIC is enabled */ - if (max > MAX_EQD) - max = MAX_EQD; - if (min > max) - min = max; - adapter->max_eqd = max; - adapter->min_eqd = min; - if (adapter->cur_eqd > max) - adapter->cur_eqd = max; - if (adapter->cur_eqd < min) - adapter->cur_eqd = min; - } else { - /* accept specified coalesce_usecs only if AIC is disabled */ - if (cur > MAX_EQD) - cur = MAX_EQD; - eq_objectp = &pnob->event_q_obj; - status = - be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur, - NULL, NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = cur; - } - return 0; -} - -static u32 be_get_rx_csum(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - return adapter->rx_csum; -} - -static int be_set_rx_csum(struct net_device *netdev, uint32_t data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - if (data) - adapter->rx_csum = 1; - else - adapter->rx_csum = 0; - - return 0; -} - -static void -be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *benet_gstrings_stats, - sizeof(benet_gstrings_stats)); - break; - } -} - -static int be_get_stats_count(struct net_device *netdev) -{ - return BENET_STATS_LEN; -} - -static void -be_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - int i; - - benet_get_stats(netdev); - - for (i = 0; i <= NET_DEV_STATS_LEN; i++) - data[i] = ((unsigned long *)&adapter->benet_stats)[i]; - - data[i] = adapter->be_stat.bes_tx_reqs; - data[i++] = adapter->be_stat.bes_tx_fails; - data[i++] = adapter->be_stat.bes_fwd_reqs; - data[i++] = adapter->be_stat.bes_tx_wrbs; - - data[i++] = adapter->be_stat.bes_ints; - data[i++] = adapter->be_stat.bes_events; - data[i++] = adapter->be_stat.bes_tx_events; - data[i++] = adapter->be_stat.bes_rx_events; - data[i++] = adapter->be_stat.bes_tx_compl; - data[i++] = adapter->be_stat.bes_rx_compl; - data[i++] = adapter->be_stat.bes_ethrx_post_fail; - data[i++] = adapter->be_stat.bes_802_3_dropped_frames; - data[i++] = adapter->be_stat.bes_802_3_malformed_frames; - data[i++] = adapter->be_stat.bes_rx_misc_pkts; - data[i++] = adapter->be_stat.bes_eth_tx_rate; - data[i++] = adapter->be_stat.bes_eth_rx_rate; - data[i++] = adapter->be_stat.bes_rx_coal; - data[i++] = adapter->be_stat.bes_rx_flush; - -} - -static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - ecmd->autoneg = AUTONEG_DISABLE; - return 0; -} - -/* Get the Ring parameters from the pnob */ -static void -be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - /* Pre Set Maxims */ - ring->rx_max_pending = pnob->rx_q_len; - ring->rx_mini_max_pending = ring->rx_mini_max_pending; - ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending; - ring->tx_max_pending = pnob->tx_q_len; - - /* Current hardware Settings */ - ring->rx_pending = atomic_read(&pnob->rx_q_posted); - ring->rx_mini_pending = ring->rx_mini_pending; - ring->rx_jumbo_pending = ring->rx_jumbo_pending; - ring->tx_pending = atomic_read(&pnob->tx_q_used); - -} - -static void -be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool rxfc, txfc; - int status; - - status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to get pause frame settings\n"); - /* return defaults */ - ecmd->rx_pause = 1; - ecmd->tx_pause = 0; - ecmd->autoneg = AUTONEG_ENABLE; - return; - } - - if (txfc == true) - ecmd->tx_pause = 1; - else - ecmd->tx_pause = 0; - - if (rxfc == true) - ecmd->rx_pause = 1; - else - ecmd->rx_pause = 0; - - ecmd->autoneg = AUTONEG_ENABLE; -} - -static int -be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool txfc, rxfc; - int status; - - if (ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - - if (ecmd->tx_pause) - txfc = true; - else - txfc = false; - - if (ecmd->rx_pause) - rxfc = true; - else - rxfc = false; - - status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to set pause frame settings\n"); - return -1; - } - return 0; -} - -struct ethtool_ops be_ethtool_ops = { - .get_settings = be_get_settings, - .get_drvinfo = be_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_coalesce = be_get_coalesce, - .set_coalesce = be_set_coalesce, - .get_ringparam = be_get_ringparam, - .get_pauseparam = be_get_pauseparam, - .set_pauseparam = be_set_pauseparam, - .get_rx_csum = be_get_rx_csum, - .set_rx_csum = be_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, - .set_tso = ethtool_op_set_tso, - .get_strings = be_get_strings, - .get_stats_count = be_get_stats_count, - .get_ethtool_stats = be_get_ethtool_stats, -}; diff --git a/drivers/staging/benet/be_init.c b/drivers/staging/benet/be_init.c deleted file mode 100644 index 12a026c3f9e..00000000000 --- a/drivers/staging/benet/be_init.c +++ /dev/null @@ -1,1382 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include <linux/etherdevice.h> -#include "benet.h" - -#define DRVR_VERSION "1.0.728" - -static const struct pci_device_id be_device_id_table[] = { - {PCI_DEVICE(0x19a2, 0x0201)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, be_device_id_table); - -MODULE_VERSION(DRVR_VERSION); - -#define DRV_DESCRIPTION "ServerEngines BladeEngine Network Driver Version " - -MODULE_DESCRIPTION(DRV_DESCRIPTION DRVR_VERSION); -MODULE_AUTHOR("ServerEngines"); -MODULE_LICENSE("GPL"); - -static unsigned int msix = 1; -module_param(msix, uint, S_IRUGO); -MODULE_PARM_DESC(msix, "Use MSI-x interrupts"); - -static unsigned int rxbuf_size = 2048; /* Default RX frag size */ -module_param(rxbuf_size, uint, S_IRUGO); -MODULE_PARM_DESC(rxbuf_size, "Size of buffers to hold Rx data"); - -const char be_drvr_ver[] = DRVR_VERSION; -char be_fw_ver[32]; /* F/W version filled in by be_probe */ -char be_driver_name[] = "benet"; - -/* - * Number of entries in each queue. - */ -#define EVENT_Q_LEN 1024 -#define ETH_TXQ_LEN 2048 -#define ETH_TXCQ_LEN 1024 -#define ETH_RXQ_LEN 1024 /* Does not support any other value */ -#define ETH_UC_RXCQ_LEN 1024 -#define ETH_BC_RXCQ_LEN 256 -#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ -#define MCC_CQ_LEN 256 - -/* Bit mask describing events of interest to be traced */ -unsigned int trace_level; - -static int -init_pci_be_function(struct be_adapter *adapter, struct pci_dev *pdev) -{ - u64 pa; - - /* CSR */ - pa = pci_resource_start(pdev, 2); - adapter->csr_va = ioremap_nocache(pa, pci_resource_len(pdev, 2)); - if (adapter->csr_va == NULL) - return -ENOMEM; - - /* Door Bell */ - pa = pci_resource_start(pdev, 4); - adapter->db_va = ioremap_nocache(pa, (128 * 1024)); - if (adapter->db_va == NULL) { - iounmap(adapter->csr_va); - return -ENOMEM; - } - - /* PCI */ - pa = pci_resource_start(pdev, 1); - adapter->pci_va = ioremap_nocache(pa, pci_resource_len(pdev, 1)); - if (adapter->pci_va == NULL) { - iounmap(adapter->csr_va); - iounmap(adapter->db_va); - return -ENOMEM; - } - return 0; -} - -/* - This function enables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_enable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function disables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_disable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function enables the interrupt from the network function - of the BladeEngine. Use the function be_disable_eq_intr() - to enable the interrupt from the event queue of only one specific - NetObject -*/ -void be_enable_intr(struct be_net_object *pnob) -{ - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw, 1); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -/* - This function disables the interrupt from the network function of - the BladeEngine. Use the function be_disable_eq_intr() to - disable the interrupt from the event queue of only one specific NetObject -*/ -void be_disable_intr(struct be_net_object *pnob) -{ - - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, hostintr, - ctrl.dw, 0); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -static int be_enable_msix(struct be_adapter *adapter) -{ - int i, ret; - - if (!msix) - return -1; - - for (i = 0; i < BE_MAX_REQ_MSIX_VECTORS; i++) - adapter->msix_entries[i].entry = i; - - ret = pci_enable_msix(adapter->pdev, adapter->msix_entries, - BE_MAX_REQ_MSIX_VECTORS); - - if (ret == 0) - adapter->msix_enabled = 1; - return ret; -} - -static int be_register_isr(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = pnob->netdev; - int intx = 0, r; - - netdev->irq = adapter->pdev->irq; - r = be_enable_msix(adapter); - - if (r == 0) { - r = request_irq(adapter->msix_entries[0].vector, - be_int, IRQF_SHARED, netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "MSIX Request IRQ failed - Errno %d\n", r); - intx = 1; - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } - } else { - intx = 1; - } - - if (intx) { - r = request_irq(netdev->irq, be_int, IRQF_SHARED, - netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "INTx Request IRQ failed - Errno %d\n", r); - return -1; - } - } - adapter->isr_registered = 1; - return 0; -} - -static void be_unregister_isr(struct be_adapter *adapter) -{ - struct net_device *netdev = adapter->netdevp; - if (adapter->isr_registered) { - if (adapter->msix_enabled) { - free_irq(adapter->msix_entries[0].vector, netdev); - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } else { - free_irq(netdev->irq, netdev); - } - adapter->isr_registered = 0; - } -} - -/* - This function processes the Flush Completions that are issued by the - ARM F/W, when a Recv Ring is destroyed. A flush completion is - identified when a Rx COmpl descriptor has the tcpcksum and udpcksum - set and the pktsize is 32. These completions are received on the - Rx Completion Queue. -*/ -static u32 be_process_rx_flush_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp; - unsigned int i = 0; - while ((rxcp = be_get_rx_cmpl(pnob)) != NULL) { - be_notify_cmpl(pnob, 1, pnob->rx_cq_id, 1); - i++; - } - return i; -} - -static void be_tx_q_clean(struct be_net_object *pnob) -{ - while (atomic_read(&pnob->tx_q_used)) - process_one_tx_compl(pnob, tx_compl_lastwrb_idx_get(pnob)); -} - -static void be_rx_q_clean(struct be_net_object *pnob) -{ - if (pnob->rx_ctxt) { - int i; - struct be_rx_page_info *rx_page_info; - for (i = 0; i < pnob->rx_q_len; i++) { - rx_page_info = &(pnob->rx_page_info[i]); - if (!pnob->rx_pg_shared || rx_page_info->page_offset) { - pci_unmap_page(pnob->adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - pnob->rx_buf_size, - PCI_DMA_FROMDEVICE); - } - if (rx_page_info->page) - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - } - pnob->rx_pg_info_hd = 0; - } -} - -static void be_destroy_netobj(struct be_net_object *pnob) -{ - int status; - - if (pnob->tx_q_created) { - status = be_eth_sq_destroy(&pnob->tx_q_obj); - pnob->tx_q_created = 0; - } - - if (pnob->rx_q_created) { - status = be_eth_rq_destroy(&pnob->rx_q_obj); - if (status != 0) { - status = be_eth_rq_destroy_options(&pnob->rx_q_obj, 0, - NULL, NULL); - BUG_ON(status); - } - pnob->rx_q_created = 0; - } - - be_process_rx_flush_cmpl(pnob); - - if (pnob->tx_cq_created) { - status = be_cq_destroy(&pnob->tx_cq_obj); - pnob->tx_cq_created = 0; - } - - if (pnob->rx_cq_created) { - status = be_cq_destroy(&pnob->rx_cq_obj); - pnob->rx_cq_created = 0; - } - - if (pnob->mcc_q_created) { - status = be_mcc_ring_destroy(&pnob->mcc_q_obj); - pnob->mcc_q_created = 0; - } - if (pnob->mcc_cq_created) { - status = be_cq_destroy(&pnob->mcc_cq_obj); - pnob->mcc_cq_created = 0; - } - - if (pnob->event_q_created) { - status = be_eq_destroy(&pnob->event_q_obj); - pnob->event_q_created = 0; - } - be_function_cleanup(&pnob->fn_obj); -} - -/* - * free all resources associated with a pnob - * Called at the time of module cleanup as well a any error during - * module init. Some resources may be partially allocated in a NetObj. - */ -static void netobject_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = adapter->netdevp; - - if (netif_running(netdev)) { - netif_stop_queue(netdev); - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - } - - be_unregister_isr(adapter); - - if (adapter->tasklet_started) { - tasklet_kill(&(adapter->sts_handler)); - adapter->tasklet_started = 0; - } - if (pnob->fn_obj_created) - be_disable_intr(pnob); - - if (adapter->dev_state != BE_DEV_STATE_NONE) - unregister_netdev(netdev); - - if (pnob->fn_obj_created) - be_destroy_netobj(pnob); - - adapter->net_obj = NULL; - adapter->netdevp = NULL; - - be_rx_q_clean(pnob); - if (pnob->rx_ctxt) { - kfree(pnob->rx_page_info); - kfree(pnob->rx_ctxt); - } - - be_tx_q_clean(pnob); - kfree(pnob->tx_ctxt); - - if (pnob->mcc_q) - pci_free_consistent(adapter->pdev, pnob->mcc_q_size, - pnob->mcc_q, pnob->mcc_q_bus); - - if (pnob->mcc_wrb_ctxt) - free_pages((unsigned long)pnob->mcc_wrb_ctxt, - get_order(pnob->mcc_wrb_ctxt_size)); - - if (pnob->mcc_cq) - pci_free_consistent(adapter->pdev, pnob->mcc_cq_size, - pnob->mcc_cq, pnob->mcc_cq_bus); - - if (pnob->event_q) - pci_free_consistent(adapter->pdev, pnob->event_q_size, - pnob->event_q, pnob->event_q_bus); - - if (pnob->tx_cq) - pci_free_consistent(adapter->pdev, pnob->tx_cq_size, - pnob->tx_cq, pnob->tx_cq_bus); - - if (pnob->tx_q) - pci_free_consistent(adapter->pdev, pnob->tx_q_size, - pnob->tx_q, pnob->tx_q_bus); - - if (pnob->rx_q) - pci_free_consistent(adapter->pdev, pnob->rx_q_size, - pnob->rx_q, pnob->rx_q_bus); - - if (pnob->rx_cq) - pci_free_consistent(adapter->pdev, pnob->rx_cq_size, - pnob->rx_cq, pnob->rx_cq_bus); - - - if (pnob->mb_ptr) - pci_free_consistent(adapter->pdev, pnob->mb_size, pnob->mb_ptr, - pnob->mb_bus); - - free_netdev(netdev); -} - - -static int be_nob_ring_alloc(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - u32 size; - - /* Mail box rd; mailbox pointer needs to be 16 byte aligned */ - pnob->mb_size = sizeof(struct MCC_MAILBOX_AMAP) + 16; - pnob->mb_ptr = pci_alloc_consistent(adapter->pdev, pnob->mb_size, - &pnob->mb_bus); - if (!pnob->mb_bus) - return -1; - memset(pnob->mb_ptr, 0, pnob->mb_size); - pnob->mb_rd.va = PTR_ALIGN(pnob->mb_ptr, 16); - pnob->mb_rd.pa = PTR_ALIGN(pnob->mb_bus, 16); - pnob->mb_rd.length = sizeof(struct MCC_MAILBOX_AMAP); - /* - * Event queue - */ - pnob->event_q_len = EVENT_Q_LEN; - pnob->event_q_size = pnob->event_q_len * sizeof(struct EQ_ENTRY_AMAP); - pnob->event_q = pci_alloc_consistent(adapter->pdev, pnob->event_q_size, - &pnob->event_q_bus); - if (!pnob->event_q_bus) - return -1; - memset(pnob->event_q, 0, pnob->event_q_size); - /* - * Eth TX queue - */ - pnob->tx_q_len = ETH_TXQ_LEN; - pnob->tx_q_port = 0; - pnob->tx_q_size = pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP); - pnob->tx_q = pci_alloc_consistent(adapter->pdev, pnob->tx_q_size, - &pnob->tx_q_bus); - if (!pnob->tx_q_bus) - return -1; - memset(pnob->tx_q, 0, pnob->tx_q_size); - /* - * Eth TX Compl queue - */ - pnob->txcq_len = ETH_TXCQ_LEN; - pnob->tx_cq_size = pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP); - pnob->tx_cq = pci_alloc_consistent(adapter->pdev, pnob->tx_cq_size, - &pnob->tx_cq_bus); - if (!pnob->tx_cq_bus) - return -1; - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - /* - * Eth RX queue - */ - pnob->rx_q_len = ETH_RXQ_LEN; - pnob->rx_q_size = pnob->rx_q_len * sizeof(struct ETH_RX_D_AMAP); - pnob->rx_q = pci_alloc_consistent(adapter->pdev, pnob->rx_q_size, - &pnob->rx_q_bus); - if (!pnob->rx_q_bus) - return -1; - memset(pnob->rx_q, 0, pnob->rx_q_size); - /* - * Eth Unicast RX Compl queue - */ - pnob->rx_cq_len = ETH_UC_RXCQ_LEN; - pnob->rx_cq_size = pnob->rx_cq_len * - sizeof(struct ETH_RX_COMPL_AMAP); - pnob->rx_cq = pci_alloc_consistent(adapter->pdev, pnob->rx_cq_size, - &pnob->rx_cq_bus); - if (!pnob->rx_cq_bus) - return -1; - memset(pnob->rx_cq, 0, pnob->rx_cq_size); - - /* TX resources */ - size = pnob->tx_q_len * sizeof(void **); - pnob->tx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->tx_ctxt == NULL) - return -1; - - /* RX resources */ - size = pnob->rx_q_len * sizeof(void *); - pnob->rx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->rx_ctxt == NULL) - return -1; - - size = (pnob->rx_q_len * sizeof(struct be_rx_page_info)); - pnob->rx_page_info = kzalloc(size, GFP_KERNEL); - if (pnob->rx_page_info == NULL) - return -1; - - adapter->eth_statsp = kzalloc(sizeof(struct FWCMD_ETH_GET_STATISTICS), - GFP_KERNEL); - if (adapter->eth_statsp == NULL) - return -1; - pnob->rx_buf_size = rxbuf_size; - return 0; -} - -/* - This function initializes the be_net_object for subsequent - network operations. - - Before calling this function, the driver must have allocated - space for the NetObject structure, initialized the structure, - allocated DMAable memory for all the network queues that form - part of the NetObject and populated the start address (virtual) - and number of entries allocated for each queue in the NetObject structure. - - The driver must also have allocated memory to hold the - mailbox structure (MCC_MAILBOX) and post the physical address, - virtual addresses and the size of the mailbox memory in the - NetObj.mb_rd. This structure is used by BECLIB for - initial communication with the embedded MCC processor. BECLIB - uses the mailbox until MCC rings are created for more efficient - communication with the MCC processor. - - If the driver wants to create multiple network interface for more - than one protection domain, it can call be_create_netobj() - multiple times once for each protection domain. A Maximum of - 32 protection domains are supported. - -*/ -static int -be_create_netobj(struct be_net_object *pnob, u8 __iomem *csr_va, - u8 __iomem *db_va, u8 __iomem *pci_va) -{ - int status = 0; - bool eventable = false, tx_no_delay = false, rx_no_delay = false; - struct be_eq_object *eq_objectp = NULL; - struct be_function_object *pfob = &pnob->fn_obj; - struct ring_desc rd; - u32 set_rxbuf_size; - u32 tx_cmpl_wm = CEV_WMARK_96; /* 0xffffffff to disable */ - u32 rx_cmpl_wm = CEV_WMARK_160; /* 0xffffffff to disable */ - u32 eq_delay = 0; /* delay in 8usec units. 0xffffffff to disable */ - - memset(&rd, 0, sizeof(struct ring_desc)); - - status = be_function_object_create(csr_va, db_va, pci_va, - BE_FUNCTION_TYPE_NETWORK, &pnob->mb_rd, pfob); - if (status != BE_SUCCESS) - return status; - pnob->fn_obj_created = true; - - if (tx_cmpl_wm == 0xffffffff) - tx_no_delay = true; - if (rx_cmpl_wm == 0xffffffff) - rx_no_delay = true; - /* - * now create the necessary rings - * Event Queue first. - */ - if (pnob->event_q_len) { - rd.va = pnob->event_q; - rd.pa = pnob->event_q_bus; - rd.length = pnob->event_q_size; - - status = be_eq_create(pfob, &rd, 4, pnob->event_q_len, - (u32) -1, /* CEV_WMARK_* or -1 */ - eq_delay, /* in 8us units, or -1 */ - &pnob->event_q_obj); - if (status != BE_SUCCESS) - goto error_ret; - pnob->event_q_id = pnob->event_q_obj.eq_id; - pnob->event_q_created = 1; - eventable = true; - eq_objectp = &pnob->event_q_obj; - } - /* - * Now Eth Tx Compl. queue. - */ - if (pnob->txcq_len) { - rd.va = pnob->tx_cq; - rd.pa = pnob->tx_cq_bus; - rd.length = pnob->tx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP), - false, /* solicted events, */ - tx_no_delay, /* nodelay */ - tx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->tx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_cq_id = pnob->tx_cq_obj.cq_id; - pnob->tx_cq_created = 1; - } - /* - * Eth Tx queue - */ - if (pnob->tx_q_len) { - struct be_eth_sq_parameters ex_params = { 0 }; - u32 type; - - if (pnob->tx_q_port) { - /* TXQ to be bound to a specific port */ - type = BE_ETH_TX_RING_TYPE_BOUND; - ex_params.port = pnob->tx_q_port - 1; - } else - type = BE_ETH_TX_RING_TYPE_STANDARD; - - rd.va = pnob->tx_q; - rd.pa = pnob->tx_q_bus; - rd.length = pnob->tx_q_size; - - status = be_eth_sq_create_ex(pfob, &rd, - pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP), - type, 2, &pnob->tx_cq_obj, - &ex_params, &pnob->tx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_q_id = pnob->tx_q_obj.bid; - pnob->tx_q_created = 1; - } - /* - * Now Eth Rx compl. queue. Always needed. - */ - rd.va = pnob->rx_cq; - rd.pa = pnob->rx_cq_bus; - rd.length = pnob->rx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->rx_cq_len * sizeof(struct ETH_RX_COMPL_AMAP), - false, /* solicted events, */ - rx_no_delay, /* nodelay */ - rx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->rx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_cq_id = pnob->rx_cq_obj.cq_id; - pnob->rx_cq_created = 1; - - status = be_eth_rq_set_frag_size(pfob, pnob->rx_buf_size, - (u32 *) &set_rxbuf_size); - if (status != BE_SUCCESS) { - be_eth_rq_get_frag_size(pfob, (u32 *) &pnob->rx_buf_size); - if ((pnob->rx_buf_size != 2048) && (pnob->rx_buf_size != 4096) - && (pnob->rx_buf_size != 8192)) - goto error_ret; - } else { - if (pnob->rx_buf_size != set_rxbuf_size) - pnob->rx_buf_size = set_rxbuf_size; - } - /* - * Eth RX queue. be_eth_rq_create() always assumes 2 pages size - */ - rd.va = pnob->rx_q; - rd.pa = pnob->rx_q_bus; - rd.length = pnob->rx_q_size; - - status = be_eth_rq_create(pfob, &rd, &pnob->rx_cq_obj, - &pnob->rx_cq_obj, &pnob->rx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_q_id = pnob->rx_q_obj.rid; - pnob->rx_q_created = 1; - - return BE_SUCCESS; /* All required queues created. */ - -error_ret: - be_destroy_netobj(pnob); - return status; -} - -static int be_nob_ring_init(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - int status; - - pnob->event_q_tl = 0; - - pnob->tx_q_hd = 0; - pnob->tx_q_tl = 0; - - pnob->tx_cq_tl = 0; - - pnob->rx_cq_tl = 0; - - memset(pnob->event_q, 0, pnob->event_q_size); - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - memset(pnob->tx_ctxt, 0, pnob->tx_q_len * sizeof(void **)); - memset(pnob->rx_ctxt, 0, pnob->rx_q_len * sizeof(void *)); - pnob->rx_pg_info_hd = 0; - pnob->rx_q_hd = 0; - atomic_set(&pnob->rx_q_posted, 0); - - status = be_create_netobj(pnob, adapter->csr_va, adapter->db_va, - adapter->pci_va); - if (status != BE_SUCCESS) - return -1; - - be_post_eth_rx_buffs(pnob); - return 0; -} - -/* This function handles async callback for link status */ -static void -be_link_status_async_callback(void *context, u32 event_code, void *event) -{ - struct ASYNC_EVENT_LINK_STATE_AMAP *link_status = event; - struct be_adapter *adapter = context; - bool link_enable = false; - struct be_net_object *pnob; - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer; - struct net_device *netdev; - u32 async_event_code, async_event_type, active_port; - u32 port0_link_status, port1_link_status, port0_duplex, port1_duplex; - u32 port0_speed, port1_speed; - - if (event_code != ASYNC_EVENT_CODE_LINK_STATE) { - /* Not our event to handle */ - return; - } - async_trailer = (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) event + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - - async_event_code = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_code, - async_trailer); - BUG_ON(async_event_code != ASYNC_EVENT_CODE_LINK_STATE); - - pnob = adapter->net_obj; - netdev = pnob->netdev; - - /* Determine if this event is a switch VLD or a physical link event */ - async_event_type = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_type, - async_trailer); - active_port = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - active_port, link_status); - port0_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_link_status, link_status); - port1_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_link_status, link_status); - port0_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_duplex, link_status); - port1_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_duplex, link_status); - port0_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_speed, link_status); - port1_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_speed, link_status); - if (async_event_type == NTWK_LINK_TYPE_VIRTUAL) { - adapter->be_stat.bes_link_change_virtual++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to VLD on switch\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - - } else { - adapter->be_stat.bes_link_change_physical++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to port link" - " status change\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - } - - memset(adapter->be_link_sts, 0, sizeof(adapter->be_link_sts)); - - if ((port0_link_status == ASYNC_EVENT_LINK_UP) || - (port1_link_status == ASYNC_EVENT_LINK_UP)) { - if ((adapter->port0_link_sts == BE_PORT_LINK_DOWN) && - (adapter->port1_link_sts == BE_PORT_LINK_DOWN)) { - /* Earlier both the ports are down So link is up */ - link_enable = true; - } - - if (port0_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port0_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac0_duplex = port0_duplex; - adapter->be_link_sts->mac0_speed = port0_speed; - if (active_port == NTWK_PORT_A) - adapter->be_link_sts->active_port = 0; - } else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (port1_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port1_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac1_duplex = port1_duplex; - adapter->be_link_sts->mac1_speed = port1_speed; - if (active_port == NTWK_PORT_B) - adapter->be_link_sts->active_port = 1; - } else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - printk(KERN_INFO "Link Properties for %s:\n", netdev->name); - dev_info(&netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - - if (!link_enable) - return; - /* - * Both ports were down previously, but atleast one of - * them has come up if this netdevice's carrier is not up, - * then indicate to stack - */ - if (!netif_carrier_ok(netdev)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - return; - } - - /* Now both the ports are down. Tell the stack about it */ - dev_info(&netdev->dev, "Both ports are down\n"); - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - if (netif_carrier_ok(netdev)) { - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - return; -} - -static int be_mcc_create(struct be_adapter *adapter) -{ - struct be_net_object *pnob; - - pnob = adapter->net_obj; - /* - * Create the MCC ring so that all further communication with - * MCC can go thru the ring. we do this at the end since - * we do not want to be dealing with interrupts until the - * initialization is complete. - */ - pnob->mcc_q_len = MCC_Q_LEN; - pnob->mcc_q_size = pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP); - pnob->mcc_q = pci_alloc_consistent(adapter->pdev, pnob->mcc_q_size, - &pnob->mcc_q_bus); - if (!pnob->mcc_q_bus) - return -1; - /* - * space for MCC WRB context - */ - pnob->mcc_wrb_ctxtLen = MCC_Q_LEN; - pnob->mcc_wrb_ctxt_size = pnob->mcc_wrb_ctxtLen * - sizeof(struct be_mcc_wrb_context); - pnob->mcc_wrb_ctxt = (void *)__get_free_pages(GFP_KERNEL, - get_order(pnob->mcc_wrb_ctxt_size)); - if (pnob->mcc_wrb_ctxt == NULL) - return -1; - /* - * Space for MCC compl. ring - */ - pnob->mcc_cq_len = MCC_CQ_LEN; - pnob->mcc_cq_size = pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP); - pnob->mcc_cq = pci_alloc_consistent(adapter->pdev, pnob->mcc_cq_size, - &pnob->mcc_cq_bus); - if (!pnob->mcc_cq_bus) - return -1; - return 0; -} - -/* - This function creates the MCC request and completion ring required - for communicating with the ARM processor. The caller must have - allocated required amount of memory for the MCC ring and MCC - completion ring and posted the virtual address and number of - entries in the corresponding members (mcc_q and mcc_cq) in the - NetObject struture. - - When this call is completed, all further communication with - ARM will switch from mailbox to this ring. - - pnob - Pointer to the NetObject structure. This NetObject should - have been created using a previous call to be_create_netobj() -*/ -int be_create_mcc_rings(struct be_net_object *pnob) -{ - int status = 0; - struct ring_desc rd; - struct be_function_object *pfob = &pnob->fn_obj; - - memset(&rd, 0, sizeof(struct ring_desc)); - if (pnob->mcc_cq_len) { - rd.va = pnob->mcc_cq; - rd.pa = pnob->mcc_cq_bus; - rd.length = pnob->mcc_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP), - false, /* solicted events, */ - true, /* nodelay */ - 0, /* 0 Watermark since Nodelay is true */ - &pnob->event_q_obj, - &pnob->mcc_cq_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_cq_id = pnob->mcc_cq_obj.cq_id; - pnob->mcc_cq_created = 1; - } - if (pnob->mcc_q_len) { - rd.va = pnob->mcc_q; - rd.pa = pnob->mcc_q_bus; - rd.length = pnob->mcc_q_size; - - status = be_mcc_ring_create(pfob, &rd, - pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP), - pnob->mcc_wrb_ctxt, pnob->mcc_wrb_ctxtLen, - &pnob->mcc_cq_obj, &pnob->mcc_q_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_q_created = 1; - } - return BE_SUCCESS; -} - -static int be_mcc_init(struct be_adapter *adapter) -{ - u32 r; - struct be_net_object *pnob; - - pnob = adapter->net_obj; - memset(pnob->mcc_q, 0, pnob->mcc_q_size); - pnob->mcc_q_hd = 0; - - memset(pnob->mcc_wrb_ctxt, 0, pnob->mcc_wrb_ctxt_size); - - memset(pnob->mcc_cq, 0, pnob->mcc_cq_size); - pnob->mcc_cq_tl = 0; - - r = be_create_mcc_rings(adapter->net_obj); - if (r != BE_SUCCESS) - return -1; - - return 0; -} - -static void be_remove(struct pci_dev *pdev) -{ - struct be_net_object *pnob; - struct be_adapter *adapter; - - adapter = pci_get_drvdata(pdev); - if (!adapter) - return; - - pci_set_drvdata(pdev, NULL); - pnob = (struct be_net_object *)adapter->net_obj; - - flush_scheduled_work(); - - if (pnob) { - /* Unregister async callback function for link status updates */ - if (pnob->mcc_q_created) - be_mcc_add_async_event_callback(&pnob->mcc_q_obj, - NULL, NULL); - netobject_cleanup(adapter, pnob); - } - - if (adapter->csr_va) - iounmap(adapter->csr_va); - if (adapter->db_va) - iounmap(adapter->db_va); - if (adapter->pci_va) - iounmap(adapter->pci_va); - - pci_release_regions(adapter->pdev); - pci_disable_device(adapter->pdev); - - kfree(adapter->be_link_sts); - kfree(adapter->eth_statsp); - - if (adapter->timer_ctxt.get_stats_timer.function) - del_timer_sync(&adapter->timer_ctxt.get_stats_timer); - kfree(adapter); -} - -/* - * This function is called by the PCI sub-system when it finds a PCI - * device with dev/vendor IDs that match with one of our devices. - * All of the driver initialization is done in this function. - */ -static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) -{ - int status = 0; - struct be_adapter *adapter; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD get_fwv; - struct be_net_object *pnob; - struct net_device *netdev; - - status = pci_enable_device(pdev); - if (status) - goto error; - - status = pci_request_regions(pdev, be_driver_name); - if (status) - goto error_pci_req; - - pci_set_master(pdev); - adapter = kzalloc(sizeof(struct be_adapter), GFP_KERNEL); - if (adapter == NULL) { - status = -ENOMEM; - goto error_adapter; - } - adapter->dev_state = BE_DEV_STATE_NONE; - adapter->pdev = pdev; - pci_set_drvdata(pdev, adapter); - - adapter->enable_aic = 1; - adapter->max_eqd = MAX_EQD; - adapter->min_eqd = 0; - adapter->cur_eqd = 0; - - status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (!status) { - adapter->dma_64bit_cap = true; - } else { - adapter->dma_64bit_cap = false; - status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (status != 0) { - printk(KERN_ERR "Could not set PCI DMA Mask\n"); - goto cleanup; - } - } - - status = init_pci_be_function(adapter, pdev); - if (status != 0) { - printk(KERN_ERR "Failed to map PCI BARS\n"); - status = -ENOMEM; - goto cleanup; - } - - be_trace_set_level(DL_ALWAYS | DL_ERR); - - adapter->be_link_sts = kmalloc(sizeof(struct BE_LINK_STATUS), - GFP_KERNEL); - if (adapter->be_link_sts == NULL) { - printk(KERN_ERR "Memory allocation for link status " - "buffer failed\n"); - goto cleanup; - } - spin_lock_init(&adapter->txq_lock); - - netdev = alloc_etherdev(sizeof(struct be_net_object)); - if (netdev == NULL) { - status = -ENOMEM; - goto cleanup; - } - pnob = netdev_priv(netdev); - adapter->net_obj = pnob; - adapter->netdevp = netdev; - pnob->adapter = adapter; - pnob->netdev = netdev; - - status = be_nob_ring_alloc(adapter, pnob); - if (status != 0) - goto cleanup; - - status = be_nob_ring_init(adapter, pnob); - if (status != 0) - goto cleanup; - - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, false, - false, false, netdev->dev_addr, NULL, NULL); - - netdev->init = &benet_init; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - SET_NETDEV_DEV(netdev, &(adapter->pdev->dev)); - - netif_napi_add(netdev, &pnob->napi, be_poll, 64); - - /* if the rx_frag size if 2K, one page is shared as two RX frags */ - pnob->rx_pg_shared = - (pnob->rx_buf_size <= PAGE_SIZE / 2) ? true : false; - if (pnob->rx_buf_size != rxbuf_size) { - printk(KERN_WARNING - "Could not set Rx buffer size to %d. Using %d\n", - rxbuf_size, pnob->rx_buf_size); - rxbuf_size = pnob->rx_buf_size; - } - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - spin_lock_init(&(adapter->int_lock)); - - status = be_register_isr(adapter, pnob); - if (status != 0) - goto cleanup; - - adapter->rx_csum = 1; - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - memset(&get_fwv, 0, - sizeof(struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD)); - printk(KERN_INFO "BladeEngine Driver version:%s. " - "Copyright ServerEngines, Corporation 2005 - 2008\n", - be_drvr_ver); - status = be_function_get_fw_version(&pnob->fn_obj, &get_fwv, NULL, - NULL); - if (status == BE_SUCCESS) { - strncpy(be_fw_ver, get_fwv.firmware_version_string, 32); - printk(KERN_INFO "BladeEngine Firmware Version:%s\n", - get_fwv.firmware_version_string); - } else { - printk(KERN_WARNING "Unable to get BE Firmware Version\n"); - } - - sema_init(&adapter->get_eth_stat_sem, 0); - init_timer(&adapter->timer_ctxt.get_stats_timer); - atomic_set(&adapter->timer_ctxt.get_stat_flag, 0); - adapter->timer_ctxt.get_stats_timer.function = - &be_get_stats_timer_handler; - - status = be_mcc_create(adapter); - if (status < 0) - goto cleanup; - status = be_mcc_init(adapter); - if (status < 0) - goto cleanup; - - - status = be_mcc_add_async_event_callback(&adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - - status = register_netdev(netdev); - if (status != 0) - goto cleanup; - be_update_link_status(adapter); - adapter->dev_state = BE_DEV_STATE_INIT; - return 0; - -cleanup: - be_remove(pdev); - return status; -error_adapter: - pci_release_regions(pdev); -error_pci_req: - pci_disable_device(pdev); -error: - printk(KERN_ERR "BladeEngine initalization failed\n"); - return status; -} - -/* - * Get the current link status and print the status on console - */ -void be_update_link_status(struct be_adapter *adapter) -{ - int status; - struct be_net_object *pnob = adapter->net_obj; - - status = be_rxf_link_status(&pnob->fn_obj, adapter->be_link_sts, NULL, - NULL, NULL); - if (status == BE_SUCCESS) { - if (adapter->be_link_sts->mac0_speed && - adapter->be_link_sts->mac0_duplex) - adapter->port0_link_sts = BE_PORT_LINK_UP; - else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (adapter->be_link_sts->mac1_speed && - adapter->be_link_sts->mac1_duplex) - adapter->port1_link_sts = BE_PORT_LINK_UP; - else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - dev_info(&pnob->netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - return; - } - dev_info(&pnob->netdev->dev, "Could not get link status\n"); - return; -} - - -#ifdef CONFIG_PM -static void -be_pm_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob, struct net_device *netdev) -{ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - - if (adapter->tasklet_started) { - tasklet_kill(&adapter->sts_handler); - adapter->tasklet_started = 0; - } - - be_unregister_isr(adapter); - be_disable_intr(pnob); - - be_tx_q_clean(pnob); - be_rx_q_clean(pnob); - - be_destroy_netobj(pnob); -} - -static int be_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - adapter->dev_pm_state = adapter->dev_state; - adapter->dev_state = BE_DEV_STATE_SUSPEND; - - netif_device_detach(netdev); - if (netif_running(netdev)) - be_pm_cleanup(adapter, pnob, netdev); - - pci_enable_wake(pdev, 3, 1); - pci_enable_wake(pdev, 4, 1); /* D3 Cold = 4 */ - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static void be_up(struct be_adapter *adapter) -{ - struct be_net_object *pnob = adapter->net_obj; - - if (pnob->num_vlans != 0) - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); - -} - -static int be_resume(struct pci_dev *pdev) -{ - int status = 0; - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - netif_device_detach(netdev); - - status = pci_enable_device(pdev); - if (status) - return status; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 is D3 cold */ - - netif_carrier_on(netdev); - netif_start_queue(netdev); - - if (netif_running(netdev)) { - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, - false, true, false, netdev->dev_addr, NULL, NULL); - - status = be_nob_ring_init(adapter, pnob); - if (status < 0) - return status; - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - - if (be_register_isr(adapter, pnob) != 0) { - printk(KERN_ERR "be_register_isr failed\n"); - return status; - } - - - status = be_mcc_init(adapter); - if (status < 0) { - printk(KERN_ERR "be_mcc_init failed\n"); - return status; - } - be_update_link_status(adapter); - /* - * Register async call back function to handle link - * status updates - */ - status = be_mcc_add_async_event_callback( - &adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - be_up(adapter); - } - netif_device_attach(netdev); - adapter->dev_state = adapter->dev_pm_state; - return 0; - -} - -#endif - -/* Wait until no more pending transmits */ -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *pnob) -{ - int i; - - /* Wait for 20us * 50000 (= 1s) and no more */ - i = 0; - while ((pnob->tx_q_tl != pnob->tx_q_hd) && (i < 50000)) { - ++i; - udelay(20); - } - - /* Check for no more pending transmits */ - if (i >= 50000) { - printk(KERN_WARNING - "Did not receive completions for all TX requests\n"); - } -} - -static struct pci_driver be_driver = { - .name = be_driver_name, - .id_table = be_device_id_table, - .probe = be_probe, -#ifdef CONFIG_PM - .suspend = be_suspend, - .resume = be_resume, -#endif - .remove = be_remove -}; - -/* - * Module init entry point. Registers our our device and return. - * Our probe will be called if the device is found. - */ -static int __init be_init_module(void) -{ - int ret; - - if (rxbuf_size != 8192 && rxbuf_size != 4096 && rxbuf_size != 2048) { - printk(KERN_WARNING - "Unsupported receive buffer size (%d) requested\n", - rxbuf_size); - printk(KERN_WARNING - "Must be 2048, 4096 or 8192. Defaulting to 2048\n"); - rxbuf_size = 2048; - } - - ret = pci_register_driver(&be_driver); - - return ret; -} - -module_init(be_init_module); - -/* - * be_exit_module - Driver Exit Cleanup Routine - */ -static void __exit be_exit_module(void) -{ - pci_unregister_driver(&be_driver); -} - -module_exit(be_exit_module); diff --git a/drivers/staging/benet/be_int.c b/drivers/staging/benet/be_int.c deleted file mode 100644 index cba95d09a8b..00000000000 --- a/drivers/staging/benet/be_int.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include <linux/if_vlan.h> -#include <linux/inet_lro.h> - -#include "benet.h" - -/* number of bytes of RX frame that are copied to skb->data */ -#define BE_HDR_LEN 64 - -#define NETIF_RX(skb) netif_receive_skb(skb) -#define VLAN_ACCEL_RX(skb, pnob, vt) \ - vlan_hwaccel_rx(skb, pnob->vlan_grp, vt) - -/* - This function notifies BladeEngine of the number of completion - entries processed from the specified completion queue by writing - the number of popped entries to the door bell. - - pnob - Pointer to the NetObject structure - n - Number of completion entries processed - cq_id - Queue ID of the completion queue for which notification - is being done. - re_arm - 1 - rearm the completion ring to generate an event. - - 0 - dont rearm the completion ring to generate an event -*/ -void be_notify_cmpl(struct be_net_object *pnob, int n, int cq_id, int re_arm) -{ - struct CQ_DB_AMAP cqdb; - - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, cq_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, n); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - * adds additional receive frags indicated by BE starting from given - * frag index (fi) to specified skb's frag list - */ -static void -add_skb_frags(struct be_net_object *pnob, struct sk_buff *skb, - u32 nresid, u32 fi) -{ - struct be_adapter *adapter = pnob->adapter; - u32 sk_frag_idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size; - - sk_frag_idx = skb_shinfo(skb)->nr_frags; - while (nresid) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = NULL; - if ((rx_page_info->page_offset) || - (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - skb_shinfo(skb)->frags[sk_frag_idx].page = rx_page_info->page; - skb_shinfo(skb)->frags[sk_frag_idx].page_offset - = rx_page_info->page_offset; - skb_shinfo(skb)->frags[sk_frag_idx].size = n; - - sk_frag_idx++; - skb->len += n; - skb->data_len += n; - skb_shinfo(skb)->nr_frags++; - nresid -= n; - - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } -} - -/* - * This function processes incoming nic packets over various Rx queues. - * This function takes the adapter, the current Rx status descriptor - * entry and the Rx completion queue ID as argument. - */ -static inline int process_nic_rx_completion(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct sk_buff *skb; - int udpcksm, tcpcksm; - int n; - u32 nresid, fi; - u32 frag_sz = pnob->rx_buf_size; - u8 *va; - struct be_rx_page_info *rx_page_info; - u32 numfrags, vtp, vtm, vlan_tag, pktsize; - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = NULL; - - /* - * If one page is used per fragment or if this is the second half of - * of the page, unmap the page here - */ - if ((rx_page_info->page_offset) || (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), frag_sz, - PCI_DMA_FROMDEVICE); - } - - atomic_dec(&pnob->rx_q_posted); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - /* - * get rid of RX flush completions first. - */ - if ((tcpcksm) && (udpcksm) && (pktsize == 32)) { - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return 0; - } - skb = netdev_alloc_skb(pnob->netdev, BE_HDR_LEN + NET_IP_ALIGN); - if (skb == NULL) { - dev_info(&pnob->netdev->dev, "alloc_skb() failed\n"); - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - goto free_frags; - } - skb_reserve(skb, NET_IP_ALIGN); - - skb->dev = pnob->netdev; - - n = min(pktsize, frag_sz); - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - - skb->len = n; - skb->data_len = n; - if (n <= BE_HDR_LEN) { - memcpy(skb->data, va, n); - put_page(rx_page_info->page); - skb->data_len -= n; - skb->tail += n; - } else { - - /* Setup the SKB with page buffer information */ - skb_shinfo(skb)->frags[0].page = rx_page_info->page; - skb_shinfo(skb)->nr_frags++; - - /* Copy the header into the skb_data */ - memcpy(skb->data, va, BE_HDR_LEN); - skb_shinfo(skb)->frags[0].page_offset = - rx_page_info->page_offset + BE_HDR_LEN; - skb_shinfo(skb)->frags[0].size = n - BE_HDR_LEN; - skb->data_len -= BE_HDR_LEN; - skb->tail += BE_HDR_LEN; - } - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - nresid = pktsize - n; - - skb->protocol = eth_type_trans(skb, pnob->netdev); - - if ((tcpcksm || udpcksm) && adapter->rx_csum) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - /* - * if we have more bytes left, the frame has been - * given to us in multiple fragments. This happens - * with Jumbo frames. Add the remaining fragments to - * skb->frags[] array. - */ - if (nresid) - add_skb_frags(pnob, skb, nresid, fi); - - /* update the the true size of the skb. */ - skb->truesize = skb->len + sizeof(struct sk_buff); - - /* - * If a 802.3 frame or 802.2 LLC frame - * (i.e) contains length field in MAC Hdr - * and frame len is greater than 64 bytes - */ - if (((skb->protocol == ntohs(ETH_P_802_2)) || - (skb->protocol == ntohs(ETH_P_802_3))) - && (pktsize > BE_HDR_LEN)) { - /* - * If the length given in Mac Hdr is less than frame size - * Erraneous frame, Drop it - */ - if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) < pktsize) { - /* Increment Non Ether type II frames dropped */ - adapter->be_stat.bes_802_3_dropped_frames++; - - kfree_skb(skb); - return 0; - } - /* - * else if the length given in Mac Hdr is greater than - * frame size, should not be seeing this sort of frames - * dump the pkt and pass to stack - */ - else if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) > pktsize) { - /* Increment Non Ether type II frames malformed */ - adapter->be_stat.bes_802_3_malformed_frames++; - } - } - - vtp = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - if (vtp && vtm) { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (!pnob->vlan_grp || pnob->num_vlans == 0) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - kfree_skb(skb); - return 0; - } - /* pass the VLAN packet to stack */ - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - VLAN_ACCEL_RX(skb, pnob, be16_to_cpu(vlan_tag)); - - } else { - NETIF_RX(skb); - } - return 0; - -free_frags: - /* free all frags associated with the current rxcp */ - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - while (numfrags-- > 1) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *) - pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - return -ENOMEM; -} - -static void process_nic_rx_completion_lro(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; - unsigned int udpcksm, tcpcksm; - u32 numfrags, vlanf, vtm, vlan_tag, nresid; - u16 vlant; - unsigned int fi, idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size, pktsize; - bool rx_coal = (adapter->max_rx_coal <= 1) ? 0 : 1; - u8 err, *va; - __wsum csum = 0; - - if (AMAP_GET_BITS_PTR(ETH_RX_COMPL, ipsec, rxcp)) { - /* Drop the pkt and move to the next completion. */ - adapter->be_stat.bes_rx_misc_pkts++; - return; - } - err = AMAP_GET_BITS_PTR(ETH_RX_COMPL, err, rxcp); - if (err || !rx_coal) { - /* We won't coalesce Rx pkts if the err bit set. - * take the path of normal completion processing */ - process_nic_rx_completion(pnob, rxcp); - return; - } - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = (void *)NULL; - /* If one page is used per fragment or if this is the - * second half of the page, unmap the page here - */ - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - vlant = be16_to_cpu(vlan_tag); - vlanf = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - - atomic_dec(&pnob->rx_q_posted); - - if (tcpcksm && udpcksm && pktsize == 32) { - /* flush completion entries */ - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return; - } - /* Only one of udpcksum and tcpcksum can be set */ - BUG_ON(udpcksm && tcpcksm); - - /* jumbo frames could come in multiple fragments */ - BUG_ON(numfrags != ((pktsize + (frag_sz - 1)) / frag_sz)); - n = min(pktsize, frag_sz); - nresid = pktsize - n; /* will be useful for jumbo pkts */ - idx = 0; - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - - /* If we got multiple fragments, we have more data. */ - while (nresid) { - idx++; - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - - nresid -= n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - - if (likely(!(vlanf && vtm))) { - lro_receive_frags(&pnob->lro_mgr, rx_frags, - pktsize, pktsize, - (void *)(unsigned long)csum, csum); - } else { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (unlikely(!pnob->vlan_grp || pnob->num_vlans == 0)) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - return; - } - /* pass the VLAN packet to stack */ - lro_vlan_hwaccel_receive_frags(&pnob->lro_mgr, - rx_frags, pktsize, pktsize, - pnob->vlan_grp, vlant, - (void *)(unsigned long)csum, - csum); - } - - adapter->be_stat.bes_rx_coal++; -} - -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp = &pnob->rx_cq[pnob->rx_cq_tl]; - u32 valid, ct; - - valid = AMAP_GET_BITS_PTR(ETH_RX_COMPL, valid, rxcp); - if (valid == 0) - return NULL; - - ct = AMAP_GET_BITS_PTR(ETH_RX_COMPL, ct, rxcp); - if (ct != 0) { - /* Invalid chute #. treat as error */ - AMAP_SET_BITS_PTR(ETH_RX_COMPL, err, rxcp, 1); - } - - be_adv_rxcq_tl(pnob); - AMAP_SET_BITS_PTR(ETH_RX_COMPL, valid, rxcp, 0); - return rxcp; -} - -static void update_rx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_rx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_rx_bytes / - ((jiffies - adapter->eth_rx_jiffies) / (HZ)); - r = (r / 1000000); /* MB/Sec */ - - /* Mega Bits/Sec */ - adapter->be_stat.bes_eth_rx_rate = (r * 8); - adapter->eth_rx_jiffies = jiffies; - adapter->eth_rx_bytes = 0; - } -} - -static int process_rx_completions(struct be_net_object *pnob, int max_work) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_RX_COMPL_AMAP *rxcp; - u32 nc = 0; - unsigned int pktsize; - - while (max_work && (rxcp = be_get_rx_cmpl(pnob))) { - prefetch(rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - process_nic_rx_completion_lro(pnob, rxcp); - adapter->eth_rx_bytes += pktsize; - update_rx_rate(adapter); - nc++; - max_work--; - adapter->be_stat.bes_rx_compl++; - } - if (likely(adapter->max_rx_coal > 1)) { - adapter->be_stat.bes_rx_flush++; - lro_flush_all(&pnob->lro_mgr); - } - - /* Refill the queue */ - if (atomic_read(&pnob->rx_q_posted) < 900) - be_post_eth_rx_buffs(pnob); - - return nc; -} - -static struct ETH_TX_COMPL_AMAP *be_get_tx_cmpl(struct be_net_object *pnob) -{ - struct ETH_TX_COMPL_AMAP *txcp = &pnob->tx_cq[pnob->tx_cq_tl]; - u32 valid; - - valid = AMAP_GET_BITS_PTR(ETH_TX_COMPL, valid, txcp); - if (valid == 0) - return NULL; - - AMAP_SET_BITS_PTR(ETH_TX_COMPL, valid, txcp, 0); - be_adv_txcq_tl(pnob); - return txcp; - -} - -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx) -{ - struct be_adapter *adapter = pnob->adapter; - int cur_index, tx_wrbs_completed = 0; - struct sk_buff *skb; - u64 busaddr, pa, pa_lo, pa_hi; - struct ETH_WRB_AMAP *wrb; - u32 frag_len, last_index, j; - - last_index = tx_compl_lastwrb_idx_get(pnob); - BUG_ON(last_index != end_idx); - pnob->tx_ctxt[pnob->tx_q_tl] = NULL; - do { - cur_index = pnob->tx_q_tl; - wrb = &pnob->tx_q[cur_index]; - pa_hi = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb); - pa_lo = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb); - frag_len = AMAP_GET_BITS_PTR(ETH_WRB, frag_len, wrb); - busaddr = (pa_hi << 32) | pa_lo; - if (busaddr != 0) { - pa = le64_to_cpu(busaddr); - pci_unmap_single(adapter->pdev, pa, - frag_len, PCI_DMA_TODEVICE); - } - if (cur_index == last_index) { - skb = (struct sk_buff *)pnob->tx_ctxt[cur_index]; - BUG_ON(!skb); - for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) { - struct skb_frag_struct *frag; - frag = &skb_shinfo(skb)->frags[j]; - pci_unmap_page(adapter->pdev, - (ulong) frag->page, frag->size, - PCI_DMA_TODEVICE); - } - kfree_skb(skb); - pnob->tx_ctxt[cur_index] = NULL; - } else { - BUG_ON(pnob->tx_ctxt[cur_index]); - } - tx_wrbs_completed++; - be_adv_txq_tl(pnob); - } while (cur_index != last_index); - atomic_sub(tx_wrbs_completed, &pnob->tx_q_used); -} - -/* there is no need to take an SMP lock here since currently - * we have only one instance of the tasklet that does completion - * processing. - */ -static void process_nic_tx_completions(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_TX_COMPL_AMAP *txcp; - struct net_device *netdev = pnob->netdev; - u32 end_idx, num_processed = 0; - - adapter->be_stat.bes_tx_events++; - - while ((txcp = be_get_tx_cmpl(pnob))) { - end_idx = AMAP_GET_BITS_PTR(ETH_TX_COMPL, wrb_index, txcp); - process_one_tx_compl(pnob, end_idx); - num_processed++; - adapter->be_stat.bes_tx_compl++; - } - be_notify_cmpl(pnob, num_processed, pnob->tx_cq_id, 1); - /* - * We got Tx completions and have usable WRBs. - * If the netdev's queue has been stopped - * because we had run out of WRBs, wake it now. - */ - spin_lock(&adapter->txq_lock); - if (netif_queue_stopped(netdev) - && atomic_read(&pnob->tx_q_used) < pnob->tx_q_len / 2) { - netif_wake_queue(netdev); - } - spin_unlock(&adapter->txq_lock); -} - -static u32 post_rx_buffs(struct be_net_object *pnob, struct list_head *rxbl) -{ - u32 nposted = 0; - struct ETH_RX_D_AMAP *rxd = NULL; - struct be_recv_buffer *rxbp; - void **rx_ctxp; - struct RQ_DB_AMAP rqdb; - - rx_ctxp = pnob->rx_ctxt; - - while (!list_empty(rxbl) && - (rx_ctxp[pnob->rx_q_hd] == NULL) && nposted < 255) { - - rxbp = list_first_entry(rxbl, struct be_recv_buffer, rxb_list); - list_del(&rxbp->rxb_list); - rxd = pnob->rx_q + pnob->rx_q_hd; - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_lo, rxd, rxbp->rxb_pa_lo); - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_hi, rxd, rxbp->rxb_pa_hi); - - rx_ctxp[pnob->rx_q_hd] = rxbp->rxb_ctxt; - be_adv_rxq_hd(pnob); - nposted++; - } - - if (nposted) { - /* Now press the door bell to notify BladeEngine. */ - rqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(RQ_DB, numPosted, &rqdb, nposted); - AMAP_SET_BITS_PTR(RQ_DB, rq, &rqdb, pnob->rx_q_id); - PD_WRITE(&pnob->fn_obj, erx_rq_db, rqdb.dw[0]); - } - atomic_add(nposted, &pnob->rx_q_posted); - return nposted; -} - -void be_post_eth_rx_buffs(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - u32 num_bufs, r; - u64 busaddr = 0, tmp_pa; - u32 max_bufs, pg_hd; - u32 frag_size; - struct be_recv_buffer *rxbp; - struct list_head rxbl; - struct be_rx_page_info *rx_page_info; - struct page *page = NULL; - u32 page_order = 0; - gfp_t alloc_flags = GFP_ATOMIC; - - BUG_ON(!adapter); - - max_bufs = 64; /* should be even # <= 255. */ - - frag_size = pnob->rx_buf_size; - page_order = get_order(frag_size); - - if (frag_size == 8192) - alloc_flags |= (gfp_t) __GFP_COMP; - /* - * Form a linked list of RECV_BUFFFER structure to be be posted. - * We will post even number of buffer so that pages can be - * shared. - */ - INIT_LIST_HEAD(&rxbl); - - for (num_bufs = 0; num_bufs < max_bufs && - !pnob->rx_page_info[pnob->rx_pg_info_hd].page; ++num_bufs) { - - rxbp = &pnob->eth_rx_bufs[num_bufs]; - pg_hd = pnob->rx_pg_info_hd; - rx_page_info = &pnob->rx_page_info[pg_hd]; - - if (!page) { - page = alloc_pages(alloc_flags, page_order); - if (unlikely(page == NULL)) { - adapter->be_stat.bes_ethrx_post_fail++; - pnob->rxbuf_post_fail++; - break; - } - pnob->rxbuf_post_fail = 0; - busaddr = pci_map_page(adapter->pdev, page, 0, - frag_size, PCI_DMA_FROMDEVICE); - rx_page_info->page_offset = 0; - rx_page_info->page = page; - /* - * If we are sharing a page among two skbs, - * alloc a new one on the next iteration - */ - if (pnob->rx_pg_shared == false) - page = NULL; - } else { - get_page(page); - rx_page_info->page_offset += frag_size; - rx_page_info->page = page; - /* - * We are finished with the alloced page, - * Alloc a new one on the next iteration - */ - page = NULL; - } - rxbp->rxb_ctxt = (void *)rx_page_info; - index_inc(&pnob->rx_pg_info_hd, pnob->rx_q_len); - - pci_unmap_addr_set(rx_page_info, bus, busaddr); - tmp_pa = busaddr + rx_page_info->page_offset; - rxbp->rxb_pa_lo = (tmp_pa & 0xFFFFFFFF); - rxbp->rxb_pa_hi = (tmp_pa >> 32); - rxbp->rxb_len = frag_size; - list_add_tail(&rxbp->rxb_list, &rxbl); - } /* End of for */ - - r = post_rx_buffs(pnob, &rxbl); - BUG_ON(r != num_bufs); - return; -} - -/* - * Interrupt service for network function. We just schedule the - * tasklet which does all completion processing. - */ -irqreturn_t be_int(int irq, void *dev) -{ - struct net_device *netdev = dev; - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 isr; - - isr = CSR_READ(&pnob->fn_obj, cev.isr1); - if (unlikely(!isr)) - return IRQ_NONE; - - spin_lock(&adapter->int_lock); - adapter->isr |= isr; - spin_unlock(&adapter->int_lock); - - adapter->be_stat.bes_ints++; - - tasklet_schedule(&adapter->sts_handler); - return IRQ_HANDLED; -} - -/* - * Poll function called by NAPI with a work budget. - * We process as many UC. BC and MC receive completions - * as the budget allows and return the actual number of - * RX ststutses processed. - */ -int be_poll(struct napi_struct *napi, int budget) -{ - struct be_net_object *pnob = - container_of(napi, struct be_net_object, napi); - u32 work_done; - - pnob->adapter->be_stat.bes_polls++; - work_done = process_rx_completions(pnob, budget); - BUG_ON(work_done > budget); - - /* All consumed */ - if (work_done < budget) { - netif_rx_complete(napi); - /* enable intr */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 1); - } else { - /* More to be consumed; continue with interrupts disabled */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 0); - } - return work_done; -} - -static struct EQ_ENTRY_AMAP *get_event(struct be_net_object *pnob) -{ - struct EQ_ENTRY_AMAP *eqp = &(pnob->event_q[pnob->event_q_tl]); - if (!AMAP_GET_BITS_PTR(EQ_ENTRY, Valid, eqp)) - return NULL; - be_adv_eq_tl(pnob); - return eqp; -} - -/* - * Processes all valid events in the event ring associated with given - * NetObject. Also, notifies BE the number of events processed. - */ -static inline u32 process_events(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct EQ_ENTRY_AMAP *eqp; - u32 rid, num_events = 0; - struct net_device *netdev = pnob->netdev; - - while ((eqp = get_event(pnob)) != NULL) { - adapter->be_stat.bes_events++; - rid = AMAP_GET_BITS_PTR(EQ_ENTRY, ResourceID, eqp); - if (rid == pnob->rx_cq_id) { - adapter->be_stat.bes_rx_events++; - netif_rx_schedule(&pnob->napi); - } else if (rid == pnob->tx_cq_id) { - process_nic_tx_completions(pnob); - } else if (rid == pnob->mcc_cq_id) { - be_mcc_process_cq(&pnob->mcc_q_obj, 1); - } else { - dev_info(&netdev->dev, - "Invalid EQ ResourceID %d\n", rid); - } - AMAP_SET_BITS_PTR(EQ_ENTRY, Valid, eqp, 0); - AMAP_SET_BITS_PTR(EQ_ENTRY, ResourceID, eqp, 0); - num_events++; - } - return num_events; -} - -static void update_eqd(struct be_adapter *adapter, struct be_net_object *pnob) -{ - int status; - struct be_eq_object *eq_objectp; - - /* update once a second */ - if ((jiffies - adapter->ips_jiffies) > 1 * (HZ)) { - /* One second elapsed since last update */ - u32 r, new_eqd = -1; - r = adapter->be_stat.bes_ints - adapter->be_stat.bes_prev_ints; - r = r / ((jiffies - adapter->ips_jiffies) / (HZ)); - adapter->be_stat.bes_ips = r; - adapter->ips_jiffies = jiffies; - adapter->be_stat.bes_prev_ints = adapter->be_stat.bes_ints; - if (r > IPS_HI_WM && adapter->cur_eqd < adapter->max_eqd) - new_eqd = (adapter->cur_eqd + 8); - if (r < IPS_LO_WM && adapter->cur_eqd > adapter->min_eqd) - new_eqd = (adapter->cur_eqd - 8); - if (adapter->enable_aic && new_eqd != -1) { - eq_objectp = &pnob->event_q_obj; - status = be_eq_modify_delay(&pnob->fn_obj, 1, - &eq_objectp, &new_eqd, NULL, - NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = new_eqd; - } - } -} - -/* - This function notifies BladeEngine of how many events were processed - from the event queue by ringing the corresponding door bell and - optionally re-arms the event queue. - n - number of events processed - re_arm - 1 - re-arm the EQ, 0 - do not re-arm the EQ - -*/ -static void be_notify_event(struct be_net_object *pnob, int n, int re_arm) -{ - struct CQ_DB_AMAP eqdb; - eqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(CQ_DB, qid, &eqdb, pnob->event_q_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &eqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, event, &eqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &eqdb, n); - /* - * Under some situations we see an interrupt and no valid - * EQ entry. To keep going, we need to ring the DB even if - * numPOsted is 0. - */ - PD_WRITE(&pnob->fn_obj, cq_db, eqdb.dw[0]); - return; -} - -/* - * Called from the tasklet scheduled by ISR. All real interrupt processing - * is done here. - */ -void be_process_intr(unsigned long context) -{ - struct be_adapter *adapter = (struct be_adapter *)context; - struct be_net_object *pnob = adapter->net_obj; - u32 isr, n; - ulong flags = 0; - - isr = adapter->isr; - - /* - * we create only one NIC event queue in Linux. Event is - * expected only in the first event queue - */ - BUG_ON(isr & 0xfffffffe); - if ((isr & 1) == 0) - return; /* not our interrupt */ - n = process_events(pnob); - /* - * Clear the event bit. adapter->isr is set by - * hard interrupt. Prevent race with lock. - */ - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->isr &= ~1; - spin_unlock_irqrestore(&adapter->int_lock, flags); - be_notify_event(pnob, n, 1); - /* - * If previous allocation attempts had failed and - * BE has used up all posted buffers, post RX buffers here - */ - if (pnob->rxbuf_post_fail && atomic_read(&pnob->rx_q_posted) == 0) - be_post_eth_rx_buffs(pnob); - update_eqd(adapter, pnob); - return; -} diff --git a/drivers/staging/benet/be_netif.c b/drivers/staging/benet/be_netif.c deleted file mode 100644 index 2b8daf63dc7..00000000000 --- a/drivers/staging/benet/be_netif.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_netif.c - * - * This file contains various entry points of drivers seen by tcp/ip stack. - */ - -#include <linux/if_vlan.h> -#include <linux/in.h> -#include "benet.h" -#include <linux/ip.h> -#include <linux/inet_lro.h> - -/* Strings to print Link properties */ -static const char *link_speed[] = { - "Invalid link Speed Value", - "10 Mbps", - "100 Mbps", - "1 Gbps", - "10 Gbps" -}; - -static const char *link_duplex[] = { - "Invalid Duplex Value", - "Half Duplex", - "Full Duplex" -}; - -static const char *link_state[] = { - "", - "(active)" -}; - -void be_print_link_info(struct BE_LINK_STATUS *lnk_status) -{ - u16 si, di, ai; - - /* Port 0 */ - if (lnk_status->mac0_speed && lnk_status->mac0_duplex) { - /* Port is up and running */ - si = (lnk_status->mac0_speed < 5) ? lnk_status->mac0_speed : 0; - di = (lnk_status->mac0_duplex < 3) ? - lnk_status->mac0_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 0: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 0: Down\n"); - - /* Port 1 */ - if (lnk_status->mac1_speed && lnk_status->mac1_duplex) { - /* Port is up and running */ - si = (lnk_status->mac1_speed < 5) ? lnk_status->mac1_speed : 0; - di = (lnk_status->mac1_duplex < 3) ? - lnk_status->mac1_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 1: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 1: Down\n"); - - return; -} - -static int -be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) -{ - struct ethhdr *eh; - struct vlan_ethhdr *veh; - struct iphdr *iph; - u8 *va = page_address(frag->page) + frag->page_offset; - unsigned long ll_hlen; - - /* find the mac header, abort if not IPv4 */ - - prefetch(va); - eh = (struct ethhdr *)va; - *mac_hdr = eh; - ll_hlen = ETH_HLEN; - if (eh->h_proto != htons(ETH_P_IP)) { - if (eh->h_proto == htons(ETH_P_8021Q)) { - veh = (struct vlan_ethhdr *)va; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - return -1; - - ll_hlen += VLAN_HLEN; - - } else { - return -1; - } - } - *hdr_flags = LRO_IPV4; - - iph = (struct iphdr *)(va + ll_hlen); - *ip_hdr = iph; - if (iph->protocol != IPPROTO_TCP) - return -1; - *hdr_flags |= LRO_TCP; - *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); - - return 0; -} - -static int benet_open(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct net_lro_mgr *lro_mgr; - - if (adapter->dev_state < BE_DEV_STATE_INIT) - return -EAGAIN; - - lro_mgr = &pnob->lro_mgr; - lro_mgr->dev = netdev; - - lro_mgr->features = LRO_F_NAPI; - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = pnob->lro_desc; - lro_mgr->get_frag_header = be_get_frag_header; - lro_mgr->max_aggr = adapter->max_rx_coal; - lro_mgr->frag_align_pad = 2; - if (lro_mgr->max_aggr > MAX_SKB_FRAGS) - lro_mgr->max_aggr = MAX_SKB_FRAGS; - - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - be_update_link_status(adapter); - - /* - * Set carrier on only if Physical Link up - * Either of the port link status up signifies this - */ - if ((adapter->port0_link_sts == BE_PORT_LINK_UP) || - (adapter->port1_link_sts == BE_PORT_LINK_UP)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - - adapter->dev_state = BE_DEV_STATE_OPEN; - napi_enable(&pnob->napi); - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - /* - * RX completion queue may be in dis-armed state. Arm it. - */ - be_notify_cmpl(pnob, 0, pnob->rx_cq_id, 1); - - return 0; -} - -static int benet_close(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - netif_stop_queue(netdev); - synchronize_irq(netdev->irq); - - be_wait_nic_tx_cmplx_cmpl(pnob); - adapter->dev_state = BE_DEV_STATE_INIT; - netif_carrier_off(netdev); - - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - be_disable_intr(pnob); - be_disable_eq_intr(pnob); - napi_disable(&pnob->napi); - - return 0; -} - -/* - * Setting a Mac Address for BE - * Takes netdev and a void pointer as arguments. - * The pointer holds the new addres to be used. - */ -static int benet_set_mac_addr(struct net_device *netdev, void *p) -{ - struct sockaddr *addr = p; - struct be_net_object *pnob = netdev_priv(netdev); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - be_rxf_mac_address_read_write(&pnob->fn_obj, 0, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - /* - * Since we are doing Active-Passive failover, both - * ports should have matching MAC addresses everytime. - */ - be_rxf_mac_address_read_write(&pnob->fn_obj, 1, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - - return 0; -} - -void be_get_stats_timer_handler(unsigned long context) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } - del_timer(&ctxt->get_stats_timer); - return; -} - -void be_get_stat_cb(void *context, int status, - struct MCC_WRB_AMAP *optional_wrb) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - /* - * just up the semaphore if the get_stat_flag - * reads 1. so that the waiter can continue. - * If it is 0, then it was handled by the timer handler. - */ - del_timer(&ctxt->get_stats_timer); - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } -} - -struct net_device_stats *benet_get_stats(struct net_device *dev) -{ - struct be_net_object *pnob = netdev_priv(dev); - struct be_adapter *adapter = pnob->adapter; - u64 pa; - struct be_timer_ctxt *ctxt = &adapter->timer_ctxt; - - if (adapter->dev_state != BE_DEV_STATE_OPEN) { - /* Return previously read stats */ - return &(adapter->benet_stats); - } - /* Get Physical Addr */ - pa = pci_map_single(adapter->pdev, adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - ctxt->get_stat_sem_addr = (unsigned long)&adapter->get_eth_stat_sem; - atomic_inc(&ctxt->get_stat_flag); - - be_rxf_query_eth_statistics(&pnob->fn_obj, adapter->eth_statsp, - cpu_to_le64(pa), be_get_stat_cb, ctxt, - NULL); - - ctxt->get_stats_timer.data = (unsigned long)ctxt; - mod_timer(&ctxt->get_stats_timer, (jiffies + (HZ * 2))); - down((void *)ctxt->get_stat_sem_addr); /* callback will unblock us */ - - /* Adding port0 and port1 stats. */ - adapter->benet_stats.rx_packets = - adapter->eth_statsp->params.response.p0recvdtotalframes + - adapter->eth_statsp->params.response.p1recvdtotalframes; - adapter->benet_stats.tx_packets = - adapter->eth_statsp->params.response.p0xmitunicastframes + - adapter->eth_statsp->params.response.p1xmitunicastframes; - adapter->benet_stats.tx_bytes = - adapter->eth_statsp->params.response.p0xmitbyteslsd + - adapter->eth_statsp->params.response.p1xmitbyteslsd; - adapter->benet_stats.rx_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_bytes = - adapter->eth_statsp->params.response.p0recvdtotalbytesLSD + - adapter->eth_statsp->params.response.p1recvdtotalbytesLSD; - adapter->benet_stats.rx_crc_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitbroadcastframes + - adapter->eth_statsp->params.response.p1xmitbroadcastframes; - adapter->benet_stats.tx_errors = 0; - - adapter->benet_stats.multicast = - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - - adapter->benet_stats.rx_fifo_errors = - adapter->eth_statsp->params.response.p0rxfifooverflowdropped + - adapter->eth_statsp->params.response.p1rxfifooverflowdropped; - adapter->benet_stats.rx_frame_errors = - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_length_errors = - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0outrangeerrors + - adapter->eth_statsp->params.response.p1outrangeerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0frametoolongerrors + - adapter->eth_statsp->params.response.p1frametoolongerrors; - - pci_unmap_single(adapter->pdev, (ulong) adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - return &(adapter->benet_stats); - -} - -static void be_start_tx(struct be_net_object *pnob, u32 nposted) -{ -#define CSR_ETH_MAX_SQPOSTS 255 - struct SQ_DB_AMAP sqdb; - - sqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(SQ_DB, cid, &sqdb, pnob->tx_q_id); - while (nposted) { - if (nposted > CSR_ETH_MAX_SQPOSTS) { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, - CSR_ETH_MAX_SQPOSTS); - nposted -= CSR_ETH_MAX_SQPOSTS; - } else { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, nposted); - nposted = 0; - } - PD_WRITE(&pnob->fn_obj, etx_sq_db, sqdb.dw[0]); - } - - return; -} - -static void update_tx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_tx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_tx_bytes / - ((jiffies - adapter->eth_tx_jiffies) / (HZ)); - r = (r / 1000000); /* M bytes/s */ - adapter->be_stat.bes_eth_tx_rate = (r * 8); /* M bits/s */ - adapter->eth_tx_jiffies = jiffies; - adapter->eth_tx_bytes = 0; - } -} - -static int wrb_cnt_in_skb(struct sk_buff *skb) -{ - int cnt = 0; - while (skb) { - if (skb->len > skb->data_len) - cnt++; - cnt += skb_shinfo(skb)->nr_frags; - skb = skb_shinfo(skb)->frag_list; - } - BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); - return cnt; -} - -static void wrb_fill(struct ETH_WRB_AMAP *wrb, u64 addr, int len) -{ - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb, addr >> 32); - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb, addr & 0xFFFFFFFF); - AMAP_SET_BITS_PTR(ETH_WRB, frag_len, wrb, len); -} - -static void wrb_fill_extra(struct ETH_WRB_AMAP *wrb, struct sk_buff *skb, - struct be_net_object *pnob) -{ - wrb->dw[2] = 0; - wrb->dw[3] = 0; - AMAP_SET_BITS_PTR(ETH_WRB, crc, wrb, 1); - if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { - AMAP_SET_BITS_PTR(ETH_WRB, lso, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, lso_mss, wrb, - skb_shinfo(skb)->gso_size); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 proto = ((struct iphdr *)ip_hdr(skb))->protocol; - if (proto == IPPROTO_TCP) - AMAP_SET_BITS_PTR(ETH_WRB, tcpcs, wrb, 1); - else if (proto == IPPROTO_UDP) - AMAP_SET_BITS_PTR(ETH_WRB, udpcs, wrb, 1); - } - if (pnob->vlan_grp && vlan_tx_tag_present(skb)) { - AMAP_SET_BITS_PTR(ETH_WRB, vlan, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, vlan_tag, wrb, vlan_tx_tag_get(skb)); - } -} - -static inline void wrb_copy_extra(struct ETH_WRB_AMAP *to, - struct ETH_WRB_AMAP *from) -{ - - to->dw[2] = from->dw[2]; - to->dw[3] = from->dw[3]; -} - -/* Returns the actual count of wrbs used including a possible dummy */ -static int copy_skb_to_txq(struct be_net_object *pnob, struct sk_buff *skb, - u32 wrb_cnt, u32 *copied) -{ - u64 busaddr; - struct ETH_WRB_AMAP *wrb = NULL, *first = NULL; - u32 i; - bool dummy = true; - struct pci_dev *pdev = pnob->adapter->pdev; - - if (wrb_cnt & 1) - wrb_cnt++; - else - dummy = false; - - atomic_add(wrb_cnt, &pnob->tx_q_used); - - 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); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, len); - be_adv_txq_hd(pnob); - *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); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, frag->size); - be_adv_txq_hd(pnob); - *copied += frag->size; - } - skb = skb_shinfo(skb)->frag_list; - } - - if (dummy) { - wrb = &pnob->tx_q[pnob->tx_q_hd]; - BUG_ON(first == NULL); - wrb_copy_extra(wrb, first); - wrb_fill(wrb, 0, 0); - be_adv_txq_hd(pnob); - } - AMAP_SET_BITS_PTR(ETH_WRB, complete, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, last, wrb, 1); - return wrb_cnt; -} - -/* For each skb transmitted, tx_ctxt stores the num of wrbs in the - * start index and skb pointer in the end index - */ -static inline void be_tx_wrb_info_remember(struct be_net_object *pnob, - struct sk_buff *skb, int wrb_cnt, - u32 start) -{ - *(u32 *) (&pnob->tx_ctxt[start]) = wrb_cnt; - index_adv(&start, wrb_cnt - 1, pnob->tx_q_len); - pnob->tx_ctxt[start] = skb; -} - -static int benet_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 wrb_cnt, copied = 0; - u32 start = pnob->tx_q_hd; - - adapter->be_stat.bes_tx_reqs++; - - wrb_cnt = wrb_cnt_in_skb(skb); - spin_lock_bh(&adapter->txq_lock); - if ((pnob->tx_q_len - 2 - atomic_read(&pnob->tx_q_used)) <= wrb_cnt) { - netif_stop_queue(pnob->netdev); - spin_unlock_bh(&adapter->txq_lock); - adapter->be_stat.bes_tx_fails++; - return NETDEV_TX_BUSY; - } - spin_unlock_bh(&adapter->txq_lock); - - wrb_cnt = copy_skb_to_txq(pnob, skb, wrb_cnt, &copied); - be_tx_wrb_info_remember(pnob, skb, wrb_cnt, start); - - be_start_tx(pnob, wrb_cnt); - - adapter->eth_tx_bytes += copied; - adapter->be_stat.bes_tx_wrbs += wrb_cnt; - update_tx_rate(adapter); - netdev->trans_start = jiffies; - - return NETDEV_TX_OK; -} - -/* - * This is the driver entry point to change the mtu of the device - * Returns 0 for success and errno for failure. - */ -static int benet_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* - * BE supports jumbo frame size upto 9000 bytes including the link layer - * header. Considering the different variants of frame formats possible - * like VLAN, SNAP/LLC, the maximum possible value for MTU is 8974 bytes - */ - - if (new_mtu < (ETH_ZLEN + ETH_FCS_LEN) || (new_mtu > BE_MAX_MTU)) { - dev_info(&netdev->dev, "Invalid MTU requested. " - "Must be between %d and %d bytes\n", - (ETH_ZLEN + ETH_FCS_LEN), BE_MAX_MTU); - return -EINVAL; - } - dev_info(&netdev->dev, "MTU changed from %d to %d\n", - netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - return 0; -} - -/* - * This is the driver entry point to register a vlan with the device - */ -static void benet_vlan_register(struct net_device *netdev, - struct vlan_group *grp) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - be_disable_eq_intr(pnob); - pnob->vlan_grp = grp; - pnob->num_vlans = 0; - be_enable_eq_intr(pnob); -} - -/* - * This is the driver entry point to add a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_add_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (pnob->num_vlans == (BE_NUM_VLAN_SUPPORTED - 1)) { - /* no way to return an error */ - dev_info(&netdev->dev, - "BladeEngine: Cannot configure more than %d Vlans\n", - BE_NUM_VLAN_SUPPORTED); - return; - } - /* The new vlan tag will be in the slot indicated by num_vlans. */ - pnob->vlan_tag[pnob->num_vlans++] = vlan_id; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This is the driver entry point to remove a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_rem_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - u32 i, value; - - /* - * In Blade Engine, we support 32 vlan tag filters across both ports. - * To program a vlan tag, the RXF_RTPR_CSR register is used. - * Each 32-bit value of RXF_RTDR_CSR can address 2 vlan tag entries. - * The Vlan table is of depth 16. thus we support 32 tags. - */ - - value = vlan_id | VLAN_VALID_BIT; - for (i = 0; i < BE_NUM_VLAN_SUPPORTED; i++) { - if (pnob->vlan_tag[i] == vlan_id) - break; - } - - if (i == BE_NUM_VLAN_SUPPORTED) - return; - /* Now compact the vlan tag array by removing hole created. */ - while ((i + 1) < BE_NUM_VLAN_SUPPORTED) { - pnob->vlan_tag[i] = pnob->vlan_tag[i + 1]; - i++; - } - if ((i + 1) == BE_NUM_VLAN_SUPPORTED) - pnob->vlan_tag[i] = (u16) 0x0; - pnob->num_vlans--; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This function is called to program multicast - * address in the multicast filter of the ASIC. - */ -static void be_set_multicast_filter(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; - u8 mac_addr[32][ETH_ALEN]; - int i; - - if (netdev->flags & IFF_ALLMULTI) { - /* set BE in Multicast promiscuous */ - be_rxf_multicast_config(&pnob->fn_obj, true, 0, NULL, NULL, - NULL, NULL); - return; - } - - for (mc_ptr = netdev->mc_list, i = 0; mc_ptr; - mc_ptr = mc_ptr->next, i++) { - memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); - } - - /* reset the promiscuous mode also. */ - be_rxf_multicast_config(&pnob->fn_obj, false, i, - &mac_addr[0][0], NULL, NULL, NULL); -} - -/* - * This is the driver entry point to set multicast list - * with the device netdev. This function will be used to - * set promiscuous mode or multicast promiscuous mode - * or multicast mode.... - */ -static void benet_set_multicast_list(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (netdev->flags & IFF_PROMISC) { - be_rxf_promiscuous(&pnob->fn_obj, 1, 1, NULL, NULL, NULL); - } else { - be_rxf_promiscuous(&pnob->fn_obj, 0, 0, NULL, NULL, NULL); - be_set_multicast_filter(netdev); - } -} - -int benet_init(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - ether_setup(netdev); - - netdev->open = &benet_open; - netdev->stop = &benet_close; - netdev->hard_start_xmit = &benet_xmit; - - netdev->get_stats = &benet_get_stats; - - netdev->set_multicast_list = &benet_set_multicast_list; - - netdev->change_mtu = &benet_change_mtu; - netdev->set_mac_address = &benet_set_mac_addr; - - netdev->vlan_rx_register = benet_vlan_register; - netdev->vlan_rx_add_vid = benet_vlan_add_vid; - netdev->vlan_rx_kill_vid = benet_vlan_rem_vid; - - netdev->features = - NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM; - - netdev->flags |= IFF_MULTICAST; - - /* If device is DAC Capable, set the HIGHDMA flag for netdevice. */ - if (adapter->dma_64bit_cap) - netdev->features |= NETIF_F_HIGHDMA; - - SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); - return 0; -} diff --git a/drivers/staging/benet/benet.h b/drivers/staging/benet/benet.h deleted file mode 100644 index 09a1f081772..00000000000 --- a/drivers/staging/benet/benet.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BENET_H_ -#define _BENET_H_ - -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/inet_lro.h> -#include "hwlib.h" - -#define _SA_MODULE_NAME "net-driver" - -#define VLAN_VALID_BIT 0x8000 -#define BE_NUM_VLAN_SUPPORTED 32 -#define BE_PORT_LINK_DOWN 0000 -#define BE_PORT_LINK_UP 0001 -#define BE_MAX_TX_FRAG_COUNT (30) - -/* Flag bits for send operation */ -#define IPCS (1 << 0) /* Enable IP checksum offload */ -#define UDPCS (1 << 1) /* Enable UDP checksum offload */ -#define TCPCS (1 << 2) /* Enable TCP checksum offload */ -#define LSO (1 << 3) /* Enable Large Segment offload */ -#define ETHVLAN (1 << 4) /* Enable VLAN insert */ -#define ETHEVENT (1 << 5) /* Generate event on completion */ -#define ETHCOMPLETE (1 << 6) /* Generate completion when done */ -#define IPSEC (1 << 7) /* Enable IPSEC */ -#define FORWARD (1 << 8) /* Send the packet in forwarding path */ -#define FIN (1 << 9) /* Issue FIN segment */ - -#define BE_MAX_MTU 8974 - -#define BE_MAX_LRO_DESCRIPTORS 8 -#define BE_LRO_MAX_PKTS 64 -#define BE_MAX_FRAGS_PER_FRAME 6 - -extern const char be_drvr_ver[]; -extern char be_fw_ver[]; -extern char be_driver_name[]; - -extern struct ethtool_ops be_ethtool_ops; - -#define BE_DEV_STATE_NONE 0 -#define BE_DEV_STATE_INIT 1 -#define BE_DEV_STATE_OPEN 2 -#define BE_DEV_STATE_SUSPEND 3 - -/* This structure is used to describe physical fragments to use - * for DMAing data from NIC. - */ -struct be_recv_buffer { - struct list_head rxb_list; /* for maintaining a linked list */ - void *rxb_va; /* buffer virtual address */ - u32 rxb_pa_lo; /* low part of physical address */ - u32 rxb_pa_hi; /* high part of physical address */ - u32 rxb_len; /* length of recv buffer */ - void *rxb_ctxt; /* context for OSM driver to use */ -}; - -/* - * fragment list to describe scattered data. - */ -struct be_tx_frag_list { - u32 txb_len; /* Size of this fragment */ - u32 txb_pa_lo; /* Lower 32 bits of 64 bit physical addr */ - u32 txb_pa_hi; /* Higher 32 bits of 64 bit physical addr */ -}; - -struct be_rx_page_info { - struct page *page; - dma_addr_t bus; - u16 page_offset; -}; - -/* - * This structure is the main tracking structure for a NIC interface. - */ -struct be_net_object { - /* MCC Ring - used to send fwcmds to embedded ARM processor */ - struct MCC_WRB_AMAP *mcc_q; /* VA of the start of the ring */ - u32 mcc_q_len; /* # of WRB entries in this ring */ - u32 mcc_q_size; - u32 mcc_q_hd; /* MCC ring head */ - u8 mcc_q_created; /* flag to help cleanup */ - struct be_mcc_object mcc_q_obj; /* BECLIB's MCC ring Object */ - dma_addr_t mcc_q_bus; /* DMA'ble bus address */ - - /* MCC Completion Ring - FW responses to fwcmds sent from MCC ring */ - struct MCC_CQ_ENTRY_AMAP *mcc_cq; /* VA of the start of the ring */ - u32 mcc_cq_len; /* # of compl. entries in this ring */ - u32 mcc_cq_size; - u32 mcc_cq_tl; /* compl. ring tail */ - u8 mcc_cq_created; /* flag to help cleanup */ - struct be_cq_object mcc_cq_obj; /* BECLIB's MCC compl. ring object */ - u32 mcc_cq_id; /* MCC ring ID */ - dma_addr_t mcc_cq_bus; /* DMA'ble bus address */ - - struct ring_desc mb_rd; /* RD for MCC_MAIL_BOX */ - void *mb_ptr; /* mailbox ptr to be freed */ - dma_addr_t mb_bus; /* DMA'ble bus address */ - u32 mb_size; - - /* BEClib uses an array of context objects to track outstanding - * requests to the MCC. We need allocate the same number of - * conext entries as the number of entries in the MCC WRB ring - */ - u32 mcc_wrb_ctxt_size; - void *mcc_wrb_ctxt; /* pointer to the context area */ - u32 mcc_wrb_ctxtLen; /* Number of entries in the context */ - /* - * NIC send request ring - used for xmitting raw ether frames. - */ - struct ETH_WRB_AMAP *tx_q; /* VA of the start of the ring */ - u32 tx_q_len; /* # if entries in the send ring */ - u32 tx_q_size; - u32 tx_q_hd; /* Head index. Next req. goes here */ - u32 tx_q_tl; /* Tail indx. oldest outstanding req. */ - u8 tx_q_created; /* flag to help cleanup */ - struct be_ethsq_object tx_q_obj;/* BECLIB's send Q handle */ - dma_addr_t tx_q_bus; /* DMA'ble bus address */ - u32 tx_q_id; /* send queue ring ID */ - u32 tx_q_port; /* 0 no binding, 1 port A, 2 port B */ - atomic_t tx_q_used; /* # of WRBs used */ - /* ptr to an array in which we store context info for each send req. */ - void **tx_ctxt; - /* - * NIC Send compl. ring - completion status for all NIC frames xmitted. - */ - struct ETH_TX_COMPL_AMAP *tx_cq;/* VA of start of the ring */ - u32 txcq_len; /* # of entries in the ring */ - u32 tx_cq_size; - /* - * index into compl ring where the host expects next completion entry - */ - u32 tx_cq_tl; - u32 tx_cq_id; /* completion queue id */ - u8 tx_cq_created; /* flag to help cleanup */ - struct be_cq_object tx_cq_obj; - dma_addr_t tx_cq_bus; /* DMA'ble bus address */ - /* - * Event Queue - all completion entries post events here. - */ - struct EQ_ENTRY_AMAP *event_q; /* VA of start of event queue */ - u32 event_q_len; /* # of entries */ - u32 event_q_size; - u32 event_q_tl; /* Tail of the event queue */ - u32 event_q_id; /* Event queue ID */ - u8 event_q_created; /* flag to help cleanup */ - struct be_eq_object event_q_obj; /* Queue handle */ - dma_addr_t event_q_bus; /* DMA'ble bus address */ - /* - * NIC receive queue - Data buffers to be used for receiving unicast, - * broadcast and multi-cast frames are posted here. - */ - struct ETH_RX_D_AMAP *rx_q; /* VA of start of the queue */ - u32 rx_q_len; /* # of entries */ - u32 rx_q_size; - u32 rx_q_hd; /* Head of the queue */ - atomic_t rx_q_posted; /* number of posted buffers */ - u32 rx_q_id; /* queue ID */ - u8 rx_q_created; /* flag to help cleanup */ - struct be_ethrq_object rx_q_obj; /* NIC RX queue handle */ - dma_addr_t rx_q_bus; /* DMA'ble bus address */ - /* - * Pointer to an array of opaque context object for use by OSM driver - */ - void **rx_ctxt; - /* - * NIC unicast RX completion queue - all unicast ether frame completion - * statuses from BE come here. - */ - struct ETH_RX_COMPL_AMAP *rx_cq; /* VA of start of the queue */ - u32 rx_cq_len; /* # of entries */ - u32 rx_cq_size; - u32 rx_cq_tl; /* Tail of the queue */ - u32 rx_cq_id; /* queue ID */ - u8 rx_cq_created; /* flag to help cleanup */ - struct be_cq_object rx_cq_obj; /* queue handle */ - dma_addr_t rx_cq_bus; /* DMA'ble bus address */ - struct be_function_object fn_obj; /* function object */ - bool fn_obj_created; - u32 rx_buf_size; /* Size of the RX buffers */ - - struct net_device *netdev; - struct be_recv_buffer eth_rx_bufs[256]; /* to pass Rx buffer - addresses */ - struct be_adapter *adapter; /* Pointer to OSM adapter */ - u32 devno; /* OSM, network dev no. */ - u32 use_port; /* Current active port */ - struct be_rx_page_info *rx_page_info; /* Array of Rx buf pages */ - u32 rx_pg_info_hd; /* Head of queue */ - int rxbuf_post_fail; /* RxBuff posting fail count */ - bool rx_pg_shared; /* Is an allocsted page shared as two frags ? */ - struct vlan_group *vlan_grp; - u32 num_vlans; /* Number of vlans in BE's filter */ - u16 vlan_tag[BE_NUM_VLAN_SUPPORTED]; /* vlans currently configured */ - struct napi_struct napi; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; -}; - -#define NET_FH(np) (&(np)->fn_obj) - -/* - * BE driver statistics. - */ -struct be_drvr_stat { - u32 bes_tx_reqs; /* number of TX requests initiated */ - u32 bes_tx_fails; /* number of TX requests that failed */ - u32 bes_fwd_reqs; /* number of send reqs through forwarding i/f */ - u32 bes_tx_wrbs; /* number of tx WRBs used */ - - u32 bes_ints; /* number of interrupts */ - u32 bes_polls; /* number of times NAPI called poll function */ - u32 bes_events; /* total evet entries processed */ - u32 bes_tx_events; /* number of tx completion events */ - u32 bes_rx_events; /* number of ucast rx completion events */ - u32 bes_tx_compl; /* number of tx completion entries processed */ - u32 bes_rx_compl; /* number of rx completion entries - processed */ - u32 bes_ethrx_post_fail; /* number of ethrx buffer alloc - failures */ - /* - * number of non ether type II frames dropped where - * frame len > length field of Mac Hdr - */ - u32 bes_802_3_dropped_frames; - /* - * number of non ether type II frames malformed where - * in frame len < length field of Mac Hdr - */ - u32 bes_802_3_malformed_frames; - u32 bes_ips; /* interrupts / sec */ - u32 bes_prev_ints; /* bes_ints at last IPS calculation */ - u16 bes_eth_tx_rate; /* ETH TX rate - Mb/sec */ - u16 bes_eth_rx_rate; /* ETH RX rate - Mb/sec */ - u32 bes_rx_coal; /* Num pkts coalasced */ - u32 bes_rx_flush; /* Num times coalasced */ - u32 bes_link_change_physical; /*Num of times physical link changed */ - u32 bes_link_change_virtual; /*Num of times virtual link changed */ - u32 bes_rx_misc_pkts; /* Misc pkts received */ -}; - -/* Maximum interrupt delay (in microseconds) allowed */ -#define MAX_EQD 120 - -/* - * timer to prevent system shutdown hang for ever if h/w stops responding - */ -struct be_timer_ctxt { - atomic_t get_stat_flag; - struct timer_list get_stats_timer; - unsigned long get_stat_sem_addr; -} ; - -/* This structure is the main BladeEngine driver context. */ -struct be_adapter { - struct net_device *netdevp; - struct be_drvr_stat be_stat; - struct net_device_stats benet_stats; - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI Config */ - - struct tasklet_struct sts_handler; - struct timer_list cq_timer; - spinlock_t int_lock; /* to protect the isr field in adapter */ - - struct FWCMD_ETH_GET_STATISTICS *eth_statsp; - /* - * This will enable the use of ethtool to enable or disable - * Checksum on Rx pkts to be obeyed or disobeyed. - * If this is true = 1, then whatever is the checksum on the - * Received pkt as per BE, it will be given to the stack. - * Else the stack will re calculate it. - */ - bool rx_csum; - /* - * This will enable the use of ethtool to enable or disable - * Coalese on Rx pkts to be obeyed or disobeyed. - * If this is grater than 0 and less than 16 then coalascing - * is enabled else it is disabled - */ - u32 max_rx_coal; - struct pci_dev *pdev; /* Pointer to OS's PCI dvice */ - - spinlock_t txq_lock; /* to stop/wake queue based on tx_q_used */ - - u32 isr; /* copy of Intr status reg. */ - - u32 port0_link_sts; /* Port 0 link status */ - u32 port1_link_sts; /* port 1 list status */ - struct BE_LINK_STATUS *be_link_sts; - - /* pointer to the first netobject of this adapter */ - struct be_net_object *net_obj; - - /* Flags to indicate what to clean up */ - bool tasklet_started; - bool isr_registered; - /* - * adaptive interrupt coalescing (AIC) related - */ - bool enable_aic; /* 1 if AIC is enabled */ - u16 min_eqd; /* minimum EQ delay in usec */ - u16 max_eqd; /* minimum EQ delay in usec */ - u16 cur_eqd; /* current EQ delay in usec */ - /* - * book keeping for interrupt / sec and TX/RX rate calculation - */ - ulong ips_jiffies; /* jiffies at last IPS calc */ - u32 eth_tx_bytes; - ulong eth_tx_jiffies; - u32 eth_rx_bytes; - ulong eth_rx_jiffies; - - struct semaphore get_eth_stat_sem; - - /* timer ctxt to prevent shutdown hanging due to un-responsive BE */ - struct be_timer_ctxt timer_ctxt; - -#define BE_MAX_MSIX_VECTORS 32 -#define BE_MAX_REQ_MSIX_VECTORS 1 /* only one EQ in Linux driver */ - struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; - bool msix_enabled; - bool dma_64bit_cap; /* the Device DAC capable or not */ - u8 dev_state; /* The current state of the device */ - u8 dev_pm_state; /* The State of device before going to suspend */ -}; - -/* - * Every second we look at the ints/sec and adjust eq_delay - * between adapter->min_eqd and adapter->max_eqd to keep the ints/sec between - * IPS_HI_WM and IPS_LO_WM. - */ -#define IPS_HI_WM 18000 -#define IPS_LO_WM 8000 - - -static inline void index_adv(u32 *index, u32 val, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + val) & (limit - 1); -} - -static inline void index_inc(u32 *index, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + 1) & (limit - 1); -} - -static inline void be_adv_eq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->event_q_tl, pnob->event_q_len); -} - -static inline void be_adv_txq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_hd, pnob->tx_q_len); -} - -static inline void be_adv_txq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_tl, pnob->tx_q_len); -} - -static inline void be_adv_txcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_cq_tl, pnob->txcq_len); -} - -static inline void be_adv_rxq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_q_hd, pnob->rx_q_len); -} - -static inline void be_adv_rxcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_cq_tl, pnob->rx_cq_len); -} - -static inline u32 tx_compl_lastwrb_idx_get(struct be_net_object *pnob) -{ - return (pnob->tx_q_tl + *(u32 *)&pnob->tx_ctxt[pnob->tx_q_tl] - 1) - & (pnob->tx_q_len - 1); -} - -int benet_init(struct net_device *); -int be_ethtool_ioctl(struct net_device *, struct ifreq *); -struct net_device_stats *benet_get_stats(struct net_device *); -void be_process_intr(unsigned long context); -irqreturn_t be_int(int irq, void *dev); -void be_post_eth_rx_buffs(struct be_net_object *); -void be_get_stat_cb(void *, int, struct MCC_WRB_AMAP *); -void be_get_stats_timer_handler(unsigned long); -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *); -void be_print_link_info(struct BE_LINK_STATUS *); -void be_update_link_status(struct be_adapter *); -void be_init_procfs(struct be_adapter *); -void be_cleanup_procfs(struct be_adapter *); -int be_poll(struct napi_struct *, int); -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *); -void be_notify_cmpl(struct be_net_object *, int, int, int); -void be_enable_intr(struct be_net_object *); -void be_enable_eq_intr(struct be_net_object *); -void be_disable_intr(struct be_net_object *); -void be_disable_eq_intr(struct be_net_object *); -int be_set_uc_mac_adr(struct be_net_object *, u8, u8, u8, - u8 *, mcc_wrb_cqe_callback, void *); -int be_get_flow_ctl(struct be_function_object *pFnObj, bool *, bool *); -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx); - -#endif /* _BENET_H_ */ diff --git a/drivers/staging/benet/bestatus.h b/drivers/staging/benet/bestatus.h deleted file mode 100644 index 59c7a4b6222..00000000000 --- a/drivers/staging/benet/bestatus.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BESTATUS_H_ -#define _BESTATUS_H_ - -#define BE_SUCCESS (0x00000000L) -/* - * MessageId: BE_PENDING - * The BladeEngine Driver call succeeded, and pended operation. - */ -#define BE_PENDING (0x20070001L) -#define BE_STATUS_PENDING (BE_PENDING) -/* - * MessageId: BE_NOT_OK - * An error occurred. - */ -#define BE_NOT_OK (0xE0070002L) -/* - * MessageId: BE_STATUS_SYSTEM_RESOURCES - * Insufficient host system resources exist to complete the API. - */ -#define BE_STATUS_SYSTEM_RESOURCES (0xE0070003L) -/* - * MessageId: BE_STATUS_CHIP_RESOURCES - * Insufficient chip resources exist to complete the API. - */ -#define BE_STATUS_CHIP_RESOURCES (0xE0070004L) -/* - * MessageId: BE_STATUS_NO_RESOURCE - * Insufficient resources to complete request. - */ -#define BE_STATUS_NO_RESOURCE (0xE0070005L) -/* - * MessageId: BE_STATUS_BUSY - * Resource is currently busy. - */ -#define BE_STATUS_BUSY (0xE0070006L) -/* - * MessageId: BE_STATUS_INVALID_PARAMETER - * Invalid Parameter in request. - */ -#define BE_STATUS_INVALID_PARAMETER (0xE0000007L) -/* - * MessageId: BE_STATUS_NOT_SUPPORTED - * Requested operation is not supported. - */ -#define BE_STATUS_NOT_SUPPORTED (0xE000000DL) - -/* - * *************************************************************************** - * E T H E R N E T S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_ETH_TX_ERROR - * The Ethernet device driver failed to transmit a packet. - */ -#define BE_ETH_TX_ERROR (0xE0070101L) - -/* - * *************************************************************************** - * S H A R E D S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_STATUS_VBD_INVALID_VERSION - * The device driver is not compatible with this version of the VBD. - */ -#define BE_STATUS_INVALID_VERSION (0xE0070402L) -/* - * MessageId: BE_STATUS_DOMAIN_DENIED - * The operation failed to complete due to insufficient access - * rights for the requesting domain. - */ -#define BE_STATUS_DOMAIN_DENIED (0xE0070403L) -/* - * MessageId: BE_STATUS_TCP_NOT_STARTED - * The embedded TCP/IP stack has not been started. - */ -#define BE_STATUS_TCP_NOT_STARTED (0xE0070409L) -/* - * MessageId: BE_STATUS_NO_MCC_WRB - * No free MCC WRB are available for posting the request. - */ -#define BE_STATUS_NO_MCC_WRB (0xE0070414L) - -#endif /* _BESTATUS_ */ diff --git a/drivers/staging/benet/cev.h b/drivers/staging/benet/cev.h deleted file mode 100644 index 30996920a54..00000000000 --- a/drivers/staging/benet/cev.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __cev_amap_h__ -#define __cev_amap_h__ -#include "ep.h" - -/* - * Host Interrupt Status Register 0. The first of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ0 through EQ31. - */ -struct BE_CEV_ISR0_CSR_AMAP { - u8 interrupt0; /* DWORD 0 */ - u8 interrupt1; /* DWORD 0 */ - u8 interrupt2; /* DWORD 0 */ - u8 interrupt3; /* DWORD 0 */ - u8 interrupt4; /* DWORD 0 */ - u8 interrupt5; /* DWORD 0 */ - u8 interrupt6; /* DWORD 0 */ - u8 interrupt7; /* DWORD 0 */ - u8 interrupt8; /* DWORD 0 */ - u8 interrupt9; /* DWORD 0 */ - u8 interrupt10; /* DWORD 0 */ - u8 interrupt11; /* DWORD 0 */ - u8 interrupt12; /* DWORD 0 */ - u8 interrupt13; /* DWORD 0 */ - u8 interrupt14; /* DWORD 0 */ - u8 interrupt15; /* DWORD 0 */ - u8 interrupt16; /* DWORD 0 */ - u8 interrupt17; /* DWORD 0 */ - u8 interrupt18; /* DWORD 0 */ - u8 interrupt19; /* DWORD 0 */ - u8 interrupt20; /* DWORD 0 */ - u8 interrupt21; /* DWORD 0 */ - u8 interrupt22; /* DWORD 0 */ - u8 interrupt23; /* DWORD 0 */ - u8 interrupt24; /* DWORD 0 */ - u8 interrupt25; /* DWORD 0 */ - u8 interrupt26; /* DWORD 0 */ - u8 interrupt27; /* DWORD 0 */ - u8 interrupt28; /* DWORD 0 */ - u8 interrupt29; /* DWORD 0 */ - u8 interrupt30; /* DWORD 0 */ - u8 interrupt31; /* DWORD 0 */ -} __packed; -struct CEV_ISR0_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 1. The second of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ32 through EQ63. - */ -struct BE_CEV_ISR1_CSR_AMAP { - u8 interrupt32; /* DWORD 0 */ - u8 interrupt33; /* DWORD 0 */ - u8 interrupt34; /* DWORD 0 */ - u8 interrupt35; /* DWORD 0 */ - u8 interrupt36; /* DWORD 0 */ - u8 interrupt37; /* DWORD 0 */ - u8 interrupt38; /* DWORD 0 */ - u8 interrupt39; /* DWORD 0 */ - u8 interrupt40; /* DWORD 0 */ - u8 interrupt41; /* DWORD 0 */ - u8 interrupt42; /* DWORD 0 */ - u8 interrupt43; /* DWORD 0 */ - u8 interrupt44; /* DWORD 0 */ - u8 interrupt45; /* DWORD 0 */ - u8 interrupt46; /* DWORD 0 */ - u8 interrupt47; /* DWORD 0 */ - u8 interrupt48; /* DWORD 0 */ - u8 interrupt49; /* DWORD 0 */ - u8 interrupt50; /* DWORD 0 */ - u8 interrupt51; /* DWORD 0 */ - u8 interrupt52; /* DWORD 0 */ - u8 interrupt53; /* DWORD 0 */ - u8 interrupt54; /* DWORD 0 */ - u8 interrupt55; /* DWORD 0 */ - u8 interrupt56; /* DWORD 0 */ - u8 interrupt57; /* DWORD 0 */ - u8 interrupt58; /* DWORD 0 */ - u8 interrupt59; /* DWORD 0 */ - u8 interrupt60; /* DWORD 0 */ - u8 interrupt61; /* DWORD 0 */ - u8 interrupt62; /* DWORD 0 */ - u8 interrupt63; /* DWORD 0 */ -} __packed; -struct CEV_ISR1_CSR_AMAP { - u32 dw[1]; -}; -/* - * Host Interrupt Status Register 2. The third of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ64 through EQ95. - */ -struct BE_CEV_ISR2_CSR_AMAP { - u8 interrupt64; /* DWORD 0 */ - u8 interrupt65; /* DWORD 0 */ - u8 interrupt66; /* DWORD 0 */ - u8 interrupt67; /* DWORD 0 */ - u8 interrupt68; /* DWORD 0 */ - u8 interrupt69; /* DWORD 0 */ - u8 interrupt70; /* DWORD 0 */ - u8 interrupt71; /* DWORD 0 */ - u8 interrupt72; /* DWORD 0 */ - u8 interrupt73; /* DWORD 0 */ - u8 interrupt74; /* DWORD 0 */ - u8 interrupt75; /* DWORD 0 */ - u8 interrupt76; /* DWORD 0 */ - u8 interrupt77; /* DWORD 0 */ - u8 interrupt78; /* DWORD 0 */ - u8 interrupt79; /* DWORD 0 */ - u8 interrupt80; /* DWORD 0 */ - u8 interrupt81; /* DWORD 0 */ - u8 interrupt82; /* DWORD 0 */ - u8 interrupt83; /* DWORD 0 */ - u8 interrupt84; /* DWORD 0 */ - u8 interrupt85; /* DWORD 0 */ - u8 interrupt86; /* DWORD 0 */ - u8 interrupt87; /* DWORD 0 */ - u8 interrupt88; /* DWORD 0 */ - u8 interrupt89; /* DWORD 0 */ - u8 interrupt90; /* DWORD 0 */ - u8 interrupt91; /* DWORD 0 */ - u8 interrupt92; /* DWORD 0 */ - u8 interrupt93; /* DWORD 0 */ - u8 interrupt94; /* DWORD 0 */ - u8 interrupt95; /* DWORD 0 */ -} __packed; -struct CEV_ISR2_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 3. The fourth of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ96 through EQ127. - */ -struct BE_CEV_ISR3_CSR_AMAP { - u8 interrupt96; /* DWORD 0 */ - u8 interrupt97; /* DWORD 0 */ - u8 interrupt98; /* DWORD 0 */ - u8 interrupt99; /* DWORD 0 */ - u8 interrupt100; /* DWORD 0 */ - u8 interrupt101; /* DWORD 0 */ - u8 interrupt102; /* DWORD 0 */ - u8 interrupt103; /* DWORD 0 */ - u8 interrupt104; /* DWORD 0 */ - u8 interrupt105; /* DWORD 0 */ - u8 interrupt106; /* DWORD 0 */ - u8 interrupt107; /* DWORD 0 */ - u8 interrupt108; /* DWORD 0 */ - u8 interrupt109; /* DWORD 0 */ - u8 interrupt110; /* DWORD 0 */ - u8 interrupt111; /* DWORD 0 */ - u8 interrupt112; /* DWORD 0 */ - u8 interrupt113; /* DWORD 0 */ - u8 interrupt114; /* DWORD 0 */ - u8 interrupt115; /* DWORD 0 */ - u8 interrupt116; /* DWORD 0 */ - u8 interrupt117; /* DWORD 0 */ - u8 interrupt118; /* DWORD 0 */ - u8 interrupt119; /* DWORD 0 */ - u8 interrupt120; /* DWORD 0 */ - u8 interrupt121; /* DWORD 0 */ - u8 interrupt122; /* DWORD 0 */ - u8 interrupt123; /* DWORD 0 */ - u8 interrupt124; /* DWORD 0 */ - u8 interrupt125; /* DWORD 0 */ - u8 interrupt126; /* DWORD 0 */ - u8 interrupt127; /* DWORD 0 */ -} __packed; -struct CEV_ISR3_CSR_AMAP { - u32 dw[1]; -}; - -/* Completions and Events block Registers. */ -struct BE_CEV_CSRMAP_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ - u8 rsvd2[32]; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ - struct BE_CEV_ISR0_CSR_AMAP isr0; - struct BE_CEV_ISR1_CSR_AMAP isr1; - struct BE_CEV_ISR2_CSR_AMAP isr2; - struct BE_CEV_ISR3_CSR_AMAP isr3; - u8 rsvd4[32]; /* DWORD 8 */ - u8 rsvd5[32]; /* DWORD 9 */ - u8 rsvd6[32]; /* DWORD 10 */ - u8 rsvd7[32]; /* DWORD 11 */ - u8 rsvd8[32]; /* DWORD 12 */ - u8 rsvd9[32]; /* DWORD 13 */ - u8 rsvd10[32]; /* DWORD 14 */ - u8 rsvd11[32]; /* DWORD 15 */ - u8 rsvd12[32]; /* DWORD 16 */ - u8 rsvd13[32]; /* DWORD 17 */ - u8 rsvd14[32]; /* DWORD 18 */ - u8 rsvd15[32]; /* DWORD 19 */ - u8 rsvd16[32]; /* DWORD 20 */ - u8 rsvd17[32]; /* DWORD 21 */ - u8 rsvd18[32]; /* DWORD 22 */ - u8 rsvd19[32]; /* DWORD 23 */ - u8 rsvd20[32]; /* DWORD 24 */ - u8 rsvd21[32]; /* DWORD 25 */ - u8 rsvd22[32]; /* DWORD 26 */ - u8 rsvd23[32]; /* DWORD 27 */ - u8 rsvd24[32]; /* DWORD 28 */ - u8 rsvd25[32]; /* DWORD 29 */ - u8 rsvd26[32]; /* DWORD 30 */ - u8 rsvd27[32]; /* DWORD 31 */ - u8 rsvd28[32]; /* DWORD 32 */ - u8 rsvd29[32]; /* DWORD 33 */ - u8 rsvd30[192]; /* DWORD 34 */ - u8 rsvd31[192]; /* DWORD 40 */ - u8 rsvd32[160]; /* DWORD 46 */ - u8 rsvd33[160]; /* DWORD 51 */ - u8 rsvd34[160]; /* DWORD 56 */ - u8 rsvd35[96]; /* DWORD 61 */ - u8 rsvd36[192][32]; /* DWORD 64 */ -} __packed; -struct CEV_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __cev_amap_h__ */ diff --git a/drivers/staging/benet/cq.c b/drivers/staging/benet/cq.c deleted file mode 100644 index 65045864543..00000000000 --- a/drivers/staging/benet/cq.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - -/* - * Completion Queue Objects - */ -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates a completion queue based on the client completion - queue configuration information. - - - FunctionObject - Handle to a function object - CqBaseVa - Base VA for a the CQ ring - NumEntries - CEV_CQ_CNT_* values - solEventEnable - 0 = All CQEs can generate Events if CQ is eventable - 1 = only CQEs with solicited bit set are eventable - eventable - Eventable CQ, generates interrupts. - nodelay - 1 = Force interrupt, relevent if CQ eventable. - Interrupt is asserted immediately after EQE - write is confirmed, regardless of EQ Timer - or watermark settings. - wme - Enable watermark based coalescing - wmThresh - High watermark(CQ fullness at which event - or interrupt should be asserted). These are the - CEV_WATERMARK encoded values. - EqObject - EQ Handle to assign to this CQ - ppCqObject - Internal CQ Handle returned. - - Returns BE_SUCCESS if successfull, otherwise a useful error code is - returned. - - IRQL < DISPATCH_LEVEL - -*/ -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, bool solicited_eventable, - bool no_delay, u32 wm_thresh, - struct be_eq_object *eq_object, struct be_cq_object *cq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding; - u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP); - struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(cq_object); - ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_CQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_CQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_CQ_CNT_1024; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - /* - * All cq entries all the same size. Use iSCSI version - * as a test for the proper rd length. - */ - memset(cq_object, 0, sizeof(*cq_object)); - - atomic_set(&cq_object->ref_count, 0); - cq_object->parent_function = pfob; - cq_object->eq_object = eq_object; - cq_object->num_entries = num_entries; - /* save for MCC cq processing */ - cq_object->va = rd->va; - - /* map into UT. */ - length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - - AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - n = (eq_object != NULL); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable, - &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1); - - n = eq_object ? eq_object->eq_id : 0; - AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Count, - &fwcmd->params.request.context, num_entries_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay, - &fwcmd->params.request.context, no_delay); - AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent, - &fwcmd->params.request.context, solicited_eventable); - - n = (wm_thresh != 0xFFFFFFFF); - AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n); - - n = (n ? wm_thresh : 0); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark, - &fwcmd->params.request.context, n); - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto Error; - } - /* Remember the CQ id. */ - cq_object->cq_id = fwcmd->params.response.cq_id; - - /* insert this cq into eq_object reference */ - if (eq_object) { - atomic_inc(&eq_object->ref_count); - list_add_tail(&cq_object->cqlist_for_eq, - &eq_object->cq_list_head); - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this object - are released. The on-chip context is also destroyed along with the queue - ID, and any mappings made into the UT. - - cq_object - CQ handle returned from cq_object_create. - - returns the current reference count on the object - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_cq_destroy(struct be_cq_object *cq_object) -{ - int status = 0; - - /* Nothing should reference this CQ at this point. */ - ASSERT(atomic_read(&cq_object->ref_count) == 0); - - /* Send fwcmd to destroy the CQ. */ - status = be_function_ring_destroy(cq_object->parent_function, - cq_object->cq_id, FWCMD_RING_TYPE_CQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Remove reference if this is an eventable CQ. */ - if (cq_object->eq_object) { - atomic_dec(&cq_object->eq_object->ref_count); - list_del(&cq_object->cqlist_for_eq); - } - return BE_SUCCESS; -} - diff --git a/drivers/staging/benet/descriptors.h b/drivers/staging/benet/descriptors.h deleted file mode 100644 index 8da438c407d..00000000000 --- a/drivers/staging/benet/descriptors.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __descriptors_amap_h__ -#define __descriptors_amap_h__ - -/* - * --- IPC_NODE_ID_ENUM --- - * IPC processor id values - */ -#define TPOST_NODE_ID (0) /* TPOST ID */ -#define TPRE_NODE_ID (1) /* TPRE ID */ -#define TXULP0_NODE_ID (2) /* TXULP0 ID */ -#define TXULP1_NODE_ID (3) /* TXULP1 ID */ -#define TXULP2_NODE_ID (4) /* TXULP2 ID */ -#define RXULP0_NODE_ID (5) /* RXULP0 ID */ -#define RXULP1_NODE_ID (6) /* RXULP1 ID */ -#define RXULP2_NODE_ID (7) /* RXULP2 ID */ -#define MPU_NODE_ID (15) /* MPU ID */ - -/* - * --- MAC_ID_ENUM --- - * Meaning of the mac_id field in rxpp_eth_d - */ -#define PORT0_HOST_MAC0 (0) /* PD 0, Port 0, host networking, MAC 0. */ -#define PORT0_HOST_MAC1 (1) /* PD 0, Port 0, host networking, MAC 1. */ -#define PORT0_STORAGE_MAC0 (2) /* PD 0, Port 0, host storage, MAC 0. */ -#define PORT0_STORAGE_MAC1 (3) /* PD 0, Port 0, host storage, MAC 1. */ -#define PORT1_HOST_MAC0 (4) /* PD 0, Port 1 host networking, MAC 0. */ -#define PORT1_HOST_MAC1 (5) /* PD 0, Port 1 host networking, MAC 1. */ -#define PORT1_STORAGE_MAC0 (6) /* PD 0, Port 1 host storage, MAC 0. */ -#define PORT1_STORAGE_MAC1 (7) /* PD 0, Port 1 host storage, MAC 1. */ -#define FIRST_VM_MAC (8) /* PD 1 MAC. Protection domains have IDs */ - /* from 0x8-0x26, one per PD. */ -#define LAST_VM_MAC (38) /* PD 31 MAC. */ -#define MGMT_MAC (39) /* Management port MAC. */ -#define MARBLE_MAC0 (59) /* Used for flushing function 0 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA = 00 - */ -#define MARBLE_MAC1 (60) /* Used for flushing function 1 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA != 00 - */ -#define NULL_MAC (61) /* Promiscuous mode, indicates no match */ -#define MCAST_MAC (62) /* Multicast match. */ -#define BCAST_MATCH (63) /* Broadcast match. */ - -#endif /* __descriptors_amap_h__ */ diff --git a/drivers/staging/benet/doorbells.h b/drivers/staging/benet/doorbells.h deleted file mode 100644 index 550cc4d5d6f..00000000000 --- a/drivers/staging/benet/doorbells.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __doorbells_amap_h__ -#define __doorbells_amap_h__ - -/* The TX/RDMA send queue doorbell. */ -struct BE_SQ_DB_AMAP { - u8 cid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct SQ_DB_AMAP { - u32 dw[1]; -}; - -/* The receive queue doorbell. */ -struct BE_RQ_DB_AMAP { - u8 rq[10]; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 Invalidate; /* DWORD 0 */ - u8 numPosted[8]; /* DWORD 0 */ -} __packed; -struct RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * The CQ/EQ doorbell. Software MUST set reserved fields in this - * descriptor to zero, otherwise (CEV) hardware will not execute the - * doorbell (flagging a bad_db_qid error instead). - */ -struct BE_CQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 num_popped[13]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ -} __packed; -struct CQ_DB_AMAP { - u32 dw[1]; -}; - -struct BE_TPM_RQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 numPosted[11]; /* DWORD 0 */ - u8 mss_cnt[5]; /* DWORD 0 */ -} __packed; -struct TPM_RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * Post WRB Queue Doorbell Register used by the host Storage stack - * to notify the controller of a posted Work Request Block - */ -struct BE_WRB_POST_DB_AMAP { - u8 wrb_cid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 wrb_index[8]; /* DWORD 0 */ - u8 numberPosted[8]; /* DWORD 0 */ -} __packed; -struct WRB_POST_DB_AMAP { - u32 dw[1]; -}; - -/* - * Update Default PDU Queue Doorbell Register used to communicate - * to the controller that the driver has stopped processing the queue - * and where in the queue it stopped, this is - * a CQ Entry Type. Used by storage driver. - */ -struct BE_DEFAULT_PDU_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 cqproc[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct DEFAULT_PDU_DB_AMAP { - u32 dw[1]; -}; - -/* Management Command and Controller default fragment ring */ -struct BE_MCC_DB_AMAP { - u8 rid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct MCC_DB_AMAP { - u32 dw[1]; -}; - -/* - * Used for bootstrapping the Host interface. This register is - * used for driver communication with the MPU when no MCC Rings exist. - * The software must write this register twice to post any MCC - * command. First, it writes the register with hi=1 and the upper bits of - * the physical address for the MCC_MAILBOX structure. Software must poll - * the ready bit until this is acknowledged. Then, sotware writes the - * register with hi=0 with the lower bits in the address. It must - * poll the ready bit until the MCC command is complete. Upon completion, - * the MCC_MAILBOX will contain a valid completion queue entry. - */ -struct BE_MPU_MAILBOX_DB_AMAP { - u8 ready; /* DWORD 0 */ - u8 hi; /* DWORD 0 */ - u8 address[30]; /* DWORD 0 */ -} __packed; -struct MPU_MAILBOX_DB_AMAP { - u32 dw[1]; -}; - -/* - * This is the protection domain doorbell register map. Note that - * while this map shows doorbells for all Blade Engine supported - * protocols, not all of these may be valid in a given function or - * protection domain. It is the responsibility of the application - * accessing the doorbells to know which are valid. Each doorbell - * occupies 32 bytes of space, but unless otherwise specified, - * only the first 4 bytes should be written. There are 32 instances - * of these doorbells for the host and 31 virtual machines respectively. - * The host and VMs will only map the doorbell pages belonging to its - * protection domain. It will not be able to touch the doorbells for - * another VM. The doorbells are the only registers directly accessible - * by a virtual machine. Similarly, there are 511 additional - * doorbells for RDMA protection domains. PD 0 for RDMA shares - * the same physical protection domain doorbell page as ETH/iSCSI. - * - */ -struct BE_PROTECTION_DOMAIN_DBMAP_AMAP { - u8 rsvd0[512]; /* DWORD 0 */ - struct BE_SQ_DB_AMAP rdma_sq_db; - u8 rsvd1[7][32]; /* DWORD 17 */ - struct BE_WRB_POST_DB_AMAP iscsi_wrb_post_db; - u8 rsvd2[7][32]; /* DWORD 25 */ - struct BE_SQ_DB_AMAP etx_sq_db; - u8 rsvd3[7][32]; /* DWORD 33 */ - struct BE_RQ_DB_AMAP rdma_rq_db; - u8 rsvd4[7][32]; /* DWORD 41 */ - struct BE_DEFAULT_PDU_DB_AMAP iscsi_default_pdu_db; - u8 rsvd5[7][32]; /* DWORD 49 */ - struct BE_TPM_RQ_DB_AMAP tpm_rq_db; - u8 rsvd6[7][32]; /* DWORD 57 */ - struct BE_RQ_DB_AMAP erx_rq_db; - u8 rsvd7[7][32]; /* DWORD 65 */ - struct BE_CQ_DB_AMAP cq_db; - u8 rsvd8[7][32]; /* DWORD 73 */ - struct BE_MCC_DB_AMAP mpu_mcc_db; - u8 rsvd9[7][32]; /* DWORD 81 */ - struct BE_MPU_MAILBOX_DB_AMAP mcc_bootstrap_db; - u8 rsvd10[935][32]; /* DWORD 89 */ -} __packed; -struct PROTECTION_DOMAIN_DBMAP_AMAP { - u32 dw[1024]; -}; - -#endif /* __doorbells_amap_h__ */ diff --git a/drivers/staging/benet/ep.h b/drivers/staging/benet/ep.h deleted file mode 100644 index 72fcf64a9ff..00000000000 --- a/drivers/staging/benet/ep.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __ep_amap_h__ -#define __ep_amap_h__ - -/* General Control and Status Register. */ -struct BE_EP_CONTROL_CSR_AMAP { - u8 m0_RxPbuf; /* DWORD 0 */ - u8 m1_RxPbuf; /* DWORD 0 */ - u8 m2_RxPbuf; /* DWORD 0 */ - u8 ff_en; /* DWORD 0 */ - u8 rsvd0[27]; /* DWORD 0 */ - u8 CPU_reset; /* DWORD 0 */ -} __packed; -struct EP_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_EP_SEMAPHORE_CSR_AMAP { - u8 value[32]; /* DWORD 0 */ -} __packed; -struct EP_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Embedded Processor Specific Registers. */ -struct BE_EP_CSRMAP_AMAP { - struct BE_EP_CONTROL_CSR_AMAP ep_control; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - u8 rsvd3[32]; /* DWORD 4 */ - u8 rsvd4[32]; /* DWORD 5 */ - u8 rsvd5[8][128]; /* DWORD 6 */ - u8 rsvd6[32]; /* DWORD 38 */ - u8 rsvd7[32]; /* DWORD 39 */ - u8 rsvd8[32]; /* DWORD 40 */ - u8 rsvd9[32]; /* DWORD 41 */ - u8 rsvd10[32]; /* DWORD 42 */ - struct BE_EP_SEMAPHORE_CSR_AMAP ep_semaphore; - u8 rsvd11[32]; /* DWORD 44 */ - u8 rsvd12[19][32]; /* DWORD 45 */ -} __packed; -struct EP_CSRMAP_AMAP { - u32 dw[64]; -}; - -#endif /* __ep_amap_h__ */ diff --git a/drivers/staging/benet/eq.c b/drivers/staging/benet/eq.c deleted file mode 100644 index db92ccd8fed..00000000000 --- a/drivers/staging/benet/eq.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" -/* - This routine creates an event queue based on the client completion - queue configuration information. - - FunctionObject - Handle to a function object - EqBaseVa - Base VA for a the EQ ring - SizeEncoding - The encoded size for the EQ entries. This value is - either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16 - NumEntries - CEV_CQ_CNT_* values. - Watermark - Enables watermark based coalescing. This parameter - must be of the type CEV_WMARK_* if watermarks - are enabled. If watermarks to to be disabled - this value should be-1. - TimerDelay - If a timer delay is enabled this value should be the - time of the delay in 8 microsecond units. If - delays are not used this parameter should be - set to -1. - ppEqObject - Internal EQ Handle returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL -*/ -int -be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, /* CEV_WMARK_* or -1 */ - u32 timer_delay, /* in 8us units, or -1 */ - struct be_eq_object *eq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding, eqe_size_encoding, length; - struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eq_object); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_EQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_EQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_EQ_CNT_1024; - break; - case 2048: - num_entries_encoding = CEV_EQ_CNT_2048; - break; - case 4096: - num_entries_encoding = CEV_EQ_CNT_4096; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - switch (eqe_size) { - case 4: - eqe_size_encoding = CEV_EQ_SIZE_4; - break; - case 16: - eqe_size_encoding = CEV_EQ_SIZE_16; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - if ((eqe_size == 4 && num_entries < 1024) || - (eqe_size == 16 && num_entries == 4096)) { - TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d", - eqe_size, num_entries); - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - memset(eq_object, 0, sizeof(*eq_object)); - - atomic_set(&eq_object->ref_count, 0); - eq_object->parent_function = pfob; - eq_object->eq_id = 0xFFFFFFFF; - - INIT_LIST_HEAD(&eq_object->cq_list_head); - - length = num_entries * eqe_size; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Size, - &fwcmd->params.request.context, eqe_size_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n); - - /* Let the caller ARM the EQ with the doorbell. */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context, - num_entries_encoding); - - n = pfob->pci_function_number * 32; - AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect, - &fwcmd->params.request.context, n); - if (watermark != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 1); - AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark, - &fwcmd->params.request.context, watermark); - ASSERT(watermark <= CEV_WMARK_240); - } else - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 0); - if (timer_delay != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 1); - - ASSERT(timer_delay <= 250); /* max value according to EAS */ - timer_delay = min(timer_delay, (u32)250); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay, - &fwcmd->params.request.context, timer_delay); - } else { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 0); - } - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create EQ failed."); - goto Error; - } - /* Get the EQ id. The MPU allocates the IDs. */ - eq_object->eq_id = fwcmd->params.response.eq_id; - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this - object are released. The on-chip context is also destroyed along with - the queue ID, and any mappings made into the UT. - - eq_object - EQ handle returned from eq_object_create. - - Returns BE_SUCCESS if successfull, otherwise a useful error code - is returned. - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_eq_destroy(struct be_eq_object *eq_object) -{ - int status = 0; - - ASSERT(atomic_read(&eq_object->ref_count) == 0); - /* no CQs should reference this EQ now */ - ASSERT(list_empty(&eq_object->cq_list_head)); - - /* Send fwcmd to destroy the EQ. */ - status = be_function_ring_destroy(eq_object->parent_function, - eq_object->eq_id, FWCMD_RING_TYPE_EQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - return BE_SUCCESS; -} -/* - *--------------------------------------------------------------------------- - * Function: be_eq_modify_delay - * Changes the EQ delay for a group of EQs. - * num_eq - The number of EQs in the eq_array to adjust. - * This also is the number of delay values in - * the eq_delay_array. - * eq_array - Array of struct be_eq_object pointers to adjust. - * eq_delay_array - Array of "num_eq" timer delays in units - * of microseconds. The be_eq_query_delay_range - * fwcmd returns the resolution and range of - * legal EQ delays. - * cb - - * cb_context - - * q_ctxt - Optional. Pointer to a previously allocated - * struct. If the MCC WRB ring is full, this - * structure is used to queue the operation. It - * will be posted to the MCC ring when space - * becomes available. All queued commands will - * be posted to the ring in the order they are - * received. It is always valid to pass a pointer to - * a generic be_generic_q_cntxt. However, - * the specific context structs - * are generally smaller than the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *------------------------------------------------------------------------- - */ -int -be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *gen_ctxt = NULL; - u32 i; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - gen_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY); - - ASSERT(num_eq > 0); - ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay)); - fwcmd->params.request.num_eq = num_eq; - for (i = 0; i < num_eq; i++) { - fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id; - fwcmd->params.request.delay[i].delay_in_microseconds = - eq_delay_array[i]; - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - diff --git a/drivers/staging/benet/eth.c b/drivers/staging/benet/eth.c deleted file mode 100644 index f641b6260d0..00000000000 --- a/drivers/staging/benet/eth.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include <linux/if_ether.h> -#include "hwlib.h" -#include "bestatus.h" - -/* - *--------------------------------------------------------- - * Function: be_eth_sq_create_ex - * Creates an ethernet send ring - extended version with - * additional parameters. - * pfob - - * rd - ring address - * length_in_bytes - - * type - The type of ring to create. - * ulp - The requested ULP number for the ring. - * This should be zero based, i.e. 0,1,2. This must - * be valid NIC ULP based on the firmware config. - * All doorbells for this ring must be sent to - * this ULP. The first network ring allocated for - * each ULP are higher performance than subsequent rings. - * cq_object - cq object for completions - * ex_parameters - Additional parameters (that may increase in - * future revisions). These parameters are only used - * for certain ring types -- see - * struct be_eth_sq_parameters for details. - * eth_sq - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_sq_create_ex(struct be_function_object *pfob, struct ring_desc *rd, - u32 length, u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq) -{ - struct FWCMD_COMMON_ETH_TX_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eth_sq); - ASSERT(ex_parameters); - - spin_lock_irqsave(&pfob->post_lock, irql); - - memset(eth_sq, 0, sizeof(*eth_sq)); - - eth_sq->parent_function = pfob; - eth_sq->bid = 0xFFFFFFFF; - eth_sq->cq_object = cq_object; - - /* Translate hwlib interface to arm interface. */ - switch (type) { - case BE_ETH_TX_RING_TYPE_FORWARDING: - type = ETH_TX_RING_TYPE_FORWARDING; - break; - case BE_ETH_TX_RING_TYPE_STANDARD: - type = ETH_TX_RING_TYPE_STANDARD; - break; - case BE_ETH_TX_RING_TYPE_BOUND: - ASSERT(ex_parameters->port < 2); - type = ETH_TX_RING_TYPE_BOUND; - break; - default: - TRACE(DL_ERR, "Invalid eth tx ring type:%d", type); - return BE_NOT_OK; - break; - } - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* NIC must be supported by the current config. */ - ASSERT(pfob->fw_config.nic_ulp_mask); - - /* - * The ulp parameter must select a valid NIC ULP - * for the current config. - */ - ASSERT((1 << ulp) & pfob->fw_config.nic_ulp_mask); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_TX_CREATE); - fwcmd->header.request.port_number = ex_parameters->port; - - AMAP_SET_BITS_PTR(ETX_CONTEXT, pd_id, - &fwcmd->params.request.context, 0); - - n = be_ring_length_to_encoding(length, sizeof(struct ETH_WRB_AMAP)); - AMAP_SET_BITS_PTR(ETX_CONTEXT, tx_ring_size, - &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(ETX_CONTEXT, cq_id_send, - &fwcmd->params.request.context, cq_object->cq_id); - - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(ETX_CONTEXT, func, &fwcmd->params.request.context, n); - - fwcmd->params.request.type = type; - fwcmd->params.request.ulp_num = (1 << ulp); - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - ASSERT(PAGES_SPANNED(rd->va, rd->length) >= - fwcmd->params.request.num_pages); - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create etx queue failed."); - goto Error; - } - /* save the butler ID */ - eth_sq->bid = fwcmd->params.response.cid; - - /* add a reference to the corresponding CQ */ - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine destroys an ethernet send queue - - EthSq - EthSq Handle returned from EthSqCreate - - This function always return BE_SUCCESS. - - This function frees memory allocated by EthSqCreate for the EthSq Object. - -*/ -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq) -{ - int status = 0; - - /* Send fwcmd to destroy the queue. */ - status = be_function_ring_destroy(eth_sq->parent_function, eth_sq->bid, - FWCMD_RING_TYPE_ETH_TX, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Derefence any associated CQs. */ - atomic_dec(ð_sq->cq_object->ref_count); - return status; -} -/* - This routine attempts to set the transmit flow control parameters. - - FunctionObject - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for - enable, false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable) -{ - struct FWCMD_COMMON_SET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FLOW_CONTROL); - - fwcmd->params.request.rx_flow_control = rxfc_enable; - fwcmd->params.request.tx_flow_control = txfc_enable; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set flow control fwcmd failed."); - goto error; - } - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to get the transmit flow control parameters. - - pfob - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for enable, - false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error code - is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable) -{ - struct FWCMD_COMMON_GET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FLOW_CONTROL); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get flow control fwcmd failed."); - goto error; - } - - *txfc_enable = fwcmd->params.response.tx_flow_control; - *rxfc_enable = fwcmd->params.response.rx_flow_control; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_qos - * This function sets the ethernet transmit Quality of Service (QoS) - * characteristics of BladeEngine for the domain. All ethernet - * transmit rings of the domain will evenly share the bandwidth. - * The exeception to sharing is the host primary (super) ethernet - * transmit ring as well as the host ethernet forwarding ring - * for missed offload data. - * pfob - - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units - * of 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps) -{ - struct FWCMD_COMMON_SET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_QOS); - - /* Set fields in fwcmd */ - fwcmd->params.request.max_bits_per_second_NIC = max_bps; - fwcmd->params.request.max_packets_per_second_NIC = max_pps; - fwcmd->params.request.valid_flags = QOS_BITS_NIC | QOS_PKTS_NIC; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) - TRACE(DL_ERR, "network set qos fwcmd failed."); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_get_qos - * This function retrieves the ethernet transmit Quality of Service (QoS) - * characteristics for the domain. - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units of - * 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps) -{ - struct FWCMD_COMMON_GET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_QOS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network get qos fwcmd failed."); - goto error; - } - - *max_bps = fwcmd->params.response.max_bits_per_second_NIC; - *max_pps = fwcmd->params.response.max_packets_per_second_NIC; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_frame_size - * This function sets the ethernet maximum frame size. The previous - * values are returned. - * pfob - - * tx_frame_size - maximum transmit frame size in bytes - * rx_frame_size - maximum receive frame size in bytes - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size) -{ - struct FWCMD_COMMON_SET_FRAME_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FRAME_SIZE); - fwcmd->params.request.max_tx_frame_size = *tx_frame_size; - fwcmd->params.request.max_rx_frame_size = *rx_frame_size; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network set frame size fwcmd failed."); - goto error; - } - - *tx_frame_size = fwcmd->params.response.chip_max_tx_frame_size; - *rx_frame_size = fwcmd->params.response.chip_max_rx_frame_size; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine creates a Ethernet receive ring. - - pfob - handle to a function object - rq_base_va - base VA for the default receive ring. this must be - exactly 8K in length and continguous physical memory. - cq_object - handle to a previously created CQ to be associated - with the RQ. - pp_eth_rq - pointer to an opqaue handle where an eth - receive object is returned. - Returns BE_SUCCESS if successfull, , otherwise a useful - int error code is returned. - - IRQL: < DISPATCH_LEVEL - this function allocates a struct be_ethrq_object *object. - there must be no more than 1 of these per function object, unless the - function object supports RSS (is networking and on the host). - the rq_base_va must point to a buffer of exactly 8K. - the erx::host_cqid (or host_stor_cqid) register and erx::ring_page registers - will be updated as appropriate on return -*/ -int -be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq) -{ - int status = 0; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_ETH_RX_CREATE *fwcmd = NULL; - unsigned long irql; - - /* MPU will set the */ - ASSERT(rd); - ASSERT(eth_rq); - - spin_lock_irqsave(&pfob->post_lock, irql); - - eth_rq->parent_function = pfob; - eth_rq->cq_object = cq_object; - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_RX_CREATE); - - fwcmd->params.request.num_pages = 2; /* required length */ - fwcmd->params.request.cq_id = cq_object->cq_id; - - if (bcmc_cq_object) - fwcmd->params.request.bcmc_cq_id = bcmc_cq_object->cq_id; - else - fwcmd->params.request.bcmc_cq_id = 0xFFFF; - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "fwcmd to map eth rxq frags failed."); - goto Error; - } - /* Save the ring ID for cleanup. */ - eth_rq->rid = fwcmd->params.response.id; - - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an Ethernet receive queue - - eth_rq - ethernet receive queue handle returned from eth_rq_create - - Returns BE_SUCCESS on success and an appropriate int on failure. - - This function frees resourcs allocated by EthRqCreate. - The erx::host_cqid (or host_stor_cqid) register and erx::ring_page - registers will be updated as appropriate on return - IRQL: < DISPATCH_LEVEL -*/ - -static void be_eth_rq_destroy_internal_cb(void *context, int status, - struct MCC_WRB_AMAP *wrb) -{ - struct be_ethrq_object *eth_rq = (struct be_ethrq_object *) context; - - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Destroy eth rq failed in internal callback.\n"); - } else { - /* Dereference any CQs associated with this queue. */ - atomic_dec(ð_rq->cq_object->ref_count); - } - - return; -} - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq) -{ - int status = BE_SUCCESS; - - /* Send fwcmd to destroy the RQ. */ - status = be_function_ring_destroy(eth_rq->parent_function, - eth_rq->rid, FWCMD_RING_TYPE_ETH_RX, NULL, NULL, - be_eth_rq_destroy_internal_cb, eth_rq); - - return status; -} - -/* - *--------------------------------------------------------------------------- - * Function: be_eth_rq_destroy_options - * Destroys an ethernet receive ring with finer granularity options - * than the standard be_eth_rq_destroy() API function. - * eth_rq - - * flush - Set to 1 to flush the ring, set to 0 to bypass the flush - * cb - Callback function on completion - * cb_context - Callback context - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *---------------------------------------------------------------------------- - */ -int -be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = BE_SUCCESS; - struct be_function_object *pfob = NULL; - unsigned long irql; - - pfob = eth_rq->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy eth_rq ring id:%d, flush:%d", eth_rq->rid, - flush); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy eth_rq ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = eth_rq->rid; - fwcmd->params.request.ring_type = FWCMD_RING_TYPE_ETH_RX; - fwcmd->params.request.bypass_flush = ((0 == flush) ? 1 : 0); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - be_eth_rq_destroy_internal_cb, eth_rq, fwcmd, NULL); - - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "eth_rq ring destroy failed. id:%d, flush:%d", - eth_rq->rid, flush); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine queries the frag size for erx. - - pfob - handle to a function object - - frag_size_bytes - erx frag size in bytes that is/was set. - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - -*/ -int -be_eth_rq_get_frag_size(struct be_function_object *pfob, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_GET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - return BE_STATUS_NO_MCC_WRB; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_GET_RX_FRAG_SIZE); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to set the frag size for erx. If the frag size is - already set, the attempt fails and the current frag size is returned. - - pfob - Handle to a function object - - frag_size - Erx frag size in bytes that is/was set. - - current_frag_size_bytes - Pointer to location where currrent frag - is to be rturned - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 frag_size, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_SET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_SET_RX_FRAG_SIZE); - - ASSERT(frag_size >= 128 && frag_size <= 16 * 1024); - - /* This is the log2 of the fragsize. This is not the exact - * ERX encoding. */ - fwcmd->params.request.new_fragsize_log2 = __ilog2_u32(frag_size); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine gets or sets a mac address for a domain - given the port and mac. - - FunctionObject - Function object handle. - port1 - Set to TRUE if this function will set/get the Port 1 - address. Only the host may set this to TRUE. - mac1 - Set to TRUE if this function will set/get the - MAC 1 address. Only the host may set this to TRUE. - write - Set to TRUE if this function should write the mac address. - mac_address - Buffer of the mac address to read or write. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, /* VM must always set to false */ - bool mac1, /* VM must always set to false */ - bool mgmt, bool write, - bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context) /* optional */ -{ - int status = BE_SUCCESS; - union { - struct FWCMD_COMMON_NTWK_MAC_QUERY *query; - struct FWCMD_COMMON_NTWK_MAC_SET *set; - } fwcmd = {NULL}; - struct MCC_WRB_AMAP *wrb = NULL; - u32 type = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - ASSERT(mac_address); - - ASSERT(port1 == false); - ASSERT(mac1 == false); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (mgmt) { - type = MAC_ADDRESS_TYPE_MANAGEMENT; - } else { - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - type = MAC_ADDRESS_TYPE_NETWORK; - else - type = MAC_ADDRESS_TYPE_STORAGE; - } - - if (write) { - /* Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.set = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_SET); - - fwcmd.set->params.request.invalidate = 0; - fwcmd.set->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.set->params.request.port = (port1 ? 1 : 0); - fwcmd.set->params.request.type = type; - - /* Copy the mac address to set. */ - fwcmd.set->params.request.mac.SizeOfStructure = - sizeof(fwcmd.set->params.request.mac); - memcpy(fwcmd.set->params.request.mac.MACAddress, - mac_address, ETH_ALEN); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - cb, cb_context, NULL, NULL, fwcmd.set, NULL); - - } else { - - /* - * Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.query = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_QUERY); - - fwcmd.query->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.query->params.request.port = (port1 ? 1 : 0); - fwcmd.query->params.request.type = type; - fwcmd.query->params.request.permanent = permanent; - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.va = mac_address; - /* Post the f/w command (with a copy for the response) */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd.query, &rc); - } - - if (status < 0) { - TRACE(DL_ERR, "mac set/query failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine writes data to context memory. - - pfob - Function object handle. - mac_table - Set to the 128-bit multicast address hash table. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt) -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_MULTICAST_SET *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(num <= ARRAY_SIZE(fwcmd->params.request.mac)); - - if (num > ARRAY_SIZE(fwcmd->params.request.mac)) { - TRACE(DL_ERR, "Too many multicast addresses. BE supports %d.", - (int) ARRAY_SIZE(fwcmd->params.request.mac)); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_MULTICAST_SET); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_mac = num; - if (num > 0) { - ASSERT(mac_table); - memcpy(fwcmd->params.request.mac, - mac_table, ETH_ALEN * num); - } - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "multicast fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine adds or removes a vlan tag from the rxf table. - - FunctionObject - Function object handle. - VLanTag - VLan tag to add or remove. - Add - Set to TRUE if this will add a vlan tag - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_vlan_q_ctxt *q_ctxt) /* optional */ -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - if (num > ARRAY_SIZE(fwcmd->params.request.vlan_tag)) { - TRACE(DL_ERR, "Too many VLAN tags."); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_VLAN_CONFIG); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_vlan = num; - - if (num > 0) { - ASSERT(vlan_tag_array); - memcpy(fwcmd->params.request.vlan_tag, vlan_tag_array, - num * sizeof(vlan_tag_array[0])); - } - } - - /* Post the commadn */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "vlan fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(link_status); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, - COMMON_NTWK_LINK_STATUS_QUERY); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.va = link_status; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "link status fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt) -{ - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(va_for_fwcmd); - ASSERT(pa_for_fwcmd); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - - TRACE(DL_INFO, "Query eth stats. fwcmd va:%p pa:0x%08x_%08x", - va_for_fwcmd, upper_32_bits(pa_for_fwcmd), (u32)pa_for_fwcmd); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - va_for_fwcmd = BE_PREPARE_NONEMBEDDED_FWCMD(pfob, wrb, - va_for_fwcmd, pa_for_fwcmd, ETH_GET_STATISTICS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, va_for_fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "eth stats fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt) -{ - struct FWCMD_ETH_PROMISCUOUS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_PROMISCUOUS); - - fwcmd->params.request.port0_promiscuous = enable_port0; - fwcmd->params.request.port1_promiscuous = enable_port1; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - - if (status < 0) { - TRACE(DL_ERR, "promiscuous fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - *------------------------------------------------------------------------- - * Function: be_rxf_filter_config - * Configures BladeEngine ethernet receive filter settings. - * pfob - - * settings - Pointer to the requested filter settings. - * The response from BladeEngine will be placed back - * in this structure. - * cb - optional - * cb_context - optional - * q_ctxt - Optional. Pointer to a previously allocated struct. - * If the MCC WRB ring is full, this structure is - * used to queue the operation. It will be posted - * to the MCC ring when space becomes available. All - * queued commands will be posted to the ring in - * the order they are received. It is always valid - * to pass a pointer to a generic - * be_generic_q_ctxt. However, the specific - * context structs are generally smaller than - * the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_RX_FILTER *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(settings); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_RX_FILTER); - memcpy(&fwcmd->params.request, settings, sizeof(*settings)); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.va = settings; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "RXF/ERX filter config fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} diff --git a/drivers/staging/benet/etx_context.h b/drivers/staging/benet/etx_context.h deleted file mode 100644 index 554fbe5d127..00000000000 --- a/drivers/staging/benet/etx_context.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __etx_context_amap_h__ -#define __etx_context_amap_h__ - -/* ETX ring context structure. */ -struct BE_ETX_CONTEXT_AMAP { - u8 tx_cidx[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 tx_pidx[11]; /* DWORD 1 */ - u8 rsvd2; /* DWORD 1 */ - u8 tx_ring_size[4]; /* DWORD 1 */ - u8 pd_id[5]; /* DWORD 1 */ - u8 pd_id_not_valid; /* DWORD 1 */ - u8 cq_id_send[10]; /* DWORD 1 */ - u8 rsvd3[32]; /* DWORD 2 */ - u8 rsvd4[32]; /* DWORD 3 */ - u8 cur_bytes[32]; /* DWORD 4 */ - u8 max_bytes[32]; /* DWORD 5 */ - u8 time_stamp[32]; /* DWORD 6 */ - u8 rsvd5[11]; /* DWORD 7 */ - u8 func; /* DWORD 7 */ - u8 rsvd6[20]; /* DWORD 7 */ - u8 cur_txd_count[32]; /* DWORD 8 */ - u8 max_txd_count[32]; /* DWORD 9 */ - u8 rsvd7[32]; /* DWORD 10 */ - u8 rsvd8[32]; /* DWORD 11 */ - u8 rsvd9[32]; /* DWORD 12 */ - u8 rsvd10[32]; /* DWORD 13 */ - u8 rsvd11[32]; /* DWORD 14 */ - u8 rsvd12[32]; /* DWORD 15 */ -} __packed; -struct ETX_CONTEXT_AMAP { - u32 dw[16]; -}; - -#endif /* __etx_context_amap_h__ */ diff --git a/drivers/staging/benet/funcobj.c b/drivers/staging/benet/funcobj.c deleted file mode 100644 index 0f57eb58dae..00000000000 --- a/drivers/staging/benet/funcobj.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - - -int -be_function_internal_query_firmware_config(struct be_function_object *pfob, - struct BE_FIRMWARE_CONFIG *config) -{ - struct FWCMD_COMMON_FIRMWARE_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_FIRMWARE_CONFIG); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.va = config; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, - NULL, NULL, NULL, fwcmd, &rc); -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This allocates and initializes a function object based on the information - provided by upper layer drivers. - - Returns BE_SUCCESS on success and an appropriate int on failure. - - A function object represents a single BladeEngine (logical) PCI function. - That is a function object either represents - the networking side of BladeEngine or the iSCSI side of BladeEngine. - - This routine will also detect and create an appropriate PD object for the - PCI function as needed. -*/ -int -be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, - struct ring_desc *mailbox, struct be_function_object *pfob) -{ - int status; - - ASSERT(pfob); /* not a magic assert */ - ASSERT(function_type <= 2); - - TRACE(DL_INFO, "Create function object. type:%s object:0x%p", - (function_type == BE_FUNCTION_TYPE_ISCSI ? "iSCSI" : - (function_type == BE_FUNCTION_TYPE_NETWORK ? "Network" : - "Arm")), pfob); - - memset(pfob, 0, sizeof(*pfob)); - - pfob->type = function_type; - pfob->csr_va = csr_va; - pfob->db_va = db_va; - pfob->pci_va = pci_va; - - spin_lock_init(&pfob->cq_lock); - spin_lock_init(&pfob->post_lock); - spin_lock_init(&pfob->mcc_context_lock); - - - pfob->pci_function_number = 1; - - - pfob->emulate = false; - TRACE(DL_NOTE, "Non-emulation mode"); - status = be_drive_POST(pfob); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "BladeEngine POST failed."); - goto error; - } - - /* Initialize the mailbox */ - status = be_mpu_init_mailbox(pfob, mailbox); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to initialize mailbox."); - goto error; - } - /* - * Cache the firmware config for ASSERTs in hwclib and later - * driver queries. - */ - status = be_function_internal_query_firmware_config(pfob, - &pfob->fw_config); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to query firmware config."); - goto error; - } - -error: - if (status != BE_SUCCESS) { - /* No cleanup necessary */ - TRACE(DL_ERR, "Failed to create function."); - memset(pfob, 0, sizeof(*pfob)); - } - return status; -} - -/* - This routine drops the reference count on a given function object. Once - the reference count falls to zero, the function object is destroyed and all - resources held are freed. - - FunctionObject - The function object to drop the reference to. -*/ -int be_function_object_destroy(struct be_function_object *pfob) -{ - TRACE(DL_INFO, "Destroy pfob. Object:0x%p", - pfob); - - - ASSERT(pfob->mcc == NULL); - - return BE_SUCCESS; -} - -int be_function_cleanup(struct be_function_object *pfob) -{ - int status = 0; - u32 isr; - u32 host_intr; - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - - - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) { - status = be_rxf_multicast_config(pfob, false, 0, - NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - } - /* VLAN */ - status = be_rxf_vlan_config(pfob, false, 0, NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - /* - * MCC Queue -- Switches to mailbox mode. May want to destroy - * all but the MCC CQ before this call if polling CQ is much better - * performance than polling mailbox register. - */ - if (pfob->mcc) - status = be_mcc_ring_destroy(pfob->mcc); - /* - * If interrupts are disabled, clear any CEV interrupt assertions that - * fired after we stopped processing EQs. - */ - ctrl.dw[0] = PCICFG1_READ(pfob, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - isr = CSR_READ(pfob, cev.isr1); - else - isr = CSR_READ(pfob, cev.isr0); - else - /* This should never happen... */ - TRACE(DL_ERR, "function_cleanup called with interrupt enabled"); - /* Function object destroy */ - status = be_function_object_destroy(pfob); - ASSERT(status == BE_SUCCESS); - - return status; -} - - -void * -be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, u32 payld_len, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - - ASSERT(wrb); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 1); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, min(payld_len, n)); - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -void * -be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - void *fwcmd_va, u64 fwcmd_pa, - u32 payld_len, - u32 request_length, - u32 response_length, - u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - struct MCC_WRB_PAYLOAD_AMAP *plp; - - ASSERT(wrb); - ASSERT(fwcmd_va); - - header = (struct FWCMD_REQUEST_HEADER *) fwcmd_va; - - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 0); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, payld_len); - - /* - * Assume one fragment. The caller may override the SGL by - * rewriting the 0th length and adding more entries. They - * will also need to update the sge_count. - */ - AMAP_SET_BITS_PTR(MCC_WRB, sge_count, wrb, 1); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - plp = (struct MCC_WRB_PAYLOAD_AMAP *)((u8 *)wrb + n); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].length, plp, payld_len); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_lo, plp, (u32)fwcmd_pa); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_hi, plp, - upper_32_bits(fwcmd_pa)); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob) -{ - struct MCC_WRB_AMAP *wrb = NULL; - u32 offset; - - if (pfob->mcc) - wrb = _be_mpu_peek_ring_wrb(pfob->mcc, false); - else { - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - wrb = (struct MCC_WRB_AMAP *) ((u8 *) pfob->mailbox.va + - offset); - } - - if (wrb) - memset(wrb, 0, sizeof(struct MCC_WRB_AMAP)); - - return wrb; -} - -#if defined(BE_DEBUG) -void be_function_debug_print_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *optional_fwcmd_va, - struct be_mcc_wrb_context *wrb_context) -{ - - struct FWCMD_REQUEST_HEADER *header = NULL; - u8 embedded; - u32 n; - - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, wrb); - - if (embedded) { - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - } else { - header = (struct FWCMD_REQUEST_HEADER *) optional_fwcmd_va; - } - - /* Save the completed count before posting for a debug assert. */ - - if (header) { - wrb_context->opcode = header->opcode; - wrb_context->subsystem = header->subsystem; - - } else { - wrb_context->opcode = 0; - wrb_context->subsystem = 0; - } -} -#else -#define be_function_debug_print_wrb(a_, b_, c_, d_) -#endif - -int -be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *rc) -{ - int status; - struct be_mcc_wrb_context *wrb_context = NULL; - u64 *p; - - if (q_ctxt) { - /* Initialize context. */ - q_ctxt->context.internal_cb = internal_cb; - q_ctxt->context.internal_cb_context = internal_cb_context; - q_ctxt->context.cb = cb; - q_ctxt->context.cb_context = cb_context; - if (rc) { - q_ctxt->context.copy.length = rc->length; - q_ctxt->context.copy.fwcmd_offset = rc->fwcmd_offset; - q_ctxt->context.copy.va = rc->va; - } else - q_ctxt->context.copy.length = 0; - - q_ctxt->context.optional_fwcmd_va = optional_fwcmd_va; - - /* Queue this request */ - status = be_function_queue_mcc_wrb(pfob, q_ctxt); - - goto Error; - } - /* - * Allocate a WRB context struct to hold the callback pointers, - * status, etc. This is required if commands complete out of order. - */ - wrb_context = _be_mcc_allocate_wrb_context(pfob); - if (!wrb_context) { - TRACE(DL_WARN, "Failed to allocate MCC WRB context."); - status = BE_STATUS_SYSTEM_RESOURCES; - goto Error; - } - /* Initialize context. */ - memset(wrb_context, 0, sizeof(*wrb_context)); - wrb_context->internal_cb = internal_cb; - wrb_context->internal_cb_context = internal_cb_context; - wrb_context->cb = cb; - wrb_context->cb_context = cb_context; - if (rc) { - wrb_context->copy.length = rc->length; - wrb_context->copy.fwcmd_offset = rc->fwcmd_offset; - wrb_context->copy.va = rc->va; - } else - wrb_context->copy.length = 0; - wrb_context->wrb = wrb; - - /* - * Copy the context pointer into the WRB opaque tag field. - * Verify assumption of 64-bit tag with a compile time assert. - */ - p = (u64 *) ((u8 *)wrb + offsetof(struct BE_MCC_WRB_AMAP, tag)/8); - *p = (u64)(size_t)wrb_context; - - /* Print info about this FWCMD for debug builds. */ - be_function_debug_print_wrb(pfob, wrb, optional_fwcmd_va, wrb_context); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - /* - * we're in WRB mode, pass to the mcc layer - */ - status = _be_mpu_post_wrb_ring(pfob->mcc, wrb, wrb_context); - } else { - /* - * we're in mailbox mode - */ - status = _be_mpu_post_wrb_mailbox(pfob, wrb, wrb_context); - - /* mailbox mode always completes synchronously */ - ASSERT(status != BE_STATUS_PENDING); - } - -Error: - - return status; -} - -int -be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context) -{ - - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy ring id:%d type:%d", id, ring_type); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = id; - fwcmd->params.request.ring_type = ring_type; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - internal_cb, internal_cb_context, fwcmd, NULL); - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "Ring destroy fwcmd failed. id:%d ring_type:%d", - id, ring_type); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -void -be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, u32 max_num) -{ - u32 num_pages = PAGES_SPANNED(rd->va, rd->length); - u32 i = 0; - u64 pa = rd->pa; - __le64 lepa; - - ASSERT(pa_list); - ASSERT(pa); - - for (i = 0; i < min(num_pages, max_num); i++) { - lepa = cpu_to_le64(pa); - pa_list[i].lo = (u32)lepa; - pa_list[i].hi = upper_32_bits(lepa); - pa += PAGE_SIZE; - } -} - - - -/*----------------------------------------------------------------------------- - * Function: be_function_get_fw_version - * Retrieves the firmware version on the adpater. If the callback is - * NULL this call executes synchronously. If the callback is not NULL, - * the returned status will be BE_PENDING if the command was issued - * successfully. - * pfob - - * fwv - Pointer to response buffer if callback is NULL. - * cb - Callback function invoked when the FWCMD completes. - * cb_context - Passed to the callback function. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fwv, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - int status = BE_SUCCESS; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_GET_FW_VERSION *fwcmd = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (!cb && !fwv) { - TRACE(DL_ERR, "callback and response buffer NULL!"); - status = BE_NOT_OK; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FW_VERSION); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.va = fwv; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd, &rc); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt) -{ - int status; - - ASSERT(q_ctxt); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - - /* We're in ring mode. Queue this item. */ - pfob->mcc->backlog_length++; - list_add_tail(&q_ctxt->context.list, &pfob->mcc->backlog); - status = BE_PENDING; - } else { - status = BE_NOT_OK; - } - return status; -} - diff --git a/drivers/staging/benet/fwcmd_common.h b/drivers/staging/benet/fwcmd_common.h deleted file mode 100644 index 406e0d6fa98..00000000000 --- a/drivers/staging/benet/fwcmd_common.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_amap_h__ -#define __fwcmd_common_amap_h__ -#include "host_struct.h" - -/* --- PHY_LINK_DUPLEX_ENUM --- */ -#define PHY_LINK_DUPLEX_NONE (0) -#define PHY_LINK_DUPLEX_HALF (1) -#define PHY_LINK_DUPLEX_FULL (2) - -/* --- PHY_LINK_SPEED_ENUM --- */ -#define PHY_LINK_SPEED_ZERO (0) /* No link. */ -#define PHY_LINK_SPEED_10MBPS (1) /* 10 Mbps */ -#define PHY_LINK_SPEED_100MBPS (2) /* 100 Mbps */ -#define PHY_LINK_SPEED_1GBPS (3) /* 1 Gbps */ -#define PHY_LINK_SPEED_10GBPS (4) /* 10 Gbps */ - -/* --- PHY_LINK_FAULT_ENUM --- */ -#define PHY_LINK_FAULT_NONE (0) /* No fault status - available or detected */ -#define PHY_LINK_FAULT_LOCAL (1) /* Local fault detected */ -#define PHY_LINK_FAULT_REMOTE (2) /* Remote fault detected */ - -/* --- BE_ULP_MASK --- */ -#define BE_ULP0_MASK (1) -#define BE_ULP1_MASK (2) -#define BE_ULP2_MASK (4) - -/* --- NTWK_ACTIVE_PORT --- */ -#define NTWK_PORT_A (0) /* Port A is currently active */ -#define NTWK_PORT_B (1) /* Port B is currently active */ -#define NTWK_NO_ACTIVE_PORT (15) /* Both ports have lost link */ - -/* --- NTWK_LINK_TYPE --- */ -#define NTWK_LINK_TYPE_PHYSICAL (0) /* link up/down event - applies to BladeEngine's - Physical Ports - */ -#define NTWK_LINK_TYPE_VIRTUAL (1) /* Virtual link up/down event - reported by BladeExchange. - This applies only when the - VLD feature is enabled - */ - -/* - * --- FWCMD_MAC_TYPE_ENUM --- - * This enum defines the types of MAC addresses in the RXF MAC Address Table. - */ -#define MAC_ADDRESS_TYPE_STORAGE (0) /* Storage MAC Address */ -#define MAC_ADDRESS_TYPE_NETWORK (1) /* Network MAC Address */ -#define MAC_ADDRESS_TYPE_PD (2) /* Protection Domain MAC Addr */ -#define MAC_ADDRESS_TYPE_MANAGEMENT (3) /* Managment MAC Address */ - - -/* --- FWCMD_RING_TYPE_ENUM --- */ -#define FWCMD_RING_TYPE_ETH_RX (1) /* Ring created with */ - /* FWCMD_COMMON_ETH_RX_CREATE. */ -#define FWCMD_RING_TYPE_ETH_TX (2) /* Ring created with */ - /* FWCMD_COMMON_ETH_TX_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_WRBQ (3) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_DEFQ (4) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_DEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_WRBQ (5) /* Ring created with */ - /* FWCMD_COMMON_TPM_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_DEFQ (6) /* Ring created with */ - /* FWCMD_COMMONTPM_TDEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_RQ (7) /* Ring created with */ - /* FWCMD_COMMON_TPM_RQ_CREATE. */ -#define FWCMD_RING_TYPE_MCC (8) /* Ring created with */ - /* FWCMD_COMMON_MCC_CREATE. */ -#define FWCMD_RING_TYPE_CQ (9) /* Ring created with */ - /* FWCMD_COMMON_CQ_CREATE. */ -#define FWCMD_RING_TYPE_EQ (10) /* Ring created with */ - /* FWCMD_COMMON_EQ_CREATE. */ -#define FWCMD_RING_TYPE_QP (11) /* Ring created with */ - /* FWCMD_RDMA_QP_CREATE. */ - - -/* --- ETH_TX_RING_TYPE_ENUM --- */ -#define ETH_TX_RING_TYPE_FORWARDING (1) /* Ethernet ring for - forwarding packets */ -#define ETH_TX_RING_TYPE_STANDARD (2) /* Ethernet ring for sending - network packets. */ -#define ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring bound to the - port specified in the command - header.port_number field. - Rings of this type are - NOT subject to the - failover logic implemented - in the BladeEngine. - */ - -/* --- FWCMD_COMMON_QOS_TYPE_ENUM --- */ -#define QOS_BITS_NIC (1) /* max_bits_per_second_NIC */ - /* field is valid. */ -#define QOS_PKTS_NIC (2) /* max_packets_per_second_NIC */ - /* field is valid. */ -#define QOS_IOPS_ISCSI (4) /* max_ios_per_second_iSCSI */ - /*field is valid. */ -#define QOS_VLAN_TAG (8) /* domain_VLAN_tag field - is valid. */ -#define QOS_FABRIC_ID (16) /* fabric_domain_ID field - is valid. */ -#define QOS_OEM_PARAMS (32) /* qos_params_oem field - is valid. */ -#define QOS_TPUT_ISCSI (64) /* max_bytes_per_second_iSCSI - field is valid. */ - - -/* - * --- FAILOVER_CONFIG_ENUM --- - * Failover configuration setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_CONFIG_NO_CHANGE (0) /* No change to automatic */ - /* port failover setting. */ -#define FAILOVER_CONFIG_ON (1) /* Automatic port failover - on link down is enabled. */ -#define FAILOVER_CONFIG_OFF (2) /* Automatic port failover - on link down is disabled. */ - -/* - * --- FAILOVER_PORT_ENUM --- - * Failover port setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_PORT_A (0) /* Selects port A. */ -#define FAILOVER_PORT_B (1) /* Selects port B. */ -#define FAILOVER_PORT_NONE (15) /* No port change requested. */ - - -/* - * --- MGMT_FLASHROM_OPCODE --- - * Flash ROM operation code - */ -#define MGMT_FLASHROM_OPCODE_FLASH (1) /* Commit downloaded data - to Flash ROM */ -#define MGMT_FLASHROM_OPCODE_SAVE (2) /* Save downloaded data to - ARM's DDR - do not flash */ -#define MGMT_FLASHROM_OPCODE_CLEAR (3) /* Erase specified component - from FlashROM */ -#define MGMT_FLASHROM_OPCODE_REPORT (4) /* Read specified component - from Flash ROM */ -#define MGMT_FLASHROM_OPCODE_IMAGE_INFO (5) /* Returns size of a - component */ - -/* - * --- MGMT_FLASHROM_OPTYPE --- - * Flash ROM operation type - */ -#define MGMT_FLASHROM_OPTYPE_CODE_FIRMWARE (0) /* Includes ARM firmware, - IPSec (optional) and EP - firmware */ -#define MGMT_FLASHROM_OPTYPE_CODE_REDBOOT (1) -#define MGMT_FLASHROM_OPTYPE_CODE_BIOS (2) -#define MGMT_FLASHROM_OPTYPE_CODE_PXE_BIOS (3) -#define MGMT_FLASHROM_OPTYPE_CODE_CTRLS (4) -#define MGMT_FLASHROM_OPTYPE_CFG_IPSEC (5) -#define MGMT_FLASHROM_OPTYPE_CFG_INI (6) -#define MGMT_FLASHROM_OPTYPE_ROM_OFFSET_SPECIFIED (7) - -/* - * --- FLASHROM_TYPE --- - * Flash ROM manufacturers supported in the f/w - */ -#define INTEL (0) -#define SPANSION (1) -#define MICRON (2) - -/* --- DDR_CAS_TYPE --- */ -#define CAS_3 (0) -#define CAS_4 (1) -#define CAS_5 (2) - -/* --- DDR_SIZE_TYPE --- */ -#define SIZE_256MB (0) -#define SIZE_512MB (1) - -/* --- DDR_MODE_TYPE --- */ -#define DDR_NO_ECC (0) -#define DDR_ECC (1) - -/* --- INTERFACE_10GB_TYPE --- */ -#define CX4_TYPE (0) -#define XFP_TYPE (1) - -/* --- BE_CHIP_MAX_MTU --- */ -#define CHIP_MAX_MTU (9000) - -/* --- XAUI_STATE_ENUM --- */ -#define XAUI_STATE_ENABLE (0) /* This MUST be the default - value for all requests - which set/change - equalization parameter. */ -#define XAUI_STATE_DISABLE (255) /* The XAUI for both ports - may be disabled for EMI - tests. There is no - provision for turning off - individual ports. - */ -/* --- BE_ASIC_REVISION --- */ -#define BE_ASIC_REV_A0 (1) -#define BE_ASIC_REV_A1 (2) - -#endif /* __fwcmd_common_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_common_bmap.h b/drivers/staging/benet/fwcmd_common_bmap.h deleted file mode 100644 index a007cf27650..00000000000 --- a/drivers/staging/benet/fwcmd_common_bmap.h +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_bmap_h__ -#define __fwcmd_common_bmap_h__ -#include "fwcmd_types_bmap.h" -#include "fwcmd_hdr_bmap.h" - -#if defined(__BIG_ENDIAN) - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - - -#else - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - -struct BE_LINK_STATUS { - u8 mac0_duplex; - u8 mac0_speed; - u8 mac1_duplex; - u8 mac1_speed; - u8 mgmt_mac_duplex; - u8 mgmt_mac_speed; - u8 active_port; - u8 rsvd0; - u8 mac0_fault; - u8 mac1_fault; - u16 rsvd1; -} __packed; -#endif - -struct FWCMD_COMMON_ANON_170_REQUEST { - u32 rsvd0; -} __packed; - -union LINK_STATUS_QUERY_PARAMS { - struct BE_LINK_STATUS response; - struct FWCMD_COMMON_ANON_170_REQUEST request; -} __packed; - -/* - * Queries the the link status for all ports. The valid values below - * DO NOT indicate that a particular duplex or speed is supported by - * BladeEngine. These enumerations simply list all possible duplexes - * and speeds for any port. Consult BladeEngine product documentation - * for the supported parameters. - */ -struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY { - union FWCMD_HEADER header; - union LINK_STATUS_QUERY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_171_REQUEST { - u8 type; - u8 port; - u8 mac1; - u8 permanent; -} __packed; - -struct FWCMD_COMMON_ANON_172_RESPONSE { - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -union NTWK_MAC_QUERY_PARAMS { - struct FWCMD_COMMON_ANON_171_REQUEST request; - struct FWCMD_COMMON_ANON_172_RESPONSE response; -} __packed; - -/* Queries one MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_QUERY { - union FWCMD_HEADER header; - union NTWK_MAC_QUERY_PARAMS params; -} __packed; - -struct MAC_SET_PARAMS_IN { - u8 type; - u8 port; - u8 mac1; - u8 invalidate; - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -struct MAC_SET_PARAMS_OUT { - u32 rsvd0; -} __packed; - -union MAC_SET_PARAMS { - struct MAC_SET_PARAMS_IN request; - struct MAC_SET_PARAMS_OUT response; -} __packed; - -/* Sets a MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_SET { - union FWCMD_HEADER header; - union MAC_SET_PARAMS params; -} __packed; - -/* MAC address list. */ -struct NTWK_MULTICAST_MAC_LIST { - u8 byte[6]; -} __packed; - -struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD { - u16 num_mac; - u8 promiscuous; - u8 rsvd0; - struct NTWK_MULTICAST_MAC_LIST mac[32]; -} __packed; - -struct FWCMD_COMMON_ANON_174_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_173_PARAMS { - struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_174_RESPONSE response; -} __packed; - -/* - * Sets multicast address hash. The MPU will merge the MAC address lists - * from all clients, including the networking and storage functions. - * This command may fail if the final merged list of MAC addresses exceeds - * 32 entries. - */ -struct FWCMD_COMMON_NTWK_MULTICAST_SET { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_173_PARAMS params; -} __packed; - -struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD { - u16 num_vlan; - u8 promiscuous; - u8 rsvd0; - u16 vlan_tag[32]; -} __packed; - -struct FWCMD_COMMON_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_175_PARAMS { - struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_176_RESPONSE response; -} __packed; - -/* - * Sets VLAN tag filter. The MPU will merge the VLAN tag list from all - * clients, including the networking and storage functions. This command - * may fail if the final vlan_tag array (from all functions) is longer - * than 32 entries. - */ -struct FWCMD_COMMON_NTWK_VLAN_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_175_PARAMS params; -} __packed; - -struct RING_DESTROY_REQUEST { - u16 ring_type; - u16 id; - u8 bypass_flush; - u8 rsvd0; - u16 rsvd1; -} __packed; - -struct FWCMD_COMMON_ANON_190_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_189_PARAMS { - struct RING_DESTROY_REQUEST request; - struct FWCMD_COMMON_ANON_190_RESPONSE response; -} __packed; -/* - * Command for destroying any ring. The connection(s) using the ring should - * be quiesced before destroying the ring. - */ -struct FWCMD_COMMON_RING_DESTROY { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_189_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_192_REQUEST { - u16 num_pages; - u16 rsvd0; - struct CQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[4]; -} __packed ; - -struct FWCMD_COMMON_ANON_193_RESPONSE { - u16 cq_id; -} __packed ; - -union FWCMD_COMMON_ANON_191_PARAMS { - struct FWCMD_COMMON_ANON_192_REQUEST request; - struct FWCMD_COMMON_ANON_193_RESPONSE response; -} __packed ; - -/* - * Command for creating a completion queue. A Completion Queue must span - * at least 1 page and at most 4 pages. Each completion queue entry - * is 16 bytes regardless of CQ entry format. Thus the ring must be - * at least 256 entries deep (corresponding to 1 page) and can be at - * most 1024 entries deep (corresponding to 4 pages). The number of - * pages posted must contain the CQ ring size as encoded in the context. - * - */ -struct FWCMD_COMMON_CQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_191_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_198_REQUEST { - u16 num_pages; - u16 rsvd0; - struct EQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_199_RESPONSE { - u16 eq_id; -} __packed ; - -union FWCMD_COMMON_ANON_197_PARAMS { - struct FWCMD_COMMON_ANON_198_REQUEST request; - struct FWCMD_COMMON_ANON_199_RESPONSE response; -} __packed ; - -/* - * Command for creating a event queue. An Event Queue must span at least - * 1 page and at most 8 pages. The number of pages posted must contain - * the EQ ring. The ring is defined by the size of the EQ entries (encoded - * in the context) and the number of EQ entries (also encoded in the - * context). - */ -struct FWCMD_COMMON_EQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_197_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_201_REQUEST { - u16 cq_id; - u16 bcmc_cq_id; - u16 num_pages; - u16 rsvd0; - struct PHYS_ADDR pages[2]; -} __packed; - -struct FWCMD_COMMON_ANON_202_RESPONSE { - u16 id; -} __packed; - -union FWCMD_COMMON_ANON_200_PARAMS { - struct FWCMD_COMMON_ANON_201_REQUEST request; - struct FWCMD_COMMON_ANON_202_RESPONSE response; -} __packed; - -/* - * Command for creating Ethernet receive ring. An ERX ring contains ETH_RX_D - * entries (8 bytes each). An ERX ring must be 1024 entries deep - * (corresponding to 2 pages). - */ -struct FWCMD_COMMON_ETH_RX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_200_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_204_REQUEST { - u16 num_pages; - u8 ulp_num; - u8 type; - struct ETX_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_205_RESPONSE { - u16 cid; - u8 ulp_num; - u8 rsvd0; -} __packed ; - -union FWCMD_COMMON_ANON_203_PARAMS { - struct FWCMD_COMMON_ANON_204_REQUEST request; - struct FWCMD_COMMON_ANON_205_RESPONSE response; -} __packed ; - -/* - * Command for creating an Ethernet transmit ring. An ETX ring contains - * ETH_WRB entries (16 bytes each). An ETX ring must be at least 256 - * entries deep (corresponding to 1 page) and at most 2k entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_ETH_TX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_203_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_222_REQUEST { - u16 num_pages; - u16 rsvd0; - struct MCC_RING_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_223_RESPONSE { - u16 id; -} __packed ; - -union FWCMD_COMMON_ANON_221_PARAMS { - struct FWCMD_COMMON_ANON_222_REQUEST request; - struct FWCMD_COMMON_ANON_223_RESPONSE response; -} __packed ; - -/* - * Command for creating the MCC ring. An MCC ring must be at least 16 - * entries deep (corresponding to 1 page) and at most 128 entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_MCC_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_221_PARAMS params; -} __packed ; - -struct GET_QOS_IN { - u32 qos_params_rsvd; -} __packed; - -struct GET_QOS_OUT { - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -union GET_QOS_PARAMS { - struct GET_QOS_IN request; - struct GET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_GET_QOS { - union FWCMD_HEADER header; - union GET_QOS_PARAMS params; -} __packed; - -struct SET_QOS_IN { - u32 valid_flags; - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -struct SET_QOS_OUT { - u32 qos_params_rsvd; -} __packed; - -union SET_QOS_PARAMS { - struct SET_QOS_IN request; - struct SET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_SET_QOS { - union FWCMD_HEADER header; - union SET_QOS_PARAMS params; -} __packed; - -struct SET_FRAME_SIZE_IN { - u32 max_tx_frame_size; - u32 max_rx_frame_size; -} __packed; - -struct SET_FRAME_SIZE_OUT { - u32 chip_max_tx_frame_size; - u32 chip_max_rx_frame_size; -} __packed; - -union SET_FRAME_SIZE_PARAMS { - struct SET_FRAME_SIZE_IN request; - struct SET_FRAME_SIZE_OUT response; -} __packed; - -/* Set frame size command. Only host domain may issue this command. */ -struct FWCMD_COMMON_SET_FRAME_SIZE { - union FWCMD_HEADER header; - union SET_FRAME_SIZE_PARAMS params; -} __packed; - -struct FORCE_FAILOVER_IN { - u32 move_to_port; - u32 failover_config; -} __packed; - -struct FWCMD_COMMON_ANON_231_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_230_PARAMS { - struct FORCE_FAILOVER_IN request; - struct FWCMD_COMMON_ANON_231_RESPONSE response; -} __packed; - -/* - * Use this command to control failover in BladeEngine. It may be used - * to failback to a restored port or to forcibly move traffic from - * one port to another. It may also be used to enable or disable the - * automatic failover feature. This command can only be issued by domain - * 0. - */ -struct FWCMD_COMMON_FORCE_FAILOVER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_230_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_240_REQUEST { - u64 context; -} __packed; - -struct FWCMD_COMMON_ANON_241_RESPONSE { - u64 context; -} __packed; - -union FWCMD_COMMON_ANON_239_PARAMS { - struct FWCMD_COMMON_ANON_240_REQUEST request; - struct FWCMD_COMMON_ANON_241_RESPONSE response; -} __packed; - -/* - * This command can be used by clients as a no-operation request. Typical - * uses for drivers are as a heartbeat mechanism, or deferred processing - * catalyst. The ARM will always complete this command with a good completion. - * The 64-bit parameter is not touched by the ARM processor. - */ -struct FWCMD_COMMON_NOP { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_239_PARAMS params; -} __packed; - -struct NTWK_RX_FILTER_SETTINGS { - u8 promiscuous; - u8 ip_cksum; - u8 tcp_cksum; - u8 udp_cksum; - u8 pass_err; - u8 pass_ckerr; - u8 strip_crc; - u8 mcast_en; - u8 bcast_en; - u8 mcast_promiscuous_en; - u8 unicast_en; - u8 vlan_promiscuous; -} __packed; - -union FWCMD_COMMON_ANON_242_PARAMS { - struct NTWK_RX_FILTER_SETTINGS request; - struct NTWK_RX_FILTER_SETTINGS response; -} __packed; - -/* - * This command is used to modify the ethernet receive filter configuration. - * Only domain 0 network function drivers may issue this command. The - * applied configuration is returned in the response payload. Note: - * Some receive packet filter settings are global on BladeEngine and - * can affect both the storage and network function clients that the - * BladeEngine hardware and firmware serve. Additionaly, depending - * on the revision of BladeEngine, some ethernet receive filter settings - * are dependent on others. If a dependency exists between settings - * for the BladeEngine revision, and the command request settings do - * not meet the dependency requirement, the invalid settings will not - * be applied despite the comand succeeding. For example: a driver may - * request to enable broadcast packets, but not enable multicast packets. - * On early revisions of BladeEngine, there may be no distinction between - * broadcast and multicast filters, so broadcast could not be enabled - * without enabling multicast. In this scenario, the comand would still - * succeed, but the response payload would indicate the previously - * configured broadcast and multicast setting. - */ -struct FWCMD_COMMON_NTWK_RX_FILTER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_242_PARAMS params; -} __packed; - - -struct FWCMD_COMMON_ANON_244_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD { - u8 firmware_version_string[32]; - u8 fw_on_flash_version_string[32]; -} __packed; - -union FWCMD_COMMON_ANON_243_PARAMS { - struct FWCMD_COMMON_ANON_244_REQUEST request; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD response; -} __packed; - -/* This comand retrieves the firmware version. */ -struct FWCMD_COMMON_GET_FW_VERSION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_243_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_246_REQUEST { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -struct FWCMD_COMMON_ANON_247_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_245_PARAMS { - struct FWCMD_COMMON_ANON_246_REQUEST request; - struct FWCMD_COMMON_ANON_247_RESPONSE response; -} __packed; - -/* - * This comand is used to program BladeEngine flow control behavior. - * Only the host networking driver is allowed to use this comand. - */ -struct FWCMD_COMMON_SET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_245_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_249_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_ANON_250_RESPONSE { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -union FWCMD_COMMON_ANON_248_PARAMS { - struct FWCMD_COMMON_ANON_249_REQUEST request; - struct FWCMD_COMMON_ANON_250_RESPONSE response; -} __packed; - -/* This comand is used to read BladeEngine flow control settings. */ -struct FWCMD_COMMON_GET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_248_PARAMS params; -} __packed; - -struct EQ_DELAY_PARAMS { - u32 eq_id; - u32 delay_in_microseconds; -} __packed; - -struct FWCMD_COMMON_ANON_257_REQUEST { - u32 num_eq; - u32 rsvd0; - struct EQ_DELAY_PARAMS delay[16]; -} __packed; - -struct FWCMD_COMMON_ANON_258_RESPONSE { - u32 delay_resolution_in_microseconds; - u32 delay_max_in_microseconds; -} __packed; - -union MODIFY_EQ_DELAY_PARAMS { - struct FWCMD_COMMON_ANON_257_REQUEST request; - struct FWCMD_COMMON_ANON_258_RESPONSE response; -} __packed; - -/* This comand changes the EQ delay for a given set of EQs. */ -struct FWCMD_COMMON_MODIFY_EQ_DELAY { - union FWCMD_HEADER header; - union MODIFY_EQ_DELAY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_260_REQUEST { - u32 rsvd0; -} __packed; - -struct BE_FIRMWARE_CONFIG { - u16 be_config_number; - u16 asic_revision; - u32 nic_ulp_mask; - u32 tulp_mask; - u32 iscsi_ulp_mask; - u32 rdma_ulp_mask; - u32 rsvd0[4]; - u32 eth_tx_id_start; - u32 eth_tx_id_count; - u32 eth_rx_id_start; - u32 eth_rx_id_count; - u32 tpm_wrbq_id_start; - u32 tpm_wrbq_id_count; - u32 tpm_defq_id_start; - u32 tpm_defq_id_count; - u32 iscsi_wrbq_id_start; - u32 iscsi_wrbq_id_count; - u32 iscsi_defq_id_start; - u32 iscsi_defq_id_count; - u32 rdma_qp_id_start; - u32 rdma_qp_id_count; - u32 rsvd1[8]; -} __packed; - -union FWCMD_COMMON_ANON_259_PARAMS { - struct FWCMD_COMMON_ANON_260_REQUEST request; - struct BE_FIRMWARE_CONFIG response; -} __packed; - -/* - * This comand queries the current firmware configuration parameters. - * The static configuration type is defined by be_config_number. This - * differentiates different BladeEngine builds, such as iSCSI Initiator - * versus iSCSI Target. For a given static configuration, the Upper - * Layer Protocol (ULP) processors may be reconfigured to support different - * protocols. Each ULP processor supports one or more protocols. The - * masks indicate which processors are configured for each protocol. - * For a given static configuration, the number of TCP connections - * supported for each protocol may vary. The *_id_start and *_id_count - * variables define a linear range of IDs that are available for each - * supported protocol. The *_id_count may be used by the driver to allocate - * the appropriate number of connection resources. The *_id_start may - * be used to map the arbitrary range of IDs to a zero-based range - * of indices. - */ -struct FWCMD_COMMON_FIRMWARE_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_259_PARAMS params; -} __packed; - -struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS { - u32 emph_lev_sel_port0; - u32 emph_lev_sel_port1; - u8 xaui_vo_sel; - u8 xaui_state; - u16 rsvd0; - u32 xaui_eq_vector; -} __packed; - -struct FWCMD_COMMON_ANON_262_REQUEST { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_261_PARAMS { - struct FWCMD_COMMON_ANON_262_REQUEST request; - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS response; -} __packed; - -/* - * This comand can be used to read XAUI equalization parameters. The - * ARM firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_GET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_261_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_264_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_263_PARAMS { - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS request; - struct FWCMD_COMMON_ANON_264_RESPONSE response; -} __packed; - -/* - * This comand can be used to set XAUI equalization parameters. The ARM - * firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_SET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_263_PARAMS params; -} __packed; - -#endif /* __fwcmd_common_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_eth_bmap.h b/drivers/staging/benet/fwcmd_eth_bmap.h deleted file mode 100644 index 234b179eace..00000000000 --- a/drivers/staging/benet/fwcmd_eth_bmap.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_eth_bmap_h__ -#define __fwcmd_eth_bmap_h__ -#include "fwcmd_hdr_bmap.h" -#include "fwcmd_types_bmap.h" - -struct MIB_ETH_STATISTICS_PARAMS_IN { - u32 rsvd0; -} __packed; - -struct BE_RXF_STATS { - u32 p0recvdtotalbytesLSD; /* DWORD 0 */ - u32 p0recvdtotalbytesMSD; /* DWORD 1 */ - u32 p0recvdtotalframes; /* DWORD 2 */ - u32 p0recvdunicastframes; /* DWORD 3 */ - u32 p0recvdmulticastframes; /* DWORD 4 */ - u32 p0recvdbroadcastframes; /* DWORD 5 */ - u32 p0crcerrors; /* DWORD 6 */ - u32 p0alignmentsymerrs; /* DWORD 7 */ - u32 p0pauseframesrecvd; /* DWORD 8 */ - u32 p0controlframesrecvd; /* DWORD 9 */ - u32 p0inrangelenerrors; /* DWORD 10 */ - u32 p0outrangeerrors; /* DWORD 11 */ - u32 p0frametoolongerrors; /* DWORD 12 */ - u32 p0droppedaddressmatch; /* DWORD 13 */ - u32 p0droppedvlanmismatch; /* DWORD 14 */ - u32 p0ipdroppedtoosmall; /* DWORD 15 */ - u32 p0ipdroppedtooshort; /* DWORD 16 */ - u32 p0ipdroppedhdrtoosmall; /* DWORD 17 */ - u32 p0tcpdroppedlen; /* DWORD 18 */ - u32 p0droppedrunt; /* DWORD 19 */ - u32 p0recvd64; /* DWORD 20 */ - u32 p0recvd65_127; /* DWORD 21 */ - u32 p0recvd128_256; /* DWORD 22 */ - u32 p0recvd256_511; /* DWORD 23 */ - u32 p0recvd512_1023; /* DWORD 24 */ - u32 p0recvd1518_1522; /* DWORD 25 */ - u32 p0recvd1522_2047; /* DWORD 26 */ - u32 p0recvd2048_4095; /* DWORD 27 */ - u32 p0recvd4096_8191; /* DWORD 28 */ - u32 p0recvd8192_9216; /* DWORD 29 */ - u32 p0rcvdipcksmerrs; /* DWORD 30 */ - u32 p0recvdtcpcksmerrs; /* DWORD 31 */ - u32 p0recvdudpcksmerrs; /* DWORD 32 */ - u32 p0recvdnonrsspackets; /* DWORD 33 */ - u32 p0recvdippackets; /* DWORD 34 */ - u32 p0recvdchute1packets; /* DWORD 35 */ - u32 p0recvdchute2packets; /* DWORD 36 */ - u32 p0recvdchute3packets; /* DWORD 37 */ - u32 p0recvdipsecpackets; /* DWORD 38 */ - u32 p0recvdmanagementpackets; /* DWORD 39 */ - u32 p0xmitbyteslsd; /* DWORD 40 */ - u32 p0xmitbytesmsd; /* DWORD 41 */ - u32 p0xmitunicastframes; /* DWORD 42 */ - u32 p0xmitmulticastframes; /* DWORD 43 */ - u32 p0xmitbroadcastframes; /* DWORD 44 */ - u32 p0xmitpauseframes; /* DWORD 45 */ - u32 p0xmitcontrolframes; /* DWORD 46 */ - u32 p0xmit64; /* DWORD 47 */ - u32 p0xmit65_127; /* DWORD 48 */ - u32 p0xmit128_256; /* DWORD 49 */ - u32 p0xmit256_511; /* DWORD 50 */ - u32 p0xmit512_1023; /* DWORD 51 */ - u32 p0xmit1518_1522; /* DWORD 52 */ - u32 p0xmit1522_2047; /* DWORD 53 */ - u32 p0xmit2048_4095; /* DWORD 54 */ - u32 p0xmit4096_8191; /* DWORD 55 */ - u32 p0xmit8192_9216; /* DWORD 56 */ - u32 p0rxfifooverflowdropped; /* DWORD 57 */ - u32 p0ipseclookupfaileddropped; /* DWORD 58 */ - u32 p1recvdtotalbytesLSD; /* DWORD 59 */ - u32 p1recvdtotalbytesMSD; /* DWORD 60 */ - u32 p1recvdtotalframes; /* DWORD 61 */ - u32 p1recvdunicastframes; /* DWORD 62 */ - u32 p1recvdmulticastframes; /* DWORD 63 */ - u32 p1recvdbroadcastframes; /* DWORD 64 */ - u32 p1crcerrors; /* DWORD 65 */ - u32 p1alignmentsymerrs; /* DWORD 66 */ - u32 p1pauseframesrecvd; /* DWORD 67 */ - u32 p1controlframesrecvd; /* DWORD 68 */ - u32 p1inrangelenerrors; /* DWORD 69 */ - u32 p1outrangeerrors; /* DWORD 70 */ - u32 p1frametoolongerrors; /* DWORD 71 */ - u32 p1droppedaddressmatch; /* DWORD 72 */ - u32 p1droppedvlanmismatch; /* DWORD 73 */ - u32 p1ipdroppedtoosmall; /* DWORD 74 */ - u32 p1ipdroppedtooshort; /* DWORD 75 */ - u32 p1ipdroppedhdrtoosmall; /* DWORD 76 */ - u32 p1tcpdroppedlen; /* DWORD 77 */ - u32 p1droppedrunt; /* DWORD 78 */ - u32 p1recvd64; /* DWORD 79 */ - u32 p1recvd65_127; /* DWORD 80 */ - u32 p1recvd128_256; /* DWORD 81 */ - u32 p1recvd256_511; /* DWORD 82 */ - u32 p1recvd512_1023; /* DWORD 83 */ - u32 p1recvd1518_1522; /* DWORD 84 */ - u32 p1recvd1522_2047; /* DWORD 85 */ - u32 p1recvd2048_4095; /* DWORD 86 */ - u32 p1recvd4096_8191; /* DWORD 87 */ - u32 p1recvd8192_9216; /* DWORD 88 */ - u32 p1rcvdipcksmerrs; /* DWORD 89 */ - u32 p1recvdtcpcksmerrs; /* DWORD 90 */ - u32 p1recvdudpcksmerrs; /* DWORD 91 */ - u32 p1recvdnonrsspackets; /* DWORD 92 */ - u32 p1recvdippackets; /* DWORD 93 */ - u32 p1recvdchute1packets; /* DWORD 94 */ - u32 p1recvdchute2packets; /* DWORD 95 */ - u32 p1recvdchute3packets; /* DWORD 96 */ - u32 p1recvdipsecpackets; /* DWORD 97 */ - u32 p1recvdmanagementpackets; /* DWORD 98 */ - u32 p1xmitbyteslsd; /* DWORD 99 */ - u32 p1xmitbytesmsd; /* DWORD 100 */ - u32 p1xmitunicastframes; /* DWORD 101 */ - u32 p1xmitmulticastframes; /* DWORD 102 */ - u32 p1xmitbroadcastframes; /* DWORD 103 */ - u32 p1xmitpauseframes; /* DWORD 104 */ - u32 p1xmitcontrolframes; /* DWORD 105 */ - u32 p1xmit64; /* DWORD 106 */ - u32 p1xmit65_127; /* DWORD 107 */ - u32 p1xmit128_256; /* DWORD 108 */ - u32 p1xmit256_511; /* DWORD 109 */ - u32 p1xmit512_1023; /* DWORD 110 */ - u32 p1xmit1518_1522; /* DWORD 111 */ - u32 p1xmit1522_2047; /* DWORD 112 */ - u32 p1xmit2048_4095; /* DWORD 113 */ - u32 p1xmit4096_8191; /* DWORD 114 */ - u32 p1xmit8192_9216; /* DWORD 115 */ - u32 p1rxfifooverflowdropped; /* DWORD 116 */ - u32 p1ipseclookupfaileddropped; /* DWORD 117 */ - u32 pxdroppednopbuf; /* DWORD 118 */ - u32 pxdroppednotxpb; /* DWORD 119 */ - u32 pxdroppednoipsecbuf; /* DWORD 120 */ - u32 pxdroppednoerxdescr; /* DWORD 121 */ - u32 pxdroppednotpredescr; /* DWORD 122 */ - u32 pxrecvdmanagementportpackets; /* DWORD 123 */ - u32 pxrecvdmanagementportbytes; /* DWORD 124 */ - u32 pxrecvdmanagementportpauseframes; /* DWORD 125 */ - u32 pxrecvdmanagementporterrors; /* DWORD 126 */ - u32 pxxmitmanagementportpackets; /* DWORD 127 */ - u32 pxxmitmanagementportbytes; /* DWORD 128 */ - u32 pxxmitmanagementportpause; /* DWORD 129 */ - u32 pxxmitmanagementportrxfifooverflow; /* DWORD 130 */ - u32 pxrecvdipsecipcksmerrs; /* DWORD 131 */ - u32 pxrecvdtcpsecipcksmerrs; /* DWORD 132 */ - u32 pxrecvdudpsecipcksmerrs; /* DWORD 133 */ - u32 pxipsecrunt; /* DWORD 134 */ - u32 pxipsecaddressmismatchdropped; /* DWORD 135 */ - u32 pxipsecrxfifooverflowdropped; /* DWORD 136 */ - u32 pxipsecframestoolong; /* DWORD 137 */ - u32 pxipsectotalipframes; /* DWORD 138 */ - u32 pxipseciptoosmall; /* DWORD 139 */ - u32 pxipseciptooshort; /* DWORD 140 */ - u32 pxipseciphdrtoosmall; /* DWORD 141 */ - u32 pxipsectcphdrbad; /* DWORD 142 */ - u32 pxrecvdipsecchute1; /* DWORD 143 */ - u32 pxrecvdipsecchute2; /* DWORD 144 */ - u32 pxrecvdipsecchute3; /* DWORD 145 */ - u32 pxdropped7frags; /* DWORD 146 */ - u32 pxdroppedfrags; /* DWORD 147 */ - u32 pxdroppedinvalidfragring; /* DWORD 148 */ - u32 pxnumforwardedpackets; /* DWORD 149 */ -} __packed; - -union MIB_ETH_STATISTICS_PARAMS { - struct MIB_ETH_STATISTICS_PARAMS_IN request; - struct BE_RXF_STATS response; -} __packed; - -/* - * Query ethernet statistics. All domains may issue this command. The - * host domain drivers may optionally reset internal statistic counters - * with a query. - */ -struct FWCMD_ETH_GET_STATISTICS { - union FWCMD_HEADER header; - union MIB_ETH_STATISTICS_PARAMS params; -} __packed; - - -struct FWCMD_ETH_ANON_175_REQUEST { - u8 port0_promiscuous; - u8 port1_promiscuous; - u16 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_ETH_ANON_174_PARAMS { - struct FWCMD_ETH_ANON_175_REQUEST request; - struct FWCMD_ETH_ANON_176_RESPONSE response; -} __packed; - -/* Enables/Disables promiscuous ethernet receive mode. */ -struct FWCMD_ETH_PROMISCUOUS { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_174_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_178_REQUEST { - u32 new_fragsize_log2; -} __packed; - -struct FWCMD_ETH_ANON_179_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_177_PARAMS { - struct FWCMD_ETH_ANON_178_REQUEST request; - struct FWCMD_ETH_ANON_179_RESPONSE response; -} __packed; - -/* - * Sets the Ethernet RX fragment size. Only host (domain 0) networking - * drivers may issue this command. This call will fail for non-host - * protection domains. In this situation the MCC CQ status will indicate - * a failure due to insufficient priviledges. The response should be - * ignored, and the driver should use the FWCMD_ETH_GET_FRAG_SIZE to - * query the existing ethernet receive fragment size. It must use this - * fragment size for all fragments in the ethernet receive ring. If - * the command succeeds, the driver must use the frag size indicated - * in the command response since the requested frag size may not be applied - * until the next reboot. When the requested fragsize matches the response - * fragsize, this indicates the request was applied immediately. - */ -struct FWCMD_ETH_SET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_177_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_181_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_182_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_180_PARAMS { - struct FWCMD_ETH_ANON_181_REQUEST request; - struct FWCMD_ETH_ANON_182_RESPONSE response; -} __packed; - -/* - * Queries the Ethernet RX fragment size. All domains may issue this - * command. The driver should call this command to determine the minimum - * required fragment size for the ethernet RX ring buffers. Drivers - * may choose to use a larger size for each fragment buffer, but BladeEngine - * will use up to the configured minimum required fragsize in each ethernet - * receive fragment buffer. For example, if the ethernet receive fragment - * size is configured to 4kB, and a driver uses 8kB fragments, a 6kB - * ethernet packet received by BladeEngine will be split accross two - * of the driver's receive framgents (4kB in one fragment buffer, and - * 2kB in the subsequent fragment buffer). - */ -struct FWCMD_ETH_GET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_180_PARAMS params; -} __packed; - -#endif /* __fwcmd_eth_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_hdr_bmap.h b/drivers/staging/benet/fwcmd_hdr_bmap.h deleted file mode 100644 index 28b45328fe7..00000000000 --- a/drivers/staging/benet/fwcmd_hdr_bmap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_hdr_bmap_h__ -#define __fwcmd_hdr_bmap_h__ - -struct FWCMD_REQUEST_HEADER { - u8 opcode; - u8 subsystem; - u8 port_number; - u8 domain; - u32 timeout; - u32 request_length; - u32 rsvd0; -} __packed; - -struct FWCMD_RESPONSE_HEADER { - u8 opcode; - u8 subsystem; - u8 rsvd0; - u8 domain; - u8 status; - u8 additional_status; - u16 rsvd1; - u32 response_length; - u32 actual_response_length; -} __packed; - -/* - * The firmware/driver overwrites the input FWCMD_REQUEST_HEADER with - * the output FWCMD_RESPONSE_HEADER. - */ -union FWCMD_HEADER { - struct FWCMD_REQUEST_HEADER request; - struct FWCMD_RESPONSE_HEADER response; -} __packed; - -#endif /* __fwcmd_hdr_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_mcc.h b/drivers/staging/benet/fwcmd_mcc.h deleted file mode 100644 index 9eeca878c1f..00000000000 --- a/drivers/staging/benet/fwcmd_mcc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_mcc_amap_h__ -#define __fwcmd_mcc_amap_h__ -#include "fwcmd_opcodes.h" -/* - * Where applicable, a WRB, may contain a list of Scatter-gather elements. - * Each element supports a 64 bit address and a 32bit length field. - */ -struct BE_MCC_SGE_AMAP { - u8 pa_lo[32]; /* DWORD 0 */ - u8 pa_hi[32]; /* DWORD 1 */ - u8 length[32]; /* DWORD 2 */ -} __packed; -struct MCC_SGE_AMAP { - u32 dw[3]; -}; -/* - * The design of an MCC_SGE allows up to 19 elements to be embedded - * in a WRB, supporting 64KB data transfers (assuming a 4KB page size). - */ -struct BE_MCC_WRB_PAYLOAD_AMAP { - union { - struct BE_MCC_SGE_AMAP sgl[19]; - u8 embedded[59][32]; /* DWORD 0 */ - }; -} __packed; -struct MCC_WRB_PAYLOAD_AMAP { - u32 dw[59]; -}; - -/* - * This is the structure of the MCC Command WRB for commands - * sent to the Management Processing Unit (MPU). See section - * for usage in embedded and non-embedded modes. - */ -struct BE_MCC_WRB_AMAP { - u8 embedded; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 sge_count[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 special[8]; /* DWORD 0 */ - u8 payload_length[32]; /* DWORD 1 */ - u8 tag[2][32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 4 */ - struct BE_MCC_WRB_PAYLOAD_AMAP payload; -} __packed; -struct MCC_WRB_AMAP { - u32 dw[64]; -}; - -/* This is the structure of the MCC Completion queue entry */ -struct BE_MCC_CQ_ENTRY_AMAP { - u8 completion_status[16]; /* DWORD 0 */ - u8 extended_status[16]; /* DWORD 0 */ - u8 mcc_tag[2][32]; /* DWORD 1 */ - u8 rsvd0[27]; /* DWORD 3 */ - u8 consumed; /* DWORD 3 */ - u8 completed; /* DWORD 3 */ - u8 hpi_buffer_completion; /* DWORD 3 */ - u8 async_event; /* DWORD 3 */ - u8 valid; /* DWORD 3 */ -} __packed; -struct MCC_CQ_ENTRY_AMAP { - u32 dw[4]; -}; - -/* Mailbox structures used by the MPU during bootstrap */ -struct BE_MCC_MAILBOX_AMAP { - struct BE_MCC_WRB_AMAP wrb; - struct BE_MCC_CQ_ENTRY_AMAP cq; -} __packed; -struct MCC_MAILBOX_AMAP { - u32 dw[68]; -}; - -#endif /* __fwcmd_mcc_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_opcodes.h b/drivers/staging/benet/fwcmd_opcodes.h deleted file mode 100644 index 23d569386b4..00000000000 --- a/drivers/staging/benet/fwcmd_opcodes.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_opcodes_amap_h__ -#define __fwcmd_opcodes_amap_h__ - -/* - * --- FWCMD_SUBSYSTEMS --- - * The commands are grouped into the following subsystems. The subsystem - * code along with the opcode uniquely identify a particular fwcmd. - */ -#define FWCMD_SUBSYSTEM_RSVD (0) /* This subsystem is reserved. It is */ - /* never used. */ -#define FWCMD_SUBSYSTEM_COMMON (1) /* CMDs in this group are common to - * all subsystems. See - * COMMON_SUBSYSTEM_OPCODES for opcodes - * and Common Host Configuration CMDs - * for the FWCMD descriptions. - */ -#define FWCMD_SUBSYSTEM_COMMON_ISCSI (2) /* CMDs in this group are */ - /* - * common to Initiator and Target. See - * COMMON_ISCSI_SUBSYSTEM_OPCODES and - * Common iSCSI Initiator and Target - * CMDs for the command descriptions. - */ -#define FWCMD_SUBSYSTEM_ETH (3) /* This subsystem is used to - execute Ethernet commands. */ - -#define FWCMD_SUBSYSTEM_TPM (4) /* This subsystem is used - to execute TPM commands. */ -#define FWCMD_SUBSYSTEM_PXE_UNDI (5) /* This subsystem is used - * to execute PXE - * and UNDI specific commands. - */ - -#define FWCMD_SUBSYSTEM_ISCSI_INI (6) /* This subsystem is used to - execute ISCSI Initiator - specific commands. - */ -#define FWCMD_SUBSYSTEM_ISCSI_TGT (7) /* This subsystem is used - to execute iSCSI Target - specific commands.between - PTL and ARM firmware. - */ -#define FWCMD_SUBSYSTEM_MILI_PTL (8) /* This subsystem is used to - execute iSCSI Target specific - commands.between MILI - and PTL. */ -#define FWCMD_SUBSYSTEM_MILI_TMD (9) /* This subsystem is used to - execute iSCSI Target specific - commands between MILI - and TMD. */ -#define FWCMD_SUBSYSTEM_PROXY (11) /* This subsystem is used - to execute proxied commands - within the host at the - explicit request of a - non priviledged domain. - This 'subsystem' is entirely - virtual from the controller - and firmware perspective as - it is implemented in host - drivers. - */ - -/* - * --- COMMON_SUBSYSTEM_OPCODES --- - * These opcodes are common to both networking and storage PCI - * functions. They are used to reserve resources and configure - * BladeEngine. These opcodes all use the FWCMD_SUBSYSTEM_COMMON - * subsystem code. - */ -#define OPCODE_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_SET (1) -#define SUBSYSTEM_COMMON_NTWK_MULTICAST_SET (1) -#define SUBSYSTEM_COMMON_NTWK_VLAN_CONFIG (1) -#define SUBSYSTEM_COMMON_NTWK_LINK_STATUS_QUERY (1) -#define SUBSYSTEM_COMMON_READ_FLASHROM (1) -#define SUBSYSTEM_COMMON_WRITE_FLASHROM (1) -#define SUBSYSTEM_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (1) -#define SUBSYSTEM_COMMON_ADD_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_REMOVE_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_RING_DESTROY (1) -#define SUBSYSTEM_COMMON_CQ_CREATE (1) -#define SUBSYSTEM_COMMON_EQ_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_RX_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_TX_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_DEFQ_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_WRBQ_CREATE (1) -#define SUBSYSTEM_COMMON_MCC_CREATE (1) -#define SUBSYSTEM_COMMON_JELL_CONFIG (1) -#define SUBSYSTEM_COMMON_FORCE_FAILOVER (1) -#define SUBSYSTEM_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_POST_ZERO_BUFFER (1) -#define SUBSYSTEM_COMMON_GET_QOS (1) -#define SUBSYSTEM_COMMON_SET_QOS (1) -#define SUBSYSTEM_COMMON_TCP_GET_STATISTICS (1) -#define SUBSYSTEM_COMMON_SEEPROM_READ (1) -#define SUBSYSTEM_COMMON_TCP_STATE_QUERY (1) -#define SUBSYSTEM_COMMON_GET_CNTL_ATTRIBUTES (1) -#define SUBSYSTEM_COMMON_NOP (1) -#define SUBSYSTEM_COMMON_NTWK_RX_FILTER (1) -#define SUBSYSTEM_COMMON_GET_FW_VERSION (1) -#define SUBSYSTEM_COMMON_SET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_GET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_SET_TCP_PARAMETERS (1) -#define SUBSYSTEM_COMMON_SET_FRAME_SIZE (1) -#define SUBSYSTEM_COMMON_GET_FAT (1) -#define SUBSYSTEM_COMMON_MODIFY_EQ_DELAY (1) -#define SUBSYSTEM_COMMON_FIRMWARE_CONFIG (1) -#define SUBSYSTEM_COMMON_ENABLE_DISABLE_DOMAINS (1) -#define SUBSYSTEM_COMMON_GET_DOMAIN_CONFIG (1) -#define SUBSYSTEM_COMMON_SET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_SET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_RED_CONFIG (1) -#define OPCODE_COMMON_NTWK_MAC_SET (2) -#define OPCODE_COMMON_NTWK_MULTICAST_SET (3) -#define OPCODE_COMMON_NTWK_VLAN_CONFIG (4) -#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY (5) -#define OPCODE_COMMON_READ_FLASHROM (6) -#define OPCODE_COMMON_WRITE_FLASHROM (7) -#define OPCODE_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (8) -#define OPCODE_COMMON_ADD_PAGE_TABLES (9) -#define OPCODE_COMMON_REMOVE_PAGE_TABLES (10) -#define OPCODE_COMMON_RING_DESTROY (11) -#define OPCODE_COMMON_CQ_CREATE (12) -#define OPCODE_COMMON_EQ_CREATE (13) -#define OPCODE_COMMON_ETH_RX_CREATE (14) -#define OPCODE_COMMON_ETH_TX_CREATE (15) -#define OPCODE_COMMON_NET_RESERVED0 (16) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED1 (17) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED2 (18) /* Reserved */ -#define OPCODE_COMMON_ISCSI_DEFQ_CREATE (19) -#define OPCODE_COMMON_ISCSI_WRBQ_CREATE (20) -#define OPCODE_COMMON_MCC_CREATE (21) -#define OPCODE_COMMON_JELL_CONFIG (22) -#define OPCODE_COMMON_FORCE_FAILOVER (23) -#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (24) -#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (25) -#define OPCODE_COMMON_POST_ZERO_BUFFER (26) -#define OPCODE_COMMON_GET_QOS (27) -#define OPCODE_COMMON_SET_QOS (28) -#define OPCODE_COMMON_TCP_GET_STATISTICS (29) -#define OPCODE_COMMON_SEEPROM_READ (30) -#define OPCODE_COMMON_TCP_STATE_QUERY (31) -#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES (32) -#define OPCODE_COMMON_NOP (33) -#define OPCODE_COMMON_NTWK_RX_FILTER (34) -#define OPCODE_COMMON_GET_FW_VERSION (35) -#define OPCODE_COMMON_SET_FLOW_CONTROL (36) -#define OPCODE_COMMON_GET_FLOW_CONTROL (37) -#define OPCODE_COMMON_SET_TCP_PARAMETERS (38) -#define OPCODE_COMMON_SET_FRAME_SIZE (39) -#define OPCODE_COMMON_GET_FAT (40) -#define OPCODE_COMMON_MODIFY_EQ_DELAY (41) -#define OPCODE_COMMON_FIRMWARE_CONFIG (42) -#define OPCODE_COMMON_ENABLE_DISABLE_DOMAINS (43) -#define OPCODE_COMMON_GET_DOMAIN_CONFIG (44) -#define OPCODE_COMMON_SET_VLD_CONFIG (45) -#define OPCODE_COMMON_GET_VLD_CONFIG (46) -#define OPCODE_COMMON_GET_PORT_EQUALIZATION (47) -#define OPCODE_COMMON_SET_PORT_EQUALIZATION (48) -#define OPCODE_COMMON_RED_CONFIG (49) - - - -/* - * --- ETH_SUBSYSTEM_OPCODES --- - * These opcodes are used for configuring the Ethernet interfaces. These - * opcodes all use the FWCMD_SUBSYSTEM_ETH subsystem code. - */ -#define OPCODE_ETH_RSS_CONFIG (1) -#define OPCODE_ETH_ACPI_CONFIG (2) -#define SUBSYSTEM_ETH_RSS_CONFIG (3) -#define SUBSYSTEM_ETH_ACPI_CONFIG (3) -#define OPCODE_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_GET_STATISTICS (3) -#define SUBSYSTEM_ETH_GET_RX_FRAG_SIZE (3) -#define SUBSYSTEM_ETH_SET_RX_FRAG_SIZE (3) -#define OPCODE_ETH_GET_STATISTICS (4) -#define OPCODE_ETH_GET_RX_FRAG_SIZE (5) -#define OPCODE_ETH_SET_RX_FRAG_SIZE (6) - - - - - -/* - * --- MCC_STATUS_CODE --- - * These are the global status codes used by all subsystems - */ -#define MCC_STATUS_SUCCESS (0) /* Indicates a successful - completion of the command */ -#define MCC_STATUS_INSUFFICIENT_PRIVILEGES (1) /* The client does not have - sufficient privileges to - execute the command */ -#define MCC_STATUS_INVALID_PARAMETER (2) /* A parameter in the command - was invalid. The extended - status contains the index - of the parameter */ -#define MCC_STATUS_INSUFFICIENT_RESOURCES (3) /* There are insufficient - chip resources to execute - the command */ -#define MCC_STATUS_QUEUE_FLUSHING (4) /* The command is completing - because the queue was - getting flushed */ -#define MCC_STATUS_DMA_FAILED (5) /* The command is completing - with a DMA error */ - -/* - * --- MGMT_ERROR_CODES --- - * Error Codes returned in the status field of the FWCMD response header - */ -#define MGMT_STATUS_SUCCESS (0) /* The FWCMD completed - without errors */ -#define MGMT_STATUS_FAILED (1) /* Error status in the Status - field of the - struct FWCMD_RESPONSE_HEADER */ -#define MGMT_STATUS_ILLEGAL_REQUEST (2) /* Invalid FWCMD opcode */ -#define MGMT_STATUS_ILLEGAL_FIELD (3) /* Invalid parameter in - the FWCMD payload */ - -#endif /* __fwcmd_opcodes_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_types_bmap.h b/drivers/staging/benet/fwcmd_types_bmap.h deleted file mode 100644 index 92217aff3a1..00000000000 --- a/drivers/staging/benet/fwcmd_types_bmap.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_types_bmap_h__ -#define __fwcmd_types_bmap_h__ - -/* MAC address format */ -struct MAC_ADDRESS_FORMAT { - u16 SizeOfStructure; - u8 MACAddress[6]; -} __packed; - -#endif /* __fwcmd_types_bmap_h__ */ diff --git a/drivers/staging/benet/host_struct.h b/drivers/staging/benet/host_struct.h deleted file mode 100644 index 3de6722b980..00000000000 --- a/drivers/staging/benet/host_struct.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __host_struct_amap_h__ -#define __host_struct_amap_h__ -#include "be_cm.h" -#include "be_common.h" -#include "descriptors.h" - -/* --- EQ_COMPLETION_MAJOR_CODE_ENUM --- */ -#define EQ_MAJOR_CODE_COMPLETION (0) /* Completion event on a */ - /* qcompletion ueue. */ -#define EQ_MAJOR_CODE_ETH (1) /* Affiliated Ethernet Event. */ -#define EQ_MAJOR_CODE_RESERVED (2) /* Reserved */ -#define EQ_MAJOR_CODE_RDMA (3) /* Affiliated RDMA Event. */ -#define EQ_MAJOR_CODE_ISCSI (4) /* Affiliated ISCSI Event */ -#define EQ_MAJOR_CODE_UNAFFILIATED (5) /* Unaffiliated Event */ - -/* --- EQ_COMPLETION_MINOR_CODE_ENUM --- */ -#define EQ_MINOR_CODE_COMPLETION (0) /* Completion event on a */ - /* completion queue. */ -#define EQ_MINOR_CODE_OTHER (1) /* Other Event (TBD). */ - -/* Queue Entry Definition for all 4 byte event queue types. */ -struct BE_EQ_ENTRY_AMAP { - u8 Valid; /* DWORD 0 */ - u8 MajorCode[3]; /* DWORD 0 */ - u8 MinorCode[12]; /* DWORD 0 */ - u8 ResourceID[16]; /* DWORD 0 */ -} __packed; -struct EQ_ENTRY_AMAP { - u32 dw[1]; -}; - -/* - * --- ETH_EVENT_CODE --- - * These codes are returned by the MPU when one of these events has occurred, - * and the event is configured to report to an Event Queue when an event - * is detected. - */ -#define ETH_EQ_LINK_STATUS (0) /* Link status change event */ - /* detected. */ -#define ETH_EQ_WATERMARK (1) /* watermark event detected. */ -#define ETH_EQ_MAGIC_PKT (2) /* magic pkt event detected. */ -#define ETH_EQ_ACPI_PKT0 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT1 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT2 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT3 (3) /* ACPI interesting packet */ - /* detected. */ - -/* - * --- ETH_TX_COMPL_STATUS_ENUM --- - * Status codes contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_VALID (0) -#define ETH_COMP_ERROR (1) -#define ETH_COMP_INVALID (15) - -/* - * --- ETH_TX_COMPL_PORT_ENUM --- - * Port indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_PORT0 (0) -#define ETH_COMP_PORT1 (1) -#define ETH_COMP_MGMT (2) - -/* - * --- ETH_TX_COMPL_CT_ENUM --- - * Completion type indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_ETH (0) - -/* - * Work request block that the driver issues to the chip for - * Ethernet transmissions. All control fields must be valid in each WRB for - * a message. The controller, as specified by the flags, optionally writes - * an entry to the Completion Ring and generate an event. - */ -struct BE_ETH_WRB_AMAP { - u8 frag_pa_hi[32]; /* DWORD 0 */ - u8 frag_pa_lo[32]; /* DWORD 1 */ - u8 complete; /* DWORD 2 */ - u8 event; /* DWORD 2 */ - u8 crc; /* DWORD 2 */ - u8 forward; /* DWORD 2 */ - u8 ipsec; /* DWORD 2 */ - u8 mgmt; /* DWORD 2 */ - u8 ipcs; /* DWORD 2 */ - u8 udpcs; /* DWORD 2 */ - u8 tcpcs; /* DWORD 2 */ - u8 lso; /* DWORD 2 */ - u8 last; /* DWORD 2 */ - u8 vlan; /* DWORD 2 */ - u8 dbg[3]; /* DWORD 2 */ - u8 hash_val[3]; /* DWORD 2 */ - u8 lso_mss[14]; /* DWORD 2 */ - u8 frag_len[16]; /* DWORD 3 */ - u8 vlan_tag[16]; /* DWORD 3 */ -} __packed; -struct ETH_WRB_AMAP { - u32 dw[4]; -}; - -/* This is an Ethernet transmit completion descriptor */ -struct BE_ETH_TX_COMPL_AMAP { - u8 user_bytes[16]; /* DWORD 0 */ - u8 nwh_bytes[8]; /* DWORD 0 */ - u8 lso; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 wrb_index[16]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 port[2]; /* DWORD 1 */ - u8 rsvd1[8]; /* DWORD 1 */ - u8 status[4]; /* DWORD 1 */ - u8 rsvd2[16]; /* DWORD 2 */ - u8 ringid[11]; /* DWORD 2 */ - u8 hash_val[4]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ -} __packed; -struct ETH_TX_COMPL_AMAP { - u32 dw[4]; -}; - -/* Ethernet Receive Buffer descriptor */ -struct BE_ETH_RX_D_AMAP { - u8 fragpa_hi[32]; /* DWORD 0 */ - u8 fragpa_lo[32]; /* DWORD 1 */ -} __packed; -struct ETH_RX_D_AMAP { - u32 dw[2]; -}; - -/* This is an Ethernet Receive Completion Descriptor */ -struct BE_ETH_RX_COMPL_AMAP { - u8 vlan_tag[16]; /* DWORD 0 */ - u8 pktsize[14]; /* DWORD 0 */ - u8 port; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 err; /* DWORD 1 */ - u8 rsshp; /* DWORD 1 */ - u8 ipf; /* DWORD 1 */ - u8 tcpf; /* DWORD 1 */ - u8 udpf; /* DWORD 1 */ - u8 ipcksm; /* DWORD 1 */ - u8 tcpcksm; /* DWORD 1 */ - u8 udpcksm; /* DWORD 1 */ - u8 macdst[6]; /* DWORD 1 */ - u8 vtp; /* DWORD 1 */ - u8 vtm; /* DWORD 1 */ - u8 fragndx[10]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 ipsec; /* DWORD 1 */ - u8 numfrags[3]; /* DWORD 1 */ - u8 rsvd1[31]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsshash[32]; /* DWORD 3 */ -} __packed; -struct ETH_RX_COMPL_AMAP { - u32 dw[4]; -}; - -#endif /* __host_struct_amap_h__ */ diff --git a/drivers/staging/benet/hwlib.h b/drivers/staging/benet/hwlib.h deleted file mode 100644 index afedf4dc590..00000000000 --- a/drivers/staging/benet/hwlib.h +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef __hwlib_h__ -#define __hwlib_h__ - -#include <linux/module.h> -#include <linux/io.h> -#include <linux/list.h> -#include <linux/spinlock.h> - -#include "regmap.h" /* srcgen array map output */ - -#include "asyncmesg.h" -#include "fwcmd_opcodes.h" -#include "post_codes.h" -#include "fwcmd_mcc.h" - -#include "fwcmd_types_bmap.h" -#include "fwcmd_common_bmap.h" -#include "fwcmd_eth_bmap.h" -#include "bestatus.h" -/* - * - * Macros for reading/writing a protection domain or CSR registers - * in BladeEngine. - */ -#define PD_READ(fo, field) ioread32((fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define PD_WRITE(fo, field, val) iowrite32(val, (fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define CSR_READ(fo, field) ioread32((fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define CSR_WRITE(fo, field, val) iowrite32(val, (fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define PCICFG0_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG0_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG1_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#define PCICFG1_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#ifdef BE_DEBUG -#define ASSERT(c) BUG_ON(!(c)); -#else -#define ASSERT(c) -#endif - -/* debug levels */ -enum BE_DEBUG_LEVELS { - DL_ALWAYS = 0, /* cannot be masked */ - DL_ERR = 0x1, /* errors that should never happen */ - DL_WARN = 0x2, /* something questionable. - recoverable errors */ - DL_NOTE = 0x4, /* infrequent, important debug info */ - DL_INFO = 0x8, /* debug information */ - DL_VERBOSE = 0x10, /* detailed info, such as buffer traces */ - BE_DL_MIN_VALUE = 0x1, /* this is the min value used */ - BE_DL_MAX_VALUE = 0x80 /* this is the higheset value used */ -} ; - -extern unsigned int trace_level; - -#define TRACE(lm, fmt, args...) { \ - if (trace_level & lm) { \ - printk(KERN_NOTICE "BE: %s:%d \n" fmt, \ - __FILE__ , __LINE__ , ## args); \ - } \ - } - -static inline unsigned int be_trace_set_level(unsigned int level) -{ - unsigned int old_level = trace_level; - trace_level = level; - return old_level; -} - -#define be_trace_get_level() trace_level -/* - * Returns number of pages spanned by the size of data - * starting at the given address. - */ -#define PAGES_SPANNED(_address, _size) \ - ((u32)((((size_t)(_address) & (PAGE_SIZE - 1)) + \ - (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) -/* Byte offset into the page corresponding to given address */ -#define OFFSET_IN_PAGE(_addr_) ((size_t)(_addr_) & (PAGE_SIZE-1)) - -/* - * circular subtract. - * Returns a - b assuming a circular number system, where a and b are - * in range (0, maxValue-1). If a==b, zero is returned so the - * highest value possible with this subtraction is maxValue-1. - */ -static inline u32 be_subc(u32 a, u32 b, u32 max) -{ - ASSERT(a <= max && b <= max); - ASSERT(max > 0); - return a >= b ? (a - b) : (max - b + a); -} - -static inline u32 be_addc(u32 a, u32 b, u32 max) -{ - ASSERT(a < max); - ASSERT(max > 0); - return (max - a > b) ? (a + b) : (b + a - max); -} - -/* descriptor for a physically contiguous memory used for ring */ -struct ring_desc { - u32 length; /* length in bytes */ - void *va; /* virtual address */ - u64 pa; /* bus address */ -} ; - -/* - * This structure stores information about a ring shared between hardware - * and software. Each ring is allocated by the driver in the uncached - * extension and mapped into BladeEngine's unified table. - */ -struct mp_ring { - u32 pages; /* queue size in pages */ - u32 id; /* queue id assigned by beklib */ - u32 num; /* number of elements in queue */ - u32 cidx; /* consumer index */ - u32 pidx; /* producer index -- not used by most rings */ - u32 itemSize; /* size in bytes of one object */ - - void *va; /* The virtual address of the ring. - This should be last to allow 32 & 64 - bit debugger extensions to work. */ -} ; - -/*----------- amap bit filed get / set macros and functions -----*/ -/* - * Structures defined in the map header files (under fw/amap/) with names - * in the format BE_<name>_AMAP are pseudo structures with members - * of type u8. These structures are templates that are used in - * conjuntion with the structures with names in the format - * <name>_AMAP to calculate the bit masks and bit offsets to get or set - * bit fields in structures. The structures <name>_AMAP are arrays - * of 32 bits words and have the correct size. The following macros - * provide convenient ways to get and set the various members - * in the structures without using strucctures with bit fields. - * Always use the macros AMAP_GET_BITS_PTR and AMAP_SET_BITS_PTR - * macros to extract and set various members. - */ - -/* - * Returns the a bit mask for the register that is NOT shifted into location. - * That means return values always look like: 0x1, 0xFF, 0x7FF, etc... - */ -static inline u32 amap_mask(u32 bit_size) -{ - return bit_size == 32 ? 0xFFFFFFFF : (1 << bit_size) - 1; -} - -#define AMAP_BIT_MASK(_struct_, field) \ - amap_mask(AMAP_BIT_SIZE(_struct_, field)) - -/* - * non-optimized set bits function. First clears the bits and then assigns them. - * This does not require knowledge of the particular DWORD you are setting. - * e.g. AMAP_SET_BITS_PTR (struct, field1, &contextMemory, 123); - */ -static inline void -amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) -{ - u32 *dw = (u32 *)ptr; - *(dw + dw_offset) &= ~(mask << offset); - *(dw + dw_offset) |= (mask & value) << offset; -} - -#define AMAP_SET_BITS_PTR(_struct_, field, _structPtr_, val) \ - amap_set(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),\ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field), val) -/* - * Non-optimized routine that gets the bits without knowing the correct DWORD. - * e.g. fieldValue = AMAP_GET_BITS_PTR (struct, field1, &contextMemory); - */ -static inline u32 -amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) -{ - u32 *dw = (u32 *)ptr; - return mask & (*(dw + dw_offset) >> offset); -} -#define AMAP_GET_BITS_PTR(_struct_, field, _structPtr_) \ - amap_get(_structPtr_, AMAP_WORD_OFFSET(_struct_, field), \ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field)) - -/* Returns 0-31 representing bit offset within a DWORD of a bitfield. */ -#define AMAP_BIT_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field) % 32) - -/* Returns 0-n representing DWORD offset of bitfield within the structure. */ -#define AMAP_WORD_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field)/32) - -/* Returns size of bitfield in bits. */ -#define AMAP_BIT_SIZE(_struct_, field) \ - sizeof(((struct BE_ ## _struct_ ## _AMAP*)0)->field) - -struct be_mcc_wrb_response_copy { - u16 length; /* bytes in response */ - u16 fwcmd_offset; /* offset within the wrb of the response */ - void *va; /* user's va to copy response into */ - -} ; -typedef void (*mcc_wrb_cqe_callback) (void *context, int status, - struct MCC_WRB_AMAP *optional_wrb); -struct be_mcc_wrb_context { - - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - int *users_final_status; /* pointer to a local - variable for synchronous - commands */ - struct MCC_WRB_AMAP *wrb; /* pointer to original wrb for embedded - commands only */ - struct list_head next; /* links context structs together in - free list */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - -#if defined(BE_DEBUG) - u16 subsystem, opcode; /* Track this FWCMD for debug builds. */ - struct MCC_WRB_AMAP *ring_wrb; - u32 consumed_count; -#endif -} ; - -/* - Represents a function object for network or storage. This - is used to manage per-function resources like MCC CQs, etc. -*/ -struct be_function_object { - - u32 magic; /*!< magic for detecting memory corruption. */ - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI config space */ - u32 emulate; /* if set, MPU is not available. - Emulate everything. */ - u32 pend_queue_driving; /* if set, drive the queued WRBs - after releasing the WRB lock */ - - spinlock_t post_lock; /* lock for verifying one thread posting wrbs */ - spinlock_t cq_lock; /* lock for verifying one thread - processing cq */ - spinlock_t mcc_context_lock; /* lock for protecting mcc - context free list */ - unsigned long post_irq; - unsigned long cq_irq; - - u32 type; - u32 pci_function_number; - - struct be_mcc_object *mcc; /* mcc rings. */ - - struct { - struct MCC_MAILBOX_AMAP *va; /* VA to the mailbox */ - u64 pa; /* PA to the mailbox */ - u32 length; /* byte length of mailbox */ - - /* One default context struct used for posting at - * least one MCC_WRB - */ - struct be_mcc_wrb_context default_context; - bool default_context_allocated; - } mailbox; - - struct { - - /* Wake on lans configured. */ - u32 wol_bitmask; /* bits 0,1,2,3 are set if - corresponding index is enabled */ - } config; - - - struct BE_FIRMWARE_CONFIG fw_config; -} ; - -/* - Represents an Event Queue -*/ -struct be_eq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - - struct list_head eq_list; - struct list_head cq_list_head; - - u32 eq_id; - void *cb_context; - -} ; - -/* - Manages a completion queue -*/ -struct be_cq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - struct be_eq_object *eq_object; - - struct list_head cq_list; - struct list_head cqlist_for_eq; - - void *va; - u32 num_entries; - - void *cb_context; - - u32 cq_id; - -} ; - -/* - Manages an ethernet send queue -*/ -struct be_ethsq_object { - u32 magic; - - struct list_head list; - - struct be_function_object *parent_function; - struct be_cq_object *cq_object; - u32 bid; - -} ; - -/* -@brief - Manages an ethernet receive queue -*/ -struct be_ethrq_object { - u32 magic; - struct list_head list; - struct be_function_object *parent_function; - u32 rid; - struct be_cq_object *cq_object; - struct be_cq_object *rss_cq_object[4]; - -} ; - -/* - Manages an MCC -*/ -typedef void (*mcc_async_event_callback) (void *context, u32 event_code, - void *event); -struct be_mcc_object { - u32 magic; - - struct be_function_object *parent_function; - struct list_head mcc_list; - - struct be_cq_object *cq_object; - - /* Async event callback for MCC CQ. */ - mcc_async_event_callback async_cb; - void *async_context; - - struct { - struct be_mcc_wrb_context *base; - u32 num; - struct list_head list_head; - } wrb_context; - - struct { - struct ring_desc *rd; - struct mp_ring ring; - } sq; - - struct { - struct mp_ring ring; - } cq; - - u32 processing; /* flag indicating that one thread - is processing CQ */ - u32 rearm; /* doorbell rearm setting to make - sure the active processing thread */ - /* rearms the CQ if any of the threads requested it. */ - - struct list_head backlog; - u32 backlog_length; - u32 driving_backlog; - u32 consumed_index; - -} ; - - -/* Queue context header -- the required software information for - * queueing a WRB. - */ -struct be_queue_driver_context { - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - void *optional_fwcmd_va; - struct list_head list; - u32 bytes; -} ; - -/* - * Common MCC WRB header that all commands require. - */ -struct be_mcc_wrb_header { - u8 rsvd[offsetof(struct BE_MCC_WRB_AMAP, payload)/8]; -} ; - -/* - * All non embedded commands supported by hwlib functions only allow - * 1 SGE. This queue context handles them all. - */ -struct be_nonembedded_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_SGE_AMAP sge[1]; -} ; - -/* - * ------------------------------------------------------------------------ - * This section contains the specific queue struct for each command. - * The user could always provide a be_generic_q_ctxt but this is a - * rather large struct. By using the specific struct, memory consumption - * can be reduced. - * ------------------------------------------------------------------------ - */ - -struct be_link_status_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY fwcmd; -} ; - -struct be_multicast_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_MULTICAST_SET fwcmd; -} ; - - -struct be_vlan_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG fwcmd; -} ; - -struct be_promiscuous_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_ETH_PROMISCUOUS fwcmd; -} ; - -struct be_force_failover_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_FORCE_FAILOVER fwcmd; -} ; - - -struct be_rxf_filter_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_RX_FILTER fwcmd; -} ; - -struct be_eq_modify_delay_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_MODIFY_EQ_DELAY fwcmd; -} ; - -/* - * The generic context is the largest size that would be required. - * It is the software context plus an entire WRB. - */ -struct be_generic_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_WRB_PAYLOAD_AMAP payload; -} ; - -/* - * Types for the BE_QUEUE_CONTEXT object. - */ -#define BE_QUEUE_INVALID (0) -#define BE_QUEUE_LINK_STATUS (0xA006) -#define BE_QUEUE_ETH_STATS (0xA007) -#define BE_QUEUE_TPM_STATS (0xA008) -#define BE_QUEUE_TCP_STATS (0xA009) -#define BE_QUEUE_MULTICAST (0xA00A) -#define BE_QUEUE_VLAN (0xA00B) -#define BE_QUEUE_RSS (0xA00C) -#define BE_QUEUE_FORCE_FAILOVER (0xA00D) -#define BE_QUEUE_PROMISCUOUS (0xA00E) -#define BE_QUEUE_WAKE_ON_LAN (0xA00F) -#define BE_QUEUE_NOP (0xA010) - -/* --- BE_FUNCTION_ENUM --- */ -#define BE_FUNCTION_TYPE_ISCSI (0) -#define BE_FUNCTION_TYPE_NETWORK (1) -#define BE_FUNCTION_TYPE_ARM (2) - -/* --- BE_ETH_TX_RING_TYPE_ENUM --- */ -#define BE_ETH_TX_RING_TYPE_FORWARDING (1) /* Ether ring for forwarding */ -#define BE_ETH_TX_RING_TYPE_STANDARD (2) /* Ether ring for sending */ - /* network packets. */ -#define BE_ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring for sending */ - /* network packets, bound */ - /* to a physical port. */ -/* - * ---------------------------------------------------------------------- - * API MACROS - * ---------------------------------------------------------------------- - */ -#define BE_FWCMD_NAME(_short_name_) struct FWCMD_##_short_name_ -#define BE_OPCODE_NAME(_short_name_) OPCODE_##_short_name_ -#define BE_SUBSYSTEM_NAME(_short_name_) SUBSYSTEM_##_short_name_ - - -#define BE_PREPARE_EMBEDDED_FWCMD(_pfob_, _wrb_, _short_name_) \ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_embedded_fwcmd(_pfob_, _wrb_, \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -#define BE_PREPARE_NONEMBEDDED_FWCMD(_pfob_, _wrb_, _iva_, _ipa_, _short_name_)\ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_nonembedded_fwcmd(_pfob_, _wrb_, (_iva_), (_ipa_), \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -int be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, struct ring_desc *mailbox_rd, - struct be_function_object *pfob); - -int be_function_object_destroy(struct be_function_object *pfob); -int be_function_cleanup(struct be_function_object *pfob); - - -int be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fw_version, - mcc_wrb_cqe_callback cb, void *cb_context); - - -int be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_eq_modify_delay_q_ctxt *q_ctxt); - - - -int be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, u32 timer_delay, struct be_eq_object *eq_object); - -int be_eq_destroy(struct be_eq_object *eq); - -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - bool solicited_eventable, bool no_delay, - u32 wm_thresh, struct be_eq_object *eq_object, - struct be_cq_object *cq_object); - -int be_cq_destroy(struct be_cq_object *cq); - -int be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc); -int be_mcc_ring_destroy(struct be_mcc_object *mcc_object); - -int be_mcc_process_cq(struct be_mcc_object *mcc_object, bool rearm); - -int be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context); - -int be_pci_soft_reset(struct be_function_object *pfob); - - -int be_drive_POST(struct be_function_object *pfob); - - -int be_eth_sq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_ethsq_object *eth_sq); - -struct be_eth_sq_parameters { - u32 port; - u32 rsvd0[2]; -} ; - -int be_eth_sq_create_ex(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq); -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq); - -int be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable); - -int be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable); -int be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps); - -int be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps); - -int be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size); - -int be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context); -int be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 new_frag_size_bytes, u32 *actual_frag_size_bytes); -int be_eth_rq_get_frag_size(struct be_function_object *pfob, - u32 *frag_size_bytes); - -void *be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - u32 payload_length, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem); -void *be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *fwcmd_header_va, u64 fwcmd_header_pa, - u32 payload_length, u32 request_length, u32 response_length, - u32 opcode, u32 subsystem); - - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob); - -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, bool mac1, bool mgmt, - bool write, bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, - void *cb_context); - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt); - -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_vlan_q_ctxt *q_ctxt); - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt); - - -int be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt); - -int be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt); - - -int be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * internal functions used by hwlib - * ------------------------------------------------------ - */ - - -int be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_callback_context); - -int be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *response_copy); - -int be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * MCC QUEUE - * ------------------------------------------------------ - */ - -int be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *rd); - - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue); - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob); - -void _be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context); - -int _be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -int _be_mpu_post_wrb_ring(struct be_mcc_object *mcc, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc); - - -/* - * ------------------------------------------------------ - * Ring Sizes - * ------------------------------------------------------ - */ -static inline u32 be_ring_encoding_to_length(u32 encoding, u32 object_size) -{ - - ASSERT(encoding != 1); /* 1 is rsvd */ - ASSERT(encoding < 16); - ASSERT(object_size > 0); - - if (encoding == 0) /* 32k deep */ - encoding = 16; - - return (1 << (encoding - 1)) * object_size; -} - -static inline -u32 be_ring_length_to_encoding(u32 length_in_bytes, u32 object_size) -{ - - u32 count, encoding; - - ASSERT(object_size > 0); - ASSERT(length_in_bytes % object_size == 0); - - count = length_in_bytes / object_size; - - ASSERT(count > 1); - ASSERT(count <= 32 * 1024); - ASSERT(length_in_bytes <= 8 * PAGE_SIZE); /* max ring size in UT */ - - encoding = __ilog2_u32(count) + 1; - - if (encoding == 16) - encoding = 0; /* 32k deep */ - - return encoding; -} - -void be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, - u32 max_num); -#endif /* __hwlib_h__ */ diff --git a/drivers/staging/benet/mpu.c b/drivers/staging/benet/mpu.c deleted file mode 100644 index 269cc11d305..00000000000 --- a/drivers/staging/benet/mpu.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include <linux/delay.h> -#include "hwlib.h" -#include "bestatus.h" - -static -inline void mp_ring_create(struct mp_ring *ring, u32 num, u32 size, void *va) -{ - ASSERT(ring); - memset(ring, 0, sizeof(struct mp_ring)); - ring->num = num; - ring->pages = DIV_ROUND_UP(num * size, PAGE_SIZE); - ring->itemSize = size; - ring->va = va; -} - -/* - * ----------------------------------------------------------------------- - * Interface for 2 index rings. i.e. consumer/producer rings - * -------------------------------------------------------------------------- - */ - -/* Returns number items pending on ring. */ -static inline u32 mp_ring_num_pending(struct mp_ring *ring) -{ - ASSERT(ring); - if (ring->num == 0) - return 0; - return be_subc(ring->pidx, ring->cidx, ring->num); -} - -/* Returns number items free on ring. */ -static inline u32 mp_ring_num_empty(struct mp_ring *ring) -{ - ASSERT(ring); - return ring->num - 1 - mp_ring_num_pending(ring); -} - -/* Consume 1 item */ -static inline void mp_ring_consume(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx != ring->cidx); - - ring->cidx = be_addc(ring->cidx, 1, ring->num); -} - -/* Produce 1 item */ -static inline void mp_ring_produce(struct mp_ring *ring) -{ - ASSERT(ring); - ring->pidx = be_addc(ring->pidx, 1, ring->num); -} - -/* Consume count items */ -static inline void mp_ring_consume_multiple(struct mp_ring *ring, u32 count) -{ - ASSERT(ring); - ASSERT(mp_ring_num_pending(ring) >= count); - ring->cidx = be_addc(ring->cidx, count, ring->num); -} - -static inline void *mp_ring_item(struct mp_ring *ring, u32 index) -{ - ASSERT(ring); - ASSERT(index < ring->num); - ASSERT(ring->itemSize > 0); - return (u8 *) ring->va + index * ring->itemSize; -} - -/* Ptr to produce item */ -static inline void *mp_ring_producer_ptr(struct mp_ring *ring) -{ - ASSERT(ring); - return mp_ring_item(ring, ring->pidx); -} - -/* - * Returns a pointer to the current location in the ring. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_current(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx == 0); /* not used */ - - return mp_ring_item(ring, ring->cidx); -} - -/* - * Increment index for rings with only 1 index. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_next(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->num > 0); - ASSERT(ring->pidx == 0); /* not used */ - - ring->cidx = be_addc(ring->cidx, 1, ring->num); - return mp_ring_current(ring); -} - -/* - This routine waits for a previously posted mailbox WRB to be completed. - Specifically it waits for the mailbox to say that it's ready to accept - more data by setting the LSB of the mailbox pd register to 1. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void be_mcc_mailbox_wait(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 i = 0; - u32 ready; - - if (pfob->emulate) { - /* No waiting for mailbox in emulated mode. */ - return; - } - - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - - while (ready == false) { - if ((++i & 0x3FFFF) == 0) { - TRACE(DL_WARN, "Waiting for mailbox ready - %dk polls", - i / 1000); - } - udelay(1); - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - } -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine returns immediately - and does not wait for the WRB to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL - -*/ -static void be_mcc_mailbox_notify(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 pa; - - ASSERT(pfob->mailbox.pa); - ASSERT(pfob->mailbox.va); - - /* If emulated, do not ring the mailbox */ - if (pfob->emulate) { - TRACE(DL_WARN, "MPU disabled. Skipping mailbox notify."); - return; - } - - /* form the higher bits in the address */ - mailbox_db.dw[0] = 0; /* init */ - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 1); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - - /* bits 34 to 63 */ - pa = (u32) (pfob->mailbox.pa >> 34); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Wait for the MPU to be ready */ - be_mcc_mailbox_wait(pfob); - - /* Ring doorbell 1st time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); - - /* Wait for 1st write to be acknowledged. */ - be_mcc_mailbox_wait(pfob); - - /* lower bits 30 bits from 4th bit (bits 4 to 33)*/ - pa = (u32) (pfob->mailbox.pa >> 4) & 0x3FFFFFFF; - - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Ring doorbell 2nd time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine spins until the - MPU writes a 1 into the LSB indicating that the data has been received - and is ready to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void -be_mcc_mailbox_notify_and_wait(struct be_function_object *pfob) -{ - /* - * Notify it - */ - be_mcc_mailbox_notify(pfob); - /* - * Now wait for completion of WRB - */ - be_mcc_mailbox_wait(pfob); -} - -void -be_mcc_process_cqe(struct be_function_object *pfob, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 offset, status; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - ASSERT(wrb_context); - - /* - * Perform a response copy if requested. - * Only copy data if the FWCMD is successful. - */ - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, cqe); - if (status == MGMT_STATUS_SUCCESS && wrb_context->copy.length > 0) { - ASSERT(wrb_context->wrb); - ASSERT(wrb_context->copy.va); - p = (u8 *)wrb_context->wrb + - offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - memcpy(wrb_context->copy.va, - (u8 *)p + wrb_context->copy.fwcmd_offset, - wrb_context->copy.length); - } - - if (status) - status = BE_NOT_OK; - /* internal callback */ - if (wrb_context->internal_cb) { - wrb_context->internal_cb(wrb_context->internal_cb_context, - status, wrb_context->wrb); - } - - /* callback */ - if (wrb_context->cb) { - wrb_context->cb(wrb_context->cb_context, - status, wrb_context->wrb); - } - /* Free the context structure */ - _be_mcc_free_wrb_context(pfob, wrb_context); -} - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc) -{ - struct be_function_object *pfob = NULL; - int status = BE_PENDING; - struct be_generic_q_ctxt *q_ctxt; - struct MCC_WRB_AMAP *wrb; - struct MCC_WRB_AMAP *queue_wrb; - u32 length, payload_length, sge_count, embedded; - unsigned long irql; - - BUILD_BUG_ON((sizeof(struct be_generic_q_ctxt) < - sizeof(struct be_queue_driver_context) + - sizeof(struct MCC_WRB_AMAP))); - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - if (mcc->driving_backlog) { - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return; - } - /* Acquire the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 1; - - while (!list_empty(&mcc->backlog)) { - wrb = _be_mpu_peek_ring_wrb(mcc, true); /* Driving the queue */ - if (!wrb) - break; /* No space in the ring yet. */ - /* Get the next queued entry to process. */ - q_ctxt = list_first_entry(&mcc->backlog, - struct be_generic_q_ctxt, context.list); - list_del(&q_ctxt->context.list); - pfob->mcc->backlog_length--; - /* - * Compute the required length of the WRB. - * Since the queue element may be smaller than - * the complete WRB, copy only the required number of bytes. - */ - queue_wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, queue_wrb); - if (embedded) { - payload_length = AMAP_GET_BITS_PTR(MCC_WRB, - payload_length, queue_wrb); - length = sizeof(struct be_mcc_wrb_header) + - payload_length; - } else { - sge_count = AMAP_GET_BITS_PTR(MCC_WRB, sge_count, - queue_wrb); - ASSERT(sge_count == 1); /* only 1 frag. */ - length = sizeof(struct be_mcc_wrb_header) + - sge_count * sizeof(struct MCC_SGE_AMAP); - } - - /* - * Truncate the length based on the size of the - * queue element. Some elements that have output parameters - * can be smaller than the payload_length field would - * indicate. We really only need to copy the request - * parameters, not the response. - */ - length = min(length, (u32) (q_ctxt->context.bytes - - offsetof(struct be_generic_q_ctxt, wrb_header))); - - /* Copy the queue element WRB into the ring. */ - memcpy(wrb, &q_ctxt->wrb_header, length); - - /* Post the wrb. This should not fail assuming we have - * enough context structs. */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - q_ctxt->context.cb, q_ctxt->context.cb_context, - q_ctxt->context.internal_cb, - q_ctxt->context.internal_cb_context, - q_ctxt->context.optional_fwcmd_va, - &q_ctxt->context.copy); - - if (status == BE_SUCCESS) { - /* - * Synchronous completion. Since it was queued, - * we will invoke the callback. - * To the user, this is an asynchronous request. - */ - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - - ASSERT(q_ctxt->context.cb); - - q_ctxt->context.cb( - q_ctxt->context.cb_context, - BE_SUCCESS, NULL); - - spin_lock_irqsave(&pfob->post_lock, irql); - - } else if (status != BE_PENDING) { - /* - * Another resource failed. Should never happen - * if we have sufficient MCC_WRB_CONTEXT structs. - * Return to head of the queue. - */ - TRACE(DL_WARN, "Failed to post a queued WRB. 0x%x", - status); - list_add(&q_ctxt->context.list, &mcc->backlog); - pfob->mcc->backlog_length++; - break; - } - } - - /* Free the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 0; - spin_unlock_irqrestore(&pfob->post_lock, irql); -} - -/* This function asserts that the WRB was consumed in order. */ -#ifdef BE_DEBUG -u32 be_mcc_wrb_consumed_in_order(struct be_mcc_object *mcc, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 wrb_index; - u32 wrb_consumed_in_order; - u32 offset; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - - ASSERT(wrb_context); - - wrb_index = (u32) (((u64)(size_t)wrb_context->ring_wrb - - (u64)(size_t)mcc->sq.ring.va) / sizeof(struct MCC_WRB_AMAP)); - - ASSERT(wrb_index < mcc->sq.ring.num); - - wrb_consumed_in_order = (u32) (wrb_index == mcc->consumed_index); - mcc->consumed_index = be_addc(mcc->consumed_index, 1, mcc->sq.ring.num); - return wrb_consumed_in_order; -} -#endif - -int be_mcc_process_cq(struct be_mcc_object *mcc, bool rearm) -{ - struct be_function_object *pfob = NULL; - struct MCC_CQ_ENTRY_AMAP *cqe; - struct CQ_DB_AMAP db; - struct mp_ring *cq_ring = &mcc->cq.ring; - struct mp_ring *mp_ring = &mcc->sq.ring; - u32 num_processed = 0; - u32 consumed = 0, valid, completed, cqe_consumed, async_event; - - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Verify that only one thread is processing the CQ at once. - * We cannot hold the lock while processing the CQ due to - * the callbacks into the OS. Therefore, this flag is used - * to control it. If any of the threads want to - * rearm the CQ, we need to honor that. - */ - if (mcc->processing != 0) { - mcc->rearm = mcc->rearm || rearm; - goto Error; - } else { - mcc->processing = 1; /* lock processing for this thread. */ - mcc->rearm = rearm; /* set our rearm setting */ - } - - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - - cqe = mp_ring_current(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - while (valid) { - - if (num_processed >= 8) { - /* coalesce doorbells, but free space in cq - * ring while processing. */ - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, - num_processed); - num_processed = 0; - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - - async_event = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, async_event, cqe); - if (async_event) { - /* This is an asynchronous event. */ - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer = - (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) cqe + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - u32 event_code; - async_event = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - async_event, async_trailer); - ASSERT(async_event == 1); - - - valid = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - valid, async_trailer); - ASSERT(valid == 1); - - /* Call the async event handler if it is installed. */ - if (mcc->async_cb) { - event_code = - AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - event_code, async_trailer); - mcc->async_cb(mcc->async_context, - (u32) event_code, (void *) cqe); - } - - } else { - /* This is a completion entry. */ - - /* No vm forwarding in this driver. */ - - cqe_consumed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - consumed, cqe); - if (cqe_consumed) { - /* - * A command on the MCC ring was consumed. - * Update the consumer index. - * These occur in order. - */ - ASSERT(be_mcc_wrb_consumed_in_order(mcc, cqe)); - consumed++; - } - - completed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - completed, cqe); - if (completed) { - /* A command completed. Use tag to - * determine which command. */ - be_mcc_process_cqe(pfob, cqe); - } - } - - /* Reset the CQE */ - AMAP_SET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe, false); - num_processed++; - - /* Update our tracking for the CQ ring. */ - cqe = mp_ring_next(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - } - - TRACE(DL_INFO, "num_processed:0x%x, and consumed:0x%x", - num_processed, consumed); - /* - * Grab the CQ lock to synchronize the "rearm" setting for - * the doorbell, and for clearing the "processing" flag. - */ - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Rearm the cq. This is done based on the global mcc->rearm - * flag which combines the rearm parameter from the current - * call to process_cq and any other threads - * that tried to process the CQ while this one was active. - * This handles the situation where a sync. fwcmd was processing - * the CQ while the interrupt/dpc tries to process it. - * The sync process gets to continue -- but it is now - * responsible for the rearming. - */ - if (num_processed > 0 || mcc->rearm == true) { - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, mcc->rearm); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, num_processed); - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - /* - * Update the consumer index after ringing the CQ doorbell. - * We don't want another thread to post more WRBs before we - * have CQ space available. - */ - mp_ring_consume_multiple(mp_ring, consumed); - - /* Clear the processing flag. */ - mcc->processing = 0; - -Error: - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - /* - * Use the local variable to detect if the current thread - * holds the WRB post lock. If rearm is false, this is - * either a synchronous command, or the upper layer driver is polling - * from a thread. We do not drive the queue from that - * context since the driver may hold the - * wrb post lock already. - */ - if (rearm) - be_drive_mcc_wrb_queue(mcc); - else - pfob->pend_queue_driving = 1; - - return BE_SUCCESS; -} - -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates an MCC object. This object contains an MCC send queue - and a CQ private to the MCC. - - pcontroller - Handle to a function object - - EqObject - EQ object that will be used to dispatch this MCC - - ppMccObject - Pointer to an internal Mcc Object returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL - -*/ -int -be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc) -{ - int status = 0; - - struct FWCMD_COMMON_MCC_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 num_entries_encoded, n, i; - void *va = NULL; - unsigned long irql; - - if (length < sizeof(struct MCC_WRB_AMAP) * 2) { - TRACE(DL_ERR, "Invalid MCC ring length:%d", length); - return BE_NOT_OK; - } - /* - * Reduce the actual ring size to be less than the number - * of context entries. This ensures that we run out of - * ring WRBs first so the queuing works correctly. We never - * queue based on context structs. - */ - if (num_context_entries + 1 < - length / sizeof(struct MCC_WRB_AMAP) - 1) { - - u32 max_length = - (num_context_entries + 2) * sizeof(struct MCC_WRB_AMAP); - - if (is_power_of_2(max_length)) - length = __roundup_pow_of_two(max_length+1) / 2; - else - length = __roundup_pow_of_two(max_length) / 2; - - ASSERT(length <= max_length); - - TRACE(DL_WARN, - "MCC ring length reduced based on context entries." - " length:%d wrbs:%d context_entries:%d", length, - (int) (length / sizeof(struct MCC_WRB_AMAP)), - num_context_entries); - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - num_entries_encoded = - be_ring_length_to_encoding(length, sizeof(struct MCC_WRB_AMAP)); - - /* Init MCC object. */ - memset(mcc, 0, sizeof(*mcc)); - mcc->parent_function = pfob; - mcc->cq_object = cq; - - INIT_LIST_HEAD(&mcc->backlog); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MCC_CREATE); - - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - /* - * Program MCC ring context - */ - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, pdid, - &fwcmd->params.request.context, 0); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, invalid, - &fwcmd->params.request.context, false); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, ring_size, - &fwcmd->params.request.context, num_entries_encoded); - - n = cq->cq_id; - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, - cq_id, &fwcmd->params.request.context, n); - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto error; - } - /* - * Create a linked list of context structures - */ - mcc->wrb_context.base = context_array; - mcc->wrb_context.num = num_context_entries; - INIT_LIST_HEAD(&mcc->wrb_context.list_head); - memset(context_array, 0, - sizeof(struct be_mcc_wrb_context) * num_context_entries); - for (i = 0; i < mcc->wrb_context.num; i++) { - list_add_tail(&context_array[i].next, - &mcc->wrb_context.list_head); - } - - /* - * - * Create an mcc_ring for tracking WRB hw ring - */ - va = rd->va; - ASSERT(va); - mp_ring_create(&mcc->sq.ring, length / sizeof(struct MCC_WRB_AMAP), - sizeof(struct MCC_WRB_AMAP), va); - mcc->sq.ring.id = fwcmd->params.response.id; - /* - * Init a mcc_ring for tracking the MCC CQ. - */ - ASSERT(cq->va); - mp_ring_create(&mcc->cq.ring, cq->num_entries, - sizeof(struct MCC_CQ_ENTRY_AMAP), cq->va); - mcc->cq.ring.id = cq->cq_id; - - /* Force zeroing of CQ. */ - memset(cq->va, 0, cq->num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP)); - - /* Initialize debug index. */ - mcc->consumed_index = 0; - - atomic_inc(&cq->ref_count); - pfob->mcc = mcc; - - TRACE(DL_INFO, "MCC ring created. id:%d bytes:%d cq_id:%d cq_entries:%d" - " num_context:%d", mcc->sq.ring.id, length, - cq->cq_id, cq->num_entries, num_context_entries); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an MCC send queue - - MccObject - Internal Mcc Object to be destroyed. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL - - The caller of this routine must ensure that no other WRB may be posted - until this routine returns. - -*/ -int be_mcc_ring_destroy(struct be_mcc_object *mcc) -{ - int status = 0; - struct be_function_object *pfob = mcc->parent_function; - - - ASSERT(mcc->processing == 0); - - /* - * Remove the ring from the function object. - * This transitions back to mailbox mode. - */ - pfob->mcc = NULL; - - /* Send fwcmd to destroy the queue. (Using the mailbox.) */ - status = be_function_ring_destroy(mcc->parent_function, mcc->sq.ring.id, - FWCMD_RING_TYPE_MCC, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Release the SQ reference to the CQ */ - atomic_dec(&mcc->cq_object->ref_count); - - return status; -} - -static void -mcc_wrb_sync_cb(void *context, int staus, struct MCC_WRB_AMAP *wrb) -{ - struct be_mcc_wrb_context *wrb_context = - (struct be_mcc_wrb_context *) context; - ASSERT(wrb_context); - *wrb_context->users_final_status = staus; -} - -/* - This routine posts a command to the MCC send queue - - mcc - Internal Mcc Object to be destroyed. - - wrb - wrb to post. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL if CompletionCallback is not NULL - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - If this routine is called with CompletionCallback != NULL the - call is considered to be asynchronous and will return as soon - as the WRB is posted to the MCC with BE_PENDING. - - If CompletionCallback is NULL, then this routine will not return until - a completion for this MCC command has been processed. - If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has been boostraped past - mailbox mode. - - -*/ -int -_be_mpu_post_wrb_ring(struct be_mcc_object *mcc, struct MCC_WRB_AMAP *wrb, - struct be_mcc_wrb_context *wrb_context) -{ - - struct MCC_WRB_AMAP *ring_wrb = NULL; - int status = BE_PENDING; - int final_status = BE_PENDING; - mcc_wrb_cqe_callback cb = NULL; - struct MCC_DB_AMAP mcc_db; - u32 embedded; - - ASSERT(mp_ring_num_empty(&mcc->sq.ring) > 0); - /* - * Input wrb is most likely the next wrb in the ring, since the client - * can peek at the address. - */ - ring_wrb = mp_ring_producer_ptr(&mcc->sq.ring); - if (wrb != ring_wrb) { - /* If not equal, copy it into the ring. */ - memcpy(ring_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } -#ifdef BE_DEBUG - wrb_context->ring_wrb = ring_wrb; -#endif - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, ring_wrb); - if (embedded) { - /* embedded commands will have the response within the WRB. */ - wrb_context->wrb = ring_wrb; - } else { - /* - * non-embedded commands will not have the response - * within the WRB, and they may complete out-of-order. - * The WRB will not be valid to inspect - * during the completion. - */ - wrb_context->wrb = NULL; - } - cb = wrb_context->cb; - - if (cb == NULL) { - /* Assign our internal callback if this is a - * synchronous call. */ - wrb_context->cb = mcc_wrb_sync_cb; - wrb_context->cb_context = wrb_context; - wrb_context->users_final_status = &final_status; - } - /* Increment producer index */ - - mcc_db.dw[0] = 0; /* initialize */ - AMAP_SET_BITS_PTR(MCC_DB, rid, &mcc_db, mcc->sq.ring.id); - AMAP_SET_BITS_PTR(MCC_DB, numPosted, &mcc_db, 1); - - mp_ring_produce(&mcc->sq.ring); - PD_WRITE(mcc->parent_function, mpu_mcc_db, mcc_db.dw[0]); - TRACE(DL_INFO, "pidx: %x and cidx: %x.", mcc->sq.ring.pidx, - mcc->sq.ring.cidx); - - if (cb == NULL) { - int polls = 0; /* At >= 1 us per poll */ - /* Wait until this command completes, polling the CQ. */ - do { - TRACE(DL_INFO, "FWCMD submitted in the poll mode."); - /* Do not rearm CQ in this context. */ - be_mcc_process_cq(mcc, false); - - if (final_status == BE_PENDING) { - if ((++polls & 0x7FFFF) == 0) { - TRACE(DL_WARN, - "Warning : polling MCC CQ for %d" - "ms.", polls / 1000); - } - - udelay(1); - } - - /* final_status changed when the command completes */ - } while (final_status == BE_PENDING); - - status = final_status; - } - - return status; -} - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue) -{ - /* If we have queued items, do not allow a post to bypass the queue. */ - if (!driving_queue && !list_empty(&mcc->backlog)) - return NULL; - - if (mp_ring_num_empty(&mcc->sq.ring) <= 0) - return NULL; - return (struct MCC_WRB_AMAP *) mp_ring_producer_ptr(&mcc->sq.ring); -} - -int -be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *mailbox) -{ - ASSERT(mailbox); - pfob->mailbox.va = mailbox->va; - pfob->mailbox.pa = cpu_to_le64(mailbox->pa); - pfob->mailbox.length = mailbox->length; - - ASSERT(((u32)(size_t)pfob->mailbox.va & 0xf) == 0); - ASSERT(((u32)(size_t)pfob->mailbox.pa & 0xf) == 0); - /* - * Issue the WRB to set MPU endianness - */ - { - u64 *endian_check = (u64 *) (pfob->mailbox.va + - offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8); - *endian_check = 0xFF1234FFFF5678FFULL; - } - - be_mcc_mailbox_notify_and_wait(pfob); - - return BE_SUCCESS; -} - - -/* - This routine posts a command to the MCC mailbox. - - FuncObj - Function Object to post the WRB on behalf of. - wrb - wrb to post. - CompletionCallback - Address of a callback routine to invoke once the WRB - is completed. - CompletionCallbackContext - Opaque context to be passed during the call to - the CompletionCallback. - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - This routine will block until a completion for this MCC command has been - processed. If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has not been boostraped past - mailbox mode. -*/ -int -_be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context) -{ - struct MCC_MAILBOX_AMAP *mailbox = NULL; - struct MCC_WRB_AMAP *mb_wrb; - struct MCC_CQ_ENTRY_AMAP *mb_cq; - u32 offset, status; - - ASSERT(pfob->mcc == NULL); - mailbox = pfob->mailbox.va; - ASSERT(mailbox); - - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - mb_wrb = (struct MCC_WRB_AMAP *) (u8 *)mailbox + offset; - if (mb_wrb != wrb) { - memset(mailbox, 0, sizeof(*mailbox)); - memcpy(mb_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } - /* The callback can inspect the final WRB to get output parameters. */ - wrb_context->wrb = mb_wrb; - - be_mcc_mailbox_notify_and_wait(pfob); - - /* A command completed. Use tag to determine which command. */ - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, cq)/8; - mb_cq = (struct MCC_CQ_ENTRY_AMAP *) ((u8 *)mailbox + offset); - be_mcc_process_cqe(pfob, mb_cq); - - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, mb_cq); - if (status) - status = BE_NOT_OK; - return status; -} - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob) -{ - struct be_mcc_wrb_context *context = NULL; - unsigned long irq; - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (!pfob->mailbox.default_context_allocated) { - /* Use the single default context that we - * always have allocated. */ - pfob->mailbox.default_context_allocated = true; - context = &pfob->mailbox.default_context; - } else if (pfob->mcc) { - /* Get a context from the free list. If any are available. */ - if (!list_empty(&pfob->mcc->wrb_context.list_head)) { - context = list_first_entry( - &pfob->mcc->wrb_context.list_head, - struct be_mcc_wrb_context, next); - } - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); - - return context; -} - -void -_be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context) -{ - unsigned long irq; - - ASSERT(context); - /* - * Zero during free to try and catch any bugs where the context - * is accessed after a free. - */ - memset(context, 0, sizeof(context)); - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (context == &pfob->mailbox.default_context) { - /* Free the default context. */ - ASSERT(pfob->mailbox.default_context_allocated); - pfob->mailbox.default_context_allocated = false; - } else { - /* Add to free list. */ - ASSERT(pfob->mcc); - list_add_tail(&context->next, - &pfob->mcc->wrb_context.list_head); - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); -} - -int -be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context) -{ - /* Lock against anyone trying to change the callback/context pointers - * while being used. */ - spin_lock_irqsave(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - /* Assign the async callback. */ - mcc_object->async_context = cb_context; - mcc_object->async_cb = cb; - - spin_unlock_irqrestore(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - return BE_SUCCESS; -} - -#define MPU_EP_CONTROL 0 -#define MPU_EP_SEMAPHORE 0xac - -/* - *------------------------------------------------------------------- - * Function: be_wait_for_POST_complete - * Waits until the BladeEngine POST completes (either in error or success). - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int be_wait_for_POST_complete(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - u32 post_error, post_stage; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 60 * print_frequency_loops; - u32 loops = 0; - - /* - * Wait for arm fw indicating it is done or a fatal error happened. - * Note: POST can take some time to complete depending on configuration - * settings (consider ARM attempts to acquire an IP address - * over DHCP!!!). - * - */ - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage != POST_STAGE_ARMFW_READY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage != POST_STAGE_ARMFW_READY) { - TRACE(DL_ERR, "POST time-out! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else { - s = BE_SUCCESS; - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_kickoff_and_wait_for_POST - * Interacts with the BladeEngine management processor to initiate POST, and - * subsequently waits until POST completes (either in error or success). - * The caller must acquire the reset semaphore before initiating POST - * to prevent multiple drivers interacting with the management processor. - * Once POST is complete the caller must release the reset semaphore. - * Callers who only want to wait for POST complete may call - * be_wait_for_POST_complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int -be_kickoff_and_wait_for_POST(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 5 * print_frequency_loops; - u32 loops = 0; - u32 post_error, post_stage; - - /* Wait for arm fw awaiting host ready or a fatal error happened. */ - TRACE(DL_INFO, "Wait for BladeEngine ready to POST"); - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage < POST_STAGE_AWAITING_HOST_RDY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "Pre-POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage == POST_STAGE_AWAITING_HOST_RDY) { - iowrite32(POST_STAGE_HOST_RDY, pfob->csr_va + MPU_EP_SEMAPHORE); - - /* Wait for POST to complete */ - s = be_wait_for_POST_complete(pfob); - } else { - /* - * Either a timeout waiting for host ready signal or POST has - * moved ahead without requiring a host ready signal. - * Might as well give POST a chance to complete - * (or timeout again). - */ - s = be_wait_for_POST_complete(pfob); - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_pci_soft_reset - * This function is called to issue a BladeEngine soft reset. - * Callers should acquire the soft reset semaphore before calling this - * function. Additionaly, callers should ensure they cannot be pre-empted - * while the routine executes. Upon completion of this routine, callers - * should release the reset semaphore. This routine implicitly waits - * for BladeEngine POST to complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_pci_soft_reset(struct be_function_object *pfob) -{ - struct PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - struct PCICFG_ONLINE0_CSR_AMAP pciOnline0; - struct PCICFG_ONLINE1_CSR_AMAP pciOnline1; - struct EP_CONTROL_CSR_AMAP epControlCsr; - int status = BE_SUCCESS; - u32 i, soft_reset_bit; - - TRACE(DL_NOTE, "PCI reset..."); - - /* Issue soft reset #1 to get BladeEngine into a known state. */ - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - /* Mask everything */ - PCICFG0_WRITE(pfob, ue_status_low_mask, 0xFFFFFFFF); - PCICFG0_WRITE(pfob, ue_status_hi_mask, 0xFFFFFFFF); - /* - * Set everything offline except MPU IRAM (it is offline with - * the soft-reset, but soft-reset does not reset the PCICFG registers!) - */ - pciOnline0.dw[0] = 0; - pciOnline1.dw[0] = 0; - AMAP_SET_BITS_PTR(PCICFG_ONLINE1_CSR, mpu_iram_online, - pciOnline1.dw, 1); - PCICFG0_WRITE(pfob, online0, pciOnline0.dw[0]); - PCICFG0_WRITE(pfob, online1, pciOnline1.dw[0]); - - udelay(20000); - - /* Issue soft reset #2. */ - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - - - udelay(20000); - - /* Take MPU out of reset. */ - - epControlCsr.dw[0] = ioread32(pfob->csr_va + MPU_EP_CONTROL); - AMAP_SET_BITS_PTR(EP_CONTROL_CSR, CPU_reset, &epControlCsr, 0); - iowrite32((u32)epControlCsr.dw[0], pfob->csr_va + MPU_EP_CONTROL); - - /* Kickoff BE POST and wait for completion */ - status = be_kickoff_and_wait_for_POST(pfob); - -Error_label: - return status; -} - - -/* - *------------------------------------------------------------------- - * Function: be_pci_reset_required - * This private function is called to detect if a host entity is - * required to issue a PCI soft reset and subsequently drive - * BladeEngine POST. Scenarios where this is required: - * 1) BIOS-less configuration - * 2) Hot-swap/plug/power-on - * pfob - - * return true if a reset is required, false otherwise - *------------------------------------------------------------------- - */ -static bool be_pci_reset_required(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - bool do_reset = false; - u32 post_error, post_stage; - - /* - * Read the POST status register - */ - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, error, - &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, stage, - &status); - if (post_stage <= POST_STAGE_AWAITING_HOST_RDY) { - /* - * If BladeEngine is waiting for host ready indication, - * we want to do a PCI reset. - */ - do_reset = true; - } - - return do_reset; -} - -/* - *------------------------------------------------------------------- - * Function: be_drive_POST - * This function is called to drive BladeEngine POST. The - * caller should ensure they cannot be pre-empted while this routine executes. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_drive_POST(struct be_function_object *pfob) -{ - int status; - - if (false != be_pci_reset_required(pfob)) { - /* PCI reset is needed (implicitly starts and waits for POST) */ - status = be_pci_soft_reset(pfob); - } else { - /* No PCI reset is needed, start POST */ - status = be_kickoff_and_wait_for_POST(pfob); - } - - return status; -} diff --git a/drivers/staging/benet/mpu.h b/drivers/staging/benet/mpu.h deleted file mode 100644 index 41f3f87516e..00000000000 --- a/drivers/staging/benet/mpu.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_amap_h__ -#define __mpu_amap_h__ -#include "ep.h" - -/* Provide control parameters for the Managment Processor Unit. */ -struct BE_MPU_CSRMAP_AMAP { - struct BE_EP_CSRMAP_AMAP ep; - u8 rsvd0[128]; /* DWORD 64 */ - u8 rsvd1[32]; /* DWORD 68 */ - u8 rsvd2[192]; /* DWORD 69 */ - u8 rsvd3[192]; /* DWORD 75 */ - u8 rsvd4[32]; /* DWORD 81 */ - u8 rsvd5[32]; /* DWORD 82 */ - u8 rsvd6[32]; /* DWORD 83 */ - u8 rsvd7[32]; /* DWORD 84 */ - u8 rsvd8[32]; /* DWORD 85 */ - u8 rsvd9[32]; /* DWORD 86 */ - u8 rsvd10[32]; /* DWORD 87 */ - u8 rsvd11[32]; /* DWORD 88 */ - u8 rsvd12[32]; /* DWORD 89 */ - u8 rsvd13[32]; /* DWORD 90 */ - u8 rsvd14[32]; /* DWORD 91 */ - u8 rsvd15[32]; /* DWORD 92 */ - u8 rsvd16[32]; /* DWORD 93 */ - u8 rsvd17[32]; /* DWORD 94 */ - u8 rsvd18[32]; /* DWORD 95 */ - u8 rsvd19[32]; /* DWORD 96 */ - u8 rsvd20[32]; /* DWORD 97 */ - u8 rsvd21[32]; /* DWORD 98 */ - u8 rsvd22[32]; /* DWORD 99 */ - u8 rsvd23[32]; /* DWORD 100 */ - u8 rsvd24[32]; /* DWORD 101 */ - u8 rsvd25[32]; /* DWORD 102 */ - u8 rsvd26[32]; /* DWORD 103 */ - u8 rsvd27[32]; /* DWORD 104 */ - u8 rsvd28[96]; /* DWORD 105 */ - u8 rsvd29[32]; /* DWORD 108 */ - u8 rsvd30[32]; /* DWORD 109 */ - u8 rsvd31[32]; /* DWORD 110 */ - u8 rsvd32[32]; /* DWORD 111 */ - u8 rsvd33[32]; /* DWORD 112 */ - u8 rsvd34[96]; /* DWORD 113 */ - u8 rsvd35[32]; /* DWORD 116 */ - u8 rsvd36[32]; /* DWORD 117 */ - u8 rsvd37[32]; /* DWORD 118 */ - u8 rsvd38[32]; /* DWORD 119 */ - u8 rsvd39[32]; /* DWORD 120 */ - u8 rsvd40[32]; /* DWORD 121 */ - u8 rsvd41[134][32]; /* DWORD 122 */ -} __packed; -struct MPU_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __mpu_amap_h__ */ diff --git a/drivers/staging/benet/mpu_context.h b/drivers/staging/benet/mpu_context.h deleted file mode 100644 index 8ce90f9c46c..00000000000 --- a/drivers/staging/benet/mpu_context.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_context_amap_h__ -#define __mpu_context_amap_h__ - -/* - * Management command and control ring context. The MPUs BTLR_CTRL1 CSR - * controls the writeback behavior of the producer and consumer index values. - */ -struct BE_MCC_RING_CONTEXT_AMAP { - u8 con_index[16]; /* DWORD 0 */ - u8 ring_size[4]; /* DWORD 0 */ - u8 cq_id[11]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 prod_index[16]; /* DWORD 1 */ - u8 pdid[15]; /* DWORD 1 */ - u8 invalid; /* DWORD 1 */ - u8 cmd_pending_current[7]; /* DWORD 2 */ - u8 rsvd1[25]; /* DWORD 2 */ - u8 hpi_port_cq_id[11]; /* DWORD 3 */ - u8 rsvd2[5]; /* DWORD 3 */ - u8 cmd_pending_max[7]; /* DWORD 3 */ - u8 rsvd3[9]; /* DWORD 3 */ -} __packed; -struct MCC_RING_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __mpu_context_amap_h__ */ diff --git a/drivers/staging/benet/pcicfg.h b/drivers/staging/benet/pcicfg.h deleted file mode 100644 index 7c15684adf4..00000000000 --- a/drivers/staging/benet/pcicfg.h +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __pcicfg_amap_h__ -#define __pcicfg_amap_h__ - -/* Vendor and Device ID Register. */ -struct BE_PCICFG_ID_CSR_AMAP { - u8 vendorid[16]; /* DWORD 0 */ - u8 deviceid[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ID_CSR_AMAP { - u32 dw[1]; -}; - -/* IO Bar Register. */ -struct BE_PCICFG_IOBAR_CSR_AMAP { - u8 iospace; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 iobar[24]; /* DWORD 0 */ -} __packed; -struct PCICFG_IOBAR_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 0 Register. */ -struct BE_PCICFG_MEMBAR0_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 membar0[18]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR0_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - Low Address Register. */ -struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 membar1lo[15]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - High Address Register. */ -struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP { - u8 membar1hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - Low Address Register. */ -struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[17]; /* DWORD 0 */ - u8 membar2lo[11]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - High Address Register. */ -struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP { - u8 membar2hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 0) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 1) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_PCICFG_SEMAPHORE_CSR_AMAP { - u8 locked; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Soft Reset Register. */ -struct BE_PCICFG_SOFT_RESET_CSR_AMAP { - u8 rsvd0[7]; /* DWORD 0 */ - u8 softreset; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 nec_ll_rcvdetect_i[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_SOFT_RESET_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (Low) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP { - u8 cev_ue_status; /* DWORD 0 */ - u8 ctx_ue_status; /* DWORD 0 */ - u8 dbuf_ue_status; /* DWORD 0 */ - u8 erx_ue_status; /* DWORD 0 */ - u8 host_ue_status; /* DWORD 0 */ - u8 mpu_ue_status; /* DWORD 0 */ - u8 ndma_ue_status; /* DWORD 0 */ - u8 ptc_ue_status; /* DWORD 0 */ - u8 rdma_ue_status; /* DWORD 0 */ - u8 rxf_ue_status; /* DWORD 0 */ - u8 rxips_ue_status; /* DWORD 0 */ - u8 rxulp0_ue_status; /* DWORD 0 */ - u8 rxulp1_ue_status; /* DWORD 0 */ - u8 rxulp2_ue_status; /* DWORD 0 */ - u8 tim_ue_status; /* DWORD 0 */ - u8 tpost_ue_status; /* DWORD 0 */ - u8 tpre_ue_status; /* DWORD 0 */ - u8 txips_ue_status; /* DWORD 0 */ - u8 txulp0_ue_status; /* DWORD 0 */ - u8 txulp1_ue_status; /* DWORD 0 */ - u8 uc_ue_status; /* DWORD 0 */ - u8 wdma_ue_status; /* DWORD 0 */ - u8 txulp2_ue_status; /* DWORD 0 */ - u8 host1_ue_status; /* DWORD 0 */ - u8 p0_ob_link_ue_status; /* DWORD 0 */ - u8 p1_ob_link_ue_status; /* DWORD 0 */ - u8 host_gpio_ue_status; /* DWORD 0 */ - u8 mbox_netw_ue_status; /* DWORD 0 */ - u8 mbox_stor_ue_status; /* DWORD 0 */ - u8 axgmac0_ue_status; /* DWORD 0 */ - u8 axgmac1_ue_status; /* DWORD 0 */ - u8 mpu_intpend_ue_status; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (High) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip; - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP { - u8 jtag_ue_status; /* DWORD 0 */ - u8 lpcmemhost_ue_status; /* DWORD 0 */ - u8 mgmt_mac_ue_status; /* DWORD 0 */ - u8 mpu_iram_ue_status; /* DWORD 0 */ - u8 pcs0online_ue_status; /* DWORD 0 */ - u8 pcs1online_ue_status; /* DWORD 0 */ - u8 pctl0_ue_status; /* DWORD 0 */ - u8 pctl1_ue_status; /* DWORD 0 */ - u8 pmem_ue_status; /* DWORD 0 */ - u8 rr_ue_status; /* DWORD 0 */ - u8 rxpp_ue_status; /* DWORD 0 */ - u8 txpb_ue_status; /* DWORD 0 */ - u8 txp_ue_status; /* DWORD 0 */ - u8 xaui_ue_status; /* DWORD 0 */ - u8 arm_ue_status; /* DWORD 0 */ - u8 ipc_ue_status; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (Low) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u8 cev_ue_mask; /* DWORD 0 */ - u8 ctx_ue_mask; /* DWORD 0 */ - u8 dbuf_ue_mask; /* DWORD 0 */ - u8 erx_ue_mask; /* DWORD 0 */ - u8 host_ue_mask; /* DWORD 0 */ - u8 mpu_ue_mask; /* DWORD 0 */ - u8 ndma_ue_mask; /* DWORD 0 */ - u8 ptc_ue_mask; /* DWORD 0 */ - u8 rdma_ue_mask; /* DWORD 0 */ - u8 rxf_ue_mask; /* DWORD 0 */ - u8 rxips_ue_mask; /* DWORD 0 */ - u8 rxulp0_ue_mask; /* DWORD 0 */ - u8 rxulp1_ue_mask; /* DWORD 0 */ - u8 rxulp2_ue_mask; /* DWORD 0 */ - u8 tim_ue_mask; /* DWORD 0 */ - u8 tpost_ue_mask; /* DWORD 0 */ - u8 tpre_ue_mask; /* DWORD 0 */ - u8 txips_ue_mask; /* DWORD 0 */ - u8 txulp0_ue_mask; /* DWORD 0 */ - u8 txulp1_ue_mask; /* DWORD 0 */ - u8 uc_ue_mask; /* DWORD 0 */ - u8 wdma_ue_mask; /* DWORD 0 */ - u8 txulp2_ue_mask; /* DWORD 0 */ - u8 host1_ue_mask; /* DWORD 0 */ - u8 p0_ob_link_ue_mask; /* DWORD 0 */ - u8 p1_ob_link_ue_mask; /* DWORD 0 */ - u8 host_gpio_ue_mask; /* DWORD 0 */ - u8 mbox_netw_ue_mask; /* DWORD 0 */ - u8 mbox_stor_ue_mask; /* DWORD 0 */ - u8 axgmac0_ue_mask; /* DWORD 0 */ - u8 axgmac1_ue_mask; /* DWORD 0 */ - u8 mpu_intpend_ue_mask; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (High) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u8 jtag_ue_mask; /* DWORD 0 */ - u8 lpcmemhost_ue_mask; /* DWORD 0 */ - u8 mgmt_mac_ue_mask; /* DWORD 0 */ - u8 mpu_iram_ue_mask; /* DWORD 0 */ - u8 pcs0online_ue_mask; /* DWORD 0 */ - u8 pcs1online_ue_mask; /* DWORD 0 */ - u8 pctl0_ue_mask; /* DWORD 0 */ - u8 pctl1_ue_mask; /* DWORD 0 */ - u8 pmem_ue_mask; /* DWORD 0 */ - u8 rr_ue_mask; /* DWORD 0 */ - u8 rxpp_ue_mask; /* DWORD 0 */ - u8 txpb_ue_mask; /* DWORD 0 */ - u8 txp_ue_mask; /* DWORD 0 */ - u8 xaui_ue_mask; /* DWORD 0 */ - u8 arm_ue_mask; /* DWORD 0 */ - u8 ipc_ue_mask; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 0. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE0_CSR_AMAP { - u8 cev_online; /* DWORD 0 */ - u8 ctx_online; /* DWORD 0 */ - u8 dbuf_online; /* DWORD 0 */ - u8 erx_online; /* DWORD 0 */ - u8 host_online; /* DWORD 0 */ - u8 mpu_online; /* DWORD 0 */ - u8 ndma_online; /* DWORD 0 */ - u8 ptc_online; /* DWORD 0 */ - u8 rdma_online; /* DWORD 0 */ - u8 rxf_online; /* DWORD 0 */ - u8 rxips_online; /* DWORD 0 */ - u8 rxulp0_online; /* DWORD 0 */ - u8 rxulp1_online; /* DWORD 0 */ - u8 rxulp2_online; /* DWORD 0 */ - u8 tim_online; /* DWORD 0 */ - u8 tpost_online; /* DWORD 0 */ - u8 tpre_online; /* DWORD 0 */ - u8 txips_online; /* DWORD 0 */ - u8 txulp0_online; /* DWORD 0 */ - u8 txulp1_online; /* DWORD 0 */ - u8 uc_online; /* DWORD 0 */ - u8 wdma_online; /* DWORD 0 */ - u8 txulp2_online; /* DWORD 0 */ - u8 host1_online; /* DWORD 0 */ - u8 p0_ob_link_online; /* DWORD 0 */ - u8 p1_ob_link_online; /* DWORD 0 */ - u8 host_gpio_online; /* DWORD 0 */ - u8 mbox_netw_online; /* DWORD 0 */ - u8 mbox_stor_online; /* DWORD 0 */ - u8 axgmac0_online; /* DWORD 0 */ - u8 axgmac1_online; /* DWORD 0 */ - u8 mpu_intpend_online; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE0_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 1. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE1_CSR_AMAP { - u8 jtag_online; /* DWORD 0 */ - u8 lpcmemhost_online; /* DWORD 0 */ - u8 mgmt_mac_online; /* DWORD 0 */ - u8 mpu_iram_online; /* DWORD 0 */ - u8 pcs0online_online; /* DWORD 0 */ - u8 pcs1online_online; /* DWORD 0 */ - u8 pctl0_online; /* DWORD 0 */ - u8 pctl1_online; /* DWORD 0 */ - u8 pmem_online; /* DWORD 0 */ - u8 rr_online; /* DWORD 0 */ - u8 rxpp_online; /* DWORD 0 */ - u8 txpb_online; /* DWORD 0 */ - u8 txp_online; /* DWORD 0 */ - u8 xaui_online; /* DWORD 0 */ - u8 arm_online; /* DWORD 0 */ - u8 ipc_online; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE1_CSR_AMAP { - u32 dw[1]; -}; - -/* Host Timer Register. */ -struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u8 hosttimer[24]; /* DWORD 0 */ - u8 hostintr; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ -} __packed; -struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u32 dw[1]; -}; - -/* Scratchpad Register (for software use). */ -struct BE_PCICFG_SCRATCHPAD_CSR_AMAP { - u8 scratchpad[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_SCRATCHPAD_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Capabilities Register. */ -struct BE_PCICFG_PCIE_CAP_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextcap[8]; /* DWORD 0 */ - u8 capver[4]; /* DWORD 0 */ - u8 devport[4]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Capabilities Register. */ -struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP { - u8 payload[3]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 lo_lat[3]; /* DWORD 0 */ - u8 l1_lat[3]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ - u8 pwr_value[8]; /* DWORD 0 */ - u8 pwr_scale[2]; /* DWORD 0 */ - u8 rsvd3[4]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_DEVCAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Control/Status Registers. */ -struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u8 CorrErrReportEn; /* DWORD 0 */ - u8 NonFatalErrReportEn; /* DWORD 0 */ - u8 FatalErrReportEn; /* DWORD 0 */ - u8 UnsuppReqReportEn; /* DWORD 0 */ - u8 EnableRelaxOrder; /* DWORD 0 */ - u8 Max_Payload_Size[3]; /* DWORD 0 */ - u8 ExtendTagFieldEnable; /* DWORD 0 */ - u8 PhantomFnEnable; /* DWORD 0 */ - u8 AuxPwrPMEnable; /* DWORD 0 */ - u8 EnableNoSnoop; /* DWORD 0 */ - u8 Max_Read_Req_Size[3]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 CorrErrDetect; /* DWORD 0 */ - u8 NonFatalErrDetect; /* DWORD 0 */ - u8 FatalErrDetect; /* DWORD 0 */ - u8 UnsuppReqDetect; /* DWORD 0 */ - u8 AuxPwrDetect; /* DWORD 0 */ - u8 TransPending; /* DWORD 0 */ - u8 rsvd1[10]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Capabilities Register. */ -struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u8 MaxLinkSpeed[4]; /* DWORD 0 */ - u8 MaxLinkWidth[6]; /* DWORD 0 */ - u8 ASPMSupport[2]; /* DWORD 0 */ - u8 L0sExitLat[3]; /* DWORD 0 */ - u8 L1ExitLat[3]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 PortNum[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Status Register. */ -struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u8 ASPMCtl[2]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 ReadCmplBndry; /* DWORD 0 */ - u8 LinkDisable; /* DWORD 0 */ - u8 RetrainLink; /* DWORD 0 */ - u8 CommonClkConfig; /* DWORD 0 */ - u8 ExtendSync; /* DWORD 0 */ - u8 rsvd1[8]; /* DWORD 0 */ - u8 LinkSpeed[4]; /* DWORD 0 */ - u8 NegLinkWidth[6]; /* DWORD 0 */ - u8 LinkTrainErr; /* DWORD 0 */ - u8 LinkTrain; /* DWORD 0 */ - u8 SlotClkConfig; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI Configuration Register. */ -struct BE_PCICFG_MSI_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextptr[8]; /* DWORD 0 */ - u8 tablesize[11]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 funcmask; /* DWORD 0 */ - u8 en; /* DWORD 0 */ -} __packed; -struct PCICFG_MSI_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X Table Offset Register. */ -struct BE_PCICFG_MSIX_TABLE_CSR_AMAP { - u8 tablebir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_TABLE_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X PBA Offset Register. */ -struct BE_PCICFG_MSIX_PBA_CSR_AMAP { - u8 pbabir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_PBA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Vector Control Register. */ -struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u8 vector_control; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Data Register. */ -struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u8 data[16]; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - High Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u8 addr[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - Low Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u8 rsvd0[2]; /* DWORD 0 */ - u8 addr[30]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_18_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_18_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_19_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_19_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_20_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[25][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_20_RSVD_AMAP { - u32 dw[26]; -}; - -struct BE_PCICFG_ANON_21_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1919][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_21_RSVD_AMAP { - u32 dw[1920]; -}; - -struct BE_PCICFG_ANON_22_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_22_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_23_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_23_RSVD_AMAP { - u32 dw[896]; -}; - -/* These PCI Configuration Space registers are for the Storage Function of - * BladeEngine (Function 0). In the memory map of the registers below their - * table, - */ -struct BE_PCICFG0_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[32]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 61 */ - u8 rsvd25[32]; /* DWORD 62 */ - u8 rsvd26[32]; /* DWORD 63 */ - u8 rsvd27[32]; /* DWORD 64 */ - u8 rsvd28[32]; /* DWORD 65 */ - u8 rsvd29[32]; /* DWORD 66 */ - u8 rsvd30[32]; /* DWORD 67 */ - u8 rsvd31[32]; /* DWORD 68 */ - u8 rsvd32[32]; /* DWORD 69 */ - u8 rsvd33[32]; /* DWORD 70 */ - u8 rsvd34[32]; /* DWORD 71 */ - u8 rsvd35[32]; /* DWORD 72 */ - u8 rsvd36[32]; /* DWORD 73 */ - u8 rsvd37[32]; /* DWORD 74 */ - u8 rsvd38[32]; /* DWORD 75 */ - u8 rsvd39[32]; /* DWORD 76 */ - u8 rsvd40[32]; /* DWORD 77 */ - u8 rsvd41[32]; /* DWORD 78 */ - u8 rsvd42[32]; /* DWORD 79 */ - u8 rsvd43[32]; /* DWORD 80 */ - u8 rsvd44[32]; /* DWORD 81 */ - u8 rsvd45[32]; /* DWORD 82 */ - u8 rsvd46[32]; /* DWORD 83 */ - u8 rsvd47[32]; /* DWORD 84 */ - u8 rsvd48[32]; /* DWORD 85 */ - u8 rsvd49[32]; /* DWORD 86 */ - u8 rsvd50[32]; /* DWORD 87 */ - u8 rsvd51[32]; /* DWORD 88 */ - u8 rsvd52[32]; /* DWORD 89 */ - u8 rsvd53[32]; /* DWORD 90 */ - u8 rsvd54[32]; /* DWORD 91 */ - u8 rsvd55[32]; /* DWORD 92 */ - u8 rsvd56[832]; /* DWORD 93 */ - u8 rsvd57[32]; /* DWORD 119 */ - u8 rsvd58[32]; /* DWORD 120 */ - u8 rsvd59[32]; /* DWORD 121 */ - u8 rsvd60[32]; /* DWORD 122 */ - u8 rsvd61[32]; /* DWORD 123 */ - u8 rsvd62[32]; /* DWORD 124 */ - u8 rsvd63[32]; /* DWORD 125 */ - u8 rsvd64[32]; /* DWORD 126 */ - u8 rsvd65[32]; /* DWORD 127 */ - u8 rsvd66[61440]; /* DWORD 128 */ - struct BE_PCICFG_ANON_22_MESSAGE_AMAP message[32]; - u8 rsvd67[28672]; /* DWORD 2176 */ - u8 rsvd68[32]; /* DWORD 3072 */ - u8 rsvd69[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG0_CSRMAP_AMAP { - u32 dw[4096]; -}; - -struct BE_PCICFG_ANON_24_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_24_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_25_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_25_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_26_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_26_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_27_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_27_RSVD_AMAP { - u32 dw[2]; -}; - -struct BE_PCICFG_ANON_28_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[3][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_28_RSVD_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_29_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[36][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_29_RSVD_AMAP { - u32 dw[37]; -}; - -struct BE_PCICFG_ANON_30_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1930][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_30_RSVD_AMAP { - u32 dw[1931]; -}; - -struct BE_PCICFG_ANON_31_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_31_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_32_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_32_RSVD_AMAP { - u32 dw[896]; -}; - -/* This PCI configuration space register map is for the Networking Function of - * BladeEngine (Function 1). - */ -struct BE_PCICFG1_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[64]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 62 */ - u8 rsvd25[32]; /* DWORD 63 */ - u8 rsvd26[32]; /* DWORD 64 */ - u8 rsvd27[32]; /* DWORD 65 */ - u8 rsvd28[32]; /* DWORD 66 */ - u8 rsvd29[32]; /* DWORD 67 */ - u8 rsvd30[32]; /* DWORD 68 */ - u8 rsvd31[32]; /* DWORD 69 */ - u8 rsvd32[32]; /* DWORD 70 */ - u8 rsvd33[32]; /* DWORD 71 */ - u8 rsvd34[32]; /* DWORD 72 */ - u8 rsvd35[32]; /* DWORD 73 */ - u8 rsvd36[32]; /* DWORD 74 */ - u8 rsvd37[128]; /* DWORD 75 */ - u8 rsvd38[32]; /* DWORD 79 */ - u8 rsvd39[1184]; /* DWORD 80 */ - u8 rsvd40[61792]; /* DWORD 117 */ - struct BE_PCICFG_ANON_31_MESSAGE_AMAP message[32]; - u8 rsvd41[28672]; /* DWORD 2176 */ - u8 rsvd42[32]; /* DWORD 3072 */ - u8 rsvd43[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG1_CSRMAP_AMAP { - u32 dw[4096]; -}; - -#endif /* __pcicfg_amap_h__ */ diff --git a/drivers/staging/benet/post_codes.h b/drivers/staging/benet/post_codes.h deleted file mode 100644 index 6d1621f5f5f..00000000000 --- a/drivers/staging/benet/post_codes.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __post_codes_amap_h__ -#define __post_codes_amap_h__ - -/* --- MGMT_HBA_POST_STAGE_ENUM --- */ -#define POST_STAGE_POWER_ON_RESET (0) /* State after a cold or warm boot. */ -#define POST_STAGE_AWAITING_HOST_RDY (1) /* ARM boot code awaiting a - go-ahed from the host. */ -#define POST_STAGE_HOST_RDY (2) /* Host has given go-ahed to ARM. */ -#define POST_STAGE_BE_RESET (3) /* Host wants to reset chip, this is a chip - workaround */ -#define POST_STAGE_SEEPROM_CS_START (256) /* SEEPROM checksum - test start. */ -#define POST_STAGE_SEEPROM_CS_DONE (257) /* SEEPROM checksum test - done. */ -#define POST_STAGE_DDR_CONFIG_START (512) /* DDR configuration start. */ -#define POST_STAGE_DDR_CONFIG_DONE (513) /* DDR configuration done. */ -#define POST_STAGE_DDR_CALIBRATE_START (768) /* DDR calibration start. */ -#define POST_STAGE_DDR_CALIBRATE_DONE (769) /* DDR calibration done. */ -#define POST_STAGE_DDR_TEST_START (1024) /* DDR memory test start. */ -#define POST_STAGE_DDR_TEST_DONE (1025) /* DDR memory test done. */ -#define POST_STAGE_REDBOOT_INIT_START (1536) /* Redboot starts execution. */ -#define POST_STAGE_REDBOOT_INIT_DONE (1537) /* Redboot done execution. */ -#define POST_STAGE_FW_IMAGE_LOAD_START (1792) /* Firmware image load to - DDR start. */ -#define POST_STAGE_FW_IMAGE_LOAD_DONE (1793) /* Firmware image load - to DDR done. */ -#define POST_STAGE_ARMFW_START (2048) /* ARMfw runtime code - starts execution. */ -#define POST_STAGE_DHCP_QUERY_START (2304) /* DHCP server query start. */ -#define POST_STAGE_DHCP_QUERY_DONE (2305) /* DHCP server query done. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_START (2560) /* Boot Target - Discovery Start. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_DONE (2561) /* Boot Target - Discovery Done. */ -#define POST_STAGE_RC_OPTION_SET (2816) /* Remote configuration - option is set in SEEPROM */ -#define POST_STAGE_SWITCH_LINK (2817) /* Wait for link up on switch */ -#define POST_STAGE_SEND_ICDS_MESSAGE (2818) /* Send the ICDS message - to switch */ -#define POST_STAGE_PERFROM_TFTP (2819) /* Download xml using TFTP */ -#define POST_STAGE_PARSE_XML (2820) /* Parse XML file */ -#define POST_STAGE_DOWNLOAD_IMAGE (2821) /* Download IMAGE from - TFTP server */ -#define POST_STAGE_FLASH_IMAGE (2822) /* Flash the IMAGE */ -#define POST_STAGE_RC_DONE (2823) /* Remote configuration - complete */ -#define POST_STAGE_REBOOT_SYSTEM (2824) /* Upgrade IMAGE done, - reboot required */ -#define POST_STAGE_MAC_ADDRESS (3072) /* MAC Address Check */ -#define POST_STAGE_ARMFW_READY (49152) /* ARMfw is done with POST - and ready. */ -#define POST_STAGE_ARMFW_UE (61440) /* ARMfw has asserted an - unrecoverable error. The - lower 3 hex digits of the - stage code identify the - unique error code. - */ - -/* This structure defines the format of the MPU semaphore - * register when used for POST. - */ -struct BE_MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u8 stage[16]; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 iscsi_driver_loaded; /* DWORD 0 */ - u8 option_rom_installed; /* DWORD 0 */ - u8 iscsi_ip_conflict; /* DWORD 0 */ - u8 iscsi_no_ip; /* DWORD 0 */ - u8 backup_fw; /* DWORD 0 */ - u8 error; /* DWORD 0 */ -} __packed; -struct MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u32 dw[1]; -}; - -/* --- MGMT_HBA_POST_DUMMY_BITS_ENUM --- */ -#define POST_BIT_ISCSI_LOADED (26) -#define POST_BIT_OPTROM_INST (27) -#define POST_BIT_BAD_IP_ADDR (28) -#define POST_BIT_NO_IP_ADDR (29) -#define POST_BIT_BACKUP_FW (30) -#define POST_BIT_ERROR (31) - -/* --- MGMT_HBA_POST_DUMMY_VALUES_ENUM --- */ -#define POST_ISCSI_DRIVER_LOADED (67108864) -#define POST_OPTROM_INSTALLED (134217728) -#define POST_ISCSI_IP_ADDRESS_CONFLICT (268435456) -#define POST_ISCSI_NO_IP_ADDRESS (536870912) -#define POST_BACKUP_FW_LOADED (1073741824) -#define POST_FATAL_ERROR (2147483648) - -#endif /* __post_codes_amap_h__ */ diff --git a/drivers/staging/benet/regmap.h b/drivers/staging/benet/regmap.h deleted file mode 100644 index e816ba210e8..00000000000 --- a/drivers/staging/benet/regmap.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __regmap_amap_h__ -#define __regmap_amap_h__ -#include "pcicfg.h" -#include "ep.h" -#include "cev.h" -#include "mpu.h" -#include "doorbells.h" - -/* - * This is the control and status register map for BladeEngine, showing - * the relative size and offset of each sub-module. The CSR registers - * are identical for the network and storage PCI functions. The - * CSR map is shown below, followed by details of each block, - * in sub-sections. The sub-sections begin with a description - * of CSRs that are instantiated in multiple blocks. - */ -struct BE_BLADE_ENGINE_CSRMAP_AMAP { - struct BE_MPU_CSRMAP_AMAP mpu; - u8 rsvd0[8192]; /* DWORD 256 */ - u8 rsvd1[8192]; /* DWORD 512 */ - struct BE_CEV_CSRMAP_AMAP cev; - u8 rsvd2[8192]; /* DWORD 1024 */ - u8 rsvd3[8192]; /* DWORD 1280 */ - u8 rsvd4[8192]; /* DWORD 1536 */ - u8 rsvd5[8192]; /* DWORD 1792 */ - u8 rsvd6[8192]; /* DWORD 2048 */ - u8 rsvd7[8192]; /* DWORD 2304 */ - u8 rsvd8[8192]; /* DWORD 2560 */ - u8 rsvd9[8192]; /* DWORD 2816 */ - u8 rsvd10[8192]; /* DWORD 3072 */ - u8 rsvd11[8192]; /* DWORD 3328 */ - u8 rsvd12[8192]; /* DWORD 3584 */ - u8 rsvd13[8192]; /* DWORD 3840 */ - u8 rsvd14[8192]; /* DWORD 4096 */ - u8 rsvd15[8192]; /* DWORD 4352 */ - u8 rsvd16[8192]; /* DWORD 4608 */ - u8 rsvd17[8192]; /* DWORD 4864 */ - u8 rsvd18[8192]; /* DWORD 5120 */ - u8 rsvd19[8192]; /* DWORD 5376 */ - u8 rsvd20[8192]; /* DWORD 5632 */ - u8 rsvd21[8192]; /* DWORD 5888 */ - u8 rsvd22[8192]; /* DWORD 6144 */ - u8 rsvd23[17152][32]; /* DWORD 6400 */ -} __packed; -struct BLADE_ENGINE_CSRMAP_AMAP { - u32 dw[23552]; -}; - -#endif /* __regmap_amap_h__ */ diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index ab69c1bf36a..c2747bc88c6 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2164,19 +2164,20 @@ static void __exit panel_cleanup_module(void) if (scan_timer.function != NULL) del_timer(&scan_timer); - if (keypad_enabled) - misc_deregister(&keypad_dev); + if (pprt != NULL) { + if (keypad_enabled) + misc_deregister(&keypad_dev); + + if (lcd_enabled) { + panel_lcd_print("\x0cLCD driver " PANEL_VERSION + "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); + misc_deregister(&lcd_dev); + } - if (lcd_enabled) { - panel_lcd_print("\x0cLCD driver " PANEL_VERSION - "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); - misc_deregister(&lcd_dev); + /* TODO: free all input signals */ + parport_release(pprt); + parport_unregister_device(pprt); } - - /* TODO: free all input signals */ - - parport_release(pprt); - parport_unregister_device(pprt); parport_unregister_driver(&panel_driver); } diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig index 79c225acd1a..f636296b54b 100644 --- a/drivers/staging/rtl8187se/Kconfig +++ b/drivers/staging/rtl8187se/Kconfig @@ -1,5 +1,6 @@ config RTL8187SE tristate "RealTek RTL8187SE Wireless LAN NIC driver" depends on PCI + depends on WIRELESS_EXT && COMPAT_NET_DEV_OPS default N ---help--- diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c index af64cfbe16d..7370296225e 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c @@ -234,20 +234,21 @@ out: void ieee80211_crypto_deinit(void) { struct list_head *ptr, *n; + struct ieee80211_crypto_alg *alg = NULL; if (hcrypt == NULL) return; - for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; - ptr = n, n = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *) ptr; - list_del(ptr); - printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " - "'%s' (deinit)\n", alg->ops->name); - kfree(alg); + list_for_each_safe(ptr, n, &hcrypt->algs) { + alg = list_entry(ptr, struct ieee80211_crypto_alg, list); + if (alg) { + list_del(ptr); + printk(KERN_DEBUG + "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n", + alg->ops->name); + kfree(alg); + } } - kfree(hcrypt); } diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 94534955e38..66de5cc8ddf 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -6161,10 +6161,10 @@ static void __exit rtl8180_pci_module_exit(void) { pci_unregister_driver (&rtl8180_pci_driver); rtl8180_proc_module_remove(); - ieee80211_crypto_deinit(); ieee80211_crypto_tkip_exit(); ieee80211_crypto_ccmp_exit(); ieee80211_crypto_wep_exit(); + ieee80211_crypto_deinit(); DMESG("Exiting"); } diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index b003f9a7e15..f716b2e92b6 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -319,16 +319,18 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id struct usb_device *udev = interface_to_usbdev(intf); struct wbsoft_priv *priv; struct ieee80211_hw *dev; - int err; + int nr, err; usb_get_dev(udev); // 20060630.2 Check the device if it already be opened - err = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ), - 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, - 0x0, 0x400, <mp, 4, HZ*100 ); - if (err) + nr = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ), + 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, + 0x0, 0x400, <mp, 4, HZ*100 ); + if (nr < 0) { + err = nr; goto error; + } ltmp = cpu_to_le32(ltmp); if (ltmp) { // Is already initialized? @@ -337,8 +339,10 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id } dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops); - if (!dev) + if (!dev) { + err = -ENOMEM; goto error; + } priv = dev->priv; @@ -369,9 +373,11 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id } dev->extra_tx_headroom = 12; /* FIXME */ - dev->flags = 0; + dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); dev->channel_change_time = 1000; + dev->max_signal = 100; dev->queues = 1; dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz; diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 5ed4ae07bac..6789089e246 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -485,7 +485,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n", wbuflen, rbuflen); ret = -ENOMEM; - goto fail; + goto err; } mutex_lock(&instance->cm_serialize); @@ -565,6 +565,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, dbg("cm %#x", cm); fail: mutex_unlock(&instance->cm_serialize); +err: return ret; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 326dd7f65ee..b3d5a23ab56 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1376,6 +1376,15 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ + }, + { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ + .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on + data interface instead of + communications interface. + Maybe we should define a new + quirk for this. */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0f5c05f6f9d..c40a9b284cc 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -50,6 +50,7 @@ static struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, { 0, } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, usbtmc_devices); @@ -106,12 +107,13 @@ static int usbtmc_open(struct inode *inode, struct file *filp) { struct usb_interface *intf; struct usbtmc_device_data *data; - int retval = -ENODEV; + int retval = 0; intf = usb_find_interface(&usbtmc_driver, iminor(inode)); if (!intf) { printk(KERN_ERR KBUILD_MODNAME ": can not find device for minor %d", iminor(inode)); + retval = -ENODEV; goto exit; } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 7513bb083c1..6585f527e38 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -359,11 +359,6 @@ static void destroy_async(struct dev_state *ps, struct list_head *list) spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); - as = async_getcompleted(ps); - while (as) { - free_async(as); - as = async_getcompleted(ps); - } } static void destroy_async_on_interface(struct dev_state *ps, @@ -643,6 +638,7 @@ static int usbdev_release(struct inode *inode, struct file *file) struct dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; unsigned int ifnum; + struct async *as; usb_lock_device(dev); @@ -661,6 +657,12 @@ static int usbdev_release(struct inode *inode, struct file *file) usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); + + as = async_getcompleted(ps); + while (as) { + free_async(as); + as = async_getcompleted(ps); + } kfree(ps); return 0; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 31fb204f44c..49e7f56e0d7 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, if (result <= 0 && result != -ETIMEDOUT) continue; if (result > 1 && ((u8 *)buf)[1] != type) { - result = -EPROTO; + result = -ENODATA; continue; } break; @@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (USB_DT_STRING << 8) + index, langid, buf, size, USB_CTRL_GET_TIMEOUT); - if (!(result == 0 || result == -EPIPE)) - break; + if (result == 0 || result == -EPIPE) + continue; + if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) { + result = -ENODATA; + continue; + } + break; } return result; } diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 3219d137340..e55fef52a5d 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -191,6 +191,7 @@ config USB_GADGET_OMAP boolean "OMAP USB Device Controller" depends on ARCH_OMAP select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG + select USB_OTG_UTILS if ARCH_OMAP help Many Texas Instruments OMAP processors have flexible full speed USB device controllers, with support for up to 30 diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 80c2e7e9622..38aa896cc5d 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -366,9 +366,9 @@ obex_bind(struct usb_configuration *c, struct usb_function *f) f->hs_descriptors = usb_copy_descriptors(hs_function); obex->hs.obex_in = usb_find_endpoint(hs_function, - f->descriptors, &obex_hs_ep_in_desc); + f->hs_descriptors, &obex_hs_ep_in_desc); obex->hs.obex_out = usb_find_endpoint(hs_function, - f->descriptors, &obex_hs_ep_out_desc); + f->hs_descriptors, &obex_hs_ep_out_desc); } /* Avoid letting this gadget enumerate until the userspace diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index b10fa31cc91..1ab9dac7e12 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3879,7 +3879,11 @@ static int __init check_parameters(struct fsg_dev *fsg) mod_data.protocol_type = USB_SC_SCSI; mod_data.protocol_name = "Transparent SCSI"; - if (gadget_is_sh(fsg->gadget)) + /* Some peripheral controllers are known not to be able to + * halt bulk endpoints correctly. If one of them is present, + * disable stalls. + */ + if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget)) mod_data.can_stall = 0; if (mod_data.release == 0xffff) { // Parameter wasn't set diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index f3c6703cffd..d8d9a52a44b 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -404,7 +404,10 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num, } if (zlt) tmp |= EP_QUEUE_HEAD_ZLT_SEL; + p_QH->max_pkt_length = cpu_to_le32(tmp); + p_QH->next_dtd_ptr = 1; + p_QH->size_ioc_int_sts = 0; return; } diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4725d15d096..e551bb38852 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -485,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd) * periodic_size can shrink by USBCMD update if hcc_params allows. */ ehci->periodic_size = DEFAULT_I_TDPS; + INIT_LIST_HEAD(&ehci->cached_itd_list); if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) return retval; @@ -497,6 +498,7 @@ static int ehci_init(struct usb_hcd *hcd) ehci->reclaim = NULL; ehci->next_uframe = -1; + ehci->clock_frame = -1; /* * dedicate a qh for the async ring head, since we couldn't unlink diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 0431397836f..10d52919abb 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh) static void ehci_mem_cleanup (struct ehci_hcd *ehci) { + free_cached_itd_list(ehci); if (ehci->async) qh_put (ehci->async); ehci->async = NULL; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3712b925b31..ecc9b66c03c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1095,7 +1095,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) prev->qh_next = qh->qh_next; wmb (); - if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { /* if (unlikely (qh->reclaim != 0)) * this will recurse, probably not much */ diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a081ee65bde..1d0b49e3f19 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; stream->bEndpointAddress &= 0x0f; - stream->ep->hcpriv = NULL; + if (stream->ep) + stream->ep->hcpriv = NULL; if (stream->rescheduled) { ehci_info (ehci, "ep%d%s-iso rescheduled " @@ -1535,7 +1536,7 @@ itd_link_urb ( struct ehci_itd, itd_list); list_move_tail (&itd->itd_list, &stream->td_list); itd->stream = iso_stream_get (stream); - itd->urb = usb_get_urb (urb); + itd->urb = urb; itd_init (ehci, stream, itd); } @@ -1644,7 +1645,7 @@ itd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (unlikely (list_empty (&stream->td_list))) { + if (unlikely(list_is_singular(&stream->td_list))) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -1653,14 +1654,27 @@ itd_complete ( (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); } iso_stream_put (ehci, stream); - /* OK to recycle this ITD now that its completion callback ran. */ + done: - usb_put_urb(urb); itd->urb = NULL; - itd->stream = NULL; - list_move(&itd->itd_list, &stream->free_list); - iso_stream_put(ehci, stream); - + if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { + /* OK to recycle this ITD now. */ + itd->stream = NULL; + list_move(&itd->itd_list, &stream->free_list); + iso_stream_put(ehci, stream); + } else { + /* HW might remember this ITD, so we can't recycle it yet. + * Move it to a safe place until a new frame starts. + */ + list_move(&itd->itd_list, &ehci->cached_itd_list); + if (stream->refcount == 2) { + /* If iso_stream_put() were called here, stream + * would be freed. Instead, just prevent reuse. + */ + stream->ep->hcpriv = NULL; + stream->ep = NULL; + } + } return retval; } @@ -1934,7 +1948,7 @@ sitd_link_urb ( struct ehci_sitd, sitd_list); list_move_tail (&sitd->sitd_list, &stream->td_list); sitd->stream = iso_stream_get (stream); - sitd->urb = usb_get_urb (urb); + sitd->urb = urb; sitd_patch(ehci, stream, sitd, sched, packet); sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, @@ -2019,7 +2033,7 @@ sitd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (list_empty (&stream->td_list)) { + if (list_is_singular(&stream->td_list)) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -2030,7 +2044,6 @@ sitd_complete ( iso_stream_put (ehci, stream); /* OK to recycle this SITD now that its completion callback ran. */ done: - usb_put_urb(urb); sitd->urb = NULL; sitd->stream = NULL; list_move(&sitd->sitd_list, &stream->free_list); @@ -2101,6 +2114,20 @@ done: /*-------------------------------------------------------------------------*/ +static void free_cached_itd_list(struct ehci_hcd *ehci) +{ + struct ehci_itd *itd, *n; + + list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { + struct ehci_iso_stream *stream = itd->stream; + itd->stream = NULL; + list_move(&itd->itd_list, &stream->free_list); + iso_stream_put(ehci, stream); + } +} + +/*-------------------------------------------------------------------------*/ + static void scan_periodic (struct ehci_hcd *ehci) { @@ -2115,10 +2142,17 @@ scan_periodic (struct ehci_hcd *ehci) * Touches as few pages as possible: cache-friendly. */ now_uframe = ehci->next_uframe; - if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) + if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { clock = ehci_readl(ehci, &ehci->regs->frame_index); - else + clock_frame = (clock >> 3) % ehci->periodic_size; + } else { clock = now_uframe + mod - 1; + clock_frame = -1; + } + if (ehci->clock_frame != clock_frame) { + free_cached_itd_list(ehci); + ehci->clock_frame = clock_frame; + } clock %= mod; clock_frame = clock >> 3; @@ -2277,6 +2311,10 @@ restart: /* rescan the rest of this frame, then ... */ clock = now; clock_frame = clock >> 3; + if (ehci->clock_frame != clock_frame) { + free_cached_itd_list(ehci); + ehci->clock_frame = clock_frame; + } } else { now_uframe++; now_uframe %= mod; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index fb7054ccf4f..262b00c9b33 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -87,6 +87,10 @@ struct ehci_hcd { /* one per controller */ int next_uframe; /* scan periodic, start here */ unsigned periodic_sched; /* periodic activity count */ + /* list of itds completed while clock_frame was still active */ + struct list_head cached_itd_list; + unsigned clock_frame; + /* per root hub port */ unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; @@ -220,6 +224,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) } } +static void free_cached_itd_list(struct ehci_hcd *ehci); + /*-------------------------------------------------------------------------*/ #include <linux/usb/ehci_def.h> diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 878c77ca086..972f20b3406 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -499,6 +499,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, retval = usb_register_dev(intf, &mdc800_class); if (retval) { dev_err(&intf->dev, "Not able to get a minor for this device.\n"); + mutex_unlock(&mdc800->io_lock); return -ENODEV; } diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 7b6922e08ed..20352654201 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -376,7 +376,7 @@ static int adu_release(struct inode *inode, struct file *file) if (dev->open_count <= 0) { dbg(1," %s : device not opened", __func__); retval = -ENODEV; - goto exit; + goto unlock; } adu_release_internal(dev); @@ -385,9 +385,9 @@ static int adu_release(struct inode *inode, struct file *file) if (!dev->open_count) /* ... and we're the last user */ adu_delete(dev); } - -exit: +unlock: mutex_unlock(&adutux_mutex); +exit: dbg(2," %s : leave, return value %d", __func__, retval); return retval; } diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c index 63dff9ba73c..f26ea8dc157 100644 --- a/drivers/usb/misc/vstusb.c +++ b/drivers/usb/misc/vstusb.c @@ -401,6 +401,7 @@ static ssize_t vstusb_write(struct file *file, const char __user *buffer, } if (copy_from_user(buf, buffer, count)) { + mutex_unlock(&vstdev->lock); dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__); retval = -EFAULT; goto exit; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 5a8fd5d57a1..2dc7606f319 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -377,18 +377,8 @@ int __init musb_platform_init(struct musb *musb) u32 revision; musb->mregs += DAVINCI_BASE_OFFSET; -#if 0 - /* REVISIT there's something odd about clocking, this - * didn't appear do the job ... - */ - musb->clock = clk_get(pDevice, "usb"); - if (IS_ERR(musb->clock)) - return PTR_ERR(musb->clock); - status = clk_enable(musb->clock); - if (status < 0) - return -ENODEV; -#endif + clk_enable(musb->clock); /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); @@ -453,5 +443,8 @@ int musb_platform_exit(struct musb *musb) } phy_off(); + + clk_disable(musb->clock); + return 0; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 2cc34fa05b7..af77e465900 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -115,7 +115,7 @@ unsigned musb_debug; -module_param(musb_debug, uint, S_IRUGO | S_IWUSR); +module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" @@ -767,6 +767,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, #ifdef CONFIG_USB_MUSB_HDRC_HCD case OTG_STATE_A_HOST: case OTG_STATE_A_SUSPEND: + usb_hcd_resume_root_hub(musb_to_hcd(musb)); musb_root_disconnect(musb); if (musb->a_wait_bcon != 0) musb_platform_try_idle(musb, jiffies @@ -1815,7 +1816,7 @@ static void musb_free(struct musb *musb) #ifdef CONFIG_SYSFS device_remove_file(musb->controller, &dev_attr_mode); device_remove_file(musb->controller, &dev_attr_vbus); -#ifdef CONFIG_USB_MUSB_OTG +#ifdef CONFIG_USB_GADGET_MUSB_HDRC device_remove_file(musb->controller, &dev_attr_srp); #endif #endif @@ -2063,7 +2064,7 @@ fail2: #ifdef CONFIG_SYSFS device_remove_file(musb->controller, &dev_attr_mode); device_remove_file(musb->controller, &dev_attr_vbus); -#ifdef CONFIG_USB_MUSB_OTG +#ifdef CONFIG_USB_GADGET_MUSB_HDRC device_remove_file(musb->controller, &dev_attr_srp); #endif #endif @@ -2243,10 +2244,10 @@ static int __init musb_init(void) return platform_driver_probe(&musb_driver, musb_probe); } -/* make us init after usbcore and before usb - * gadget and host-side drivers start to register +/* make us init after usbcore and i2c (transceivers, regulators, etc) + * and before usb gadget and host-side drivers start to register */ -subsys_initcall(musb_init); +fs_initcall(musb_init); static void __exit musb_cleanup(void) { diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 4ea30538798..c7ebd0867fc 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -575,7 +575,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) struct usb_request *request = &req->request; struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; void __iomem *epio = musb->endpoints[epnum].regs; - u16 fifo_count = 0; + unsigned fifo_count = 0; u16 len = musb_ep->packet_sz; csr = musb_readw(epio, MUSB_RXCSR); @@ -687,7 +687,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) len, fifo_count, musb_ep->packet_sz); - fifo_count = min(len, fifo_count); + fifo_count = min_t(unsigned, len, fifo_count); #ifdef CONFIG_USB_TUSB_OMAP_DMA if (tusb_dma_omap() && musb_ep->dma) { diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index a035ceccf95..6dbbd0786a6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -335,16 +335,11 @@ musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb) static struct musb_qh * musb_giveback(struct musb_qh *qh, struct urb *urb, int status) { - int is_in; struct musb_hw_ep *ep = qh->hw_ep; struct musb *musb = ep->musb; + int is_in = usb_pipein(urb->pipe); int ready = qh->is_ready; - if (ep->is_shared_fifo) - is_in = 1; - else - is_in = usb_pipein(urb->pipe); - /* save toggle eagerly, for paranoia */ switch (qh->type) { case USB_ENDPOINT_XFER_BULK: @@ -432,7 +427,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb, else qh = musb_giveback(qh, urb, urb->status); - if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) { + if (qh != NULL && qh->is_ready) { DBG(4, "... next ep%d %cX urb %p\n", hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh)); @@ -942,8 +937,8 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) switch (musb->ep0_stage) { case MUSB_EP0_IN: fifo_dest = urb->transfer_buffer + urb->actual_length; - fifo_count = min(len, ((u16) (urb->transfer_buffer_length - - urb->actual_length))); + fifo_count = min_t(size_t, len, urb->transfer_buffer_length - + urb->actual_length); if (fifo_count < len) urb->status = -EOVERFLOW; @@ -976,10 +971,9 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) } /* FALLTHROUGH */ case MUSB_EP0_OUT: - fifo_count = min(qh->maxpacket, ((u16) - (urb->transfer_buffer_length - - urb->actual_length))); - + fifo_count = min_t(size_t, qh->maxpacket, + urb->transfer_buffer_length - + urb->actual_length); if (fifo_count) { fifo_dest = (u8 *) (urb->transfer_buffer + urb->actual_length); @@ -1161,7 +1155,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) struct urb *urb; struct musb_hw_ep *hw_ep = musb->endpoints + epnum; void __iomem *epio = hw_ep->regs; - struct musb_qh *qh = hw_ep->out_qh; + struct musb_qh *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh + : hw_ep->out_qh; u32 status = 0; void __iomem *mbase = musb->mregs; struct dma_channel *dma; @@ -1308,7 +1303,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) * packets before updating TXCSR ... other docs disagree ... */ /* PIO: start next packet in this URB */ - wLength = min(qh->maxpacket, (u16) wLength); + if (wLength > qh->maxpacket) + wLength = qh->maxpacket; musb_write_fifo(hw_ep, wLength, buf); qh->segsize = wLength; @@ -1867,19 +1863,21 @@ static int musb_urb_enqueue( } qh->type_reg = type_reg; - /* precompute rxinterval/txinterval register */ - interval = min((u8)16, epd->bInterval); /* log encoding */ + /* Precompute RXINTERVAL/TXINTERVAL register */ switch (qh->type) { case USB_ENDPOINT_XFER_INT: - /* fullspeed uses linear encoding */ - if (USB_SPEED_FULL == urb->dev->speed) { - interval = epd->bInterval; - if (!interval) - interval = 1; + /* + * Full/low speeds use the linear encoding, + * high speed uses the logarithmic encoding. + */ + if (urb->dev->speed <= USB_SPEED_FULL) { + interval = max_t(u8, epd->bInterval, 1); + break; } /* FALLTHROUGH */ case USB_ENDPOINT_XFER_ISOC: - /* iso always uses log encoding */ + /* ISO always uses logarithmic encoding */ + interval = min_t(u8, epd->bInterval, 16); break; default: /* REVISIT we actually want to use NAK limits, hinting to the @@ -2037,9 +2035,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto done; /* Any URB not actively programmed into endpoint hardware can be - * immediately given back. Such an URB must be at the head of its + * immediately given back; that's any URB not at the head of an * endpoint queue, unless someday we get real DMA queues. And even - * then, it might not be known to the hardware... + * if it's at the head, it might not be known to the hardware... * * Otherwise abort current transfer, pending dma, etc.; urb->status * has already been updated. This is a synchronous abort; it'd be @@ -2078,6 +2076,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) qh->is_ready = 0; __musb_giveback(musb, urb, 0); qh->is_ready = ready; + + /* If nothing else (usually musb_giveback) is using it + * and its URB list has emptied, recycle this qh. + */ + if (ready && list_empty(&qh->hep->urb_list)) { + qh->hep->hcpriv = NULL; + list_del(&qh->ring); + kfree(qh); + } } else ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); done: @@ -2093,15 +2100,16 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) unsigned long flags; struct musb *musb = hcd_to_musb(hcd); u8 is_in = epnum & USB_DIR_IN; - struct musb_qh *qh = hep->hcpriv; - struct urb *urb, *tmp; + struct musb_qh *qh; + struct urb *urb; struct list_head *sched; - if (!qh) - return; - spin_lock_irqsave(&musb->lock, flags); + qh = hep->hcpriv; + if (qh == NULL) + goto exit; + switch (qh->type) { case USB_ENDPOINT_XFER_CONTROL: sched = &musb->control; @@ -2135,13 +2143,28 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) /* cleanup */ musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); - } else - urb = NULL; - /* then just nuke all the others */ - list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list) - musb_giveback(qh, urb, -ESHUTDOWN); + /* Then nuke all the others ... and advance the + * queue on hw_ep (e.g. bulk ring) when we're done. + */ + while (!list_empty(&hep->urb_list)) { + urb = next_urb(qh); + urb->status = -ESHUTDOWN; + musb_advance_schedule(musb, urb, qh->hw_ep, is_in); + } + } else { + /* Just empty the queue; the hardware is busy with + * other transfers, and since !qh->is_ready nothing + * will activate any of these as it advances. + */ + while (!list_empty(&hep->urb_list)) + __musb_giveback(musb, next_urb(qh), -ESHUTDOWN); + hep->hcpriv = NULL; + list_del(&qh->ring); + kfree(qh); + } +exit: spin_unlock_irqrestore(&musb->lock, flags); } diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 027f4b7dde8..9b4082b58c5 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -79,6 +79,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f92f4d77337..ae84c326a54 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -663,6 +663,11 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, + { USB_DEVICE(ATMEL_VID, STK541_PID) }, + { USB_DEVICE(DE_VID, STB_PID) }, + { USB_DEVICE(DE_VID, WHT_PID) }, + { USB_DEVICE(ADI_VID, ADI_GNICE_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index e300c840f8c..daaf63db0b5 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -893,6 +893,26 @@ #define DIEBOLD_BCS_SE923_PID 0xfb99 /* + * Atmel STK541 + */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Dresden Elektronic Sensor Terminal Board + */ +#define DE_VID 0x1cf1 /* Vendor ID */ +#define STB_PID 0x0001 /* Sensor Terminal Board */ +#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ + +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 + +/* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ * wValue: 0 diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index bfd0b68cecc..61ebddc4849 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -89,6 +89,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041 #define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061 #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 +#define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E600 0x1001 @@ -197,6 +198,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* OVATION PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 +#define NOVATELWIRELESS_PRODUCT_U727 0x5010 /* FUTURE NOVATEL PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0X6000 @@ -288,13 +290,13 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 +#define ZTE_PRODUCT_MF622 0x0001 #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe -/* Ericsson products */ -#define ERICSSON_VENDOR_ID 0x0bdb -#define ERICSSON_PRODUCT_F3507G 0x1900 +#define BENQ_VENDOR_ID 0x04a5 +#define BENQ_PRODUCT_H10 0x4068 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, @@ -321,6 +323,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTM380_MODEM) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, @@ -411,6 +414,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, /* Novatel EVDO product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ @@ -438,7 +442,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ - { USB_DEVICE(DELL_VENDOR_ID, 0x8147) }, /* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ @@ -506,10 +509,12 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, + { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, + { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 50dc33a6065..cfde74a6faa 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -226,7 +226,7 @@ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0610, US_FL_MAX_SECTORS_64 ), /* Reported by Manuel Osdoba <manuel.osdoba@tu-ilmenau.de> */ -UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452, +UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999, "Nokia", "Nokia 6233", US_SC_DEVICE, US_PR_DEVICE, NULL, @@ -907,13 +907,13 @@ UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, "Genesys Logic", "USB to IDE Optical", US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), + US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ), UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, "Genesys Logic", "USB to IDE Disk", US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), + US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ), /* Reported by Ben Efros <ben@pc-doctor.com> */ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, @@ -951,7 +951,9 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, US_FL_FIX_CAPACITY ), /* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */ -UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100, +/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by + * Thomas Bartosik <tbartdev@gmx-topmail.de> */ +UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100, "Prolific Technology Inc.", "Mass Storage Device", US_SC_DEVICE, US_PR_DEVICE, NULL, @@ -1390,6 +1392,16 @@ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, 0 ), +/* Reported by Jan Dumon <j.dumon@option.com> + * This device (wrongly) has a vendor-specific device descriptor. + * The entry is needed so usb-storage can bind to it's mass-storage + * interface as an interface driver */ +UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000, + "Option", + "GI 0431 SD-Card", + US_SC_DEVICE, US_PR_DEVICE, NULL, + 0 ), + /* Reported by Ben Efros <ben@pc-doctor.com> */ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, "Seagate", diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 238a96aee3a..613a5fc490d 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -921,8 +921,10 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer) result = -ENODEV; /* FIXME: segmentation broken -- kills DWA */ mutex_lock(&wusbhc->mutex); /* get a WUSB dev */ - if (urb->dev == NULL) + if (urb->dev == NULL) { + mutex_unlock(&wusbhc->mutex); goto error_dev_gone; + } wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); if (wusb_dev == NULL) { mutex_unlock(&wusbhc->mutex); diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 2181ce4d7eb..35e8eb02b9e 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1853,13 +1853,14 @@ static void aty128_bl_exit(struct backlight_device *bd) * Initialisation */ -#ifdef CONFIG_PPC_PMAC +#ifdef CONFIG_PPC_PMAC__disabled static void aty128_early_resume(void *data) { struct aty128fb_par *par = data; if (try_acquire_console_sem()) return; + pci_restore_state(par->pdev); aty128_do_resume(par->pdev); release_console_sem(); } @@ -1907,7 +1908,14 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(aty128_early_resume, par); +#endif } /* Find default mode */ diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index ca5f0dc2854..c6d7cc76516 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2507,6 +2507,25 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) #endif /* CONFIG_PPC_OF */ +static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state) +{ + u16 pwr_cmd; + + for (;;) { + pci_read_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + &pwr_cmd); + if (pwr_cmd & 2) + break; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2; + pci_write_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + pwr_cmd); + msleep(500); + } + rinfo->pdev->current_state = state; +} + static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { u32 tmp; @@ -2558,6 +2577,11 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) /* Switch PCI power management to D2. */ pci_disable_device(rinfo->pdev); pci_save_state(rinfo->pdev); + /* The chip seems to need us to whack the PM register + * repeatedly until it sticks. We do that -prior- to + * calling pci_set_power_state() + */ + radeonfb_whack_power_state(rinfo, PCI_D2); pci_set_power_state(rinfo->pdev, PCI_D2); } else { printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", @@ -2762,12 +2786,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) return rc; } -#ifdef CONFIG_PPC_OF +#ifdef CONFIG_PPC_OF__disabled static void radeonfb_early_resume(void *data) { struct radeonfb_info *rinfo = data; rinfo->no_schedule = 1; + pci_restore_state(rinfo->pdev); radeonfb_pci_resume(rinfo->pdev); rinfo->no_schedule = 0; } @@ -2834,7 +2859,14 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis */ if (rinfo->pm_mode != radeon_pm_none) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(radeonfb_early_resume, rinfo); +#endif } #if 0 diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index a24e680d2b9..2e940199fc8 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -993,6 +993,7 @@ static int i810_check_params(struct fb_var_screeninfo *var, struct i810fb_par *par = info->par; int line_length, vidmem, mode_valid = 0, retval = 0; u32 vyres = var->yres_virtual, vxres = var->xres_virtual; + /* * Memory limit */ @@ -1002,12 +1003,12 @@ static int i810_check_params(struct fb_var_screeninfo *var, if (vidmem > par->fb.size) { vyres = par->fb.size/line_length; if (vyres < var->yres) { - vyres = yres; + vyres = info->var.yres; vxres = par->fb.size/vyres; vxres /= var->bits_per_pixel >> 3; line_length = get_line_length(par, vxres, var->bits_per_pixel); - vidmem = line_length * yres; + vidmem = line_length * info->var.yres; if (vxres < var->xres) { printk("i810fb: required video memory, " "%d bytes, for %dx%d-%d (virtual) " diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm index 3c14e43b82f..de93ff3fc1a 100644 --- a/drivers/video/logo/logo_linux_clut224.ppm +++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,2828 @@ P3 -# Standard 224-color Linux logo -80 80 +145 113 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 10 10 10 10 10 10 - 10 10 10 6 6 6 6 6 6 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 22 22 22 26 26 26 30 30 30 34 34 34 - 30 30 30 30 30 30 26 26 26 18 18 18 - 14 14 14 10 10 10 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 26 26 26 42 42 42 - 54 54 54 66 66 66 78 78 78 78 78 78 - 78 78 78 74 74 74 66 66 66 54 54 54 - 42 42 42 26 26 26 18 18 18 10 10 10 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 22 22 22 42 42 42 66 66 66 86 86 86 - 66 66 66 38 38 38 38 38 38 22 22 22 - 26 26 26 34 34 34 54 54 54 66 66 66 - 86 86 86 70 70 70 46 46 46 26 26 26 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 50 50 50 82 82 82 58 58 58 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 54 54 54 86 86 86 66 66 66 - 38 38 38 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 78 78 78 34 34 34 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 70 70 70 - 78 78 78 46 46 46 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 42 42 42 82 82 82 - 26 26 26 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 46 46 46 34 34 34 6 6 6 2 2 6 - 42 42 42 78 78 78 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 30 30 30 66 66 66 58 58 58 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 86 86 86 101 101 101 46 46 46 10 10 10 - 2 2 6 58 58 58 70 70 70 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 86 86 86 10 10 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 30 30 30 - 94 94 94 94 94 94 58 58 58 26 26 26 - 2 2 6 6 6 6 78 78 78 54 54 54 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 62 62 62 62 62 62 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 54 54 54 38 38 38 18 18 18 10 10 10 - 2 2 6 2 2 6 34 34 34 82 82 82 - 38 38 38 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 10 10 10 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 54 54 54 - 66 66 66 26 26 26 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 82 82 82 2 2 6 2 2 6 - 2 2 6 6 6 6 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 6 6 6 - 14 14 14 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 18 18 18 - 82 82 82 34 34 34 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 6 6 6 6 6 6 22 22 22 34 34 34 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 34 34 34 - 10 10 10 50 50 50 22 22 22 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 86 86 86 42 42 42 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 38 38 38 116 116 116 94 94 94 22 22 22 - 22 22 22 2 2 6 2 2 6 2 2 6 - 14 14 14 86 86 86 138 138 138 162 162 162 -154 154 154 38 38 38 26 26 26 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 14 14 14 -134 134 134 198 198 198 195 195 195 116 116 116 - 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 -214 214 214 134 134 134 14 14 14 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 50 50 50 18 18 18 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 - 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 174 174 174 123 123 123 -221 221 221 234 234 234 74 74 74 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 -123 123 123 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 - 90 90 90 238 238 238 158 158 158 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 149 149 149 -128 128 128 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 - 46 46 46 190 190 190 198 198 198 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 94 94 94 14 14 14 101 101 101 -128 128 128 2 2 6 18 18 18 116 116 116 -118 98 46 121 92 8 121 92 8 98 78 10 -162 162 162 106 106 106 2 2 6 2 2 6 - 2 2 6 195 195 195 195 195 195 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 1 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 54 38 6 154 114 10 -226 170 11 236 186 11 225 175 15 184 144 12 -215 174 15 175 146 61 37 26 9 2 2 6 - 70 70 70 246 246 246 138 138 138 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 66 66 66 26 26 26 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 188 164 115 192 133 9 225 175 15 -239 182 13 234 190 10 232 195 16 232 200 30 -245 207 45 241 208 19 232 195 16 184 144 12 -218 194 134 211 206 186 42 42 42 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 74 74 74 30 30 30 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 86 86 86 14 14 14 2 2 6 -121 87 25 192 133 9 219 162 10 239 182 13 -236 186 11 232 195 16 241 208 19 244 214 54 -246 218 60 246 218 38 246 215 20 241 208 19 -241 208 19 226 184 13 121 87 25 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 82 82 82 34 34 34 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 82 82 82 30 30 30 61 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 -234 190 10 238 202 15 241 208 19 246 218 74 -246 218 38 246 215 20 246 215 20 246 215 20 -226 184 13 215 174 15 184 144 12 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 26 26 26 94 94 94 42 42 42 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 236 186 11 -232 195 16 241 208 19 244 214 54 245 215 43 -246 215 20 246 215 20 241 208 19 198 155 10 -200 144 11 216 158 10 156 118 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 90 90 90 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 210 162 10 239 182 13 238 190 10 -238 202 15 241 208 19 246 215 20 246 215 20 -241 208 19 203 166 17 185 133 11 210 150 10 -216 158 10 210 150 10 102 78 10 2 2 6 - 6 6 6 54 54 54 14 14 14 2 2 6 - 2 2 6 62 62 62 74 74 74 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 78 78 78 50 50 50 6 6 6 - 94 70 30 139 102 15 190 146 13 226 184 13 -232 200 30 232 195 16 215 174 15 190 146 13 -168 122 10 192 133 9 210 150 10 213 154 11 -202 150 34 182 157 106 101 98 89 2 2 6 - 2 2 6 78 78 78 116 116 116 58 58 58 - 2 2 6 22 22 22 90 90 90 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 50 50 50 6 6 6 -128 128 128 174 154 114 156 107 11 168 122 10 -198 155 10 184 144 12 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 188 164 115 -195 195 195 198 198 198 174 174 174 14 14 14 - 2 2 6 22 22 22 116 116 116 116 116 116 - 22 22 22 2 2 6 74 74 74 70 70 70 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 101 101 101 26 26 26 10 10 10 -138 138 138 190 190 190 174 154 114 156 107 11 -197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 190 142 34 190 178 144 187 187 187 -202 202 202 221 221 221 214 214 214 66 66 66 - 2 2 6 2 2 6 50 50 50 62 62 62 - 6 6 6 2 2 6 10 10 10 90 90 90 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 34 34 34 - 74 74 74 74 74 74 2 2 6 6 6 6 -144 144 144 198 198 198 190 190 190 178 166 146 -154 121 60 156 107 11 156 107 11 168 124 44 -174 154 114 187 187 187 190 190 190 210 210 210 -246 246 246 253 253 253 253 253 253 182 182 182 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 62 62 62 - 74 74 74 34 34 34 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 22 22 22 54 54 54 - 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 -190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 - 82 82 82 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 86 86 86 54 54 54 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 46 46 46 90 90 90 - 46 46 46 18 18 18 6 6 6 182 182 182 -253 253 253 246 246 246 206 206 206 190 190 190 -190 190 190 190 190 190 190 190 190 190 190 190 -206 206 206 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 86 86 86 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 38 38 38 74 74 74 66 66 66 - 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 -190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 78 78 78 70 70 70 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 66 66 66 78 78 78 6 6 6 - 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 178 178 178 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 18 18 18 90 90 90 62 62 62 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 58 58 58 90 90 90 18 18 18 2 2 6 - 2 2 6 110 110 110 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 94 94 94 - 54 54 54 26 26 26 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 90 90 90 26 26 26 2 2 6 2 2 6 - 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 86 86 86 50 50 50 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 38 38 38 82 82 82 - 34 34 34 2 2 6 2 2 6 2 2 6 - 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 38 38 38 82 82 82 42 42 42 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 62 62 62 66 66 66 - 2 2 6 2 2 6 2 2 6 6 6 6 - 70 70 70 170 170 170 206 206 206 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 -226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 -214 214 214 206 206 206 202 202 202 202 202 202 -198 198 198 202 202 202 182 182 182 18 18 18 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 62 62 62 66 66 66 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 82 82 82 18 18 18 - 2 2 6 2 2 6 2 2 6 10 10 10 - 94 94 94 182 182 182 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 -234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 158 158 158 - 6 6 6 14 14 14 50 50 50 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 86 86 86 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 70 70 70 2 2 6 - 2 2 6 10 10 10 2 2 6 22 22 22 -166 166 166 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 206 206 206 198 198 198 226 226 226 - 94 94 94 2 2 6 6 6 6 38 38 38 - 30 30 30 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 62 62 62 66 66 66 - 26 26 26 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 50 50 50 2 2 6 - 26 26 26 26 26 26 2 2 6 106 106 106 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 -210 210 210 14 14 14 2 2 6 2 2 6 - 30 30 30 22 22 22 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 86 86 86 - 42 42 42 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 90 90 90 22 22 22 2 2 6 - 42 42 42 2 2 6 18 18 18 218 218 218 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 -218 218 218 101 101 101 2 2 6 14 14 14 - 18 18 18 38 38 38 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 58 58 58 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 82 82 82 2 2 6 26 26 26 - 22 22 22 2 2 6 123 123 123 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -238 238 238 198 198 198 6 6 6 38 38 38 - 58 58 58 26 26 26 38 38 38 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 78 78 78 30 30 30 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 30 30 30 - 74 74 74 58 58 58 2 2 6 42 42 42 - 2 2 6 22 22 22 231 231 231 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 46 46 46 38 38 38 - 42 42 42 14 14 14 38 38 38 14 14 14 - 2 2 6 2 2 6 2 2 6 6 6 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 42 42 42 - 90 90 90 18 18 18 18 18 18 26 26 26 - 2 2 6 116 116 116 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 94 94 94 6 6 6 - 2 2 6 2 2 6 10 10 10 34 34 34 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 26 26 26 66 66 66 - 82 82 82 2 2 6 38 38 38 6 6 6 - 14 14 14 210 210 210 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 144 144 144 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 74 74 74 30 30 30 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 42 42 42 90 90 90 - 26 26 26 6 6 6 42 42 42 2 2 6 - 74 74 74 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 182 182 182 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 10 10 10 86 86 86 38 38 38 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 66 66 66 82 82 82 - 2 2 6 22 22 22 18 18 18 2 2 6 -149 149 149 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 86 86 86 46 46 46 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 46 46 46 86 86 86 18 18 18 - 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 221 221 221 6 6 6 - 2 2 6 2 2 6 6 6 6 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 26 26 26 66 66 66 62 62 62 2 2 6 - 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 6 6 6 - 2 2 6 2 2 6 10 10 10 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 78 78 78 6 6 6 2 2 6 - 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 10 10 10 - 2 2 6 2 2 6 22 22 22 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 74 74 74 2 2 6 2 2 6 - 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 14 14 14 - 2 2 6 2 2 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 62 62 62 2 2 6 2 2 6 - 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 226 226 226 10 10 10 - 2 2 6 6 6 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 62 62 62 2 2 6 2 2 6 - 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 22 22 22 34 34 34 18 14 6 22 22 22 - 26 26 26 18 18 18 6 6 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 26 26 26 - 62 62 62 106 106 106 74 54 14 185 133 11 -210 162 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 158 158 158 18 18 18 - 14 14 14 2 2 6 2 2 6 2 2 6 - 6 6 6 18 18 18 66 66 66 38 38 38 - 6 6 6 94 94 94 50 50 50 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 10 10 10 10 10 10 18 18 18 38 38 38 - 78 78 78 142 134 106 216 158 10 242 186 14 -246 190 14 246 190 14 156 118 10 10 10 10 - 90 90 90 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 -238 204 91 238 204 91 181 142 44 37 26 9 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 38 38 38 46 46 46 - 26 26 26 106 106 106 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 22 22 22 - 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 190 142 34 226 170 11 242 186 14 -246 190 14 246 190 14 246 190 14 154 114 10 - 6 6 6 74 74 74 226 226 226 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 228 184 62 -241 196 14 241 208 19 232 195 16 38 30 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 30 30 30 26 26 26 -203 166 17 154 142 90 66 66 66 26 26 26 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 38 38 38 58 58 58 - 78 78 78 86 86 86 101 101 101 123 123 123 -175 146 61 210 150 10 234 174 13 246 186 14 -246 190 14 246 190 14 246 190 14 238 190 10 -102 78 10 2 2 6 46 46 46 198 198 198 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 224 178 62 -242 186 14 241 196 14 210 166 10 22 18 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 38 38 38 70 70 70 154 122 46 -190 142 34 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -225 175 15 46 32 6 2 2 6 22 22 22 -158 158 158 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 224 178 62 -239 182 13 236 186 11 213 154 11 46 32 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 225 175 15 -238 190 10 236 186 11 112 100 78 42 42 42 - 14 14 14 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 154 122 46 213 154 11 -226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 144 12 10 10 10 2 2 6 - 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 214 170 54 -236 178 12 236 178 12 210 150 10 137 92 6 - 18 14 6 2 2 6 2 2 6 2 2 6 - 6 6 6 70 47 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 70 70 70 180 133 36 226 170 11 -239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 - 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 206 206 206 198 198 198 214 166 58 -230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 116 81 8 102 78 10 116 81 8 -167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 162 146 94 78 78 78 - 34 34 34 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 190 142 34 226 170 11 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 203 166 17 22 18 6 - 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 206 206 206 198 198 198 202 162 69 -226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 -210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 225 175 15 124 112 88 - 62 62 62 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 174 135 50 224 166 10 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 - 2 2 6 2 2 6 2 2 6 2 2 6 - 78 78 78 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 190 150 46 -219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 -226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 206 162 42 -101 101 101 58 58 58 30 30 30 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 174 135 50 216 158 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 226 184 13 - 61 42 6 2 2 6 2 2 6 2 2 6 - 22 22 22 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 180 133 36 -216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 -206 162 42 106 106 106 66 66 66 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 213 154 11 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 -190 146 13 18 14 6 2 2 6 2 2 6 - 46 46 46 246 246 246 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 -216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 225 175 15 142 122 72 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 210 150 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 18 14 6 163 110 8 -216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 163 133 67 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 163 133 67 210 150 10 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 215 174 15 190 178 144 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 218 218 218 - 58 58 58 2 2 6 22 18 6 167 114 7 -216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 186 14 242 186 14 190 150 46 - 54 54 54 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 38 38 38 86 86 86 180 133 36 213 154 11 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 170 170 170 26 26 26 - 2 2 6 2 2 6 37 26 9 163 110 8 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 224 166 10 142 122 72 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 109 106 95 192 133 9 224 166 10 -242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 226 184 13 210 162 10 142 110 46 -226 226 226 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -198 198 198 66 66 66 2 2 6 2 2 6 - 2 2 6 2 2 6 50 34 6 156 107 11 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 -234 174 13 213 154 11 154 122 46 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 154 121 60 206 145 10 234 174 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 210 162 10 163 110 8 - 61 42 6 138 138 138 218 218 218 250 250 250 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 144 144 144 66 66 66 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 163 110 8 -216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 -190 142 34 124 112 88 70 70 70 38 38 38 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 62 62 62 168 124 44 206 145 10 224 166 10 -236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 236 178 12 216 158 10 175 118 6 - 80 54 7 2 2 6 6 6 6 30 30 30 - 54 54 54 62 62 62 50 50 50 38 38 38 - 14 14 14 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 167 114 7 -213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 135 50 124 112 88 - 82 82 82 54 54 54 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 158 118 36 192 133 9 200 144 11 -216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 91 60 6 167 114 7 -206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 -239 182 13 230 174 11 224 166 10 213 154 11 -180 133 36 124 112 88 86 86 86 58 58 58 - 38 38 38 22 22 22 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 70 70 70 138 110 50 158 118 36 -167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 -224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 -239 182 13 216 158 10 185 133 11 152 99 6 -104 69 6 18 14 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 152 99 6 -192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 -224 166 10 206 145 10 192 133 9 154 121 60 - 94 94 94 62 62 62 42 42 42 22 22 22 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 34 34 34 58 58 58 78 78 78 -101 98 89 124 112 88 142 110 46 156 107 11 -163 110 8 167 114 7 175 118 6 180 123 7 -185 133 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 -219 162 10 197 138 11 163 110 8 130 83 6 - 91 60 6 10 10 10 2 2 6 2 2 6 - 18 18 18 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 26 26 26 2 2 6 - 2 2 6 6 6 6 70 47 6 137 92 6 -175 118 6 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 -192 133 9 163 110 8 124 112 88 82 82 82 - 50 50 50 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 22 22 22 34 34 34 - 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 122 102 70 130 98 46 121 87 25 -137 92 6 152 99 6 163 110 8 180 123 7 -185 133 11 197 138 11 206 145 10 200 144 11 -180 123 7 156 107 11 130 83 6 104 69 6 - 50 34 6 54 54 54 110 110 110 101 98 89 - 86 86 86 82 82 82 78 78 78 78 78 78 - 78 78 78 78 78 78 78 78 78 78 78 78 - 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 86 66 34 124 80 6 -156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 175 118 6 -139 102 15 109 106 95 70 70 70 42 42 42 - 22 22 22 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 10 10 10 - 14 14 14 22 22 22 30 30 30 38 38 38 - 50 50 50 62 62 62 74 74 74 90 90 90 -101 98 89 112 100 78 121 87 25 124 80 6 -137 92 6 152 99 6 152 99 6 152 99 6 -138 86 6 124 80 6 98 70 6 86 66 30 -101 98 89 82 82 82 58 58 58 46 46 46 - 38 38 38 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 38 38 38 42 42 42 - 54 54 54 82 82 82 94 86 76 91 60 6 -134 86 6 156 107 11 167 114 7 175 118 6 -175 118 6 167 114 7 152 99 6 121 87 25 -101 98 89 62 62 62 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 6 6 6 10 10 10 - 18 18 18 22 22 22 30 30 30 42 42 42 - 50 50 50 66 66 66 86 86 86 101 98 89 -106 86 58 98 70 6 104 69 6 104 69 6 -104 69 6 91 60 6 82 62 34 90 90 90 - 62 62 62 38 38 38 22 22 22 14 14 14 - 10 10 10 10 10 10 10 10 10 10 10 10 - 10 10 10 10 10 10 6 6 6 10 10 10 - 10 10 10 10 10 10 10 10 10 14 14 14 - 22 22 22 42 42 42 70 70 70 89 81 66 - 80 54 7 104 69 6 124 80 6 137 92 6 -134 86 6 116 81 8 100 82 52 86 86 86 - 58 58 58 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 18 18 18 26 26 26 38 38 38 54 54 54 - 70 70 70 86 86 86 94 86 76 89 81 66 - 89 81 66 86 86 86 74 74 74 50 50 50 - 30 30 30 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 34 34 34 58 58 58 - 82 82 82 89 81 66 89 81 66 89 81 66 - 94 86 66 94 86 76 74 74 74 50 50 50 - 26 26 26 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 14 14 14 18 18 18 - 30 30 30 38 38 38 46 46 46 54 54 54 - 50 50 50 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 26 26 26 - 38 38 38 50 50 50 58 58 58 58 58 58 - 54 54 54 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 6 6 6 10 10 10 14 14 14 18 18 18 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 18 18 18 22 22 22 22 22 22 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 4 4 6 7 7 +8 10 10 8 10 10 6 8 8 6 7 7 3 4 4 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 5 5 17 18 17 +27 29 28 35 37 36 40 43 41 43 45 43 40 43 41 37 39 37 +32 34 33 27 30 29 23 25 24 17 21 21 15 18 18 12 15 15 +11 13 13 8 10 10 6 7 7 3 4 4 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 13 13 32 34 33 49 51 48 60 60 56 58 59 55 +55 57 54 55 56 53 49 51 48 43 45 43 39 40 39 33 37 35 +28 31 30 23 27 26 20 23 23 17 20 20 14 17 17 13 16 16 +11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 6 7 7 +2 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 7 7 12 15 15 +12 15 15 8 9 9 2 3 3 0 0 0 1 1 1 25 27 26 +55 56 53 68 70 65 65 66 61 65 66 61 63 64 60 63 64 60 +58 59 55 51 52 50 47 48 46 41 42 42 35 37 36 30 32 31 +26 28 27 20 24 24 18 22 22 16 19 19 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +8 9 9 6 8 8 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 6 7 7 20 24 24 23 27 26 +23 27 26 18 22 22 11 13 13 23 24 24 61 63 57 72 73 67 +72 73 67 68 70 65 68 70 65 68 70 65 63 64 60 58 59 55 +55 56 53 47 48 46 41 42 42 35 37 36 30 32 31 26 28 27 +20 24 24 18 22 22 16 20 20 15 19 19 14 17 17 13 16 16 +12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 +8 10 10 8 9 9 7 9 9 6 7 7 1 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 4 5 5 5 6 5 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 15 19 19 40 41 39 53 55 47 +33 36 34 27 30 29 51 52 50 72 73 67 72 73 67 72 73 67 +72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 51 52 50 +47 48 46 40 43 41 33 37 35 30 32 31 26 28 27 20 24 24 +18 22 22 17 21 21 16 19 19 14 18 18 14 17 17 13 17 17 +13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 +9 11 11 8 10 10 8 9 9 7 9 9 6 8 8 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 6 8 8 10 12 12 10 12 12 10 12 12 10 12 12 +6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 20 23 23 71 71 57 131 127 93 +115 113 82 63 64 60 72 73 67 72 73 67 72 73 67 72 73 67 +68 70 65 65 66 61 61 63 57 55 57 54 49 51 48 43 45 43 +39 40 39 33 36 34 28 31 30 23 27 26 20 24 24 20 23 23 +17 21 21 16 20 20 15 19 19 15 18 18 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 +10 12 12 9 11 11 8 10 10 7 9 9 7 9 9 6 8 8 +4 5 5 0 0 0 0 0 0 0 0 0 1 1 1 6 7 7 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 3 4 4 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 18 22 22 71 71 57 144 139 99 +84 83 72 68 70 65 72 73 67 72 73 67 68 70 65 65 66 61 +63 64 60 55 57 54 51 52 50 47 48 46 40 43 41 35 37 36 +30 32 31 27 29 28 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 15 19 19 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 6 8 8 +6 8 8 3 4 4 0 0 0 2 2 2 8 10 10 10 12 12 +10 12 12 10 12 12 11 13 13 36 38 35 61 61 53 48 49 45 +10 12 12 7 9 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 15 19 19 61 61 53 84 83 72 +68 70 65 72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 +51 52 50 47 48 46 41 42 42 37 39 37 32 35 33 28 31 30 +23 27 26 20 24 24 20 23 23 18 22 22 17 21 21 17 21 21 +17 21 21 17 21 21 17 20 20 16 20 20 16 20 20 16 19 19 +15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 +6 8 8 6 8 8 5 6 5 9 11 11 10 12 12 10 12 12 +19 20 18 82 81 62 149 145 103 160 154 106 142 137 94 96 95 69 +10 12 12 10 12 12 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 12 12 44 46 43 68 70 65 +72 73 67 68 70 65 68 70 65 63 64 60 55 57 54 49 51 48 +43 45 43 39 40 39 33 37 35 30 32 31 26 28 27 23 27 26 +20 24 24 18 22 22 18 22 22 18 22 22 18 22 22 20 23 23 +20 24 24 23 25 24 23 25 24 22 24 23 20 23 23 18 22 22 +17 20 20 15 19 19 15 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 11 13 13 10 12 12 9 11 11 8 10 10 8 9 9 +7 9 9 7 9 9 10 12 12 10 12 12 10 12 12 71 71 57 +164 159 111 186 182 128 186 182 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 8 10 10 63 64 60 68 70 65 +72 73 67 68 70 65 63 64 60 55 57 54 47 48 46 40 43 41 +33 37 35 30 32 31 27 29 28 23 27 26 20 24 24 20 23 23 +18 22 22 18 22 22 20 23 22 21 25 23 23 27 26 27 29 28 +28 31 30 31 33 31 31 33 31 31 33 31 28 31 30 26 28 27 +23 25 24 20 23 22 16 20 20 15 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +10 12 12 10 13 13 10 12 12 12 14 14 96 95 69 165 161 109 +186 182 128 192 187 134 192 187 134 176 171 126 160 154 106 103 101 77 +10 12 12 10 12 12 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 35 37 36 68 70 65 72 73 67 +68 70 65 65 66 61 58 59 55 49 51 48 40 43 41 33 37 35 +28 31 30 23 27 26 20 24 24 20 23 23 18 22 22 18 22 22 +18 22 22 20 23 23 23 27 26 27 30 29 32 35 33 37 39 37 +40 43 41 44 46 43 46 47 43 44 46 43 40 43 41 36 38 35 +31 33 31 27 29 28 22 24 23 17 21 21 15 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 11 14 14 11 13 13 13 16 16 +13 16 16 11 14 14 10 12 12 79 78 62 142 137 94 164 159 111 +178 174 128 192 187 134 192 187 134 176 171 126 160 154 106 96 95 69 +10 12 12 10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 55 57 54 68 70 65 72 73 67 +68 70 65 63 64 60 55 56 53 43 45 43 35 37 36 28 31 30 +23 27 26 20 24 24 18 22 22 17 21 21 17 21 21 17 21 21 +20 24 24 25 27 26 31 33 31 38 39 37 46 47 43 53 55 47 +61 61 53 66 65 55 66 65 55 66 65 55 61 61 53 53 55 47 +46 47 43 37 39 37 30 33 30 24 26 24 17 21 21 15 18 18 +13 17 17 12 15 15 12 15 15 13 16 16 14 18 18 14 18 18 +14 17 17 12 15 15 30 31 28 118 116 76 134 131 96 160 154 106 +174 170 121 178 174 128 178 174 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 63 64 60 68 70 65 68 70 65 +65 66 61 58 59 55 49 51 48 39 40 39 30 32 31 23 27 26 +20 24 24 18 22 22 17 21 21 16 20 20 17 21 21 20 23 23 +25 27 26 32 35 33 43 44 41 53 55 47 66 65 55 75 75 61 +82 81 62 84 83 72 87 86 72 87 86 72 82 81 62 75 75 61 +66 65 55 53 55 47 40 41 39 31 33 31 23 25 24 17 20 20 +14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 14 18 18 +14 18 18 13 16 16 46 47 43 96 95 69 125 122 87 142 137 94 +160 154 106 165 161 109 164 159 111 155 149 109 142 137 94 75 75 61 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 60 60 56 68 70 65 68 70 65 +63 64 60 55 57 54 46 47 45 35 37 36 27 30 29 23 25 24 +18 22 22 17 21 21 16 20 20 17 21 21 18 22 22 23 27 26 +31 33 31 43 44 41 55 56 53 71 71 57 84 83 72 92 91 72 +103 101 77 92 91 72 82 81 62 82 81 62 87 86 72 92 91 72 +84 83 72 71 71 57 55 56 53 43 44 41 30 33 30 22 24 23 +16 19 19 14 17 17 12 15 15 12 15 15 13 16 16 14 18 18 +14 18 18 14 17 17 43 44 41 82 81 62 118 116 76 125 122 87 +142 137 94 144 139 99 144 139 99 134 131 96 118 116 76 53 55 47 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 47 48 46 63 64 60 63 64 60 +55 57 54 49 51 48 40 43 41 32 34 33 26 28 27 20 24 24 +18 22 22 16 20 20 16 20 20 17 21 21 20 24 24 28 31 30 +40 41 39 53 55 47 75 75 61 90 89 73 87 86 72 48 49 45 +14 14 13 2 2 2 1 2 2 1 1 1 1 1 1 2 2 2 +19 20 18 43 44 41 66 65 55 53 55 47 38 39 37 26 28 27 +18 22 22 14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 +14 18 18 14 18 18 30 31 28 66 65 55 96 95 69 103 101 77 +118 116 76 118 116 76 118 116 76 118 116 76 103 101 77 36 38 35 +10 12 12 10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 28 31 30 55 57 54 51 52 50 +49 51 48 41 42 42 35 37 36 28 31 30 23 27 26 20 23 23 +17 21 21 16 20 20 16 20 20 18 22 22 23 27 26 33 36 34 +48 49 45 71 71 57 82 81 62 43 44 41 8 9 9 6 7 7 +6 7 7 6 7 7 6 7 7 5 6 5 4 5 5 3 4 4 +2 3 3 1 2 2 4 5 4 36 38 35 48 49 45 32 35 33 +21 25 23 16 19 19 13 17 17 12 15 15 12 15 15 13 16 16 +14 18 18 14 18 18 16 18 16 36 38 35 61 61 53 82 81 62 +96 95 69 96 95 69 96 95 69 96 95 69 79 78 62 19 20 18 +10 12 12 10 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 13 13 46 47 45 43 45 43 +40 43 41 35 37 36 30 32 31 23 27 26 20 24 24 18 22 22 +17 21 21 16 20 20 17 21 21 20 23 23 27 30 29 40 41 39 +61 61 53 53 55 47 16 17 16 9 11 11 10 12 12 10 12 12 +10 12 12 10 12 12 10 12 12 9 11 11 8 10 10 8 9 9 +6 8 8 5 6 5 4 5 5 2 3 3 19 20 18 38 39 37 +26 28 27 17 21 21 14 17 17 13 16 16 12 15 15 12 15 15 +13 17 17 14 18 18 12 15 15 13 12 7 30 31 28 46 47 43 +53 55 47 66 65 55 66 65 55 53 55 47 36 38 35 10 12 12 +10 12 12 10 12 12 2 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 33 37 35 35 37 36 +32 35 33 28 31 30 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 16 20 20 17 21 21 21 25 23 31 33 31 44 46 43 +31 33 31 11 13 13 12 14 14 12 15 15 13 16 16 14 17 17 +14 17 17 14 17 17 14 17 17 13 16 16 12 15 15 12 14 14 +11 13 13 9 11 11 8 10 10 6 8 8 4 5 5 17 18 17 +30 33 30 20 23 22 15 18 18 13 16 16 12 15 15 12 14 14 +13 16 16 14 17 17 14 18 18 11 12 11 7 7 5 16 17 12 +21 22 20 30 31 28 25 27 25 21 22 20 14 14 13 10 12 12 +10 12 12 9 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 27 30 29 +27 29 28 40 41 39 53 55 47 53 55 47 53 55 47 46 47 43 +25 27 25 16 20 20 17 21 21 23 25 24 31 33 31 20 20 20 +12 15 15 14 17 17 15 19 19 16 20 20 17 21 21 18 22 22 +18 22 22 18 22 22 18 22 22 17 21 21 17 21 21 16 19 19 +15 18 18 13 16 16 12 15 15 10 12 12 8 10 10 6 8 8 +21 22 21 22 24 23 15 19 19 13 17 17 13 16 16 12 15 15 +12 15 15 13 17 17 14 18 18 14 18 18 13 15 14 10 9 6 +7 7 5 7 7 5 7 7 5 9 11 11 10 12 12 10 12 12 +10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 82 81 62 +118 116 76 118 116 76 161 156 96 161 156 96 161 156 96 118 116 76 +118 116 76 96 95 69 53 55 47 22 24 23 14 17 17 13 16 16 +15 19 19 17 21 21 18 22 22 20 24 24 20 24 24 23 27 26 +23 27 26 23 27 26 23 27 26 23 27 26 23 27 26 20 24 24 +20 23 23 17 21 21 16 19 19 14 17 17 12 15 15 10 12 12 +9 11 11 20 23 22 16 19 19 14 17 17 13 16 16 12 15 15 +11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 12 15 15 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +9 11 11 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 53 55 47 161 156 96 +161 156 96 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 96 95 69 21 22 20 16 19 19 +18 22 22 20 24 24 23 27 26 23 27 26 26 28 27 27 30 29 +27 30 29 18 22 22 12 14 14 8 10 10 9 11 11 17 21 21 +23 27 26 23 27 26 20 24 24 18 22 22 16 20 20 14 17 17 +12 14 14 14 17 17 16 20 20 14 17 17 13 17 17 13 16 16 +12 15 15 12 15 15 13 17 17 14 18 18 14 17 17 13 16 16 +11 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 12 7 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 30 31 28 +20 24 24 23 27 26 27 30 29 28 31 30 30 32 31 23 27 26 +16 19 19 17 21 21 12 15 15 9 11 11 10 12 12 9 11 11 +20 24 24 28 31 30 26 28 27 23 27 26 20 24 24 17 21 21 +15 19 19 13 16 16 16 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 +12 15 15 10 12 12 10 12 12 10 12 12 10 12 12 8 9 9 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 161 156 96 230 229 82 +230 229 82 233 233 100 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 +27 29 28 27 30 29 30 32 31 30 32 31 23 27 26 20 24 24 +26 28 27 17 21 21 6 7 7 72 73 67 145 141 105 15 15 15 +14 17 17 33 37 35 30 32 31 28 31 30 26 28 27 23 27 26 +20 23 23 16 20 20 15 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 12 15 15 13 17 17 14 18 18 14 17 17 +13 16 16 11 13 13 10 12 12 10 12 12 9 11 11 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 16 17 12 161 156 96 230 229 82 230 229 82 +243 242 120 235 234 117 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +82 81 62 28 31 30 28 31 30 27 30 29 28 31 30 30 32 31 +33 37 35 13 16 16 3 3 3 105 104 92 210 208 158 12 14 14 +17 21 21 33 37 35 33 37 35 32 35 33 30 32 31 27 30 29 +23 27 26 20 23 23 17 20 20 15 18 18 14 18 18 13 17 17 +13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 +13 17 17 12 15 15 10 12 12 10 12 12 3 4 4 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 244 244 132 +241 241 143 243 242 120 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 46 47 43 32 35 33 33 37 35 33 37 35 33 37 35 +40 43 41 23 27 26 1 1 1 2 2 2 24 26 24 14 17 17 +23 27 26 33 37 35 33 37 35 33 37 35 33 37 35 30 32 31 +27 30 29 23 27 26 20 23 23 15 18 18 14 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 14 17 17 +14 17 17 13 16 16 11 13 13 6 8 8 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 16 17 12 161 156 96 230 229 82 235 234 117 239 239 170 +239 239 170 236 236 101 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 118 116 76 33 37 35 33 37 35 37 39 37 37 39 37 +43 45 43 49 51 48 20 24 24 8 10 10 17 20 20 35 37 36 +33 37 35 40 43 41 37 39 37 35 37 36 33 37 35 33 37 35 +30 32 31 27 30 29 23 27 26 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 +14 17 17 13 17 17 11 14 14 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 +241 241 143 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 36 38 35 33 37 35 33 37 35 33 37 35 +37 39 37 47 48 46 55 57 54 55 57 54 49 51 48 43 45 43 +43 45 43 43 45 43 40 43 41 40 43 41 37 39 37 33 37 35 +33 37 35 28 31 30 26 28 27 16 20 20 15 18 18 14 18 18 +14 17 17 13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 +14 17 17 14 17 17 8 10 10 5 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +16 17 12 230 229 82 230 229 82 243 242 120 251 251 187 251 251 187 +246 246 123 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 66 65 55 30 32 31 32 35 33 33 37 35 +33 37 35 37 39 37 40 43 41 47 48 46 49 51 48 51 52 50 +55 57 54 55 57 54 51 52 50 47 48 46 43 45 43 39 40 39 +33 37 35 30 32 31 26 28 27 17 21 21 15 19 19 14 18 18 +14 17 17 13 16 16 12 15 15 12 14 14 11 14 14 13 16 16 +14 17 17 12 15 15 7 9 9 6 8 8 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 239 239 170 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 96 95 69 27 30 29 28 31 30 30 32 31 +33 37 35 40 43 41 46 47 45 55 57 54 63 64 60 72 73 67 +72 73 67 72 73 67 72 73 67 65 66 61 55 57 54 47 48 46 +39 40 39 32 35 33 27 30 29 17 21 21 15 19 19 15 18 18 +14 18 18 13 17 17 13 16 16 12 15 15 11 14 14 12 14 14 +13 16 16 9 11 11 7 9 9 9 11 11 66 65 55 115 113 82 +21 22 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 12 7 +230 229 82 230 229 82 236 236 101 251 251 187 251 251 187 246 246 123 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 118 116 76 23 27 26 26 28 27 32 35 33 +51 52 50 90 89 73 110 109 94 145 141 105 168 163 120 177 172 135 +177 172 135 188 184 146 188 184 146 181 176 137 194 191 148 188 184 146 +184 179 149 188 184 146 188 184 146 156 151 111 177 172 135 181 176 137 +177 172 135 168 163 120 168 163 120 158 153 112 156 151 111 158 153 112 +156 151 111 158 153 112 177 172 135 188 184 146 188 184 146 194 189 146 +36 38 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 82 81 62 +230 229 82 230 229 82 244 244 132 251 251 187 244 244 132 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 82 81 62 +96 95 69 230 229 82 181 178 103 110 109 94 156 151 111 188 184 146 +188 184 146 197 193 154 188 184 146 184 181 136 188 184 146 168 163 120 +168 163 120 178 174 128 156 151 111 158 153 112 174 170 121 156 151 111 +156 151 111 158 153 112 156 151 111 168 163 120 178 174 128 181 176 137 +176 171 126 178 174 128 184 181 136 176 171 126 178 174 128 184 181 136 +176 171 126 178 174 128 184 181 136 164 159 111 155 149 109 96 95 69 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 161 156 96 +230 229 82 230 229 82 244 244 132 244 244 132 236 236 101 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 46 47 43 82 81 62 +158 153 112 197 193 154 194 189 146 184 181 136 188 184 146 168 163 120 +156 151 111 137 133 100 131 127 93 137 133 100 137 133 100 158 153 112 +121 119 87 137 133 100 156 151 111 145 141 105 99 98 80 84 83 72 +63 64 60 52 53 49 40 43 41 33 36 34 36 38 35 36 38 35 +38 39 37 43 44 41 43 44 41 46 47 43 48 49 45 48 49 45 +46 47 43 36 38 35 30 31 28 19 20 18 6 7 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 230 229 82 +230 229 82 230 229 82 246 246 123 236 236 101 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 53 55 47 121 119 87 +176 171 126 171 165 117 161 156 96 82 81 62 53 55 47 33 37 35 +39 40 39 63 64 60 99 98 80 121 119 87 137 133 100 177 172 135 +176 171 126 184 181 136 131 127 93 131 127 93 110 109 94 84 83 72 +51 52 50 39 40 39 27 29 28 18 22 22 16 19 19 15 19 19 +15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 9 9 7 9 9 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 236 236 101 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 96 95 69 71 71 57 +36 38 35 118 116 76 118 116 76 12 15 15 15 18 18 20 24 24 +33 37 35 55 56 53 84 83 72 110 109 94 145 141 105 110 109 94 +168 163 120 121 119 87 156 151 111 131 127 93 87 86 72 61 63 57 +47 48 46 28 31 30 18 22 22 15 19 19 15 18 18 15 19 19 +15 19 19 14 18 18 14 17 17 13 17 17 13 16 16 12 15 15 +11 13 13 10 12 12 9 11 11 8 10 10 7 9 9 3 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 0 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 230 229 82 118 116 76 11 14 14 14 17 17 18 22 22 +27 30 29 40 43 41 60 60 56 84 83 72 105 104 92 110 109 94 +110 109 94 110 109 94 99 98 80 90 89 73 68 70 65 47 48 46 +32 34 33 23 25 24 20 23 23 17 21 21 15 19 19 14 17 17 +15 19 19 15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 +11 14 14 10 12 12 9 11 11 8 10 10 7 9 9 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 11 13 13 13 16 16 15 19 19 +20 24 24 30 32 31 40 43 41 51 52 50 63 64 60 72 73 67 +65 66 61 65 66 61 65 66 61 55 57 54 46 47 45 33 37 35 +27 29 28 20 24 24 17 21 21 16 20 20 16 20 20 15 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 8 10 10 7 9 9 6 7 7 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 53 55 47 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 118 116 76 53 55 47 10 13 13 12 15 15 14 17 17 +17 20 20 20 24 24 27 29 28 32 34 33 37 39 37 40 43 41 +43 45 43 41 42 42 35 37 36 30 32 31 28 31 30 23 27 26 +20 23 23 17 21 21 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 10 12 12 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +118 116 76 82 81 62 13 14 12 10 13 13 12 15 15 13 17 17 +15 19 19 16 20 20 20 23 23 20 24 24 23 27 26 26 28 27 +26 28 27 26 28 27 23 27 26 18 22 22 20 23 23 17 21 21 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 15 18 18 14 17 17 13 17 17 13 16 16 +12 15 15 12 14 14 12 14 14 12 14 14 12 14 14 23 24 24 +6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 118 116 76 +71 71 57 13 14 12 9 12 12 10 13 13 12 15 15 13 17 17 +15 18 18 15 19 19 16 20 20 17 21 21 17 21 21 18 22 22 +18 22 22 18 22 22 17 21 21 16 19 19 15 18 18 14 18 18 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 15 19 19 15 18 18 14 18 18 16 20 20 23 25 24 +17 21 21 25 27 26 47 48 46 47 48 46 51 52 50 72 73 67 +33 36 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 46 47 43 +9 11 11 9 11 11 10 12 12 11 13 13 12 15 15 14 17 17 +15 18 18 15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 20 24 24 55 56 53 32 34 33 84 83 72 +90 89 73 110 109 94 110 109 94 105 104 92 110 109 94 110 109 94 +72 73 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 82 81 62 16 17 12 9 11 11 +9 11 11 9 12 12 10 13 13 12 14 14 13 16 16 14 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 19 19 33 36 34 99 98 80 156 151 111 145 141 105 184 179 149 +168 163 120 184 179 149 177 172 135 156 151 111 145 141 105 110 109 94 +90 89 73 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 71 71 57 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 230 229 82 230 229 82 230 229 82 161 156 96 +118 116 76 82 81 62 30 31 28 9 11 11 9 11 11 9 11 11 +10 12 12 10 13 13 11 14 14 13 16 16 14 17 17 15 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +18 22 22 58 59 55 137 133 100 197 193 154 214 212 158 210 208 158 +197 193 154 184 179 149 184 179 149 137 133 100 110 109 94 99 98 80 +84 83 72 10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 161 156 96 161 156 96 161 156 96 118 116 76 71 71 57 +21 22 20 12 14 14 11 13 13 10 12 12 10 12 12 10 13 13 +11 13 13 12 15 15 13 16 16 14 17 17 14 18 18 15 19 19 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 17 21 21 +23 27 26 84 83 72 184 179 149 251 251 187 210 208 158 184 179 149 +184 179 149 156 151 111 110 109 94 84 83 72 63 64 60 51 52 50 +18 22 22 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +161 156 96 161 156 96 118 116 76 53 55 47 20 23 22 16 19 19 +13 16 16 12 15 15 12 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 13 16 16 14 17 17 15 19 19 16 20 20 17 21 21 +23 27 26 18 22 22 20 24 24 23 27 26 30 32 31 17 21 21 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +23 27 26 33 37 35 137 133 100 156 151 111 158 153 112 105 104 92 +105 104 92 68 70 65 39 40 39 18 22 22 12 14 14 12 15 15 +9 11 11 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 +118 116 76 66 65 55 43 45 43 32 34 33 25 27 26 20 23 22 +17 20 20 15 18 18 14 17 17 15 18 18 13 16 16 14 17 17 +14 18 18 16 20 20 32 34 33 55 57 54 58 59 55 72 73 67 +105 104 92 55 57 54 65 66 61 63 64 60 40 43 41 33 37 35 +41 42 42 20 24 24 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 21 21 26 28 27 30 32 31 35 37 36 68 70 65 39 40 39 +23 27 26 15 18 18 13 16 16 11 14 14 9 12 12 8 10 10 +7 9 9 6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 +230 229 82 230 229 82 230 229 82 96 95 69 30 31 28 49 51 48 +90 89 73 68 70 65 55 57 54 47 48 46 47 48 46 43 45 43 +32 34 33 43 45 43 43 45 43 23 27 26 25 27 26 40 43 41 +40 43 41 90 89 73 110 109 94 145 141 105 156 151 111 156 151 111 +184 179 149 184 179 149 177 172 135 184 179 149 137 133 100 84 83 72 +105 104 92 63 64 60 49 51 48 47 48 46 28 31 30 18 22 22 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 15 19 19 15 19 19 15 19 19 18 22 22 15 19 19 +13 16 16 12 15 15 11 14 14 10 13 13 9 12 12 9 11 11 +8 10 10 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +30 31 28 230 229 82 71 71 57 2 2 1 0 0 0 58 59 55 +105 104 92 84 83 72 65 66 61 84 83 72 110 109 94 110 109 94 +145 141 105 105 104 92 110 109 94 110 109 94 84 83 72 110 109 94 +158 153 112 197 193 154 197 193 154 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 197 193 154 +197 193 154 184 179 149 145 141 105 137 133 100 105 104 92 47 48 46 +20 23 23 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 19 19 15 19 19 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 14 14 12 14 14 13 13 13 13 13 13 +13 13 13 12 12 12 10 10 9 6 7 7 2 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 65 66 61 +105 104 92 84 83 72 84 83 72 110 109 94 184 179 149 210 208 158 +210 208 158 210 208 158 214 212 158 197 193 154 214 212 158 210 208 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 251 251 187 184 179 149 84 83 72 +26 28 27 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +13 17 17 13 16 16 15 15 15 14 14 13 14 14 13 14 14 13 +13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 73 67 +105 104 92 99 98 80 84 83 72 99 98 80 177 172 135 197 193 154 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 197 193 154 99 98 80 +23 27 26 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 16 16 16 16 16 16 16 16 16 15 15 15 14 14 13 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 84 83 72 +110 109 94 99 98 80 72 73 67 63 64 60 99 98 80 177 172 135 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 184 179 149 177 172 135 110 109 94 33 37 35 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 19 19 14 18 18 +15 18 18 18 19 18 18 19 18 17 17 17 16 16 16 15 15 15 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 105 104 92 +108 107 93 99 98 80 72 73 67 63 64 60 51 52 50 87 86 72 +105 104 92 110 109 94 108 107 93 156 151 111 184 179 149 184 179 149 +197 193 154 197 193 154 197 193 154 184 179 149 184 179 149 177 172 135 +197 193 154 156 151 111 177 172 135 184 179 149 168 163 120 137 133 100 +145 141 105 110 109 94 99 98 80 47 48 46 55 57 54 15 19 19 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 20 20 17 21 21 16 20 20 16 19 19 15 19 19 16 19 19 +20 20 20 21 22 21 20 20 20 19 20 19 18 19 18 16 16 16 +15 15 15 14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 58 59 55 110 109 94 +105 104 92 90 89 73 72 73 67 55 57 54 43 45 43 39 40 39 +43 45 43 46 47 45 43 45 43 68 70 65 65 66 61 63 64 60 +108 107 93 72 73 67 105 104 92 90 89 73 72 73 67 40 43 41 +72 73 67 68 70 65 68 70 65 58 59 55 63 64 60 49 51 48 +43 45 43 33 36 34 27 30 29 20 24 24 16 20 20 15 19 19 +15 19 19 15 19 19 15 19 19 16 19 19 16 20 20 16 20 20 +17 21 21 20 24 24 20 23 22 17 21 21 17 20 20 20 20 20 +21 22 21 21 22 21 21 22 21 21 22 21 20 20 20 18 19 18 +16 16 16 15 15 15 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 21 22 21 110 109 94 110 109 94 +105 104 92 84 83 72 68 70 65 51 52 50 41 42 42 33 37 35 +28 31 30 23 27 26 20 23 23 18 22 22 17 20 20 25 27 26 +26 28 27 27 30 29 25 27 26 20 23 23 23 27 26 30 32 31 +20 24 24 17 21 21 18 22 22 15 19 19 26 28 27 20 23 23 +14 18 18 15 19 19 15 18 18 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 16 19 19 +16 20 20 22 24 23 24 26 24 22 24 23 20 23 22 22 24 23 +24 26 24 24 26 24 23 24 24 22 24 23 21 22 21 19 20 19 +17 17 17 15 15 15 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 2 2 2 99 98 80 110 109 94 108 107 93 +105 104 92 84 83 72 63 64 60 49 51 48 39 40 39 32 34 33 +27 30 29 23 25 24 20 23 23 17 20 20 15 19 19 14 18 18 +14 17 17 13 17 17 13 17 17 13 17 17 13 17 17 13 17 17 +14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 14 18 18 15 18 18 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 17 21 21 27 29 28 26 28 27 25 27 26 25 27 26 +27 29 28 27 29 28 26 28 27 24 26 24 21 22 21 20 20 20 +18 19 18 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 110 109 94 110 109 94 105 104 92 +90 89 73 72 73 67 55 57 54 43 45 43 35 37 36 30 32 31 +26 28 27 20 24 24 17 21 21 16 19 19 15 18 18 14 17 17 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 +15 18 18 15 18 18 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 27 29 28 32 34 33 28 31 30 27 29 28 +30 32 31 30 32 31 30 31 28 26 28 27 23 24 24 21 22 21 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 3 3 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 10 9 108 107 93 110 109 94 108 107 93 99 98 80 +84 83 72 63 64 60 49 51 48 40 43 41 33 36 34 27 30 29 +23 27 26 18 22 22 17 20 20 15 18 18 14 17 17 13 16 16 +13 16 16 13 16 16 12 15 15 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 +14 18 18 14 18 18 15 18 18 15 18 18 15 19 19 15 19 19 +15 19 19 15 19 19 17 21 21 33 36 34 32 34 33 31 33 31 +33 36 34 33 36 34 31 33 31 27 29 28 25 27 26 21 22 21 +19 20 19 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 63 64 60 137 133 100 43 45 43 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 +68 70 65 55 57 54 43 45 43 35 37 36 30 32 31 26 28 27 +20 24 24 17 21 21 16 19 19 14 17 17 13 16 16 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 15 18 18 +15 19 19 15 19 19 15 19 19 20 24 24 32 34 33 35 37 36 +37 39 37 35 37 36 33 36 34 30 32 31 26 28 27 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 99 98 80 184 179 149 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 15 15 110 109 94 110 109 94 108 107 93 99 98 80 72 73 67 +61 63 57 49 51 48 39 40 39 33 36 34 27 30 29 23 25 24 +18 22 22 16 19 19 14 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +12 15 15 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 +14 18 18 15 18 18 15 19 19 15 19 19 30 32 31 38 39 37 +39 40 39 39 40 39 35 37 36 31 33 31 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +110 109 94 197 193 154 210 208 158 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 65 66 61 +51 52 50 43 45 43 35 37 36 30 32 31 25 27 26 20 23 23 +17 20 20 15 18 18 13 16 16 12 15 15 12 15 15 11 14 14 +11 14 14 11 14 14 11 13 13 11 13 13 11 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 +13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 16 19 19 37 39 37 41 42 42 +41 42 42 41 42 42 38 39 37 32 34 33 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 11 11 11 137 133 100 +197 193 154 251 251 187 239 239 170 184 179 149 31 33 31 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 12 12 +110 109 94 110 109 94 105 104 92 90 89 73 72 73 67 58 59 55 +46 47 45 37 39 37 31 33 31 26 28 27 20 24 24 17 21 21 +15 18 18 13 16 16 12 15 15 12 14 14 11 13 13 11 13 13 +10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 +14 17 17 14 17 17 14 18 18 23 27 26 41 42 42 41 42 42 +43 45 43 41 42 42 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 27 29 28 168 163 120 210 208 158 +251 251 187 251 251 187 210 208 158 137 133 100 1 1 1 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 60 56 +110 109 94 105 104 92 105 104 92 84 83 72 65 66 61 51 52 50 +40 43 41 33 36 34 27 30 29 23 25 24 18 22 22 16 19 19 +14 17 17 12 15 15 11 14 14 11 14 14 10 13 13 10 13 13 +10 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 13 13 11 14 14 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 32 34 33 43 45 43 43 45 43 +43 45 43 43 45 43 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 68 70 65 184 179 149 210 208 158 251 251 187 +251 251 187 214 212 158 184 179 149 37 39 37 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 7 7 105 104 92 +105 104 92 105 104 92 99 98 80 72 73 67 58 59 55 46 47 45 +35 37 36 30 32 31 25 27 26 20 23 23 16 19 19 14 17 17 +12 15 15 12 14 14 11 13 13 10 13 13 10 12 12 10 12 12 +10 12 12 10 12 12 9 12 12 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 17 20 20 41 42 42 46 47 45 46 47 45 +46 47 45 43 45 43 40 41 39 33 36 34 27 29 28 23 24 24 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 15 15 110 109 94 197 193 154 214 212 158 251 251 187 251 251 187 +239 239 170 184 179 149 84 83 72 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 47 48 46 105 104 92 +105 104 92 99 98 80 84 83 72 68 70 65 51 52 50 40 43 41 +32 34 33 27 29 28 22 24 23 17 21 21 15 18 18 13 16 16 +12 15 15 11 13 13 10 13 13 10 12 12 9 12 12 9 12 12 +9 12 12 9 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 9 12 12 9 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 +12 15 15 13 16 16 28 31 30 43 45 43 47 48 46 47 48 46 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 3 4 4 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 60 60 56 +177 172 135 197 193 154 251 251 187 251 251 187 251 251 187 251 251 187 +184 179 149 110 109 94 3 4 4 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 99 98 80 105 104 92 +99 98 80 87 86 72 84 83 72 63 64 60 46 47 45 35 37 36 +30 32 31 25 27 26 18 22 22 16 19 19 14 17 17 12 15 15 +11 14 14 10 13 13 9 12 12 9 12 12 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 +9 12 12 10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +10 13 13 11 13 13 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 14 17 17 41 42 42 47 48 46 49 51 48 51 52 50 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 23 24 24 137 133 100 184 179 149 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 +110 109 94 13 13 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 30 32 31 105 104 92 99 98 80 +84 83 72 84 83 72 72 73 67 55 57 54 41 42 42 32 34 33 +27 29 28 20 24 24 17 20 20 14 17 17 13 16 16 12 14 14 +10 13 13 10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 12 12 9 12 12 10 12 12 10 12 12 10 12 12 +10 13 13 10 13 13 10 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 27 29 28 55 56 53 72 73 67 51 52 50 51 52 50 +49 51 48 43 45 43 39 40 39 32 34 33 26 28 27 21 22 21 +19 20 19 16 16 16 18 19 17 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 8 8 7 84 83 72 184 179 149 197 193 154 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 145 141 105 +19 20 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 14 14 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 72 73 67 105 104 92 84 83 72 +72 73 67 84 83 72 68 70 65 49 51 48 39 40 39 30 32 31 +25 27 26 18 22 22 15 18 18 13 16 16 12 15 15 11 13 13 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 11 13 13 +13 16 16 41 42 42 99 98 80 158 153 112 65 66 61 51 52 50 +49 51 48 43 45 43 39 40 39 31 33 31 25 27 26 21 22 21 +21 22 21 68 70 65 55 56 53 13 13 13 12 12 12 12 12 12 +12 12 12 11 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +63 64 60 158 153 112 184 179 149 210 208 158 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 184 179 149 137 133 100 27 29 28 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +21 22 21 110 109 94 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 13 13 13 105 104 92 90 89 73 72 73 67 +68 70 65 84 83 72 63 64 60 46 47 45 35 37 36 27 29 28 +22 24 23 17 20 20 14 17 17 12 15 15 11 14 14 10 12 12 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +30 32 31 47 48 46 177 172 135 210 208 158 137 133 100 55 56 53 +49 51 48 43 45 43 38 39 37 31 33 31 25 27 26 22 24 23 +110 109 94 184 179 149 63 64 60 13 13 13 12 12 12 12 12 12 +12 12 12 8 9 9 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 21 22 21 105 104 92 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 184 179 149 145 141 105 23 24 24 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 184 179 149 105 104 92 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 99 98 80 84 83 72 63 64 60 +68 70 65 72 73 67 55 57 54 41 42 42 32 34 33 25 27 26 +20 23 23 16 19 19 13 16 16 12 14 14 10 13 13 10 12 12 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 12 12 9 12 12 10 12 12 17 20 20 +46 47 45 72 73 67 210 208 158 251 251 187 210 208 158 63 64 60 +49 51 48 43 45 43 37 39 37 30 32 31 24 26 24 105 104 92 +210 208 158 197 193 154 47 48 46 13 13 13 12 12 12 12 12 12 +12 12 12 6 7 7 33 36 34 48 49 45 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 8 8 7 23 24 24 55 56 53 110 109 94 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 184 179 149 110 109 94 20 20 20 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +110 109 94 251 251 187 210 208 158 47 48 46 0 0 0 0 0 0 +0 0 0 1 1 1 90 89 73 90 89 73 72 73 67 55 56 53 +72 73 67 68 70 65 51 52 50 37 39 37 28 31 30 23 25 24 +17 21 21 15 18 18 12 15 15 11 14 14 10 13 13 9 12 12 +9 11 11 9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 13 16 16 41 42 42 +49 51 48 110 109 94 251 251 187 251 251 187 251 251 187 105 104 92 +49 51 48 43 45 43 35 37 36 30 31 28 47 48 46 197 193 154 +251 251 187 197 193 154 31 33 31 12 12 12 12 12 12 12 12 12 +12 12 12 51 52 50 184 179 149 72 73 67 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 +11 11 11 21 22 21 30 32 31 40 41 39 60 60 56 145 141 105 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +184 179 149 110 109 94 13 13 13 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 4 5 4 61 61 53 48 49 45 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +156 151 111 251 251 187 251 251 187 184 179 149 11 11 11 0 0 0 +0 0 0 26 28 27 99 98 80 84 83 72 60 60 56 43 45 43 +72 73 67 65 66 61 49 51 48 35 37 36 27 29 28 20 24 24 +17 20 20 14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 +9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 11 13 13 37 39 37 47 48 46 +51 52 50 184 179 149 251 251 187 251 251 187 251 251 187 145 141 105 +47 48 46 41 42 42 35 37 36 27 29 28 137 133 100 251 251 187 +251 251 187 197 193 154 19 20 19 12 12 12 12 12 12 12 12 12 +27 29 28 184 179 149 214 212 158 63 64 60 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 6 7 7 16 16 16 24 26 24 +30 32 31 38 39 37 47 48 46 55 57 54 68 70 65 110 109 94 +197 193 154 251 251 187 251 251 187 251 251 187 210 208 158 184 179 149 +105 104 92 8 8 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 65 66 61 184 179 149 156 151 111 +30 32 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +168 163 120 251 251 187 251 251 187 251 251 187 110 109 94 0 0 0 +0 0 0 60 60 56 84 83 72 68 70 65 51 52 50 38 39 37 +84 83 72 63 64 60 43 45 43 33 36 34 25 27 26 20 23 22 +15 18 18 13 16 16 12 14 14 10 13 13 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 9 11 11 10 12 12 33 36 34 46 47 45 51 52 50 +72 73 67 210 208 158 251 251 187 251 251 187 251 251 187 177 172 135 +47 48 46 41 42 42 35 37 36 37 39 37 184 179 149 251 251 187 +251 251 187 197 193 154 13 13 13 12 12 12 12 12 12 12 12 12 +110 109 94 251 251 187 251 251 187 37 39 37 0 0 0 0 0 0 +0 0 0 21 22 20 2 2 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4 5 5 12 12 12 21 22 21 25 27 26 30 32 31 38 39 37 +46 47 45 55 56 53 60 60 56 65 66 61 68 70 65 105 104 92 +110 109 94 197 193 154 210 208 158 197 193 154 184 179 149 84 83 72 +2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 13 13 184 179 149 251 251 187 +197 193 154 43 44 41 0 0 0 0 0 0 0 0 0 0 0 0 +145 141 105 251 251 187 251 251 187 251 251 187 214 212 158 43 45 43 +2 2 2 84 83 72 72 73 67 58 59 55 41 42 42 38 39 37 +72 73 67 58 59 55 41 42 42 31 33 31 25 27 26 18 22 22 +14 17 17 12 15 15 12 14 14 10 12 12 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 12 12 31 33 31 43 45 43 49 51 48 55 56 53 +110 109 94 251 251 187 251 251 187 251 251 187 251 251 187 168 163 120 +47 48 46 41 42 42 33 36 34 63 64 60 197 193 154 251 251 187 +251 251 187 184 179 149 13 13 13 12 12 12 12 12 12 16 16 16 +197 193 154 251 251 187 239 239 170 20 20 20 0 0 0 2 2 1 +108 107 93 110 109 94 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 4 5 5 11 11 11 18 19 18 +22 24 23 26 28 27 32 34 33 39 40 39 46 47 45 51 52 50 +55 57 54 60 60 56 63 64 60 63 64 60 63 64 60 58 59 55 +63 64 60 99 98 80 145 141 105 137 133 100 43 45 43 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 110 109 94 251 251 187 +251 251 187 184 179 149 25 27 26 0 0 0 0 0 0 0 0 0 +99 98 80 251 251 187 251 251 187 251 251 187 251 251 187 156 151 111 +25 27 26 84 83 72 65 66 61 47 48 46 32 34 33 39 40 39 +72 73 67 55 57 54 40 41 39 30 32 31 23 25 24 18 22 22 +14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 28 31 30 41 42 42 47 48 46 55 56 53 58 59 55 +137 133 100 251 251 187 251 251 187 251 251 187 210 208 158 137 133 100 +47 48 46 40 41 39 32 34 33 75 75 61 184 179 149 239 239 170 +251 251 187 177 172 135 13 13 13 12 12 12 12 12 12 43 44 41 +197 193 154 251 251 187 210 208 158 10 10 9 0 0 0 84 83 72 +251 251 187 84 83 72 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +6 7 7 11 11 11 17 17 17 20 20 20 23 24 24 27 29 28 +32 34 33 38 39 37 43 45 43 47 48 46 51 52 50 55 56 53 +58 59 55 58 59 55 55 57 54 55 56 53 47 48 46 41 42 42 +35 37 36 31 33 31 47 48 46 14 14 13 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 66 65 55 99 98 80 20 20 20 +0 0 0 0 0 0 0 0 0 0 0 0 43 45 43 214 212 158 +251 251 187 251 251 187 145 141 105 3 3 3 0 0 0 0 0 0 +48 49 45 184 179 149 239 239 170 251 251 187 239 239 170 177 172 135 +84 83 72 72 73 67 55 56 53 39 40 39 26 28 27 39 40 39 +68 70 65 51 52 50 39 40 39 28 31 30 22 24 23 17 20 20 +14 17 17 12 14 14 10 13 13 9 11 11 9 11 11 9 11 11 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +27 29 28 40 41 39 46 47 45 51 52 50 55 57 54 63 64 60 +131 127 93 197 193 154 210 208 158 197 193 154 168 163 120 96 95 69 +47 48 46 40 41 39 32 34 33 71 71 57 145 141 105 184 179 149 +184 179 149 131 127 93 13 13 13 12 12 12 12 12 12 48 49 45 +168 163 120 184 179 149 156 151 111 6 7 7 14 14 13 177 172 135 +239 239 170 40 41 39 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 3 3 3 6 7 7 11 11 11 16 16 16 +18 19 18 21 22 21 23 24 24 27 29 28 32 34 33 37 39 37 +41 42 42 43 45 43 47 48 46 51 52 50 51 52 50 51 52 50 +51 52 50 49 51 48 46 47 45 40 41 39 32 34 33 25 27 26 +20 20 20 14 14 13 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 33 36 34 197 193 154 184 179 149 +41 42 42 0 0 0 0 0 0 0 0 0 3 3 3 184 179 149 +251 251 187 251 251 187 184 179 149 48 49 45 0 0 0 0 0 0 +16 17 12 121 119 87 177 172 135 194 189 146 188 184 146 145 141 105 +82 81 62 63 64 60 46 47 45 31 33 31 21 22 21 35 37 36 +68 70 65 51 52 50 37 39 37 27 30 29 22 24 23 17 20 20 +13 16 16 12 14 14 10 13 13 9 11 11 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 25 27 26 +38 39 37 43 45 43 51 52 50 55 56 53 60 60 56 63 64 60 +92 91 72 158 153 112 176 171 126 171 165 117 149 143 98 82 81 62 +44 46 43 38 39 37 30 32 31 71 71 57 131 127 93 160 154 106 +149 143 98 82 81 62 13 13 13 12 12 12 12 12 12 46 47 43 +121 119 87 134 131 96 96 95 69 7 7 6 38 39 37 131 127 93 +145 141 105 12 13 12 0 0 0 1 1 1 3 3 3 6 7 7 +10 10 9 12 12 12 14 14 13 16 16 16 18 19 18 21 22 21 +22 24 23 26 28 27 30 31 28 33 36 34 37 39 37 40 41 39 +41 42 42 43 45 43 46 47 45 46 47 45 46 47 45 43 45 43 +41 42 42 37 39 37 31 33 31 26 28 27 21 22 21 16 16 16 +6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 177 172 135 251 251 187 +197 193 154 27 29 28 0 0 0 0 0 0 0 0 0 110 109 94 +239 239 170 239 239 170 184 179 149 87 86 72 2 2 1 0 0 0 +1 1 1 82 81 62 142 137 94 165 161 109 165 161 109 131 127 93 +75 75 61 55 56 53 37 39 37 25 27 26 19 20 19 32 34 33 +65 66 61 49 51 48 35 37 36 27 29 28 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 22 24 23 35 37 36 +41 42 42 47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 +71 71 57 131 127 93 160 154 106 160 154 106 142 137 94 82 81 62 +46 47 43 40 41 39 33 36 34 66 65 55 125 122 87 149 143 98 +142 137 94 82 81 62 17 17 17 18 19 17 14 14 13 46 47 43 +118 116 76 125 122 87 96 95 69 16 17 12 71 71 57 103 101 77 +82 81 62 11 11 11 11 11 11 13 13 13 14 14 13 14 14 13 +15 15 15 16 16 16 17 17 17 19 20 19 21 22 21 23 24 24 +26 28 27 27 29 28 31 33 31 33 36 34 35 37 36 38 39 37 +39 40 39 39 40 39 38 39 37 37 39 37 35 37 36 31 33 31 +27 29 28 24 26 24 21 22 21 17 17 17 12 12 12 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 68 70 65 251 251 187 +251 251 187 156 151 111 2 2 1 0 0 0 0 0 0 43 44 41 +177 172 135 184 179 149 158 153 112 103 101 77 19 20 18 0 0 0 +0 0 0 46 47 43 131 127 93 160 154 106 160 154 106 131 127 93 +71 71 57 43 45 43 30 32 31 21 22 21 16 16 16 26 28 27 +63 64 60 47 48 46 35 37 36 26 28 27 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 20 20 20 33 36 34 40 41 39 +46 47 45 51 52 50 55 57 54 60 60 56 63 64 60 65 66 61 +66 65 55 118 116 76 151 147 98 165 161 109 151 147 98 121 119 87 +96 95 69 96 95 69 96 95 69 103 101 77 142 137 94 151 147 98 +142 137 94 103 101 77 82 81 62 82 81 62 82 81 62 96 95 69 +131 127 93 142 137 94 103 101 77 46 47 43 96 95 69 118 116 76 +71 71 57 14 14 13 14 14 13 15 15 15 15 15 15 16 16 16 +16 16 16 17 17 17 18 19 18 20 20 20 21 22 21 23 24 24 +25 27 26 27 29 28 30 31 28 30 32 31 31 33 31 31 33 31 +31 33 31 31 33 31 30 31 28 27 29 28 25 27 26 22 24 23 +20 20 20 16 16 16 13 13 13 6 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +58 59 55 68 70 65 8 8 7 0 0 0 10 10 9 210 208 158 +251 251 187 184 179 149 38 39 37 0 0 0 0 0 0 8 8 7 +103 101 77 149 143 98 149 143 98 118 116 76 40 41 39 25 27 25 +53 55 47 82 81 62 144 139 99 165 161 109 165 161 109 142 137 94 +71 71 57 35 37 36 24 26 24 18 19 18 15 15 15 22 24 23 +63 64 60 46 47 45 33 36 34 26 28 27 20 23 22 17 18 17 +12 15 15 11 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 16 16 16 30 31 28 35 37 36 41 42 42 +47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 65 66 61 +61 61 53 103 101 77 151 147 98 171 165 117 171 165 117 168 163 120 +158 153 112 158 153 112 155 149 109 151 147 98 151 147 98 160 154 106 +151 147 98 149 143 98 142 137 94 149 143 98 149 143 98 149 143 98 +155 149 109 151 147 98 131 127 93 103 101 77 125 122 87 118 116 76 +71 71 57 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 +17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 21 22 21 +23 24 24 24 26 24 25 27 26 26 28 27 26 28 27 26 28 27 +25 27 26 24 26 24 22 24 23 21 22 21 19 20 19 16 16 16 +14 14 13 8 8 7 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +20 20 20 184 179 149 168 163 120 21 22 21 0 0 0 105 104 92 +177 172 135 145 141 105 71 71 57 0 0 0 0 0 0 0 0 0 +66 65 55 131 127 93 151 147 98 142 137 94 118 116 76 121 119 87 +145 141 105 158 153 112 176 171 126 178 174 128 176 171 126 149 145 103 +96 95 69 31 33 31 21 22 21 16 16 16 14 14 13 18 19 18 +60 60 56 46 47 45 33 36 34 25 27 26 21 22 21 15 18 18 +12 15 15 11 13 13 9 11 11 8 10 10 8 10 10 8 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 10 12 12 26 28 27 31 33 31 38 39 37 43 45 43 +51 52 50 55 56 53 60 60 56 63 64 60 65 66 61 68 70 65 +63 64 60 96 95 69 158 153 112 178 174 128 188 184 146 194 189 146 +194 189 146 188 184 146 184 181 136 176 171 126 171 165 117 173 167 111 +173 167 111 165 161 109 171 165 117 174 170 121 176 171 126 178 174 128 +178 174 128 174 170 121 160 154 106 149 143 98 149 143 98 125 122 87 +71 71 57 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 +17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 +21 22 21 21 22 21 21 22 21 22 24 23 21 22 21 21 22 21 +21 22 21 19 20 19 18 19 18 16 16 16 14 14 13 11 11 11 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 105 104 92 197 193 154 110 109 94 9 9 8 36 38 35 +121 119 87 131 127 93 96 95 69 18 19 17 30 31 28 66 65 55 +96 95 69 142 137 94 160 154 106 160 154 106 160 154 106 168 163 120 +184 181 136 194 191 148 197 193 154 197 193 154 194 189 146 168 163 120 +125 122 87 46 47 43 18 19 18 15 15 15 13 13 13 14 14 13 +55 57 54 43 45 43 32 34 33 25 27 26 18 22 22 17 17 17 +12 14 14 10 12 12 9 11 11 8 10 10 8 9 9 7 9 9 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 32 34 33 41 42 42 35 37 36 39 40 39 37 39 37 +35 37 36 55 57 54 60 60 56 63 64 60 65 66 61 65 66 61 +61 63 57 115 113 82 168 163 120 194 191 148 204 201 155 210 208 158 +210 208 158 210 208 158 197 193 154 194 189 146 186 182 128 176 171 126 +174 170 121 176 171 126 186 182 128 190 186 136 194 191 148 197 193 154 +197 193 154 188 184 146 181 176 137 174 170 121 165 161 109 142 137 94 +82 81 62 24 26 24 16 16 16 16 16 16 16 16 16 16 16 16 +17 17 17 17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 +19 20 19 19 20 19 20 20 20 19 20 19 19 20 19 18 19 18 +17 17 17 15 15 15 13 13 13 12 12 12 6 7 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 17 18 17 137 133 100 115 113 82 53 55 47 19 20 18 +103 101 77 144 139 99 137 133 100 115 113 82 137 133 100 156 151 111 +158 153 112 164 159 111 171 165 117 174 170 121 178 174 128 194 189 146 +204 201 155 214 212 158 214 212 158 214 212 158 210 208 158 188 184 146 +158 153 112 87 86 72 17 17 17 13 13 13 13 13 13 15 15 15 +55 56 53 43 45 43 32 34 33 24 26 24 17 20 20 16 16 16 +12 14 14 10 12 12 8 10 10 8 10 10 7 9 9 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 110 109 94 84 83 72 49 51 48 26 28 27 8 10 10 +8 9 9 51 52 50 58 59 55 63 64 60 63 64 60 63 64 60 +66 65 55 134 131 96 181 176 137 210 208 158 214 212 158 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 194 189 146 186 182 128 +186 182 128 184 181 136 194 189 146 204 201 155 210 208 158 210 208 158 +210 208 158 210 208 158 197 193 154 190 186 136 176 171 126 155 149 109 +118 116 76 36 38 35 15 15 15 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 +17 17 17 17 17 17 17 17 17 16 16 16 16 16 16 15 15 15 +13 13 13 12 12 12 8 8 7 2 2 2 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 53 55 47 103 101 77 96 95 69 53 55 47 +103 101 77 158 153 112 177 172 135 184 179 149 188 184 146 197 193 154 +194 189 146 190 186 136 184 181 136 184 181 136 194 189 146 210 208 158 +214 212 158 239 239 170 251 251 187 251 251 187 224 223 159 204 201 155 +177 172 135 121 119 87 30 31 28 13 13 13 12 12 12 39 40 39 +60 60 56 43 45 43 32 34 33 23 25 24 18 19 18 13 16 16 +13 13 13 9 11 11 8 10 10 8 9 9 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +14 17 17 197 193 154 158 153 112 55 57 54 7 9 9 7 9 9 +8 10 10 51 52 50 58 59 55 60 60 56 63 64 60 63 64 60 +71 71 57 155 149 109 194 191 148 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 190 186 136 +190 186 136 194 189 146 204 201 155 210 208 158 224 223 159 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 190 186 136 164 159 111 +125 122 87 40 41 39 15 15 15 15 15 15 15 15 15 15 15 15 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 15 15 15 14 14 13 13 13 13 12 12 12 +8 9 9 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 21 22 20 96 95 69 125 122 87 121 119 87 +144 139 99 177 172 135 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 204 201 155 194 191 148 194 189 146 204 201 155 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +188 184 146 145 141 105 53 55 47 12 12 12 15 15 15 63 64 60 +63 64 60 41 42 42 31 33 31 23 24 24 17 18 17 12 15 15 +11 13 13 9 11 11 8 9 9 7 9 9 6 8 8 6 8 8 +6 7 7 6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 8 7 +43 45 43 251 251 187 156 151 111 8 10 10 7 9 9 7 9 9 +21 22 21 51 52 50 55 56 53 55 57 54 58 59 55 58 59 55 +75 75 61 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 176 171 126 +125 122 87 36 38 35 14 14 13 14 14 13 15 15 15 15 15 15 +15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 +15 15 15 14 14 13 13 13 13 12 12 12 10 10 9 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 7 7 5 71 71 57 131 127 93 158 153 112 +177 172 135 197 193 154 214 212 158 239 239 170 251 251 187 251 251 187 +238 237 168 210 208 158 204 201 155 197 193 154 204 201 155 214 212 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +197 193 154 156 151 111 66 65 55 12 12 12 37 39 37 58 59 55 +58 59 55 41 42 42 31 33 31 22 24 23 17 17 17 12 14 14 +10 12 12 8 10 10 6 8 8 6 8 8 6 7 7 6 7 7 +6 7 7 5 7 7 6 7 7 6 7 7 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +61 63 57 197 193 154 16 19 19 6 8 8 6 8 8 8 9 9 +41 42 42 47 48 46 51 52 50 51 52 50 55 56 53 55 56 53 +71 71 57 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 224 223 159 204 201 155 177 172 135 +121 119 87 30 31 28 13 13 13 14 14 13 14 14 13 14 14 13 +14 14 13 14 14 13 15 15 15 15 15 15 14 14 13 13 13 13 +12 12 12 12 12 12 10 10 9 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 48 49 45 131 127 93 174 170 121 +194 189 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 197 193 154 204 201 155 210 208 158 +239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 214 212 158 +194 191 148 156 151 111 71 71 57 19 20 19 51 52 50 51 52 50 +51 52 50 41 42 42 30 32 31 21 22 21 17 17 17 13 13 13 +9 11 11 8 9 9 6 8 8 6 7 7 6 7 7 5 7 7 +5 6 5 5 6 5 5 7 7 5 7 7 6 7 7 6 7 7 +6 8 8 6 8 8 6 8 8 6 7 7 6 7 7 6 7 7 +6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +55 56 53 43 45 43 6 8 8 6 8 8 6 8 8 47 48 46 +60 60 56 47 48 46 46 47 45 47 48 46 38 39 37 10 12 12 +66 65 55 145 141 105 197 193 154 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 224 223 159 210 208 158 194 191 148 184 181 136 +184 181 136 194 189 146 204 201 155 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 181 176 137 +115 113 82 21 22 20 13 13 13 13 13 13 13 13 13 13 13 13 +14 14 13 13 13 13 13 13 13 13 13 13 12 12 12 11 11 11 +10 10 9 6 7 7 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 2 2 1 66 65 55 144 139 99 178 174 128 +204 201 155 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 194 191 148 197 193 154 204 201 155 +214 212 158 239 239 170 239 239 170 239 239 170 214 212 158 210 208 158 +184 181 136 149 145 103 66 65 55 41 42 42 47 48 46 46 47 45 +43 45 43 39 40 39 28 31 30 21 22 21 16 16 16 10 12 12 +8 10 10 6 8 8 6 7 7 6 7 7 5 6 5 5 6 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 5 7 7 5 7 7 5 7 7 +5 7 7 6 7 7 6 7 7 6 7 7 6 7 7 6 8 8 +6 8 8 6 8 8 6 7 7 6 7 7 46 47 45 156 151 111 +105 104 92 58 59 55 43 45 43 32 34 33 6 8 8 6 8 8 +49 51 48 125 122 87 181 176 137 204 201 155 214 212 158 239 239 170 +239 239 170 214 212 158 210 208 158 197 193 154 181 176 137 176 171 126 +176 171 126 184 181 136 197 193 154 210 208 158 239 239 170 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +99 98 80 13 13 13 12 12 12 12 12 12 13 13 13 12 12 12 +12 12 12 12 12 12 11 11 11 11 11 11 8 9 9 4 5 5 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 1 1 0 61 61 53 142 137 94 181 176 137 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 197 193 154 190 186 136 184 181 136 188 184 146 +197 193 154 204 201 155 210 208 158 210 208 158 204 201 155 194 189 146 +176 171 126 134 131 96 66 65 55 43 45 43 41 42 42 39 40 39 +35 37 36 33 36 34 27 29 28 20 20 20 15 15 15 9 11 11 +8 9 9 6 7 7 5 6 5 5 6 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 5 6 5 4 5 5 +4 5 5 5 6 5 4 5 5 5 6 5 5 6 5 5 6 5 +5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 28 31 30 184 179 149 184 179 149 +145 141 105 84 83 72 27 29 28 5 7 7 5 6 5 16 16 16 +43 44 41 96 95 69 158 153 112 188 184 146 204 201 155 210 208 158 +204 201 155 197 193 154 184 179 149 177 172 135 168 163 120 164 159 111 +164 159 111 174 170 121 184 181 136 197 193 154 214 212 158 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +71 71 57 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11 +10 10 9 10 10 9 8 8 7 3 4 4 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 31 33 31 121 119 87 176 171 126 +197 193 154 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 210 208 158 194 189 146 178 174 128 174 170 121 176 171 126 +177 172 135 181 176 137 184 179 149 184 179 149 181 176 137 178 174 128 +158 153 112 121 119 87 53 55 47 37 39 37 33 36 34 30 32 31 +27 29 28 25 27 26 24 26 24 19 20 19 13 13 13 8 10 10 +6 8 8 6 7 7 5 6 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 3 4 4 3 4 4 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 +5 6 5 5 6 5 12 14 14 145 141 105 184 179 149 177 172 135 +90 89 73 21 22 21 5 6 5 5 6 5 4 5 5 37 39 37 +38 39 37 61 61 53 134 131 96 168 163 120 184 181 136 188 184 146 +184 179 149 177 172 135 168 163 120 164 159 111 155 149 109 151 147 98 +151 147 98 164 159 111 176 171 126 184 179 149 210 208 158 239 239 170 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 158 153 112 +46 47 43 10 10 9 10 10 9 10 10 9 8 9 9 8 9 9 +6 7 7 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 13 12 7 82 81 62 158 153 112 +188 184 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +224 223 159 204 201 155 184 181 136 171 165 117 164 159 111 160 154 106 +158 153 112 164 159 111 168 163 120 168 163 120 168 163 120 164 159 111 +142 137 94 96 95 69 43 44 41 27 29 28 26 28 27 23 24 24 +21 22 21 18 19 18 17 17 17 18 19 18 13 13 13 8 8 7 +6 7 7 5 6 5 4 5 5 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 3 3 3 4 4 3 4 4 +3 4 4 3 4 4 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 31 33 31 65 66 61 +37 39 37 38 39 37 96 95 69 144 139 99 168 163 120 174 170 121 +168 163 120 164 159 111 155 149 109 149 145 103 149 143 98 142 137 94 +149 143 98 151 147 98 164 159 111 177 172 135 197 193 154 210 208 158 +251 251 187 251 251 187 251 251 187 239 239 170 197 193 154 137 133 100 +24 26 24 8 9 9 8 9 9 8 8 7 6 7 7 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 46 47 43 125 122 87 +176 171 126 197 193 154 210 208 158 239 239 170 251 251 187 239 239 170 +214 212 158 197 193 154 181 176 137 164 159 111 151 147 98 149 143 98 +149 143 98 149 143 98 149 145 103 155 149 109 160 154 106 149 143 98 +118 116 76 82 81 62 30 31 28 21 22 21 19 20 19 17 17 17 +14 14 13 12 12 12 10 10 9 12 12 12 10 12 12 6 8 8 +4 5 5 3 4 4 3 4 4 3 4 4 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 2 3 3 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 4 5 5 +4 5 5 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 3 4 4 3 4 4 23 24 24 110 109 94 72 73 67 +39 40 39 22 24 23 46 47 43 103 101 77 142 137 94 155 149 109 +160 154 106 155 149 109 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 176 171 126 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 214 212 158 184 179 149 105 104 92 +10 10 9 6 7 7 3 4 4 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 12 12 9 82 81 62 +149 145 103 181 176 137 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 197 193 154 177 172 135 158 153 112 149 143 98 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 151 147 98 131 127 93 +103 101 77 71 71 57 22 24 23 15 15 15 13 13 13 11 11 11 +8 9 9 6 7 7 6 7 7 4 5 5 8 9 9 6 7 7 +4 5 5 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 21 22 21 145 141 105 145 141 105 72 73 67 +17 18 17 3 4 4 21 22 20 66 65 55 118 116 76 142 137 94 +149 143 98 151 147 98 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 168 163 120 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 210 208 158 177 172 135 71 71 57 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 +115 113 82 158 153 112 181 176 137 197 193 154 204 201 155 210 208 158 +204 201 155 188 184 146 177 172 135 164 159 111 149 145 103 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 149 143 98 125 122 87 +96 95 69 61 61 53 16 17 12 8 9 9 8 8 7 6 7 7 +4 5 5 3 4 4 3 3 3 3 3 3 3 3 3 5 6 5 +3 4 4 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 +2 2 2 2 2 2 2 3 3 2 3 3 2 3 3 2 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 8 9 9 8 8 7 3 3 3 +3 3 3 3 3 3 9 9 8 36 38 35 82 81 62 118 116 76 +142 137 94 151 147 98 151 147 98 151 147 98 149 143 98 149 143 98 +149 143 98 151 147 98 160 154 106 176 171 126 188 184 146 210 208 158 +239 239 170 251 251 187 239 239 170 210 208 158 156 151 111 31 33 31 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5 +66 65 55 125 122 87 158 153 112 181 176 137 194 189 146 197 193 154 +197 193 154 184 179 149 177 172 135 168 163 120 156 151 111 151 147 98 +151 147 98 151 147 98 151 147 98 161 156 96 149 143 98 118 116 76 +82 81 62 53 55 47 12 12 9 4 5 5 3 4 4 3 3 3 +3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 2 2 +3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 3 3 3 +3 3 3 3 3 3 72 73 67 61 61 53 53 55 47 96 95 69 +131 127 93 151 147 98 161 156 96 161 156 96 151 147 98 151 147 98 +161 156 96 160 154 106 164 159 111 177 172 135 197 193 154 210 208 158 +239 239 170 251 251 187 224 223 159 197 193 154 131 127 93 9 9 8 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +24 26 24 82 81 62 131 127 93 164 159 111 178 174 128 188 184 146 +188 184 146 188 184 146 181 176 137 176 171 126 168 163 120 164 159 111 +160 154 106 160 154 106 160 154 106 160 154 106 151 147 98 125 122 87 +82 81 62 61 61 53 12 12 9 3 3 3 3 3 3 2 2 2 +2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 30 32 31 72 73 67 31 33 31 36 38 35 82 81 62 +118 116 76 149 143 98 161 156 96 161 156 96 161 156 96 160 154 106 +165 161 109 165 161 109 176 171 126 188 184 146 204 201 155 214 212 158 +239 239 170 239 239 170 214 212 158 184 179 149 82 81 62 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 43 44 41 96 95 69 131 127 93 160 154 106 176 171 126 +184 181 136 184 181 136 184 181 136 181 176 137 178 174 128 174 170 121 +171 165 117 173 167 111 173 167 111 173 167 111 160 154 106 131 127 93 +96 95 69 66 65 55 16 17 12 2 2 2 1 1 1 1 1 1 +1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 10 9 6 30 31 28 71 71 57 +118 116 76 149 143 98 165 161 109 165 161 109 165 161 109 173 167 111 +173 167 111 176 171 126 184 181 136 197 193 154 210 208 158 224 223 159 +251 251 187 239 239 170 210 208 158 168 163 120 40 41 39 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 12 7 61 61 53 96 95 69 131 127 93 160 154 106 +176 171 126 184 181 136 184 181 136 188 184 146 184 181 136 184 181 136 +184 181 136 186 182 128 186 182 128 178 174 128 174 170 121 149 145 103 +118 116 76 82 81 62 21 22 20 1 1 1 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 3 3 3 30 31 28 66 65 55 +118 116 76 149 143 98 165 161 109 173 167 111 173 167 111 174 170 121 +186 182 128 190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 239 239 170 197 193 154 137 133 100 12 12 9 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 30 31 28 71 71 57 103 101 77 134 131 96 +164 159 111 176 171 126 184 181 136 188 184 146 194 189 146 197 193 154 +197 193 154 197 193 154 194 191 148 194 189 146 190 186 136 176 171 126 +145 141 105 103 101 77 40 41 39 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 30 31 28 71 71 57 +118 116 76 160 154 106 173 167 111 178 174 128 186 182 128 190 186 136 +194 191 148 204 201 155 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 214 212 158 184 179 149 84 83 72 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 5 3 43 44 41 82 81 62 103 101 77 +142 137 94 165 161 109 178 174 128 190 186 136 197 193 154 204 201 155 +210 208 158 210 208 158 210 208 158 210 208 158 210 208 158 197 193 154 +177 172 135 145 141 105 79 78 62 5 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 30 31 28 82 81 62 +142 137 94 165 161 109 178 174 128 190 186 136 194 191 148 204 201 155 +210 208 158 214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 168 163 120 36 38 35 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 53 55 47 82 81 62 +118 116 76 151 147 98 171 165 117 184 181 136 194 191 148 210 208 158 +214 212 158 224 223 159 239 239 170 239 239 170 224 223 159 214 212 158 +197 193 154 176 171 126 115 113 82 24 26 24 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 40 41 39 103 101 77 +151 147 98 176 171 126 190 186 136 197 193 154 210 208 158 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 197 193 154 110 109 94 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 30 31 28 66 65 55 +96 95 69 125 122 87 160 154 106 178 174 128 194 189 146 204 201 155 +214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 +210 208 158 188 184 146 149 145 103 61 61 53 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 61 61 53 131 127 93 +164 159 111 184 181 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +210 208 158 168 163 120 43 44 41 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 3 2 36 38 35 +71 71 57 96 95 69 142 137 94 165 161 109 184 181 136 197 193 154 +210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 168 163 120 103 101 77 7 7 5 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 0 0 0 0 0 0 0 0 0 82 81 62 142 137 94 +174 170 121 194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 224 223 159 +184 179 149 99 98 80 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5 +43 44 41 82 81 62 118 116 76 142 137 94 171 165 117 190 186 136 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 174 170 121 125 122 87 30 31 28 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 4 3 82 81 62 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 239 239 170 204 201 155 +145 141 105 30 31 28 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 174 170 121 +194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 224 223 159 +210 208 158 194 191 148 174 170 121 134 131 96 53 55 47 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 177 172 135 +75 75 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 +176 171 126 194 191 148 210 208 158 214 212 158 214 212 158 210 208 158 +197 193 154 184 181 136 164 159 111 131 127 93 53 55 47 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98 +174 170 121 194 189 146 204 201 155 214 212 158 239 239 170 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 184 179 149 110 109 94 +12 12 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 9 6 43 44 41 82 81 62 115 113 82 +144 139 99 168 163 120 188 184 146 197 193 154 197 193 154 194 189 146 +184 181 136 174 170 121 151 147 98 118 116 76 36 38 35 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 4 3 2 82 81 62 142 137 94 +171 165 117 186 182 128 194 191 148 210 208 158 214 212 158 224 223 159 +239 239 170 224 223 159 210 208 158 184 179 149 137 133 100 36 38 35 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 36 38 35 71 71 57 +103 101 77 131 127 93 155 149 109 168 163 120 168 163 120 168 163 120 +164 159 111 149 143 98 125 122 87 82 81 62 13 12 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 61 61 53 125 122 87 +160 154 106 174 170 121 184 181 136 194 189 146 204 201 155 210 208 158 +210 208 158 204 201 155 184 179 149 145 141 105 61 61 53 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 30 31 28 +61 61 53 82 81 62 103 101 77 121 119 87 125 122 87 125 122 87 +118 116 76 103 101 77 79 78 62 24 26 24 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 25 27 25 96 95 69 +142 137 94 160 154 106 171 165 117 178 174 128 184 181 136 184 181 136 +181 176 137 177 172 135 145 141 105 75 75 61 5 5 3 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +16 17 12 40 41 39 61 61 53 71 71 57 71 71 57 71 71 57 +66 65 55 43 44 41 12 12 9 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 46 47 43 +96 95 69 125 122 87 142 137 94 149 145 103 155 149 109 155 149 109 +145 141 105 121 119 87 66 65 55 7 7 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 16 17 12 24 26 24 25 27 25 19 20 18 +7 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 +25 27 25 61 61 53 82 81 62 96 95 69 96 95 69 82 81 62 +61 61 53 25 27 25 2 2 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 6 5 13 12 7 10 9 6 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 diff --git a/drivers/video/logo/logo_linux_vga16.ppm b/drivers/video/logo/logo_linux_vga16.ppm index 1850c15e6fe..12ac3a5454c 100644 --- a/drivers/video/logo/logo_linux_vga16.ppm +++ b/drivers/video/logo/logo_linux_vga16.ppm @@ -1,1604 +1,2739 @@ P3 -# Standard 16-color Linux logo -80 80 +142 114 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 85 85 85 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 170 170 170 170 170 -170 170 170 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 170 170 170 255 255 255 255 255 255 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 170 170 170 170 170 170 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 0 0 0 0 0 0 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 170 170 170 0 0 0 85 85 85 -170 170 170 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 85 85 85 0 0 0 0 0 0 - 85 85 85 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 0 0 0 0 0 0 170 170 170 - 85 85 85 85 85 85 85 85 85 85 85 85 -255 255 255 85 85 85 0 0 0 0 0 0 - 85 85 85 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 255 255 255 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 170 170 170 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 170 170 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 85 85 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 85 85 85 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 0 0 0 - 0 0 0 0 0 0 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 170 170 170 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 - 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 85 85 85 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 - 85 85 85 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 170 85 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 85 85 85 85 85 85 170 85 0 -170 85 0 170 85 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 170 170 170 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 255 85 +255 85 85 85 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 255 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 85 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 170 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 85 0 85 255 85 170 85 0 170 85 0 170 85 0 85 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 170 85 0 +255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 170 85 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 85 255 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 170 85 0 +170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 85 0 255 255 85 85 255 85 255 255 85 +170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 255 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 85 0 85 255 85 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 85 0 255 255 85 255 255 85 255 255 255 170 170 170 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 85 255 85 170 85 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 85 255 85 255 255 85 170 170 170 255 255 255 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 170 85 0 +255 255 85 170 85 0 170 85 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +85 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 170 85 0 170 85 0 +170 85 0 85 255 85 255 255 85 85 85 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 255 85 170 170 170 170 170 170 +85 85 85 170 170 170 170 170 170 170 85 0 170 170 170 170 170 170 +85 255 85 170 170 170 170 85 0 170 170 170 85 255 85 255 85 85 +85 255 85 170 170 170 255 255 85 85 85 85 255 255 85 170 170 170 +85 255 85 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 +255 85 85 85 255 85 85 85 85 255 85 85 85 85 85 170 170 170 +170 85 0 170 170 170 85 85 85 85 255 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 85 85 85 85 85 +255 255 85 170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 170 170 170 170 85 0 170 170 170 +170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 0 170 0 +0 0 0 170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +170 170 170 85 85 85 85 85 85 170 170 170 170 85 0 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +170 85 0 255 255 85 170 85 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +85 255 85 170 85 0 0 170 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 170 0 170 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +85 255 85 170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 170 85 0 +0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +255 255 85 85 255 85 170 85 0 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 85 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 +170 85 0 170 85 0 85 255 85 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 +170 85 0 255 255 85 170 85 0 85 255 85 170 85 0 170 85 0 +0 170 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 85 255 85 170 85 0 +255 255 85 170 85 0 0 170 0 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 +0 170 0 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 85 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +170 170 170 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 255 255 255 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 85 85 85 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 85 255 85 170 85 0 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 170 85 0 85 255 85 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 170 85 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 255 85 85 170 170 170 85 255 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 85 85 170 170 170 85 85 85 +170 170 170 170 85 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 85 0 85 255 85 85 85 85 85 85 85 85 85 85 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 255 85 170 170 170 170 170 170 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 255 85 255 85 85 170 170 170 170 170 170 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 +170 170 170 170 170 170 170 85 0 85 85 85 85 85 85 85 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 85 85 85 85 85 85 85 85 85 85 +85 255 85 255 85 85 170 170 170 170 85 0 170 170 170 85 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 +170 170 170 255 85 85 170 170 170 170 170 170 255 255 85 170 170 170 +85 255 85 170 170 170 255 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 0 0 0 85 85 85 +85 85 85 170 85 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 85 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 85 170 170 170 +255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 85 85 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 85 85 85 +85 85 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 +255 255 85 255 255 255 255 255 85 170 170 170 170 170 170 170 85 0 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 255 255 255 255 255 85 255 255 255 255 255 255 170 170 170 +255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 85 170 170 170 255 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 170 85 0 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 255 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +255 85 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 85 255 85 +255 85 85 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 170 170 170 255 255 85 170 170 170 255 85 85 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 255 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +170 170 170 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 85 0 170 170 170 85 85 85 +170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 85 85 85 +85 255 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 85 255 85 170 85 0 170 170 170 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 170 85 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 170 170 +170 85 0 170 85 0 170 170 170 85 255 85 85 85 85 170 170 170 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 85 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 85 85 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 85 0 +85 85 85 255 85 85 85 255 85 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 85 85 85 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 85 85 85 170 170 170 +85 255 85 255 85 85 170 170 170 85 255 85 255 85 85 85 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 85 255 85 255 85 85 170 170 170 85 255 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 85 85 85 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +85 85 85 255 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 85 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +170 85 0 170 170 170 170 85 0 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 +170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 255 255 255 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 85 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 85 255 255 255 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 255 255 85 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 85 0 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 85 0 85 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 85 0 85 85 85 170 85 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 170 170 170 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 48ff701d3a7..2552b9f325e 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -2230,7 +2230,7 @@ static int __devexit pxafb_remove(struct platform_device *dev) static struct platform_driver pxafb_driver = { .probe = pxafb_probe, - .remove = pxafb_remove, + .remove = __devexit_p(pxafb_remove), .suspend = pxafb_suspend, .resume = pxafb_resume, .driver = { diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 0e2b8fd24df..2c5d069e5f0 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -446,7 +446,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) { struct sh_mobile_lcdc_chan *ch; struct sh_mobile_lcdc_board_cfg *board_cfg; - unsigned long tmp; int k; /* tell the board code to disable the panel */ @@ -456,9 +455,8 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) if (board_cfg->display_off) board_cfg->display_off(board_cfg->board_data); - /* cleanup deferred io if SYS bus */ - tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; - if (ch->ldmt1r_value & (1 << 12) && tmp) { + /* cleanup deferred io if enabled */ + if (ch->info.fbdefio) { fb_deferred_io_cleanup(&ch->info); ch->info.fbdefio = NULL; } diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index 9e1138a75e8..a411702413d 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -39,7 +39,7 @@ static u8 w1_gpio_read_bit(void *data) { struct w1_gpio_platform_data *pdata = data; - return gpio_get_value(pdata->pin); + return gpio_get_value(pdata->pin) ? 1 : 0; } static int __init w1_gpio_probe(struct platform_device *pdev) diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 8d0b1fb1e52..1f51366417b 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig @@ -16,6 +16,12 @@ config W1_SLAVE_SMEM Say Y here if you want to connect 1-wire simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. +config W1_SLAVE_DS2431 + tristate "1kb EEPROM family support (DS2431)" + help + Say Y here if you want to use a 1-wire + 1kb EEPROM family device (DS2431) + config W1_SLAVE_DS2433 tristate "4kb EEPROM family support (DS2433)" help diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index 990f400b6d2..f1f51f19b12 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o +obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 858c16a544c..13944714882 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -156,6 +156,9 @@ out_up: */ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) { +#ifdef CONFIG_W1_SLAVE_DS2433_CRC + struct w1_f23_data *f23 = sl->family_data; +#endif u8 wrbuf[4]; u8 rdbuf[W1_PAGE_SIZE + 3]; u8 es = (addr + len - 1) & 0x1f; @@ -196,7 +199,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) /* Reset the bus to wake up the EEPROM (this may not be needed) */ w1_reset_bus(sl->master); - +#ifdef CONFIG_W1_SLAVE_DS2433_CRC + f23->validcrc &= ~(1 << (addr >> W1_PAGE_BITS)); +#endif return 0; } diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index f0c2b7a1a17..734d9806a87 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -269,7 +269,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev, bus_clk = 133; /* in MHz */ freq = fsl_get_sys_freq(); - if (freq > 0) + if (freq != -1) bus_clk = freq; /* Map devices registers into memory */ diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index 0b798fdaa37..74c92d38411 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c @@ -21,6 +21,7 @@ #include <linux/watchdog.h> #include <linux/io.h> #include <linux/uaccess.h> +#include <mach/timex.h> #include <mach/regs-timer.h> #define WDT_DEFAULT_TIME 5 /* seconds */ diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index 14a339f58b6..b64ae1a1783 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c @@ -29,6 +29,7 @@ #define WDT_EN 0x0010 #define WDT_VAL (TIMER_VIRT_BASE + 0x0024) +#define ORION5X_TCLK 166666667 #define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK) #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 57027f4653c..f3553fa40b1 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -34,104 +34,89 @@ #include <asm/time.h> #include <asm/mach-rc32434/integ.h> -#define MAX_TIMEOUT 20 -#define RC32434_WDT_INTERVAL (15 * HZ) - -#define VERSION "0.2" +#define VERSION "0.4" static struct { - struct completion stop; - int running; - struct timer_list timer; - int queue; - int default_ticks; unsigned long inuse; } rc32434_wdt_device; static struct integ __iomem *wdt_reg; -static int ticks = 100 * HZ; static int expect_close; -static int timeout; + +/* Board internal clock speed in Hz, + * the watchdog timer ticks at. */ +extern unsigned int idt_cpu_freq; + +/* translate wtcompare value to seconds and vice versa */ +#define WTCOMP2SEC(x) (x / idt_cpu_freq) +#define SEC2WTCOMP(x) (x * idt_cpu_freq) + +/* Use a default timeout of 20s. This should be + * safe for CPU clock speeds up to 400MHz, as + * ((2 ^ 32) - 1) / (400MHz / 2) = 21s. */ +#define WATCHDOG_TIMEOUT 20 + +static int timeout = WATCHDOG_TIMEOUT; static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +/* apply or and nand masks to data read from addr and write back */ +#define SET_BITS(addr, or, nand) \ + writel((readl(&addr) | or) & ~nand, &addr) static void rc32434_wdt_start(void) { - u32 val; - - if (!rc32434_wdt_device.inuse) { - writel(0, &wdt_reg->wtcount); + u32 or, nand; - val = RC32434_ERR_WRE; - writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs); + /* zero the counter before enabling */ + writel(0, &wdt_reg->wtcount); - val = RC32434_WTC_EN; - writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc); - } - rc32434_wdt_device.running++; -} + /* don't generate a non-maskable interrupt, + * do a warm reset instead */ + nand = 1 << RC32434_ERR_WNE; + or = 1 << RC32434_ERR_WRE; -static void rc32434_wdt_stop(void) -{ - u32 val; + /* reset the ERRCS timeout bit in case it's set */ + nand |= 1 << RC32434_ERR_WTO; - if (rc32434_wdt_device.running) { + SET_BITS(wdt_reg->errcs, or, nand); - val = ~RC32434_WTC_EN; - writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); + /* reset WTC timeout bit and enable WDT */ + nand = 1 << RC32434_WTC_TO; + or = 1 << RC32434_WTC_EN; - val = ~RC32434_ERR_WRE; - writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs); + SET_BITS(wdt_reg->wtc, or, nand); +} - rc32434_wdt_device.running = 0; - } +static void rc32434_wdt_stop(void) +{ + /* Disable WDT */ + SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN); } -static void rc32434_wdt_set(int new_timeout) +static int rc32434_wdt_set(int new_timeout) { - u32 cmp = new_timeout * HZ; - u32 state, val; + int max_to = WTCOMP2SEC((u32)-1); + if (new_timeout < 0 || new_timeout > max_to) { + printk(KERN_ERR KBUILD_MODNAME + ": timeout value must be between 0 and %d", + max_to); + return -EINVAL; + } timeout = new_timeout; - /* - * store and disable WTC - */ - state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN); - val = ~RC32434_WTC_EN; - writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); - - writel(0, &wdt_reg->wtcount); - writel(cmp, &wdt_reg->wtcompare); - - /* - * restore WTC - */ - - writel(readl(&wdt_reg->wtc) | state, &wdt_reg); -} + writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); -static void rc32434_wdt_reset(void) -{ - ticks = rc32434_wdt_device.default_ticks; + return 0; } -static void rc32434_wdt_update(unsigned long unused) +static void rc32434_wdt_ping(void) { - if (rc32434_wdt_device.running) - ticks--; - writel(0, &wdt_reg->wtcount); - - if (rc32434_wdt_device.queue && ticks) - mod_timer(&rc32434_wdt_device.timer, - jiffies + RC32434_WDT_INTERVAL); - else - complete(&rc32434_wdt_device.stop); } static int rc32434_wdt_open(struct inode *inode, struct file *file) @@ -142,19 +127,23 @@ static int rc32434_wdt_open(struct inode *inode, struct file *file) if (nowayout) __module_get(THIS_MODULE); + rc32434_wdt_start(); + rc32434_wdt_ping(); + return nonseekable_open(inode, file); } static int rc32434_wdt_release(struct inode *inode, struct file *file) { - if (expect_close && nowayout == 0) { + if (expect_close == 42) { rc32434_wdt_stop(); printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n"); module_put(THIS_MODULE); - } else + } else { printk(KERN_CRIT KBUILD_MODNAME ": device closed unexpectedly. WDT will not stop !\n"); - + rc32434_wdt_ping(); + } clear_bit(0, &rc32434_wdt_device.inuse); return 0; } @@ -174,10 +163,10 @@ static ssize_t rc32434_wdt_write(struct file *file, const char *data, if (get_user(c, data + i)) return -EFAULT; if (c == 'V') - expect_close = 1; + expect_close = 42; } } - rc32434_wdt_update(0); + rc32434_wdt_ping(); return len; } return 0; @@ -197,11 +186,11 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, }; switch (cmd) { case WDIOC_KEEPALIVE: - rc32434_wdt_reset(); + rc32434_wdt_ping(); break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - value = readl(&wdt_reg->wtcount); + value = 0; if (copy_to_user(argp, &value, sizeof(int))) return -EFAULT; break; @@ -218,6 +207,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, break; case WDIOS_DISABLECARD: rc32434_wdt_stop(); + break; default: return -EINVAL; } @@ -225,11 +215,9 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, case WDIOC_SETTIMEOUT: if (copy_from_user(&new_timeout, argp, sizeof(int))) return -EFAULT; - if (new_timeout < 1) + if (rc32434_wdt_set(new_timeout)) return -EINVAL; - if (new_timeout > MAX_TIMEOUT) - return -EINVAL; - rc32434_wdt_set(new_timeout); + /* Fall through */ case WDIOC_GETTIMEOUT: return copy_to_user(argp, &timeout, sizeof(int)); default: @@ -254,15 +242,15 @@ static struct miscdevice rc32434_wdt_miscdev = { .fops = &rc32434_wdt_fops, }; -static char banner[] = KERN_INFO KBUILD_MODNAME +static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME ": Watchdog Timer version " VERSION ", timer margin: %d sec\n"; -static int rc32434_wdt_probe(struct platform_device *pdev) +static int __devinit rc32434_wdt_probe(struct platform_device *pdev) { int ret; struct resource *r; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res"); + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res"); if (!r) { printk(KERN_ERR KBUILD_MODNAME "failed to retrieve resources\n"); @@ -277,24 +265,12 @@ static int rc32434_wdt_probe(struct platform_device *pdev) } ret = misc_register(&rc32434_wdt_miscdev); - if (ret < 0) { printk(KERN_ERR KBUILD_MODNAME "failed to register watchdog device\n"); goto unmap; } - init_completion(&rc32434_wdt_device.stop); - rc32434_wdt_device.queue = 0; - - clear_bit(0, &rc32434_wdt_device.inuse); - - setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L); - - rc32434_wdt_device.default_ticks = ticks; - - rc32434_wdt_start(); - printk(banner, timeout); return 0; @@ -304,23 +280,17 @@ unmap: return ret; } -static int rc32434_wdt_remove(struct platform_device *pdev) +static int __devexit rc32434_wdt_remove(struct platform_device *pdev) { - if (rc32434_wdt_device.queue) { - rc32434_wdt_device.queue = 0; - wait_for_completion(&rc32434_wdt_device.stop); - } misc_deregister(&rc32434_wdt_miscdev); - iounmap(wdt_reg); - return 0; } static struct platform_driver rc32434_wdt = { .probe = rc32434_wdt_probe, - .remove = rc32434_wdt_remove, - .driver = { + .remove = __devexit_p(rc32434_wdt_remove), + .driver = { .name = "rc32434_wdt", } }; |