diff options
Diffstat (limited to 'drivers')
293 files changed, 3659 insertions, 22124 deletions
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 68d9744..12878e1 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -45,10 +45,71 @@ #include "accommon.h" #include "acdispat.h" #include "acinterp.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exfield") +/* Local prototypes */ +static u32 +acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); + +/******************************************************************************* + * + * FUNCTION: acpi_get_serial_access_bytes + * + * PARAMETERS: accessor_type - The type of the protocol indicated by region + * field access attributes + * access_length - The access length of the region field + * + * RETURN: Decoded access length + * + * DESCRIPTION: This routine returns the length of the generic_serial_bus + * protocol bytes + * + ******************************************************************************/ + +static u32 +acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) +{ + u32 length; + + switch (accessor_type) { + case AML_FIELD_ATTRIB_QUICK: + + length = 0; + break; + + case AML_FIELD_ATTRIB_SEND_RCV: + case AML_FIELD_ATTRIB_BYTE: + + length = 1; + break; + + case AML_FIELD_ATTRIB_WORD: + case AML_FIELD_ATTRIB_WORD_CALL: + + length = 2; + break; + + case AML_FIELD_ATTRIB_MULTIBYTE: + case AML_FIELD_ATTRIB_RAW_BYTES: + case AML_FIELD_ATTRIB_RAW_PROCESS: + + length = access_length; + break; + + case AML_FIELD_ATTRIB_BLOCK: + case AML_FIELD_ATTRIB_BLOCK_CALL: + default: + + length = ACPI_GSBUS_BUFFER_SIZE; + break; + } + + return (length); +} + /******************************************************************************* * * FUNCTION: acpi_ex_read_data_from_field @@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield") * Buffer, depending on the size of the field. * ******************************************************************************/ + acpi_status -acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, +acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, union acpi_operand_object *obj_desc, union acpi_operand_object **ret_buffer_desc) { @@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, acpi_size length; void *buffer; u32 function; + u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ACPI_READ | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { - length = ACPI_GSBUS_BUFFER_SIZE; - function = - ACPI_READ | (obj_desc->field.attribute << 16); + accessor_type = obj_desc->field.attribute; + length = acpi_ex_get_serial_access_length(accessor_type, + obj_desc-> + field. + access_length); + + /* + * Add additional 2 bytes for modeled generic_serial_bus data buffer: + * typedef struct { + * BYTEStatus; // Byte 0 of the data buffer + * BYTELength; // Byte 1 of the data buffer + * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, + * } + */ + length += 2; + function = ACPI_READ | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; @@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, void *buffer; union acpi_operand_object *buffer_desc; u32 function; + u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ACPI_WRITE | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { - length = ACPI_GSBUS_BUFFER_SIZE; - function = - ACPI_WRITE | (obj_desc->field.attribute << 16); + accessor_type = obj_desc->field.attribute; + length = acpi_ex_get_serial_access_length(accessor_type, + obj_desc-> + field. + access_length); + + /* + * Add additional 2 bytes for modeled generic_serial_bus data buffer: + * typedef struct { + * BYTEStatus; // Byte 0 of the data buffer + * BYTELength; // Byte 1 of the data buffer + * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, + * } + */ + length += 2; + function = ACPI_WRITE | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e7e5844..cf925c4 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -380,9 +380,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) break; default: - acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); - ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; - goto err; + acpi_handle_debug(handle, "Unknown event type 0x%x\n", type); + break; } adev = acpi_bus_get_acpi_device(handle); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 20e03a7..c270604 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -116,7 +116,7 @@ config AHCI_ST config AHCI_IMX tristate "Freescale i.MX AHCI SATA support" - depends on MFD_SYSCON + depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST) help This option enables support for the Freescale i.MX SoC's onboard AHCI SATA. @@ -134,8 +134,7 @@ config AHCI_SUNXI config AHCI_XGENE tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support" - depends on ARM64 || COMPILE_TEST - select PHY_XGENE + depends on PHY_XGENE help This option enables support for APM X-Gene SoC SATA host controller. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5a0bf8e..71e15b7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1164,9 +1164,9 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) #endif static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, - struct ahci_host_priv *hpriv) + struct ahci_host_priv *hpriv) { - int nvec; + int rc, nvec; if (hpriv->flags & AHCI_HFLAG_NO_MSI) goto intx; @@ -1183,12 +1183,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, if (nvec < n_ports) goto single_msi; - nvec = pci_enable_msi_range(pdev, nvec, nvec); - if (nvec == -ENOSPC) + rc = pci_enable_msi_exact(pdev, nvec); + if (rc == -ENOSPC) goto single_msi; - else if (nvec < 0) + else if (rc < 0) goto intx; + /* fallback to single MSI mode if the controller enforced MRSM mode */ + if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { + pci_disable_msi(pdev); + printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); + goto single_msi; + } + return nvec; single_msi: @@ -1232,18 +1239,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) return rc; for (i = 0; i < host->n_ports; i++) { - const char* desc; struct ahci_port_priv *pp = host->ports[i]->private_data; - /* pp is NULL for dummy ports */ - if (pp) - desc = pp->irq_desc; - else - desc = dev_driver_string(host->dev); + /* Do not receive interrupts sent by dummy ports */ + if (!pp) { + disable_irq(irq + i); + continue; + } - rc = devm_request_threaded_irq(host->dev, - irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED, - desc, host->ports[i]); + rc = devm_request_threaded_irq(host->dev, irq + i, + ahci_hw_interrupt, + ahci_thread_fn, IRQF_SHARED, + pp->irq_desc, host->ports[i]); if (rc) goto out_free_irqs; } diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 51af275..b5eb886 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -94,6 +94,7 @@ enum { /* HOST_CTL bits */ HOST_RESET = (1 << 0), /* reset controller; self-clear */ HOST_IRQ_EN = (1 << 1), /* global IRQ enable */ + HOST_MRSM = (1 << 2), /* MSI Revert to Single Message */ HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ /* HOST_CAP bits */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c19734d..943cc8b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4224,8 +4224,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER }, /* devices that don't properly handle queued TRIM commands */ - { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, - { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Micron_M500*", "MU0[1-4]*", ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M500SSD*", "MU0[1-4]*", ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, /* * Some WD SATA-I drives spin up and down erratically when the link @@ -4792,21 +4794,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) { struct ata_queued_cmd *qc = NULL; - unsigned int i; + unsigned int i, tag; /* no command while frozen */ if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) return NULL; - /* the last tag is reserved for internal command. */ - for (i = 0; i < ATA_MAX_QUEUE - 1; i++) - if (!test_and_set_bit(i, &ap->qc_allocated)) { - qc = __ata_qc_from_tag(ap, i); + for (i = 0; i < ATA_MAX_QUEUE; i++) { + tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE; + + /* the last tag is reserved for internal command. */ + if (tag == ATA_TAG_INTERNAL) + continue; + + if (!test_and_set_bit(tag, &ap->qc_allocated)) { + qc = __ata_qc_from_tag(ap, tag); + qc->tag = tag; + ap->last_tag = tag; break; } - - if (qc) - qc->tag = i; + } return qc; } diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 6fac524..4edb1a8 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -898,9 +898,12 @@ static int arasan_cf_probe(struct platform_device *pdev) cf_card_detect(acdev, 0); - return ata_host_activate(host, acdev->irq, irq_handler, 0, - &arasan_cf_sht); + ret = ata_host_activate(host, acdev->irq, irq_handler, 0, + &arasan_cf_sht); + if (!ret) + return 0; + cf_exit(acdev); free_clk: clk_put(acdev->clk); return ret; diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index e9c8727..8a66f23 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -407,12 +407,13 @@ static int pata_at91_probe(struct platform_device *pdev) host->private_data = info; - return ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0, - gpio_is_valid(irq) ? ata_sff_interrupt : NULL, - irq_flags, &pata_at91_sht); + ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0, + gpio_is_valid(irq) ? ata_sff_interrupt : NULL, + irq_flags, &pata_at91_sht); + if (ret) + goto err_put; - if (!ret) - return 0; + return 0; err_put: clk_put(info->mck); diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index a79566d..0610e78 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c @@ -594,9 +594,13 @@ static int __init pata_s3c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); - return ata_host_activate(host, info->irq, - info->irq ? pata_s3c_irq : NULL, - 0, &pata_s3c_sht); + ret = ata_host_activate(host, info->irq, + info->irq ? pata_s3c_irq : NULL, + 0, &pata_s3c_sht); + if (ret) + goto stop_clk; + + return 0; stop_clk: clk_disable(info->clk); diff --git a/drivers/base/core.c b/drivers/base/core.c index 0dd6528..20da3ad 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev, } EXPORT_SYMBOL_GPL(device_remove_bin_file); -/** - * device_schedule_callback_owner - helper to schedule a callback for a device - * @dev: device. - * @func: callback function to invoke later. - * @owner: module owning the callback routine - * - * Attribute methods must not unregister themselves or their parent device - * (which would amount to the same thing). Attempts to do so will deadlock, - * since unregistration is mutually exclusive with driver callbacks. - * - * Instead methods can call this routine, which will attempt to allocate - * and schedule a workqueue request to call back @func with @dev as its - * argument in the workqueue's process context. @dev will be pinned until - * @func returns. - * - * This routine is usually called via the inline device_schedule_callback(), - * which automatically sets @owner to THIS_MODULE. - * - * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated, -ENODEV if a reference to @owner isn't available. - * - * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an - * underlying sysfs routine (since it is intended for use by attribute - * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. - */ -int device_schedule_callback_owner(struct device *dev, - void (*func)(struct device *), struct module *owner) -{ - return sysfs_schedule_callback(&dev->kobj, - (void (*)(void *)) func, dev, owner); -} -EXPORT_SYMBOL_GPL(device_schedule_callback_owner); - static void klist_children_get(struct klist_node *n) { struct device_private *p = to_device_private_parent(n); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0605176..8986b9f 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -187,8 +187,8 @@ static void driver_bound(struct device *dev) return; } - pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev), - __func__, dev->driver->name); + pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name, + __func__, dev_name(dev)); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); diff --git a/drivers/base/topology.c b/drivers/base/topology.c index bbcbd3c..be7c1fb 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -39,8 +39,7 @@ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ - unsigned int cpu = dev->id; \ - return sprintf(buf, "%d\n", topology_##name(cpu)); \ + return sprintf(buf, "%d\n", topology_##name(dev->id)); \ } #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \ diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fbae63e..6e9f74a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -40,7 +40,7 @@ config SGI_MBCS source "drivers/tty/serial/Kconfig" config TTY_PRINTK - bool "TTY driver to output user messages via printk" + tristate "TTY driver to output user messages via printk" depends on EXPERT && TTY default n ---help--- diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index b27f534..8d3dfb0 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig @@ -15,7 +15,7 @@ config SYNCLINK_CS This driver may be built as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called synclinkmp. If you want to do that, say M + The module will be called synclink_cs. If you want to do that, say M here. config CARDMAN_4000 diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index daea84c..a15ce4e 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -17,7 +17,7 @@ #include <linux/device.h> #include <linux/serial.h> #include <linux/tty.h> -#include <linux/export.h> +#include <linux/module.h> struct ttyprintk_port { struct tty_port port; @@ -210,10 +210,19 @@ static int __init ttyprintk_init(void) return 0; error: - tty_unregister_driver(ttyprintk_driver); put_tty_driver(ttyprintk_driver); tty_port_destroy(&tpk_port.port); - ttyprintk_driver = NULL; return ret; } + +static void __exit ttyprintk_exit(void) +{ + tty_unregister_driver(ttyprintk_driver); + put_tty_driver(ttyprintk_driver); + tty_port_destroy(&tpk_port.port); +} + device_initcall(ttyprintk_init); +module_exit(ttyprintk_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 166e02f..cc37c34 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -764,7 +764,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true }, [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true }, [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true }, - [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true }, [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true }, [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true }, @@ -809,7 +808,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_trace] = { .dt_id = TEGRA124_CLK_TRACE, .present = true }, [tegra_clk_soc_therm] = { .dt_id = TEGRA124_CLK_SOC_THERM, .present = true }, [tegra_clk_dtv] = { .dt_id = TEGRA124_CLK_DTV, .present = true }, - [tegra_clk_ndspeed] = { .dt_id = TEGRA124_CLK_NDSPEED, .present = true }, [tegra_clk_i2cslow] = { .dt_id = TEGRA124_CLK_I2CSLOW, .present = true }, [tegra_clk_dsib] = { .dt_id = TEGRA124_CLK_DSIB, .present = true }, [tegra_clk_tsec] = { .dt_id = TEGRA124_CLK_TSEC, .present = true }, @@ -952,7 +950,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true }, [tegra_clk_dsia_mux] = { .dt_id = TEGRA124_CLK_DSIA_MUX, .present = true }, [tegra_clk_dsib_mux] = { .dt_id = TEGRA124_CLK_DSIB_MUX, .present = true }, - [tegra_clk_uarte] = { .dt_id = TEGRA124_CLK_UARTE, .present = true }, }; static struct tegra_devclk devclks[] __initdata = { diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index 2dc8b41..a535c7b 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -102,7 +102,7 @@ void __init vexpress_osc_of_setup(struct device_node *node) osc = kzalloc(sizeof(*osc), GFP_KERNEL); if (!osc) - goto error; + return; osc->func = vexpress_config_func_get_by_node(node); if (!osc->func) { diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 0e9cce8..5805035 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -92,11 +92,7 @@ config ARM_EXYNOS_CPU_FREQ_BOOST_SW config ARM_HIGHBANK_CPUFREQ tristate "Calxeda Highbank-based" - depends on ARCH_HIGHBANK - select GENERIC_CPUFREQ_CPU0 - select PM_OPP - select REGULATOR - + depends on ARCH_HIGHBANK && GENERIC_CPUFREQ_CPU0 && REGULATOR default m help This adds the CPUFreq driver for Calxeda Highbank SoC diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 9edccc6..af49688 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -29,6 +29,7 @@ #include <asm/cputhreads.h> #include <asm/reg.h> +#include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ #define POWERNV_MAX_PSTATES 256 diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index b7e677b..a1ca3dd 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -206,7 +206,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) per_cpu(cpu_data, i) = data; policy->cpuinfo.transition_latency = - (12 * NSEC_PER_SEC) / fsl_get_sys_freq(); + (12ULL * NSEC_PER_SEC) / fsl_get_sys_freq(); of_node_put(np); return 0; diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c index 8d045af..6f9dfa8 100644 --- a/drivers/cpufreq/unicore2-cpufreq.c +++ b/drivers/cpufreq/unicore2-cpufreq.c @@ -60,9 +60,7 @@ static int __init ucv2_cpu_init(struct cpufreq_policy *policy) policy->max = policy->cpuinfo.max_freq = 1000000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->clk = clk_get(NULL, "MAIN_CLK"); - if (IS_ERR(policy->clk)) - return PTR_ERR(policy->clk); - return 0; + return PTR_ERR_OR_ZERO(policy->clk); } static struct cpufreq_driver ucv2_driver = { diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ba06d1d..5c58638 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -197,7 +197,7 @@ config AMCC_PPC440SPE_ADMA config TIMB_DMA tristate "Timberdale FPGA DMA support" - depends on MFD_TIMBERDALE || HAS_IOMEM + depends on MFD_TIMBERDALE select DMA_ENGINE help Enable support for the Timberdale FPGA DMA engine. diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index cd04eb7b..926360c 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -182,11 +182,13 @@ static void edma_execute(struct edma_chan *echan) echan->ecc->dummy_slot); } - edma_resume(echan->ch_num); - if (edesc->processed <= MAX_NR_SG) { dev_dbg(dev, "first transfer starting %d\n", echan->ch_num); edma_start(echan->ch_num); + } else { + dev_dbg(dev, "chan: %d: completed %d elements, resuming\n", + echan->ch_num, edesc->processed); + edma_resume(echan->ch_num); } /* diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c index 381e793..b396a7f 100644 --- a/drivers/dma/fsl-edma.c +++ b/drivers/dma/fsl-edma.c @@ -968,7 +968,17 @@ static struct platform_driver fsl_edma_driver = { .remove = fsl_edma_remove, }; -module_platform_driver(fsl_edma_driver); +static int __init fsl_edma_init(void) +{ + return platform_driver_register(&fsl_edma_driver); +} +subsys_initcall(fsl_edma_init); + +static void __exit fsl_edma_exit(void) +{ + platform_driver_unregister(&fsl_edma_driver); +} +module_exit(fsl_edma_exit); MODULE_ALIAS("platform:fsl-edma"); MODULE_DESCRIPTION("Freescale eDMA engine driver"); diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index a1bd829..03f7820 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -666,7 +666,7 @@ static struct dma_chan *of_dma_sirfsoc_xlate(struct of_phandle_args *dma_spec, struct sirfsoc_dma *sdma = ofdma->of_dma_data; unsigned int request = dma_spec->args[0]; - if (request > SIRFSOC_DMA_CHANNELS) + if (request >= SIRFSOC_DMA_CHANNELS) return NULL; return dma_get_slave_channel(&sdma->channels[request].chan); diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index e9a0415..30bcc53 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -2,7 +2,7 @@ * SPEAr platform SPI chipselect abstraction over gpiolib * * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim <shiraz.hashim@st.com> + * Shiraz Hashim <shiraz.linux.kernel@gmail.com> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -205,6 +205,6 @@ static int __init spics_gpio_init(void) } subsys_initcall(spics_gpio_init); -MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>"); +MODULE_AUTHOR("Shiraz Hashim <shiraz.linux.kernel@gmail.com>"); MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index bf0f8b4..401add2 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -233,7 +233,7 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio) { struct gpio_chip *chip = acpi_gpio->chip; - if (!chip->dev || !chip->to_irq) + if (!chip->to_irq) return; INIT_LIST_HEAD(&acpi_gpio->events); @@ -253,7 +253,7 @@ static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio) struct acpi_gpio_event *event, *ep; struct gpio_chip *chip = acpi_gpio->chip; - if (!chip->dev || !chip->to_irq) + if (!chip->to_irq) return; list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) { @@ -451,7 +451,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, if (function == ACPI_WRITE) gpiod_set_raw_value(desc, !!((1 << i) & *value)); else - *value |= gpiod_get_raw_value(desc) << i; + *value |= (u64)gpiod_get_raw_value(desc) << i; } out: @@ -501,6 +501,9 @@ void acpi_gpiochip_add(struct gpio_chip *chip) acpi_handle handle; acpi_status status; + if (!chip || !chip->dev) + return; + handle = ACPI_HANDLE(chip->dev); if (!handle) return; @@ -531,6 +534,9 @@ void acpi_gpiochip_remove(struct gpio_chip *chip) acpi_handle handle; acpi_status status; + if (!chip || !chip->dev) + return; + handle = ACPI_HANDLE(chip->dev); if (!handle) return; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 761013f..f48817d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1387,8 +1387,8 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, { struct gpio_chip *chip = d->host_data; - irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); irq_set_chip_data(irq, chip); + irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9d25dbb..48e38ba 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -23,7 +23,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-usb-y := drm_usb.o -drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o +drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 977cfb3..635f6ff 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -572,7 +572,7 @@ static u32 cbr_scan2(struct ast_private *ast) for (loop = 0; loop < CBR_PASSNUM2; loop++) { if ((data = cbr_test2(ast)) != 0) { data2 &= data; - if (!data) + if (!data2) return 0; break; } diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 741965c..7eb52dd 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -1,5 +1,6 @@ #include <linux/io.h> #include <linux/fb.h> +#include <linux/console.h> #include <drm/drmP.h> #include <drm/drm_crtc.h> @@ -87,8 +88,6 @@ struct bochs_device { struct bochs_framebuffer gfb; struct drm_fb_helper helper; int size; - int x1, y1, x2, y2; /* dirty rect */ - spinlock_t dirty_lock; bool initialized; } fb; }; diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 395bba2..9c13df2 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -95,6 +95,49 @@ static struct drm_driver bochs_driver = { }; /* ---------------------------------------------------------------------- */ +/* pm interface */ + +static int bochs_pm_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct bochs_device *bochs = drm_dev->dev_private; + + drm_kms_helper_poll_disable(drm_dev); + + if (bochs->fb.initialized) { + console_lock(); + fb_set_suspend(bochs->fb.helper.fbdev, 1); + console_unlock(); + } + + return 0; +} + +static int bochs_pm_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct bochs_device *bochs = drm_dev->dev_private; + + drm_helper_resume_force_mode(drm_dev); + + if (bochs->fb.initialized) { + console_lock(); + fb_set_suspend(bochs->fb.helper.fbdev, 0); + console_unlock(); + } + + drm_kms_helper_poll_enable(drm_dev); + return 0; +} + +static const struct dev_pm_ops bochs_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend, + bochs_pm_resume) +}; + +/* ---------------------------------------------------------------------- */ /* pci interface */ static int bochs_kick_out_firmware_fb(struct pci_dev *pdev) @@ -155,6 +198,7 @@ static struct pci_driver bochs_pci_driver = { .id_table = bochs_pci_tbl, .probe = bochs_pci_probe, .remove = bochs_pci_remove, + .driver.pm = &bochs_pm_ops, }; /* ---------------------------------------------------------------------- */ diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index 4da5206..561b844 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c @@ -190,7 +190,6 @@ int bochs_fbdev_init(struct bochs_device *bochs) int ret; bochs->fb.helper.funcs = &bochs_fb_helper_funcs; - spin_lock_init(&bochs->fb.dirty_lock); ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, 1, 1); diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 953fc8a..08ce520 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/console.h> #include <drm/drmP.h> +#include <drm/drm_crtc_helper.h> #include "cirrus_drv.h" @@ -75,6 +76,41 @@ static void cirrus_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } +static int cirrus_pm_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct cirrus_device *cdev = drm_dev->dev_private; + + drm_kms_helper_poll_disable(drm_dev); + + if (cdev->mode_info.gfbdev) { + console_lock(); + fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1); + console_unlock(); + } + + return 0; +} + +static int cirrus_pm_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct cirrus_device *cdev = drm_dev->dev_private; + + drm_helper_resume_force_mode(drm_dev); + + if (cdev->mode_info.gfbdev) { + console_lock(); + fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0); + console_unlock(); + } + + drm_kms_helper_poll_enable(drm_dev); + return 0; +} + static const struct file_operations cirrus_driver_fops = { .owner = THIS_MODULE, .open = drm_open, @@ -103,11 +139,17 @@ static struct drm_driver driver = { .dumb_destroy = drm_gem_dumb_destroy, }; +static const struct dev_pm_ops cirrus_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend, + cirrus_pm_resume) +}; + static struct pci_driver cirrus_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, .probe = cirrus_pci_probe, .remove = cirrus_pci_remove, + .driver.pm = &cirrus_pm_ops, }; static int __init cirrus_init(void) diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 2d64aea..f59433b 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -308,6 +308,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, WREG_HDR(hdr); cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); + + /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ + outb(0x20, 0x3c0); return 0; } diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index c43825e..df281b5 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -72,147 +72,6 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) } EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); -static bool drm_kms_helper_poll = true; -module_param_named(poll, drm_kms_helper_poll, bool, 0600); - -static void drm_mode_validate_flag(struct drm_connector *connector, - int flags) -{ - struct drm_display_mode *mode; - - if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | - DRM_MODE_FLAG_3D_MASK)) - return; - - list_for_each_entry(mode, &connector->modes, head) { - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && - !(flags & DRM_MODE_FLAG_INTERLACE)) - mode->status = MODE_NO_INTERLACE; - if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && - !(flags & DRM_MODE_FLAG_DBLSCAN)) - mode->status = MODE_NO_DBLESCAN; - if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && - !(flags & DRM_MODE_FLAG_3D_MASK)) - mode->status = MODE_NO_STEREO; - } - - return; -} - -/** - * drm_helper_probe_single_connector_modes - get complete set of display modes - * @connector: connector to probe - * @maxX: max width for modes - * @maxY: max height for modes - * - * Based on the helper callbacks implemented by @connector try to detect all - * valid modes. Modes will first be added to the connector's probed_modes list, - * then culled (based on validity and the @maxX, @maxY parameters) and put into - * the normal modes list. - * - * Intended to be use as a generic implementation of the ->fill_modes() - * @connector vfunc for drivers that use the crtc helpers for output mode - * filtering and detection. - * - * Returns: - * The number of modes found on @connector. - */ -int drm_helper_probe_single_connector_modes(struct drm_connector *connector, - uint32_t maxX, uint32_t maxY) -{ - struct drm_device *dev = connector->dev; - struct drm_display_mode *mode; - struct drm_connector_helper_funcs *connector_funcs = - connector->helper_private; - int count = 0; - int mode_flags = 0; - bool verbose_prune = true; - - WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, - drm_get_connector_name(connector)); - /* set all modes to the unverified state */ - list_for_each_entry(mode, &connector->modes, head) - mode->status = MODE_UNVERIFIED; - - if (connector->force) { - if (connector->force == DRM_FORCE_ON) - connector->status = connector_status_connected; - else - connector->status = connector_status_disconnected; - if (connector->funcs->force) - connector->funcs->force(connector); - } else { - connector->status = connector->funcs->detect(connector, true); - } - - /* Re-enable polling in case the global poll config changed. */ - if (drm_kms_helper_poll != dev->mode_config.poll_running) - drm_kms_helper_poll_enable(dev); - - dev->mode_config.poll_running = drm_kms_helper_poll; - - if (connector->status == connector_status_disconnected) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", - connector->base.id, drm_get_connector_name(connector)); - drm_mode_connector_update_edid_property(connector, NULL); - verbose_prune = false; - goto prune; - } - -#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE - count = drm_load_edid_firmware(connector); - if (count == 0) -#endif - count = (*connector_funcs->get_modes)(connector); - - if (count == 0 && connector->status == connector_status_connected) - count = drm_add_modes_noedid(connector, 1024, 768); - if (count == 0) - goto prune; - - drm_mode_connector_list_update(connector); - - if (maxX && maxY) - drm_mode_validate_size(dev, &connector->modes, maxX, maxY); - - if (connector->interlace_allowed) - mode_flags |= DRM_MODE_FLAG_INTERLACE; - if (connector->doublescan_allowed) - mode_flags |= DRM_MODE_FLAG_DBLSCAN; - if (connector->stereo_allowed) - mode_flags |= DRM_MODE_FLAG_3D_MASK; - drm_mode_validate_flag(connector, mode_flags); - - list_for_each_entry(mode, &connector->modes, head) { - if (mode->status == MODE_OK) - mode->status = connector_funcs->mode_valid(connector, - mode); - } - -prune: - drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); - - if (list_empty(&connector->modes)) - return 0; - - list_for_each_entry(mode, &connector->modes, head) - mode->vrefresh = drm_mode_vrefresh(mode); - - drm_mode_sort(&connector->modes); - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, - drm_get_connector_name(connector)); - list_for_each_entry(mode, &connector->modes, head) { - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - drm_mode_debug_printmodeline(mode); - } - - return count; -} -EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); - /** * drm_helper_encoder_in_use - check if a given encoder is in use * @encoder: encoder to check @@ -1020,232 +879,3 @@ void drm_helper_resume_force_mode(struct drm_device *dev) drm_modeset_unlock_all(dev); } EXPORT_SYMBOL(drm_helper_resume_force_mode); - -/** - * drm_kms_helper_hotplug_event - fire off KMS hotplug events - * @dev: drm_device whose connector state changed - * - * This function fires off the uevent for userspace and also calls the - * output_poll_changed function, which is most commonly used to inform the fbdev - * emulation code and allow it to update the fbcon output configuration. - * - * Drivers should call this from their hotplug handling code when a change is - * detected. Note that this function does not do any output detection of its - * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the - * driver already. - * - * This function must be called from process context with no mode - * setting locks held. - */ -void drm_kms_helper_hotplug_event(struct drm_device *dev) -{ - /* send a uevent + call fbdev */ - drm_sysfs_hotplug_event(dev); - if (dev->mode_config.funcs->output_poll_changed) - dev->mode_config.funcs->output_poll_changed(dev); -} -EXPORT_SYMBOL(drm_kms_helper_hotplug_event); - -#define DRM_OUTPUT_POLL_PERIOD (10*HZ) -static void output_poll_execute(struct work_struct *work) -{ - struct delayed_work *delayed_work = to_delayed_work(work); - struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); - struct drm_connector *connector; - enum drm_connector_status old_status; - bool repoll = false, changed = false; - - if (!drm_kms_helper_poll) - return; - - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - - /* Ignore forced connectors. */ - if (connector->force) - continue; - - /* Ignore HPD capable connectors and connectors where we don't - * want any hotplug detection at all for polling. */ - if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) - continue; - - repoll = true; - - old_status = connector->status; - /* if we are connected and don't want to poll for disconnect - skip it */ - if (old_status == connector_status_connected && - !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) - continue; - - connector->status = connector->funcs->detect(connector, false); - if (old_status != connector->status) { - const char *old, *new; - - old = drm_get_connector_status_name(old_status); - new = drm_get_connector_status_name(connector->status); - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " - "status updated from %s to %s\n", - connector->base.id, - drm_get_connector_name(connector), - old, new); - - changed = true; - } - } - - mutex_unlock(&dev->mode_config.mutex); - - if (changed) - drm_kms_helper_hotplug_event(dev); - - if (repoll) - schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); -} - -/** - * drm_kms_helper_poll_disable - disable output polling - * @dev: drm_device - * - * This function disables the output polling work. - * - * Drivers can call this helper from their device suspend implementation. It is - * not an error to call this even when output polling isn't enabled or arlready - * disabled. - */ -void drm_kms_helper_poll_disable(struct drm_device *dev) -{ - if (!dev->mode_config.poll_enabled) - return; - cancel_delayed_work_sync(&dev->mode_config.output_poll_work); -} -EXPORT_SYMBOL(drm_kms_helper_poll_disable); - -/** - * drm_kms_helper_poll_enable - re-enable output polling. - * @dev: drm_device - * - * This function re-enables the output polling work. - * - * Drivers can call this helper from their device resume implementation. It is - * an error to call this when the output polling support has not yet been set - * up. - */ -void drm_kms_helper_poll_enable(struct drm_device *dev) -{ - bool poll = false; - struct drm_connector *connector; - - if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) - return; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT)) - poll = true; - } - - if (poll) - schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); -} -EXPORT_SYMBOL(drm_kms_helper_poll_enable); - -/** - * drm_kms_helper_poll_init - initialize and enable output polling - * @dev: drm_device - * - * This function intializes and then also enables output polling support for - * @dev. Drivers which do not have reliable hotplug support in hardware can use - * this helper infrastructure to regularly poll such connectors for changes in - * their connection state. - * - * Drivers can control which connectors are polled by setting the - * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On - * connectors where probing live outputs can result in visual distortion drivers - * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. - * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are - * completely ignored by the polling logic. - * - * Note that a connector can be both polled and probed from the hotplug handler, - * in case the hotplug interrupt is known to be unreliable. - */ -void drm_kms_helper_poll_init(struct drm_device *dev) -{ - INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); - dev->mode_config.poll_enabled = true; - - drm_kms_helper_poll_enable(dev); -} -EXPORT_SYMBOL(drm_kms_helper_poll_init); - -/** - * drm_kms_helper_poll_fini - disable output polling and clean it up - * @dev: drm_device - */ -void drm_kms_helper_poll_fini(struct drm_device *dev) -{ - drm_kms_helper_poll_disable(dev); -} -EXPORT_SYMBOL(drm_kms_helper_poll_fini); - -/** - * drm_helper_hpd_irq_event - hotplug processing - * @dev: drm_device - * - * Drivers can use this helper function to run a detect cycle on all connectors - * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All - * other connectors are ignored, which is useful to avoid reprobing fixed - * panels. - * - * This helper function is useful for drivers which can't or don't track hotplug - * interrupts for each connector. - * - * Drivers which support hotplug interrupts for each connector individually and - * which have a more fine-grained detect logic should bypass this code and - * directly call drm_kms_helper_hotplug_event() in case the connector state - * changed. - * - * This function must be called from process context with no mode - * setting locks held. - * - * Note that a connector can be both polled and probed from the hotplug handler, - * in case the hotplug interrupt is known to be unreliable. - */ -bool drm_helper_hpd_irq_event(struct drm_device *dev) -{ - struct drm_connector *connector; - enum drm_connector_status old_status; - bool changed = false; - - if (!dev->mode_config.poll_enabled) - return false; - - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - - /* Only handle HPD capable connectors. */ - if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) - continue; - - old_status = connector->status; - - connector->status = connector->funcs->detect(connector, false); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", - connector->base.id, - drm_get_connector_name(connector), - drm_get_connector_status_name(old_status), - drm_get_connector_status_name(connector->status)); - if (old_status != connector->status) - changed = true; - } - - mutex_unlock(&dev->mode_config.mutex); - - if (changed) - drm_kms_helper_hotplug_event(dev); - - return changed; -} -EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2767148..4b6e6f3 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -577,7 +577,9 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) /* * Transfer a single I2C-over-AUX message and handle various error conditions, - * retrying the transaction as appropriate. + * retrying the transaction as appropriate. It is assumed that the + * aux->transfer function does not modify anything in the msg other than the + * reply field. */ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { @@ -665,11 +667,26 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, { struct drm_dp_aux *aux = adapter->algo_data; unsigned int i, j; + struct drm_dp_aux_msg msg; + int err = 0; - for (i = 0; i < num; i++) { - struct drm_dp_aux_msg msg; - int err; + memset(&msg, 0, sizeof(msg)); + for (i = 0; i < num; i++) { + msg.address = msgs[i].addr; + msg.request = (msgs[i].flags & I2C_M_RD) ? + DP_AUX_I2C_READ : + DP_AUX_I2C_WRITE; + msg.request |= DP_AUX_I2C_MOT; + /* Send a bare address packet to start the transaction. + * Zero sized messages specify an address only (bare + * address) transaction. + */ + msg.buffer = NULL; + msg.size = 0; + err = drm_dp_i2c_do_msg(aux, &msg); + if (err < 0) + break; /* * Many hardware implementations support FIFOs larger than a * single byte, but it has been empirically determined that @@ -678,30 +695,28 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, * transferred byte-by-byte. */ for (j = 0; j < msgs[i].len; j++) { - memset(&msg, 0, sizeof(msg)); - msg.address = msgs[i].addr; - - msg.request = (msgs[i].flags & I2C_M_RD) ? - DP_AUX_I2C_READ : - DP_AUX_I2C_WRITE; - - /* - * All messages except the last one are middle-of- - * transfer messages. - */ - if ((i < num - 1) || (j < msgs[i].len - 1)) - msg.request |= DP_AUX_I2C_MOT; - msg.buffer = msgs[i].buf + j; msg.size = 1; err = drm_dp_i2c_do_msg(aux, &msg); if (err < 0) - return err; + break; } + if (err < 0) + break; } + if (err >= 0) + err = num; + /* Send a bare address packet to close out the transaction. + * Zero sized messages specify an address only (bare + * address) transaction. + */ + msg.request &= ~DP_AUX_I2C_MOT; + msg.buffer = NULL; + msg.size = 0; + (void)drm_dp_i2c_do_msg(aux, &msg); - return num; + return err; } static const struct i2c_algorithm drm_dp_i2c_algo = { diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 71e2d3f..04a209e 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) return 0; } - WARN(1, "no hole found for node 0x%lx + 0x%lx\n", - node->start, node->size); return -ENOSPC; } EXPORT_SYMBOL(drm_mm_reserve_node); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index e768d35..d2b1c03 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -203,9 +203,9 @@ EXPORT_SYMBOL(drm_primary_helper_update); * * Provides a default plane disable handler for primary planes. This is handler * is called in response to a userspace SetPlane operation on the plane with a - * NULL framebuffer parameter. We call the driver's modeset handler with a NULL - * framebuffer to disable the CRTC if no other planes are currently enabled. - * If other planes are still enabled on the same CRTC, we return -EBUSY. + * NULL framebuffer parameter. It unconditionally fails the disable call with + * -EINVAL the only way to disable the primary plane without driver support is + * to disable the entier CRTC. Which does not match the plane ->disable hook. * * Note that some hardware may be able to disable the primary plane without * disabling the whole CRTC. Drivers for such hardware should provide their @@ -214,34 +214,11 @@ EXPORT_SYMBOL(drm_primary_helper_update); * disabled primary plane). * * RETURNS: - * Zero on success, error code on failure + * Unconditionally returns -EINVAL. */ int drm_primary_helper_disable(struct drm_plane *plane) { - struct drm_plane *p; - struct drm_mode_set set = { - .crtc = plane->crtc, - .fb = NULL, - }; - - if (plane->crtc == NULL || plane->fb == NULL) - /* Already disabled */ - return 0; - - list_for_each_entry(p, &plane->dev->mode_config.plane_list, head) - if (p != plane && p->fb) { - DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n"); - return -EBUSY; - } - - /* - * N.B. We call set_config() directly here rather than - * drm_mode_set_config_internal() since drm_mode_setplane() already - * handles the basic refcounting and we don't need the special - * cross-CRTC refcounting (no chance of stealing connectors from - * other CRTC's with this update). - */ - return plane->crtc->funcs->set_config(&set); + return -EINVAL; } EXPORT_SYMBOL(drm_primary_helper_disable); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c new file mode 100644 index 0000000..e70f54d --- /dev/null +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2006-2008 Intel Corporation + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> + * + * DRM core CRTC related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + * Keith Packard + * Eric Anholt <eric@anholt.net> + * Dave Airlie <airlied@linux.ie> + * Jesse Barnes <jesse.barnes@intel.com> + */ + +#include <linux/export.h> +#include <linux/moduleparam.h> + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_edid.h> + +/** + * DOC: output probing helper overview + * + * This library provides some helper code for output probing. It provides an + * implementation of the core connector->fill_modes interface with + * drm_helper_probe_single_connector_modes. + * + * It also provides support for polling connectors with a work item and for + * generic hotplug interrupt handling where the driver doesn't or cannot keep + * track of a per-connector hpd interrupt. + * + * This helper library can be used independently of the modeset helper library. + * Drivers can also overwrite different parts e.g. use their own hotplug + * handling code to avoid probing unrelated outputs. + */ + +static bool drm_kms_helper_poll = true; +module_param_named(poll, drm_kms_helper_poll, bool, 0600); + +static void drm_mode_validate_flag(struct drm_connector *connector, + int flags) +{ + struct drm_display_mode *mode; + + if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | + DRM_MODE_FLAG_3D_MASK)) + return; + + list_for_each_entry(mode, &connector->modes, head) { + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && + !(flags & DRM_MODE_FLAG_INTERLACE)) + mode->status = MODE_NO_INTERLACE; + if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && + !(flags & DRM_MODE_FLAG_DBLSCAN)) + mode->status = MODE_NO_DBLESCAN; + if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && + !(flags & DRM_MODE_FLAG_3D_MASK)) + mode->status = MODE_NO_STEREO; + } + + return; +} + +/** + * drm_helper_probe_single_connector_modes - get complete set of display modes + * @connector: connector to probe + * @maxX: max width for modes + * @maxY: max height for modes + * + * Based on the helper callbacks implemented by @connector try to detect all + * valid modes. Modes will first be added to the connector's probed_modes list, + * then culled (based on validity and the @maxX, @maxY parameters) and put into + * the normal modes list. + * + * Intended to be use as a generic implementation of the ->fill_modes() + * @connector vfunc for drivers that use the crtc helpers for output mode + * filtering and detection. + * + * Returns: + * The number of modes found on @connector. + */ +int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + uint32_t maxX, uint32_t maxY) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode; + struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + int count = 0; + int mode_flags = 0; + bool verbose_prune = true; + + WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, + drm_get_connector_name(connector)); + /* set all modes to the unverified state */ + list_for_each_entry(mode, &connector->modes, head) + mode->status = MODE_UNVERIFIED; + + if (connector->force) { + if (connector->force == DRM_FORCE_ON) + connector->status = connector_status_connected; + else + connector->status = connector_status_disconnected; + if (connector->funcs->force) + connector->funcs->force(connector); + } else { + connector->status = connector->funcs->detect(connector, true); + } + + /* Re-enable polling in case the global poll config changed. */ + if (drm_kms_helper_poll != dev->mode_config.poll_running) + drm_kms_helper_poll_enable(dev); + + dev->mode_config.poll_running = drm_kms_helper_poll; + + if (connector->status == connector_status_disconnected) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", + connector->base.id, drm_get_connector_name(connector)); + drm_mode_connector_update_edid_property(connector, NULL); + verbose_prune = false; + goto prune; + } + +#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE + count = drm_load_edid_firmware(connector); + if (count == 0) +#endif + count = (*connector_funcs->get_modes)(connector); + + if (count == 0 && connector->status == connector_status_connected) + count = drm_add_modes_noedid(connector, 1024, 768); + if (count == 0) + goto prune; + + drm_mode_connector_list_update(connector); + + if (maxX && maxY) + drm_mode_validate_size(dev, &connector->modes, maxX, maxY); + + if (connector->interlace_allowed) + mode_flags |= DRM_MODE_FLAG_INTERLACE; + if (connector->doublescan_allowed) + mode_flags |= DRM_MODE_FLAG_DBLSCAN; + if (connector->stereo_allowed) + mode_flags |= DRM_MODE_FLAG_3D_MASK; + drm_mode_validate_flag(connector, mode_flags); + + list_for_each_entry(mode, &connector->modes, head) { + if (mode->status == MODE_OK) + mode->status = connector_funcs->mode_valid(connector, + mode); + } + +prune: + drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); + + if (list_empty(&connector->modes)) + return 0; + + list_for_each_entry(mode, &connector->modes, head) + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_sort(&connector->modes); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, + drm_get_connector_name(connector)); + list_for_each_entry(mode, &connector->modes, head) { + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_debug_printmodeline(mode); + } + + return count; +} +EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); + +/** + * drm_kms_helper_hotplug_event - fire off KMS hotplug events + * @dev: drm_device whose connector state changed + * + * This function fires off the uevent for userspace and also calls the + * output_poll_changed function, which is most commonly used to inform the fbdev + * emulation code and allow it to update the fbcon output configuration. + * + * Drivers should call this from their hotplug handling code when a change is + * detected. Note that this function does not do any output detection of its + * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the + * driver already. + * + * This function must be called from process context with no mode + * setting locks held. + */ +void drm_kms_helper_hotplug_event(struct drm_device *dev) +{ + /* send a uevent + call fbdev */ + drm_sysfs_hotplug_event(dev); + if (dev->mode_config.funcs->output_poll_changed) + dev->mode_config.funcs->output_poll_changed(dev); +} +EXPORT_SYMBOL(drm_kms_helper_hotplug_event); + +#define DRM_OUTPUT_POLL_PERIOD (10*HZ) +static void output_poll_execute(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); + struct drm_connector *connector; + enum drm_connector_status old_status; + bool repoll = false, changed = false; + + if (!drm_kms_helper_poll) + return; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + /* Ignore forced connectors. */ + if (connector->force) + continue; + + /* Ignore HPD capable connectors and connectors where we don't + * want any hotplug detection at all for polling. */ + if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) + continue; + + repoll = true; + + old_status = connector->status; + /* if we are connected and don't want to poll for disconnect + skip it */ + if (old_status == connector_status_connected && + !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) + continue; + + connector->status = connector->funcs->detect(connector, false); + if (old_status != connector->status) { + const char *old, *new; + + old = drm_get_connector_status_name(old_status); + new = drm_get_connector_status_name(connector->status); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " + "status updated from %s to %s\n", + connector->base.id, + drm_get_connector_name(connector), + old, new); + + changed = true; + } + } + + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); + + if (repoll) + schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); +} + +/** + * drm_kms_helper_poll_disable - disable output polling + * @dev: drm_device + * + * This function disables the output polling work. + * + * Drivers can call this helper from their device suspend implementation. It is + * not an error to call this even when output polling isn't enabled or arlready + * disabled. + */ +void drm_kms_helper_poll_disable(struct drm_device *dev) +{ + if (!dev->mode_config.poll_enabled) + return; + cancel_delayed_work_sync(&dev->mode_config.output_poll_work); +} +EXPORT_SYMBOL(drm_kms_helper_poll_disable); + +/** + * drm_kms_helper_poll_enable - re-enable output polling. + * @dev: drm_device + * + * This function re-enables the output polling work. + * + * Drivers can call this helper from their device resume implementation. It is + * an error to call this when the output polling support has not yet been set + * up. + */ +void drm_kms_helper_poll_enable(struct drm_device *dev) +{ + bool poll = false; + struct drm_connector *connector; + + if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) + return; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT)) + poll = true; + } + + if (poll) + schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); +} +EXPORT_SYMBOL(drm_kms_helper_poll_enable); + +/** + * drm_kms_helper_poll_init - initialize and enable output polling + * @dev: drm_device + * + * This function intializes and then also enables output polling support for + * @dev. Drivers which do not have reliable hotplug support in hardware can use + * this helper infrastructure to regularly poll such connectors for changes in + * their connection state. + * + * Drivers can control which connectors are polled by setting the + * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On + * connectors where probing live outputs can result in visual distortion drivers + * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. + * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are + * completely ignored by the polling logic. + * + * Note that a connector can be both polled and probed from the hotplug handler, + * in case the hotplug interrupt is known to be unreliable. + */ +void drm_kms_helper_poll_init(struct drm_device *dev) +{ + INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); + dev->mode_config.poll_enabled = true; + + drm_kms_helper_poll_enable(dev); +} +EXPORT_SYMBOL(drm_kms_helper_poll_init); + +/** + * drm_kms_helper_poll_fini - disable output polling and clean it up + * @dev: drm_device + */ +void drm_kms_helper_poll_fini(struct drm_device *dev) +{ + drm_kms_helper_poll_disable(dev); +} +EXPORT_SYMBOL(drm_kms_helper_poll_fini); + +/** + * drm_helper_hpd_irq_event - hotplug processing + * @dev: drm_device + * + * Drivers can use this helper function to run a detect cycle on all connectors + * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All + * other connectors are ignored, which is useful to avoid reprobing fixed + * panels. + * + * This helper function is useful for drivers which can't or don't track hotplug + * interrupts for each connector. + * + * Drivers which support hotplug interrupts for each connector individually and + * which have a more fine-grained detect logic should bypass this code and + * directly call drm_kms_helper_hotplug_event() in case the connector state + * changed. + * + * This function must be called from process context with no mode + * setting locks held. + * + * Note that a connector can be both polled and probed from the hotplug handler, + * in case the hotplug interrupt is known to be unreliable. + */ +bool drm_helper_hpd_irq_event(struct drm_device *dev) +{ + struct drm_connector *connector; + enum drm_connector_status old_status; + bool changed = false; + + if (!dev->mode_config.poll_enabled) + return false; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + /* Only handle HPD capable connectors. */ + if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) + continue; + + old_status = connector->status; + + connector->status = connector->funcs->detect(connector, false); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", + connector->base.id, + drm_get_connector_name(connector), + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status)); + if (old_status != connector->status) + changed = true; + } + + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); + + return changed; +} +EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0905cd9..ec82f6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1308,6 +1308,7 @@ struct intel_vbt_data { struct { u16 pwm_freq_hz; + bool present; bool active_low_pwm; } backlight; @@ -2431,20 +2432,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); int i915_gem_context_enable(struct drm_i915_private *dev_priv); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct intel_ring_buffer *ring, - struct drm_file *file, struct i915_hw_context *to); + struct i915_hw_context *to); struct i915_hw_context * i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); void i915_gem_context_free(struct kref *ctx_ref); static inline void i915_gem_context_reference(struct i915_hw_context *ctx) { - if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) - kref_get(&ctx->ref); + kref_get(&ctx->ref); } static inline void i915_gem_context_unreference(struct i915_hw_context *ctx) { - if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) - kref_put(&ctx->ref, i915_gem_context_free); + kref_put(&ctx->ref, i915_gem_context_free); } static inline bool i915_gem_context_is_default(const struct i915_hw_context *c) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6370a76..2871ce7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev) /* Flush everything onto the inactive list. */ for_each_ring(ring, dev_priv, i) { - ret = i915_switch_context(ring, NULL, ring->default_context); + ret = i915_switch_context(ring, ring->default_context); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6043062..d72db15 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -96,9 +96,6 @@ #define GEN6_CONTEXT_ALIGN (64<<10) #define GEN7_CONTEXT_ALIGN 4096 -static int do_switch(struct intel_ring_buffer *ring, - struct i915_hw_context *to); - static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt) { struct drm_device *dev = ppgtt->base.dev; @@ -185,13 +182,15 @@ void i915_gem_context_free(struct kref *ctx_ref) typeof(*ctx), ref); struct i915_hw_ppgtt *ppgtt = NULL; - /* We refcount even the aliasing PPGTT to keep the code symmetric */ - if (USES_PPGTT(ctx->obj->base.dev)) - ppgtt = ctx_to_ppgtt(ctx); + if (ctx->obj) { + /* We refcount even the aliasing PPGTT to keep the code symmetric */ + if (USES_PPGTT(ctx->obj->base.dev)) + ppgtt = ctx_to_ppgtt(ctx); - /* XXX: Free up the object before tearing down the address space, in - * case we're bound in the PPGTT */ - drm_gem_object_unreference(&ctx->obj->base); + /* XXX: Free up the object before tearing down the address space, in + * case we're bound in the PPGTT */ + drm_gem_object_unreference(&ctx->obj->base); + } if (ppgtt) kref_put(&ppgtt->ref, ppgtt_release); @@ -232,32 +231,32 @@ __create_hw_context(struct drm_device *dev, return ERR_PTR(-ENOMEM); kref_init(&ctx->ref); - ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); - INIT_LIST_HEAD(&ctx->link); - if (ctx->obj == NULL) { - kfree(ctx); - DRM_DEBUG_DRIVER("Context object allocated failed\n"); - return ERR_PTR(-ENOMEM); - } + list_add_tail(&ctx->link, &dev_priv->context_list); - if (INTEL_INFO(dev)->gen >= 7) { - ret = i915_gem_object_set_cache_level(ctx->obj, - I915_CACHE_L3_LLC); - /* Failure shouldn't ever happen this early */ - if (WARN_ON(ret)) + if (dev_priv->hw_context_size) { + ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); + if (ctx->obj == NULL) { + ret = -ENOMEM; goto err_out; - } + } - list_add_tail(&ctx->link, &dev_priv->context_list); + if (INTEL_INFO(dev)->gen >= 7) { + ret = i915_gem_object_set_cache_level(ctx->obj, + I915_CACHE_L3_LLC); + /* Failure shouldn't ever happen this early */ + if (WARN_ON(ret)) + goto err_out; + } + } /* Default context will never have a file_priv */ - if (file_priv == NULL) - return ctx; - - ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0, - GFP_KERNEL); - if (ret < 0) - goto err_out; + if (file_priv != NULL) { + ret = idr_alloc(&file_priv->context_idr, ctx, + DEFAULT_CONTEXT_ID, 0, GFP_KERNEL); + if (ret < 0) + goto err_out; + } else + ret = DEFAULT_CONTEXT_ID; ctx->file_priv = file_priv; ctx->id = ret; @@ -294,7 +293,7 @@ i915_gem_create_context(struct drm_device *dev, if (IS_ERR(ctx)) return ctx; - if (is_global_default_ctx) { + if (is_global_default_ctx && ctx->obj) { /* We may need to do things with the shrinker which * require us to immediately switch back to the default * context. This can cause a problem as pinning the @@ -342,7 +341,7 @@ i915_gem_create_context(struct drm_device *dev, return ctx; err_unpin: - if (is_global_default_ctx) + if (is_global_default_ctx && ctx->obj) i915_gem_object_ggtt_unpin(ctx->obj); err_destroy: i915_gem_context_unreference(ctx); @@ -352,32 +351,22 @@ err_destroy: void i915_gem_context_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; int i; - if (!HAS_HW_CONTEXTS(dev)) - return; - /* Prevent the hardware from restoring the last context (which hung) on * the next switch */ for (i = 0; i < I915_NUM_RINGS; i++) { - struct i915_hw_context *dctx; - if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) - continue; + struct intel_ring_buffer *ring = &dev_priv->ring[i]; + struct i915_hw_context *dctx = ring->default_context; /* Do a fake switch to the default context */ - ring = &dev_priv->ring[i]; - dctx = ring->default_context; - if (WARN_ON(!dctx)) + if (ring->last_context == dctx) continue; if (!ring->last_context) continue; - if (ring->last_context == dctx) - continue; - - if (i == RCS) { + if (dctx->obj && i == RCS) { WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj, get_context_alignment(dev), 0)); /* Fake a finish/inactive */ @@ -394,44 +383,35 @@ void i915_gem_context_reset(struct drm_device *dev) int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; + struct i915_hw_context *ctx; int i; - if (!HAS_HW_CONTEXTS(dev)) - return 0; - /* Init should only be called once per module load. Eventually the * restriction on the context_disabled check can be loosened. */ if (WARN_ON(dev_priv->ring[RCS].default_context)) return 0; - dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); - - if (dev_priv->hw_context_size > (1<<20)) { - DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n"); - return -E2BIG; + if (HAS_HW_CONTEXTS(dev)) { + dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); + if (dev_priv->hw_context_size > (1<<20)) { + DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n", + dev_priv->hw_context_size); + dev_priv->hw_context_size = 0; + } } - dev_priv->ring[RCS].default_context = - i915_gem_create_context(dev, NULL, USES_PPGTT(dev)); - - if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) { - DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n", - PTR_ERR(dev_priv->ring[RCS].default_context)); - return PTR_ERR(dev_priv->ring[RCS].default_context); + ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev)); + if (IS_ERR(ctx)) { + DRM_ERROR("Failed to create default global context (error %ld)\n", + PTR_ERR(ctx)); + return PTR_ERR(ctx); } - for (i = RCS + 1; i < I915_NUM_RINGS; i++) { - if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) - continue; - - ring = &dev_priv->ring[i]; + /* NB: RCS will hold a ref for all rings */ + for (i = 0; i < I915_NUM_RINGS; i++) + dev_priv->ring[i].default_context = ctx; - /* NB: RCS will hold a ref for all rings */ - ring->default_context = dev_priv->ring[RCS].default_context; - } - - DRM_DEBUG_DRIVER("HW context support initialized\n"); + DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake"); return 0; } @@ -441,33 +421,30 @@ void i915_gem_context_fini(struct drm_device *dev) struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; int i; - if (!HAS_HW_CONTEXTS(dev)) - return; - - /* The only known way to stop the gpu from accessing the hw context is - * to reset it. Do this as the very last operation to avoid confusing - * other code, leading to spurious errors. */ - intel_gpu_reset(dev); - - /* When default context is created and switched to, base object refcount - * will be 2 (+1 from object creation and +1 from do_switch()). - * i915_gem_context_fini() will be called after gpu_idle() has switched - * to default context. So we need to unreference the base object once - * to offset the do_switch part, so that i915_gem_context_unreference() - * can then free the base object correctly. */ - WARN_ON(!dev_priv->ring[RCS].last_context); - if (dev_priv->ring[RCS].last_context == dctx) { - /* Fake switch to NULL context */ - WARN_ON(dctx->obj->active); - i915_gem_object_ggtt_unpin(dctx->obj); - i915_gem_context_unreference(dctx); - dev_priv->ring[RCS].last_context = NULL; + if (dctx->obj) { + /* The only known way to stop the gpu from accessing the hw context is + * to reset it. Do this as the very last operation to avoid confusing + * other code, leading to spurious errors. */ + intel_gpu_reset(dev); + + /* When default context is created and switched to, base object refcount + * will be 2 (+1 from object creation and +1 from do_switch()). + * i915_gem_context_fini() will be called after gpu_idle() has switched + * to default context. So we need to unreference the base object once + * to offset the do_switch part, so that i915_gem_context_unreference() + * can then free the base object correctly. */ + WARN_ON(!dev_priv->ring[RCS].last_context); + if (dev_priv->ring[RCS].last_context == dctx) { + /* Fake switch to NULL context */ + WARN_ON(dctx->obj->active); + i915_gem_object_ggtt_unpin(dctx->obj); + i915_gem_context_unreference(dctx); + dev_priv->ring[RCS].last_context = NULL; + } } for (i = 0; i < I915_NUM_RINGS; i++) { struct intel_ring_buffer *ring = &dev_priv->ring[i]; - if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) - continue; if (ring->last_context) i915_gem_context_unreference(ring->last_context); @@ -478,7 +455,6 @@ void i915_gem_context_fini(struct drm_device *dev) i915_gem_object_ggtt_unpin(dctx->obj); i915_gem_context_unreference(dctx); - dev_priv->mm.aliasing_ppgtt = NULL; } int i915_gem_context_enable(struct drm_i915_private *dev_priv) @@ -486,9 +462,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) struct intel_ring_buffer *ring; int ret, i; - if (!HAS_HW_CONTEXTS(dev_priv->dev)) - return 0; - /* This is the only place the aliasing PPGTT gets enabled, which means * it has to happen before we bail on reset */ if (dev_priv->mm.aliasing_ppgtt) { @@ -503,7 +476,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) BUG_ON(!dev_priv->ring[RCS].default_context); for_each_ring(ring, dev_priv, i) { - ret = do_switch(ring, ring->default_context); + ret = i915_switch_context(ring, ring->default_context); if (ret) return ret; } @@ -526,19 +499,6 @@ static int context_idr_cleanup(int id, void *p, void *data) int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!HAS_HW_CONTEXTS(dev)) { - /* Cheat for hang stats */ - file_priv->private_default_ctx = - kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL); - - if (file_priv->private_default_ctx == NULL) - return -ENOMEM; - - file_priv->private_default_ctx->vm = &dev_priv->gtt.base; - return 0; - } idr_init(&file_priv->context_idr); @@ -559,14 +519,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - if (!HAS_HW_CONTEXTS(dev)) { - kfree(file_priv->private_default_ctx); - return; - } - idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); - i915_gem_context_unreference(file_priv->private_default_ctx); idr_destroy(&file_priv->context_idr); + + i915_gem_context_unreference(file_priv->private_default_ctx); } struct i915_hw_context * @@ -574,9 +530,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) { struct i915_hw_context *ctx; - if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev)) - return file_priv->private_default_ctx; - ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); if (!ctx) return ERR_PTR(-ENOENT); @@ -758,7 +711,6 @@ unpin_out: /** * i915_switch_context() - perform a GPU context switch. * @ring: ring for which we'll execute the context switch - * @file_priv: file_priv associated with the context, may be NULL * @to: the context to switch to * * The context life cycle is simple. The context refcount is incremented and @@ -767,24 +719,30 @@ unpin_out: * object while letting the normal object tracking destroy the backing BO. */ int i915_switch_context(struct intel_ring_buffer *ring, - struct drm_file *file, struct i915_hw_context *to) { struct drm_i915_private *dev_priv = ring->dev->dev_private; WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); - BUG_ON(file && to == NULL); - - /* We have the fake context */ - if (!HAS_HW_CONTEXTS(ring->dev)) { - ring->last_context = to; + if (to->obj == NULL) { /* We have the fake context */ + if (to != ring->last_context) { + i915_gem_context_reference(to); + if (ring->last_context) + i915_gem_context_unreference(ring->last_context); + ring->last_context = to; + } return 0; } return do_switch(ring, to); } +static bool hw_context_enabled(struct drm_device *dev) +{ + return to_i915(dev)->hw_context_size; +} + int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -793,7 +751,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct i915_hw_context *ctx; int ret; - if (!HAS_HW_CONTEXTS(dev)) + if (!hw_context_enabled(dev)) return -ENODEV; ret = i915_mutex_lock_interruptible(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7447160..2c9d9cb 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret) goto err; - ret = i915_switch_context(ring, file, ctx); + ret = i915_switch_context(ring, ctx); if (ret) goto err; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4867f4c..fa486c5 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -287,6 +287,9 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) const struct bdb_lfp_backlight_data *backlight_data; const struct bdb_lfp_backlight_data_entry *entry; + /* Err to enabling backlight if no backlight block. */ + dev_priv->vbt.backlight.present = true; + backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); if (!backlight_data) return; @@ -299,6 +302,13 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) entry = &backlight_data->data[panel_type]; + dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; + if (!dev_priv->vbt.backlight.present) { + DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n", + entry->type); + return; + } + dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 83b7629..f27f7b2 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -374,6 +374,9 @@ struct bdb_lvds_lfp_data { struct bdb_lvds_lfp_data_entry data[16]; } __packed; +#define BDB_BACKLIGHT_TYPE_NONE 0 +#define BDB_BACKLIGHT_TYPE_PWM 2 + struct bdb_lfp_backlight_data_entry { u8 type:2; u8 active_low_pwm:1; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a0dad1a..d2a5588 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -575,7 +575,8 @@ out: return ret; } -#define HEADER_SIZE 4 +#define BARE_ADDRESS_SIZE 3 +#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) static ssize_t intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { @@ -592,7 +593,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_WRITE: case DP_AUX_I2C_WRITE: - txsize = HEADER_SIZE + msg->size; + txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE; rxsize = 1; if (WARN_ON(txsize > 20)) @@ -611,7 +612,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) case DP_AUX_NATIVE_READ: case DP_AUX_I2C_READ: - txsize = HEADER_SIZE; + txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE; rxsize = msg->size + 1; if (WARN_ON(rxsize > 20)) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index cb05840..0eead16 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1065,6 +1065,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector) unsigned long flags; int ret; + if (!dev_priv->vbt.backlight.present) { + DRM_DEBUG_KMS("native backlight control not available per VBT\n"); + return 0; + } + /* set level and max in panel struct */ spin_lock_irqsave(&dev_priv->backlight_lock, flags); ret = dev_priv->display.setup_backlight(intel_connector); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5874716..19e94c3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1545,6 +1545,16 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); + if (IS_I915GM(dev) && enabled) { + struct intel_framebuffer *fb; + + fb = to_intel_framebuffer(enabled->primary->fb); + + /* self-refresh seems busted with untiled */ + if (fb->obj->tiling_mode == I915_TILING_NONE) + enabled = NULL; + } + /* * Overlay gets an aggressive default since video jitter is bad. */ diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e9df94f..fb0b6b2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -109,7 +109,7 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios) return; } - addr = (u64)(addr >> 8) << 8; + addr = (addr & 0xffffff00) << 8; if (!addr) { addr = (u64)nv_rd32(bios, 0x001700) << 16; addr += 0xf0000; diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 355157e..e3c47a8 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -33,6 +33,7 @@ struct omap_crtc { int pipe; enum omap_channel channel; struct omap_overlay_manager_info info; + struct drm_encoder *current_encoder; /* * Temporary: eventually this will go away, but it is needed @@ -120,13 +121,25 @@ static void omap_crtc_start_update(struct omap_overlay_manager *mgr) { } +static void set_enabled(struct drm_crtc *crtc, bool enable); + static int omap_crtc_enable(struct omap_overlay_manager *mgr) { + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + + dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); + dispc_mgr_set_timings(omap_crtc->channel, + &omap_crtc->timings); + set_enabled(&omap_crtc->base, true); + return 0; } static void omap_crtc_disable(struct omap_overlay_manager *mgr) { + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + + set_enabled(&omap_crtc->base, false); } static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, @@ -184,7 +197,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) WARN_ON(omap_crtc->apply_irq.registered); omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); - omap_crtc->plane->funcs->destroy(omap_crtc->plane); drm_crtc_cleanup(crtc); kfree(omap_crtc); @@ -338,17 +350,23 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_plane *primary = crtc->primary; struct drm_gem_object *bo; + unsigned long flags; DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1, fb->base.id, event); + spin_lock_irqsave(&dev->event_lock, flags); + if (omap_crtc->old_fb) { + spin_unlock_irqrestore(&dev->event_lock, flags); dev_err(dev->dev, "already a pending flip\n"); return -EINVAL; } omap_crtc->event = event; - primary->fb = fb; + omap_crtc->old_fb = primary->fb = fb; + + spin_unlock_irqrestore(&dev->event_lock, flags); /* * Hold a reference temporarily until the crtc is updated @@ -528,38 +546,46 @@ static void set_enabled(struct drm_crtc *crtc, bool enable) struct drm_device *dev = crtc->dev; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); enum omap_channel channel = omap_crtc->channel; - struct omap_irq_wait *wait = NULL; + struct omap_irq_wait *wait; + u32 framedone_irq, vsync_irq; + int ret; if (dispc_mgr_is_enabled(channel) == enable) return; - /* ignore sync-lost irqs during enable/disable */ + /* + * Digit output produces some sync lost interrupts during the first + * frame when enabling, so we need to ignore those. + */ omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); - if (dispc_mgr_get_framedone_irq(channel)) { - if (!enable) { - wait = omap_irq_wait_init(dev, - dispc_mgr_get_framedone_irq(channel), 1); - } + framedone_irq = dispc_mgr_get_framedone_irq(channel); + vsync_irq = dispc_mgr_get_vsync_irq(channel); + + if (enable) { + wait = omap_irq_wait_init(dev, vsync_irq, 1); } else { /* - * When we disable digit output, we need to wait until fields - * are done. Otherwise the DSS is still working, and turning - * off the clocks prevents DSS from going to OFF mode. And when - * enabling, we need to wait for the extra sync losts + * When we disable the digit output, we need to wait for + * FRAMEDONE to know that DISPC has finished with the output. + * + * OMAP2/3 does not have FRAMEDONE irq for digit output, and in + * that case we need to use vsync interrupt, and wait for both + * even and odd frames. */ - wait = omap_irq_wait_init(dev, - dispc_mgr_get_vsync_irq(channel), 2); + + if (framedone_irq) + wait = omap_irq_wait_init(dev, framedone_irq, 1); + else + wait = omap_irq_wait_init(dev, vsync_irq, 2); } dispc_mgr_enable(channel, enable); - if (wait) { - int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); - if (ret) { - dev_err(dev->dev, "%s: timeout waiting for %s\n", - omap_crtc->name, enable ? "enable" : "disable"); - } + ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); + if (ret) { + dev_err(dev->dev, "%s: timeout waiting for %s\n", + omap_crtc->name, enable ? "enable" : "disable"); } omap_irq_register(crtc->dev, &omap_crtc->error_irq); @@ -586,8 +612,12 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) } } + if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder) + omap_encoder_set_enabled(omap_crtc->current_encoder, false); + + omap_crtc->current_encoder = encoder; + if (!omap_crtc->enabled) { - set_enabled(&omap_crtc->base, false); if (encoder) omap_encoder_set_enabled(encoder, false); } else { @@ -596,13 +626,7 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) omap_encoder_update(encoder, omap_crtc->mgr, &omap_crtc->timings); omap_encoder_set_enabled(encoder, true); - omap_crtc->full_update = false; } - - dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); - dispc_mgr_set_timings(omap_crtc->channel, - &omap_crtc->timings); - set_enabled(&omap_crtc->base, true); } omap_crtc->full_update = false; @@ -613,10 +637,30 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply) /* nothing needed for post-apply */ } +void omap_crtc_flush(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + int loops = 0; + + while (!list_empty(&omap_crtc->pending_applies) || + !list_empty(&omap_crtc->queued_applies) || + omap_crtc->event || omap_crtc->old_fb) { + + if (++loops > 10) { + dev_err(crtc->dev->dev, + "omap_crtc_flush() timeout\n"); + break; + } + + schedule_timeout_uninterruptible(msecs_to_jiffies(20)); + } +} + static const char *channel_names[] = { [OMAP_DSS_CHANNEL_LCD] = "lcd", [OMAP_DSS_CHANNEL_DIGIT] = "tv", [OMAP_DSS_CHANNEL_LCD2] = "lcd2", + [OMAP_DSS_CHANNEL_LCD3] = "lcd3", }; void omap_crtc_pre_init(void) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index bf39fcc..c8270e4 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -513,12 +513,18 @@ static int dev_load(struct drm_device *dev, unsigned long flags) static int dev_unload(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; + int i; DBG("unload: dev=%p", dev); drm_kms_helper_poll_fini(dev); omap_fbdev_free(dev); + + /* flush crtcs so the fbs get released */ + for (i = 0; i < priv->num_crtcs; i++) + omap_crtc_flush(priv->crtcs[i]); + omap_modeset_free(dev); omap_gem_deinit(dev); @@ -696,10 +702,11 @@ static int pdev_remove(struct platform_device *device) { DBG(""); + drm_put_dev(platform_get_drvdata(device)); + omap_disconnect_dssdevs(); omap_crtc_pre_uninit(); - drm_put_dev(platform_get_drvdata(device)); return 0; } @@ -726,18 +733,33 @@ static struct platform_driver pdev = { static int __init omap_drm_init(void) { + int r; + DBG("init"); - if (platform_driver_register(&omap_dmm_driver)) { - /* we can continue on without DMM.. so not fatal */ - dev_err(NULL, "DMM registration failed\n"); + + r = platform_driver_register(&omap_dmm_driver); + if (r) { + pr_err("DMM driver registration failed\n"); + return r; + } + + r = platform_driver_register(&pdev); + if (r) { + pr_err("omapdrm driver registration failed\n"); + platform_driver_unregister(&omap_dmm_driver); + return r; } - return platform_driver_register(&pdev); + + return 0; } static void __exit omap_drm_fini(void) { DBG("fini"); + platform_driver_unregister(&pdev); + + platform_driver_unregister(&omap_dmm_driver); } /* need late_initcall() so we load after dss_driver's are loaded */ diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 428b2981..284b80f 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -163,6 +163,7 @@ void omap_crtc_pre_init(void); void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id); +void omap_crtc_flush(struct drm_crtc *crtc); struct drm_plane *omap_plane_init(struct drm_device *dev, int plane_id, bool private_plane); diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index d2b8c49..8b01960 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -218,6 +218,20 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, info->rotation_type = OMAP_DSS_ROT_TILER; info->screen_width = omap_gem_tiled_stride(plane->bo, orient); } else { + switch (win->rotation & 0xf) { + case 0: + case BIT(DRM_ROTATE_0): + /* OK */ + break; + + default: + dev_warn(fb->dev->dev, + "rotation '%d' ignored for non-tiled fb\n", + win->rotation); + win->rotation = 0; + break; + } + info->paddr = get_linear_addr(plane, format, 0, x, y); info->rotation_type = OMAP_DSS_ROT_DMA; info->screen_width = plane->pitch; diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 002988d..1388ca7 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -371,6 +371,9 @@ void omap_fbdev_free(struct drm_device *dev) fbdev = to_omap_fbdev(priv->fbdev); + /* release the ref taken in omap_fbdev_create() */ + omap_gem_put_paddr(fbdev->bo); + /* this will free the backing object */ if (fbdev->fb) { drm_framebuffer_unregister_private(fbdev->fb); diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index c8d9727..95dbce2 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -980,12 +980,9 @@ int omap_gem_resume(struct device *dev) #ifdef CONFIG_DEBUG_FS void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) { - struct drm_device *dev = obj->dev; struct omap_gem_object *omap_obj = to_omap_bo(obj); uint64_t off; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - off = drm_vma_node_start(&obj->vma_node); seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", @@ -1050,10 +1047,10 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter) { struct omap_gem_object *omap_obj = waiter->omap_obj; if ((waiter->op & OMAP_GEM_READ) && - (omap_obj->sync->read_complete < waiter->read_target)) + (omap_obj->sync->write_complete < waiter->write_target)) return true; if ((waiter->op & OMAP_GEM_WRITE) && - (omap_obj->sync->write_complete < waiter->write_target)) + (omap_obj->sync->read_complete < waiter->read_target)) return true; return false; } @@ -1229,6 +1226,8 @@ int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op, } spin_unlock(&sync_lock); + + kfree(waiter); } /* no waiting.. */ diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e6..3cf31ee 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -225,6 +225,11 @@ int omap_plane_mode_set(struct drm_plane *plane, omap_plane->apply_done_cb.arg = arg; } + if (plane->fb) + drm_framebuffer_unreference(plane->fb); + + drm_framebuffer_reference(fb); + plane->fb = fb; plane->crtc = crtc; @@ -241,10 +246,13 @@ static int omap_plane_update(struct drm_plane *plane, struct omap_plane *omap_plane = to_omap_plane(plane); omap_plane->enabled = true; - if (plane->fb) - drm_framebuffer_unreference(plane->fb); - - drm_framebuffer_reference(fb); + /* omap_plane_mode_set() takes adjusted src */ + switch (omap_plane->win.rotation & 0xf) { + case BIT(DRM_ROTATE_90): + case BIT(DRM_ROTATE_270): + swap(src_w, src_h); + break; + } return omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 8b0ab17..bc0119f 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -142,7 +142,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, return recv_bytes; } -#define HEADER_SIZE 4 +#define BARE_ADDRESS_SIZE 3 +#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) static ssize_t radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) @@ -160,13 +161,19 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) tx_buf[0] = msg->address & 0xff; tx_buf[1] = msg->address >> 8; tx_buf[2] = msg->request << 4; - tx_buf[3] = msg->size - 1; + tx_buf[3] = msg->size ? (msg->size - 1) : 0; switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_WRITE: case DP_AUX_I2C_WRITE: + /* tx_size needs to be 4 even for bare address packets since the atom + * table needs the info in tx_buf[3]. + */ tx_size = HEADER_SIZE + msg->size; - tx_buf[3] |= tx_size << 4; + if (msg->size == 0) + tx_buf[3] |= BARE_ADDRESS_SIZE << 4; + else + tx_buf[3] |= tx_size << 4; memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); ret = radeon_process_aux_ch(chan, tx_buf, tx_size, NULL, 0, delay, &ack); @@ -176,8 +183,14 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) break; case DP_AUX_NATIVE_READ: case DP_AUX_I2C_READ: + /* tx_size needs to be 4 even for bare address packets since the atom + * table needs the info in tx_buf[3]. + */ tx_size = HEADER_SIZE; - tx_buf[3] |= tx_size << 4; + if (msg->size == 0) + tx_buf[3] |= BARE_ADDRESS_SIZE << 4; + else + tx_buf[3] |= tx_size << 4; ret = radeon_process_aux_ch(chan, tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); break; @@ -186,7 +199,7 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) break; } - if (ret > 0) + if (ret >= 0) msg->reply = ack >> 4; return ret; @@ -194,98 +207,16 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) void radeon_dp_aux_init(struct radeon_connector *radeon_connector) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - - dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev; - dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer; -} - -int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - u8 write_byte, u8 *read_byte) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter); - u16 address = algo_data->address; - u8 msg[5]; - u8 reply[2]; - unsigned retry; - int msg_bytes; - int reply_bytes = 1; int ret; - u8 ack; - - /* Set up the address */ - msg[0] = address; - msg[1] = address >> 8; - - /* Set up the command byte */ - if (mode & MODE_I2C_READ) { - msg[2] = DP_AUX_I2C_READ << 4; - msg_bytes = 4; - msg[3] = msg_bytes << 4; - } else { - msg[2] = DP_AUX_I2C_WRITE << 4; - msg_bytes = 5; - msg[3] = msg_bytes << 4; - msg[4] = write_byte; - } - - /* special handling for start/stop */ - if (mode & (MODE_I2C_START | MODE_I2C_STOP)) - msg[3] = 3 << 4; - - /* Set MOT bit for all but stop */ - if ((mode & MODE_I2C_STOP) == 0) - msg[2] |= DP_AUX_I2C_MOT << 4; - - for (retry = 0; retry < 7; retry++) { - ret = radeon_process_aux_ch(auxch, - msg, msg_bytes, reply, reply_bytes, 0, &ack); - if (ret == -EBUSY) - continue; - else if (ret < 0) { - DRM_DEBUG_KMS("aux_ch failed %d\n", ret); - return ret; - } - - switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) { - case DP_AUX_NATIVE_REPLY_ACK: - /* I2C-over-AUX Reply field is only valid - * when paired with AUX ACK. - */ - break; - case DP_AUX_NATIVE_REPLY_NACK: - DRM_DEBUG_KMS("aux_ch native nack\n"); - return -EREMOTEIO; - case DP_AUX_NATIVE_REPLY_DEFER: - DRM_DEBUG_KMS("aux_ch native defer\n"); - usleep_range(500, 600); - continue; - default: - DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); - return -EREMOTEIO; - } - switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) { - case DP_AUX_I2C_REPLY_ACK: - if (mode == MODE_I2C_READ) - *read_byte = reply[0]; - return ret; - case DP_AUX_I2C_REPLY_NACK: - DRM_DEBUG_KMS("aux_i2c nack\n"); - return -EREMOTEIO; - case DP_AUX_I2C_REPLY_DEFER: - DRM_DEBUG_KMS("aux_i2c defer\n"); - usleep_range(400, 500); - break; - default: - DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); - return -EREMOTEIO; - } - } + radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; + radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; + radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer; + ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux); + if (!ret) + radeon_connector->ddc_bus->has_aux = true; - DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); - return -EREMOTEIO; + WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d\n", ret); } /***** general DP utility functions *****/ @@ -420,12 +351,11 @@ static u8 radeon_dp_encoder_service(struct radeon_device *rdev, u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; struct drm_device *dev = radeon_connector->base.dev; struct radeon_device *rdev = dev->dev_private; return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, - dig_connector->dp_i2c_bus->rec.i2c_id, 0); + radeon_connector->ddc_bus->rec.i2c_id, 0); } static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) @@ -436,11 +366,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3)) DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3)) DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); } @@ -451,7 +381,7 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) u8 msg[DP_DPCD_SIZE]; int ret, i; - ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg, + ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, DP_DPCD_SIZE); if (ret > 0) { memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); @@ -489,7 +419,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, if (dp_bridge != ENCODER_OBJECT_ID_NONE) { /* DP bridge chips */ - drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_EDP_CONFIGURATION_CAP, &tmp); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; @@ -500,7 +430,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { /* eDP */ - drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_EDP_CONFIGURATION_CAP, &tmp); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; @@ -554,7 +484,8 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) u8 link_status[DP_LINK_STATUS_SIZE]; struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0) + if (drm_dp_dpcd_read_link_status(&radeon_connector->ddc_bus->aux, link_status) + <= 0) return false; if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) return false; @@ -574,7 +505,7 @@ void radeon_dp_set_rx_power_state(struct drm_connector *connector, /* power up/down the sink */ if (dig_connector->dpcd[0] >= 0x11) { - drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_writeb(&radeon_connector->ddc_bus->aux, DP_SET_POWER, power_state); usleep_range(1000, 2000); } @@ -878,7 +809,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, else dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; - drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp); + drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp); if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) dp_info.tp3_supported = true; else @@ -890,7 +821,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, dp_info.connector = connector; dp_info.dp_lane_count = dig_connector->dp_lane_count; dp_info.dp_clock = dig_connector->dp_clock; - dp_info.aux = &dig_connector->dp_i2c_bus->aux; + dp_info.aux = &radeon_connector->ddc_bus->aux; if (radeon_dp_link_train_init(&dp_info)) goto done; diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index cad89a9..10dae41 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -21,8 +21,10 @@ * */ +#include <linux/firmware.h> #include "drmP.h" #include "radeon.h" +#include "radeon_ucode.h" #include "cikd.h" #include "r600_dpm.h" #include "ci_dpm.h" @@ -202,24 +204,29 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) struct ci_power_info *pi = ci_get_pi(rdev); switch (rdev->pdev->device) { + case 0x6649: case 0x6650: + case 0x6651: case 0x6658: case 0x665C: + case 0x665D: default: pi->powertune_defaults = &defaults_bonaire_xt; break; - case 0x6651: - case 0x665D: - pi->powertune_defaults = &defaults_bonaire_pro; - break; case 0x6640: - pi->powertune_defaults = &defaults_saturn_xt; - break; case 0x6641: - pi->powertune_defaults = &defaults_saturn_pro; + case 0x6646: + case 0x6647: + pi->powertune_defaults = &defaults_saturn_xt; break; case 0x67B8: case 0x67B0: + pi->powertune_defaults = &defaults_hawaii_xt; + break; + case 0x67BA: + case 0x67B1: + pi->powertune_defaults = &defaults_hawaii_pro; + break; case 0x67A0: case 0x67A1: case 0x67A2: @@ -228,11 +235,7 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) case 0x67AA: case 0x67B9: case 0x67BE: - pi->powertune_defaults = &defaults_hawaii_xt; - break; - case 0x67BA: - case 0x67B1: - pi->powertune_defaults = &defaults_hawaii_pro; + pi->powertune_defaults = &defaults_bonaire_xt; break; } @@ -5146,6 +5149,12 @@ int ci_dpm_init(struct radeon_device *rdev) pi->mclk_dpm_key_disabled = 0; pi->pcie_dpm_key_disabled = 0; + /* mclk dpm is unstable on some R7 260X cards with the old mc ucode */ + if ((rdev->pdev->device == 0x6658) && + (rdev->mc_fw->size == (BONAIRE_MC_UCODE_SIZE * 4))) { + pi->mclk_dpm_key_disabled = 1; + } + pi->caps_sclk_ds = true; pi->mclk_strobe_mode_threshold = 40000; diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 745143c..199eb19 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -38,6 +38,7 @@ MODULE_FIRMWARE("radeon/BONAIRE_me.bin"); MODULE_FIRMWARE("radeon/BONAIRE_ce.bin"); MODULE_FIRMWARE("radeon/BONAIRE_mec.bin"); MODULE_FIRMWARE("radeon/BONAIRE_mc.bin"); +MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin"); MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin"); MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin"); MODULE_FIRMWARE("radeon/BONAIRE_smc.bin"); @@ -46,6 +47,7 @@ MODULE_FIRMWARE("radeon/HAWAII_me.bin"); MODULE_FIRMWARE("radeon/HAWAII_ce.bin"); MODULE_FIRMWARE("radeon/HAWAII_mec.bin"); MODULE_FIRMWARE("radeon/HAWAII_mc.bin"); +MODULE_FIRMWARE("radeon/HAWAII_mc2.bin"); MODULE_FIRMWARE("radeon/HAWAII_rlc.bin"); MODULE_FIRMWARE("radeon/HAWAII_sdma.bin"); MODULE_FIRMWARE("radeon/HAWAII_smc.bin"); @@ -1703,20 +1705,20 @@ int ci_mc_load_microcode(struct radeon_device *rdev) const __be32 *fw_data; u32 running, blackout = 0; u32 *io_mc_regs; - int i, ucode_size, regs_size; + int i, regs_size, ucode_size; if (!rdev->mc_fw) return -EINVAL; + ucode_size = rdev->mc_fw->size / 4; + switch (rdev->family) { case CHIP_BONAIRE: io_mc_regs = (u32 *)&bonaire_io_mc_regs; - ucode_size = CIK_MC_UCODE_SIZE; regs_size = BONAIRE_IO_MC_REGS_SIZE; break; case CHIP_HAWAII: io_mc_regs = (u32 *)&hawaii_io_mc_regs; - ucode_size = HAWAII_MC_UCODE_SIZE; regs_size = HAWAII_IO_MC_REGS_SIZE; break; default: @@ -1783,7 +1785,7 @@ static int cik_init_microcode(struct radeon_device *rdev) const char *chip_name; size_t pfp_req_size, me_req_size, ce_req_size, mec_req_size, rlc_req_size, mc_req_size = 0, - sdma_req_size, smc_req_size = 0; + sdma_req_size, smc_req_size = 0, mc2_req_size = 0; char fw_name[30]; int err; @@ -1797,7 +1799,8 @@ static int cik_init_microcode(struct radeon_device *rdev) ce_req_size = CIK_CE_UCODE_SIZE * 4; mec_req_size = CIK_MEC_UCODE_SIZE * 4; rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; - mc_req_size = CIK_MC_UCODE_SIZE * 4; + mc_req_size = BONAIRE_MC_UCODE_SIZE * 4; + mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4); break; @@ -1809,6 +1812,7 @@ static int cik_init_microcode(struct radeon_device *rdev) mec_req_size = CIK_MEC_UCODE_SIZE * 4; rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; mc_req_size = HAWAII_MC_UCODE_SIZE * 4; + mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4); break; @@ -1904,16 +1908,22 @@ static int cik_init_microcode(struct radeon_device *rdev) /* No SMC, MC ucode on APUs */ if (!(rdev->flags & RADEON_IS_IGP)) { - snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); - if (err) - goto out; - if (rdev->mc_fw->size != mc_req_size) { + if (err) { + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); + if (err) + goto out; + } + if ((rdev->mc_fw->size != mc_req_size) && + (rdev->mc_fw->size != mc2_req_size)){ printk(KERN_ERR "cik_mc: Bogus length %zu in firmware \"%s\"\n", rdev->mc_fw->size, fw_name); err = -EINVAL; } + DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size); snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 89b4afa..f7e46cf 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -597,7 +597,7 @@ int cik_sdma_ring_test(struct radeon_device *rdev, tmp = 0xCAFEDEAD; writel(tmp, ptr); - r = radeon_ring_lock(rdev, ring, 4); + r = radeon_ring_lock(rdev, ring, 5); if (r) { DRM_ERROR("radeon: dma failed to lock ring %d (%d).\n", ring->idx, r); return r; diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 94e8587..0a65dc7 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -309,11 +309,17 @@ int dce6_audio_init(struct radeon_device *rdev) rdev->audio.enabled = true; - if (ASIC_IS_DCE8(rdev)) + if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */ + rdev->audio.num_pins = 7; + else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */ + rdev->audio.num_pins = 3; + else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */ + rdev->audio.num_pins = 7; + else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */ rdev->audio.num_pins = 6; - else if (ASIC_IS_DCE61(rdev)) - rdev->audio.num_pins = 4; - else + else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */ + rdev->audio.num_pins = 2; + else /* SI: 6 streams, 6 endpoints */ rdev->audio.num_pins = 6; for (i = 0; i < rdev->audio.num_pins; i++) { diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index cbf7e32..9c61b74 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -158,16 +158,18 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev) u32 line_time_us, vblank_lines; u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - radeon_crtc = to_radeon_crtc(crtc); - if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { - line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) / - radeon_crtc->hw_mode.clock; - vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end - - radeon_crtc->hw_mode.crtc_vdisplay + - (radeon_crtc->v_border * 2); - vblank_time_us = vblank_lines * line_time_us; - break; + if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { + line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) / + radeon_crtc->hw_mode.clock; + vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end - + radeon_crtc->hw_mode.crtc_vdisplay + + (radeon_crtc->v_border * 2); + vblank_time_us = vblank_lines * line_time_us; + break; + } } } @@ -181,14 +183,15 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev) struct radeon_crtc *radeon_crtc; u32 vrefresh = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - radeon_crtc = to_radeon_crtc(crtc); - if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { - vrefresh = radeon_crtc->hw_mode.vrefresh; - break; + if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { + vrefresh = radeon_crtc->hw_mode.vrefresh; + break; + } } } - return vrefresh; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f21db7a..b58e1af 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -739,7 +739,7 @@ union radeon_irq_stat_regs { struct cik_irq_stat_regs cik; }; -#define RADEON_MAX_HPD_PINS 6 +#define RADEON_MAX_HPD_PINS 7 #define RADEON_MAX_CRTCS 6 #define RADEON_MAX_AFMT_BLOCKS 7 @@ -2321,6 +2321,7 @@ struct radeon_device { bool have_disp_power_ref; }; +bool radeon_is_px(struct drm_device *dev); int radeon_device_init(struct radeon_device *rdev, struct drm_device *ddev, struct pci_dev *pdev, @@ -2631,6 +2632,9 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); #define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND)) #define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN)) #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) +#define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI)) +#define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE)) +#define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI)) #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ (rdev->ddev->pdev->device == 0x6850) || \ diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index fa9a9c0..a9fb0d0 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -59,7 +59,7 @@ struct atpx_mux { u16 mux; } __packed; -bool radeon_is_px(void) { +bool radeon_has_atpx(void) { return radeon_atpx_priv.atpx_detected; } @@ -528,6 +528,13 @@ static bool radeon_atpx_detect(void) has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); } + /* some newer PX laptops mark the dGPU as a non-VGA display device */ + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { + vga_count++; + + has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); + } + if (has_atpx && vga_count == 2) { acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index c566b48..ea50e0a 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1261,21 +1261,6 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = { .force = radeon_dvi_force, }; -static void radeon_dp_connector_destroy(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; - - if (radeon_connector->edid) - kfree(radeon_connector->edid); - if (radeon_dig_connector->dp_i2c_bus) - radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); - kfree(radeon_connector->con_priv); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - static int radeon_dp_get_modes(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1553,7 +1538,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_connector_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1562,7 +1547,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_lvds_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1571,7 +1556,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_lvds_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1668,17 +1653,10 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; if (i2c_bus->valid) { - /* add DP i2c bus */ - if (connector_type == DRM_MODE_CONNECTOR_eDP) - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); - else - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (radeon_dig_connector->dp_i2c_bus) + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (radeon_connector->ddc_bus) has_aux = true; else - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } switch (connector_type) { @@ -1893,10 +1871,6 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { - /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (!radeon_dig_connector->dp_i2c_bus) - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (radeon_connector->ddc_bus) has_aux = true; @@ -1942,14 +1916,10 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { - /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); - if (radeon_dig_connector->dp_i2c_bus) + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (radeon_connector->ddc_bus) has_aux = true; else - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } drm_object_attach_property(&radeon_connector->base.base, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 835516d..511fe26 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -102,11 +102,14 @@ static const char radeon_family_name[][16] = { "LAST", }; -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_is_px(void); -#else -static inline bool radeon_is_px(void) { return false; } -#endif +bool radeon_is_px(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + + if (rdev->flags & RADEON_IS_PX) + return true; + return false; +} /** * radeon_program_register_sequence - program an array of registers. @@ -1082,7 +1085,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero { struct drm_device *dev = pci_get_drvdata(pdev); - if (radeon_is_px() && state == VGA_SWITCHEROO_OFF) + if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) return; if (state == VGA_SWITCHEROO_ON) { @@ -1301,9 +1304,7 @@ int radeon_device_init(struct radeon_device *rdev, * ignore it */ vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); - if (radeon_runtime_pm == 1) - runtime = true; - if ((radeon_runtime_pm == -1) && radeon_is_px()) + if (rdev->flags & RADEON_IS_PX) runtime = true; vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); if (runtime) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 386cfa4..8d99d5e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -759,19 +759,18 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != ENCODER_OBJECT_ID_NONE) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - - if (dig->dp_i2c_bus) + if (radeon_connector->ddc_bus->has_aux) radeon_connector->edid = drm_get_edid(&radeon_connector->base, - &dig->dp_i2c_bus->adapter); + &radeon_connector->ddc_bus->aux.ddc); } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || - dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) + dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && + radeon_connector->ddc_bus->has_aux) radeon_connector->edid = drm_get_edid(&radeon_connector->base, - &dig->dp_i2c_bus->adapter); + &radeon_connector->ddc_bus->aux.ddc); else if (radeon_connector->ddc_bus && !radeon_connector->edid) radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); @@ -841,6 +840,38 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den, } /** + * avivo_get_fb_ref_div - feedback and ref divider calculation + * + * @nom: nominator + * @den: denominator + * @post_div: post divider + * @fb_div_max: feedback divider maximum + * @ref_div_max: reference divider maximum + * @fb_div: resulting feedback divider + * @ref_div: resulting reference divider + * + * Calculate feedback and reference divider for a given post divider. Makes + * sure we stay within the limits. + */ +static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, + unsigned fb_div_max, unsigned ref_div_max, + unsigned *fb_div, unsigned *ref_div) +{ + /* limit reference * post divider to a maximum */ + ref_div_max = min(210 / post_div, ref_div_max); + + /* get matching reference and feedback divider */ + *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); + *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); + + /* limit fb divider to its maximum */ + if (*fb_div > fb_div_max) { + *ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div); + *fb_div = fb_div_max; + } +} + +/** * radeon_compute_pll_avivo - compute PLL paramaters * * @pll: information about the PLL @@ -861,11 +892,14 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, u32 *ref_div_p, u32 *post_div_p) { + unsigned target_clock = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? + freq : freq / 10; + unsigned fb_div_min, fb_div_max, fb_div; unsigned post_div_min, post_div_max, post_div; unsigned ref_div_min, ref_div_max, ref_div; unsigned post_div_best, diff_best; - unsigned nom, den, tmp; + unsigned nom, den; /* determine allowed feedback divider range */ fb_div_min = pll->min_feedback_div; @@ -881,14 +915,18 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, ref_div_min = pll->reference_div; else ref_div_min = pll->min_ref_div; - ref_div_max = pll->max_ref_div; + + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && + pll->flags & RADEON_PLL_USE_REF_DIV) + ref_div_max = pll->reference_div; + else + ref_div_max = pll->max_ref_div; /* determine allowed post divider range */ if (pll->flags & RADEON_PLL_USE_POST_DIV) { post_div_min = pll->post_div; post_div_max = pll->post_div; } else { - unsigned target_clock = freq / 10; unsigned vco_min, vco_max; if (pll->flags & RADEON_PLL_IS_LCD) { @@ -899,6 +937,11 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, vco_max = pll->pll_out_max; } + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { + vco_min *= 10; + vco_max *= 10; + } + post_div_min = vco_min / target_clock; if ((target_clock * post_div_min) < vco_min) ++post_div_min; @@ -913,7 +956,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, } /* represent the searched ratio as fractional number */ - nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10; + nom = target_clock; den = pll->reference_freq; /* reduce the numbers to a simpler ratio */ @@ -927,7 +970,12 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, diff_best = ~0; for (post_div = post_div_min; post_div <= post_div_max; ++post_div) { - unsigned diff = abs(den - den / post_div * post_div); + unsigned diff; + avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, + ref_div_max, &fb_div, &ref_div); + diff = abs(target_clock - (pll->reference_freq * fb_div) / + (ref_div * post_div)); + if (diff < diff_best || (diff == diff_best && !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) { @@ -937,24 +985,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, } post_div = post_div_best; - /* get matching reference and feedback divider */ - ref_div = max(den / post_div, 1u); - fb_div = nom; - - /* we're almost done, but reference and feedback - divider might be to large now */ - - tmp = ref_div; - - if (fb_div > fb_div_max) { - ref_div = ref_div * fb_div_max / fb_div; - fb_div = fb_div_max; - } - - if (ref_div > ref_div_max) { - ref_div = ref_div_max; - fb_div = nom * ref_div_max / tmp; - } + /* get the feedback and reference divider for the optimal value */ + avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max, + &fb_div, &ref_div); /* reduce the numbers to a simpler ratio once more */ /* this also makes sure that the reference divider is large enough */ @@ -976,7 +1009,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, *post_div_p = post_div; DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n", - freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p, + freq, *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, ref_div, post_div); } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index d0eba48..c00a2f5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -115,6 +115,7 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime); +extern bool radeon_is_px(struct drm_device *dev); extern const struct drm_ioctl_desc radeon_ioctls_kms[]; extern int radeon_max_kms_ioctl; int radeon_mmap(struct file *filp, struct vm_area_struct *vma); @@ -144,11 +145,9 @@ void radeon_debugfs_cleanup(struct drm_minor *minor); #if defined(CONFIG_VGA_SWITCHEROO) void radeon_register_atpx_handler(void); void radeon_unregister_atpx_handler(void); -bool radeon_is_px(void); #else static inline void radeon_register_atpx_handler(void) {} static inline void radeon_unregister_atpx_handler(void) {} -static inline bool radeon_is_px(void) { return false; } #endif int radeon_no_wb; @@ -186,7 +185,7 @@ module_param_named(dynclks, radeon_dynclks, int, 0444); MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx"); module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); -MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing"); +MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, radeon_vram_limit, int, 0600); MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); @@ -405,12 +404,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); int ret; - if (radeon_runtime_pm == 0) { - pm_runtime_forbid(dev); - return -EBUSY; - } - - if (radeon_runtime_pm == -1 && !radeon_is_px()) { + if (!radeon_is_px(drm_dev)) { pm_runtime_forbid(dev); return -EBUSY; } @@ -434,10 +428,7 @@ static int radeon_pmops_runtime_resume(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); int ret; - if (radeon_runtime_pm == 0) - return -EINVAL; - - if (radeon_runtime_pm == -1 && !radeon_is_px()) + if (!radeon_is_px(drm_dev)) return -EINVAL; drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; @@ -462,14 +453,7 @@ static int radeon_pmops_runtime_idle(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); struct drm_crtc *crtc; - if (radeon_runtime_pm == 0) { - pm_runtime_forbid(dev); - return -EBUSY; - } - - /* are we PX enabled? */ - if (radeon_runtime_pm == -1 && !radeon_is_px()) { - DRM_DEBUG_DRIVER("failing to power off - not px\n"); + if (!radeon_is_px(drm_dev)) { pm_runtime_forbid(dev); return -EBUSY; } diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 614ad54..9da5da4 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h @@ -115,6 +115,7 @@ enum radeon_chip_flags { RADEON_NEW_MEMMAP = 0x00400000UL, RADEON_IS_PCI = 0x00800000UL, RADEON_IS_IGPGART = 0x01000000UL, + RADEON_IS_PX = 0x02000000UL, }; #endif diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index e24ca6a..7b94414 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -64,8 +64,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) radeon_router_select_ddc_port(radeon_connector); if (use_aux) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); + ret = i2c_transfer(&radeon_connector->ddc_bus->aux.ddc, msgs, 2); } else { ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); } @@ -950,16 +949,16 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, /* set the radeon bit adapter */ snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "Radeon i2c bit bus %s", name); - i2c->adapter.algo_data = &i2c->algo.bit; - i2c->algo.bit.pre_xfer = pre_xfer; - i2c->algo.bit.post_xfer = post_xfer; - i2c->algo.bit.setsda = set_data; - i2c->algo.bit.setscl = set_clock; - i2c->algo.bit.getsda = get_data; - i2c->algo.bit.getscl = get_clock; - i2c->algo.bit.udelay = 10; - i2c->algo.bit.timeout = usecs_to_jiffies(2200); /* from VESA */ - i2c->algo.bit.data = i2c; + i2c->adapter.algo_data = &i2c->bit; + i2c->bit.pre_xfer = pre_xfer; + i2c->bit.post_xfer = post_xfer; + i2c->bit.setsda = set_data; + i2c->bit.setscl = set_clock; + i2c->bit.getsda = get_data; + i2c->bit.getscl = get_clock; + i2c->bit.udelay = 10; + i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ + i2c->bit.data = i2c; ret = i2c_bit_add_bus(&i2c->adapter); if (ret) { DRM_ERROR("Failed to register bit i2c %s\n", name); @@ -974,46 +973,13 @@ out_free: } -struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, - struct radeon_i2c_bus_rec *rec, - const char *name) -{ - struct radeon_i2c_chan *i2c; - int ret; - - i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); - if (i2c == NULL) - return NULL; - - i2c->rec = *rec; - i2c->adapter.owner = THIS_MODULE; - i2c->adapter.class = I2C_CLASS_DDC; - i2c->adapter.dev.parent = &dev->pdev->dev; - i2c->dev = dev; - snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), - "Radeon aux bus %s", name); - i2c_set_adapdata(&i2c->adapter, i2c); - i2c->adapter.algo_data = &i2c->algo.dp; - i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch; - i2c->algo.dp.address = 0; - ret = i2c_dp_aux_add_bus(&i2c->adapter); - if (ret) { - DRM_INFO("Failed to register i2c %s\n", name); - goto out_free; - } - - return i2c; -out_free: - kfree(i2c); - return NULL; - -} - void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) { if (!i2c) return; i2c_del_adapter(&i2c->adapter); + if (i2c->has_aux) + drm_dp_aux_unregister_i2c_bus(&i2c->aux); kfree(i2c); } diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 3e49342..0cc47f1 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -35,9 +35,9 @@ #include <linux/pm_runtime.h> #if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_is_px(void); +bool radeon_has_atpx(void); #else -static inline bool radeon_is_px(void) { return false; } +static inline bool radeon_has_atpx(void) { return false; } #endif /** @@ -107,6 +107,11 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) flags |= RADEON_IS_PCI; } + if ((radeon_runtime_pm != 0) && + radeon_has_atpx() && + ((flags & RADEON_IS_IGP) == 0)) + flags |= RADEON_IS_PX; + /* radeon_device_init should report only fatal error * like memory allocation failure or iomapping failure, * or memory manager initialization failure, it must @@ -137,8 +142,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) "Error during ACPI methods call\n"); } - if ((radeon_runtime_pm == 1) || - ((radeon_runtime_pm == -1) && radeon_is_px())) { + if (radeon_is_px(dev)) { pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); @@ -568,12 +572,17 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) } r = radeon_vm_init(rdev, &fpriv->vm); - if (r) + if (r) { + kfree(fpriv); return r; + } r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); - if (r) + if (r) { + radeon_vm_fini(rdev, &fpriv->vm); + kfree(fpriv); return r; + } /* map the ib pool buffer read only into * virtual address space */ diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 832d9fa..6ddf31a 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -187,12 +187,10 @@ struct radeon_pll { struct radeon_i2c_chan { struct i2c_adapter adapter; struct drm_device *dev; - union { - struct i2c_algo_bit_data bit; - struct i2c_algo_dp_aux_data dp; - } algo; + struct i2c_algo_bit_data bit; struct radeon_i2c_bus_rec rec; struct drm_dp_aux aux; + bool has_aux; }; /* mostly for macs, but really any system without connector tables */ @@ -440,7 +438,6 @@ struct radeon_encoder { struct radeon_connector_atom_dig { uint32_t igp_lane_info; /* displayport */ - struct radeon_i2c_chan *dp_i2c_bus; u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 dp_sink_type; int dp_clock; @@ -702,8 +699,6 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, uint8_t lane_set); extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); -extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - u8 write_byte, u8 *read_byte); void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); extern void radeon_i2c_init(struct radeon_device *rdev); @@ -715,9 +710,6 @@ extern void radeon_i2c_add(struct radeon_device *rdev, const char *name); extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, struct radeon_i2c_bus_rec *i2c_bus); -extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, - struct radeon_i2c_bus_rec *rec, - const char *name); extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, struct radeon_i2c_bus_rec *rec, const char *name); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index ee738a5..6fac8ef 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -603,7 +603,6 @@ static const struct attribute_group *hwmon_groups[] = { static int radeon_hwmon_init(struct radeon_device *rdev) { int err = 0; - struct device *hwmon_dev; switch (rdev->pm.int_thermal_type) { case THERMAL_TYPE_RV6XX: @@ -616,11 +615,11 @@ static int radeon_hwmon_init(struct radeon_device *rdev) case THERMAL_TYPE_KV: if (rdev->asic->pm.get_temperature == NULL) return err; - hwmon_dev = hwmon_device_register_with_groups(rdev->dev, - "radeon", rdev, - hwmon_groups); - if (IS_ERR(hwmon_dev)) { - err = PTR_ERR(hwmon_dev); + rdev->pm.int_hwmon_dev = hwmon_device_register_with_groups(rdev->dev, + "radeon", rdev, + hwmon_groups); + if (IS_ERR(rdev->pm.int_hwmon_dev)) { + err = PTR_ERR(rdev->pm.int_hwmon_dev); dev_err(rdev->dev, "Unable to register hwmon device: %d\n", err); } @@ -632,6 +631,12 @@ static int radeon_hwmon_init(struct radeon_device *rdev) return err; } +static void radeon_hwmon_fini(struct radeon_device *rdev) +{ + if (rdev->pm.int_hwmon_dev) + hwmon_device_unregister(rdev->pm.int_hwmon_dev); +} + static void radeon_dpm_thermal_work_handler(struct work_struct *work) { struct radeon_device *rdev = @@ -1257,6 +1262,7 @@ int radeon_pm_init(struct radeon_device *rdev) case CHIP_RV670: case CHIP_RS780: case CHIP_RS880: + case CHIP_RV770: case CHIP_BARTS: case CHIP_TURKS: case CHIP_CAICOS: @@ -1273,7 +1279,6 @@ int radeon_pm_init(struct radeon_device *rdev) else rdev->pm.pm_method = PM_METHOD_PROFILE; break; - case CHIP_RV770: case CHIP_RV730: case CHIP_RV710: case CHIP_RV740: @@ -1353,6 +1358,8 @@ static void radeon_pm_fini_old(struct radeon_device *rdev) device_remove_file(rdev->dev, &dev_attr_power_method); } + radeon_hwmon_fini(rdev); + if (rdev->pm.power_state) kfree(rdev->pm.power_state); } @@ -1372,6 +1379,8 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev) } radeon_dpm_fini(rdev); + radeon_hwmon_fini(rdev); + if (rdev->pm.power_state) kfree(rdev->pm.power_state); } @@ -1397,12 +1406,14 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev) rdev->pm.active_crtcs = 0; rdev->pm.active_crtc_count = 0; - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - radeon_crtc = to_radeon_crtc(crtc); - if (radeon_crtc->enabled) { - rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id); - rdev->pm.active_crtc_count++; + if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (radeon_crtc->enabled) { + rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id); + rdev->pm.active_crtc_count++; + } } } @@ -1469,12 +1480,14 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev) /* update active crtc counts */ rdev->pm.dpm.new_active_crtcs = 0; rdev->pm.dpm.new_active_crtc_count = 0; - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - radeon_crtc = to_radeon_crtc(crtc); - if (crtc->enabled) { - rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id); - rdev->pm.dpm.new_active_crtc_count++; + if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled) { + rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id); + rdev->pm.dpm.new_active_crtc_count++; + } } } diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index a77cd27..58d1293 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -57,9 +57,14 @@ #define BTC_MC_UCODE_SIZE 6024 #define CAYMAN_MC_UCODE_SIZE 6037 #define SI_MC_UCODE_SIZE 7769 +#define TAHITI_MC_UCODE_SIZE 7808 +#define PITCAIRN_MC_UCODE_SIZE 7775 +#define VERDE_MC_UCODE_SIZE 7875 #define OLAND_MC_UCODE_SIZE 7863 -#define CIK_MC_UCODE_SIZE 7866 +#define BONAIRE_MC_UCODE_SIZE 7866 +#define BONAIRE_MC2_UCODE_SIZE 7948 #define HAWAII_MC_UCODE_SIZE 7933 +#define HAWAII_MC2_UCODE_SIZE 8091 /* SDMA */ #define CIK_SDMA_UCODE_SIZE 1050 diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 76e9904..ced53dd 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -613,7 +613,7 @@ void radeon_vce_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[fence->ring]; - uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr; + uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr; radeon_ring_write(ring, VCE_CMD_FENCE); radeon_ring_write(ring, addr); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d589475..ac708e0 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -39,30 +39,35 @@ MODULE_FIRMWARE("radeon/TAHITI_pfp.bin"); MODULE_FIRMWARE("radeon/TAHITI_me.bin"); MODULE_FIRMWARE("radeon/TAHITI_ce.bin"); MODULE_FIRMWARE("radeon/TAHITI_mc.bin"); +MODULE_FIRMWARE("radeon/TAHITI_mc2.bin"); MODULE_FIRMWARE("radeon/TAHITI_rlc.bin"); MODULE_FIRMWARE("radeon/TAHITI_smc.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_me.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin"); +MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin"); MODULE_FIRMWARE("radeon/VERDE_pfp.bin"); MODULE_FIRMWARE("radeon/VERDE_me.bin"); MODULE_FIRMWARE("radeon/VERDE_ce.bin"); MODULE_FIRMWARE("radeon/VERDE_mc.bin"); +MODULE_FIRMWARE("radeon/VERDE_mc2.bin"); MODULE_FIRMWARE("radeon/VERDE_rlc.bin"); MODULE_FIRMWARE("radeon/VERDE_smc.bin"); MODULE_FIRMWARE("radeon/OLAND_pfp.bin"); MODULE_FIRMWARE("radeon/OLAND_me.bin"); MODULE_FIRMWARE("radeon/OLAND_ce.bin"); MODULE_FIRMWARE("radeon/OLAND_mc.bin"); +MODULE_FIRMWARE("radeon/OLAND_mc2.bin"); MODULE_FIRMWARE("radeon/OLAND_rlc.bin"); MODULE_FIRMWARE("radeon/OLAND_smc.bin"); MODULE_FIRMWARE("radeon/HAINAN_pfp.bin"); MODULE_FIRMWARE("radeon/HAINAN_me.bin"); MODULE_FIRMWARE("radeon/HAINAN_ce.bin"); MODULE_FIRMWARE("radeon/HAINAN_mc.bin"); +MODULE_FIRMWARE("radeon/HAINAN_mc2.bin"); MODULE_FIRMWARE("radeon/HAINAN_rlc.bin"); MODULE_FIRMWARE("radeon/HAINAN_smc.bin"); @@ -1467,36 +1472,33 @@ int si_mc_load_microcode(struct radeon_device *rdev) const __be32 *fw_data; u32 running, blackout = 0; u32 *io_mc_regs; - int i, ucode_size, regs_size; + int i, regs_size, ucode_size; if (!rdev->mc_fw) return -EINVAL; + ucode_size = rdev->mc_fw->size / 4; + switch (rdev->family) { case CHIP_TAHITI: io_mc_regs = (u32 *)&tahiti_io_mc_regs; - ucode_size = SI_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_PITCAIRN: io_mc_regs = (u32 *)&pitcairn_io_mc_regs; - ucode_size = SI_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_VERDE: default: io_mc_regs = (u32 *)&verde_io_mc_regs; - ucode_size = SI_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_OLAND: io_mc_regs = (u32 *)&oland_io_mc_regs; - ucode_size = OLAND_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_HAINAN: io_mc_regs = (u32 *)&hainan_io_mc_regs; - ucode_size = OLAND_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; } @@ -1552,7 +1554,7 @@ static int si_init_microcode(struct radeon_device *rdev) const char *chip_name; const char *rlc_chip_name; size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; - size_t smc_req_size; + size_t smc_req_size, mc2_req_size; char fw_name[30]; int err; @@ -1567,6 +1569,7 @@ static int si_init_microcode(struct radeon_device *rdev) ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; mc_req_size = SI_MC_UCODE_SIZE * 4; + mc2_req_size = TAHITI_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4); break; case CHIP_PITCAIRN: @@ -1577,6 +1580,7 @@ static int si_init_microcode(struct radeon_device *rdev) ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; mc_req_size = SI_MC_UCODE_SIZE * 4; + mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4); break; case CHIP_VERDE: @@ -1587,6 +1591,7 @@ static int si_init_microcode(struct radeon_device *rdev) ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; mc_req_size = SI_MC_UCODE_SIZE * 4; + mc2_req_size = VERDE_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4); break; case CHIP_OLAND: @@ -1596,7 +1601,7 @@ static int si_init_microcode(struct radeon_device *rdev) me_req_size = SI_PM4_UCODE_SIZE * 4; ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; - mc_req_size = OLAND_MC_UCODE_SIZE * 4; + mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4); break; case CHIP_HAINAN: @@ -1606,7 +1611,7 @@ static int si_init_microcode(struct radeon_device *rdev) me_req_size = SI_PM4_UCODE_SIZE * 4; ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; - mc_req_size = OLAND_MC_UCODE_SIZE * 4; + mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4); break; default: BUG(); @@ -1659,16 +1664,22 @@ static int si_init_microcode(struct radeon_device *rdev) err = -EINVAL; } - snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); - if (err) - goto out; - if (rdev->mc_fw->size != mc_req_size) { + if (err) { + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); + if (err) + goto out; + } + if ((rdev->mc_fw->size != mc_req_size) && + (rdev->mc_fw->size != mc2_req_size)) { printk(KERN_ERR "si_mc: Bogus length %zu in firmware \"%s\"\n", rdev->mc_fw->size, fw_name); err = -EINVAL; } + DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size); snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index d536ed3..005c19b 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -99,55 +99,73 @@ static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer, static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { - unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ; unsigned long timeout = msecs_to_jiffies(250); struct tegra_dpaux *dpaux = to_dpaux(aux); unsigned long status; ssize_t ret = 0; + u32 value; - if (msg->size < 1 || msg->size > 16) + /* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */ + if (msg->size > 16) return -EINVAL; - tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); + /* + * Allow zero-sized messages only for I2C, in which case they specify + * address-only transactions. + */ + if (msg->size < 1) { + switch (msg->request & ~DP_AUX_I2C_MOT) { + case DP_AUX_I2C_WRITE: + case DP_AUX_I2C_READ: + value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY; + break; + + default: + return -EINVAL; + } + } else { + /* For non-zero-sized messages, set the CMDLEN field. */ + value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); + } switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_I2C_WRITE: if (msg->request & DP_AUX_I2C_MOT) - value = DPAUX_DP_AUXCTL_CMD_MOT_WR; + value |= DPAUX_DP_AUXCTL_CMD_MOT_WR; else - value = DPAUX_DP_AUXCTL_CMD_I2C_WR; + value |= DPAUX_DP_AUXCTL_CMD_I2C_WR; break; case DP_AUX_I2C_READ: if (msg->request & DP_AUX_I2C_MOT) - value = DPAUX_DP_AUXCTL_CMD_MOT_RD; + value |= DPAUX_DP_AUXCTL_CMD_MOT_RD; else - value = DPAUX_DP_AUXCTL_CMD_I2C_RD; + value |= DPAUX_DP_AUXCTL_CMD_I2C_RD; break; case DP_AUX_I2C_STATUS: if (msg->request & DP_AUX_I2C_MOT) - value = DPAUX_DP_AUXCTL_CMD_MOT_RQ; + value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; else - value = DPAUX_DP_AUXCTL_CMD_I2C_RQ; + value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ; break; case DP_AUX_NATIVE_WRITE: - value = DPAUX_DP_AUXCTL_CMD_AUX_WR; + value |= DPAUX_DP_AUXCTL_CMD_AUX_WR; break; case DP_AUX_NATIVE_READ: - value = DPAUX_DP_AUXCTL_CMD_AUX_RD; + value |= DPAUX_DP_AUXCTL_CMD_AUX_RD; break; default: return -EINVAL; } - value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); + tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL); if ((msg->request & DP_AUX_I2C_READ) == 0) { @@ -198,7 +216,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, break; } - if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) { + if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) { if (msg->request & DP_AUX_I2C_READ) { size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK; diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h index 4f5bf10..806e245 100644 --- a/drivers/gpu/drm/tegra/dpaux.h +++ b/drivers/gpu/drm/tegra/dpaux.h @@ -32,6 +32,7 @@ #define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12) #define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12) #define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12) +#define DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY (1 << 8) #define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff) #define DPAUX_DP_AUXSTAT 0x31 diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index db9017a..498b37e 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -47,7 +47,7 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) unsigned long reg; int i, id; - for (i = 0; i <= BIT_WORD(host->info->nb_pts); i++) { + for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) { reg = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); for_each_set_bit(id, ®, BITS_PER_LONG) { @@ -64,7 +64,7 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host) { u32 i; - for (i = 0; i <= BIT_WORD(host->info->nb_pts); ++i) { + for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) { host1x_sync_writel(host, 0xffffffffu, HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i)); host1x_sync_writel(host, 0xffffffffu, diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9e806420..10a2c08 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -718,6 +718,9 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) case HID_MAIN_ITEM_TAG_END_COLLECTION: break; case HID_MAIN_ITEM_TAG_INPUT: + /* ignore constant inputs, they will be ignored by hid-input */ + if (data & HID_MAIN_ITEM_CONSTANT) + break; for (i = 0; i < parser->local.usage_index; i++) hid_scan_input_usage(parser, parser->local.usage[i]); break; @@ -1821,8 +1824,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index bd22126..c8af720 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -455,7 +455,8 @@ #define USB_VENDOR_ID_INTEL_0 0x8086 #define USB_VENDOR_ID_INTEL_1 0x8087 -#define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa +#define USB_DEVICE_ID_INTEL_HID_SENSOR_0 0x09fa +#define USB_DEVICE_ID_INTEL_HID_SENSOR_1 0x0a04 #define USB_VENDOR_ID_STM_0 0x0483 #define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1 @@ -629,8 +630,6 @@ #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c -#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 -#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 6fd5817..8ba17a9 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -274,10 +274,6 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), .driver_data = MS_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), - .driver_data = 0 }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), - .driver_data = 0 }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 5182031..af8244b 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -697,10 +697,13 @@ static void sensor_hub_remove(struct hid_device *hdev) static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_0, - USB_DEVICE_ID_INTEL_HID_SENSOR), + USB_DEVICE_ID_INTEL_HID_SENSOR_0), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, - USB_DEVICE_ID_INTEL_HID_SENSOR), + USB_DEVICE_ID_INTEL_HID_SENSOR_0), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, + USB_DEVICE_ID_INTEL_HID_SENSOR_1), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, USB_DEVICE_ID_STM_HID_SENSOR), diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 69204af..908de27 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1721,8 +1721,6 @@ static void sony_remove(struct hid_device *hdev) if (sc->quirks & SONY_LED_SUPPORT) sony_leds_remove(hdev); - if (sc->worker_initialized) - cancel_work_sync(&sc->state_worker); if (sc->quirks & SONY_BATTERY_SUPPORT) { hid_hw_close(hdev); sony_battery_remove(sc); diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index f2d7bf9..2e7801a 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -55,6 +55,9 @@ static __u32 vmbus_get_next_version(__u32 current_version) case (VERSION_WIN8): return VERSION_WIN7; + case (VERSION_WIN8_1): + return VERSION_WIN8; + case (VERSION_WS2008): default: return VERSION_INVAL; @@ -77,7 +80,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); - if (version == VERSION_WIN8) + if (version == VERSION_WIN8_1) msg->target_vcpu = hv_context.vp_index[smp_processor_id()]; /* diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c index c104cc3..c9cddf5 100644 --- a/drivers/hwmon/ltc2945.c +++ b/drivers/hwmon/ltc2945.c @@ -1,4 +1,4 @@ -/* + /* * Driver for Linear Technology LTC2945 I2C Power Monitor * * Copyright (c) 2014 Guenter Roeck @@ -314,8 +314,8 @@ static ssize_t ltc2945_reset_history(struct device *dev, reg = LTC2945_MAX_ADIN_H; break; default: - BUG(); - break; + WARN_ONCE(1, "Bad register: 0x%x\n", reg); + return -EINVAL; } /* Reset maximum */ ret = regmap_bulk_write(regmap, reg, buf_max, num_regs); diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c index d867e6b..8242b75 100644 --- a/drivers/hwmon/vexpress.c +++ b/drivers/hwmon/vexpress.c @@ -27,15 +27,15 @@ struct vexpress_hwmon_data { struct device *hwmon_dev; struct vexpress_config_func *func; + const char *name; }; static ssize_t vexpress_hwmon_name_show(struct device *dev, struct device_attribute *dev_attr, char *buffer) { - const char *compatible = of_get_property(dev->of_node, "compatible", - NULL); + struct vexpress_hwmon_data *data = dev_get_drvdata(dev); - return sprintf(buffer, "%s\n", compatible); + return sprintf(buffer, "%s\n", data->name); } static ssize_t vexpress_hwmon_label_show(struct device *dev, @@ -43,9 +43,6 @@ static ssize_t vexpress_hwmon_label_show(struct device *dev, { const char *label = of_get_property(dev->of_node, "label", NULL); - if (!label) - return -ENOENT; - return snprintf(buffer, PAGE_SIZE, "%s\n", label); } @@ -84,6 +81,20 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev, to_sensor_dev_attr(dev_attr)->index)); } +static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = kobj_to_dev(kobj); + struct device_attribute *dev_attr = container_of(attr, + struct device_attribute, attr); + + if (dev_attr->show == vexpress_hwmon_label_show && + !of_get_property(dev->of_node, "label", NULL)) + return 0; + + return attr->mode; +} + static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL); #define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \ @@ -94,14 +105,27 @@ struct attribute *vexpress_hwmon_attrs_##_name[] = { \ NULL \ } +struct vexpress_hwmon_type { + const char *name; + const struct attribute_group **attr_groups; +}; + #if !defined(CONFIG_REGULATOR_VEXPRESS) static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, NULL, 1000); static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input); static struct attribute_group vexpress_hwmon_group_volt = { + .is_visible = vexpress_hwmon_attr_is_visible, .attrs = vexpress_hwmon_attrs_volt, }; +static struct vexpress_hwmon_type vexpress_hwmon_volt = { + .name = "vexpress_volt", + .attr_groups = (const struct attribute_group *[]) { + &vexpress_hwmon_group_volt, + NULL, + }, +}; #endif static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); @@ -109,52 +133,84 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, NULL, 1000); static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input); static struct attribute_group vexpress_hwmon_group_amp = { + .is_visible = vexpress_hwmon_attr_is_visible, .attrs = vexpress_hwmon_attrs_amp, }; +static struct vexpress_hwmon_type vexpress_hwmon_amp = { + .name = "vexpress_amp", + .attr_groups = (const struct attribute_group *[]) { + &vexpress_hwmon_group_amp, + NULL + }, +}; static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, NULL, 1000); static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input); static struct attribute_group vexpress_hwmon_group_temp = { + .is_visible = vexpress_hwmon_attr_is_visible, .attrs = vexpress_hwmon_attrs_temp, }; +static struct vexpress_hwmon_type vexpress_hwmon_temp = { + .name = "vexpress_temp", + .attr_groups = (const struct attribute_group *[]) { + &vexpress_hwmon_group_temp, + NULL + }, +}; static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, NULL, 1); static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input); static struct attribute_group vexpress_hwmon_group_power = { + .is_visible = vexpress_hwmon_attr_is_visible, .attrs = vexpress_hwmon_attrs_power, }; +static struct vexpress_hwmon_type vexpress_hwmon_power = { + .name = "vexpress_power", + .attr_groups = (const struct attribute_group *[]) { + &vexpress_hwmon_group_power, + NULL + }, +}; static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, NULL, 1); static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input); static struct attribute_group vexpress_hwmon_group_energy = { + .is_visible = vexpress_hwmon_attr_is_visible, .attrs = vexpress_hwmon_attrs_energy, }; +static struct vexpress_hwmon_type vexpress_hwmon_energy = { + .name = "vexpress_energy", + .attr_groups = (const struct attribute_group *[]) { + &vexpress_hwmon_group_energy, + NULL + }, +}; static struct of_device_id vexpress_hwmon_of_match[] = { #if !defined(CONFIG_REGULATOR_VEXPRESS) { .compatible = "arm,vexpress-volt", - .data = &vexpress_hwmon_group_volt, + .data = &vexpress_hwmon_volt, }, #endif { .compatible = "arm,vexpress-amp", - .data = &vexpress_hwmon_group_amp, + .data = &vexpress_hwmon_amp, }, { .compatible = "arm,vexpress-temp", - .data = &vexpress_hwmon_group_temp, + .data = &vexpress_hwmon_temp, }, { .compatible = "arm,vexpress-power", - .data = &vexpress_hwmon_group_power, + .data = &vexpress_hwmon_power, }, { .compatible = "arm,vexpress-energy", - .data = &vexpress_hwmon_group_energy, + .data = &vexpress_hwmon_energy, }, {} }; @@ -165,6 +221,7 @@ static int vexpress_hwmon_probe(struct platform_device *pdev) int err; const struct of_device_id *match; struct vexpress_hwmon_data *data; + const struct vexpress_hwmon_type *type; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -174,12 +231,14 @@ static int vexpress_hwmon_probe(struct platform_device *pdev) match = of_match_device(vexpress_hwmon_of_match, &pdev->dev); if (!match) return -ENODEV; + type = match->data; + data->name = type->name; data->func = vexpress_config_func_get_by_dev(&pdev->dev); if (!data->func) return -ENODEV; - err = sysfs_create_group(&pdev->dev.kobj, match->data); + err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups); if (err) goto error; diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index a43220c..4d140bb 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -750,9 +750,10 @@ void intel_idle_state_table_update(void) if (package_num + 1 > num_sockets) { num_sockets = package_num + 1; - if (num_sockets > 4) + if (num_sockets > 4) { cpuidle_state_table = ivt_cstates_8s; return; + } } } diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 5b1aa02..89777ed 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -765,14 +765,17 @@ static int at91_adc_probe_pdata(struct at91_adc_state *st, if (!pdata) return -EINVAL; + st->caps = (struct at91_adc_caps *) + platform_get_device_id(pdev)->driver_data; + st->use_external = pdata->use_external_triggers; st->vref_mv = pdata->vref; st->channels_mask = pdata->channels_used; - st->num_channels = pdata->num_channels; + st->num_channels = st->caps->num_channels; st->startup_time = pdata->startup_time; st->trigger_number = pdata->trigger_number; st->trigger_list = pdata->trigger_list; - st->registers = pdata->registers; + st->registers = &st->caps->registers; return 0; } @@ -1004,8 +1007,11 @@ static int at91_adc_probe(struct platform_device *pdev) * the best converted final value between two channels selection * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock */ - shtim = round_up((st->sample_hold_time * adc_clk_khz / - 1000) - 1, 1); + if (st->sample_hold_time > 0) + shtim = round_up((st->sample_hold_time * adc_clk_khz / 1000) + - 1, 1); + else + shtim = 0; reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask; reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask; @@ -1101,7 +1107,6 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static struct at91_adc_caps at91sam9260_caps = { .calc_startup_ticks = calc_startup_ticks_9260, .num_channels = 4, @@ -1154,11 +1159,27 @@ static const struct of_device_id at91_adc_dt_ids[] = { {}, }; MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); -#endif + +static const struct platform_device_id at91_adc_ids[] = { + { + .name = "at91sam9260-adc", + .driver_data = (unsigned long)&at91sam9260_caps, + }, { + .name = "at91sam9g45-adc", + .driver_data = (unsigned long)&at91sam9g45_caps, + }, { + .name = "at91sam9x5-adc", + .driver_data = (unsigned long)&at91sam9x5_caps, + }, { + /* terminator */ + } +}; +MODULE_DEVICE_TABLE(platform, at91_adc_ids); static struct platform_driver at91_adc_driver = { .probe = at91_adc_probe, .remove = at91_adc_remove, + .id_table = at91_adc_ids, .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(at91_adc_dt_ids), diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index e108f2a..e472cff 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -165,7 +165,8 @@ static ssize_t iio_scan_el_show(struct device *dev, int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); - ret = test_bit(to_iio_dev_attr(attr)->address, + /* Ensure ret is 0 or 1. */ + ret = !!test_bit(to_iio_dev_attr(attr)->address, indio_dev->buffer->scan_mask); return sprintf(buf, "%d\n", ret); @@ -862,7 +863,8 @@ int iio_scan_mask_query(struct iio_dev *indio_dev, if (!buffer->scan_mask) return 0; - return test_bit(bit, buffer->scan_mask); + /* Ensure return value is 0 or 1. */ + return !!test_bit(bit, buffer->scan_mask); }; EXPORT_SYMBOL_GPL(iio_scan_mask_query); diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index 47a6dba..d976e6c 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -221,6 +221,7 @@ static int cm32181_read_raw(struct iio_dev *indio_dev, *val = cm32181->calibscale; return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: + *val = 0; ret = cm32181_read_als_it(cm32181, val2); return ret; } diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index a45e074..39fc67e 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -652,7 +652,19 @@ static int cm36651_probe(struct i2c_client *client, cm36651->client = client; cm36651->ps_client = i2c_new_dummy(client->adapter, CM36651_I2C_ADDR_PS); + if (!cm36651->ps_client) { + dev_err(&client->dev, "%s: new i2c device failed\n", __func__); + ret = -ENODEV; + goto error_disable_reg; + } + cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA); + if (!cm36651->ara_client) { + dev_err(&client->dev, "%s: new i2c device failed\n", __func__); + ret = -ENODEV; + goto error_i2c_unregister_ps; + } + mutex_init(&cm36651->lock); indio_dev->dev.parent = &client->dev; indio_dev->channels = cm36651_channels; @@ -664,7 +676,7 @@ static int cm36651_probe(struct i2c_client *client, ret = cm36651_setup_reg(cm36651); if (ret) { dev_err(&client->dev, "%s: register setup failed\n", __func__); - goto error_disable_reg; + goto error_i2c_unregister_ara; } ret = request_threaded_irq(client->irq, NULL, cm36651_irq_handler, @@ -672,7 +684,7 @@ static int cm36651_probe(struct i2c_client *client, "cm36651", indio_dev); if (ret) { dev_err(&client->dev, "%s: request irq failed\n", __func__); - goto error_disable_reg; + goto error_i2c_unregister_ara; } ret = iio_device_register(indio_dev); @@ -685,6 +697,10 @@ static int cm36651_probe(struct i2c_client *client, error_free_irq: free_irq(client->irq, indio_dev); +error_i2c_unregister_ara: + i2c_unregister_device(cm36651->ara_client); +error_i2c_unregister_ps: + i2c_unregister_device(cm36651->ps_client); error_disable_reg: regulator_disable(cm36651->vled_reg); return ret; @@ -698,6 +714,8 @@ static int cm36651_remove(struct i2c_client *client) iio_device_unregister(indio_dev); regulator_disable(cm36651->vled_reg); free_irq(client->irq, indio_dev); + i2c_unregister_device(cm36651->ps_client); + i2c_unregister_device(cm36651->ara_client); return 0; } diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 02436d5..185452a 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -173,12 +173,15 @@ static void start_ep_timer(struct c4iw_ep *ep) add_timer(&ep->timer); } -static void stop_ep_timer(struct c4iw_ep *ep) +static int stop_ep_timer(struct c4iw_ep *ep) { PDBG("%s ep %p stopping\n", __func__, ep); del_timer_sync(&ep->timer); - if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) + if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { c4iw_put_ep(&ep->com); + return 0; + } + return 1; } static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb, @@ -1165,12 +1168,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); /* - * Stop mpa timer. If it expired, then the state has - * changed and we bail since ep_timeout already aborted - * the connection. + * Stop mpa timer. If it expired, then + * we ignore the MPA reply. process_timeout() + * will abort the connection. */ - stop_ep_timer(ep); - if (ep->com.state != MPA_REQ_SENT) + if (stop_ep_timer(ep)) return; /* @@ -1375,15 +1377,12 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); - if (ep->com.state != MPA_REQ_WAIT) - return; - /* * If we get more than the supported amount of private data * then we must fail this connection. */ if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1413,13 +1412,13 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) if (mpa->revision > mpa_rev) { printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," " Received = %d\n", __func__, mpa_rev, mpa->revision); - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1430,7 +1429,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) * Fail if there's too much private data. */ if (plen > MPA_MAX_PRIVATE_DATA) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1439,7 +1438,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) * If plen does not account for pkt size */ if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1496,18 +1495,24 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, ep->mpa_attr.p2p_type); - __state_set(&ep->com, MPA_REQ_RCVD); - stop_ep_timer(ep); - - /* drive upcall */ - mutex_lock(&ep->parent_ep->com.mutex); - if (ep->parent_ep->com.state != DEAD) { - if (connect_request_upcall(ep)) + /* + * If the endpoint timer already expired, then we ignore + * the start request. process_timeout() will abort + * the connection. + */ + if (!stop_ep_timer(ep)) { + __state_set(&ep->com, MPA_REQ_RCVD); + + /* drive upcall */ + mutex_lock(&ep->parent_ep->com.mutex); + if (ep->parent_ep->com.state != DEAD) { + if (connect_request_upcall(ep)) + abort_connection(ep, skb, GFP_KERNEL); + } else { abort_connection(ep, skb, GFP_KERNEL); - } else { - abort_connection(ep, skb, GFP_KERNEL); + } + mutex_unlock(&ep->parent_ep->com.mutex); } - mutex_unlock(&ep->parent_ep->com.mutex); return; } @@ -2265,7 +2270,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) disconnect = 0; break; case MORIBUND: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); if (ep->com.cm_id && ep->com.qp) { attrs.next_state = C4IW_QP_STATE_IDLE; c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, @@ -2325,10 +2330,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) case CONNECTING: break; case MPA_REQ_WAIT: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); break; case MPA_REQ_SENT: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1)) connect_reply_upcall(ep, -ECONNRESET); else { @@ -2433,7 +2438,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) __state_set(&ep->com, MORIBUND); break; case MORIBUND: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); if ((ep->com.cm_id) && (ep->com.qp)) { attrs.next_state = C4IW_QP_STATE_IDLE; c4iw_modify_qp(ep->com.qp->rhp, @@ -3028,7 +3033,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { close = 1; if (abrupt) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); ep->com.state = ABORTING; } else ep->com.state = MORIBUND; @@ -3462,6 +3467,16 @@ static void process_timeout(struct c4iw_ep *ep) __state_set(&ep->com, ABORTING); close_complete_upcall(ep, -ETIMEDOUT); break; + case ABORTING: + case DEAD: + + /* + * These states are expected if the ep timed out at the same + * time as another thread was calling stop_ep_timer(). + * So we silently do nothing for these states. + */ + abort = 0; + break; default: WARN(1, "%s unexpected state ep %p tid %u state %u\n", __func__, ep, ep->hwtid, ep->com.state); @@ -3483,6 +3498,8 @@ static void process_timedout_eps(void) tmp = timeout_list.next; list_del(tmp); + tmp->next = NULL; + tmp->prev = NULL; spin_unlock_irq(&timeout_lock); ep = list_entry(tmp, struct c4iw_ep, entry); process_timeout(ep); @@ -3499,6 +3516,7 @@ static void process_work(struct work_struct *work) unsigned int opcode; int ret; + process_timedout_eps(); while ((skb = skb_dequeue(&rxq))) { rpl = cplhdr(skb); dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); @@ -3508,8 +3526,8 @@ static void process_work(struct work_struct *work) ret = work_handlers[opcode](dev, skb); if (!ret) kfree_skb(skb); + process_timedout_eps(); } - process_timedout_eps(); } static DECLARE_WORK(skb_work, process_work); @@ -3521,8 +3539,13 @@ static void ep_timeout(unsigned long arg) spin_lock(&timeout_lock); if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { - list_add_tail(&ep->entry, &timeout_list); - kickit = 1; + /* + * Only insert if it is not already on the list. + */ + if (!ep->entry.next) { + list_add_tail(&ep->entry, &timeout_list); + kickit = 1; + } } spin_unlock(&timeout_lock); if (kickit) diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index ce468e5..cfaa56a 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -235,27 +235,21 @@ int c4iw_flush_sq(struct c4iw_qp *qhp) struct t4_cq *cq = &chp->cq; int idx; struct t4_swsqe *swsqe; - int error = (qhp->attr.state != C4IW_QP_STATE_CLOSING && - qhp->attr.state != C4IW_QP_STATE_IDLE); if (wq->sq.flush_cidx == -1) wq->sq.flush_cidx = wq->sq.cidx; idx = wq->sq.flush_cidx; BUG_ON(idx >= wq->sq.size); while (idx != wq->sq.pidx) { - if (error) { - swsqe = &wq->sq.sw_sq[idx]; - BUG_ON(swsqe->flushed); - swsqe->flushed = 1; - insert_sq_cqe(wq, cq, swsqe); - if (wq->sq.oldest_read == swsqe) { - BUG_ON(swsqe->opcode != FW_RI_READ_REQ); - advance_oldest_read(wq); - } - flushed++; - } else { - t4_sq_consume(wq); + swsqe = &wq->sq.sw_sq[idx]; + BUG_ON(swsqe->flushed); + swsqe->flushed = 1; + insert_sq_cqe(wq, cq, swsqe); + if (wq->sq.oldest_read == swsqe) { + BUG_ON(swsqe->opcode != FW_RI_READ_REQ); + advance_oldest_read(wq); } + flushed++; if (++idx == wq->sq.size) idx = 0; } @@ -678,7 +672,7 @@ skip_cqe: static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc) { struct c4iw_qp *qhp = NULL; - struct t4_cqe cqe = {0, 0}, *rd_cqe; + struct t4_cqe uninitialized_var(cqe), *rd_cqe; struct t4_wq *wq; u32 credit = 0; u8 cqe_flushed; diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 9489a38..f4fa50a 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -682,7 +682,10 @@ static void c4iw_dealloc(struct uld_ctx *ctx) idr_destroy(&ctx->dev->hwtid_idr); idr_destroy(&ctx->dev->stid_idr); idr_destroy(&ctx->dev->atid_idr); - iounmap(ctx->dev->rdev.oc_mw_kva); + if (ctx->dev->rdev.bar2_kva) + iounmap(ctx->dev->rdev.bar2_kva); + if (ctx->dev->rdev.oc_mw_kva) + iounmap(ctx->dev->rdev.oc_mw_kva); ib_dealloc_device(&ctx->dev->ibdev); ctx->dev = NULL; } @@ -722,11 +725,31 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) } devp->rdev.lldi = *infop; - devp->rdev.oc_mw_pa = pci_resource_start(devp->rdev.lldi.pdev, 2) + - (pci_resource_len(devp->rdev.lldi.pdev, 2) - - roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size)); - devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa, - devp->rdev.lldi.vr->ocq.size); + /* + * For T5 devices, we map all of BAR2 with WC. + * For T4 devices with onchip qp mem, we map only that part + * of BAR2 with WC. + */ + devp->rdev.bar2_pa = pci_resource_start(devp->rdev.lldi.pdev, 2); + if (is_t5(devp->rdev.lldi.adapter_type)) { + devp->rdev.bar2_kva = ioremap_wc(devp->rdev.bar2_pa, + pci_resource_len(devp->rdev.lldi.pdev, 2)); + if (!devp->rdev.bar2_kva) { + pr_err(MOD "Unable to ioremap BAR2\n"); + return ERR_PTR(-EINVAL); + } + } else if (ocqp_supported(infop)) { + devp->rdev.oc_mw_pa = + pci_resource_start(devp->rdev.lldi.pdev, 2) + + pci_resource_len(devp->rdev.lldi.pdev, 2) - + roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size); + devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa, + devp->rdev.lldi.vr->ocq.size); + if (!devp->rdev.oc_mw_kva) { + pr_err(MOD "Unable to ioremap onchip mem\n"); + return ERR_PTR(-EINVAL); + } + } PDBG(KERN_INFO MOD "ocq memory: " "hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n", @@ -1003,9 +1026,11 @@ static int enable_qp_db(int id, void *p, void *data) static void resume_rc_qp(struct c4iw_qp *qp) { spin_lock(&qp->lock); - t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc); + t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc, + is_t5(qp->rhp->rdev.lldi.adapter_type), NULL); qp->wq.sq.wq_pidx_inc = 0; - t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc); + t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc, + is_t5(qp->rhp->rdev.lldi.adapter_type), NULL); qp->wq.rq.wq_pidx_inc = 0; spin_unlock(&qp->lock); } diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index e872203..7b8c580 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -149,6 +149,8 @@ struct c4iw_rdev { struct gen_pool *ocqp_pool; u32 flags; struct cxgb4_lld_info lldi; + unsigned long bar2_pa; + void __iomem *bar2_kva; unsigned long oc_mw_pa; void __iomem *oc_mw_kva; struct c4iw_stats stats; diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index f9ca072..ec7a298 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -259,8 +259,12 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) { stag_idx = c4iw_get_resource(&rdev->resource.tpt_table); - if (!stag_idx) + if (!stag_idx) { + mutex_lock(&rdev->stats.lock); + rdev->stats.stag.fail++; + mutex_unlock(&rdev->stats.lock); return -ENOMEM; + } mutex_lock(&rdev->stats.lock); rdev->stats.stag.cur += 32; if (rdev->stats.stag.cur > rdev->stats.stag.max) diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index 7942925..a94a3e1 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c @@ -328,7 +328,7 @@ static int c4iw_query_device(struct ib_device *ibdev, props->max_mr = c4iw_num_stags(&dev->rdev); props->max_pd = T4_MAX_NUM_PD; props->local_ca_ack_delay = 0; - props->max_fast_reg_page_list_len = T4_MAX_FR_DEPTH; + props->max_fast_reg_page_list_len = t4_max_fr_depth(use_dsgl); return 0; } diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index cb76eb5..7b5114c 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -212,13 +212,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, wq->db = rdev->lldi.db_reg; wq->gts = rdev->lldi.gts_reg; - if (user) { - wq->sq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) + - (wq->sq.qid << rdev->qpshift); - wq->sq.udb &= PAGE_MASK; - wq->rq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) + - (wq->rq.qid << rdev->qpshift); - wq->rq.udb &= PAGE_MASK; + if (user || is_t5(rdev->lldi.adapter_type)) { + u32 off; + + off = (wq->sq.qid << rdev->qpshift) & PAGE_MASK; + if (user) { + wq->sq.udb = (u64 __iomem *)(rdev->bar2_pa + off); + } else { + off += 128 * (wq->sq.qid & rdev->qpmask) + 8; + wq->sq.udb = (u64 __iomem *)(rdev->bar2_kva + off); + } + off = (wq->rq.qid << rdev->qpshift) & PAGE_MASK; + if (user) { + wq->rq.udb = (u64 __iomem *)(rdev->bar2_pa + off); + } else { + off += 128 * (wq->rq.qid & rdev->qpmask) + 8; + wq->rq.udb = (u64 __iomem *)(rdev->bar2_kva + off); + } } wq->rdev = rdev; wq->rq.msn = 1; @@ -299,9 +309,10 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, if (ret) goto free_dma; - PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%llx rqudb 0x%llx\n", + PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%lx rqudb 0x%lx\n", __func__, wq->sq.qid, wq->rq.qid, wq->db, - (unsigned long long)wq->sq.udb, (unsigned long long)wq->rq.udb); + (__force unsigned long) wq->sq.udb, + (__force unsigned long) wq->rq.udb); return 0; free_dma: @@ -425,6 +436,8 @@ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe, default: return -EINVAL; } + wqe->send.r3 = 0; + wqe->send.r4 = 0; plen = 0; if (wr->num_sge) { @@ -555,7 +568,8 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe, int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32); int rem; - if (wr->wr.fast_reg.page_list_len > T4_MAX_FR_DEPTH) + if (wr->wr.fast_reg.page_list_len > + t4_max_fr_depth(use_dsgl)) return -EINVAL; wqe->fr.qpbinde_to_dcacpu = 0; @@ -650,9 +664,10 @@ static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc) spin_lock_irqsave(&qhp->rhp->lock, flags); spin_lock(&qhp->lock); - if (qhp->rhp->db_state == NORMAL) { - t4_ring_sq_db(&qhp->wq, inc); - } else { + if (qhp->rhp->db_state == NORMAL) + t4_ring_sq_db(&qhp->wq, inc, + is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL); + else { add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry); qhp->wq.sq.wq_pidx_inc += inc; } @@ -667,9 +682,10 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc) spin_lock_irqsave(&qhp->rhp->lock, flags); spin_lock(&qhp->lock); - if (qhp->rhp->db_state == NORMAL) { - t4_ring_rq_db(&qhp->wq, inc); - } else { + if (qhp->rhp->db_state == NORMAL) + t4_ring_rq_db(&qhp->wq, inc, + is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL); + else { add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry); qhp->wq.rq.wq_pidx_inc += inc; } @@ -686,7 +702,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, enum fw_wr_opcodes fw_opcode = 0; enum fw_ri_wr_flags fw_flags; struct c4iw_qp *qhp; - union t4_wr *wqe; + union t4_wr *wqe = NULL; u32 num_wrs; struct t4_swsqe *swsqe; unsigned long flag; @@ -792,7 +808,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); } if (!qhp->rhp->rdev.status_page->db_off) { - t4_ring_sq_db(&qhp->wq, idx); + t4_ring_sq_db(&qhp->wq, idx, + is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe); spin_unlock_irqrestore(&qhp->lock, flag); } else { spin_unlock_irqrestore(&qhp->lock, flag); @@ -806,7 +823,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, { int err = 0; struct c4iw_qp *qhp; - union t4_recv_wr *wqe; + union t4_recv_wr *wqe = NULL; u32 num_wrs; u8 len16 = 0; unsigned long flag; @@ -858,7 +875,8 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, num_wrs--; } if (!qhp->rhp->rdev.status_page->db_off) { - t4_ring_rq_db(&qhp->wq, idx); + t4_ring_rq_db(&qhp->wq, idx, + is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe); spin_unlock_irqrestore(&qhp->lock, flag); } else { spin_unlock_irqrestore(&qhp->lock, flag); @@ -1352,6 +1370,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, switch (attrs->next_state) { case C4IW_QP_STATE_CLOSING: BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2); + t4_set_wq_in_error(&qhp->wq); set_state(qhp, C4IW_QP_STATE_CLOSING); ep = qhp->ep; if (!internal) { @@ -1359,18 +1378,18 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, disconnect = 1; c4iw_get_ep(&qhp->ep->com); } - t4_set_wq_in_error(&qhp->wq); ret = rdma_fini(rhp, qhp, ep); if (ret) goto err; break; case C4IW_QP_STATE_TERMINATE: + t4_set_wq_in_error(&qhp->wq); set_state(qhp, C4IW_QP_STATE_TERMINATE); qhp->attr.layer_etype = attrs->layer_etype; qhp->attr.ecode = attrs->ecode; - t4_set_wq_in_error(&qhp->wq); ep = qhp->ep; disconnect = 1; + c4iw_get_ep(&qhp->ep->com); if (!internal) terminate = 1; else { @@ -1378,11 +1397,10 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, if (ret) goto err; } - c4iw_get_ep(&qhp->ep->com); break; case C4IW_QP_STATE_ERROR: - set_state(qhp, C4IW_QP_STATE_ERROR); t4_set_wq_in_error(&qhp->wq); + set_state(qhp, C4IW_QP_STATE_ERROR); if (!internal) { abort = 1; disconnect = 1; @@ -1677,11 +1695,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize); insert_mmap(ucontext, mm2); mm3->key = uresp.sq_db_gts_key; - mm3->addr = qhp->wq.sq.udb; + mm3->addr = (__force unsigned long) qhp->wq.sq.udb; mm3->len = PAGE_SIZE; insert_mmap(ucontext, mm3); mm4->key = uresp.rq_db_gts_key; - mm4->addr = qhp->wq.rq.udb; + mm4->addr = (__force unsigned long) qhp->wq.rq.udb; mm4->len = PAGE_SIZE; insert_mmap(ucontext, mm4); if (mm5) { diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c index cdef4d7..67df71a 100644 --- a/drivers/infiniband/hw/cxgb4/resource.c +++ b/drivers/infiniband/hw/cxgb4/resource.c @@ -179,8 +179,12 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx) kfree(entry); } else { qid = c4iw_get_resource(&rdev->resource.qid_table); - if (!qid) + if (!qid) { + mutex_lock(&rdev->stats.lock); + rdev->stats.qid.fail++; + mutex_unlock(&rdev->stats.lock); goto out; + } mutex_lock(&rdev->stats.lock); rdev->stats.qid.cur += rdev->qpmask + 1; mutex_unlock(&rdev->stats.lock); @@ -322,8 +326,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size) unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6); PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6); if (!addr) - printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n", - pci_name(rdev->lldi.pdev)); + pr_warn_ratelimited(MOD "%s: Out of RQT memory\n", + pci_name(rdev->lldi.pdev)); mutex_lock(&rdev->stats.lock); if (addr) { rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT); diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index eeca8b1..2178f31 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -84,7 +84,14 @@ struct t4_status_page { sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge)) #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \ sizeof(struct fw_ri_immd)) & ~31UL) -#define T4_MAX_FR_DEPTH (1024 / sizeof(u64)) +#define T4_MAX_FR_IMMD_DEPTH (T4_MAX_FR_IMMD / sizeof(u64)) +#define T4_MAX_FR_DSGL 1024 +#define T4_MAX_FR_DSGL_DEPTH (T4_MAX_FR_DSGL / sizeof(u64)) + +static inline int t4_max_fr_depth(int use_dsgl) +{ + return use_dsgl ? T4_MAX_FR_DSGL_DEPTH : T4_MAX_FR_IMMD_DEPTH; +} #define T4_RQ_NUM_SLOTS 2 #define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS) @@ -292,7 +299,7 @@ struct t4_sq { unsigned long phys_addr; struct t4_swsqe *sw_sq; struct t4_swsqe *oldest_read; - u64 udb; + u64 __iomem *udb; size_t memsize; u32 qid; u16 in_use; @@ -314,7 +321,7 @@ struct t4_rq { dma_addr_t dma_addr; DEFINE_DMA_UNMAP_ADDR(mapping); struct t4_swrqe *sw_rq; - u64 udb; + u64 __iomem *udb; size_t memsize; u32 qid; u32 msn; @@ -435,15 +442,67 @@ static inline u16 t4_sq_wq_size(struct t4_wq *wq) return wq->sq.size * T4_SQ_NUM_SLOTS; } -static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc) +/* This function copies 64 byte coalesced work request to memory + * mapped BAR2 space. For coalesced WRs, the SGE fetches data + * from the FIFO instead of from Host. + */ +static inline void pio_copy(u64 __iomem *dst, u64 *src) +{ + int count = 8; + + while (count) { + writeq(*src, dst); + src++; + dst++; + count--; + } +} + +static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5, + union t4_wr *wqe) { + + /* Flush host queue memory writes. */ wmb(); + if (t5) { + if (inc == 1 && wqe) { + PDBG("%s: WC wq->sq.pidx = %d\n", + __func__, wq->sq.pidx); + pio_copy(wq->sq.udb + 7, (void *)wqe); + } else { + PDBG("%s: DB wq->sq.pidx = %d\n", + __func__, wq->sq.pidx); + writel(PIDX_T5(inc), wq->sq.udb); + } + + /* Flush user doorbell area writes. */ + wmb(); + return; + } writel(QID(wq->sq.qid) | PIDX(inc), wq->db); } -static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc) +static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5, + union t4_recv_wr *wqe) { + + /* Flush host queue memory writes. */ wmb(); + if (t5) { + if (inc == 1 && wqe) { + PDBG("%s: WC wq->rq.pidx = %d\n", + __func__, wq->rq.pidx); + pio_copy(wq->rq.udb + 7, (void *)wqe); + } else { + PDBG("%s: DB wq->rq.pidx = %d\n", + __func__, wq->rq.pidx); + writel(PIDX_T5(inc), wq->rq.udb); + } + + /* Flush user doorbell area writes. */ + wmb(); + return; + } writel(QID(wq->rq.qid) | PIDX(inc), wq->db); } @@ -568,6 +627,9 @@ static inline int t4_next_hw_cqe(struct t4_cq *cq, struct t4_cqe **cqe) printk(KERN_ERR MOD "cq overflow cqid %u\n", cq->cqid); BUG_ON(1); } else if (t4_valid_cqe(cq, &cq->queue[cq->cidx])) { + + /* Ensure CQE is flushed to memory */ + rmb(); *cqe = &cq->queue[cq->cidx]; ret = 0; } else diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index fa6dc87..364d4b6 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -282,6 +282,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, props->sig_guard_cap = IB_GUARD_T10DIF_CRC | IB_GUARD_T10DIF_CSUM; } + if (flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST) + props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; props->vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffffff; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index ae788d27..dc930ed 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -807,6 +807,15 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, spin_lock_init(&qp->sq.lock); spin_lock_init(&qp->rq.lock); + if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) { + if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) { + mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n"); + return -EINVAL; + } else { + qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK; + } + } + if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE; @@ -878,6 +887,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, if (qp->wq_sig) in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_ENABLE_SIG); + if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK) + in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_BLOCK_MCAST); + if (qp->scat_cqe && is_connected(init_attr->qp_type)) { int rcqe_sz; int scqe_sz; diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 87897b9..ded76c1 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -858,13 +858,9 @@ static int mthca_enable_msi_x(struct mthca_dev *mdev) entries[1].entry = 1; entries[2].entry = 2; - err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries)); - if (err) { - if (err > 0) - mthca_info(mdev, "Only %d MSI-X vectors available, " - "not using MSI-X\n", err); + err = pci_enable_msix_exact(mdev->pdev, entries, ARRAY_SIZE(entries)); + if (err) return err; - } mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector; mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector; diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index c8d9c4a..61a0046 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt, struct qib_msix_entry *qib_msix_entry) { int ret; - u32 tabsize = 0; - u16 msix_flags; + int nvec = *msixcnt; struct msix_entry *msix_entry; int i; + ret = pci_msix_vec_count(dd->pcidev); + if (ret < 0) + goto do_intx; + + nvec = min(nvec, ret); + /* We can't pass qib_msix_entry array to qib_msix_setup * so use a dummy msix_entry array and copy the allocated * irq back to the qib_msix_entry array. */ - msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL); - if (!msix_entry) { - ret = -ENOMEM; + msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL); + if (!msix_entry) goto do_intx; - } - for (i = 0; i < *msixcnt; i++) + + for (i = 0; i < nvec; i++) msix_entry[i] = qib_msix_entry[i].msix; - pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags); - tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE); - if (tabsize > *msixcnt) - tabsize = *msixcnt; - ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); - if (ret > 0) { - tabsize = ret; - ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); - } -do_intx: - if (ret) { - qib_dev_err(dd, - "pci_enable_msix %d vectors failed: %d, falling back to INTx\n", - tabsize, ret); - tabsize = 0; - } - for (i = 0; i < tabsize; i++) + ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); + if (ret < 0) + goto free_msix_entry; + else + nvec = ret; + + for (i = 0; i < nvec; i++) qib_msix_entry[i].msix = msix_entry[i]; + kfree(msix_entry); - *msixcnt = tabsize; + *msixcnt = nvec; + return; - if (ret) - qib_enable_intx(dd->pcidev); +free_msix_entry: + kfree(msix_entry); +do_intx: + qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, " + "falling back to INTx\n", nvec, ret); + *msixcnt = 0; + qib_enable_intx(dd->pcidev); } /** diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c index 4b11ede..4765799 100644 --- a/drivers/input/misc/da9055_onkey.c +++ b/drivers/input/misc/da9055_onkey.c @@ -109,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work); - irq = regmap_irq_get_virq(da9055->irq_data, irq); err = request_threaded_irq(irq, NULL, da9055_onkey_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ONKEY", onkey); diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 08ead2a..20c80f5 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -169,6 +169,7 @@ static int soc_button_pnp_probe(struct pnp_dev *pdev, soc_button_remove(pdev); return error; } + continue; } priv->children[i] = pd; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index ef1cf52..088d354 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1353,6 +1353,7 @@ static int elantech_set_properties(struct elantech_data *etd) case 6: case 7: case 8: + case 9: etd->hw_version = 4; break; default: diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d8d49d1..ef9f491 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -117,6 +117,44 @@ void synaptics_reset(struct psmouse *psmouse) } #ifdef CONFIG_MOUSE_PS2_SYNAPTICS +/* This list has been kindly provided by Synaptics. */ +static const char * const topbuttonpad_pnp_ids[] = { + "LEN0017", + "LEN0018", + "LEN0019", + "LEN0023", + "LEN002A", + "LEN002B", + "LEN002C", + "LEN002D", + "LEN002E", + "LEN0033", /* Helix */ + "LEN0034", /* T431s, T540, X1 Carbon 2nd */ + "LEN0035", /* X240 */ + "LEN0036", /* T440 */ + "LEN0037", + "LEN0038", + "LEN0041", + "LEN0042", /* Yoga */ + "LEN0045", + "LEN0046", + "LEN0047", + "LEN0048", + "LEN0049", + "LEN2000", + "LEN2001", + "LEN2002", + "LEN2003", + "LEN2004", /* L440 */ + "LEN2005", + "LEN2006", + "LEN2007", + "LEN2008", + "LEN2009", + "LEN200A", + "LEN200B", + NULL +}; /***************************************************************************** * Synaptics communications functions @@ -1255,8 +1293,10 @@ static void set_abs_position_params(struct input_dev *dev, input_abs_set_res(dev, y_code, priv->y_res); } -static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) +static void set_input_params(struct psmouse *psmouse, + struct synaptics_data *priv) { + struct input_dev *dev = psmouse->dev; int i; /* Things that apply to both modes */ @@ -1325,6 +1365,17 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); + /* See if this buttonpad has a top button area */ + if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) { + for (i = 0; topbuttonpad_pnp_ids[i]; i++) { + if (strstr(psmouse->ps2dev.serio->firmware_id, + topbuttonpad_pnp_ids[i])) { + __set_bit(INPUT_PROP_TOPBUTTONPAD, + dev->propbit); + break; + } + } + } /* Clickpads report only left button */ __clear_bit(BTN_RIGHT, dev->keybit); __clear_bit(BTN_MIDDLE, dev->keybit); @@ -1515,6 +1566,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { .driver_data = (int []){1232, 5710, 1156, 4696}, }, { + /* Lenovo ThinkPad T431s */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"), + }, + .driver_data = (int []){1024, 5112, 2024, 4832}, + }, + { /* Lenovo ThinkPad T440s */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -1523,6 +1582,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { .driver_data = (int []){1024, 5112, 2024, 4832}, }, { + /* Lenovo ThinkPad L440 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"), + }, + .driver_data = (int []){1024, 5112, 2024, 4832}, + }, + { /* Lenovo ThinkPad T540p */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -1530,6 +1597,32 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { }, .driver_data = (int []){1024, 5056, 2058, 4832}, }, + { + /* Lenovo ThinkPad L540 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"), + }, + .driver_data = (int []){1024, 5112, 2024, 4832}, + }, + { + /* Lenovo Yoga S1 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, + "ThinkPad S1 Yoga"), + }, + .driver_data = (int []){1232, 5710, 1156, 4696}, + }, + { + /* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, + "ThinkPad X1 Carbon 2nd"), + }, + .driver_data = (int []){1024, 5112, 2024, 4832}, + }, #endif { } }; @@ -1593,7 +1686,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) priv->capabilities, priv->ext_cap, priv->ext_cap_0c, priv->board_id, priv->firmware_id); - set_input_params(psmouse->dev, priv); + set_input_params(psmouse, priv); /* * Encode touchpad model so that it can be used to set diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 0ec9abb..381b20d 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -702,6 +702,17 @@ static int i8042_pnp_aux_irq; static char i8042_pnp_kbd_name[32]; static char i8042_pnp_aux_name[32]; +static void i8042_pnp_id_to_string(struct pnp_id *id, char *dst, int dst_size) +{ + strlcpy(dst, "PNP:", dst_size); + + while (id) { + strlcat(dst, " ", dst_size); + strlcat(dst, id->id, dst_size); + id = id->next; + } +} + static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did) { if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1) @@ -718,6 +729,8 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name)); strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); } + i8042_pnp_id_to_string(dev->id, i8042_kbd_firmware_id, + sizeof(i8042_kbd_firmware_id)); /* Keyboard ports are always supposed to be wakeup-enabled */ device_set_wakeup_enable(&dev->dev, true); @@ -742,6 +755,8 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name)); strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name)); } + i8042_pnp_id_to_string(dev->id, i8042_aux_firmware_id, + sizeof(i8042_aux_firmware_id)); i8042_pnp_aux_devices++; return 0; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 020053fa..3807c3e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -87,6 +87,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); #endif static bool i8042_bypass_aux_irq_test; +static char i8042_kbd_firmware_id[128]; +static char i8042_aux_firmware_id[128]; #include "i8042.h" @@ -1218,6 +1220,8 @@ static int __init i8042_create_kbd_port(void) serio->dev.parent = &i8042_platform_device->dev; strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); + strlcpy(serio->firmware_id, i8042_kbd_firmware_id, + sizeof(serio->firmware_id)); port->serio = serio; port->irq = I8042_KBD_IRQ; @@ -1244,6 +1248,8 @@ static int __init i8042_create_aux_port(int idx) if (idx < 0) { strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); + strlcpy(serio->firmware_id, i8042_aux_firmware_id, + sizeof(serio->firmware_id)); serio->close = i8042_port_close; } else { snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 8f4c4ab..b29134d 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -451,6 +451,13 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute * return retval; } +static ssize_t firmware_id_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct serio *serio = to_serio_port(dev); + + return sprintf(buf, "%s\n", serio->firmware_id); +} + static DEVICE_ATTR_RO(type); static DEVICE_ATTR_RO(proto); static DEVICE_ATTR_RO(id); @@ -473,12 +480,14 @@ static DEVICE_ATTR_RO(modalias); static DEVICE_ATTR_WO(drvctl); static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL); static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode); +static DEVICE_ATTR_RO(firmware_id); static struct attribute *serio_device_attrs[] = { &dev_attr_modalias.attr, &dev_attr_description.attr, &dev_attr_drvctl.attr, &dev_attr_bind_mode.attr, + &dev_attr_firmware_id.attr, NULL }; @@ -921,9 +930,14 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto); SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id); SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra); + SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); + if (serio->firmware_id[0]) + SERIO_ADD_UEVENT_VAR("SERIO_FIRMWARE_ID=%s", + serio->firmware_id); + return 0; } #undef SERIO_ADD_UEVENT_VAR diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index b16ebef..611fc39 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -22,23 +22,18 @@ #define HID_USAGE_PAGE_DIGITIZER 0x0d #define HID_USAGE_PAGE_DESKTOP 0x01 #define HID_USAGE 0x09 -#define HID_USAGE_X 0x30 -#define HID_USAGE_Y 0x31 -#define HID_USAGE_X_TILT 0x3d -#define HID_USAGE_Y_TILT 0x3e -#define HID_USAGE_FINGER 0x22 -#define HID_USAGE_STYLUS 0x20 -#define HID_USAGE_CONTACTMAX 0x55 +#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30) +#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31) +#define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30) +#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d) +#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e) +#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22) +#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20) +#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55) #define HID_COLLECTION 0xa1 #define HID_COLLECTION_LOGICAL 0x02 #define HID_COLLECTION_END 0xc0 -enum { - WCM_UNDEFINED = 0, - WCM_DESKTOP, - WCM_DIGITIZER, -}; - struct hid_descriptor { struct usb_descriptor_header header; __le16 bcdHID; @@ -305,7 +300,7 @@ static int wacom_parse_hid(struct usb_interface *intf, char limit = 0; /* result has to be defined as int for some devices */ int result = 0, touch_max = 0; - int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; + int i = 0, page = 0, finger = 0, pen = 0; unsigned char *report; report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); @@ -332,134 +327,121 @@ static int wacom_parse_hid(struct usb_interface *intf, switch (report[i]) { case HID_USAGE_PAGE: - switch (report[i + 1]) { - case HID_USAGE_PAGE_DIGITIZER: - usage = WCM_DIGITIZER; - i++; - break; - - case HID_USAGE_PAGE_DESKTOP: - usage = WCM_DESKTOP; - i++; - break; - } + page = report[i + 1]; + i++; break; case HID_USAGE: - switch (report[i + 1]) { + switch (page << 16 | report[i + 1]) { case HID_USAGE_X: - if (usage == WCM_DESKTOP) { - if (finger) { - features->device_type = BTN_TOOL_FINGER; - /* touch device at least supports one touch point */ - touch_max = 1; - switch (features->type) { - case TABLETPC2FG: - features->pktlen = WACOM_PKGLEN_TPC2FG; - break; - - case MTSCREEN: - case WACOM_24HDT: - features->pktlen = WACOM_PKGLEN_MTOUCH; - break; - - case MTTPC: - features->pktlen = WACOM_PKGLEN_MTTPC; - break; - - case BAMBOO_PT: - features->pktlen = WACOM_PKGLEN_BBTOUCH; - break; - - default: - features->pktlen = WACOM_PKGLEN_GRAPHIRE; - break; - } - - switch (features->type) { - case BAMBOO_PT: - features->x_phy = - get_unaligned_le16(&report[i + 5]); - features->x_max = - get_unaligned_le16(&report[i + 8]); - i += 15; - break; - - case WACOM_24HDT: - features->x_max = - get_unaligned_le16(&report[i + 3]); - features->x_phy = - get_unaligned_le16(&report[i + 8]); - features->unit = report[i - 1]; - features->unitExpo = report[i - 3]; - i += 12; - break; - - default: - features->x_max = - get_unaligned_le16(&report[i + 3]); - features->x_phy = - get_unaligned_le16(&report[i + 6]); - features->unit = report[i + 9]; - features->unitExpo = report[i + 11]; - i += 12; - break; - } - } else if (pen) { - /* penabled only accepts exact bytes of data */ - if (features->type >= TABLETPC) - features->pktlen = WACOM_PKGLEN_GRAPHIRE; - features->device_type = BTN_TOOL_PEN; + if (finger) { + features->device_type = BTN_TOOL_FINGER; + /* touch device at least supports one touch point */ + touch_max = 1; + switch (features->type) { + case TABLETPC2FG: + features->pktlen = WACOM_PKGLEN_TPC2FG; + break; + + case MTSCREEN: + case WACOM_24HDT: + features->pktlen = WACOM_PKGLEN_MTOUCH; + break; + + case MTTPC: + features->pktlen = WACOM_PKGLEN_MTTPC; + break; + + case BAMBOO_PT: + features->pktlen = WACOM_PKGLEN_BBTOUCH; + break; + + default: + features->pktlen = WACOM_PKGLEN_GRAPHIRE; + break; + } + + switch (features->type) { + case BAMBOO_PT: + features->x_phy = + get_unaligned_le16(&report[i + 5]); + features->x_max = + get_unaligned_le16(&report[i + 8]); + i += 15; + break; + + case WACOM_24HDT: features->x_max = get_unaligned_le16(&report[i + 3]); - i += 4; + features->x_phy = + get_unaligned_le16(&report[i + 8]); + features->unit = report[i - 1]; + features->unitExpo = report[i - 3]; + i += 12; + break; + + default: + features->x_max = + get_unaligned_le16(&report[i + 3]); + features->x_phy = + get_unaligned_le16(&report[i + 6]); + features->unit = report[i + 9]; + features->unitExpo = report[i + 11]; + i += 12; + break; } + } else if (pen) { + /* penabled only accepts exact bytes of data */ + if (features->type >= TABLETPC) + features->pktlen = WACOM_PKGLEN_GRAPHIRE; + features->device_type = BTN_TOOL_PEN; + features->x_max = + get_unaligned_le16(&report[i + 3]); + i += 4; } break; case HID_USAGE_Y: - if (usage == WCM_DESKTOP) { - if (finger) { - switch (features->type) { - case TABLETPC2FG: - case MTSCREEN: - case MTTPC: - features->y_max = - get_unaligned_le16(&report[i + 3]); - features->y_phy = - get_unaligned_le16(&report[i + 6]); - i += 7; - break; - - case WACOM_24HDT: - features->y_max = - get_unaligned_le16(&report[i + 3]); - features->y_phy = - get_unaligned_le16(&report[i - 2]); - i += 7; - break; - - case BAMBOO_PT: - features->y_phy = - get_unaligned_le16(&report[i + 3]); - features->y_max = - get_unaligned_le16(&report[i + 6]); - i += 12; - break; - - default: - features->y_max = - features->x_max; - features->y_phy = - get_unaligned_le16(&report[i + 3]); - i += 4; - break; - } - } else if (pen) { + if (finger) { + switch (features->type) { + case TABLETPC2FG: + case MTSCREEN: + case MTTPC: + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i + 6]); + i += 7; + break; + + case WACOM_24HDT: + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i - 2]); + i += 7; + break; + + case BAMBOO_PT: + features->y_phy = + get_unaligned_le16(&report[i + 3]); + features->y_max = + get_unaligned_le16(&report[i + 6]); + i += 12; + break; + + default: features->y_max = + features->x_max; + features->y_phy = get_unaligned_le16(&report[i + 3]); i += 4; + break; } + } else if (pen) { + features->y_max = + get_unaligned_le16(&report[i + 3]); + i += 4; } break; @@ -484,12 +466,20 @@ static int wacom_parse_hid(struct usb_interface *intf, wacom_retrieve_report_data(intf, features); i++; break; + + case HID_USAGE_PRESSURE: + if (pen) { + features->pressure_max = + get_unaligned_le16(&report[i + 3]); + i += 4; + } + break; } break; case HID_COLLECTION_END: /* reset UsagePage and Finger */ - finger = usage = 0; + finger = page = 0; break; case HID_COLLECTION: diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 05f371d..4822c57 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) static int wacom_dtu_irq(struct wacom_wac *wacom) { - struct wacom_features *features = &wacom->features; - char *data = wacom->data; + unsigned char *data = wacom->data; struct input_dev *input = wacom->input; - int prox = data[1] & 0x20, pressure; + int prox = data[1] & 0x20; dev_dbg(input->dev.parent, "%s: received report #%d", __func__, data[0]); @@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) input_report_key(input, BTN_STYLUS2, data[1] & 0x10); input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - input_report_abs(input, ABS_PRESSURE, pressure); + input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]); input_report_key(input, BTN_TOUCH, data[1] & 0x05); if (!prox) /* out-prox */ wacom->id[0] = 0; @@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2) static int wacom_24hdt_irq(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; - char *data = wacom->data; + unsigned char *data = wacom->data; int i; int current_num_contacts = data[61]; int contacts_to_send = 0; @@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) static int wacom_mt_touch(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; - char *data = wacom->data; + unsigned char *data = wacom->data; int i; int current_num_contacts = data[2]; int contacts_to_send = 0; @@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom) static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) { - char *data = wacom->data; + unsigned char *data = wacom->data; struct input_dev *input = wacom->input; bool prox; int x = 0, y = 0; @@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) static int wacom_tpc_pen(struct wacom_wac *wacom) { - struct wacom_features *features = &wacom->features; - char *data = wacom->data; + unsigned char *data = wacom->data; struct input_dev *input = wacom->input; - int pressure; bool prox = data[1] & 0x20; if (!wacom->shared->stylus_in_proximity) /* first in prox */ @@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom) input_report_key(input, BTN_STYLUS2, data[1] & 0x10); input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - input_report_abs(input, ABS_PRESSURE, pressure); + input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]); input_report_key(input, BTN_TOUCH, data[1] & 0x05); input_report_key(input, wacom->tool[0], prox); return 1; @@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom) static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) { - char *data = wacom->data; + unsigned char *data = wacom->data; dev_dbg(wacom->input->dev.parent, "%s: received report #%d\n", __func__, data[0]); @@ -1838,7 +1829,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case DTU: if (features->type == DTUS) { input_set_capability(input_dev, EV_MSC, MSC_SERIAL); - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) __set_bit(BTN_0 + i, input_dev->keybit); } __set_bit(BTN_TOOL_PEN, input_dev->keybit); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 45a06e4..7f8aa98 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -425,7 +425,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command) name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct ads7846 *ts = dev_get_drvdata(dev); \ - ssize_t v = ads7846_read12_ser(dev, \ + ssize_t v = ads7846_read12_ser(&ts->spi->dev, \ READ_12BIT_SER(var)); \ if (v < 0) \ return v; \ diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 8b89e33..647c3c7 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1381,7 +1381,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, do { next = pmd_addr_end(addr, end); - ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, + ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, next, pfn, prot, stage); phys += next - addr; } while (pmd++, addr = next, addr < end); @@ -1499,7 +1499,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0); arm_smmu_tlb_inv_context(&smmu_domain->root_cfg); - return ret ? ret : size; + return ret ? 0 : size; } static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index f445c10..39f8b71 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -152,7 +152,8 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) info->seg = pci_domain_nr(dev->bus); info->level = level; if (event == BUS_NOTIFY_ADD_DEVICE) { - for (tmp = dev, level--; tmp; tmp = tmp->bus->self) { + for (tmp = dev; tmp; tmp = tmp->bus->self) { + level--; info->path[level].device = PCI_SLOT(tmp->devfn); info->path[level].function = PCI_FUNC(tmp->devfn); if (pci_is_root_bus(tmp->bus)) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 69fa7da..f256ffc 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1009,11 +1009,13 @@ static struct page *dma_pte_list_pagetables(struct dmar_domain *domain, if (level == 1) return freelist; - for (pte = page_address(pg); !first_pte_in_page(pte); pte++) { + pte = page_address(pg); + do { if (dma_pte_present(pte) && !dma_pte_superpage(pte)) freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist); - } + pte++; + } while (!first_pte_in_page(pte)); return freelist; } @@ -2235,7 +2237,9 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw) bridge_devfn = dev_tmp->devfn; } spin_lock_irqsave(&device_domain_lock, flags); - info = dmar_search_domain_by_dev_info(segment, bus, devfn); + info = dmar_search_domain_by_dev_info(segment, + bridge_bus, + bridge_devfn); if (info) { iommu = info->iommu; domain = info->domain; diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index 8527743..3fdda3a 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c @@ -5,7 +5,7 @@ * Viresh Kumar <viresh.linux@gmail.com> * * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim <shiraz.hashim@st.com> + * Shiraz Hashim <shiraz.linux.kernel@gmail.com> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 53d487f..6a7447c 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1155,7 +1155,7 @@ icn_command(isdn_ctrl *c, icn_card *card) ulong a; ulong flags; int i; - char cbuf[60]; + char cbuf[80]; isdn_ctrl cmd; icn_cdef cdef; char __user *arg; @@ -1309,7 +1309,6 @@ icn_command(isdn_ctrl *c, icn_card *card) break; if ((c->arg & 255) < ICN_BCH) { char *p; - char dial[50]; char dcode[4]; a = c->arg; @@ -1321,10 +1320,10 @@ icn_command(isdn_ctrl *c, icn_card *card) } else /* Normal Dial */ strcpy(dcode, "CAL"); - strcpy(dial, p); - sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), - dcode, dial, c->parm.setup.si1, - c->parm.setup.si2, c->parm.setup.eazmsn); + snprintf(cbuf, sizeof(cbuf), + "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), + dcode, p, c->parm.setup.si1, + c->parm.setup.si2, c->parm.setup.eazmsn); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c index d1278b5..0049269 100644 --- a/drivers/mcb/mcb-parse.c +++ b/drivers/mcb/mcb-parse.c @@ -141,6 +141,7 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, default: pr_err("Invalid chameleon descriptor type 0x%x\n", dtype); + kfree(header); return -EINVAL; } num_cells++; diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index c137abf..20f1655 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -56,7 +56,7 @@ config VIDEO_VIU config VIDEO_TIMBERDALE tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && DMADEVICES + depends on MFD_TIMBERDALE && VIDEO_V4L2 && I2C && DMADEVICES select DMA_ENGINE select TIMB_DMA select VIDEO_ADV7180 diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1cb7408..8baff0e 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -300,8 +300,8 @@ config SGI_GRU_DEBUG depends on SGI_GRU default n ---help--- - This option enables addition debugging code for the SGI GRU driver. If - you are unsure, say N. + This option enables additional debugging code for the SGI GRU driver. + If you are unsure, say N. config APDS9802ALS tristate "Medfield Avago APDS9802 ALS Sensor module" diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h index 5e4dbd2..0e608a2 100644 --- a/drivers/misc/genwqe/card_base.h +++ b/drivers/misc/genwqe/card_base.h @@ -337,6 +337,44 @@ enum genwqe_requ_state { }; /** + * struct genwqe_sgl - Scatter gather list describing user-space memory + * @sgl: scatter gather list needs to be 128 byte aligned + * @sgl_dma_addr: dma address of sgl + * @sgl_size: size of area used for sgl + * @user_addr: user-space address of memory area + * @user_size: size of user-space memory area + * @page: buffer for partial pages if needed + * @page_dma_addr: dma address partial pages + */ +struct genwqe_sgl { + dma_addr_t sgl_dma_addr; + struct sg_entry *sgl; + size_t sgl_size; /* size of sgl */ + + void __user *user_addr; /* user-space base-address */ + size_t user_size; /* size of memory area */ + + unsigned long nr_pages; + unsigned long fpage_offs; + size_t fpage_size; + size_t lpage_size; + + void *fpage; + dma_addr_t fpage_dma_addr; + + void *lpage; + dma_addr_t lpage_dma_addr; +}; + +int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + void __user *user_addr, size_t user_size); + +int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + dma_addr_t *dma_list); + +int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl); + +/** * struct ddcb_requ - Kernel internal representation of the DDCB request * @cmd: User space representation of the DDCB execution request */ @@ -347,9 +385,7 @@ struct ddcb_requ { struct ddcb_queue *queue; /* associated queue */ struct dma_mapping dma_mappings[DDCB_FIXUPS]; - struct sg_entry *sgl[DDCB_FIXUPS]; - dma_addr_t sgl_dma_addr[DDCB_FIXUPS]; - size_t sgl_size[DDCB_FIXUPS]; + struct genwqe_sgl sgls[DDCB_FIXUPS]; /* kernel/user shared content */ struct genwqe_ddcb_cmd cmd; /* ddcb_no for this request */ @@ -453,22 +489,6 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, int genwqe_user_vunmap(struct genwqe_dev *cd, struct dma_mapping *m, struct ddcb_requ *req); -struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages, - dma_addr_t *dma_addr, size_t *sgl_size); - -void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list, - dma_addr_t dma_addr, size_t size); - -int genwqe_setup_sgl(struct genwqe_dev *cd, - unsigned long offs, - unsigned long size, - struct sg_entry *sgl, /* genwqe sgl */ - dma_addr_t dma_addr, size_t sgl_size, - dma_addr_t *dma_list, int page_offs, int num_pages); - -int genwqe_check_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list, - int size); - static inline bool dma_mapping_used(struct dma_mapping *m) { if (!m) diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c index 6f1acc0..c8046db 100644 --- a/drivers/misc/genwqe/card_ddcb.c +++ b/drivers/misc/genwqe/card_ddcb.c @@ -305,6 +305,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue, break; new = (old | DDCB_NEXT_BE32); + + wmb(); icrc_hsi_shi = cmpxchg(&prev_ddcb->icrc_hsi_shi_32, old, new); if (icrc_hsi_shi == old) @@ -314,6 +316,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue, /* Queue must be re-started by updating QUEUE_OFFSET */ ddcb_mark_tapped(pddcb); num = (u64)ddcb_no << 8; + + wmb(); __genwqe_writeq(cd, queue->IO_QUEUE_OFFSET, num); /* start queue */ return RET_DDCB_TAPPED; @@ -1306,7 +1310,7 @@ static int queue_wake_up_all(struct genwqe_dev *cd) */ int genwqe_finish_queue(struct genwqe_dev *cd) { - int i, rc, in_flight; + int i, rc = 0, in_flight; int waitmax = genwqe_ddcb_software_timeout; struct pci_dev *pci_dev = cd->pci_dev; struct ddcb_queue *queue = &cd->queue; diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 2c2c9cc..1d2f163 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -531,7 +531,9 @@ static int do_flash_update(struct genwqe_file *cfile, case '1': cmdopts = 0x1C; break; /* download/erase_first/part_1 */ - case 'v': /* cmdopts = 0x0c (VPD) */ + case 'v': + cmdopts = 0x0C; + break; /* download/erase_first/vpd */ default: return -EINVAL; } @@ -665,6 +667,8 @@ static int do_flash_read(struct genwqe_file *cfile, cmdopts = 0x1A; break; /* upload/part_1 */ case 'v': + cmdopts = 0x0A; + break; /* upload/vpd */ default: return -EINVAL; } @@ -836,15 +840,8 @@ static int ddcb_cmd_cleanup(struct genwqe_file *cfile, struct ddcb_requ *req) __genwqe_del_mapping(cfile, dma_map); genwqe_user_vunmap(cd, dma_map, req); } - if (req->sgl[i] != NULL) { - genwqe_free_sgl(cd, req->sgl[i], - req->sgl_dma_addr[i], - req->sgl_size[i]); - req->sgl[i] = NULL; - req->sgl_dma_addr[i] = 0x0; - req->sgl_size[i] = 0; - } - + if (req->sgls[i].sgl != NULL) + genwqe_free_sync_sgl(cd, &req->sgls[i]); } return 0; } @@ -913,7 +910,7 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req) case ATS_TYPE_SGL_RDWR: case ATS_TYPE_SGL_RD: { - int page_offs, nr_pages, offs; + int page_offs; u_addr = be64_to_cpu(*((__be64 *) &cmd->asiv[asiv_offs])); @@ -951,27 +948,18 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req) page_offs = 0; } - offs = offset_in_page(u_addr); - nr_pages = DIV_ROUND_UP(offs + u_size, PAGE_SIZE); - /* create genwqe style scatter gather list */ - req->sgl[i] = genwqe_alloc_sgl(cd, m->nr_pages, - &req->sgl_dma_addr[i], - &req->sgl_size[i]); - if (req->sgl[i] == NULL) { - rc = -ENOMEM; + rc = genwqe_alloc_sync_sgl(cd, &req->sgls[i], + (void __user *)u_addr, + u_size); + if (rc != 0) goto err_out; - } - genwqe_setup_sgl(cd, offs, u_size, - req->sgl[i], - req->sgl_dma_addr[i], - req->sgl_size[i], - m->dma_list, - page_offs, - nr_pages); + + genwqe_setup_sgl(cd, &req->sgls[i], + &m->dma_list[page_offs]); *((__be64 *)&cmd->asiv[asiv_offs]) = - cpu_to_be64(req->sgl_dma_addr[i]); + cpu_to_be64(req->sgls[i].sgl_dma_addr); break; } diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 6b1a6ef..d049d27 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -275,67 +275,107 @@ static int genwqe_sgl_size(int num_pages) return roundup(len, PAGE_SIZE); } -struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages, - dma_addr_t *dma_addr, size_t *sgl_size) +/** + * genwqe_alloc_sync_sgl() - Allocate memory for sgl and overlapping pages + * + * Allocates memory for sgl and overlapping pages. Pages which might + * overlap other user-space memory blocks are being cached for DMAs, + * such that we do not run into syncronization issues. Data is copied + * from user-space into the cached pages. + */ +int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + void __user *user_addr, size_t user_size) { + int rc; struct pci_dev *pci_dev = cd->pci_dev; - struct sg_entry *sgl; - *sgl_size = genwqe_sgl_size(num_pages); - if (get_order(*sgl_size) > MAX_ORDER) { + sgl->fpage_offs = offset_in_page((unsigned long)user_addr); + sgl->fpage_size = min_t(size_t, PAGE_SIZE-sgl->fpage_offs, user_size); + sgl->nr_pages = DIV_ROUND_UP(sgl->fpage_offs + user_size, PAGE_SIZE); + sgl->lpage_size = (user_size - sgl->fpage_size) % PAGE_SIZE; + + dev_dbg(&pci_dev->dev, "[%s] uaddr=%p usize=%8ld nr_pages=%ld " + "fpage_offs=%lx fpage_size=%ld lpage_size=%ld\n", + __func__, user_addr, user_size, sgl->nr_pages, + sgl->fpage_offs, sgl->fpage_size, sgl->lpage_size); + + sgl->user_addr = user_addr; + sgl->user_size = user_size; + sgl->sgl_size = genwqe_sgl_size(sgl->nr_pages); + + if (get_order(sgl->sgl_size) > MAX_ORDER) { dev_err(&pci_dev->dev, "[%s] err: too much memory requested!\n", __func__); - return NULL; + return -ENOMEM; } - sgl = __genwqe_alloc_consistent(cd, *sgl_size, dma_addr); - if (sgl == NULL) { + sgl->sgl = __genwqe_alloc_consistent(cd, sgl->sgl_size, + &sgl->sgl_dma_addr); + if (sgl->sgl == NULL) { dev_err(&pci_dev->dev, "[%s] err: no memory available!\n", __func__); - return NULL; + return -ENOMEM; } - return sgl; + /* Only use buffering on incomplete pages */ + if ((sgl->fpage_size != 0) && (sgl->fpage_size != PAGE_SIZE)) { + sgl->fpage = __genwqe_alloc_consistent(cd, PAGE_SIZE, + &sgl->fpage_dma_addr); + if (sgl->fpage == NULL) + goto err_out; + + /* Sync with user memory */ + if (copy_from_user(sgl->fpage + sgl->fpage_offs, + user_addr, sgl->fpage_size)) { + rc = -EFAULT; + goto err_out; + } + } + if (sgl->lpage_size != 0) { + sgl->lpage = __genwqe_alloc_consistent(cd, PAGE_SIZE, + &sgl->lpage_dma_addr); + if (sgl->lpage == NULL) + goto err_out1; + + /* Sync with user memory */ + if (copy_from_user(sgl->lpage, user_addr + user_size - + sgl->lpage_size, sgl->lpage_size)) { + rc = -EFAULT; + goto err_out1; + } + } + return 0; + + err_out1: + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, + sgl->fpage_dma_addr); + err_out: + __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl, + sgl->sgl_dma_addr); + return -ENOMEM; } -int genwqe_setup_sgl(struct genwqe_dev *cd, - unsigned long offs, - unsigned long size, - struct sg_entry *sgl, - dma_addr_t dma_addr, size_t sgl_size, - dma_addr_t *dma_list, int page_offs, int num_pages) +int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + dma_addr_t *dma_list) { int i = 0, j = 0, p; unsigned long dma_offs, map_offs; - struct pci_dev *pci_dev = cd->pci_dev; dma_addr_t prev_daddr = 0; struct sg_entry *s, *last_s = NULL; - - /* sanity checks */ - if (offs > PAGE_SIZE) { - dev_err(&pci_dev->dev, - "[%s] too large start offs %08lx\n", __func__, offs); - return -EFAULT; - } - if (sgl_size < genwqe_sgl_size(num_pages)) { - dev_err(&pci_dev->dev, - "[%s] sgl_size too small %08lx for %d pages\n", - __func__, sgl_size, num_pages); - return -EFAULT; - } + size_t size = sgl->user_size; dma_offs = 128; /* next block if needed/dma_offset */ - map_offs = offs; /* offset in first page */ + map_offs = sgl->fpage_offs; /* offset in first page */ - s = &sgl[0]; /* first set of 8 entries */ + s = &sgl->sgl[0]; /* first set of 8 entries */ p = 0; /* page */ - while (p < num_pages) { + while (p < sgl->nr_pages) { dma_addr_t daddr; unsigned int size_to_map; /* always write the chaining entry, cleanup is done later */ j = 0; - s[j].target_addr = cpu_to_be64(dma_addr + dma_offs); + s[j].target_addr = cpu_to_be64(sgl->sgl_dma_addr + dma_offs); s[j].len = cpu_to_be32(128); s[j].flags = cpu_to_be32(SG_CHAINED); j++; @@ -343,7 +383,17 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, while (j < 8) { /* DMA mapping for requested page, offs, size */ size_to_map = min(size, PAGE_SIZE - map_offs); - daddr = dma_list[page_offs + p] + map_offs; + + if ((p == 0) && (sgl->fpage != NULL)) { + daddr = sgl->fpage_dma_addr + map_offs; + + } else if ((p == sgl->nr_pages - 1) && + (sgl->lpage != NULL)) { + daddr = sgl->lpage_dma_addr; + } else { + daddr = dma_list[p] + map_offs; + } + size -= size_to_map; map_offs = 0; @@ -358,7 +408,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, size_to_map); p++; /* process next page */ - if (p == num_pages) + if (p == sgl->nr_pages) goto fixup; /* nothing to do */ prev_daddr = daddr + size_to_map; @@ -374,7 +424,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, j++; p++; /* process next page */ - if (p == num_pages) + if (p == sgl->nr_pages) goto fixup; /* nothing to do */ } dma_offs += 128; @@ -395,10 +445,50 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, return 0; } -void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list, - dma_addr_t dma_addr, size_t size) +/** + * genwqe_free_sync_sgl() - Free memory for sgl and overlapping pages + * + * After the DMA transfer has been completed we free the memory for + * the sgl and the cached pages. Data is being transfered from cached + * pages into user-space buffers. + */ +int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl) { - __genwqe_free_consistent(cd, size, sg_list, dma_addr); + int rc; + struct pci_dev *pci_dev = cd->pci_dev; + + if (sgl->fpage) { + if (copy_to_user(sgl->user_addr, sgl->fpage + sgl->fpage_offs, + sgl->fpage_size)) { + dev_err(&pci_dev->dev, "[%s] err: copying fpage!\n", + __func__); + rc = -EFAULT; + } + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, + sgl->fpage_dma_addr); + sgl->fpage = NULL; + sgl->fpage_dma_addr = 0; + } + if (sgl->lpage) { + if (copy_to_user(sgl->user_addr + sgl->user_size - + sgl->lpage_size, sgl->lpage, + sgl->lpage_size)) { + dev_err(&pci_dev->dev, "[%s] err: copying lpage!\n", + __func__); + rc = -EFAULT; + } + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage, + sgl->lpage_dma_addr); + sgl->lpage = NULL; + sgl->lpage_dma_addr = 0; + } + __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl, + sgl->sgl_dma_addr); + + sgl->sgl = NULL; + sgl->sgl_dma_addr = 0x0; + sgl->sgl_size = 0; + return rc; } /** diff --git a/drivers/misc/genwqe/genwqe_driver.h b/drivers/misc/genwqe/genwqe_driver.h index 46e916b..cd52631 100644 --- a/drivers/misc/genwqe/genwqe_driver.h +++ b/drivers/misc/genwqe/genwqe_driver.h @@ -36,7 +36,7 @@ #include <asm/byteorder.h> #include <linux/genwqe/genwqe_card.h> -#define DRV_VERS_STRING "2.0.0" +#define DRV_VERS_STRING "2.0.15" /* * Static minor number assignement, until we decide/implement diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index 66f411a..cabc043 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -115,6 +115,11 @@ #define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ #define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ + +/* Host Firmware Status Registers in PCI Config Space */ +#define PCI_CFG_HFS_1 0x40 +#define PCI_CFG_HFS_2 0x48 + /* * MEI HW Section */ diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 29b5af8..4e3cba6d 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -455,8 +455,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) cl->status = 0; list_del(&cb->list); - if (MEI_WRITING == cl->writing_state && - cb->fop_type == MEI_FOP_WRITE && + if (cb->fop_type == MEI_FOP_WRITE && cl != &dev->iamthif_cl) { cl_dbg(dev, cl, "MEI WRITE COMPLETE\n"); cl->writing_state = MEI_WRITE_COMPLETE; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index b35594d..1474131 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -644,8 +644,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) goto out; } - if (MEI_WRITE_COMPLETE == cl->writing_state) - mask |= (POLLIN | POLLRDNORM); + mask |= (POLLIN | POLLRDNORM); out: mutex_unlock(&dev->device_lock); diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 1c8fd3a..95889e2 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -97,15 +97,31 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { u32 reg; - if (ent->device == MEI_DEV_ID_PBG_1) { - pci_read_config_dword(pdev, 0x48, ®); - /* make sure that bit 9 is up and bit 10 is down */ - if ((reg & 0x600) == 0x200) { - dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); - return false; - } + /* Cougar Point || Patsburg */ + if (ent->device == MEI_DEV_ID_CPT_1 || + ent->device == MEI_DEV_ID_PBG_1) { + pci_read_config_dword(pdev, PCI_CFG_HFS_2, ®); + /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */ + if ((reg & 0x600) == 0x200) + goto no_mei; } + + /* Lynx Point */ + if (ent->device == MEI_DEV_ID_LPT_H || + ent->device == MEI_DEV_ID_LPT_W || + ent->device == MEI_DEV_ID_LPT_HR) { + /* Read ME FW Status check for SPS Firmware */ + pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + /* if bits [19:16] = 15, running SPS Firmware */ + if ((reg & 0xf0000) == 0xf0000) + goto no_mei; + } + return true; + +no_mei: + dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); + return false; } /** * mei_probe - Device Initialization Routine diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 363da96..c4176b0 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c @@ -6,7 +6,7 @@ * * Copyright © 2010 STMicroelectronics. * Ashish Priyadarshi - * Shiraz Hashim <shiraz.hashim@st.com> + * Shiraz Hashim <shiraz.linux.kernel@gmail.com> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -1089,5 +1089,5 @@ static struct platform_driver spear_smi_driver = { module_platform_driver(spear_smi_driver); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>"); +MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.linux.kernel@gmail.com>"); MODULE_DESCRIPTION("MTD SMI driver for serial nor flash chips"); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index b9f7022..e5d95c5 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12286,7 +12286,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e if (tg3_flag(tp, MAX_RXPEND_64) && tp->rx_pending > 63) tp->rx_pending = 63; - tp->rx_jumbo_pending = ering->rx_jumbo_pending; + + if (tg3_flag(tp, JUMBO_RING_ENABLE)) + tp->rx_jumbo_pending = ering->rx_jumbo_pending; for (i = 0; i < tp->irq_max; i++) tp->napi[i].tx_pending = ering->tx_pending; diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index b248bcb..14786c8 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -89,8 +89,9 @@ #define MVNETA_TX_IN_PRGRS BIT(1) #define MVNETA_TX_FIFO_EMPTY BIT(8) #define MVNETA_RX_MIN_FRAME_SIZE 0x247c -#define MVNETA_SGMII_SERDES_CFG 0x24A0 +#define MVNETA_SERDES_CFG 0x24A0 #define MVNETA_SGMII_SERDES_PROTO 0x0cc7 +#define MVNETA_QSGMII_SERDES_PROTO 0x0667 #define MVNETA_TYPE_PRIO 0x24bc #define MVNETA_FORCE_UNI BIT(21) #define MVNETA_TXQ_CMD_1 0x24e4 @@ -711,35 +712,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp, mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); } - - -/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */ -static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable) -{ - u32 val; - - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - - if (enable) - val |= MVNETA_GMAC2_PORT_RGMII; - else - val &= ~MVNETA_GMAC2_PORT_RGMII; - - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); -} - -/* Config SGMII port */ -static void mvneta_port_sgmii_config(struct mvneta_port *pp) -{ - u32 val; - - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - val |= MVNETA_GMAC2_PCS_ENABLE; - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); - - mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); -} - /* Start the Ethernet port RX and TX activity */ static void mvneta_port_up(struct mvneta_port *pp) { @@ -2749,26 +2721,44 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp, } /* Power up the port */ -static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) +static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) { - u32 val; + u32 ctrl; /* MAC Cause register should be cleared */ mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); - if (phy_mode == PHY_INTERFACE_MODE_SGMII) - mvneta_port_sgmii_config(pp); + ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - mvneta_gmac_rgmii_set(pp, 1); + /* Even though it might look weird, when we're configured in + * SGMII or QSGMII mode, the RGMII bit needs to be set. + */ + switch(phy_mode) { + case PHY_INTERFACE_MODE_QSGMII: + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO); + ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; + break; + case PHY_INTERFACE_MODE_SGMII: + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); + ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + ctrl |= MVNETA_GMAC2_PORT_RGMII; + break; + default: + return -EINVAL; + } /* Cancel Port Reset */ - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - val &= ~MVNETA_GMAC2_PORT_RESET; - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); + ctrl &= ~MVNETA_GMAC2_PORT_RESET; + mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl); while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & MVNETA_GMAC2_PORT_RESET) != 0) continue; + + return 0; } /* Device initialization routine */ @@ -2879,7 +2869,12 @@ static int mvneta_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't init eth hal\n"); goto err_free_stats; } - mvneta_port_power_up(pp, phy_mode); + + err = mvneta_port_power_up(pp, phy_mode); + if (err < 0) { + dev_err(&pdev->dev, "can't power up port\n"); + goto err_deinit; + } dram_target_info = mv_mbus_dram_info(); if (dram_target_info) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index 70e9532..c2cd8d3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c @@ -66,7 +66,6 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, cq->ring = ring; cq->is_tx = mode; - spin_lock_init(&cq->lock); /* Allocate HW buffers on provided NUMA node. * dev->numa_node is used in mtt range allocation flow. diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index f085c2d..7e4b172 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1304,15 +1304,11 @@ static void mlx4_en_netpoll(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_cq *cq; - unsigned long flags; int i; for (i = 0; i < priv->rx_ring_num; i++) { cq = priv->rx_cq[i]; - spin_lock_irqsave(&cq->lock, flags); - napi_synchronize(&cq->napi); - mlx4_en_process_rx_cq(dev, cq, 0); - spin_unlock_irqrestore(&cq->lock, flags); + napi_schedule(&cq->napi); } } #endif diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 7a733c2..04d9b6fe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -319,7 +319,6 @@ struct mlx4_en_cq { struct mlx4_cq mcq; struct mlx4_hwq_resources wqres; int ring; - spinlock_t lock; struct net_device *dev; struct napi_struct napi; int size; diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 21c20ea0..b5ed30a 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -738,8 +738,11 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type) /* If it was a port reset, trigger reallocation of MC resources. * Note that on an MC reset nothing needs to be done now because we'll * detect the MC reset later and handle it then. + * For an FLR, we never get an MC reset event, but the MC has reset all + * resources assigned to us, so we have to trigger reallocation now. */ - if (reset_type == RESET_TYPE_ALL && !rc) + if ((reset_type == RESET_TYPE_ALL || + reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc) efx_ef10_reset_mc_allocations(efx); return rc; } @@ -2141,6 +2144,11 @@ static int efx_ef10_fini_dmaq(struct efx_nic *efx) return 0; } +static void efx_ef10_prepare_flr(struct efx_nic *efx) +{ + atomic_set(&efx->active_queues, 0); +} + static bool efx_ef10_filter_equal(const struct efx_filter_spec *left, const struct efx_filter_spec *right) { @@ -3603,6 +3611,8 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .probe_port = efx_mcdi_port_probe, .remove_port = efx_mcdi_port_remove, .fini_dmaq = efx_ef10_fini_dmaq, + .prepare_flr = efx_ef10_prepare_flr, + .finish_flr = efx_port_dummy_op_void, .describe_stats = efx_ef10_describe_stats, .update_stats = efx_ef10_update_stats, .start_stats = efx_mcdi_mac_start_stats, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 57b971e..63d595f 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -76,6 +76,7 @@ const char *const efx_reset_type_names[] = { [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL", [RESET_TYPE_WORLD] = "WORLD", [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE", + [RESET_TYPE_MC_BIST] = "MC_BIST", [RESET_TYPE_DISABLE] = "DISABLE", [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG", [RESET_TYPE_INT_ERROR] = "INT_ERROR", @@ -83,7 +84,7 @@ const char *const efx_reset_type_names[] = { [RESET_TYPE_DMA_ERROR] = "DMA_ERROR", [RESET_TYPE_TX_SKIP] = "TX_SKIP", [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", - [RESET_TYPE_MC_BIST] = "MC_BIST", + [RESET_TYPE_MCDI_TIMEOUT] = "MCDI_TIMEOUT (FLR)", }; /* Reset workqueue. If any NIC has a hardware failure then a reset will be @@ -1739,7 +1740,8 @@ static void efx_start_all(struct efx_nic *efx) /* Check that it is appropriate to restart the interface. All * of these flags are safe to read under just the rtnl lock */ - if (efx->port_enabled || !netif_running(efx->net_dev)) + if (efx->port_enabled || !netif_running(efx->net_dev) || + efx->reset_pending) return; efx_start_port(efx); @@ -2334,6 +2336,9 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method) { EFX_ASSERT_RESET_SERIALISED(efx); + if (method == RESET_TYPE_MCDI_TIMEOUT) + efx->type->prepare_flr(efx); + efx_stop_all(efx); efx_disable_interrupts(efx); @@ -2354,6 +2359,10 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) EFX_ASSERT_RESET_SERIALISED(efx); + if (method == RESET_TYPE_MCDI_TIMEOUT) + efx->type->finish_flr(efx); + + /* Ensure that SRAM is initialised even if we're disabling the device */ rc = efx->type->init(efx); if (rc) { netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n"); @@ -2417,7 +2426,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) /* Clear flags for the scopes we covered. We assume the NIC and * driver are now quiescent so that there is no race here. */ - efx->reset_pending &= -(1 << (method + 1)); + if (method < RESET_TYPE_MAX_METHOD) + efx->reset_pending &= -(1 << (method + 1)); + else /* it doesn't fit into the well-ordered scope hierarchy */ + __clear_bit(method, &efx->reset_pending); /* Reinitialise bus-mastering, which may have been turned off before * the reset was scheduled. This is still appropriate, even in the @@ -2546,6 +2558,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) case RESET_TYPE_DISABLE: case RESET_TYPE_RECOVER_OR_DISABLE: case RESET_TYPE_MC_BIST: + case RESET_TYPE_MCDI_TIMEOUT: method = type; netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", RESET_TYPE(method)); diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h index 75ef7ef..d1dbb5f 100644 --- a/drivers/net/ethernet/sfc/enum.h +++ b/drivers/net/ethernet/sfc/enum.h @@ -143,6 +143,7 @@ enum efx_loopback_mode { * @RESET_TYPE_WORLD: Reset as much as possible * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if * unsuccessful. + * @RESET_TYPE_MC_BIST: MC entering BIST mode. * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog * @RESET_TYPE_INT_ERROR: reset due to internal error @@ -150,14 +151,16 @@ enum efx_loopback_mode { * @RESET_TYPE_DMA_ERROR: DMA error * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors * @RESET_TYPE_MC_FAILURE: MC reboot/assertion + * @RESET_TYPE_MCDI_TIMEOUT: MCDI timeout. */ enum reset_type { - RESET_TYPE_INVISIBLE = 0, - RESET_TYPE_RECOVER_OR_ALL = 1, - RESET_TYPE_ALL = 2, - RESET_TYPE_WORLD = 3, - RESET_TYPE_RECOVER_OR_DISABLE = 4, - RESET_TYPE_DISABLE = 5, + RESET_TYPE_INVISIBLE, + RESET_TYPE_RECOVER_OR_ALL, + RESET_TYPE_ALL, + RESET_TYPE_WORLD, + RESET_TYPE_RECOVER_OR_DISABLE, + RESET_TYPE_MC_BIST, + RESET_TYPE_DISABLE, RESET_TYPE_MAX_METHOD, RESET_TYPE_TX_WATCHDOG, RESET_TYPE_INT_ERROR, @@ -165,7 +168,13 @@ enum reset_type { RESET_TYPE_DMA_ERROR, RESET_TYPE_TX_SKIP, RESET_TYPE_MC_FAILURE, - RESET_TYPE_MC_BIST, + /* RESET_TYPE_MCDI_TIMEOUT is actually a method, not just a reason, but + * it doesn't fit the scope hierarchy (not well-ordered by inclusion). + * We encode this by having its enum value be greater than + * RESET_TYPE_MAX_METHOD. This also prevents issuing it with + * efx_ioctl_reset. + */ + RESET_TYPE_MCDI_TIMEOUT, RESET_TYPE_MAX, }; diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8ec20b7..fae25a4 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2696,6 +2696,8 @@ const struct efx_nic_type falcon_a1_nic_type = { .fini_dmaq = efx_farch_fini_dmaq, .prepare_flush = falcon_prepare_flush, .finish_flush = efx_port_dummy_op_void, + .prepare_flr = efx_port_dummy_op_void, + .finish_flr = efx_farch_finish_flr, .describe_stats = falcon_describe_nic_stats, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, @@ -2790,6 +2792,8 @@ const struct efx_nic_type falcon_b0_nic_type = { .fini_dmaq = efx_farch_fini_dmaq, .prepare_flush = falcon_prepare_flush, .finish_flush = efx_port_dummy_op_void, + .prepare_flr = efx_port_dummy_op_void, + .finish_flr = efx_farch_finish_flr, .describe_stats = falcon_describe_nic_stats, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index a087613..0537381 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -741,6 +741,28 @@ int efx_farch_fini_dmaq(struct efx_nic *efx) return rc; } +/* Reset queue and flush accounting after FLR + * + * One possible cause of FLR recovery is that DMA may be failing (eg. if bus + * mastering was disabled), in which case we don't receive (RXQ) flush + * completion events. This means that efx->rxq_flush_outstanding remained at 4 + * after the FLR; also, efx->active_queues was non-zero (as no flush completion + * events were received, and we didn't go through efx_check_tx_flush_complete()) + * If we don't fix this up, on the next call to efx_realloc_channels() we won't + * flush any RX queues because efx->rxq_flush_outstanding is at the limit of 4 + * for batched flush requests; and the efx->active_queues gets messed up because + * we keep incrementing for the newly initialised queues, but it never went to + * zero previously. Then we get a timeout every time we try to restart the + * queues, as it doesn't go back to zero when we should be flushing the queues. + */ +void efx_farch_finish_flr(struct efx_nic *efx) +{ + atomic_set(&efx->rxq_flush_pending, 0); + atomic_set(&efx->rxq_flush_outstanding, 0); + atomic_set(&efx->active_queues, 0); +} + + /************************************************************************** * * Event queue processing diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 7bd4b14..5239cf9 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -52,12 +52,7 @@ static void efx_mcdi_timeout_async(unsigned long context); static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, bool *was_attached_out); static bool efx_mcdi_poll_once(struct efx_nic *efx); - -static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) -{ - EFX_BUG_ON_PARANOID(!efx->mcdi); - return &efx->mcdi->iface; -} +static void efx_mcdi_abandon(struct efx_nic *efx); int efx_mcdi_init(struct efx_nic *efx) { @@ -558,6 +553,8 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, rc = 0; } + efx_mcdi_abandon(efx); + /* Close the race with efx_mcdi_ev_cpl() executing just too late * and completing a request we've just cancelled, by ensuring * that the seqno check therein fails. @@ -672,6 +669,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, if (efx->mc_bist_for_other_fn) return -ENETDOWN; + if (mcdi->mode == MCDI_MODE_FAIL) + return -ENETDOWN; + efx_mcdi_acquire_sync(mcdi); efx_mcdi_send_request(efx, cmd, inbuf, inlen); return 0; @@ -812,7 +812,11 @@ void efx_mcdi_mode_poll(struct efx_nic *efx) return; mcdi = efx_mcdi(efx); - if (mcdi->mode == MCDI_MODE_POLL) + /* If already in polling mode, nothing to do. + * If in fail-fast state, don't switch to polled completion. + * FLR recovery will do that later. + */ + if (mcdi->mode == MCDI_MODE_POLL || mcdi->mode == MCDI_MODE_FAIL) return; /* We can switch from event completion to polled completion, because @@ -841,8 +845,8 @@ void efx_mcdi_flush_async(struct efx_nic *efx) mcdi = efx_mcdi(efx); - /* We must be in polling mode so no more requests can be queued */ - BUG_ON(mcdi->mode != MCDI_MODE_POLL); + /* We must be in poll or fail mode so no more requests can be queued */ + BUG_ON(mcdi->mode == MCDI_MODE_EVENTS); del_timer_sync(&mcdi->async_timer); @@ -875,8 +879,11 @@ void efx_mcdi_mode_event(struct efx_nic *efx) return; mcdi = efx_mcdi(efx); - - if (mcdi->mode == MCDI_MODE_EVENTS) + /* If already in event completion mode, nothing to do. + * If in fail-fast state, don't switch to event completion. FLR + * recovery will do that later. + */ + if (mcdi->mode == MCDI_MODE_EVENTS || mcdi->mode == MCDI_MODE_FAIL) return; /* We can't switch from polled to event completion in the middle of a @@ -966,6 +973,19 @@ static void efx_mcdi_ev_bist(struct efx_nic *efx) spin_unlock(&mcdi->iface_lock); } +/* MCDI timeouts seen, so make all MCDI calls fail-fast and issue an FLR to try + * to recover. + */ +static void efx_mcdi_abandon(struct efx_nic *efx) +{ + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + + if (xchg(&mcdi->mode, MCDI_MODE_FAIL) == MCDI_MODE_FAIL) + return; /* it had already been done */ + netif_dbg(efx, hw, efx->net_dev, "MCDI is timing out; trying to recover\n"); + efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT); +} + /* Called from falcon_process_eventq for MCDI events */ void efx_mcdi_process_event(struct efx_channel *channel, efx_qword_t *event) @@ -1512,6 +1532,19 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method) { int rc; + /* If MCDI is down, we can't handle_assertion */ + if (method == RESET_TYPE_MCDI_TIMEOUT) { + rc = pci_reset_function(efx->pci_dev); + if (rc) + return rc; + /* Re-enable polled MCDI completion */ + if (efx->mcdi) { + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + mcdi->mode = MCDI_MODE_POLL; + } + return 0; + } + /* Recover from a failed assertion pre-reset */ rc = efx_mcdi_handle_assertion(efx); if (rc) diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 52931ae..56465f7 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -28,9 +28,16 @@ enum efx_mcdi_state { MCDI_STATE_COMPLETED, }; +/** + * enum efx_mcdi_mode - MCDI transaction mode + * @MCDI_MODE_POLL: poll for MCDI completion, until timeout + * @MCDI_MODE_EVENTS: wait for an mcdi_event. On timeout, poll once + * @MCDI_MODE_FAIL: we think MCDI is dead, so fail-fast all calls + */ enum efx_mcdi_mode { MCDI_MODE_POLL, MCDI_MODE_EVENTS, + MCDI_MODE_FAIL, }; /** @@ -104,6 +111,12 @@ struct efx_mcdi_data { u32 fn_flags; }; +static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) +{ + EFX_BUG_ON_PARANOID(!efx->mcdi); + return &efx->mcdi->iface; +} + #ifdef CONFIG_SFC_MCDI_MON static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx) { diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 8a400a0..5bdae8e 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -972,6 +972,8 @@ struct efx_mtd_partition { * (for Falcon architecture) * @finish_flush: Clean up after flushing the DMA queues (for Falcon * architecture) + * @prepare_flr: Prepare for an FLR + * @finish_flr: Clean up after an FLR * @describe_stats: Describe statistics for ethtool * @update_stats: Update statistics not provided by event handling. * Either argument may be %NULL. @@ -1100,6 +1102,8 @@ struct efx_nic_type { int (*fini_dmaq)(struct efx_nic *efx); void (*prepare_flush)(struct efx_nic *efx); void (*finish_flush)(struct efx_nic *efx); + void (*prepare_flr)(struct efx_nic *efx); + void (*finish_flr)(struct efx_nic *efx); size_t (*describe_stats)(struct efx_nic *efx, u8 *names); size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, struct rtnl_link_stats64 *core_stats); diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index a001fae..d3ad8ed 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -757,6 +757,7 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx) int efx_nic_flush_queues(struct efx_nic *efx); void siena_prepare_flush(struct efx_nic *efx); int efx_farch_fini_dmaq(struct efx_nic *efx); +void efx_farch_finish_flr(struct efx_nic *efx); void siena_finish_flush(struct efx_nic *efx); void falcon_start_nic_stats(struct efx_nic *efx); void falcon_stop_nic_stats(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 23f3a6f..50ffefe 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -921,6 +921,8 @@ const struct efx_nic_type siena_a0_nic_type = { .fini_dmaq = efx_farch_fini_dmaq, .prepare_flush = siena_prepare_flush, .finish_flush = siena_finish_flush, + .prepare_flr = efx_port_dummy_op_void, + .finish_flr = efx_farch_finish_flr, .describe_stats = siena_describe_nic_stats, .update_stats = siena_update_nic_stats, .start_stats = efx_mcdi_mac_start_stats, diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index e701433..9c4defd 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -32,29 +32,39 @@ struct mdio_gpio_info { struct mdiobb_ctrl ctrl; - int mdc, mdio; + int mdc, mdio, mdo; + int mdc_active_low, mdio_active_low, mdo_active_low; }; static void *mdio_gpio_of_get_data(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mdio_gpio_platform_data *pdata; + enum of_gpio_flags flags; int ret; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; - ret = of_get_gpio(np, 0); + ret = of_get_gpio_flags(np, 0, &flags); if (ret < 0) return NULL; pdata->mdc = ret; + pdata->mdc_active_low = flags & OF_GPIO_ACTIVE_LOW; - ret = of_get_gpio(np, 1); + ret = of_get_gpio_flags(np, 1, &flags); if (ret < 0) return NULL; pdata->mdio = ret; + pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW; + + ret = of_get_gpio_flags(np, 2, &flags); + if (ret > 0) { + pdata->mdo = ret; + pdata->mdo_active_low = flags & OF_GPIO_ACTIVE_LOW; + } return pdata; } @@ -64,8 +74,19 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); + if (bitbang->mdo) { + /* Separate output pin. Always set its value to high + * when changing direction. If direction is input, + * assume the pin serves as pull-up. If direction is + * output, the default value is high. + */ + gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low); + return; + } + if (dir) - gpio_direction_output(bitbang->mdio, 1); + gpio_direction_output(bitbang->mdio, + 1 ^ bitbang->mdio_active_low); else gpio_direction_input(bitbang->mdio); } @@ -75,7 +96,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - return gpio_get_value(bitbang->mdio); + return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low; } static void mdio_set(struct mdiobb_ctrl *ctrl, int what) @@ -83,7 +104,10 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - gpio_set_value(bitbang->mdio, what); + if (bitbang->mdo) + gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low); + else + gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); } static void mdc_set(struct mdiobb_ctrl *ctrl, int what) @@ -91,7 +115,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - gpio_set_value(bitbang->mdc, what); + gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low); } static struct mdiobb_ops mdio_gpio_ops = { @@ -110,18 +134,22 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, struct mdio_gpio_info *bitbang; int i; - bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL); + bitbang = devm_kzalloc(dev, sizeof(*bitbang), GFP_KERNEL); if (!bitbang) goto out; bitbang->ctrl.ops = &mdio_gpio_ops; bitbang->ctrl.reset = pdata->reset; bitbang->mdc = pdata->mdc; + bitbang->mdc_active_low = pdata->mdc_active_low; bitbang->mdio = pdata->mdio; + bitbang->mdio_active_low = pdata->mdio_active_low; + bitbang->mdo = pdata->mdo; + bitbang->mdo_active_low = pdata->mdo_active_low; new_bus = alloc_mdio_bitbang(&bitbang->ctrl); if (!new_bus) - goto out_free_bitbang; + goto out; new_bus->name = "GPIO Bitbanged MDIO", @@ -138,11 +166,18 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id); - if (gpio_request(bitbang->mdc, "mdc")) + if (devm_gpio_request(dev, bitbang->mdc, "mdc")) + goto out_free_bus; + + if (devm_gpio_request(dev, bitbang->mdio, "mdio")) goto out_free_bus; - if (gpio_request(bitbang->mdio, "mdio")) - goto out_free_mdc; + if (bitbang->mdo) { + if (devm_gpio_request(dev, bitbang->mdo, "mdo")) + goto out_free_bus; + gpio_direction_output(bitbang->mdo, 1); + gpio_direction_input(bitbang->mdio); + } gpio_direction_output(bitbang->mdc, 0); @@ -150,12 +185,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, return new_bus; -out_free_mdc: - gpio_free(bitbang->mdc); out_free_bus: free_mdio_bitbang(new_bus); -out_free_bitbang: - kfree(bitbang); out: return NULL; } @@ -163,13 +194,8 @@ out: static void mdio_gpio_bus_deinit(struct device *dev) { struct mii_bus *bus = dev_get_drvdata(dev); - struct mdio_gpio_info *bitbang = bus->priv; - dev_set_drvdata(dev, NULL); - gpio_free(bitbang->mdio); - gpio_free(bitbang->mdc); free_mdio_bitbang(bus); - kfree(bitbang); } static void mdio_gpio_bus_destroy(struct device *dev) diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index e323b4d..34f97c3 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c @@ -41,6 +41,8 @@ static const char * const cw1200_debug_link_id[] = { "REQ", "SOFT", "HARD", + "RESET", + "RESET_REMAP", }; static const char *cw1200_debug_mode(int mode) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 003a546..4c2d4ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -67,8 +67,8 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL7260_UCODE_API_MAX 8 -#define IWL3160_UCODE_API_MAX 8 +#define IWL7260_UCODE_API_MAX 9 +#define IWL3160_UCODE_API_MAX 9 /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 8 @@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = { MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); +MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 685f7e8..fa858d54 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c @@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { cpu_to_le32(0xcc00aaaa), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xc0004000), - cpu_to_le32(0x00000000), + cpu_to_le32(0x00004000), cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000), }, @@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { /* Tx Tx disabled */ cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xeeaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xcc00aaaa), cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xC0004000), - cpu_to_le32(0xC0004000), - cpu_to_le32(0xF0005000), - cpu_to_le32(0xF0005000), + cpu_to_le32(0xc0004000), + cpu_to_le32(0xc0004000), + cpu_to_le32(0xf0005000), + cpu_to_le32(0xf0005000), }, }; @@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 ant_isolation = le32_to_cpup((void *)pkt->data); u8 __maybe_unused lower_bound, upper_bound; + int ret; u8 lut; struct iwl_bt_coex_cmd *bt_cmd; @@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, sizeof(bt_cmd->bt4_corun_lut40)); - return 0; + ret = iwl_mvm_send_cmd(mvm, &cmd); + + kfree(bt_cmd); + return ret; } diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 4dd9ff4..f0cebf1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, */ iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); + iwl_mvm_sf_update(mvm, vif, false); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) { diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 568abd6..9f52c5b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -59,7 +59,7 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) - +#define RS_IDLE_TIMEOUT (5*HZ) static u8 rs_ht_to_legacy[] = { [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, @@ -142,7 +142,7 @@ enum rs_column_mode { RS_MIMO2, }; -#define MAX_NEXT_COLUMNS 5 +#define MAX_NEXT_COLUMNS 7 #define MAX_COLUMN_CHECKS 3 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, @@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, - RS_COLUMN_MIMO2, - RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, }, }, [RS_COLUMN_LEGACY_ANT_B] = { @@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, - RS_COLUMN_MIMO2, - RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, }, }, [RS_COLUMN_SISO_ANT_A] = { @@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, - RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, }, .checks = { rs_siso_allow, @@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_SISO_ANT_A_SGI, - RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, }, .checks = { rs_siso_allow, @@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, @@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, @@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, @@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, @@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) window->average_tpt = IWL_INVALID_VALUE; } -static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl) +static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm, + struct iwl_scale_tbl_info *tbl) { int i; + IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&tbl->win[i]); } @@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, return; } +#ifdef CPTCFG_MAC80211_DEBUGFS + /* Disable last tx check if we are debugging with fixed rate */ + if (lq_sta->dbg_fixed_rate) { + IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); + return; + } +#endif if (!ieee80211_is_data(hdr->frame_control) || info->flags & IEEE80211_TX_CTL_NO_ACK) return; @@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, mac_index++; } + if (time_after(jiffies, + (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) { + int tid; + IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); + for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) + ieee80211_stop_tx_ba_session(sta, tid); + + iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); + return; + } + lq_sta->last_tx = jiffies; + /* Here we actually compare this rate to the latest LQ command */ if ((mac_index < 0) || (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || @@ -1186,9 +1223,26 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, lq_sta->visited_columns = 0; } +static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta, + const struct rs_tx_column *column) +{ + switch (column->mode) { + case RS_LEGACY: + return lq_sta->max_legacy_rate_idx; + case RS_SISO: + return lq_sta->max_siso_rate_idx; + case RS_MIMO2: + return lq_sta->max_mimo2_rate_idx; + default: + WARN_ON_ONCE(1); + } + + return lq_sta->max_legacy_rate_idx; +} + static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, - const struct rs_tx_column *column, - u32 bw) + const struct rs_tx_column *column, + u32 bw) { /* Used to choose among HT tables */ const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT]; @@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) IWL_DEBUG_RATE(mvm, "LQ: stay in table clear win\n"); - rs_rate_scale_clear_tbl_windows(tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); } } @@ -1446,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) * bitmaps and stats in active table (this will become the new * "search" table). */ if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { - IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); - rs_rate_scale_clear_tbl_windows(tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); } } } @@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl) { - int i, j, n; + int i, j, max_rate; enum rs_column next_col_id; const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; const struct rs_tx_column *next_col; allow_column_func_t allow_func; u8 valid_ants = mvm->fw->valid_tx_ant; const u16 *expected_tpt_tbl; - s32 tpt, max_expected_tpt; + u16 tpt, max_expected_tpt; for (i = 0; i < MAX_NEXT_COLUMNS; i++) { next_col_id = curr_col->next_columns[i]; @@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, if (WARN_ON_ONCE(!expected_tpt_tbl)) continue; - max_expected_tpt = 0; - for (n = 0; n < IWL_RATE_COUNT; n++) - if (expected_tpt_tbl[n] > max_expected_tpt) - max_expected_tpt = expected_tpt_tbl[n]; + max_rate = rs_get_max_allowed_rate(lq_sta, next_col); + if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID)) + continue; + max_expected_tpt = expected_tpt_tbl[max_rate]; if (tpt >= max_expected_tpt) { IWL_DEBUG_RATE(mvm, "Skip column %d: can't beat current TPT. Max expected %d current %d\n", @@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, continue; } + IWL_DEBUG_RATE(mvm, + "Found potential column %d. Max expected %d current %d\n", + next_col_id, max_expected_tpt, tpt); break; } if (i == MAX_NEXT_COLUMNS) return RS_COLUMN_INVALID; - IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); - return next_col_id; } @@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, { enum rs_action action = RS_ACTION_STAY; - /* Too many failures, decrease rate */ if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { IWL_DEBUG_RATE(mvm, - "decrease rate because of low SR\n"); - action = RS_ACTION_DOWNSCALE; - /* No throughput measured yet for adjacent rates; try increase. */ - } else if ((low_tpt == IWL_INVALID_VALUE) && - (high_tpt == IWL_INVALID_VALUE)) { - if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { - IWL_DEBUG_RATE(mvm, - "Good SR and no high rate measurement. " - "Increase rate\n"); - action = RS_ACTION_UPSCALE; - } else if (low != IWL_RATE_INVALID) { - IWL_DEBUG_RATE(mvm, - "Remain in current rate\n"); - action = RS_ACTION_STAY; - } + "Decrease rate because of low SR\n"); + return RS_ACTION_DOWNSCALE; } - /* Both adjacent throughputs are measured, but neither one has better - * throughput; we're using the best rate, don't change it! - */ - else if ((low_tpt != IWL_INVALID_VALUE) && - (high_tpt != IWL_INVALID_VALUE) && - (low_tpt < current_tpt) && - (high_tpt < current_tpt)) { + if ((low_tpt == IWL_INVALID_VALUE) && + (high_tpt == IWL_INVALID_VALUE) && + (high != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, - "Both high and low are worse. " - "Maintain rate\n"); - action = RS_ACTION_STAY; + "No data about high/low rates. Increase rate\n"); + return RS_ACTION_UPSCALE; } - /* At least one adjacent rate's throughput is measured, - * and may have better performance. - */ - else { - /* Higher adjacent rate's throughput is measured */ - if (high_tpt != IWL_INVALID_VALUE) { - /* Higher rate has better throughput */ - if (high_tpt > current_tpt && - sr >= IWL_RATE_INCREASE_TH) { - IWL_DEBUG_RATE(mvm, - "Higher rate is better and good " - "SR. Increate rate\n"); - action = RS_ACTION_UPSCALE; - } else { - IWL_DEBUG_RATE(mvm, - "Higher rate isn't better OR " - "no good SR. Maintain rate\n"); - action = RS_ACTION_STAY; - } + if ((high_tpt == IWL_INVALID_VALUE) && + (high != IWL_RATE_INVALID) && + (low_tpt != IWL_INVALID_VALUE) && + (low_tpt < current_tpt)) { + IWL_DEBUG_RATE(mvm, + "No data about high rate and low rate is worse. Increase rate\n"); + return RS_ACTION_UPSCALE; + } - /* Lower adjacent rate's throughput is measured */ - } else if (low_tpt != IWL_INVALID_VALUE) { - /* Lower rate has better throughput */ - if (low_tpt > current_tpt) { - IWL_DEBUG_RATE(mvm, - "Lower rate is better. " - "Decrease rate\n"); - action = RS_ACTION_DOWNSCALE; - } else if (sr >= IWL_RATE_INCREASE_TH) { - IWL_DEBUG_RATE(mvm, - "Lower rate isn't better and " - "good SR. Increase rate\n"); - action = RS_ACTION_UPSCALE; - } - } + if ((high_tpt != IWL_INVALID_VALUE) && + (high_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Higher rate is better. Increate rate\n"); + return RS_ACTION_UPSCALE; } - /* Sanity check; asked for decrease, but success rate or throughput - * has been good at old rate. Don't change it. - */ - if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && - ((sr > IWL_RATE_HIGH_TH) || - (current_tpt > (100 * tbl->expected_tpt[low])))) { + if ((low_tpt != IWL_INVALID_VALUE) && + (high_tpt != IWL_INVALID_VALUE) && + (low_tpt < current_tpt) && + (high_tpt < current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Both high and low are worse. Maintain rate\n"); + return RS_ACTION_STAY; + } + + if ((low_tpt != IWL_INVALID_VALUE) && + (low_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Lower rate is better\n"); + action = RS_ACTION_DOWNSCALE; + goto out; + } + + if ((low_tpt == IWL_INVALID_VALUE) && + (low != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, - "Sanity check failed. Maintain rate\n"); - action = RS_ACTION_STAY; + "No data about lower rate\n"); + action = RS_ACTION_DOWNSCALE; + goto out; + } + + IWL_DEBUG_RATE(mvm, "Maintain rate\n"); + +out: + if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { + if (sr >= RS_SR_NO_DECREASE) { + IWL_DEBUG_RATE(mvm, + "SR is above NO DECREASE. Avoid downscale\n"); + action = RS_ACTION_STAY; + } else if (current_tpt > (100 * tbl->expected_tpt[low])) { + IWL_DEBUG_RATE(mvm, + "Current TPT is higher than max expected in low rate. Avoid downscale\n"); + action = RS_ACTION_STAY; + } else { + IWL_DEBUG_RATE(mvm, "Decrease rate\n"); + } } return action; @@ -1792,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, "Aggregation changed: prev %d current %d. Update expected TPT table\n", prev_agg, lq_sta->is_agg); rs_set_expected_tpt_table(lq_sta, tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); } /* current tx rate */ @@ -2021,7 +2067,7 @@ lq_update: if (lq_sta->search_better_tbl) { /* Access the "search" table, clear its history. */ tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - rs_rate_scale_clear_tbl_windows(tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); /* Use new "search" start rate */ index = tbl->rate.index; @@ -2042,8 +2088,18 @@ lq_update: * stay with best antenna legacy modulation for a while * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); - if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) { + if (is_legacy(&tbl1->rate)) { IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); + + if (tid != IWL_MAX_TID_COUNT) { + tid_data = &sta_priv->tid_data[tid]; + if (tid_data->state != IWL_AGG_OFF) { + IWL_DEBUG_RATE(mvm, + "Stop aggregation on tid %d\n", + tid); + ieee80211_stop_tx_ba_session(sta, tid); + } + } rs_set_stay_in_table(mvm, 1, lq_sta); } else { /* If we're in an HT mode, and all 3 mode switch actions @@ -2342,9 +2398,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->lq.sta_id = sta_priv->sta_id; for (j = 0; j < LQ_SIZE; j++) - rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); + rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); lq_sta->flush_timer = 0; + lq_sta->last_tx = jiffies; IWL_DEBUG_RATE(mvm, "LQ: *** rate scale station global init for station %d ***\n", @@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->is_vht = true; } - IWL_DEBUG_RATE(mvm, - "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", + lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, + BITS_PER_LONG); + lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, + BITS_PER_LONG); + lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate, + BITS_PER_LONG); + + IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n", + lq_sta->active_legacy_rate, lq_sta->active_siso_rate, lq_sta->active_mimo2_rate, lq_sta->is_vht); + IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", + lq_sta->max_legacy_rate_idx, + lq_sta->max_siso_rate_idx, + lq_sta->max_mimo2_rate_idx); /* These values will be overridden later */ lq_sta->lq.single_stream_ant_msk = @@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, if (is_siso(&rate)) { num_rates = RS_SECONDARY_SISO_NUM_RATES; num_retries = RS_SECONDARY_SISO_RETRIES; + lq_cmd->mimo_delim = index; } else if (is_legacy(&rate)) { num_rates = RS_SECONDARY_LEGACY_NUM_RATES; num_retries = RS_LEGACY_RETRIES_PER_RATE; @@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, return -ENOMEM; desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); - desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", + desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n", lq_sta->total_failed, lq_sta->total_success, lq_sta->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 3332b39..0acfac9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -156,6 +156,7 @@ enum { #define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */ #define RS_SR_FORCE_DECREASE 1920 /* 15% */ +#define RS_SR_NO_DECREASE 10880 /* 85% */ #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) @@ -310,13 +311,20 @@ struct iwl_lq_sta { u32 visited_columns; /* Bitmask marking which Tx columns were * explored during a search cycle */ + u64 last_tx; bool is_vht; enum ieee80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ - u16 active_legacy_rate; - u16 active_siso_rate; - u16 active_mimo2_rate; + unsigned long active_legacy_rate; + unsigned long active_siso_rate; + unsigned long active_mimo2_rate; + + /* Highest rate per Tx mode */ + u8 max_legacy_rate_idx; + u8 max_siso_rate_idx; + u8 max_mimo2_rate_idx; + s8 max_rate_idx; /* Max rate set by user */ u8 missed_rate_counter; diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 8401627..88809b2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c @@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif, return -EINVAL; if (changed_vif->type != NL80211_IFTYPE_STATION) { new_state = SF_UNINIT; - } else if (changed_vif->bss_conf.assoc) { + } else if (changed_vif->bss_conf.assoc && + changed_vif->bss_conf.dtim_period) { mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); sta_id = mvmvif->ap_sta_id; new_state = SF_FULL_ON; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index edb015c..3d1d57f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 77db088..9c771b3 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -292,6 +292,12 @@ process_start: while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) mwifiex_handle_rx_packet(adapter, skb); + /* Check for event */ + if (adapter->event_received) { + adapter->event_received = false; + mwifiex_process_event(adapter); + } + /* Check for Cmd Resp */ if (adapter->cmd_resp_received) { adapter->cmd_resp_received = false; @@ -304,12 +310,6 @@ process_start: } } - /* Check for event */ - if (adapter->event_received) { - adapter->event_received = false; - mwifiex_process_event(adapter); - } - /* Check if we need to confirm Sleep Request received previously */ if (adapter->ps_state == PS_STATE_PRE_SLEEP) { diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 8942706..536c14a 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -60,9 +60,10 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, int status; /* Wait for completion */ - status = wait_event_interruptible(adapter->cmd_wait_q.wait, - *(cmd_queued->condition)); - if (status) { + status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait, + *(cmd_queued->condition), + (12 * HZ)); + if (status <= 0) { dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); mwifiex_cancel_all_pending_cmd(adapter); return status; diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c index 1a8d321..cf61d6e 100644 --- a/drivers/net/wireless/rsi/rsi_91x_core.c +++ b/drivers/net/wireless/rsi/rsi_91x_core.c @@ -88,7 +88,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common) bool recontend_queue = false; u32 q_len = 0; u8 q_num = INVALID_QUEUE; - u8 ii, min = 0; + u8 ii = 0, min = 0; if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) { if (!common->mgmt_q_block) diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 7369429..1b28cda 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -841,16 +841,6 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) rsi_dbg(MGMT_TX_ZONE, "%s: Sending scan req frame\n", __func__); - skb = dev_alloc_skb(FRAME_DESC_SZ); - if (!skb) { - rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", - __func__); - return -ENOMEM; - } - - memset(skb->data, 0, FRAME_DESC_SZ); - mgmt_frame = (struct rsi_mac_frame *)skb->data; - if (common->band == IEEE80211_BAND_5GHZ) { if ((channel >= 36) && (channel <= 64)) channel = ((channel - 32) / 4); @@ -868,6 +858,16 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) } } + skb = dev_alloc_skb(FRAME_DESC_SZ); + if (!skb) { + rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", + __func__); + return -ENOMEM; + } + + memset(skb->data, 0, FRAME_DESC_SZ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); mgmt_frame->desc_word[4] = cpu_to_le16(channel); @@ -966,6 +966,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common) if (!selected_rates) { rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n", __func__); + dev_kfree_skb(skb); return -ENOMEM; } diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h index 398f3d2..a76e98e 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h @@ -68,6 +68,26 @@ struct wl18xx_event_mailbox { /* bitmap of inactive stations (by HLID) */ __le32 inactive_sta_bitmap; + + /* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */ + u8 rx_ba_role_id; + u8 rx_ba_link_id; + u8 rx_ba_win_size; + u8 padding; + + /* smart config */ + u8 sc_ssid_len; + u8 sc_pwd_len; + u8 sc_token_len; + u8 padding1; + u8 sc_ssid[32]; + u8 sc_pwd[32]; + u8 sc_token[32]; + + /* smart config sync channel */ + u8 sc_sync_channel; + u8 sc_sync_band; + u8 padding2[2]; } __packed; int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 1f9a360..16d1028 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -158,6 +158,11 @@ EXPORT_SYMBOL_GPL(wlcore_event_channel_switch); void wlcore_event_dummy_packet(struct wl1271 *wl) { + if (wl->plt) { + wl1271_info("Got DUMMY_PACKET event in PLT mode. FW bug, ignoring."); + return; + } + wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); wl1271_tx_dummy_packet(wl); } diff --git a/drivers/of/base.c b/drivers/of/base.c index f72d19b..6d4ee22 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1828,17 +1828,13 @@ int of_update_property(struct device_node *np, struct property *newprop) next = &(*next)->next; } raw_spin_unlock_irqrestore(&devtree_lock, flags); - if (rc) - return rc; + if (!found) + return -ENODEV; /* Update the sysfs attribute */ - if (oldprop) - sysfs_remove_bin_file(&np->kobj, &oldprop->attr); + sysfs_remove_bin_file(&np->kobj, &oldprop->attr); __of_add_property_sysfs(np, newprop); - if (!found) - return -ENODEV; - return 0; } diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index fa16a91..7a2ef7b 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -491,7 +491,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, * in /reserved-memory matches the values supported by the current implementation, * also check if ranges property has been provided */ -static int __reserved_mem_check_root(unsigned long node) +static int __init __reserved_mem_check_root(unsigned long node) { __be32 *prop; diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index fd3e3ab..4fe349d 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -15,6 +15,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_pci.h> #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -180,8 +181,13 @@ static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pci_sys_data *sys = dev->bus->sysdata; struct rcar_pci_priv *priv = sys->private_data; + int irq; + + irq = of_irq_parse_and_map_pci(dev, slot, pin); + if (!irq) + irq = priv->irq; - return priv->irq; + return irq; } #ifdef CONFIG_PCI_DEBUG diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 330f7e3..083cf37 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -639,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); + int irq; tegra_cpuidle_pcie_irqs_in_use(); - return pcie->irq; + irq = of_irq_parse_and_map_pci(pdev, slot, pin); + if (!irq) + irq = pcie->irq; + + return irq; } static void tegra_pcie_add_bus(struct pci_bus *bus) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 509a29d..c4e3732 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/msi.h> #include <linux/of_address.h> +#include <linux/of_pci.h> #include <linux/pci.h> #include <linux/pci_regs.h> #include <linux/types.h> @@ -490,7 +491,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) dw_pci.nr_controllers = 1; dw_pci.private_data = (void **)&pp; - pci_common_init(&dw_pci); + pci_common_init_dev(pp->dev, &dw_pci); pci_assign_unassigned_resources(); #ifdef CONFIG_PCI_DOMAINS dw_pci.domain++; @@ -520,13 +521,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, PCIE_ATU_VIEWPORT); dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, PCIE_ATU_LIMIT); dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) @@ -535,7 +536,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, PCIE_ATU_VIEWPORT); dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, @@ -543,6 +543,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) @@ -551,7 +552,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, PCIE_ATU_VIEWPORT); dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, @@ -559,6 +559,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, @@ -723,7 +724,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) if (pp) { pp->root_bus_nr = sys->busnr; - bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops, + bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops, sys, &sys->resources); } else { bus = NULL; @@ -736,8 +737,13 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); + int irq; + + irq = of_irq_parse_and_map_pci(dev, slot, pin); + if (!irq) + irq = pp->irq; - return pp->irq; + return irq; } static void dw_pcie_add_bus(struct pci_bus *bus) @@ -764,7 +770,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp) u32 membase; u32 memlimit; - /* set the number of lines as 4 */ + /* set the number of lanes */ dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); val &= ~PORT_LINK_MODE_MASK; switch (pp->lanes) { diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 3bb05f1..4906c27 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -33,6 +33,7 @@ config PHY_MVEBU_SATA config OMAP_CONTROL_PHY tristate "OMAP CONTROL PHY Driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST help Enable this to add support for the PHY part present in the control module. This driver has API to power on the USB2 PHY and to write to diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 2faf78e..7728518 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -13,8 +13,9 @@ obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o -obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-samsung-usb2.o -obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o -obj-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o -obj-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o +obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o +phy-exynos-usb2-y += phy-samsung-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o obj-$(CONFIG_PHY_XGENE) += phy-xgene.o diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 623b71c..c64a2f3 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -64,6 +64,9 @@ static struct phy *phy_lookup(struct device *device, const char *port) class_dev_iter_init(&iter, phy_class, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) { phy = to_phy(dev); + + if (!phy->init_data) + continue; count = phy->init_data->num_consumers; consumers = phy->init_data->consumers; while (count--) { diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 258fef2..3736bc4 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -15,6 +15,7 @@ #include <linux/types.h> #include <linux/kernel.h> +#include <linux/pci.h> #include <linux/string.h> #include <linux/slab.h> #include <linux/pnp.h> @@ -334,6 +335,81 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev) } #endif +#ifdef CONFIG_X86 +/* Device IDs of parts that have 32KB MCH space */ +static const unsigned int mch_quirk_devices[] = { + 0x0154, /* Ivy Bridge */ + 0x0c00, /* Haswell */ +}; + +static struct pci_dev *get_intel_host(void) +{ + int i; + struct pci_dev *host; + + for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) { + host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i], + NULL); + if (host) + return host; + } + return NULL; +} + +static void quirk_intel_mch(struct pnp_dev *dev) +{ + struct pci_dev *host; + u32 addr_lo, addr_hi; + struct pci_bus_region region; + struct resource mch; + struct pnp_resource *pnp_res; + struct resource *res; + + host = get_intel_host(); + if (!host) + return; + + /* + * MCHBAR is not an architected PCI BAR, so MCH space is usually + * reported as a PNP0C02 resource. The MCH space was originally + * 16KB, but is 32KB in newer parts. Some BIOSes still report a + * PNP0C02 resource that is only 16KB, which means the rest of the + * MCH space is consumed but unreported. + */ + + /* + * Read MCHBAR for Host Member Mapped Register Range Base + * https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet + * Sec 3.1.12. + */ + pci_read_config_dword(host, 0x48, &addr_lo); + region.start = addr_lo & ~0x7fff; + pci_read_config_dword(host, 0x4c, &addr_hi); + region.start |= (u64) addr_hi << 32; + region.end = region.start + 32*1024 - 1; + + memset(&mch, 0, sizeof(mch)); + mch.flags = IORESOURCE_MEM; + pcibios_bus_to_resource(host->bus, &mch, ®ion); + + list_for_each_entry(pnp_res, &dev->resources, list) { + res = &pnp_res->res; + if (res->end < mch.start || res->start > mch.end) + continue; /* no overlap */ + if (res->start == mch.start && res->end == mch.end) + continue; /* exact match */ + + dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n", + res, pci_name(host), &mch); + res->start = mch.start; + res->end = mch.end; + break; + } + + pci_dev_put(host); +} +#endif + /* * PnP Quirks * Cards or devices that need some tweaking due to incomplete resource info @@ -364,6 +440,9 @@ static struct pnp_fixup pnp_fixups[] = { #ifdef CONFIG_AMD_NB {"PNP0c01", quirk_amd_mmconfig_area}, #endif +#ifdef CONFIG_X86 + {"PNP0c02", quirk_intel_mch}, +#endif {""} }; diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 476aa49..b95cf71 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -11,7 +11,7 @@ * Copyright (C) 2012 ARM Limited */ -#include <linux/jiffies.h> +#include <linux/delay.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -23,17 +23,12 @@ static void vexpress_reset_do(struct device *dev, const char *what) { int err = -ENOENT; - struct vexpress_config_func *func = - vexpress_config_func_get_by_dev(dev); + struct vexpress_config_func *func = dev_get_drvdata(dev); if (func) { - unsigned long timeout; - err = vexpress_config_write(func, 0, 0); - - timeout = jiffies + HZ; - while (time_before(jiffies, timeout)) - cpu_relax(); + if (!err) + mdelay(1000); } dev_emerg(dev, "Unable to %s (%d)\n", what, err); @@ -96,12 +91,18 @@ static int vexpress_reset_probe(struct platform_device *pdev) enum vexpress_reset_func func; const struct of_device_id *match = of_match_device(vexpress_reset_of_match, &pdev->dev); + struct vexpress_config_func *config_func; if (match) func = (enum vexpress_reset_func)match->data; else func = pdev->id_entry->driver_data; + config_func = vexpress_config_func_get_by_dev(&pdev->dev); + if (!config_func) + return -EINVAL; + dev_set_drvdata(&pdev->dev, config_func); + switch (func) { case FUNC_SHUTDOWN: vexpress_power_off_device = &pdev->dev; diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c index 8ad26b8..cb2d4f0 100644 --- a/drivers/pwm/pwm-spear.c +++ b/drivers/pwm/pwm-spear.c @@ -2,7 +2,7 @@ * ST Microelectronics SPEAr Pulse Width Modulator driver * * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim <shiraz.hashim@st.com> + * Shiraz Hashim <shiraz.linux.kernel@gmail.com> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -264,6 +264,6 @@ static struct platform_driver spear_pwm_driver = { module_platform_driver(spear_pwm_driver); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>"); +MODULE_AUTHOR("Shiraz Hashim <shiraz.linux.kernel@gmail.com>"); MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.com>"); MODULE_ALIAS("platform:spear-pwm"); diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c index ded3b35..6d38be3 100644 --- a/drivers/regulator/pbias-regulator.c +++ b/drivers/regulator/pbias-regulator.c @@ -38,66 +38,24 @@ struct pbias_reg_info { struct pbias_regulator_data { struct regulator_desc desc; void __iomem *pbias_addr; - unsigned int pbias_reg; struct regulator_dev *dev; struct regmap *syscon; const struct pbias_reg_info *info; int voltage; }; -static int pbias_regulator_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) -{ - struct pbias_regulator_data *data = rdev_get_drvdata(dev); - const struct pbias_reg_info *info = data->info; - int ret, vmode; - - if (min_uV <= 1800000) - vmode = 0; - else if (min_uV > 1800000) - vmode = info->vmode; - - ret = regmap_update_bits(data->syscon, data->pbias_reg, - info->vmode, vmode); - - return ret; -} - -static int pbias_regulator_get_voltage(struct regulator_dev *rdev) -{ - struct pbias_regulator_data *data = rdev_get_drvdata(rdev); - const struct pbias_reg_info *info = data->info; - int value, voltage; - - regmap_read(data->syscon, data->pbias_reg, &value); - value &= info->vmode; - - voltage = value ? 3000000 : 1800000; - - return voltage; -} +static const unsigned int pbias_volt_table[] = { + 1800000, + 3000000 +}; static int pbias_regulator_enable(struct regulator_dev *rdev) { struct pbias_regulator_data *data = rdev_get_drvdata(rdev); const struct pbias_reg_info *info = data->info; - int ret; - - ret = regmap_update_bits(data->syscon, data->pbias_reg, - info->enable_mask, info->enable); - - return ret; -} - -static int pbias_regulator_disable(struct regulator_dev *rdev) -{ - struct pbias_regulator_data *data = rdev_get_drvdata(rdev); - const struct pbias_reg_info *info = data->info; - int ret; - ret = regmap_update_bits(data->syscon, data->pbias_reg, - info->enable_mask, 0); - return ret; + return regmap_update_bits(data->syscon, rdev->desc->enable_reg, + info->enable_mask, info->enable); } static int pbias_regulator_is_enable(struct regulator_dev *rdev) @@ -106,17 +64,18 @@ static int pbias_regulator_is_enable(struct regulator_dev *rdev) const struct pbias_reg_info *info = data->info; int value; - regmap_read(data->syscon, data->pbias_reg, &value); + regmap_read(data->syscon, rdev->desc->enable_reg, &value); - return (value & info->enable_mask) == info->enable_mask; + return (value & info->enable_mask) == info->enable; } static struct regulator_ops pbias_regulator_voltage_ops = { - .set_voltage = pbias_regulator_set_voltage, - .get_voltage = pbias_regulator_get_voltage, - .enable = pbias_regulator_enable, - .disable = pbias_regulator_disable, - .is_enabled = pbias_regulator_is_enable, + .list_voltage = regulator_list_voltage_table, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = pbias_regulator_enable, + .disable = regulator_disable_regmap, + .is_enabled = pbias_regulator_is_enable, }; static const struct pbias_reg_info pbias_mmc_omap2430 = { @@ -192,6 +151,7 @@ static int pbias_regulator_probe(struct platform_device *pdev) if (IS_ERR(syscon)) return PTR_ERR(syscon); + cfg.regmap = syscon; cfg.dev = &pdev->dev; for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) { @@ -207,15 +167,19 @@ static int pbias_regulator_probe(struct platform_device *pdev) if (!res) return -EINVAL; - drvdata[data_idx].pbias_reg = res->start; drvdata[data_idx].syscon = syscon; drvdata[data_idx].info = info; drvdata[data_idx].desc.name = info->name; drvdata[data_idx].desc.owner = THIS_MODULE; drvdata[data_idx].desc.type = REGULATOR_VOLTAGE; drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops; + drvdata[data_idx].desc.volt_table = pbias_volt_table; drvdata[data_idx].desc.n_voltages = 2; drvdata[data_idx].desc.enable_time = info->enable_time; + drvdata[data_idx].desc.vsel_reg = res->start; + drvdata[data_idx].desc.vsel_mask = info->vmode; + drvdata[data_idx].desc.enable_reg = res->start; + drvdata[data_idx].desc.enable_mask = info->enable_mask; cfg.init_data = pbias_matches[idx].init_data; cfg.driver_data = &drvdata[data_idx]; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 8cf4a0c..9a6e4a2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7463,6 +7463,10 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) if (hpsa_simple_mode) return; + trans_support = readl(&(h->cfgtable->TransportSupport)); + if (!(trans_support & PERFORMANT_MODE)) + return; + /* Check for I/O accelerator mode support */ if (trans_support & CFGTBL_Trans_io_accel1) { transMethod |= CFGTBL_Trans_io_accel1 | @@ -7479,10 +7483,6 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) } /* TODO, check that this next line h->nreply_queues is correct */ - trans_support = readl(&(h->cfgtable->TransportSupport)); - if (!(trans_support & PERFORMANT_MODE)) - return; - h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1; hpsa_get_max_perf_mode_cmds(h); /* Performant mode ring buffer and supporting data structures */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 771c16b..f17aa7a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -189,6 +189,7 @@ scsi_abort_command(struct scsi_cmnd *scmd) /* * Retry after abort failed, escalate to next level. */ + scmd->eh_eflags &= ~SCSI_EH_ABORT_SCHEDULED; SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "scmd %p previous abort failed\n", scmd)); @@ -920,10 +921,12 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, ses->prot_op = scmd->prot_op; scmd->prot_op = SCSI_PROT_NORMAL; + scmd->eh_eflags = 0; scmd->cmnd = ses->eh_cmnd; memset(scmd->cmnd, 0, BLK_MAX_CDB); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->request->next_rq = NULL; + scmd->result = 0; if (sense_bytes) { scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE, @@ -1157,6 +1160,15 @@ int scsi_eh_get_sense(struct list_head *work_q, __func__)); break; } + if (status_byte(scmd->result) != CHECK_CONDITION) + /* + * don't request sense if there's no check condition + * status because the error we're processing isn't one + * that has a sense code (and some devices get + * confused by sense requests out of the blue) + */ + continue; + SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd, "%s: requesting sense\n", current->comm)); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 65a123d..9db097a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -137,6 +137,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) * lock such that the kblockd_schedule_work() call happens * before blk_cleanup_queue() finishes. */ + cmd->result = 0; spin_lock_irqsave(q->queue_lock, flags); blk_requeue_request(q, cmd->request); kblockd_schedule_work(q, &device->requeue_work); @@ -1044,6 +1045,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, */ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) { + struct scsi_device *sdev = cmd->device; struct request *rq = cmd->request; int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask); @@ -1091,7 +1093,7 @@ err_exit: scsi_release_buffers(cmd); cmd->request->special = NULL; scsi_put_command(cmd); - put_device(&cmd->device->sdev_gendev); + put_device(&sdev->sdev_gendev); return error; } EXPORT_SYMBOL(scsi_init_io); @@ -1273,7 +1275,7 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret) struct scsi_cmnd *cmd = req->special; scsi_release_buffers(cmd); scsi_put_command(cmd); - put_device(&cmd->device->sdev_gendev); + put_device(&sdev->sdev_gendev); req->special = NULL; } break; diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 8005f98..079e6b1 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1115,8 +1115,11 @@ static int atmel_spi_one_transfer(struct spi_master *master, atmel_spi_next_xfer_pio(master, xfer); } + /* interrupts are disabled, so free the lock for schedule */ + atmel_spi_unlock(as); ret = wait_for_completion_timeout(&as->xfer_completion, SPI_DMA_TIMEOUT); + atmel_spi_lock(as); if (WARN_ON(ret == 0)) { dev_err(&spi->dev, "spi trasfer timeout, err %d\n", ret); diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 55e57c3..ebf720b 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/gpio.h> #include <linux/slab.h> #include <linux/io.h> #include <linux/ioport.h> diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 9009456..c8e795e 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -244,9 +244,9 @@ static int hspi_probe(struct platform_device *pdev) return -ENOMEM; } - clk = clk_get(NULL, "shyway_clk"); + clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { - dev_err(&pdev->dev, "shyway_clk is required\n"); + dev_err(&pdev->dev, "couldn't get clock\n"); ret = -EINVAL; goto error0; } diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 1a77ad5..67d8909 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -287,8 +287,8 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) sspi->left_rx_word) sspi->rx_word(sspi); - if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY - | SIRFSOC_SPI_TXFIFO_THD_REACH)) + if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY | + SIRFSOC_SPI_TXFIFO_THD_REACH)) while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) & SIRFSOC_SPI_FIFO_FULL)) && sspi->left_tx_word) @@ -470,7 +470,16 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) writel(regval, sspi->base + SIRFSOC_SPI_CTRL); } else { int gpio = sspi->chipselect[spi->chip_select]; - gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); + switch (value) { + case BITBANG_CS_ACTIVE: + gpio_direction_output(gpio, + spi->mode & SPI_CS_HIGH ? 1 : 0); + break; + case BITBANG_CS_INACTIVE: + gpio_direction_output(gpio, + spi->mode & SPI_CS_HIGH ? 0 : 1); + break; + } } } @@ -559,6 +568,11 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) regval &= ~SIRFSOC_SPI_CMD_MODE; sspi->tx_by_cmd = false; } + /* + * set spi controller in RISC chipselect mode, we are controlling CS by + * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE. + */ + regval |= SIRFSOC_SPI_CS_IO_MODE; writel(regval, sspi->base + SIRFSOC_SPI_CTRL); if (IS_DMA_VALID(t)) { diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ea5efb4..22365f1 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -40,8 +40,6 @@ source "drivers/staging/olpc_dcon/Kconfig" source "drivers/staging/panel/Kconfig" -source "drivers/staging/rtl8187se/Kconfig" - source "drivers/staging/rtl8192u/Kconfig" source "drivers/staging/rtl8192e/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 86e020c..fbe84ed 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ obj-$(CONFIG_PANEL) += panel/ -obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 924fce9..2575950 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -61,6 +61,8 @@ static void __comedi_buf_free(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; + struct comedi_buf_map *bm; + unsigned long flags; if (async->prealloc_buf) { vunmap(async->prealloc_buf); @@ -68,8 +70,11 @@ static void __comedi_buf_free(struct comedi_device *dev, async->prealloc_bufsz = 0; } - comedi_buf_map_put(async->buf_map); + spin_lock_irqsave(&s->spin_lock, flags); + bm = async->buf_map; async->buf_map = NULL; + spin_unlock_irqrestore(&s->spin_lock, flags); + comedi_buf_map_put(bm); } static void __comedi_buf_alloc(struct comedi_device *dev, @@ -80,6 +85,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, struct page **pages = NULL; struct comedi_buf_map *bm; struct comedi_buf_page *buf; + unsigned long flags; unsigned i; if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) { @@ -92,8 +98,10 @@ static void __comedi_buf_alloc(struct comedi_device *dev, if (!bm) return; - async->buf_map = bm; kref_init(&bm->refcount); + spin_lock_irqsave(&s->spin_lock, flags); + async->buf_map = bm; + spin_unlock_irqrestore(&s->spin_lock, flags); bm->dma_dir = s->async_dma_dir; if (bm->dma_dir != DMA_NONE) /* Need ref to hardware device to free buffer later. */ @@ -127,7 +135,9 @@ static void __comedi_buf_alloc(struct comedi_device *dev, pages[i] = virt_to_page(buf->virt_addr); } + spin_lock_irqsave(&s->spin_lock, flags); bm->n_pages = i; + spin_unlock_irqrestore(&s->spin_lock, flags); /* vmap the prealloc_buf if all the pages were allocated */ if (i == n_pages) @@ -150,6 +160,29 @@ int comedi_buf_map_put(struct comedi_buf_map *bm) return 1; } +/* returns s->async->buf_map and increments its kref refcount */ +struct comedi_buf_map * +comedi_buf_map_from_subdev_get(struct comedi_subdevice *s) +{ + struct comedi_async *async = s->async; + struct comedi_buf_map *bm = NULL; + unsigned long flags; + + if (!async) + return NULL; + + spin_lock_irqsave(&s->spin_lock, flags); + bm = async->buf_map; + /* only want it if buffer pages allocated */ + if (bm && bm->n_pages) + comedi_buf_map_get(bm); + else + bm = NULL; + spin_unlock_irqrestore(&s->spin_lock, flags); + + return bm; +} + bool comedi_buf_is_mmapped(struct comedi_async *async) { struct comedi_buf_map *bm = async->buf_map; diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ea6dc36..acc8019 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1926,14 +1926,21 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) struct comedi_device *dev = file->private_data; struct comedi_subdevice *s; struct comedi_async *async; - struct comedi_buf_map *bm; + struct comedi_buf_map *bm = NULL; unsigned long start = vma->vm_start; unsigned long size; int n_pages; int i; int retval; - mutex_lock(&dev->mutex); + /* + * 'trylock' avoids circular dependency with current->mm->mmap_sem + * and down-reading &dev->attach_lock should normally succeed without + * contention unless the device is in the process of being attached + * or detached. + */ + if (!down_read_trylock(&dev->attach_lock)) + return -EAGAIN; if (!dev->attached) { dev_dbg(dev->class_dev, "no driver attached\n"); @@ -1973,7 +1980,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) } n_pages = size >> PAGE_SHIFT; - bm = async->buf_map; + + /* get reference to current buf map (if any) */ + bm = comedi_buf_map_from_subdev_get(s); if (!bm || n_pages > bm->n_pages) { retval = -EINVAL; goto done; @@ -1997,7 +2006,8 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) retval = 0; done: - mutex_unlock(&dev->mutex); + up_read(&dev->attach_lock); + comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */ return retval; } diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index 9a74657..a492f2d 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -19,6 +19,8 @@ void comedi_buf_reset(struct comedi_async *async); bool comedi_buf_is_mmapped(struct comedi_async *async); void comedi_buf_map_get(struct comedi_buf_map *bm); int comedi_buf_map_put(struct comedi_buf_map *bm); +struct comedi_buf_map *comedi_buf_map_from_subdev_get( + struct comedi_subdevice *s); unsigned int comedi_buf_write_n_allocated(struct comedi_async *async); void comedi_device_cancel_all(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 71db683..b59af03 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -493,7 +493,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) /* pointer to the DA */ *datap++ = val & 0xff; *datap++ = (val >> 8) & 0xff; - *datap++ = chan; + *datap++ = chan << 6; devpriv->ao_readback[chan] = val; s->async->events |= COMEDI_CB_BLOCK; @@ -1040,11 +1040,8 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; - for (i = 0; i < cmd->chanlist_len; ++i) { - unsigned int chan = CR_CHAN(cmd->chanlist[i]); - - devpriv->ao_chanlist[i] = chan << 6; - } + for (i = 0; i < cmd->chanlist_len; ++i) + devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]); /* we count in steps of 1ms (125us) */ /* 125us mode not used yet */ diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index f96dcec..7ac2602 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -334,6 +334,7 @@ static int goldfish_audio_probe(struct platform_device *pdev) return 0; err_misc_register_failed: + free_irq(data->irq, data); err_request_irq_failed: dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, data->buffer_virt, data->buffer_phys); diff --git a/drivers/staging/gs_fpgaboot/Makefile b/drivers/staging/gs_fpgaboot/Makefile index 34cb606..d2f0211 100644 --- a/drivers/staging/gs_fpgaboot/Makefile +++ b/drivers/staging/gs_fpgaboot/Makefile @@ -1,4 +1,2 @@ gs_fpga-y += gs_fpgaboot.o io.o obj-$(CONFIG_GS_FPGABOOT) += gs_fpga.o - -ccflags-$(CONFIG_GS_FPGA_DEBUG) := -DDEBUG diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index 89bc84d..7506900 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -373,7 +373,6 @@ static int __init gs_fpgaboot_init(void) r = -1; pr_info("FPGA DOWNLOAD --->\n"); - pr_info("built at %s UTC\n", __TIMESTAMP__); pr_info("FPGA image file name: %s\n", file); diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 11fb952..dae8d1a 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -1526,7 +1526,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) struct resource *iores; int ret = 0, touch_ret; int i, s; - unsigned int scale_uv; + uint64_t scale_uv; /* Allocate the IIO device. */ iio = devm_iio_device_alloc(dev, sizeof(*lradc)); diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index 36eedd8..e2b4820 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -70,6 +70,7 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev, vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); vel = (vel << 4) >> 4; *val = vel; + break; default: mutex_unlock(&st->lock); return -EINVAL; diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig deleted file mode 100644 index ff8d41e..0000000 --- a/drivers/staging/rtl8187se/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config R8187SE - tristate "RealTek RTL8187SE Wireless LAN NIC driver" - depends on PCI && WLAN - depends on m - select WIRELESS_EXT - select WEXT_PRIV - select EEPROM_93CX6 - select CRYPTO - ---help--- - If built as a module, it will be called r8187se.ko. diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile deleted file mode 100644 index 91d1aa2..0000000 --- a/drivers/staging/rtl8187se/Makefile +++ /dev/null @@ -1,38 +0,0 @@ - -#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y -#ccflags-y += -std=gnu89 -#ccflags-y += -O2 -#CC = gcc - -ccflags-y := -DSW_ANTE -ccflags-y += -DTX_TRACK -ccflags-y += -DHIGH_POWER -ccflags-y += -DSW_DIG -ccflags-y += -DRATE_ADAPT - -#enable it for legacy power save, disable it for leisure power save -ccflags-y += -DENABLE_LPS - - -#ccflags-y := -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y - -r8187se-y := \ - r8180_core.o \ - r8180_wx.o \ - r8180_rtl8225z2.o \ - r8185b_init.o \ - r8180_dm.o \ - ieee80211/dot11d.o \ - ieee80211/ieee80211_softmac.o \ - ieee80211/ieee80211_rx.o \ - ieee80211/ieee80211_tx.o \ - ieee80211/ieee80211_wx.o \ - ieee80211/ieee80211_module.o \ - ieee80211/ieee80211_softmac_wx.o \ - ieee80211/ieee80211_crypt.o \ - ieee80211/ieee80211_crypt_tkip.o \ - ieee80211/ieee80211_crypt_ccmp.o \ - ieee80211/ieee80211_crypt_wep.o - -obj-$(CONFIG_R8187SE) += r8187se.o - diff --git a/drivers/staging/rtl8187se/Module.symvers b/drivers/staging/rtl8187se/Module.symvers deleted file mode 100644 index e69de29..0000000 --- a/drivers/staging/rtl8187se/Module.symvers +++ /dev/null diff --git a/drivers/staging/rtl8187se/TODO b/drivers/staging/rtl8187se/TODO deleted file mode 100644 index 704949a..0000000 --- a/drivers/staging/rtl8187se/TODO +++ /dev/null @@ -1,13 +0,0 @@ -TODO: -- prepare private ieee80211 stack for merge with rtl8192su's version: - - add hwsec_active flag to struct ieee80211_device - - add bHwSec flag to cb_desc structure -- switch to use shared "librtl" instead of private ieee80211 stack -- switch to use LIB80211 -- switch to use MAC80211 -- use kernel coding style -- checkpatch.pl fixes -- sparse fixes -- integrate with drivers/net/wireless/rtl818x - -Please send any patches to Greg Kroah-Hartman <greg@kroah.com>. diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c deleted file mode 100644 index 4483c2c..0000000 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "dot11d.h" - -void Dot11d_Init(struct ieee80211_device *ieee) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - - pDot11dInfo->bEnabled = 0; - - pDot11dInfo->State = DOT11D_STATE_NONE; - pDot11dInfo->CountryIeLen = 0; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - RESET_CIE_WATCHDOG(ieee); - - netdev_info(ieee->dev, "Dot11d_Init()\n"); -} - -/* Reset to the state as we are just entering a regulatory domain. */ -void Dot11d_Reset(struct ieee80211_device *ieee) -{ - u32 i; - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - - /* Clear old channel map */ - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - /* Set new channel map */ - for (i = 1; i <= 11; i++) - (pDot11dInfo->channel_map)[i] = 1; - - for (i = 12; i <= 14; i++) - (pDot11dInfo->channel_map)[i] = 2; - - pDot11dInfo->State = DOT11D_STATE_NONE; - pDot11dInfo->CountryIeLen = 0; - RESET_CIE_WATCHDOG(ieee); -} - -/* - * Description: - * Update country IE from Beacon or Probe Response and configure PHY for - * operation in the regulatory domain. - * - * TODO: - * Configure Tx power. - * - * Assumption: - * 1. IS_DOT11D_ENABLE() is TRUE. - * 2. Input IE is an valid one. - */ -void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr, - u16 CoutryIeLen, u8 *pCoutryIe) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 i, j, NumTriples, MaxChnlNum; - u8 index, MaxTxPowerInDbm; - PCHNL_TXPOWER_TRIPLE pTriple; - - if ((CoutryIeLen - 3)%3 != 0) { - netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); - Dot11d_Reset(dev); - return; - } - - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - MaxChnlNum = 0; - NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */ - pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); - for (i = 0; i < NumTriples; i++) { - if (MaxChnlNum >= pTriple->FirstChnl) { - /* - * It is not in a monotonically increasing order, - * so stop processing. - */ - netdev_info(dev->dev, - "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); - Dot11d_Reset(dev); - return; - } - if (MAX_CHANNEL_NUMBER < - (pTriple->FirstChnl + pTriple->NumChnls)) { - /* - * It is not a valid set of channel id, - * so stop processing - */ - netdev_info(dev->dev, - "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); - Dot11d_Reset(dev); - return; - } - - for (j = 0; j < pTriple->NumChnls; j++) { - index = pTriple->FirstChnl + j; - pDot11dInfo->channel_map[index] = 1; - MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm; - pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm; - MaxChnlNum = pTriple->FirstChnl + j; - } - - pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3); - } -#if 1 - netdev_info(dev->dev, "Channel List:"); - for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) - if (pDot11dInfo->channel_map[i] > 0) - netdev_info(dev->dev, " %d", i); - netdev_info(dev->dev, "\n"); -#endif - - UPDATE_CIE_SRC(dev, pTaddr); - - pDot11dInfo->CountryIeLen = CoutryIeLen; - memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen); - pDot11dInfo->State = DOT11D_STATE_LEARNED; -} - -u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 MaxTxPwrInDbm = 255; - - if (MAX_CHANNEL_NUMBER < Channel) { - netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); - return MaxTxPwrInDbm; - } - if (pDot11dInfo->channel_map[Channel]) - MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; - - return MaxTxPwrInDbm; -} - - -void DOT11D_ScanComplete(struct ieee80211_device *dev) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - - switch (pDot11dInfo->State) { - case DOT11D_STATE_LEARNED: - pDot11dInfo->State = DOT11D_STATE_DONE; - break; - - case DOT11D_STATE_DONE: - if (GET_CIE_WATCHDOG(dev) == 0) { - /* Reset country IE if previous one is gone. */ - Dot11d_Reset(dev); - } - break; - case DOT11D_STATE_NONE: - break; - } -} - -int IsLegalChannel(struct ieee80211_device *dev, u8 channel) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - - if (MAX_CHANNEL_NUMBER < channel) { - netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n"); - return 0; - } - if (pDot11dInfo->channel_map[channel] > 0) - return 1; - return 0; -} - -int ToLegalChannel(struct ieee80211_device *dev, u8 channel) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 default_chn = 0; - u32 i = 0; - - for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) { - if (pDot11dInfo->channel_map[i] > 0) { - default_chn = i; - break; - } - } - - if (MAX_CHANNEL_NUMBER < channel) { - netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n"); - return default_chn; - } - - if (pDot11dInfo->channel_map[channel] > 0) - return channel; - - return default_chn; -} diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h deleted file mode 100644 index f996691..0000000 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __INC_DOT11D_H -#define __INC_DOT11D_H - -#include "ieee80211.h" - -/* #define ENABLE_DOT11D */ - -/* #define DOT11D_MAX_CHNL_NUM 83 */ - -typedef struct _CHNL_TXPOWER_TRIPLE { - u8 FirstChnl; - u8 NumChnls; - u8 MaxTxPowerInDbm; -} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; - -typedef enum _DOT11D_STATE { - DOT11D_STATE_NONE = 0, - DOT11D_STATE_LEARNED, - DOT11D_STATE_DONE, -} DOT11D_STATE; - -typedef struct _RT_DOT11D_INFO { - /* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */ - - bool bEnabled; /* dot11MultiDomainCapabilityEnabled */ - - u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */ - u8 CountryIeBuf[MAX_IE_LEN]; - u8 CountryIeSrcAddr[6]; /* Source AP of the country IE. */ - u8 CountryIeWatchdog; - - u8 channel_map[MAX_CHANNEL_NUMBER+1]; /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */ - /* u8 ChnlListLen; // #Bytes valid in ChnlList[]. */ - /* u8 ChnlList[DOT11D_MAX_CHNL_NUM]; */ - u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; - - DOT11D_STATE State; -} RT_DOT11D_INFO, *PRT_DOT11D_INFO; - -#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1:0) -#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5]) -#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) - -#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled -#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) - -#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) -#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) - -#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ - (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ - FALSE : \ - (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) - -#define CIE_WATCHDOG_TH 1 -#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog -#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 -#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) - -#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) - -void Dot11d_Init(struct ieee80211_device *dev); -void Dot11d_Reset(struct ieee80211_device *dev); -void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr, - u16 CoutryIeLen, u8 *pCoutryIe); -u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel); -void DOT11D_ScanComplete(struct ieee80211_device *dev); -int IsLegalChannel(struct ieee80211_device *dev, u8 channel); -int ToLegalChannel(struct ieee80211_device *dev, u8 channel); - -#endif /* #ifndef __INC_DOT11D_H */ diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h deleted file mode 100644 index d1763b7..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ /dev/null @@ -1,1496 +0,0 @@ -/* - * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 - * remains copyright by the original authors - * - * Portions of the merged code are based on Host AP (software wireless - * LAN access point) driver for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * <jketreno@linux.intel.com> - * Copyright (c) 2004, Intel Corporation - * - * Modified for Realtek's wi-fi cards by Andrea Merello - * <andrea.merello@gmail.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. See README and COPYING for - * more details. - */ -#ifndef IEEE80211_H -#define IEEE80211_H -#include <linux/if_ether.h> /* ETH_ALEN */ -#include <linux/kernel.h> /* ARRAY_SIZE */ -#include <linux/jiffies.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/semaphore.h> -#include <linux/wireless.h> -#include <linux/ieee80211.h> -#include <linux/interrupt.h> - -#define KEY_TYPE_NA 0x0 -#define KEY_TYPE_WEP40 0x1 -#define KEY_TYPE_TKIP 0x2 -#define KEY_TYPE_CCMP 0x4 -#define KEY_TYPE_WEP104 0x5 - -#define aSifsTime 10 - -#define MGMT_QUEUE_NUM 5 - - -#define IEEE_CMD_SET_WPA_PARAM 1 -#define IEEE_CMD_SET_WPA_IE 2 -#define IEEE_CMD_SET_ENCRYPTION 3 -#define IEEE_CMD_MLME 4 - -#define IEEE_PARAM_WPA_ENABLED 1 -#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 -#define IEEE_PARAM_DROP_UNENCRYPTED 3 -#define IEEE_PARAM_PRIVACY_INVOKED 4 -#define IEEE_PARAM_AUTH_ALGS 5 -#define IEEE_PARAM_IEEE_802_1X 6 -//It should consistent with the driver_XXX.c -// David, 2006.9.26 -#define IEEE_PARAM_WPAX_SELECT 7 -//Added for notify the encryption type selection -// David, 2006.9.26 -#define IEEE_PROTO_WPA 1 -#define IEEE_PROTO_RSN 2 -//Added for notify the encryption type selection -// David, 2006.9.26 -#define IEEE_WPAX_USEGROUP 0 -#define IEEE_WPAX_WEP40 1 -#define IEEE_WPAX_TKIP 2 -#define IEEE_WPAX_WRAP 3 -#define IEEE_WPAX_CCMP 4 -#define IEEE_WPAX_WEP104 5 - -#define IEEE_KEY_MGMT_IEEE8021X 1 -#define IEEE_KEY_MGMT_PSK 2 - - - -#define IEEE_MLME_STA_DEAUTH 1 -#define IEEE_MLME_STA_DISASSOC 2 - - -#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 -#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 -#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 -#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 - - -#define IEEE_CRYPT_ALG_NAME_LEN 16 - -extern int ieee80211_crypto_tkip_init(void); -extern void ieee80211_crypto_tkip_exit(void); - -//by amy for ps -typedef struct ieee_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[0]; - } wpa_ie; - struct{ - int command; - int reason_code; - } mlme; - struct { - u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - - } u; -}ieee_param; - - -#define MSECS(t) msecs_to_jiffies(t) -#define msleep_interruptible_rtl msleep_interruptible - -#define IEEE80211_DATA_LEN 2304 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - The figure in section 7.1.2 suggests a body size of up to 2312 - bytes is allowed, which is a bit confusing, I suspect this - represents the 2304 bytes of real data, plus a possible 8 bytes of - WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ - -#define IEEE80211_3ADDR_LEN 24 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_FCS_LEN 4 -#define IEEE80211_HLEN IEEE80211_4ADDR_LEN -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) -#define IEEE80211_MGMT_HDR_LEN 24 -#define IEEE80211_DATA_HDR3_LEN 24 -#define IEEE80211_DATA_HDR4_LEN 30 - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* Frame control field constants */ -#define IEEE80211_FCTL_DSTODS 0x0300 //added by david -#define IEEE80211_FCTL_WEP 0x4000 - -/* debug macros */ - -#ifdef CONFIG_IEEE80211_DEBUG -extern u32 ieee80211_debug_level; -#define IEEE80211_DEBUG(level, fmt, args...) \ -do { if (ieee80211_debug_level & (level)) \ - printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) -#else -#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) -#endif /* CONFIG_IEEE80211_DEBUG */ - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IEEE80211_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your - * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/ipw/debug_level - * - * you simply need to add your entry to the ipw_debug_levels array. - * - * If you do not see debug_level in /proc/net/ipw then you do not have - * CONFIG_IEEE80211_DEBUG defined in your kernel configuration - * - */ - -#define IEEE80211_DL_INFO (1<<0) -#define IEEE80211_DL_WX (1<<1) -#define IEEE80211_DL_SCAN (1<<2) -#define IEEE80211_DL_STATE (1<<3) -#define IEEE80211_DL_MGMT (1<<4) -#define IEEE80211_DL_FRAG (1<<5) -#define IEEE80211_DL_EAP (1<<6) -#define IEEE80211_DL_DROP (1<<7) - -#define IEEE80211_DL_TX (1<<8) -#define IEEE80211_DL_RX (1<<9) - -#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) -#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) -#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) - -#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) -#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) -//#define IEEE_DEBUG_SCAN IEEE80211_WARNING -#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) -#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) -#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) -#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) -#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) -#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) -#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) -#include <linux/netdevice.h> -#include <linux/if_arp.h> /* ARPHRD_ETHER */ - -#ifndef WIRELESS_SPY -#define WIRELESS_SPY // enable iwspy support -#endif -#include <net/iw_handler.h> // new driver API - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ - -} __attribute__ ((packed)); - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ) - -#define WLAN_CAPABILITY_BSS (1<<0) -#define WLAN_CAPABILITY_SHORT_SLOT (1<<10) - -#define IEEE80211_STATMASK_SIGNAL (1<<0) -#define IEEE80211_STATMASK_RSSI (1<<1) -#define IEEE80211_STATMASK_NOISE (1<<2) -#define IEEE80211_STATMASK_RATE (1<<3) -#define IEEE80211_STATMASK_WEMASK 0x7 - - -#define IEEE80211_CCK_MODULATION (1<<0) -#define IEEE80211_OFDM_MODULATION (1<<1) - -#define IEEE80211_24GHZ_BAND (1<<0) -#define IEEE80211_52GHZ_BAND (1<<1) - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_LEN 8 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - -/* this is stolen and modified from the madwifi driver*/ -#define IEEE80211_FC0_TYPE_MASK 0x0c -#define IEEE80211_FC0_TYPE_DATA 0x08 -#define IEEE80211_FC0_SUBTYPE_MASK 0xB0 -#define IEEE80211_FC0_SUBTYPE_QOS 0x80 - -#define IEEE80211_QOS_HAS_SEQ(fc) \ - (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \ - (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) - -/* this is stolen from ipw2200 driver */ -#define IEEE_IBSS_MAC_HASH_SIZE 31 -struct ieee_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num[17]; - u16 frag_num[17]; - unsigned long packet_time[17]; - struct list_head list; -}; - -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. */ -struct ieee80211_rx_stats { - u32 mac_time[2]; - u8 signalstrength; - s8 rssi; - u8 signal; - u8 noise; - u16 rate; /* in 100 kbps */ - u8 received_channel; - u8 control; - u8 mask; - u8 freq; - u16 len; - u8 nic_type; -}; - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -#define IEEE80211_FRAG_CACHE_LEN 4 - -struct ieee80211_frag_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int last_frag; - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct ieee80211_stats { - unsigned int tx_unicast_frames; - unsigned int tx_multicast_frames; - unsigned int tx_fragments; - unsigned int tx_unicast_octets; - unsigned int tx_multicast_octets; - unsigned int tx_deferred_transmissions; - unsigned int tx_single_retry_frames; - unsigned int tx_multiple_retry_frames; - unsigned int tx_retry_limit_exceeded; - unsigned int tx_discards; - unsigned int rx_unicast_frames; - unsigned int rx_multicast_frames; - unsigned int rx_fragments; - unsigned int rx_unicast_octets; - unsigned int rx_multicast_octets; - unsigned int rx_fcs_errors; - unsigned int rx_discards_no_buffer; - unsigned int tx_discards_wrong_sa; - unsigned int rx_discards_undecryptable; - unsigned int rx_message_in_msg_fragments; - unsigned int rx_message_in_bad_msg_fragments; -}; - -struct ieee80211_device; - -#include "ieee80211_crypt.h" - -#define SEC_KEY_1 (1<<0) -#define SEC_KEY_2 (1<<1) -#define SEC_KEY_3 (1<<2) -#define SEC_KEY_4 (1<<3) -#define SEC_ACTIVE_KEY (1<<4) -#define SEC_AUTH_MODE (1<<5) -#define SEC_UNICAST_GROUP (1<<6) -#define SEC_LEVEL (1<<7) -#define SEC_ENABLED (1<<8) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - -#define WEP_KEYS 4 -#define WEP_KEY_LEN 13 - -#define WEP_KEY_LEN_MODIF 32 - -struct ieee80211_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][WEP_KEY_LEN_MODIF]; - u8 level; - u16 flags; -} __attribute__ ((packed)); - - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -/* Management Frame Information Element Types */ -enum { - MFIE_TYPE_SSID = 0, - MFIE_TYPE_RATES = 1, - MFIE_TYPE_FH_SET = 2, - MFIE_TYPE_DS_SET = 3, - MFIE_TYPE_CF_SET = 4, - MFIE_TYPE_TIM = 5, - MFIE_TYPE_IBSS_SET = 6, - MFIE_TYPE_COUNTRY = 7, - MFIE_TYPE_CHALLENGE = 16, - MFIE_TYPE_ERP = 42, - MFIE_TYPE_RSN = 48, - MFIE_TYPE_RATES_EX = 50, - MFIE_TYPE_GENERIC = 221, -}; - -struct ieee80211_header_data { - __le16 frame_ctl; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}; - -struct ieee80211_hdr_4addr { - __le16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; -} __attribute__ ((packed)); - -struct ieee80211_hdr_3addrqos { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u16 qos_ctl; -} __attribute__ ((packed)); - -struct ieee80211_hdr_4addrqos { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; - u16 qos_ctl; -} __attribute__ ((packed)); - -struct ieee80211_info_element_hdr { - u8 id; - u8 len; -} __attribute__ ((packed)); - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __attribute__ ((packed)); - -struct ieee80211_authentication { - struct ieee80211_header_data header; - u16 algorithm; - u16 transaction; - u16 status; - //struct ieee80211_info_element_hdr info_element; -} __attribute__ ((packed)); - -struct ieee80211_disassoc_frame { - struct ieee80211_hdr_3addr header; - u16 reasoncode; -} __attribute__ ((packed)); - -struct ieee80211_probe_request { - struct ieee80211_header_data header; - /* struct ieee80211_info_element info_element; */ -} __attribute__ ((packed)); - -struct ieee80211_probe_response { - struct ieee80211_header_data header; - u32 time_stamp[2]; - u16 beacon_interval; - u16 capability; - struct ieee80211_info_element info_element; -} __attribute__ ((packed)); - -struct ieee80211_assoc_request_frame { - struct ieee80211_hdr_3addr header; - u16 capability; - u16 listen_interval; - //u8 current_ap[ETH_ALEN]; - struct ieee80211_info_element_hdr info_element; -} __attribute__ ((packed)); - -struct ieee80211_assoc_response_frame { - struct ieee80211_hdr_3addr header; - u16 capability; - u16 status; - u16 aid; - struct ieee80211_info_element info_element; /* supported rates */ -} __attribute__ ((packed)); - -struct ieee80211_txb { - u8 nr_frags; - u8 encrypted; - u16 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[0]; -}; - -/* SWEEP TABLE ENTRIES NUMBER */ -#define MAX_SWEEP_TAB_ENTRIES 42 -#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 - -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) - -#define MAX_NETWORK_COUNT 128 - -#define MAX_CHANNEL_NUMBER 165 - -#define IEEE80211_SOFTMAC_SCAN_TIME 100 /* (HZ / 2) */ -#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) - -#define CRC_LENGTH 4U - -#define MAX_WPA_IE_LEN 64 - -#define NETWORK_EMPTY_ESSID (1 << 0) -#define NETWORK_HAS_OFDM (1 << 1) -#define NETWORK_HAS_CCK (1 << 2) - -struct ieee80211_wmm_ac_param { - u8 ac_aci_acm_aifsn; - u8 ac_ecwmin_ecwmax; - u16 ac_txop_limit; -}; - -struct ieee80211_wmm_ts_info { - u8 ac_dir_tid; - u8 ac_up_psb; - u8 reserved; -} __attribute__ ((packed)); - -struct ieee80211_wmm_tspec_elem { - struct ieee80211_wmm_ts_info ts_info; - u16 norm_msdu_size; - u16 max_msdu_size; - u32 min_serv_inter; - u32 max_serv_inter; - u32 inact_inter; - u32 suspen_inter; - u32 serv_start_time; - u32 min_data_rate; - u32 mean_data_rate; - u32 peak_data_rate; - u32 max_burst_size; - u32 delay_bound; - u32 min_phy_rate; - u16 surp_band_allow; - u16 medium_time; -}__attribute__((packed)); - -enum eap_type { - EAP_PACKET = 0, - EAPOL_START, - EAPOL_LOGOFF, - EAPOL_KEY, - EAPOL_ENCAP_ASF_ALERT -}; - -static const char *eap_types[] = { - [EAP_PACKET] = "EAP-Packet", - [EAPOL_START] = "EAPOL-Start", - [EAPOL_LOGOFF] = "EAPOL-Logoff", - [EAPOL_KEY] = "EAPOL-Key", - [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" -}; - -static inline const char *eap_get_type(int type) -{ - return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; -} - -struct eapol { - u8 snap[6]; - u16 ethertype; - u8 version; - u8 type; - u16 length; -} __attribute__ ((packed)); - -struct ieee80211_softmac_stats { - unsigned int rx_ass_ok; - unsigned int rx_ass_err; - unsigned int rx_probe_rq; - unsigned int tx_probe_rs; - unsigned int tx_beacons; - unsigned int rx_auth_rq; - unsigned int rx_auth_rs_ok; - unsigned int rx_auth_rs_err; - unsigned int tx_auth_rq; - unsigned int no_auth_rs; - unsigned int no_ass_rs; - unsigned int tx_ass_rq; - unsigned int rx_ass_rq; - unsigned int tx_probe_rq; - unsigned int reassoc; - unsigned int swtxstop; - unsigned int swtxawake; -}; - -#define BEACON_PROBE_SSID_ID_POSITION 12 - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __attribute__ ((packed)); - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - -#define IEEE80211_DEFAULT_TX_ESSID "Penguin" -#define IEEE80211_DEFAULT_BASIC_RATE 10 - -enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; -#define MAX_SP_Len (WMM_all_frame << 4) -#define IEEE80211_QOS_TID 0x0f -#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) - -#define MAX_IE_LEN 0xFF //+YJ,080625 - -struct rtl8187se_channel_list { - u8 channel[MAX_CHANNEL_NUMBER + 1]; - u8 len; -}; - -//by amy for ps -#define IEEE80211_WATCH_DOG_TIME 2000 -//by amy for ps -//by amy for antenna -#define ANTENNA_DIVERSITY_TIMER_PERIOD 1000 // 1000 m -//by amy for antenna - -#define IEEE80211_DTIM_MBCAST 4 -#define IEEE80211_DTIM_UCAST 2 -#define IEEE80211_DTIM_VALID 1 -#define IEEE80211_DTIM_INVALID 0 - -#define IEEE80211_PS_DISABLED 0 -#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST -#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST -#define IEEE80211_PS_ENABLE IEEE80211_DTIM_VALID -//added by David for QoS 2006/6/30 -//#define WMM_Hang_8187 -#ifdef WMM_Hang_8187 -#undef WMM_Hang_8187 -#endif - -#define WME_AC_BE 0x00 -#define WME_AC_BK 0x01 -#define WME_AC_VI 0x02 -#define WME_AC_VO 0x03 -#define WME_ACI_MASK 0x03 -#define WME_AIFSN_MASK 0x03 -#define WME_AC_PRAM_LEN 16 - -//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP -//#define UP2AC(up) ((up<3) ? ((up==0)?1:0) : (up>>1)) -#define UP2AC(up) ( \ - ((up) < 1) ? WME_AC_BE : \ - ((up) < 3) ? WME_AC_BK : \ - ((up) < 4) ? WME_AC_BE : \ - ((up) < 6) ? WME_AC_VI : \ - WME_AC_VO) -//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue -#define AC2UP(_ac) ( \ - ((_ac) == WME_AC_VO) ? 6 : \ - ((_ac) == WME_AC_VI) ? 5 : \ - ((_ac) == WME_AC_BK) ? 1 : \ - 0) - -#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ -struct ether_header { - u8 ether_dhost[ETHER_ADDR_LEN]; - u8 ether_shost[ETHER_ADDR_LEN]; - u16 ether_type; -} __attribute__((packed)); - -#ifndef ETHERTYPE_PAE -#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ -#endif -#ifndef ETHERTYPE_IP -#define ETHERTYPE_IP 0x0800 /* IP protocol */ -#endif - -struct ieee80211_network { - /* These entries are used to identify a unique network */ - u8 bssid[ETH_ALEN]; - u8 channel; - /* Ensure null-terminated for any debug msgs */ - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - /* These are network statistics */ - struct ieee80211_rx_stats stats; - u16 capability; - u8 rates[MAX_RATES_LENGTH]; - u8 rates_len; - u8 rates_ex[MAX_RATES_EX_LENGTH]; - u8 rates_ex_len; - unsigned long last_scanned; - u8 mode; - u8 flags; - u32 last_associate; - u32 time_stamp[2]; - u16 beacon_interval; - u16 listen_interval; - u16 atim_window; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - u8 dtim_period; - u8 dtim_data; - u32 last_dtim_sta_time[2]; - struct list_head list; - //appeded for QoS - u8 wmm_info; - struct ieee80211_wmm_ac_param wmm_param[4]; - u8 QoS_Enable; - u8 SignalStrength; -//by amy 080312 - u8 HighestOperaRate; -//by amy 080312 - u8 Turbo_Enable;//enable turbo mode, added by thomas - u16 CountryIeLen; - u8 CountryIeBuf[MAX_IE_LEN]; -}; - -enum ieee80211_state { - - /* the card is not linked at all */ - IEEE80211_NOLINK = 0, - - /* IEEE80211_ASSOCIATING* are for BSS client mode - * the driver shall not perform RX filtering unless - * the state is LINKED. - * The driver shall just check for the state LINKED and - * defaults to NOLINK for ALL the other states (including - * LINKED_SCANNING) - */ - - /* the association procedure will start (wq scheduling)*/ - IEEE80211_ASSOCIATING, - IEEE80211_ASSOCIATING_RETRY, - - /* the association procedure is sending AUTH request*/ - IEEE80211_ASSOCIATING_AUTHENTICATING, - - /* the association procedure has successfully authenticated - * and is sending association request - */ - IEEE80211_ASSOCIATING_AUTHENTICATED, - - /* the link is ok. the card associated to a BSS or linked - * to a ibss cell or acting as an AP and creating the bss - */ - IEEE80211_LINKED, - - /* same as LINKED, but the driver shall apply RX filter - * rules as we are in NO_LINK mode. As the card is still - * logically linked, but it is doing a syncro site survey - * then it will be back to LINKED state. - */ - IEEE80211_LINKED_SCANNING, - -}; - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 - -#define CFG_IEEE80211_RESERVE_FCS (1<<0) -#define CFG_IEEE80211_COMPUTE_FCS (1<<1) - -typedef struct tx_pending_t{ - int frag; - struct ieee80211_txb *txb; -}tx_pending_t; - -enum { - COUNTRY_CODE_FCC = 0, - COUNTRY_CODE_IC = 1, - COUNTRY_CODE_ETSI = 2, - COUNTRY_CODE_SPAIN = 3, - COUNTRY_CODE_FRANCE = 4, - COUNTRY_CODE_MKK = 5, - COUNTRY_CODE_MKK1 = 6, - COUNTRY_CODE_ISRAEL = 7, - COUNTRY_CODE_TELEC = 8, - COUNTRY_CODE_GLOBAL_DOMAIN = 9, - COUNTRY_CODE_WORLD_WIDE_13_INDEX = 10 -}; - -struct ieee80211_device { - struct net_device *dev; - - /* Bookkeeping structures */ - struct net_device_stats stats; - struct ieee80211_stats ieee_stats; - struct ieee80211_softmac_stats softmac_stats; - - /* Probe / Beacon management */ - struct list_head network_free_list; - struct list_head network_list; - struct ieee80211_network *networks; - int scans; - int scan_age; - - int iw_mode; /* operating mode (IW_MODE_*) */ - - spinlock_t lock; - spinlock_t wpax_suitlist_lock; - - int tx_headroom; /* Set to size of any additional room needed at front - * of allocated Tx SKBs */ - u32 config; - - /* WEP and other encryption related settings at the device level */ - int open_wep; /* Set to 1 to allow unencrypted frames */ - - int reset_on_keychange; /* Set to 1 if the HW needs to be reset on - * WEP key changes */ - - /* If the host performs {en,de}cryption, then set to 1 */ - int host_encrypt; - int host_decrypt; - int ieee802_1x; /* is IEEE 802.1X used */ - - /* WPA data */ - int wpa_enabled; - int drop_unencrypted; - int tkip_countermeasures; - int privacy_invoked; - size_t wpa_ie_len; - u8 *wpa_ie; - - u8 ap_mac_addr[6]; - u16 pairwise_key_type; - u16 broadcast_key_type; - - struct list_head crypt_deinit_list; - struct ieee80211_crypt_data *crypt[WEP_KEYS]; - int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ - struct timer_list crypt_deinit_timer; - - int bcrx_sta_key; /* use individual keys to override default keys even - * with RX of broad/multicast frames */ - - /* Fragmentation structures */ - /* each stream contains an entry */ - struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN]; - unsigned int frag_next_idx[17]; - u16 fts; /* Fragmentation Threshold */ - - /* This stores infos for the current network. - * Either the network we are associated in INFRASTRUCTURE - * or the network that we are creating in MASTER mode. - * ad-hoc is a mixture ;-). - * Note that in infrastructure mode, even when not associated, - * fields bssid and essid may be valid (if wpa_set and essid_set - * are true) as thy carry the value set by the user via iwconfig - */ - struct ieee80211_network current_network; - - - enum ieee80211_state state; - - int short_slot; - int mode; /* A, B, G */ - int modulation; /* CCK, OFDM */ - int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ - int abg_true; /* ABG flag */ - - /* used for forcing the ibss workqueue to terminate - * without wait for the syncro scan to terminate - */ - short sync_scan_hurryup; - - void * pDot11dInfo; - bool bGlobalDomain; - - // For Liteon Ch12~13 passive scan - u8 MinPassiveChnlNum; - u8 IbssStartChnl; - - int rate; /* current rate */ - int basic_rate; - //FIXME: please callback, see if redundant with softmac_features - short active_scan; - - /* this contains flags for selectively enable softmac support */ - u16 softmac_features; - - /* if the sequence control field is not filled by HW */ - u16 seq_ctrl[5]; - - /* association procedure transaction sequence number */ - u16 associate_seq; - - /* AID for RTXed association responses */ - u16 assoc_id; - - /* power save mode related*/ - short ps; - short sta_sleep; - int ps_timeout; - struct tasklet_struct ps_task; - u32 ps_th; - u32 ps_tl; - - short raw_tx; - /* used if IEEE_SOFTMAC_TX_QUEUE is set */ - short queue_stop; - short scanning; - short proto_started; - - struct semaphore wx_sem; - struct semaphore scan_sem; - - spinlock_t mgmt_tx_lock; - spinlock_t beacon_lock; - - short beacon_txing; - - short wap_set; - short ssid_set; - - u8 wpax_type_set; //{added by David, 2006.9.28} - u32 wpax_type_notify; //{added by David, 2006.9.26} - - /* QoS related flag */ - char init_wmmparam_flag; - - /* for discarding duplicated packets in IBSS */ - struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; - - /* for discarding duplicated packets in BSS */ - u16 last_rxseq_num[17]; /* rx seq previous per-tid */ - u16 last_rxfrag_num[17];/* tx frag previous per-tid */ - unsigned long last_packet_time[17]; - - /* for PS mode */ - unsigned long last_rx_ps_time; - - /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ - struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; - int mgmt_queue_head; - int mgmt_queue_tail; - - - /* used if IEEE_SOFTMAC_TX_QUEUE is set */ - struct tx_pending_t tx_pending; - - /* used if IEEE_SOFTMAC_ASSOCIATE is set */ - struct timer_list associate_timer; - - /* used if IEEE_SOFTMAC_BEACONS is set */ - struct timer_list beacon_timer; - - struct work_struct associate_complete_wq; -// struct work_struct associate_retry_wq; - struct work_struct associate_procedure_wq; -// struct work_struct softmac_scan_wq; - struct work_struct wx_sync_scan_wq; - struct work_struct wmm_param_update_wq; - struct work_struct ps_request_tx_ack_wq;//for ps -// struct work_struct hw_wakeup_wq; -// struct work_struct hw_sleep_wq; -// struct work_struct watch_dog_wq; - bool bInactivePs; - bool actscanning; - bool beinretry; - u16 ListenInterval; - unsigned long NumRxDataInPeriod; //YJ,add,080828 - unsigned long NumRxBcnInPeriod; //YJ,add,080828 - unsigned long NumRxOkTotal; - unsigned long NumRxUnicast;//YJ,add,080828,for keep alive - bool bHwRadioOff; - struct delayed_work softmac_scan_wq; - struct delayed_work associate_retry_wq; - struct delayed_work hw_wakeup_wq; - struct delayed_work hw_sleep_wq;//+by amy 080324 - struct delayed_work watch_dog_wq; - struct delayed_work sw_antenna_wq; - struct delayed_work start_ibss_wq; -//by amy for rate adaptive 080312 - struct delayed_work rate_adapter_wq; -//by amy for rate adaptive - struct delayed_work hw_dig_wq; - struct delayed_work tx_pw_wq; - -//Added for RF power on power off by lizhaoming 080512 - struct delayed_work GPIOChangeRFWorkItem; - - struct workqueue_struct *wq; - - /* Callback functions */ - void (*set_security)(struct net_device *dev, - struct ieee80211_security *sec); - - /* Used to TX data frame by using txb structs. - * this is not used if in the softmac_features - * is set the flag IEEE_SOFTMAC_TX_QUEUE - */ - int (*hard_start_xmit)(struct ieee80211_txb *txb, - struct net_device *dev); - - int (*reset_port)(struct net_device *dev); - - /* Softmac-generated frames (management) are TXed via this - * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is - * not set. As some cards may have different HW queues that - * one might want to use for data and management frames - * the option to have two callbacks might be useful. - * This function can't sleep. - */ - int (*softmac_hard_start_xmit)(struct sk_buff *skb, - struct net_device *dev); - - /* used instead of hard_start_xmit (not softmac_hard_start_xmit) - * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data - * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set - * then also management frames are sent via this callback. - * This function can't sleep. - */ - void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, - struct net_device *dev,int rate); - - /* stops the HW queue for DATA frames. Useful to avoid - * waste time to TX data frame when we are reassociating - * This function can sleep. - */ - void (*data_hard_stop)(struct net_device *dev); - - /* OK this is complementar to data_poll_hard_stop */ - void (*data_hard_resume)(struct net_device *dev); - - /* ask to the driver to retune the radio . - * This function can sleep. the driver should ensure - * the radio has been switched before return. - */ - void (*set_chan)(struct net_device *dev,short ch); - - /* These are not used if the ieee stack takes care of - * scanning (IEEE_SOFTMAC_SCAN feature set). - * In this case only the set_chan is used. - * - * The syncro version is similar to the start_scan but - * does not return until all channels has been scanned. - * this is called in user context and should sleep, - * it is called in a work_queue when switching to ad-hoc mode - * or in behalf of iwlist scan when the card is associated - * and root user ask for a scan. - * the function stop_scan should stop both the syncro and - * background scanning and can sleep. - * The function start_scan should initiate the background - * scanning and can't sleep. - */ - void (*scan_syncro)(struct net_device *dev); - void (*start_scan)(struct net_device *dev); - void (*stop_scan)(struct net_device *dev); - - /* indicate the driver that the link state is changed - * for example it may indicate the card is associated now. - * Driver might be interested in this to apply RX filter - * rules or simply light the LINK led - */ - void (*link_change)(struct net_device *dev); - - /* these two function indicates to the HW when to start - * and stop to send beacons. This is used when the - * IEEE_SOFTMAC_BEACONS is not set. For now the - * stop_send_bacons is NOT guaranteed to be called only - * after start_send_beacons. - */ - void (*start_send_beacons) (struct net_device *dev); - void (*stop_send_beacons) (struct net_device *dev); - - /* power save mode related */ - void (*sta_wake_up) (struct net_device *dev); - void (*ps_request_tx_ack) (struct net_device *dev); - void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl); - short (*ps_is_queue_empty) (struct net_device *dev); - - /* QoS related */ - //void (*wmm_param_update) (struct net_device *dev, u8 *ac_param); - //void (*wmm_param_update) (struct ieee80211_device *ieee); - - /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_ieee80211 */ - u8 priv[0]; -}; - -#define IEEE_A (1<<0) -#define IEEE_B (1<<1) -#define IEEE_G (1<<2) -#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) - -/* Generate a 802.11 header */ - -/* Uses the channel change callback directly - * instead of [start/stop] scan callbacks - */ -#define IEEE_SOFTMAC_SCAN (1<<2) - -/* Perform authentication and association handshake */ -#define IEEE_SOFTMAC_ASSOCIATE (1<<3) - -/* Generate probe requests */ -#define IEEE_SOFTMAC_PROBERQ (1<<4) - -/* Generate response to probe requests */ -#define IEEE_SOFTMAC_PROBERS (1<<5) - -/* The ieee802.11 stack will manages the netif queue - * wake/stop for the driver, taking care of 802.11 - * fragmentation. See softmac.c for details. */ -#define IEEE_SOFTMAC_TX_QUEUE (1<<7) - -/* Uses only the softmac_data_hard_start_xmit - * even for TX management frames. - */ -#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8) - -/* Generate beacons. The stack will enqueue beacons - * to the card - */ -#define IEEE_SOFTMAC_BEACONS (1<<6) - - - -static inline void *ieee80211_priv(struct net_device *dev) -{ - return ((struct ieee80211_device *)netdev_priv(dev))->priv; -} - -static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - - return 1; -} - -static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, - int mode) -{ - /* - * It is possible for both access points and our device to support - * combinations of modes, so as long as there is one valid combination - * of ap/device supported modes, then return success - * - */ - if ((mode & IEEE_A) && - (ieee->modulation & IEEE80211_OFDM_MODULATION) && - (ieee->freq_band & IEEE80211_52GHZ_BAND)) - return 1; - - if ((mode & IEEE_G) && - (ieee->modulation & IEEE80211_OFDM_MODULATION) && - (ieee->freq_band & IEEE80211_24GHZ_BAND)) - return 1; - - if ((mode & IEEE_B) && - (ieee->modulation & IEEE80211_CCK_MODULATION) && - (ieee->freq_band & IEEE80211_24GHZ_BAND)) - return 1; - - return 0; -} - -static inline int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (WLAN_FC_GET_TYPE(fc)) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = 30; /* Addr4 */ - if(IEEE80211_QOS_HAS_SEQ(fc)) - hdrlen += 2; /* QOS ctrl*/ - break; - case IEEE80211_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - default: - hdrlen = 16; - break; - } - break; - } - - return hdrlen; -} - - - -/* ieee80211.c */ -extern void free_ieee80211(struct net_device *dev); -extern struct net_device *alloc_ieee80211(int sizeof_priv); - -extern int ieee80211_set_encryption(struct ieee80211_device *ieee); - -/* ieee80211_tx.c */ - -extern int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, - struct sk_buff *frag, int hdr_len); - -extern int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev); -extern void ieee80211_txb_free(struct ieee80211_txb *); - - -/* ieee80211_rx.c */ -extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats); -extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header, - struct ieee80211_rx_stats *stats); - -/* ieee80211_wx.c */ -extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -int ieee80211_wx_set_auth(struct ieee80211_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra); -int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); -/* ieee80211_softmac.c */ -extern short ieee80211_is_54g(const struct ieee80211_network *net); -extern short ieee80211_is_shortslot(const struct ieee80211_network *net); -extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, - struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, - u16 type, u16 stype); -extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, - struct ieee80211_network *net); - -extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, - struct ieee80211_device *ieee); -extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee); -extern void ieee80211_start_bss(struct ieee80211_device *ieee); -extern void ieee80211_start_master_bss(struct ieee80211_device *ieee); -extern void ieee80211_start_ibss(struct ieee80211_device *ieee); -extern void ieee80211_softmac_init(struct ieee80211_device *ieee); -extern void ieee80211_softmac_free(struct ieee80211_device *ieee); -extern void ieee80211_associate_abort(struct ieee80211_device *ieee); -extern void ieee80211_disassociate(struct ieee80211_device *ieee); -extern void ieee80211_stop_scan(struct ieee80211_device *ieee); -extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee); -extern void ieee80211_check_all_nets(struct ieee80211_device *ieee); -extern void ieee80211_start_protocol(struct ieee80211_device *ieee); -extern void ieee80211_stop_protocol(struct ieee80211_device *ieee); -extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); -extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); -extern void ieee80211_reset_queue(struct ieee80211_device *ieee); -extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); -extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); -extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); -extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); -extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, - struct iw_point *p); -extern void notify_wx_assoc_event(struct ieee80211_device *ieee); -extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); -extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, - u8 asRsn); -extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee); - -//Add for RF power on power off by lizhaoming 080512 -extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, - u8 asRsn); - -/* ieee80211_crypt_ccmp&tkip&wep.c */ -extern void ieee80211_tkip_null(void); -extern void ieee80211_wep_null(void); -extern void ieee80211_ccmp_null(void); -/* ieee80211_softmac_wx.c */ - -extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *ext); - -extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra); - -extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern void ieee80211_wx_sync_scan_wq(struct work_struct *work); - -extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_name(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee); - -extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, - short pwr); - -extern const long ieee80211_wlan_frequencies[]; - -extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) -{ - ieee->scans++; -} - -extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) -{ - return ieee->scans; -} - -static inline const char *escape_essid(const char *essid, u8 essid_len) { - static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - const char *s = essid; - char *d = escaped; - - if (ieee80211_is_empty_essid(essid, essid_len)) { - memcpy(escaped, "<hidden>", sizeof("<hidden>")); - return escaped; - } - - essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); - while (essid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { - *d++ = *s++; - } - } - *d = '\0'; - return escaped; -} -#endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c deleted file mode 100644 index 101f0c0..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Host AP crypto routines - * - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -//#include <linux/config.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/errno.h> - -#include "ieee80211.h" - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("HostAP crypto"); -MODULE_LICENSE("GPL"); - -struct ieee80211_crypto_alg { - struct list_head list; - struct ieee80211_crypto_ops *ops; -}; - - -struct ieee80211_crypto { - struct list_head algs; - spinlock_t lock; -}; - -static struct ieee80211_crypto *hcrypt; - -void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) -{ - struct list_head *ptr, *n; - struct ieee80211_crypt_data *entry; - - for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; - ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { - entry = list_entry(ptr, struct ieee80211_crypt_data, list); - - if (atomic_read(&entry->refcnt) != 0 && !force) - continue; - - list_del(ptr); - - if (entry->ops) - entry->ops->deinit(entry->priv); - kfree(entry); - } -} - -void ieee80211_crypt_deinit_handler(unsigned long data) -{ - struct ieee80211_device *ieee = (struct ieee80211_device *)data; - unsigned long flags; - - spin_lock_irqsave(&ieee->lock, flags); - ieee80211_crypt_deinit_entries(ieee, 0); - if (!list_empty(&ieee->crypt_deinit_list)) { - pr_debug("entries remaining in delayed crypt deletion list\n"); - ieee->crypt_deinit_timer.expires = jiffies + HZ; - add_timer(&ieee->crypt_deinit_timer); - } - spin_unlock_irqrestore(&ieee->lock, flags); - -} - -void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, - struct ieee80211_crypt_data **crypt) -{ - struct ieee80211_crypt_data *tmp; - unsigned long flags; - - if (*crypt == NULL) - return; - - tmp = *crypt; - *crypt = NULL; - - /* must not run ops->deinit() while there may be pending encrypt or - * decrypt operations. Use a list of delayed deinits to avoid needing - * locking. */ - - spin_lock_irqsave(&ieee->lock, flags); - list_add(&tmp->list, &ieee->crypt_deinit_list); - if (!timer_pending(&ieee->crypt_deinit_timer)) { - ieee->crypt_deinit_timer.expires = jiffies + HZ; - add_timer(&ieee->crypt_deinit_timer); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) -{ - unsigned long flags; - struct ieee80211_crypto_alg *alg; - - if (hcrypt == NULL) - return -1; - - alg = kzalloc(sizeof(*alg), GFP_KERNEL); - if (alg == NULL) - return -ENOMEM; - - alg->ops = ops; - - spin_lock_irqsave(&hcrypt->lock, flags); - list_add(&alg->list, &hcrypt->algs); - spin_unlock_irqrestore(&hcrypt->lock, flags); - - pr_debug("registered algorithm '%s'\n", ops->name); - - return 0; -} - -int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) -{ - unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *del_alg = NULL; - - if (hcrypt == NULL) - return -1; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *) ptr; - if (alg->ops == ops) { - list_del(&alg->list); - del_alg = alg; - break; - } - } - spin_unlock_irqrestore(&hcrypt->lock, flags); - - if (del_alg) { - pr_debug("unregistered algorithm '%s'\n", ops->name); - kfree(del_alg); - } - - return del_alg ? 0 : -1; -} - - -struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) -{ - unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *found_alg = NULL; - - if (hcrypt == NULL) - return NULL; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *) ptr; - if (strcmp(alg->ops->name, name) == 0) { - found_alg = alg; - break; - } - } - spin_unlock_irqrestore(&hcrypt->lock, flags); - - if (found_alg) - return found_alg->ops; - else - return NULL; -} - - -static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } -static void ieee80211_crypt_null_deinit(void *priv) {} - -static struct ieee80211_crypto_ops ieee80211_crypt_null = { - .name = "NULL", - .init = ieee80211_crypt_null_init, - .deinit = ieee80211_crypt_null_deinit, - .encrypt_mpdu = NULL, - .decrypt_mpdu = NULL, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = NULL, - .get_key = NULL, - .extra_prefix_len = 0, - .extra_postfix_len = 0, - .owner = THIS_MODULE, -}; - - -int ieee80211_crypto_init(void) -{ - int ret = -ENOMEM; - - hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL); - if (!hcrypt) - goto out; - - INIT_LIST_HEAD(&hcrypt->algs); - spin_lock_init(&hcrypt->lock); - - ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); - if (ret < 0) { - kfree(hcrypt); - hcrypt = NULL; - } -out: - return ret; -} - - -void ieee80211_crypto_deinit(void) -{ - struct list_head *ptr, *n; - struct ieee80211_crypto_alg *alg = NULL; - - if (hcrypt == NULL) - return; - - list_for_each_safe(ptr, n, &hcrypt->algs) { - alg = list_entry(ptr, struct ieee80211_crypto_alg, list); - if (alg) { - list_del(ptr); - pr_debug("unregistered algorithm '%s' (deinit)\n", - alg->ops->name); - kfree(alg); - } - } - kfree(hcrypt); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h deleted file mode 100644 index 0b4ea43..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Original code based on Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * <jketreno@linux.intel.com> - * - * Copyright (c) 2004, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -/* - * This file defines the interface to the ieee80211 crypto module. - */ -#ifndef IEEE80211_CRYPT_H -#define IEEE80211_CRYPT_H - -#include <linux/skbuff.h> - -struct ieee80211_crypto_ops { - const char *name; - - /* init new crypto context (e.g., allocate private data space, - * select IV, etc.); returns NULL on failure or pointer to allocated - * private data on success */ - void * (*init)(int keyidx); - - /* deinitialize crypto context and free allocated private data */ - void (*deinit)(void *priv); - - /* encrypt/decrypt return < 0 on error or >= 0 on success. The return - * value from decrypt_mpdu is passed as the keyidx value for - * decrypt_msdu. skb must have enough head and tail room for the - * encryption; if not, error will be returned; these functions are - * called for all MPDUs (i.e., fragments). - */ - int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); - int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); - - /* These functions are called for full MSDUs, i.e. full frames. - * These can be NULL if full MSDU operations are not needed. */ - int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); - int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, - void *priv); - - int (*set_key)(void *key, int len, u8 *seq, void *priv); - int (*get_key)(void *key, int len, u8 *seq, void *priv); - - /* procfs handler for printing out key information and possible - * statistics */ - char * (*print_stats)(char *p, void *priv); - - /* maximum number of bytes added by encryption; encrypt buf is - * allocated with extra_prefix_len bytes, copy of in_buf, and - * extra_postfix_len; encrypt need not use all this space, but - * the result must start at the beginning of the buffer and correct - * length must be returned */ - int extra_prefix_len, extra_postfix_len; - - struct module *owner; -}; - -struct ieee80211_crypt_data { - struct list_head list; /* delayed deletion list */ - struct ieee80211_crypto_ops *ops; - void *priv; - atomic_t refcnt; -}; - -int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops); -int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops); -struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name); -void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int); -void ieee80211_crypt_deinit_handler(unsigned long); -void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, - struct ieee80211_crypt_data **crypt); - -#endif diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c deleted file mode 100644 index 4fe2538..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Host AP crypt: host-based CCMP encryption implementation for Host AP driver - * - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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. See README and COPYING for - * more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/if_ether.h> -#include <linux/if_arp.h> -#include <linux/string.h> -#include <linux/wireless.h> - -#include "ieee80211.h" - -#include <linux/crypto.h> -#include <linux/scatterlist.h> - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: CCMP"); -MODULE_LICENSE("GPL"); - - -#define AES_BLOCK_LEN 16 -#define CCMP_HDR_LEN 8 -#define CCMP_MIC_LEN 8 -#define CCMP_TK_LEN 16 -#define CCMP_PN_LEN 6 - -struct ieee80211_ccmp_data { - u8 key[CCMP_TK_LEN]; - int key_set; - - u8 tx_pn[CCMP_PN_LEN]; - u8 rx_pn[CCMP_PN_LEN]; - - u32 dot11RSNAStatsCCMPFormatErrors; - u32 dot11RSNAStatsCCMPReplays; - u32 dot11RSNAStatsCCMPDecryptErrors; - - int key_idx; - - struct crypto_tfm *tfm; - - /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; -}; - -static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one((void *)tfm, ct, pt); -} - -static void *ieee80211_ccmp_init(int key_idx) -{ - struct ieee80211_ccmp_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (priv == NULL) - goto fail; - priv->key_idx = key_idx; - - priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm)) { - pr_debug("could not allocate crypto API aes\n"); - priv->tfm = NULL; - goto fail; - } - - return priv; - -fail: - if (priv) { - if (priv->tfm) - crypto_free_cipher((void *)priv->tfm); - kfree(priv); - } - - return NULL; -} - - -static void ieee80211_ccmp_deinit(void *priv) -{ - struct ieee80211_ccmp_data *_priv = priv; - - if (_priv && _priv->tfm) - crypto_free_cipher((void *)_priv->tfm); - kfree(priv); -} - - -static inline void xor_block(u8 *b, u8 *a, size_t len) -{ - int i; - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - -static void ccmp_init_blocks(struct crypto_tfm *tfm, - struct ieee80211_hdr_4addr *hdr, - u8 *pn, size_t dlen, u8 *b0, u8 *auth, - u8 *s0) -{ - u8 *pos, qc = 0; - size_t aad_len; - u16 fc; - int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; - - fc = le16_to_cpu(hdr->frame_ctl); - a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)); - /* - qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && - (WLAN_FC_GET_STYPE(fc) & 0x08)); - */ - qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && - (WLAN_FC_GET_STYPE(fc) & 0x80)); - aad_len = 22; - if (a4_included) - aad_len += 6; - if (qc_included) { - pos = (u8 *) &hdr->addr4; - if (a4_included) - pos += 6; - qc = *pos & 0x0f; - aad_len += 2; - } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; - - /* AAD: - * FC with bits 4..6 and 11..13 masked to zero; 14 is always one - * A1 | A2 | A3 - * SC with bits 4..15 (seq#) masked to zero - * A4 (if present) - * QC (if present) - */ - pos = (u8 *) hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); - pos = (u8 *) &hdr->seq_ctl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); - if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); - if (qc_included) { - aad[a4_included ? 30 : 24] = qc; - /* rest of QC masked */ - } - - /* Start with the first block and AAD */ - ieee80211_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = b0[15] = 0; - ieee80211_ccmp_aes_encrypt(tfm, b0, s0); -} - -static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_ccmp_data *key = priv; - int data_len, i; - u8 *pos; - struct ieee80211_hdr_4addr *hdr; - int blocks, last, len; - u8 *mic; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; - - if (skb_headroom(skb) < CCMP_HDR_LEN || - skb_tailroom(skb) < CCMP_MIC_LEN || - skb->len < hdr_len) - return -1; - - data_len = skb->len - hdr_len; - pos = skb_push(skb, CCMP_HDR_LEN); - memmove(pos, pos + CCMP_HDR_LEN, hdr_len); - pos += hdr_len; - - i = CCMP_PN_LEN - 1; - while (i >= 0) { - key->tx_pn[i]++; - if (key->tx_pn[i] != 0) - break; - i--; - } - - *pos++ = key->tx_pn[5]; - *pos++ = key->tx_pn[4]; - *pos++ = 0; - *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; - *pos++ = key->tx_pn[3]; - *pos++ = key->tx_pn[2]; - *pos++ = key->tx_pn[1]; - *pos++ = key->tx_pn[0]; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - mic = skb_put(skb, CCMP_MIC_LEN); - - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); - - blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } - - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; - - return 0; -} - - -static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_ccmp_data *key = priv; - u8 keyidx, *pos; - struct ieee80211_hdr_4addr *hdr; - u8 pn[6]; - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; - int i, blocks, last, len; - - if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { - key->dot11RSNAStatsCCMPFormatErrors++; - return -1; - } - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - pos = skb->data + hdr_len; - keyidx = pos[3]; - if (!(keyidx & (1 << 5))) { - if (net_ratelimit()) { - pr_debug("received packet without ExtIV flag from %pM\n", - hdr->addr2); - } - key->dot11RSNAStatsCCMPFormatErrors++; - return -2; - } - keyidx >>= 6; - if (key->key_idx != keyidx) { - pr_debug("RX tkey->key_idx=%d frame keyidx=%d priv=%p\n", - key->key_idx, keyidx, priv); - return -6; - } - if (!key->key_set) { - if (net_ratelimit()) { - pr_debug("received packet from %pM with keyid=%d that does not have a configured key\n", - hdr->addr2, keyidx); - } - return -3; - } - - pn[0] = pos[7]; - pn[1] = pos[6]; - pn[2] = pos[5]; - pn[3] = pos[4]; - pn[4] = pos[1]; - pn[5] = pos[0]; - pos += 8; - - if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { - if (net_ratelimit()) { - pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n", - hdr->addr2, key->rx_pn, pn); - } - key->dot11RSNAStatsCCMPReplays++; - return -4; - } - - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } - - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { - if (net_ratelimit()) - pr_debug("decrypt failed: STA=%pM\n", hdr->addr2); - - key->dot11RSNAStatsCCMPDecryptErrors++; - return -5; - } - - memcpy(key->rx_pn, pn, CCMP_PN_LEN); - - /* Remove hdr and MIC */ - memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); - skb_pull(skb, CCMP_HDR_LEN); - skb_trim(skb, skb->len - CCMP_MIC_LEN); - - return keyidx; -} - - -static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_ccmp_data *data = priv; - int keyidx; - struct crypto_tfm *tfm = data->tfm; - - keyidx = data->key_idx; - memset(data, 0, sizeof(*data)); - data->key_idx = keyidx; - data->tfm = tfm; - if (len == CCMP_TK_LEN) { - memcpy(data->key, key, CCMP_TK_LEN); - data->key_set = 1; - if (seq) { - data->rx_pn[0] = seq[5]; - data->rx_pn[1] = seq[4]; - data->rx_pn[2] = seq[3]; - data->rx_pn[3] = seq[2]; - data->rx_pn[4] = seq[1]; - data->rx_pn[5] = seq[0]; - } - crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); - } else if (len == 0) - data->key_set = 0; - else - return -1; - - return 0; -} - - -static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_ccmp_data *data = priv; - - if (len < CCMP_TK_LEN) - return -1; - - if (!data->key_set) - return 0; - memcpy(key, data->key, CCMP_TK_LEN); - - if (seq) { - seq[0] = data->tx_pn[5]; - seq[1] = data->tx_pn[4]; - seq[2] = data->tx_pn[3]; - seq[3] = data->tx_pn[2]; - seq[4] = data->tx_pn[1]; - seq[5] = data->tx_pn[0]; - } - - return CCMP_TK_LEN; -} - - -static char *ieee80211_ccmp_print_stats(char *p, void *priv) -{ - struct ieee80211_ccmp_data *ccmp = priv; - p += sprintf(p, - "key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n", - ccmp->key_idx, ccmp->key_set, - ccmp->tx_pn, ccmp->rx_pn, - ccmp->dot11RSNAStatsCCMPFormatErrors, - ccmp->dot11RSNAStatsCCMPReplays, - ccmp->dot11RSNAStatsCCMPDecryptErrors); - - return p; -} - -void ieee80211_ccmp_null(void) -{ - return; -} -static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { - .name = "CCMP", - .init = ieee80211_ccmp_init, - .deinit = ieee80211_ccmp_deinit, - .encrypt_mpdu = ieee80211_ccmp_encrypt, - .decrypt_mpdu = ieee80211_ccmp_decrypt, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = ieee80211_ccmp_set_key, - .get_key = ieee80211_ccmp_get_key, - .print_stats = ieee80211_ccmp_print_stats, - .extra_prefix_len = CCMP_HDR_LEN, - .extra_postfix_len = CCMP_MIC_LEN, - .owner = THIS_MODULE, -}; - - -int ieee80211_crypto_ccmp_init(void) -{ - return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); -} - - -void ieee80211_crypto_ccmp_exit(void) -{ - ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c deleted file mode 100644 index 6c1acc5..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Host AP crypt: host-based TKIP encryption implementation for Host AP driver - * - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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. See README and COPYING for - * more details. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/if_ether.h> -#include <linux/if_arp.h> -#include <asm/string.h> - -#include "ieee80211.h" - -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/crc32.h> - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: TKIP"); -MODULE_LICENSE("GPL"); - - -struct ieee80211_tkip_data { -#define TKIP_KEY_LEN 32 - u8 key[TKIP_KEY_LEN]; - int key_set; - - u32 tx_iv32; - u16 tx_iv16; - u16 tx_ttak[5]; - int tx_phase1_done; - - u32 rx_iv32; - u16 rx_iv16; - u16 rx_ttak[5]; - int rx_phase1_done; - u32 rx_iv32_new; - u16 rx_iv16_new; - - u32 dot11RSNAStatsTKIPReplays; - u32 dot11RSNAStatsTKIPICVErrors; - u32 dot11RSNAStatsTKIPLocalMICFailures; - - int key_idx; - - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; - struct crypto_tfm *tfm_arc4; - struct crypto_tfm *tfm_michael; - - /* scratch buffers for virt_to_page() (crypto API) */ - u8 rx_hdr[16], tx_hdr[16]; -}; - -static void *ieee80211_tkip_init(int key_idx) -{ - struct ieee80211_tkip_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (priv == NULL) - goto fail; - priv->key_idx = key_idx; - - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tx_tfm_arc4)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API arc4\n"); - priv->tx_tfm_arc4 = NULL; - goto fail; - } - - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tx_tfm_michael)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API michael_mic\n"); - priv->tx_tfm_michael = NULL; - goto fail; - } - - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->rx_tfm_arc4)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API arc4\n"); - priv->rx_tfm_arc4 = NULL; - goto fail; - } - - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->rx_tfm_michael)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API michael_mic\n"); - priv->rx_tfm_michael = NULL; - goto fail; - } - - return priv; - -fail: - if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); - kfree(priv); - } - - return NULL; -} - - -static void ieee80211_tkip_deinit(void *priv) -{ - struct ieee80211_tkip_data *_priv = priv; - - if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); - } - kfree(priv); -} - - -static inline u16 RotR1(u16 val) -{ - return (val >> 1) | (val << 15); -} - - -static inline u8 Lo8(u16 val) -{ - return val & 0xff; -} - - -static inline u8 Hi8(u16 val) -{ - return val >> 8; -} - - -static inline u16 Lo16(u32 val) -{ - return val & 0xffff; -} - - -static inline u16 Hi16(u32 val) -{ - return val >> 16; -} - - -static inline u16 Mk16(u8 hi, u8 lo) -{ - return lo | (((u16) hi) << 8); -} - - -static inline u16 Mk16_le(u16 *v) -{ - return le16_to_cpu(*v); -} - - -static const u16 Sbox[256] = { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, -}; - - -static inline u16 _S_(u16 v) -{ - u16 t = Sbox[Hi8(v)]; - return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); -} - -#define PHASE1_LOOP_COUNT 8 - -static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) -{ - int i, j; - - /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ - TTAK[0] = Lo16(IV32); - TTAK[1] = Hi16(IV32); - TTAK[2] = Mk16(TA[1], TA[0]); - TTAK[3] = Mk16(TA[3], TA[2]); - TTAK[4] = Mk16(TA[5], TA[4]); - - for (i = 0; i < PHASE1_LOOP_COUNT; i++) { - j = 2 * (i & 1); - TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); - TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); - TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); - TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); - TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; - } -} - - -static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, - u16 IV16) -{ - /* Make temporary area overlap WEP seed so that the final copy can be - * avoided on little endian hosts. */ - u16 *PPK = (u16 *) &WEPSeed[4]; - - /* Step 1 - make copy of TTAK and bring in TSC */ - PPK[0] = TTAK[0]; - PPK[1] = TTAK[1]; - PPK[2] = TTAK[2]; - PPK[3] = TTAK[3]; - PPK[4] = TTAK[4]; - PPK[5] = TTAK[4] + IV16; - - /* Step 2 - 96-bit bijective mixing using S-box */ - PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); - PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); - PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); - PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); - PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); - PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); - - PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); - PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - - /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value - * WEPSeed[0..2] is transmitted as WEP IV */ - WEPSeed[0] = Hi8(IV16); - WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; - WEPSeed[2] = Lo8(IV16); - WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); - -#ifdef __BIG_ENDIAN - { - int i; - for (i = 0; i < 6; i++) - PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); - } -#endif -} - -static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; - int len; - u8 *pos; - struct ieee80211_hdr_4addr *hdr; - u8 rc4key[16], *icv; - u32 crc; - struct scatterlist sg; - int ret; - - ret = 0; - if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || - skb->len < hdr_len) - return -1; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - if (!tkey->tx_phase1_done) { - tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, - tkey->tx_iv32); - tkey->tx_phase1_done = 1; - } - tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); - - len = skb->len - hdr_len; - pos = skb_push(skb, 8); - memmove(pos, pos + 8, hdr_len); - pos += hdr_len; - - *pos++ = rc4key[0]; - *pos++ = rc4key[1]; - *pos++ = rc4key[2]; - *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; - *pos++ = tkey->tx_iv32 & 0xff; - *pos++ = (tkey->tx_iv32 >> 8) & 0xff; - *pos++ = (tkey->tx_iv32 >> 16) & 0xff; - *pos++ = (tkey->tx_iv32 >> 24) & 0xff; - - icv = skb_put(skb, 4); - crc = ~crc32_le(~0, pos, len); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, len + 4); - ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); - - tkey->tx_iv16++; - if (tkey->tx_iv16 == 0) { - tkey->tx_phase1_done = 0; - tkey->tx_iv32++; - } - return ret; -} - -static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 }; - u8 keyidx, *pos; - u32 iv32; - u16 iv16; - struct ieee80211_hdr_4addr *hdr; - u8 icv[4]; - u32 crc; - struct scatterlist sg; - u8 rc4key[16]; - int plen; - - if (skb->len < hdr_len + 8 + 4) - return -1; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - pos = skb->data + hdr_len; - keyidx = pos[3]; - if (!(keyidx & (1 << 5))) { - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: received packet without ExtIV" - " flag from %pM\n", hdr->addr2); - } - return -2; - } - keyidx >>= 6; - if (tkey->key_idx != keyidx) { - printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " - "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); - return -6; - } - if (!tkey->key_set) { - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: received packet from %pM" - " with keyid=%d that does not have a configured" - " key\n", hdr->addr2, keyidx); - } - return -3; - } - iv16 = (pos[0] << 8) | pos[2]; - iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); - pos += 8; - - if (iv32 < tkey->rx_iv32 || - (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" - " previous TSC %08x%04x received TSC " - "%08x%04x\n", hdr->addr2, - tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); - } - tkey->dot11RSNAStatsTKIPReplays++; - return -4; - } - - if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { - tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); - tkey->rx_phase1_done = 1; - } - tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); - - plen = skb->len - hdr_len - 12; - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, plen + 4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { - if (net_ratelimit()) { - printk(KERN_DEBUG ": TKIP: failed to decrypt " - "received packet from %pM\n", - hdr->addr2); - } - return -7; - } - - crc = ~crc32_le(~0, pos, plen); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - if (memcmp(icv, pos + plen, 4) != 0) { - if (iv32 != tkey->rx_iv32) { - /* Previously cached Phase1 result was already lost, so - * it needs to be recalculated for the next packet. */ - tkey->rx_phase1_done = 0; - } - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: ICV error detected: STA=" - "%pM\n", hdr->addr2); - } - tkey->dot11RSNAStatsTKIPICVErrors++; - return -5; - } - - /* Update real counters only after Michael MIC verification has - * completed */ - tkey->rx_iv32_new = iv32; - tkey->rx_iv16_new = iv16; - - /* Remove IV and ICV */ - memmove(skb->data + 8, skb->data, hdr_len); - skb_pull(skb, 8); - skb_trim(skb, skb->len - 4); - - return keyidx; -} - -static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, - u8 *data, size_t data_len, u8 *mic) -{ - struct hash_desc desc; - struct scatterlist sg[2]; - - if (tfm_michael == NULL) { - printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); - return -1; - } - - sg_init_table(sg, 2); - sg_set_buf(&sg[0], hdr, 16); - sg_set_buf(&sg[1], data, data_len); - - if (crypto_hash_setkey(tfm_michael, key, 8)) - return -1; - - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); -} - -static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) -{ - struct ieee80211_hdr_4addr *hdr11; - - hdr11 = (struct ieee80211_hdr_4addr *)skb->data; - switch (le16_to_cpu(hdr11->frame_ctl) & - (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_TODS: - memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ - break; - case IEEE80211_FCTL_FROMDS: - memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ - break; - case 0: - memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ - break; - } - - hdr[12] = 0; /* priority */ - - hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ -} - - -static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, - void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - u8 *pos; - struct ieee80211_hdr_4addr *hdr; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { - printk(KERN_DEBUG "Invalid packet for Michael MIC add " - "(tailroom=%d hdr_len=%d skb->len=%d)\n", - skb_tailroom(skb), hdr_len, skb->len); - return -1; - } - - michael_mic_hdr(skb, tkey->tx_hdr); - - if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) - tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; - - pos = skb_put(skb, 8); - - if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, - skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) - return -1; - - return 0; -} - -static void ieee80211_michael_mic_failure(struct net_device *dev, - struct ieee80211_hdr_4addr *hdr, - int keyidx) -{ - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - - /* TODO: needed parameters: count, keyid, key type, TSC */ - memset(&ev, 0, sizeof(ev)); - ev.flags = keyidx & IW_MICFAILURE_KEY_ID; - if (hdr->addr1[0] & 0x01) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - ev.src_addr.sa_family = ARPHRD_ETHER; - memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); -} - -static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, - int hdr_len, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - u8 mic[8]; - struct ieee80211_hdr_4addr *hdr; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - if (!tkey->key_set) - return -1; - - michael_mic_hdr(skb, tkey->rx_hdr); - if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) - tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; - - if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, - skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) - return -1; - - if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { - struct ieee80211_hdr_4addr *hdr; - hdr = (struct ieee80211_hdr_4addr *)skb->data; - printk(KERN_DEBUG "%s: Michael MIC verification failed for " - "MSDU from %pM keyidx=%d\n", - skb->dev ? skb->dev->name : "N/A", hdr->addr2, - keyidx); - if (skb->dev) - ieee80211_michael_mic_failure(skb->dev, hdr, keyidx); - tkey->dot11RSNAStatsTKIPLocalMICFailures++; - return -1; - } - - /* Update TSC counters for RX now that the packet verification has - * completed. */ - tkey->rx_iv32 = tkey->rx_iv32_new; - tkey->rx_iv16 = tkey->rx_iv16_new; - - skb_trim(skb, skb->len - 8); - - return 0; -} - - -static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; - - keyidx = tkey->key_idx; - memset(tkey, 0, sizeof(*tkey)); - tkey->key_idx = keyidx; - - tkey->tx_tfm_michael = tfm; - tkey->tx_tfm_arc4 = tfm2; - tkey->rx_tfm_michael = tfm3; - tkey->rx_tfm_arc4 = tfm4; - - if (len == TKIP_KEY_LEN) { - memcpy(tkey->key, key, TKIP_KEY_LEN); - tkey->key_set = 1; - tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ - if (seq) { - tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | - (seq[3] << 8) | seq[2]; - tkey->rx_iv16 = (seq[1] << 8) | seq[0]; - } - } else if (len == 0) - tkey->key_set = 0; - else - return -1; - - return 0; -} - - -static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - - if (len < TKIP_KEY_LEN) - return -1; - - if (!tkey->key_set) - return 0; - memcpy(key, tkey->key, TKIP_KEY_LEN); - - if (seq) { - /* Return the sequence number of the last transmitted frame. */ - u16 iv16 = tkey->tx_iv16; - u32 iv32 = tkey->tx_iv32; - if (iv16 == 0) - iv32--; - iv16--; - seq[0] = tkey->tx_iv16; - seq[1] = tkey->tx_iv16 >> 8; - seq[2] = tkey->tx_iv32; - seq[3] = tkey->tx_iv32 >> 8; - seq[4] = tkey->tx_iv32 >> 16; - seq[5] = tkey->tx_iv32 >> 24; - } - - return TKIP_KEY_LEN; -} - - -static char *ieee80211_tkip_print_stats(char *p, void *priv) -{ - struct ieee80211_tkip_data *tkip = priv; - p += sprintf(p, "key[%d] alg=TKIP key_set=%d " - "tx_pn=%02x%02x%02x%02x%02x%02x " - "rx_pn=%02x%02x%02x%02x%02x%02x " - "replays=%d icv_errors=%d local_mic_failures=%d\n", - tkip->key_idx, tkip->key_set, - (tkip->tx_iv32 >> 24) & 0xff, - (tkip->tx_iv32 >> 16) & 0xff, - (tkip->tx_iv32 >> 8) & 0xff, - tkip->tx_iv32 & 0xff, - (tkip->tx_iv16 >> 8) & 0xff, - tkip->tx_iv16 & 0xff, - (tkip->rx_iv32 >> 24) & 0xff, - (tkip->rx_iv32 >> 16) & 0xff, - (tkip->rx_iv32 >> 8) & 0xff, - tkip->rx_iv32 & 0xff, - (tkip->rx_iv16 >> 8) & 0xff, - tkip->rx_iv16 & 0xff, - tkip->dot11RSNAStatsTKIPReplays, - tkip->dot11RSNAStatsTKIPICVErrors, - tkip->dot11RSNAStatsTKIPLocalMICFailures); - return p; -} - - -static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { - .name = "TKIP", - .init = ieee80211_tkip_init, - .deinit = ieee80211_tkip_deinit, - .encrypt_mpdu = ieee80211_tkip_encrypt, - .decrypt_mpdu = ieee80211_tkip_decrypt, - .encrypt_msdu = ieee80211_michael_mic_add, - .decrypt_msdu = ieee80211_michael_mic_verify, - .set_key = ieee80211_tkip_set_key, - .get_key = ieee80211_tkip_get_key, - .print_stats = ieee80211_tkip_print_stats, - .extra_prefix_len = 4 + 4, /* IV + ExtIV */ - .extra_postfix_len = 8 + 4, /* MIC + ICV */ - .owner = THIS_MODULE, -}; - - -int ieee80211_crypto_tkip_init(void) -{ - return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip); -} - - -void ieee80211_crypto_tkip_exit(void) -{ - ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip); -} - - -void ieee80211_tkip_null(void) -{ -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c deleted file mode 100644 index f253672..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Host AP crypt: host-based WEP encryption implementation for Host AP driver - * - * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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. See README and COPYING for - * more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/skbuff.h> -#include <linux/string.h> - -#include "ieee80211.h" - -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/crc32.h> - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: WEP"); -MODULE_LICENSE("GPL"); - -struct prism2_wep_data { - u32 iv; -#define WEP_KEY_LEN 13 - u8 key[WEP_KEY_LEN + 1]; - u8 key_len; - u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; -}; - -static void *prism2_wep_init(int keyidx) -{ - struct prism2_wep_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (priv == NULL) - goto fail; - priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tx_tfm)) { - pr_debug("could not allocate crypto API arc4\n"); - priv->tx_tfm = NULL; - goto fail; - } - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->rx_tfm)) { - pr_debug("could not allocate crypto API arc4\n"); - priv->rx_tfm = NULL; - goto fail; - } - - /* start WEP IV from a random value */ - get_random_bytes(&priv->iv, 4); - - return priv; - -fail: - if (priv) { - if (priv->tx_tfm) - crypto_free_blkcipher(priv->tx_tfm); - if (priv->rx_tfm) - crypto_free_blkcipher(priv->rx_tfm); - kfree(priv); - } - - return NULL; -} - -static void prism2_wep_deinit(void *priv) -{ - struct prism2_wep_data *_priv = priv; - - if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); - } - - kfree(priv); -} - -/* Perform WEP encryption on given skb that has at least 4 bytes of headroom - * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, - * so the payload length increases with 8 bytes. - * - * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) - */ -static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->tx_tfm }; - u32 klen, len; - u8 key[WEP_KEY_LEN + 3]; - u8 *pos; - u32 crc; - u8 *icv; - struct scatterlist sg; - - if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || - skb->len < hdr_len) - return -1; - - len = skb->len - hdr_len; - pos = skb_push(skb, 4); - memmove(pos, pos + 4, hdr_len); - pos += hdr_len; - - klen = 3 + wep->key_len; - - wep->iv++; - - /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key - * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) - * can be used to speedup attacks, so avoid using them. */ - if ((wep->iv & 0xff00) == 0xff00) { - u8 B = (wep->iv >> 16) & 0xff; - if (B >= 3 && B < klen) - wep->iv += 0x0100; - } - - /* Prepend 24-bit IV to RC4 key and TX frame */ - *pos++ = key[0] = (wep->iv >> 16) & 0xff; - *pos++ = key[1] = (wep->iv >> 8) & 0xff; - *pos++ = key[2] = wep->iv & 0xff; - *pos++ = wep->key_idx << 6; - - /* Copy rest of the WEP key (the secret part) */ - memcpy(key + 3, wep->key, wep->key_len); - - /* Append little-endian CRC32 and encrypt it to produce ICV */ - crc = ~crc32_le(~0, pos, len); - icv = skb_put(skb, 4); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); - sg_init_one(&sg, pos, len + 4); - - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); -} - -/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of - * the frame: IV (4 bytes), encrypted payload (including SNAP header), - * ICV (4 bytes). len includes both IV and ICV. - * - * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on - * failure. If frame is OK, IV and ICV will be removed. - */ -static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->rx_tfm }; - u32 klen, plen; - u8 key[WEP_KEY_LEN + 3]; - u8 keyidx, *pos; - u32 crc; - u8 icv[4]; - struct scatterlist sg; - - if (skb->len < hdr_len + 8) - return -1; - - pos = skb->data + hdr_len; - key[0] = *pos++; - key[1] = *pos++; - key[2] = *pos++; - keyidx = *pos++ >> 6; - if (keyidx != wep->key_idx) - return -1; - - klen = 3 + wep->key_len; - - /* Copy rest of the WEP key (the secret part) */ - memcpy(key + 3, wep->key, wep->key_len); - - /* Apply RC4 to data and compute CRC32 over decrypted data */ - plen = skb->len - hdr_len - 8; - - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); - sg_init_one(&sg, pos, plen + 4); - - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) - return -7; - - crc = ~crc32_le(~0, pos, plen); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - if (memcmp(icv, pos + plen, 4) != 0) { - /* ICV mismatch - drop frame */ - return -2; - } - - /* Remove IV and ICV */ - memmove(skb->data + 4, skb->data, hdr_len); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - return 0; -} - -static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct prism2_wep_data *wep = priv; - - if (len < 0 || len > WEP_KEY_LEN) - return -1; - - memcpy(wep->key, key, len); - wep->key_len = len; - - return 0; -} - -static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct prism2_wep_data *wep = priv; - - if (len < wep->key_len) - return -1; - - memcpy(key, wep->key, wep->key_len); - - return wep->key_len; -} - -static char *prism2_wep_print_stats(char *p, void *priv) -{ - struct prism2_wep_data *wep = priv; - p += sprintf(p, "key[%d] alg=WEP len=%d\n", - wep->key_idx, wep->key_len); - return p; -} - -static struct ieee80211_crypto_ops ieee80211_crypt_wep = { - .name = "WEP", - .init = prism2_wep_init, - .deinit = prism2_wep_deinit, - .encrypt_mpdu = prism2_wep_encrypt, - .decrypt_mpdu = prism2_wep_decrypt, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = prism2_wep_set_key, - .get_key = prism2_wep_get_key, - .print_stats = prism2_wep_print_stats, - .extra_prefix_len = 4, /* IV */ - .extra_postfix_len = 4, /* ICV */ - .owner = THIS_MODULE, -}; - -int ieee80211_crypto_wep_init(void) -{ - return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); -} - -void ieee80211_crypto_wep_exit(void) -{ - ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); -} - -void ieee80211_wep_null(void) -{ - return; -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c deleted file mode 100644 index 07a1fbb..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c +++ /dev/null @@ -1,203 +0,0 @@ -/******************************************************************************* - - Copyright(c) 2004 Intel Corporation. All rights reserved. - - Portions of this file are based on the WEP enablement code provided by the - Host AP project hostap-drivers v0.1.3 - Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - <jkmaline@cc.hut.fi> - Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 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 LICENSE. - - Contact Information: - James P. Ketrenos <ipw2100-admin@linux.intel.com> - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include <linux/compiler.h> -//#include <linux/config.h> -#include <linux/errno.h> -#include <linux/if_arp.h> -#include <linux/in6.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/wireless.h> -#include <linux/etherdevice.h> -#include <linux/uaccess.h> -#include <net/arp.h> -#include <net/net_namespace.h> - -#include "ieee80211.h" - -MODULE_DESCRIPTION("802.11 data/management/control stack"); -MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>"); -MODULE_LICENSE("GPL"); - -#define DRV_NAME "ieee80211" - -static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) -{ - if (ieee->networks) - return 0; - - ieee->networks = kcalloc( - MAX_NETWORK_COUNT, sizeof(struct ieee80211_network), - GFP_KERNEL); - if (!ieee->networks) - return -ENOMEM; - - return 0; -} - -static inline void ieee80211_networks_free(struct ieee80211_device *ieee) -{ - if (!ieee->networks) - return; - kfree(ieee->networks); - ieee->networks = NULL; -} - -static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) -{ - int i; - - INIT_LIST_HEAD(&ieee->network_free_list); - INIT_LIST_HEAD(&ieee->network_list); - for (i = 0; i < MAX_NETWORK_COUNT; i++) - list_add_tail(&ieee->networks[i].list, &ieee->network_free_list); -} - - -struct net_device *alloc_ieee80211(int sizeof_priv) -{ - struct ieee80211_device *ieee; - struct net_device *dev; - int i, err; - - IEEE80211_DEBUG_INFO("Initializing...\n"); - - dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); - if (!dev) { - IEEE80211_ERROR("Unable to network device.\n"); - goto failed; - } - ieee = netdev_priv(dev); - - ieee->dev = dev; - - err = ieee80211_networks_allocate(ieee); - if (err) { - IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", - err); - goto failed; - } - ieee80211_networks_initialize(ieee); - - /* Default fragmentation threshold is maximum payload size */ - ieee->fts = DEFAULT_FTS; - ieee->scan_age = DEFAULT_MAX_SCAN_AGE; - ieee->open_wep = 1; - - /* Default to enabling full open WEP with host based encrypt/decrypt */ - ieee->host_encrypt = 1; - ieee->host_decrypt = 1; - ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ - - INIT_LIST_HEAD(&ieee->crypt_deinit_list); - init_timer(&ieee->crypt_deinit_timer); - ieee->crypt_deinit_timer.data = (unsigned long)ieee; - ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler; - - spin_lock_init(&ieee->lock); - spin_lock_init(&ieee->wpax_suitlist_lock); - - ieee->wpax_type_set = 0; - ieee->wpa_enabled = 0; - ieee->tkip_countermeasures = 0; - ieee->drop_unencrypted = 0; - ieee->privacy_invoked = 0; - ieee->ieee802_1x = 1; - ieee->raw_tx = 0; - - ieee80211_softmac_init(ieee); - - for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]); - - for (i = 0; i < 17; i++) { - ieee->last_rxseq_num[i] = -1; - ieee->last_rxfrag_num[i] = -1; - ieee->last_packet_time[i] = 0; - } -//These function were added to load crypte module autoly - ieee80211_tkip_null(); - ieee80211_wep_null(); - ieee80211_ccmp_null(); - return dev; - - failed: - if (dev) - free_netdev(dev); - return NULL; -} - - -void free_ieee80211(struct net_device *dev) -{ - struct ieee80211_device *ieee = netdev_priv(dev); - - int i; - struct list_head *p, *q; - - - ieee80211_softmac_free(ieee); - del_timer_sync(&ieee->crypt_deinit_timer); - ieee80211_crypt_deinit_entries(ieee, 1); - - for (i = 0; i < WEP_KEYS; i++) { - struct ieee80211_crypt_data *crypt = ieee->crypt[i]; - if (crypt) { - if (crypt->ops) - crypt->ops->deinit(crypt->priv); - kfree(crypt); - ieee->crypt[i] = NULL; - } - } - - ieee80211_networks_free(ieee); - - for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) { - list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) { - kfree(list_entry(p, struct ieee_ibss_seq, list)); - list_del(p); - } - } - - - free_netdev(dev); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c deleted file mode 100644 index b522b57..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c +++ /dev/null @@ -1,1486 +0,0 @@ -/* - * Original code based Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3 - hostap.o module, common routines - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * Copyright (c) 2004, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - ****************************************************************************** - - Few modifications for Realtek's Wi-Fi drivers by - Andrea Merello <andrea.merello@gmail.com> - - A special thanks goes to Realtek for their support ! - -******************************************************************************/ - - -#include <linux/compiler.h> -//#include <linux/config.h> -#include <linux/errno.h> -#include <linux/if_arp.h> -#include <linux/in6.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/wireless.h> -#include <linux/etherdevice.h> -#include <linux/uaccess.h> -#include <linux/ctype.h> - -#include "ieee80211.h" -#include "dot11d.h" -static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, - struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats) -{ - struct ieee80211_hdr_4addr *hdr = - (struct ieee80211_hdr_4addr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_ctl); - - skb->dev = ieee->dev; - skb_reset_mac_header(skb); - skb_pull(skb, ieee80211_get_hdrlen(fc)); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_80211_RAW); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - - -/* Called only as a tasklet (software IRQ) */ -static struct ieee80211_frag_entry * -ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq, - unsigned int frag, u8 tid, u8 *src, u8 *dst) -{ - struct ieee80211_frag_entry *entry; - int i; - - for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) { - entry = &ieee->frag_cache[tid][i]; - if (entry->skb != NULL && - time_after(jiffies, entry->first_frag_time + 2 * HZ)) { - IEEE80211_DEBUG_FRAG( - "expiring fragment cache entry " - "seq=%u last_frag=%u\n", - entry->seq, entry->last_frag); - dev_kfree_skb_any(entry->skb); - entry->skb = NULL; - } - - if (entry->skb != NULL && entry->seq == seq && - (entry->last_frag + 1 == frag || frag == -1) && - memcmp(entry->src_addr, src, ETH_ALEN) == 0 && - memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) - return entry; - } - - return NULL; -} - -/* Called only as a tasklet (software IRQ) */ -static struct sk_buff * -ieee80211_frag_cache_get(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *hdr) -{ - struct sk_buff *skb = NULL; - u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 sc = le16_to_cpu(hdr->seq_ctl); - unsigned int frag = WLAN_GET_SEQ_FRAG(sc); - unsigned int seq = WLAN_GET_SEQ_SEQ(sc); - struct ieee80211_frag_entry *entry; - struct ieee80211_hdr_3addrqos *hdr_3addrqos; - struct ieee80211_hdr_4addrqos *hdr_4addrqos; - u8 tid; - - if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - if (frag == 0) { - /* Reserve enough space to fit maximum frame length */ - skb = dev_alloc_skb(ieee->dev->mtu + - sizeof(struct ieee80211_hdr_4addr) + - 8 /* LLC */ + - 2 /* alignment */ + - 8 /* WEP */ + - ETH_ALEN /* WDS */ + - (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */); - if (skb == NULL) - return NULL; - - entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; - ieee->frag_next_idx[tid]++; - if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN) - ieee->frag_next_idx[tid] = 0; - - if (entry->skb != NULL) - dev_kfree_skb_any(entry->skb); - - entry->first_frag_time = jiffies; - entry->seq = seq; - entry->last_frag = frag; - entry->skb = skb; - memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); - memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); - } else { - /* received a fragment of a frame for which the head fragment - * should have already been received */ - entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, - hdr->addr1); - if (entry != NULL) { - entry->last_frag = frag; - skb = entry->skb; - } - } - - return skb; -} - - -/* Called only as a tasklet (software IRQ) */ -static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *hdr) -{ - u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 sc = le16_to_cpu(hdr->seq_ctl); - unsigned int seq = WLAN_GET_SEQ_SEQ(sc); - struct ieee80211_frag_entry *entry; - struct ieee80211_hdr_3addrqos *hdr_3addrqos; - struct ieee80211_hdr_4addrqos *hdr_4addrqos; - u8 tid; - - if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2, - hdr->addr1); - - if (entry == NULL) { - IEEE80211_DEBUG_FRAG( - "could not invalidate fragment cache " - "entry (seq=%u)\n", seq); - return -1; - } - - entry->skb = NULL; - return 0; -} - - - -/* ieee80211_rx_frame_mgtmt - * - * Responsible for handling management control frames - * - * Called by ieee80211_rx */ -static inline int -ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, u16 type, - u16 stype) -{ - struct ieee80211_hdr_4addr *hdr; - - // cheat the the hdr type - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - /* On the struct stats definition there is written that - * this is not mandatory.... but seems that the probe - * response parser uses it - */ - rx_stats->len = skb->len; - ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data, - rx_stats); - - if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) { - dev_kfree_skb_any(skb); - return 0; - } - - ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype); - - dev_kfree_skb_any(skb); - - return 0; - -} - - - -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -/* No encapsulation header if EtherType < 0x600 (=length) */ - -/* Called by ieee80211_rx_frame_decrypt */ -static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, - struct sk_buff *skb, size_t hdrlen) -{ - struct net_device *dev = ieee->dev; - u16 fc, ethertype; - struct ieee80211_hdr_4addr *hdr; - u8 *pos; - - if (skb->len < 24) - return 0; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - fc = le16_to_cpu(hdr->frame_ctl); - - /* check that the frame is unicast frame to us */ - if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && - memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { - /* ToDS frame with own addr BSSID and DA */ - } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { - /* FromDS frame with own addr as DA */ - } else - return 0; - - if (skb->len < 24 + 8) - return 0; - - /* check for port access entity Ethernet type */ -// pos = skb->data + 24; - pos = skb->data + hdrlen; - ethertype = (pos[6] << 8) | pos[7]; - if (ethertype == ETH_P_PAE) - return 1; - - return 0; -} - -/* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static inline int -ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_crypt_data *crypt) -{ - struct ieee80211_hdr_4addr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) - return 0; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - -#ifdef CONFIG_IEEE80211_CRYPT_TKIP - if (ieee->tkip_countermeasures && - strcmp(crypt->ops->name, "TKIP") == 0) { - if (net_ratelimit()) { - netdev_dbg(ieee->dev, - "TKIP countermeasures: dropped received packet from %pM\n", - ieee->dev->name, hdr->addr2); - } - return -1; - } -#endif - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - IEEE80211_DEBUG_DROP( - "decryption failed (SA=%pM" - ") res=%d\n", hdr->addr2, res); - if (res == -2) - IEEE80211_DEBUG_DROP("Decryption failed ICV " - "mismatch (key %d)\n", - skb->data[hdrlen + 3] >> 6); - ieee->ieee_stats.rx_discards_undecryptable++; - return -1; - } - - return res; -} - - -/* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static inline int -ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, - struct sk_buff *skb, int keyidx, - struct ieee80211_crypt_data *crypt) -{ - struct ieee80211_hdr_4addr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) - return 0; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_dbg(ieee->dev, - "MSDU decryption/MIC verification failed (SA=%pM keyidx=%d)\n", - hdr->addr2, keyidx); - return -1; - } - - return 0; -} - - -/* this function is stolen from ipw2200 driver*/ -#define IEEE_PACKET_RETRY_TIME (5*HZ) -static int is_duplicate_packet(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header) -{ - u16 fc = le16_to_cpu(header->frame_ctl); - u16 sc = le16_to_cpu(header->seq_ctl); - u16 seq = WLAN_GET_SEQ_SEQ(sc); - u16 frag = WLAN_GET_SEQ_FRAG(sc); - u16 *last_seq, *last_frag; - unsigned long *last_time; - struct ieee80211_hdr_3addrqos *hdr_3addrqos; - struct ieee80211_hdr_4addrqos *hdr_4addrqos; - u8 tid; - - //TO2DS and QoS - if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS - hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else { // no QoS - tid = 0; - } - switch (ieee->iw_mode) { - case IW_MODE_ADHOC: - { - struct list_head *p; - struct ieee_ibss_seq *entry = NULL; - u8 *mac = header->addr2; - int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; - - list_for_each(p, &ieee->ibss_mac_hash[index]) { - entry = list_entry(p, struct ieee_ibss_seq, list); - if (!memcmp(entry->mac, mac, ETH_ALEN)) - break; - } - // if (memcmp(entry->mac, mac, ETH_ALEN)){ - if (p == &ieee->ibss_mac_hash[index]) { - entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC); - if (!entry) - return 0; - - memcpy(entry->mac, mac, ETH_ALEN); - entry->seq_num[tid] = seq; - entry->frag_num[tid] = frag; - entry->packet_time[tid] = jiffies; - list_add(&entry->list, &ieee->ibss_mac_hash[index]); - return 0; - } - last_seq = &entry->seq_num[tid]; - last_frag = &entry->frag_num[tid]; - last_time = &entry->packet_time[tid]; - break; - } - - case IW_MODE_INFRA: - last_seq = &ieee->last_rxseq_num[tid]; - last_frag = &ieee->last_rxfrag_num[tid]; - last_time = &ieee->last_packet_time[tid]; - - break; - default: - return 0; - } - -// if(tid != 0) { -// printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl); -// } - if ((*last_seq == seq) && - time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) { - if (*last_frag == frag) { - //printk(KERN_WARNING "[1] go drop!\n"); - goto drop; - - } - if (*last_frag + 1 != frag) - /* out-of-order fragment */ - //printk(KERN_WARNING "[2] go drop!\n"); - goto drop; - } else - *last_seq = seq; - - *last_frag = frag; - *last_time = jiffies; - return 0; - -drop: -// BUG_ON(!(fc & IEEE80211_FCTL_RETRY)); -// printk("DUP\n"); - - return 1; -} - - -/* All received frames are sent to this function. @skb contains the frame in - * IEEE 802.11 format, i.e., in the format it was sent over air. - * This function is called only as a tasklet (software IRQ). */ -int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats) -{ - struct net_device *dev = ieee->dev; - //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct ieee80211_hdr_4addr *hdr; - - size_t hdrlen; - u16 fc, type, stype, sc; - struct net_device_stats *stats; - unsigned int frag; - u8 *payload; - u16 ethertype; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - struct ieee80211_crypt_data *crypt = NULL; - int keyidx = 0; - - // cheat the the hdr type - hdr = (struct ieee80211_hdr_4addr *)skb->data; - stats = &ieee->stats; - - if (skb->len < 10) { - netdev_info(ieee->dev, "SKB length < 10\n"); - goto rx_dropped; - } - - fc = le16_to_cpu(hdr->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - sc = le16_to_cpu(hdr->seq_ctl); - - frag = WLAN_GET_SEQ_FRAG(sc); - -//YJ,add,080828,for keep alive - if ((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS) { - if (!memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) - ieee->NumRxUnicast++; - } else { - if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) - ieee->NumRxUnicast++; - } -//YJ,add,080828,for keep alive,end - - hdrlen = ieee80211_get_hdrlen(fc); - - - if (ieee->iw_mode == IW_MODE_MONITOR) { - ieee80211_monitor_rx(ieee, skb, rx_stats); - stats->rx_packets++; - stats->rx_bytes += skb->len; - return 1; - } - - if (ieee->host_decrypt) { - int idx = 0; - if (skb->len >= hdrlen + 3) - idx = skb->data[hdrlen + 3] >> 6; - crypt = ieee->crypt[idx]; - - /* allow NULL decrypt to indicate an station specific override - * for default encryption */ - if (crypt && (crypt->ops == NULL || - crypt->ops->decrypt_mpdu == NULL)) - crypt = NULL; - - if (!crypt && (fc & IEEE80211_FCTL_WEP)) { - /* This seems to be triggered by some (multicast?) - * frames from other than current BSS, so just drop the - * frames silently instead of filling system log with - * these reports. */ - IEEE80211_DEBUG_DROP("Decryption failed (not set)" - " (SA=%pM)\n", - hdr->addr2); - ieee->ieee_stats.rx_discards_undecryptable++; - goto rx_dropped; - } - } - - if (skb->len < IEEE80211_DATA_HDR3_LEN) - goto rx_dropped; - - // if QoS enabled, should check the sequence for each of the AC - if (is_duplicate_packet(ieee, hdr)) - goto rx_dropped; - - - if (type == IEEE80211_FTYPE_MGMT) { - if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) - goto rx_dropped; - else - goto rx_exit; - } - - /* Data frame - extract src/dst addresses */ - switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_FROMDS: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - memcpy(bssid, hdr->addr2, ETH_ALEN); - break; - case IEEE80211_FCTL_TODS: - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - memcpy(bssid, hdr->addr1, ETH_ALEN); - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - if (skb->len < IEEE80211_DATA_HDR4_LEN) - goto rx_dropped; - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); - break; - case 0: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - memcpy(bssid, hdr->addr3, ETH_ALEN); - break; - } - - - dev->last_rx = jiffies; - - - /* Nullfunc frames may have PS-bit set, so they must be passed to - * hostap_handle_sta_rx() before being dropped here. */ - if (stype != IEEE80211_STYPE_DATA && - stype != IEEE80211_STYPE_DATA_CFACK && - stype != IEEE80211_STYPE_DATA_CFPOLL && - stype != IEEE80211_STYPE_DATA_CFACKPOLL && - stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4 - ) { - if (stype != IEEE80211_STYPE_NULLFUNC) - IEEE80211_DEBUG_DROP( - "RX: dropped data frame " - "with no data (type=0x%02x, " - "subtype=0x%02x, len=%d)\n", - type, stype, skb->len); - goto rx_dropped; - } - if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) - goto rx_dropped; - - ieee->NumRxDataInPeriod++; - ieee->NumRxOkTotal++; - /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ - - if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) - goto rx_dropped; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - /* skb: hdr + (possibly fragmented) plaintext payload */ - // PR: FIXME: hostap has additional conditions in the "if" below: - // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { - int flen; - struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); - IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); - - if (!frag_skb) { - IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG, - "Rx cannot get skb from fragment " - "cache (morefrag=%d seq=%u frag=%u)\n", - (fc & IEEE80211_FCTL_MOREFRAGS) != 0, - WLAN_GET_SEQ_SEQ(sc), frag); - goto rx_dropped; - } - flen = skb->len; - if (frag != 0) - flen -= hdrlen; - - if (frag_skb->tail + flen > frag_skb->end) { - netdev_warn(ieee->dev, - "host decrypted and reassembled frame did not fit skb\n"); - ieee80211_frag_cache_invalidate(ieee, hdr); - goto rx_dropped; - } - - if (frag == 0) { - /* copy first fragment (including full headers) into - * beginning of the fragment cache skb */ - memcpy(skb_put(frag_skb, flen), skb->data, flen); - } else { - /* append frame payload to the end of the fragment - * cache skb */ - memcpy(skb_put(frag_skb, flen), skb->data + hdrlen, - flen); - } - dev_kfree_skb_any(skb); - skb = NULL; - - if (fc & IEEE80211_FCTL_MOREFRAGS) { - /* more fragments expected - leave the skb in fragment - * cache for now; it will be delivered to upper layers - * after all fragments have been received */ - goto rx_exit; - } - - /* this was the last fragment and the frame will be - * delivered, so remove skb from fragment cache */ - skb = frag_skb; - hdr = (struct ieee80211_hdr_4addr *)skb->data; - ieee80211_frag_cache_invalidate(ieee, hdr); - } - - /* skb: hdr + (possible reassembled) full MSDU payload; possibly still - * encrypted/authenticated */ - if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) - goto rx_dropped; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { - if (/*ieee->ieee802_1x &&*/ - ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - -#ifdef CONFIG_IEEE80211_DEBUG - /* pass unencrypted EAPOL frames even if encryption is - * configured */ - struct eapol *eap = (struct eapol *)(skb->data + - 24); - IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); -#endif - } else { - IEEE80211_DEBUG_DROP( - "encryption configured, but RX " - "frame not encrypted (SA=%pM)\n", - hdr->addr2); - goto rx_dropped; - } - } - -#ifdef CONFIG_IEEE80211_DEBUG - if (crypt && !(fc & IEEE80211_FCTL_WEP) && - ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - struct eapol *eap = (struct eapol *)(skb->data + - 24); - IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); - } -#endif - - if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep && - !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - IEEE80211_DEBUG_DROP( - "dropped unencrypted RX data " - "frame from %pM" - " (drop_unencrypted=1)\n", - hdr->addr2); - goto rx_dropped; - } -/* - if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n"); - } -*/ - /* skb: hdr + (possible reassembled) full plaintext payload */ - payload = skb->data + hdrlen; - ethertype = (payload[6] << 8) | payload[7]; - - - /* convert hdr + possible LLC headers into Ethernet header */ - if (skb->len - hdrlen >= 8 && - ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ - skb_pull(skb, hdrlen + SNAP_SIZE); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } else { - u16 len; - /* Leave Ethernet header part of hdr and full payload */ - skb_pull(skb, hdrlen); - len = htons(skb->len); - memcpy(skb_push(skb, 2), &len, 2); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } - - - stats->rx_packets++; - stats->rx_bytes += skb->len; - - if (skb) { - skb->protocol = eth_type_trans(skb, dev); - memset(skb->cb, 0, sizeof(skb->cb)); - skb->dev = dev; - skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ - ieee->last_rx_ps_time = jiffies; - netif_rx(skb); - } - - rx_exit: - return 1; - - rx_dropped: - stats->rx_dropped++; - - /* Returning 0 indicates to caller that we have not handled the SKB-- - * so it is still allocated and can be used again by underlying - * hardware as a DMA target */ - return 0; -} - -#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 - -static inline int ieee80211_is_ofdm_rate(u8 rate) -{ - switch (rate & ~IEEE80211_BASIC_RATE_MASK) { - case IEEE80211_OFDM_RATE_6MB: - case IEEE80211_OFDM_RATE_9MB: - case IEEE80211_OFDM_RATE_12MB: - case IEEE80211_OFDM_RATE_18MB: - case IEEE80211_OFDM_RATE_24MB: - case IEEE80211_OFDM_RATE_36MB: - case IEEE80211_OFDM_RATE_48MB: - case IEEE80211_OFDM_RATE_54MB: - return 1; - } - return 0; -} - -static inline int ieee80211_SignalStrengthTranslate(int CurrSS) -{ - int RetSS; - - // Step 1. Scale mapping. - if (CurrSS >= 71 && CurrSS <= 100) - RetSS = 90 + ((CurrSS - 70) / 3); - else if (CurrSS >= 41 && CurrSS <= 70) - RetSS = 78 + ((CurrSS - 40) / 3); - else if (CurrSS >= 31 && CurrSS <= 40) - RetSS = 66 + (CurrSS - 30); - else if (CurrSS >= 21 && CurrSS <= 30) - RetSS = 54 + (CurrSS - 20); - else if (CurrSS >= 5 && CurrSS <= 20) - RetSS = 42 + (((CurrSS - 5) * 2) / 3); - else if (CurrSS == 4) - RetSS = 36; - else if (CurrSS == 3) - RetSS = 27; - else if (CurrSS == 2) - RetSS = 18; - else if (CurrSS == 1) - RetSS = 9; - else - RetSS = CurrSS; - - //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); - - // Step 2. Smoothing. - - //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); - - return RetSS; -} - -static inline void -ieee80211_extract_country_ie(struct ieee80211_device *ieee, - struct ieee80211_info_element *info_element, - struct ieee80211_network *network, u8 *addr2) -{ - if (IS_DOT11D_ENABLE(ieee)) { - if (info_element->len != 0) { - memcpy(network->CountryIeBuf, info_element->data, info_element->len); - network->CountryIeLen = info_element->len; - - if (!IS_COUNTRY_IE_VALID(ieee)) - Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data); - } - - // - // 070305, rcnjko: I update country IE watch dog here because - // some AP (e.g. Cisco 1242) don't include country IE in their - // probe response frame. - // - if (IS_EQUAL_CIE_SRC(ieee, addr2)) - UPDATE_CIE_WATCHDOG(ieee); - } - -} - -/* SignalStrengthIndex is 0-100 */ -static int ieee80211_TranslateToDbm(unsigned char SignalStrengthIndex) -{ - unsigned char SignalPower; // in dBm. - - // Translate to dBm (x=0.5y-95). - SignalPower = (int)SignalStrengthIndex * 7 / 10; - SignalPower -= 95; - - return SignalPower; -} -inline int ieee80211_network_init( - struct ieee80211_device *ieee, - struct ieee80211_probe_response *beacon, - struct ieee80211_network *network, - struct ieee80211_rx_stats *stats) -{ -#ifdef CONFIG_IEEE80211_DEBUG - char rates_str[64]; - char *p; -#endif - struct ieee80211_info_element *info_element; - u16 left; - u8 i; - short offset; - u8 curRate = 0, hOpRate = 0, curRate_ex = 0; - - /* Pull out fixed field data */ - memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); - network->capability = beacon->capability; - network->last_scanned = jiffies; - network->time_stamp[0] = beacon->time_stamp[0]; - network->time_stamp[1] = beacon->time_stamp[1]; - network->beacon_interval = beacon->beacon_interval; - /* Where to pull this? beacon->listen_interval;*/ - network->listen_interval = 0x0A; - network->rates_len = network->rates_ex_len = 0; - network->last_associate = 0; - network->ssid_len = 0; - network->flags = 0; - network->atim_window = 0; - network->QoS_Enable = 0; -//by amy 080312 - network->HighestOperaRate = 0; -//by amy 080312 - network->Turbo_Enable = 0; - network->CountryIeLen = 0; - memset(network->CountryIeBuf, 0, MAX_IE_LEN); - - if (stats->freq == IEEE80211_52GHZ_BAND) { - /* for A band (No DS info) */ - network->channel = stats->received_channel; - } else - network->flags |= NETWORK_HAS_CCK; - - network->wpa_ie_len = 0; - network->rsn_ie_len = 0; - - info_element = &beacon->info_element; - left = stats->len - ((void *)info_element - (void *)beacon); - while (left >= sizeof(struct ieee80211_info_element_hdr)) { - if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) { - IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n", - info_element->len + sizeof(struct ieee80211_info_element), - left); - return 1; - } - - switch (info_element->id) { - case MFIE_TYPE_SSID: - if (ieee80211_is_empty_essid(info_element->data, - info_element->len)) { - network->flags |= NETWORK_EMPTY_ESSID; - break; - } - - network->ssid_len = min(info_element->len, - (u8)IW_ESSID_MAX_SIZE); - memcpy(network->ssid, info_element->data, network->ssid_len); - if (network->ssid_len < IW_ESSID_MAX_SIZE) - memset(network->ssid + network->ssid_len, 0, - IW_ESSID_MAX_SIZE - network->ssid_len); - - IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", - network->ssid, network->ssid_len); - break; - - case MFIE_TYPE_RATES: -#ifdef CONFIG_IEEE80211_DEBUG - p = rates_str; -#endif - network->rates_len = min(info_element->len, MAX_RATES_LENGTH); - for (i = 0; i < network->rates_len; i++) { - network->rates[i] = info_element->data[i]; - curRate = network->rates[i] & 0x7f; - if (hOpRate < curRate) - hOpRate = curRate; -#ifdef CONFIG_IEEE80211_DEBUG - p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); -#endif - if (ieee80211_is_ofdm_rate(info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - IEEE80211_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", - rates_str, network->rates_len); - break; - - case MFIE_TYPE_RATES_EX: -#ifdef CONFIG_IEEE80211_DEBUG - p = rates_str; -#endif - network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH); - for (i = 0; i < network->rates_ex_len; i++) { - network->rates_ex[i] = info_element->data[i]; - curRate_ex = network->rates_ex[i] & 0x7f; - if (hOpRate < curRate_ex) - hOpRate = curRate_ex; -#ifdef CONFIG_IEEE80211_DEBUG - p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); -#endif - if (ieee80211_is_ofdm_rate(info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - IEEE80211_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", - rates_str, network->rates_ex_len); - break; - - case MFIE_TYPE_DS_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", - info_element->data[0]); - if (stats->freq == IEEE80211_24GHZ_BAND) - network->channel = info_element->data[0]; - break; - - case MFIE_TYPE_FH_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); - break; - - case MFIE_TYPE_CF_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); - break; - - case MFIE_TYPE_TIM: - - if (info_element->len < 4) - break; - - network->dtim_period = info_element->data[1]; - - if (ieee->state != IEEE80211_LINKED) - break; - - network->last_dtim_sta_time[0] = jiffies; - network->last_dtim_sta_time[1] = stats->mac_time[1]; - - network->dtim_data = IEEE80211_DTIM_VALID; - - if (info_element->data[0] != 0) - break; - - if (info_element->data[2] & 1) - network->dtim_data |= IEEE80211_DTIM_MBCAST; - - offset = (info_element->data[2] >> 1)*2; - - //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id); - - /* add and modified for ps 2008.1.22 */ - if (ieee->assoc_id < 8*offset || - ieee->assoc_id > 8*(offset + info_element->len - 3)) { - break; - } - - offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ; - - // printk("offset:%x data:%x, ucast:%d\n", offset, - // info_element->data[3+offset] , - // info_element->data[3+offset] & (1<<(ieee->assoc_id%8))); - - if (info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) - network->dtim_data |= IEEE80211_DTIM_UCAST; - - break; - - case MFIE_TYPE_IBSS_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n"); - break; - - case MFIE_TYPE_CHALLENGE: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); - break; - - case MFIE_TYPE_GENERIC: - //nic is 87B - IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", - info_element->len); - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x01) { - network->wpa_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->wpa_ie, info_element, - network->wpa_ie_len); - } - - if (info_element->len == 7 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0xe0 && - info_element->data[2] == 0x4c && - info_element->data[3] == 0x01 && - info_element->data[4] == 0x02) { - network->Turbo_Enable = 1; - } - if (1 == stats->nic_type) //nic 87 - break; - - if (info_element->len >= 5 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x02 && - info_element->data[4] == 0x00) { - //printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]); - //WMM Information Element - network->wmm_info = info_element->data[6]; - network->QoS_Enable = 1; - } - - if (info_element->len >= 8 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x02 && - info_element->data[4] == 0x01) { - // Not care about version at present. - //WMM Information Element - //printk(KERN_WARNING "wmm info¶m updated: %x\n", info_element->data[6]); - network->wmm_info = info_element->data[6]; - //WMM Parameter Element - memcpy(network->wmm_param, (u8 *)(info_element->data + 8), (info_element->len - 8)); - network->QoS_Enable = 1; - } - break; - - case MFIE_TYPE_RSN: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", - info_element->len); - network->rsn_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->rsn_ie, info_element, - network->rsn_ie_len); - break; - case MFIE_TYPE_COUNTRY: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n", - info_element->len); -// printk("=====>Receive <%s> Country IE\n",network->ssid); - ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2); - break; - default: - IEEE80211_DEBUG_SCAN("unsupported IE %d\n", - info_element->id); - break; - } - - left -= sizeof(struct ieee80211_info_element_hdr) + - info_element->len; - info_element = (struct ieee80211_info_element *) - &info_element->data[info_element->len]; - } -//by amy 080312 - network->HighestOperaRate = hOpRate; -//by amy 080312 - network->mode = 0; - if (stats->freq == IEEE80211_52GHZ_BAND) - network->mode = IEEE_A; - else { - if (network->flags & NETWORK_HAS_OFDM) - network->mode |= IEEE_G; - if (network->flags & NETWORK_HAS_CCK) - network->mode |= IEEE_B; - } - - if (network->mode == 0) { - IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' " - "network.\n", - escape_essid(network->ssid, - network->ssid_len), - network->bssid); - return 1; - } - - if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) - network->flags |= NETWORK_EMPTY_ESSID; - - stats->signal = ieee80211_TranslateToDbm(stats->signalstrength); - //stats->noise = stats->signal - stats->noise; - stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25; - memcpy(&network->stats, stats, sizeof(network->stats)); - - return 0; -} - -static inline int is_same_network(struct ieee80211_network *src, - struct ieee80211_network *dst, - struct ieee80211_device *ieee) -{ - /* A network is only a duplicate if the channel, BSSID, ESSID - * and the capability field (in particular IBSS and BSS) all match. - * We treat all <hidden> with the same BSSID and channel - * as one network */ - return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap - //((src->ssid_len == dst->ssid_len) && - (src->channel == dst->channel) && - !memcmp(src->bssid, dst->bssid, ETH_ALEN) && - (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap - //!memcmp(src->ssid, dst->ssid, src->ssid_len) && - ((src->capability & WLAN_CAPABILITY_IBSS) == - (dst->capability & WLAN_CAPABILITY_IBSS)) && - ((src->capability & WLAN_CAPABILITY_BSS) == - (dst->capability & WLAN_CAPABILITY_BSS))); -} - -inline void update_network(struct ieee80211_network *dst, - struct ieee80211_network *src) -{ - unsigned char quality = src->stats.signalstrength; - unsigned char signal = 0; - unsigned char noise = 0; - if (dst->stats.signalstrength > 0) - quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6; - signal = ieee80211_TranslateToDbm(quality); - //noise = signal - src->stats.noise; - if (dst->stats.noise > 0) - noise = (dst->stats.noise * 5 + src->stats.noise)/6; - //if(strcmp(dst->ssid, "linksys_lzm000") == 0) -// printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal); - memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); - dst->stats.signalstrength = quality; - dst->stats.signal = signal; -// printk("==================>stats.signal is %d\n",dst->stats.signal); - dst->stats.noise = noise; - - - dst->capability = src->capability; - memcpy(dst->rates, src->rates, src->rates_len); - dst->rates_len = src->rates_len; - memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); - dst->rates_ex_len = src->rates_ex_len; - dst->HighestOperaRate = src->HighestOperaRate; - //printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel); - - //YJ,add,080819,for hidden ap - if (src->ssid_len > 0) { - //if(src->ssid_len == 13) - // printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid); - memset(dst->ssid, 0, dst->ssid_len); - dst->ssid_len = src->ssid_len; - memcpy(dst->ssid, src->ssid, src->ssid_len); - } - //YJ,add,080819,for hidden ap,end - - dst->channel = src->channel; - dst->mode = src->mode; - dst->flags = src->flags; - dst->time_stamp[0] = src->time_stamp[0]; - dst->time_stamp[1] = src->time_stamp[1]; - - dst->beacon_interval = src->beacon_interval; - dst->listen_interval = src->listen_interval; - dst->atim_window = src->atim_window; - dst->dtim_period = src->dtim_period; - dst->dtim_data = src->dtim_data; - dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0]; - dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1]; -// printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data); - memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); - dst->wpa_ie_len = src->wpa_ie_len; - memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); - dst->rsn_ie_len = src->rsn_ie_len; - - dst->last_scanned = jiffies; - /* dst->last_associate is not overwritten */ -// disable QoS process now, added by David 2006/7/25 -#if 1 - dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. -/* - if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter - memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN); - } -*/ - if (src->wmm_param[0].ac_aci_acm_aifsn || \ - src->wmm_param[1].ac_aci_acm_aifsn || \ - src->wmm_param[2].ac_aci_acm_aifsn || \ - src->wmm_param[3].ac_aci_acm_aifsn) { - memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); - } - dst->QoS_Enable = src->QoS_Enable; -#else - dst->QoS_Enable = 1;//for Rtl8187 simulation -#endif - dst->SignalStrength = src->SignalStrength; - dst->Turbo_Enable = src->Turbo_Enable; - dst->CountryIeLen = src->CountryIeLen; - memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen); -} - - -inline void -ieee80211_process_probe_response(struct ieee80211_device *ieee, - struct ieee80211_probe_response *beacon, - struct ieee80211_rx_stats *stats) -{ - struct ieee80211_network network; - struct ieee80211_network *target; - struct ieee80211_network *oldest = NULL; -#ifdef CONFIG_IEEE80211_DEBUG - struct ieee80211_info_element *info_element = &beacon->info_element; -#endif - unsigned long flags; - short renew; - u8 wmm_info; - u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON) ? 1 : 0; //YJ,add,080819,for hidden ap - - memset(&network, 0, sizeof(struct ieee80211_network)); - - IEEE80211_DEBUG_SCAN( - "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", - escape_essid(info_element->data, info_element->len), - beacon->header.addr3, - (beacon->capability & (1<<0xf)) ? '1' : '0', - (beacon->capability & (1<<0xe)) ? '1' : '0', - (beacon->capability & (1<<0xd)) ? '1' : '0', - (beacon->capability & (1<<0xc)) ? '1' : '0', - (beacon->capability & (1<<0xb)) ? '1' : '0', - (beacon->capability & (1<<0xa)) ? '1' : '0', - (beacon->capability & (1<<0x9)) ? '1' : '0', - (beacon->capability & (1<<0x8)) ? '1' : '0', - (beacon->capability & (1<<0x7)) ? '1' : '0', - (beacon->capability & (1<<0x6)) ? '1' : '0', - (beacon->capability & (1<<0x5)) ? '1' : '0', - (beacon->capability & (1<<0x4)) ? '1' : '0', - (beacon->capability & (1<<0x3)) ? '1' : '0', - (beacon->capability & (1<<0x2)) ? '1' : '0', - (beacon->capability & (1<<0x1)) ? '1' : '0', - (beacon->capability & (1<<0x0)) ? '1' : '0'); - - if (ieee80211_network_init(ieee, beacon, &network, stats)) { - IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", - escape_essid(info_element->data, - info_element->len), - beacon->header.addr3, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == - IEEE80211_STYPE_PROBE_RESP ? - "PROBE RESPONSE" : "BEACON"); - return; - } - - // For Asus EeePc request, - // (1) if wireless adapter receive get any 802.11d country code in AP beacon, - // wireless adapter should follow the country code. - // (2) If there is no any country code in beacon, - // then wireless adapter should do active scan from ch1~11 and - // passive scan from ch12~14 - if (ieee->bGlobalDomain) { - if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) { - // Case 1: Country code - if (IS_COUNTRY_IE_VALID(ieee)) { - if (!IsLegalChannel(ieee, network.channel)) { - printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel); - return; - } - } - // Case 2: No any country code. - else { - // Filter over channel ch12~14 - if (network.channel > 11) { - printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel); - return; - } - } - } else { - // Case 1: Country code - if (IS_COUNTRY_IE_VALID(ieee)) { - if (!IsLegalChannel(ieee, network.channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network.channel); - return; - } - } - // Case 2: No any country code. - else { - // Filter over channel ch12~14 - if (network.channel > 14) { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network.channel); - return; - } - } - } - } - /* The network parsed correctly -- so now we scan our known networks - * to see if we can find it in our list. - * - * NOTE: This search is definitely not optimized. Once its doing - * the "right thing" we'll optimize it for efficiency if - * necessary */ - - /* Search for this entry in the list and update it if it is - * already there. */ - - spin_lock_irqsave(&ieee->lock, flags); - - if (is_same_network(&ieee->current_network, &network, ieee)) { - wmm_info = ieee->current_network.wmm_info; - //YJ,add,080819,for hidden ap - if (is_beacon == 0) - network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); - else if (ieee->state == IEEE80211_LINKED) - ieee->NumRxBcnInPeriod++; - //YJ,add,080819,for hidden ap,end - //printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid); - update_network(&ieee->current_network, &network); - } - - list_for_each_entry(target, &ieee->network_list, list) { - if (is_same_network(target, &network, ieee)) - break; - if ((oldest == NULL) || - (target->last_scanned < oldest->last_scanned)) - oldest = target; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (&target->list == &ieee->network_list) { - if (list_empty(&ieee->network_free_list)) { - /* If there are no more slots, expire the oldest */ - list_del(&oldest->list); - target = oldest; - IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from " - "network list.\n", - escape_essid(target->ssid, - target->ssid_len), - target->bssid); - } else { - /* Otherwise just pull from the free list */ - target = list_entry(ieee->network_free_list.next, - struct ieee80211_network, list); - list_del(ieee->network_free_list.next); - } - - -#ifdef CONFIG_IEEE80211_DEBUG - IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", - escape_essid(network.ssid, - network.ssid_len), - network.bssid, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == - IEEE80211_STYPE_PROBE_RESP ? - "PROBE RESPONSE" : "BEACON"); -#endif - - memcpy(target, &network, sizeof(*target)); - list_add_tail(&target->list, &ieee->network_list); - } else { - IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", - escape_essid(target->ssid, - target->ssid_len), - target->bssid, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == - IEEE80211_STYPE_PROBE_RESP ? - "PROBE RESPONSE" : "BEACON"); - - /* we have an entry and we are going to update it. But this entry may - * be already expired. In this case we do the same as we found a new - * net and call the new_net handler - */ - renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); - //YJ,add,080819,for hidden ap - if (is_beacon == 0) - network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); - //if(strncmp(network.ssid, "linksys-c",9) == 0) - // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); - if (((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ - && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\ - || ((ieee->current_network.ssid_len == network.ssid_len) && (strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) - renew = 1; - //YJ,add,080819,for hidden ap,end - update_network(target, &network); - } - - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_rx_mgt(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header, - struct ieee80211_rx_stats *stats) -{ - switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { - - case IEEE80211_STYPE_BEACON: - IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); - IEEE80211_DEBUG_SCAN("Beacon\n"); - ieee80211_process_probe_response( - ieee, (struct ieee80211_probe_response *)header, stats); - break; - - case IEEE80211_STYPE_PROBE_RESP: - IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); - IEEE80211_DEBUG_SCAN("Probe response\n"); - ieee80211_process_probe_response( - ieee, (struct ieee80211_probe_response *)header, stats); - break; - } -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c deleted file mode 100644 index 03eb164..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ /dev/null @@ -1,2711 +0,0 @@ -/* IEEE 802.11 SoftMAC layer - * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> - * - * Mostly extracted from the rtl8180-sa2400 driver for the - * in-kernel generic ieee802.11 stack. - * - * Few lines might be stolen from other part of the ieee80211 - * stack. Copyright who own it's copyright - * - * WPA code stolen from the ipw2200 driver. - * Copyright who own it's copyright. - * - * released under the GPL - */ - -#include "ieee80211.h" - -#include <linux/random.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/uaccess.h> -#include <linux/etherdevice.h> - -#include "dot11d.h" - -short ieee80211_is_54g(const struct ieee80211_network *net) -{ - return (net->rates_ex_len > 0) || (net->rates_len > 4); -} - -short ieee80211_is_shortslot(const struct ieee80211_network *net) -{ - return net->capability & WLAN_CAPABILITY_SHORT_SLOT; -} - -/* returns the total length needed for placing the RATE MFIE - * tag and the EXTENDED RATE MFIE tag if needed. - * It encludes two bytes per tag for the tag itself and its len - */ -static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) -{ - unsigned int rate_len = 0; - - if (ieee->modulation & IEEE80211_CCK_MODULATION) - rate_len = IEEE80211_CCK_RATE_LEN + 2; - - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - - rate_len += IEEE80211_OFDM_RATE_LEN + 2; - - return rate_len; -} - -/* place the MFIE rate, tag to the memory (double) poised. - * Then it updates the pointer so that it points after the new MFIE tag added. - */ -static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - *tag++ = MFIE_TYPE_RATES; - *tag++ = 4; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - } - - /* We may add an option for custom rates that specific HW might support */ - *tag_p = tag; -} - -static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - if (ieee->modulation & IEEE80211_OFDM_MODULATION) { - *tag++ = MFIE_TYPE_RATES_EX; - *tag++ = 8; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; - - } - /* We may add an option for custom rates that specific HW might support */ - *tag_p = tag; -} - -static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_GENERIC; /* 0 */ - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0x50; - *tag++ = 0xf2; - *tag++ = 0x02; /* 5 */ - *tag++ = 0x00; - *tag++ = 0x01; -#ifdef SUPPORT_USPD - if (ieee->current_network.wmm_info & 0x80) - *tag++ = 0x0f|MAX_SP_Len; - else - *tag++ = MAX_SP_Len; -#else - *tag++ = MAX_SP_Len; -#endif - *tag_p = tag; -} - -static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - *tag++ = MFIE_TYPE_GENERIC; /* 0 */ - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0xe0; - *tag++ = 0x4c; - *tag++ = 0x01; /* 5 */ - *tag++ = 0x02; - *tag++ = 0x11; - *tag++ = 0x00; - *tag_p = tag; - printk(KERN_ALERT "This is enable turbo mode IE process\n"); -} - -static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb) -{ - int nh; - nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM; - - ieee->mgmt_queue_head = nh; - ieee->mgmt_queue_ring[nh] = skb; -} - -static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee) -{ - struct sk_buff *ret; - - if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head) - return NULL; - - ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail]; - - ieee->mgmt_queue_tail = - (ieee->mgmt_queue_tail + 1) % MGMT_QUEUE_NUM; - - return ret; -} - -static void init_mgmt_queue(struct ieee80211_device *ieee) -{ - ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; -} - -void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl); - -inline void softmac_mgmt_xmit(struct sk_buff *skb, - struct ieee80211_device *ieee) -{ - unsigned long flags; - short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *) skb->data; - - spin_lock_irqsave(&ieee->lock, flags); - - /* called with 2nd param 0, no mgmt lock required */ - ieee80211_sta_wakeup(ieee, 0); - - if (single) { - if (ieee->queue_stop) { - enqueue_mgmt(ieee, skb); - } else { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate); - } - - spin_unlock_irqrestore(&ieee->lock, flags); - } else { - spin_unlock_irqrestore(&ieee->lock, flags); - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); - - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_hard_start_xmit(skb, ieee->dev); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); - } -} - -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, - struct ieee80211_device *ieee) -{ - short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *) skb->data; - - if (single) { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate); - } else { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_hard_start_xmit(skb, ieee->dev); - } -} - -inline struct sk_buff * -ieee80211_disassociate_skb(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, u8 asRsn) -{ - struct sk_buff *skb; - struct ieee80211_disassoc_frame *disass; - - skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc_frame)); - if (!skb) - return NULL; - - disass = (struct ieee80211_disassoc_frame *) skb_put(skb, sizeof(struct ieee80211_disassoc_frame)); - disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC); - disass->header.duration_id = 0; - - memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); - memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN); - - disass->reasoncode = asRsn; - return skb; -} - -void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn) -{ - struct ieee80211_network *beacon = &ieee->current_network; - struct sk_buff *skb; - skb = ieee80211_disassociate_skb(beacon, ieee, asRsn); - if (skb) - softmac_mgmt_xmit(skb, ieee); -} - -inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) -{ - unsigned int len, rate_len; - u8 *tag; - struct sk_buff *skb; - struct ieee80211_probe_request *req; - - len = ieee->current_network.ssid_len; - - rate_len = ieee80211_MFIE_rate_len(ieee); - - skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + - 2 + len + rate_len); - if (!skb) - return NULL; - - req = (struct ieee80211_probe_request *) skb_put(skb, sizeof(struct ieee80211_probe_request)); - req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - req->header.duration_id = 0; /* FIXME: is this OK ? */ - - memset(req->header.addr1, 0xff, ETH_ALEN); - memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memset(req->header.addr3, 0xff, ETH_ALEN); - - tag = (u8 *) skb_put(skb, len + 2 + rate_len); - - *tag++ = MFIE_TYPE_SSID; - *tag++ = len; - memcpy(tag, ieee->current_network.ssid, len); - tag += len; - ieee80211_MFIE_Brate(ieee, &tag); - ieee80211_MFIE_Grate(ieee, &tag); - - return skb; -} - -struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee); - -static void ieee80211_send_beacon(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - - skb = ieee80211_get_beacon_(ieee); - - if (skb) { - softmac_mgmt_xmit(skb, ieee); - ieee->softmac_stats.tx_beacons++; - dev_kfree_skb_any(skb); - } - - ieee->beacon_timer.expires = jiffies + - (MSECS(ieee->current_network.beacon_interval - 5)); - - if (ieee->beacon_txing) - add_timer(&ieee->beacon_timer); -} - - -static void ieee80211_send_beacon_cb(unsigned long _ieee) -{ - struct ieee80211_device *ieee = - (struct ieee80211_device *) _ieee; - unsigned long flags; - - spin_lock_irqsave(&ieee->beacon_lock, flags); - ieee80211_send_beacon(ieee); - spin_unlock_irqrestore(&ieee->beacon_lock, flags); -} - -static void ieee80211_send_probe(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - - skb = ieee80211_probe_req(ieee); - if (skb) { - softmac_mgmt_xmit(skb, ieee); - ieee->softmac_stats.tx_probe_rq++; - } -} - -static void ieee80211_send_probe_requests(struct ieee80211_device *ieee) -{ - if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) { - ieee80211_send_probe(ieee); - ieee80211_send_probe(ieee); - } -} - -/* this performs syncro scan blocking the caller until all channels - * in the allowed channel map has been checked. - */ -static void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) -{ - short ch = 0; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); - down(&ieee->scan_sem); - - while (1) { - do { - ch++; - if (ch > MAX_CHANNEL_NUMBER) - goto out; /* scan completed */ - - } while (!channel_map[ch]); - /* this function can be called in two situations - * 1- We have switched to ad-hoc mode and we are - * performing a complete syncro scan before conclude - * there are no interesting cell and to create a - * new one. In this case the link state is - * IEEE80211_NOLINK until we found an interesting cell. - * If so the ieee8021_new_net, called by the RX path - * will set the state to IEEE80211_LINKED, so we stop - * scanning - * 2- We are linked and the root uses run iwlist scan. - * So we switch to IEEE80211_LINKED_SCANNING to remember - * that we are still logically linked (not interested in - * new network events, despite for updating the net list, - * but we are temporarily 'unlinked' as the driver shall - * not filter RX frames and the channel is changing. - * So the only situation in witch are interested is to check - * if the state become LINKED because of the #1 situation - */ - - if (ieee->state == IEEE80211_LINKED) - goto out; - - ieee->set_chan(ieee->dev, ch); - if (channel_map[ch] == 1) - ieee80211_send_probe_requests(ieee); - - /* this prevent excessive time wait when we - * need to wait for a syncro scan to end.. - */ - if (ieee->sync_scan_hurryup) - goto out; - - msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME); - } -out: - ieee->sync_scan_hurryup = 0; - up(&ieee->scan_sem); - if (IS_DOT11D_ENABLE(ieee)) - DOT11D_ScanComplete(ieee); -} - -void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee) -{ - int ch; - unsigned int watch_dog = 0; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); - down(&ieee->scan_sem); - ch = ieee->current_network.channel; - - while (1) { - /* this function can be called in two situations - * 1- We have switched to ad-hoc mode and we are - * performing a complete syncro scan before conclude - * there are no interesting cell and to create a - * new one. In this case the link state is - * IEEE80211_NOLINK until we found an interesting cell. - * If so the ieee8021_new_net, called by the RX path - * will set the state to IEEE80211_LINKED, so we stop - * scanning - * 2- We are linked and the root uses run iwlist scan. - * So we switch to IEEE80211_LINKED_SCANNING to remember - * that we are still logically linked (not interested in - * new network events, despite for updating the net list, - * but we are temporarily 'unlinked' as the driver shall - * not filter RX frames and the channel is changing. - * So the only situation in witch are interested is to check - * if the state become LINKED because of the #1 situation - */ - if (ieee->state == IEEE80211_LINKED) - goto out; - - if (channel_map[ieee->current_network.channel] > 0) - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - if (channel_map[ieee->current_network.channel] == 1) - ieee80211_send_probe_requests(ieee); - - msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME); - - do { - if (watch_dog++ >= MAX_CHANNEL_NUMBER) - goto out; /* scan completed */ - - ieee->current_network.channel = (ieee->current_network.channel + 1)%MAX_CHANNEL_NUMBER; - } while (!channel_map[ieee->current_network.channel]); - } -out: - ieee->actscanning = false; - up(&ieee->scan_sem); - if (IS_DOT11D_ENABLE(ieee)) - DOT11D_ScanComplete(ieee); -} - -static void ieee80211_softmac_scan_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq); - static short watchdog; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); - down(&ieee->scan_sem); - - do { - ieee->current_network.channel = - (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; - if (watchdog++ > MAX_CHANNEL_NUMBER) - goto out; /* no good chans */ - } while (!channel_map[ieee->current_network.channel]); - - if (ieee->scanning == 0) { - printk("error out, scanning = 0\n"); - goto out; - } - ieee->set_chan(ieee->dev, ieee->current_network.channel); - if (channel_map[ieee->current_network.channel] == 1) - ieee80211_send_probe_requests(ieee); - - queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME); - up(&ieee->scan_sem); - return; -out: - ieee->actscanning = false; - watchdog = 0; - ieee->scanning = 0; - up(&ieee->scan_sem); - - if (IS_DOT11D_ENABLE(ieee)) - DOT11D_ScanComplete(ieee); - return; -} - -static void ieee80211_beacons_start(struct ieee80211_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->beacon_lock, flags); - - ieee->beacon_txing = 1; - ieee80211_send_beacon(ieee); - - spin_unlock_irqrestore(&ieee->beacon_lock, flags); -} - -static void ieee80211_beacons_stop(struct ieee80211_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->beacon_lock, flags); - - ieee->beacon_txing = 0; - del_timer_sync(&ieee->beacon_timer); - - spin_unlock_irqrestore(&ieee->beacon_lock, flags); -} - -void ieee80211_stop_send_beacons(struct ieee80211_device *ieee) -{ - if (ieee->stop_send_beacons) - ieee->stop_send_beacons(ieee->dev); - if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) - ieee80211_beacons_stop(ieee); -} - -void ieee80211_start_send_beacons(struct ieee80211_device *ieee) -{ - if (ieee->start_send_beacons) - ieee->start_send_beacons(ieee->dev); - if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) - ieee80211_beacons_start(ieee); -} - -static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee) -{ - down(&ieee->scan_sem); - - if (ieee->scanning == 1) { - ieee->scanning = 0; - cancel_delayed_work(&ieee->softmac_scan_wq); - } - - up(&ieee->scan_sem); -} - -void ieee80211_stop_scan(struct ieee80211_device *ieee) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - ieee80211_softmac_stop_scan(ieee); - else - ieee->stop_scan(ieee->dev); -} - -/* called with ieee->lock held */ -void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) -{ - if (IS_DOT11D_ENABLE(ieee)) { - if (IS_COUNTRY_IE_VALID(ieee)) - RESET_CIE_WATCHDOG(ieee); - } - - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { - if (ieee->scanning == 0) { - ieee->scanning = 1; -#if 1 - queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0); -#endif - } - }else - ieee->start_scan(ieee->dev); -} - -/* called with wx_sem held */ -void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) -{ - if (IS_DOT11D_ENABLE(ieee)) { - if (IS_COUNTRY_IE_VALID(ieee)) - RESET_CIE_WATCHDOG(ieee); - } - ieee->sync_scan_hurryup = 0; - - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - ieee80211_softmac_scan_syncro(ieee); - else - ieee->scan_syncro(ieee->dev); -} - -inline struct sk_buff * -ieee80211_authentication_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, int challengelen) -{ - struct sk_buff *skb; - struct ieee80211_authentication *auth; - - skb = dev_alloc_skb(sizeof(struct ieee80211_authentication) + challengelen); - - if (!skb) - return NULL; - - auth = (struct ieee80211_authentication *) - skb_put(skb, sizeof(struct ieee80211_authentication)); - - auth->header.frame_ctl = IEEE80211_STYPE_AUTH; - if (challengelen) - auth->header.frame_ctl |= IEEE80211_FCTL_WEP; - - auth->header.duration_id = 0x013a; /* FIXME */ - - memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); - memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); - - auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; - - auth->transaction = cpu_to_le16(ieee->associate_seq); - ieee->associate_seq++; - - auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); - - return skb; -} - -static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, - u8 *dest) -{ - u8 *tag; - int beacon_size; - struct ieee80211_probe_response *beacon_buf; - struct sk_buff *skb; - int encrypt; - int atim_len, erp_len; - struct ieee80211_crypt_data *crypt; - - char *ssid = ieee->current_network.ssid; - int ssid_len = ieee->current_network.ssid_len; - int rate_len = ieee->current_network.rates_len+2; - int rate_ex_len = ieee->current_network.rates_ex_len; - int wpa_ie_len = ieee->wpa_ie_len; - if (rate_ex_len > 0) - rate_ex_len += 2; - - if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS) - atim_len = 4; - else - atim_len = 0; - - if (ieee80211_is_54g(&ieee->current_network)) - erp_len = 3; - else - erp_len = 0; - - beacon_size = sizeof(struct ieee80211_probe_response)+ - ssid_len - +3 /* channel */ - +rate_len - +rate_ex_len - +atim_len - +wpa_ie_len - +erp_len; - - skb = dev_alloc_skb(beacon_size); - - if (!skb) - return NULL; - - beacon_buf = (struct ieee80211_probe_response *) skb_put(skb, beacon_size); - - memcpy(beacon_buf->header.addr1, dest, ETH_ALEN); - memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); - - beacon_buf->header.duration_id = 0; /* FIXME */ - beacon_buf->beacon_interval = - cpu_to_le16(ieee->current_network.beacon_interval); - beacon_buf->capability = - cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); - - if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) - beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - - crypt = ieee->crypt[ieee->tx_keyidx]; - - encrypt = ieee->host_encrypt && crypt && crypt->ops && - ((0 == strcmp(crypt->ops->name, "WEP")) || wpa_ie_len); - - if (encrypt) - beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - - - beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); - - beacon_buf->info_element.id = MFIE_TYPE_SSID; - beacon_buf->info_element.len = ssid_len; - - tag = (u8 *) beacon_buf->info_element.data; - - memcpy(tag, ssid, ssid_len); - - tag += ssid_len; - - *(tag++) = MFIE_TYPE_RATES; - *(tag++) = rate_len - 2; - memcpy(tag, ieee->current_network.rates, rate_len-2); - tag += rate_len - 2; - - *(tag++) = MFIE_TYPE_DS_SET; - *(tag++) = 1; - *(tag++) = ieee->current_network.channel; - - if (atim_len) { - *(tag++) = MFIE_TYPE_IBSS_SET; - *(tag++) = 2; - *((u16 *)(tag)) = cpu_to_le16(ieee->current_network.atim_window); - tag += 2; - } - - if (erp_len) { - *(tag++) = MFIE_TYPE_ERP; - *(tag++) = 1; - *(tag++) = 0; - } - - if (rate_ex_len) { - *(tag++) = MFIE_TYPE_RATES_EX; - *(tag++) = rate_ex_len-2; - memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2); - tag += rate_ex_len - 2; - } - - if (wpa_ie_len) { - if (ieee->iw_mode == IW_MODE_ADHOC) { - /* as Windows will set pairwise key same as the group - * key which is not allowed in Linux, so set this for - * IOT issue. - */ - memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4); - } - - memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); - } - skb->dev = ieee->dev; - return skb; -} - -static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee, - u8 *dest) -{ - struct sk_buff *skb; - u8 *tag; - - struct ieee80211_crypt_data *crypt; - struct ieee80211_assoc_response_frame *assoc; - short encrypt; - - unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); - int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len; - - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - assoc = (struct ieee80211_assoc_response_frame *) - skb_put(skb, sizeof(struct ieee80211_assoc_response_frame)); - - assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); - memcpy(assoc->header.addr1, dest, ETH_ALEN); - memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); - memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? - WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS); - - if (ieee->short_slot) - assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - - if (ieee->host_encrypt) - crypt = ieee->crypt[ieee->tx_keyidx]; - else - crypt = NULL; - - encrypt = (crypt && crypt->ops); - - if (encrypt) - assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - - assoc->status = 0; - assoc->aid = cpu_to_le16(ieee->assoc_id); - if (ieee->assoc_id == 0x2007) - ieee->assoc_id = 0; - else - ieee->assoc_id++; - - tag = (u8 *) skb_put(skb, rate_len); - - ieee80211_MFIE_Brate(ieee, &tag); - ieee80211_MFIE_Grate(ieee, &tag); - - return skb; -} - -static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee, - int status, u8 *dest) -{ - struct sk_buff *skb; - struct ieee80211_authentication *auth; - - skb = dev_alloc_skb(sizeof(struct ieee80211_authentication)+1); - - if (!skb) - return NULL; - - skb->len = sizeof(struct ieee80211_authentication); - - auth = (struct ieee80211_authentication *)skb->data; - - auth->status = cpu_to_le16(status); - auth->transaction = cpu_to_le16(2); - auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN); - - memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); - memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(auth->header.addr1, dest, ETH_ALEN); - auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); - return skb; -} - -static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee, short pwr) -{ - struct sk_buff *skb; - struct ieee80211_hdr_3addr *hdr; - - skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr)); - - if (!skb) - return NULL; - - hdr = (struct ieee80211_hdr_3addr *)skb_put(skb, sizeof(struct ieee80211_hdr_3addr)); - - memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN); - memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); - - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | - (pwr ? IEEE80211_FCTL_PM:0)); - - return skb; -} - -static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest) -{ - struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest); - - if (buf) { - softmac_mgmt_xmit(buf, ieee); - dev_kfree_skb_any(buf); - } -} - -static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8 *dest) -{ - struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest); - - if (buf) { - softmac_mgmt_xmit(buf, ieee); - dev_kfree_skb_any(buf); - } -} - -static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) -{ - struct sk_buff *buf = ieee80211_probe_resp(ieee, dest); - - if (buf) { - softmac_mgmt_xmit(buf, ieee); - dev_kfree_skb_any(buf); - } -} - -inline struct sk_buff * -ieee80211_association_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - - struct ieee80211_assoc_request_frame *hdr; - u8 *tag; - unsigned int wpa_len = beacon->wpa_ie_len; -#if 1 - /* for testing purpose */ - unsigned int rsn_len = beacon->rsn_ie_len; -#endif - unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); - unsigned int wmm_info_len = beacon->QoS_Enable?9:0; - unsigned int turbo_info_len = beacon->Turbo_Enable?9:0; - - u8 encry_proto = ieee->wpax_type_notify & 0xff; - - int len = 0; - - /* [0] Notify type of encryption: WPA/WPA2 - * [1] pair wise type - * [2] authen type - */ - if (ieee->wpax_type_set) { - if (IEEE_PROTO_WPA == encry_proto) { - rsn_len = 0; - } else if (IEEE_PROTO_RSN == encry_proto) { - wpa_len = 0; - } - } - len = sizeof(struct ieee80211_assoc_request_frame)+ - + beacon->ssid_len /* essid tagged val */ - + rate_len /* rates tagged val */ - + wpa_len - + rsn_len - + wmm_info_len - + turbo_info_len; - - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - hdr = (struct ieee80211_assoc_request_frame *) - skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)); - - hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ; - hdr->header.duration_id = 37; /* FIXME */ - memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); - memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); - memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN); /* for HW security */ - - hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS); - if (beacon->capability & WLAN_CAPABILITY_PRIVACY) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - - if (ieee->short_slot) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - - hdr->listen_interval = 0xa; /* FIXME */ - - hdr->info_element.id = MFIE_TYPE_SSID; - - hdr->info_element.len = beacon->ssid_len; - tag = skb_put(skb, beacon->ssid_len); - memcpy(tag, beacon->ssid, beacon->ssid_len); - - tag = skb_put(skb, rate_len); - - ieee80211_MFIE_Brate(ieee, &tag); - ieee80211_MFIE_Grate(ieee, &tag); - - /* add rsn==0 condition for ap's mix security mode(wpa+wpa2) - * choose AES encryption as default algorithm while using mixed mode. - */ - - tag = skb_put(skb, ieee->wpa_ie_len); - memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); - - tag = skb_put(skb, wmm_info_len); - if (wmm_info_len) - ieee80211_WMM_Info(ieee, &tag); - - tag = skb_put(skb, turbo_info_len); - if (turbo_info_len) - ieee80211_TURBO_Info(ieee, &tag); - - return skb; -} - -void ieee80211_associate_abort(struct ieee80211_device *ieee) -{ - unsigned long flags; - spin_lock_irqsave(&ieee->lock, flags); - - ieee->associate_seq++; - - /* don't scan, and avoid to have the RX path possibly - * try again to associate. Even do not react to AUTH or - * ASSOC response. Just wait for the retry wq to be scheduled. - * Here we will check if there are good nets to associate - * with, so we retry or just get back to NO_LINK and scanning - */ - if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) { - IEEE80211_DEBUG_MGMT("Authentication failed\n"); - ieee->softmac_stats.no_auth_rs++; - } else { - IEEE80211_DEBUG_MGMT("Association failed\n"); - ieee->softmac_stats.no_ass_rs++; - } - - ieee->state = IEEE80211_ASSOCIATING_RETRY; - - queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, IEEE80211_SOFTMAC_ASSOC_RETRY_TIME); - - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static void ieee80211_associate_abort_cb(unsigned long dev) -{ - ieee80211_associate_abort((struct ieee80211_device *) dev); -} - -static void ieee80211_associate_step1(struct ieee80211_device *ieee) -{ - struct ieee80211_network *beacon = &ieee->current_network; - struct sk_buff *skb; - - IEEE80211_DEBUG_MGMT("Stopping scan\n"); - ieee->softmac_stats.tx_auth_rq++; - skb = ieee80211_authentication_req(beacon, ieee, 0); - if (!skb) { - ieee80211_associate_abort(ieee); - } else { - ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING; - IEEE80211_DEBUG_MGMT("Sending authentication request\n"); - softmac_mgmt_xmit(skb, ieee); - /* BUGON when you try to add_timer twice, using mod_timer may - * be better. - */ - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - /* If call dev_kfree_skb_any,a warning will ocur.... - * KERNEL: assertion (!atomic_read(&skb->users)) failed at - * net/core/dev.c (1708) - */ - } -} - -static void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, - int chlen) -{ - u8 *c; - struct sk_buff *skb; - struct ieee80211_network *beacon = &ieee->current_network; - del_timer_sync(&ieee->associate_timer); - ieee->associate_seq++; - ieee->softmac_stats.tx_auth_rq++; - - skb = ieee80211_authentication_req(beacon, ieee, chlen+2); - if (!skb) - ieee80211_associate_abort(ieee); - else { - c = skb_put(skb, chlen+2); - *(c++) = MFIE_TYPE_CHALLENGE; - *(c++) = chlen; - memcpy(c, challenge, chlen); - - IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n"); - - ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr)); - - softmac_mgmt_xmit(skb, ieee); - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - dev_kfree_skb_any(skb); - } - kfree(challenge); -} - -static void ieee80211_associate_step2(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - struct ieee80211_network *beacon = &ieee->current_network; - - del_timer_sync(&ieee->associate_timer); - - IEEE80211_DEBUG_MGMT("Sending association request\n"); - ieee->softmac_stats.tx_ass_rq++; - skb = ieee80211_association_req(beacon, ieee); - if (!skb) - ieee80211_associate_abort(ieee); - else { - softmac_mgmt_xmit(skb, ieee); - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - } -} - -static void ieee80211_associate_complete_wq(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); - - printk(KERN_INFO "Associated successfully\n"); - if (ieee80211_is_54g(&ieee->current_network) && - (ieee->modulation & IEEE80211_OFDM_MODULATION)) { - ieee->rate = 540; - printk(KERN_INFO"Using G rates\n"); - } else { - ieee->rate = 110; - printk(KERN_INFO"Using B rates\n"); - } - ieee->link_change(ieee->dev); - notify_wx_assoc_event(ieee); - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - netif_carrier_on(ieee->dev); -} - -static void ieee80211_associate_complete(struct ieee80211_device *ieee) -{ - del_timer_sync(&ieee->associate_timer); - - ieee->state = IEEE80211_LINKED; - IEEE80211_DEBUG_MGMT("Successfully associated\n"); - - queue_work(ieee->wq, &ieee->associate_complete_wq); -} - -static void ieee80211_associate_procedure_wq(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq); - - ieee->sync_scan_hurryup = 1; - down(&ieee->wx_sem); - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - - ieee80211_stop_scan(ieee); - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - ieee->associate_seq = 1; - ieee80211_associate_step1(ieee); - - up(&ieee->wx_sem); -} - -inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, - struct ieee80211_network *net) -{ - u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; - int tmp_ssid_len = 0; - - short apset, ssidset, ssidbroad, apmatch, ssidmatch; - - /* we are interested in new new only if we are not associated - * and we are not associating / authenticating - */ - if (ieee->state != IEEE80211_NOLINK) - return; - - if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS)) - return; - - if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS)) - return; - - if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) { - /* if the user specified the AP MAC, we need also the essid - * This could be obtained by beacons or, if the network does not - * broadcast it, it can be put manually. - */ - apset = ieee->wap_set; - ssidset = ieee->ssid_set; - ssidbroad = !(net->ssid_len == 0 || net->ssid[0] == '\0'); - apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN) == 0); - - if (ieee->current_network.ssid_len != net->ssid_len) - ssidmatch = 0; - else - ssidmatch = (0 == strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); - - /* if the user set the AP check if match. - * if the network does not broadcast essid we check the user - * supplied ANY essid - * if the network does broadcast and the user does not set essid - * it is OK - * if the network does broadcast and the user did set essid - * chech if essid match - * (apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || - * (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) || - * if the ap is not set, check that the user set the bssid and - * the network does broadcast and that those two bssid matches - * (!apset && ssidset && ssidbroad && ssidmatch) - */ - if ((apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || - (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) || - (!apset && ssidset && ssidbroad && ssidmatch)) { - /* if the essid is hidden replace it with the - * essid provided by the user. - */ - if (!ssidbroad) { - strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE); - tmp_ssid_len = ieee->current_network.ssid_len; - } - memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network)); - - if (!ssidbroad) { - strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE); - ieee->current_network.ssid_len = tmp_ssid_len; - } - printk(KERN_INFO"Linking with %s: channel is %d\n", ieee->current_network.ssid, ieee->current_network.channel); - - if (ieee->iw_mode == IW_MODE_INFRA) { - ieee->state = IEEE80211_ASSOCIATING; - ieee->beinretry = false; - queue_work(ieee->wq, &ieee->associate_procedure_wq); - } else { - if (ieee80211_is_54g(&ieee->current_network) && - (ieee->modulation & IEEE80211_OFDM_MODULATION)) { - ieee->rate = 540; - printk(KERN_INFO"Using G rates\n"); - } else { - ieee->rate = 110; - printk(KERN_INFO"Using B rates\n"); - } - ieee->state = IEEE80211_LINKED; - ieee->beinretry = false; - } - } - } -} - -void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee) -{ - unsigned long flags; - struct ieee80211_network *target; - - spin_lock_irqsave(&ieee->lock, flags); - list_for_each_entry(target, &ieee->network_list, list) { - /* if the state become different that NOLINK means - * we had found what we are searching for - */ - if (ieee->state != IEEE80211_NOLINK) - break; - - if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies)) - ieee80211_softmac_new_net(ieee, target); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen) -{ - struct ieee80211_authentication *a; - u8 *t; - if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) { - IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); - return 0xcafe; - } - *challenge = NULL; - a = (struct ieee80211_authentication *) skb->data; - if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) { - t = skb->data + sizeof(struct ieee80211_authentication); - - if (*(t++) == MFIE_TYPE_CHALLENGE) { - *chlen = *(t++); - *challenge = kmemdup(t, *chlen, GFP_ATOMIC); - if (!*challenge) - return -ENOMEM; - } - } - return cpu_to_le16(a->status); -} - -static int auth_rq_parse(struct sk_buff *skb, u8 *dest) -{ - struct ieee80211_authentication *a; - - if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) { - IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len); - return -1; - } - a = (struct ieee80211_authentication *) skb->data; - - memcpy(dest, a->header.addr2, ETH_ALEN); - - if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) - return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - - return WLAN_STATUS_SUCCESS; -} - -static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, - u8 *src) -{ - u8 *tag; - u8 *skbend; - u8 *ssid = NULL; - u8 ssidlen = 0; - - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *) skb->data; - - if (skb->len < sizeof(struct ieee80211_hdr_3addr)) - return -1; /* corrupted */ - - memcpy(src, header->addr2, ETH_ALEN); - - skbend = (u8 *)skb->data + skb->len; - - tag = skb->data + sizeof(struct ieee80211_hdr_3addr); - - while (tag+1 < skbend) { - if (*tag == 0) { - ssid = tag+2; - ssidlen = *(tag+1); - break; - } - tag++; /* point to the len field */ - tag = tag + *(tag); /* point to the last data byte of the tag */ - tag++; /* point to the next tag */ - } - - if (ssidlen == 0) - return 1; - - if (!ssid) - return 1; /* ssid not found in tagged param */ - - return (!strncmp(ssid, ieee->current_network.ssid, ssidlen)); - -} - -static int assoc_rq_parse(struct sk_buff *skb, u8 *dest) -{ - struct ieee80211_assoc_request_frame *a; - - if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) - - sizeof(struct ieee80211_info_element))) { - - IEEE80211_DEBUG_MGMT("invalid len in auth request:%d\n", skb->len); - return -1; - } - - a = (struct ieee80211_assoc_request_frame *) skb->data; - - memcpy(dest, a->header.addr2, ETH_ALEN); - - return 0; -} - -static inline u16 assoc_parse(struct sk_buff *skb, int *aid) -{ - struct ieee80211_assoc_response_frame *a; - if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) { - IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); - return 0xcafe; - } - - a = (struct ieee80211_assoc_response_frame *) skb->data; - *aid = le16_to_cpu(a->aid) & 0x3fff; - return le16_to_cpu(a->status); -} - -static inline void ieee80211_rx_probe_rq(struct ieee80211_device *ieee, - struct sk_buff *skb) -{ - u8 dest[ETH_ALEN]; - - ieee->softmac_stats.rx_probe_rq++; - if (probe_rq_parse(ieee, skb, dest)) { - ieee->softmac_stats.tx_probe_rs++; - ieee80211_resp_to_probe(ieee, dest); - } -} - -inline void ieee80211_rx_auth_rq(struct ieee80211_device *ieee, - struct sk_buff *skb) -{ - u8 dest[ETH_ALEN]; - int status; - ieee->softmac_stats.rx_auth_rq++; - - status = auth_rq_parse(skb, dest); - if (status != -1) - ieee80211_resp_to_auth(ieee, status, dest); -} - -inline void -ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb) -{ - - u8 dest[ETH_ALEN]; - - ieee->softmac_stats.rx_ass_rq++; - if (assoc_rq_parse(skb, dest) != -1) - ieee80211_resp_to_assoc_rq(ieee, dest); - - - printk(KERN_INFO"New client associated: %pM\n", dest); -} - -void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr) -{ - struct sk_buff *buf = ieee80211_null_func(ieee, pwr); - - if (buf) - softmac_ps_mgmt_xmit(buf, ieee); -} - -static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, - u32 *time_l) -{ - int timeout = 0; - - u8 dtim; - dtim = ieee->current_network.dtim_data; - - if (!(dtim & IEEE80211_DTIM_VALID)) - return 0; - else - timeout = ieee->current_network.beacon_interval; - - ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID; - - if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps)) - return 2; - - if (!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))) - return 0; - - if (!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))) - return 0; - - if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) && - (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) - return 0; - - if (time_l) { - *time_l = ieee->current_network.last_dtim_sta_time[0] - + MSECS((ieee->current_network.beacon_interval)); - } - - if (time_h) { - *time_h = ieee->current_network.last_dtim_sta_time[1]; - if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) - *time_h += 1; - } - - return 1; -} - -static inline void ieee80211_sta_ps(struct ieee80211_device *ieee) -{ - - u32 th, tl; - short sleep; - - unsigned long flags, flags2; - - spin_lock_irqsave(&ieee->lock, flags); - - if ((ieee->ps == IEEE80211_PS_DISABLED || - ieee->iw_mode != IW_MODE_INFRA || - ieee->state != IEEE80211_LINKED)) { - - /* #warning CHECK_LOCK_HERE */ - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - - ieee80211_sta_wakeup(ieee, 1); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - - sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl); - /* 2 wake, 1 sleep, 0 do nothing */ - if (sleep == 0) - goto out; - - if (sleep == 1) { - if (ieee->sta_sleep == 1) - ieee->enter_sleep_state(ieee->dev, th, tl); - - else if (ieee->sta_sleep == 0) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - if (ieee->ps_is_queue_empty(ieee->dev)) { - ieee->sta_sleep = 2; - - ieee->ps_request_tx_ack(ieee->dev); - - ieee80211_sta_ps_send_null_frame(ieee, 1); - - ieee->ps_th = th; - ieee->ps_tl = tl; - } - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - } else if (sleep == 2) { - /* #warning CHECK_LOCK_HERE */ - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - - ieee80211_sta_wakeup(ieee, 1); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } -out: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl) -{ - if (ieee->sta_sleep == 0) { - if (nl) { - ieee->ps_request_tx_ack(ieee->dev); - ieee80211_sta_ps_send_null_frame(ieee, 0); - } - return; - } - - if (ieee->sta_sleep == 1) - ieee->sta_wake_up(ieee->dev); - - ieee->sta_sleep = 0; - - if (nl) { - ieee->ps_request_tx_ack(ieee->dev); - ieee80211_sta_ps_send_null_frame(ieee, 0); - } -} - -void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success) -{ - unsigned long flags, flags2; - - spin_lock_irqsave(&ieee->lock, flags); - if (ieee->sta_sleep == 2) { - /* Null frame with PS bit set */ - if (success) { - ieee->sta_sleep = 1; - ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl); - } - /* if the card report not success we can't be sure the AP - * has not RXed so we can't assume the AP believe us awake - */ - } else { - if ((ieee->sta_sleep == 0) && !success) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - ieee80211_sta_ps_send_null_frame(ieee, 0); - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -inline int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, - struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, - u16 type, u16 stype) -{ - struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data; - u16 errcode; - u8 *challenge = NULL; - int chlen = 0; - int aid = 0; - struct ieee80211_assoc_response_frame *assoc_resp; - struct ieee80211_info_element *info_element; - - if (!ieee->proto_started) - return 0; - - if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED && - ieee->iw_mode == IW_MODE_INFRA && - ieee->state == IEEE80211_LINKED)) - - tasklet_schedule(&ieee->ps_task); - - if (WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_PROBE_RESP && - WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_BEACON) - ieee->last_rx_ps_time = jiffies; - - switch (WLAN_FC_GET_STYPE(header->frame_control)) { - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: - IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && - ieee->iw_mode == IW_MODE_INFRA) { - errcode = assoc_parse(skb, &aid); - if (0 == errcode) { - u16 left; - - ieee->state = IEEE80211_LINKED; - ieee->assoc_id = aid; - ieee->softmac_stats.rx_ass_ok++; - /* card type is 8187 */ - if (1 == rx_stats->nic_type) - goto associate_complete; - - assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data; - info_element = &assoc_resp->info_element; - left = skb->len - ((void *)info_element - (void *)assoc_resp); - - while (left >= sizeof(struct ieee80211_info_element_hdr)) { - if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) { - printk(KERN_WARNING "[re]associate response error!"); - return 1; - } - switch (info_element->id) { - case MFIE_TYPE_GENERIC: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", info_element->len); - if (info_element->len >= 8 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x02 && - info_element->data[4] == 0x01) { - /* Not care about version at present. - * WMM Parameter Element. - */ - memcpy(ieee->current_network.wmm_param, (u8 *)(info_element->data\ - + 8), (info_element->len - 8)); - - if (((ieee->current_network.wmm_info^info_element->data[6])& \ - 0x0f) || (!ieee->init_wmmparam_flag)) { - /* refresh parameter element for current network - * update the register parameter for hardware. - */ - ieee->init_wmmparam_flag = 1; - queue_work(ieee->wq, &ieee->wmm_param_update_wq); - } - /* update info_element for current network */ - ieee->current_network.wmm_info = info_element->data[6]; - } - break; - default: - /* nothing to do at present!!! */ - break; - } - - left -= sizeof(struct ieee80211_info_element_hdr) + - info_element->len; - info_element = (struct ieee80211_info_element *) - &info_element->data[info_element->len]; - } - /* legacy AP, reset the AC_xx_param register */ - if (!ieee->init_wmmparam_flag) { - queue_work(ieee->wq, &ieee->wmm_param_update_wq); - ieee->init_wmmparam_flag = 1; /* indicate AC_xx_param upated since last associate */ - } -associate_complete: - ieee80211_associate_complete(ieee); - } else { - ieee->softmac_stats.rx_ass_err++; - IEEE80211_DEBUG_MGMT( - "Association response status code 0x%x\n", - errcode); - ieee80211_associate_abort(ieee); - } - } - break; - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->iw_mode == IW_MODE_MASTER) - - ieee80211_rx_assoc_rq(ieee, skb); - break; - case IEEE80211_STYPE_AUTH: - if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) { - if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING && - ieee->iw_mode == IW_MODE_INFRA){ - IEEE80211_DEBUG_MGMT("Received authentication response"); - - errcode = auth_parse(skb, &challenge, &chlen); - if (0 == errcode) { - if (ieee->open_wep || !challenge) { - ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED; - ieee->softmac_stats.rx_auth_rs_ok++; - - ieee80211_associate_step2(ieee); - } else { - ieee80211_rtl_auth_challenge(ieee, challenge, chlen); - } - } else { - ieee->softmac_stats.rx_auth_rs_err++; - IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x", errcode); - ieee80211_associate_abort(ieee); - } - - } else if (ieee->iw_mode == IW_MODE_MASTER) { - ieee80211_rx_auth_rq(ieee, skb); - } - } - break; - case IEEE80211_STYPE_PROBE_REQ: - if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && - ((ieee->iw_mode == IW_MODE_ADHOC || - ieee->iw_mode == IW_MODE_MASTER) && - ieee->state == IEEE80211_LINKED)) - - ieee80211_rx_probe_rq(ieee, skb); - break; - case IEEE80211_STYPE_DISASSOC: - case IEEE80211_STYPE_DEAUTH: - /* FIXME for now repeat all the association procedure - * both for disassociation and deauthentication - */ - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - (ieee->state == IEEE80211_LINKED) && - (ieee->iw_mode == IW_MODE_INFRA) && - (!memcmp(header->addr2, ieee->current_network.bssid, ETH_ALEN))) { - ieee->state = IEEE80211_ASSOCIATING; - ieee->softmac_stats.reassoc++; - - queue_work(ieee->wq, &ieee->associate_procedure_wq); - } - break; - default: - return -1; - break; - } - return 0; -} - -/* following are for a simpler TX queue management. - * Instead of using netif_[stop/wake]_queue the driver - * will uses these two function (plus a reset one), that - * will internally uses the kernel netif_* and takes - * care of the ieee802.11 fragmentation. - * So the driver receives a fragment per time and might - * call the stop function when it want without take care - * to have enough room to TX an entire packet. - * This might be useful if each fragment need it's own - * descriptor, thus just keep a total free memory > than - * the max fragmentation threshold is not enough.. If the - * ieee802.11 stack passed a TXB struct then you needed - * to keep N free descriptors where - * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD - * In this way you need just one and the 802.11 stack - * will take care of buffering fragments and pass them to - * to the driver later, when it wakes the queue. - */ - -void ieee80211_softmac_xmit(struct ieee80211_txb *txb, - struct ieee80211_device *ieee) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&ieee->lock, flags); - - /* called with 2nd parm 0, no tx mgmt lock required */ - ieee80211_sta_wakeup(ieee, 0); - - for (i = 0; i < txb->nr_frags; i++) { - if (ieee->queue_stop) { - ieee->tx_pending.txb = txb; - ieee->tx_pending.frag = i; - goto exit; - } else { - ieee->softmac_data_hard_start_xmit( - txb->fragments[i], - ieee->dev, ieee->rate); - ieee->stats.tx_packets++; - ieee->stats.tx_bytes += txb->fragments[i]->len; - ieee->dev->trans_start = jiffies; - } - } - - ieee80211_txb_free(txb); - - exit: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -/* called with ieee->lock acquired */ -static void ieee80211_resume_tx(struct ieee80211_device *ieee) -{ - int i; - for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) { - - if (ieee->queue_stop) { - ieee->tx_pending.frag = i; - return; - } else { - ieee->softmac_data_hard_start_xmit( - ieee->tx_pending.txb->fragments[i], - ieee->dev, ieee->rate); - ieee->stats.tx_packets++; - ieee->dev->trans_start = jiffies; - } - } - - ieee80211_txb_free(ieee->tx_pending.txb); - ieee->tx_pending.txb = NULL; -} - -void ieee80211_reset_queue(struct ieee80211_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->lock, flags); - init_mgmt_queue(ieee); - if (ieee->tx_pending.txb) { - ieee80211_txb_free(ieee->tx_pending.txb); - ieee->tx_pending.txb = NULL; - } - ieee->queue_stop = 0; - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) -{ - unsigned long flags; - struct sk_buff *skb; - struct ieee80211_hdr_3addr *header; - - spin_lock_irqsave(&ieee->lock, flags); - if (!ieee->queue_stop) - goto exit; - - ieee->queue_stop = 0; - - if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) { - while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) { - header = (struct ieee80211_hdr_3addr *) skb->data; - - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate); - dev_kfree_skb_any(skb); - } - } - if (!ieee->queue_stop && ieee->tx_pending.txb) - ieee80211_resume_tx(ieee); - - if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) { - ieee->softmac_stats.swtxawake++; - netif_wake_queue(ieee->dev); - } -exit: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) -{ - if (!netif_queue_stopped(ieee->dev)) { - netif_stop_queue(ieee->dev); - ieee->softmac_stats.swtxstop++; - } - ieee->queue_stop = 1; -} - -inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) -{ - random_ether_addr(ieee->current_network.bssid); -} - -/* called in user context only */ -void ieee80211_start_master_bss(struct ieee80211_device *ieee) -{ - ieee->assoc_id = 1; - - if (ieee->current_network.ssid_len == 0) { - strncpy(ieee->current_network.ssid, - IEEE80211_DEFAULT_TX_ESSID, - IW_ESSID_MAX_SIZE); - - ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); - ieee->ssid_set = 1; - } - - memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN); - - ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->state = IEEE80211_LINKED; - ieee->link_change(ieee->dev); - notify_wx_assoc_event(ieee); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); -} - -static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee) -{ - if (ieee->raw_tx) { - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); - } -} - -static void ieee80211_start_ibss_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq); - - /* iwconfig mode ad-hoc will schedule this and return - * on the other hand this will block further iwconfig SET - * operations because of the wx_sem hold. - * Anyway some most set operations set a flag to speed-up - * (abort) this wq (when syncro scanning) before sleeping - * on the semaphore - */ - - down(&ieee->wx_sem); - - if (ieee->current_network.ssid_len == 0) { - strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID); - ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); - ieee->ssid_set = 1; - } - - /* check if we have this cell in our network list */ - ieee80211_softmac_check_all_nets(ieee); - - if (ieee->state == IEEE80211_NOLINK) - ieee->current_network.channel = 10; - /* if not then the state is not linked. Maybe the user switched to - * ad-hoc mode just after being in monitor mode, or just after - * being very few time in managed mode (so the card have had no - * time to scan all the chans..) or we have just run up the iface - * after setting ad-hoc mode. So we have to give another try.. - * Here, in ibss mode, should be safe to do this without extra care - * (in bss mode we had to make sure no-one tried to associate when - * we had just checked the ieee->state and we was going to start the - * scan) because in ibss mode the ieee80211_new_net function, when - * finds a good net, just set the ieee->state to IEEE80211_LINKED, - * so, at worst, we waste a bit of time to initiate an unneeded syncro - * scan, that will stop at the first round because it sees the state - * associated. - */ - if (ieee->state == IEEE80211_NOLINK) - ieee80211_start_scan_syncro(ieee); - - /* the network definitively is not here.. create a new cell */ - if (ieee->state == IEEE80211_NOLINK) { - printk("creating new IBSS cell\n"); - if (!ieee->wap_set) - ieee80211_randomize_cell(ieee); - - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - ieee->current_network.rates_len = 4; - - ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - - } else - ieee->current_network.rates_len = 0; - - if (ieee->modulation & IEEE80211_OFDM_MODULATION) { - ieee->current_network.rates_ex_len = 8; - - ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; - ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; - ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; - ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; - ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; - ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; - ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; - ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; - - ieee->rate = 540; - } else { - ieee->current_network.rates_ex_len = 0; - ieee->rate = 110; - } - - /* By default, WMM function will be disabled in IBSS mode */ - ieee->current_network.QoS_Enable = 0; - - ieee->current_network.atim_window = 0; - ieee->current_network.capability = WLAN_CAPABILITY_IBSS; - if (ieee->short_slot) - ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT; - } - - ieee->state = IEEE80211_LINKED; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->link_change(ieee->dev); - - notify_wx_assoc_event(ieee); - - ieee80211_start_send_beacons(ieee); - printk(KERN_WARNING "after sending beacon packet!\n"); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); - - up(&ieee->wx_sem); -} - -inline void ieee80211_start_ibss(struct ieee80211_device *ieee) -{ - queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 100); -} - -/* this is called only in user context, with wx_sem held */ -void ieee80211_start_bss(struct ieee80211_device *ieee) -{ - unsigned long flags; - /* Ref: 802.11d 11.1.3.3 - * STA shall not start a BSS unless properly formed Beacon frame - * including a Country IE. - */ - if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) { - if (!ieee->bGlobalDomain) - return; - } - /* check if we have already found the net we are interested in (if any). - * if not (we are disassociated and we are not - * in associating / authenticating phase) start the background scanning. - */ - ieee80211_softmac_check_all_nets(ieee); - - /* ensure no-one start an associating process (thus setting - * the ieee->state to ieee80211_ASSOCIATING) while we - * have just cheked it and we are going to enable scan. - * The ieee80211_new_net function is always called with - * lock held (from both ieee80211_softmac_check_all_nets and - * the rx path), so we cannot be in the middle of such function - */ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->state == IEEE80211_NOLINK) { - ieee->actscanning = true; - ieee80211_rtl_start_scan(ieee); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -/* called only in userspace context */ -void ieee80211_disassociate(struct ieee80211_device *ieee) -{ - netif_carrier_off(ieee->dev); - - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) - ieee80211_reset_queue(ieee); - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - - if (IS_DOT11D_ENABLE(ieee)) - Dot11d_Reset(ieee); - - ieee->link_change(ieee->dev); - if (ieee->state == IEEE80211_LINKED) - notify_wx_assoc_event(ieee); - ieee->state = IEEE80211_NOLINK; - -} -static void ieee80211_associate_retry_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq); - unsigned long flags; - down(&ieee->wx_sem); - if (!ieee->proto_started) - goto exit; - if (ieee->state != IEEE80211_ASSOCIATING_RETRY) - goto exit; - /* until we do not set the state to IEEE80211_NOLINK - * there are no possibility to have someone else trying - * to start an association procedure (we get here with - * ieee->state = IEEE80211_ASSOCIATING). - * When we set the state to IEEE80211_NOLINK it is possible - * that the RX path run an attempt to associate, but - * both ieee80211_softmac_check_all_nets and the - * RX path works with ieee->lock held so there are no - * problems. If we are still disassociated then start a scan. - * the lock here is necessary to ensure no one try to start - * an association procedure when we have just checked the - * state and we are going to start the scan. - */ - ieee->state = IEEE80211_NOLINK; - ieee->beinretry = true; - ieee80211_softmac_check_all_nets(ieee); - - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->state == IEEE80211_NOLINK) { - ieee->beinretry = false; - ieee->actscanning = true; - ieee80211_rtl_start_scan(ieee); - } - if (ieee->state == IEEE80211_NOLINK) - notify_wx_assoc_event(ieee); - spin_unlock_irqrestore(&ieee->lock, flags); - -exit: - up(&ieee->wx_sem); -} - -struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) -{ - u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - struct sk_buff *skb = NULL; - struct ieee80211_probe_response *b; - - skb = ieee80211_probe_resp(ieee, broadcast_addr); - if (!skb) - return NULL; - - b = (struct ieee80211_probe_response *) skb->data; - b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); - - return skb; -} - -struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - struct ieee80211_probe_response *b; - - skb = ieee80211_get_beacon_(ieee); - if (!skb) - return NULL; - - b = (struct ieee80211_probe_response *) skb->data; - b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - return skb; -} - -void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee) -{ - ieee->sync_scan_hurryup = 1; - down(&ieee->wx_sem); - ieee80211_stop_protocol(ieee); - up(&ieee->wx_sem); -} - -void ieee80211_stop_protocol(struct ieee80211_device *ieee) -{ - if (!ieee->proto_started) - return; - - ieee->proto_started = 0; - - ieee80211_stop_send_beacons(ieee); - if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_LINKED)) - SendDisassociation(ieee, NULL, WLAN_REASON_DISASSOC_STA_HAS_LEFT); - - del_timer_sync(&ieee->associate_timer); - cancel_delayed_work(&ieee->associate_retry_wq); - cancel_delayed_work(&ieee->start_ibss_wq); - ieee80211_stop_scan(ieee); - - ieee80211_disassociate(ieee); -} - -void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee) -{ - ieee->sync_scan_hurryup = 0; - down(&ieee->wx_sem); - ieee80211_start_protocol(ieee); - up(&ieee->wx_sem); -} - -void ieee80211_start_protocol(struct ieee80211_device *ieee) -{ - short ch = 0; - int i = 0; - - if (ieee->proto_started) - return; - - ieee->proto_started = 1; - - if (ieee->current_network.channel == 0) { - do { - ch++; - if (ch > MAX_CHANNEL_NUMBER) - return; /* no channel found */ - - } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]); - - ieee->current_network.channel = ch; - } - - if (ieee->current_network.beacon_interval == 0) - ieee->current_network.beacon_interval = 100; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - for (i = 0; i < 17; i++) { - ieee->last_rxseq_num[i] = -1; - ieee->last_rxfrag_num[i] = -1; - ieee->last_packet_time[i] = 0; - } - - ieee->init_wmmparam_flag = 0; /* reinitialize AC_xx_PARAM registers. */ - - /* if the user set the MAC of the ad-hoc cell and then - * switch to managed mode, shall we make sure that association - * attempts does not fail just because the user provide the essid - * and the nic is still checking for the AP MAC ?? - */ - switch (ieee->iw_mode) { - case IW_MODE_AUTO: - ieee->iw_mode = IW_MODE_INFRA; - /* not set break here intentionly */ - case IW_MODE_INFRA: - ieee80211_start_bss(ieee); - break; - - case IW_MODE_ADHOC: - ieee80211_start_ibss(ieee); - break; - - case IW_MODE_MASTER: - ieee80211_start_master_bss(ieee); - break; - - case IW_MODE_MONITOR: - ieee80211_start_monitor_mode(ieee); - break; - - default: - ieee->iw_mode = IW_MODE_INFRA; - ieee80211_start_bss(ieee); - break; - } -} - -#define DRV_NAME "Ieee80211" -void ieee80211_softmac_init(struct ieee80211_device *ieee) -{ - int i; - memset(&ieee->current_network, 0, sizeof(struct ieee80211_network)); - - ieee->state = IEEE80211_NOLINK; - ieee->sync_scan_hurryup = 0; - for (i = 0; i < 5; i++) - ieee->seq_ctrl[i] = 0; - - ieee->assoc_id = 0; - ieee->queue_stop = 0; - ieee->scanning = 0; - ieee->softmac_features = 0; /* so IEEE2100-like driver are happy */ - ieee->wap_set = 0; - ieee->ssid_set = 0; - ieee->proto_started = 0; - ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE; - ieee->rate = 3; - ieee->ps = IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST; - ieee->sta_sleep = 0; - ieee->bInactivePs = false; - ieee->actscanning = false; - ieee->ListenInterval = 2; - ieee->NumRxDataInPeriod = 0; - ieee->NumRxBcnInPeriod = 0; - ieee->NumRxOkTotal = 0; - ieee->NumRxUnicast = 0; /* for keep alive */ - ieee->beinretry = false; - ieee->bHwRadioOff = false; - - init_mgmt_queue(ieee); - - ieee->tx_pending.txb = NULL; - - init_timer(&ieee->associate_timer); - ieee->associate_timer.data = (unsigned long)ieee; - ieee->associate_timer.function = ieee80211_associate_abort_cb; - - init_timer(&ieee->beacon_timer); - ieee->beacon_timer.data = (unsigned long) ieee; - ieee->beacon_timer.function = ieee80211_send_beacon_cb; - - ieee->wq = create_workqueue(DRV_NAME); - - INIT_DELAYED_WORK(&ieee->start_ibss_wq, (void *) ieee80211_start_ibss_wq); - INIT_WORK(&ieee->associate_complete_wq, (void *) ieee80211_associate_complete_wq); - INIT_WORK(&ieee->associate_procedure_wq, (void *) ieee80211_associate_procedure_wq); - INIT_DELAYED_WORK(&ieee->softmac_scan_wq, (void *) ieee80211_softmac_scan_wq); - INIT_DELAYED_WORK(&ieee->associate_retry_wq, (void *) ieee80211_associate_retry_wq); - INIT_WORK(&ieee->wx_sync_scan_wq, (void *) ieee80211_wx_sync_scan_wq); - - sema_init(&ieee->wx_sem, 1); - sema_init(&ieee->scan_sem, 1); - - spin_lock_init(&ieee->mgmt_tx_lock); - spin_lock_init(&ieee->beacon_lock); - - tasklet_init(&ieee->ps_task, - (void(*)(unsigned long)) ieee80211_sta_ps, - (unsigned long)ieee); - ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC); -} - -void ieee80211_softmac_free(struct ieee80211_device *ieee) -{ - down(&ieee->wx_sem); - - del_timer_sync(&ieee->associate_timer); - cancel_delayed_work(&ieee->associate_retry_wq); - - /* add for RF power on power of */ - cancel_delayed_work(&ieee->GPIOChangeRFWorkItem); - - destroy_workqueue(ieee->wq); - kfree(ieee->pDot11dInfo); - up(&ieee->wx_sem); -} - -/* Start of WPA code. This is stolen from the ipw2200 driver */ -static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value) -{ - /* This is called when wpa_supplicant loads and closes the driver - * interface. */ - printk("%s WPA\n", value ? "enabling" : "disabling"); - ieee->wpa_enabled = value; - return 0; -} - -static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, - int wpa_ie_len) -{ - /* make sure WPA is enabled */ - ieee80211_wpa_enable(ieee, 1); - - ieee80211_disassociate(ieee); -} - -static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, - int reason) -{ - int ret = 0; - - switch (command) { - case IEEE_MLME_STA_DEAUTH: - /* silently ignore */ - break; - - case IEEE_MLME_STA_DISASSOC: - ieee80211_disassociate(ieee); - break; - - default: - printk("Unknown MLME request: %d\n", command); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee, - struct ieee_param *param, int plen) -{ - u8 *buf; - - if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || - (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) - return -EINVAL; - - if (param->u.wpa_ie.len) { - buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len, - GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = param->u.wpa_ie.len; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - - ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len); - return 0; -} - -#define AUTH_ALG_OPEN_SYSTEM 0x1 -#define AUTH_ALG_SHARED_KEY 0x2 - -static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value) -{ - struct ieee80211_security sec = { - .flags = SEC_AUTH_MODE, - }; - int ret = 0; - - if (value & AUTH_ALG_SHARED_KEY) { - sec.auth_mode = WLAN_AUTH_SHARED_KEY; - ieee->open_wep = 0; - } else { - sec.auth_mode = WLAN_AUTH_OPEN; - ieee->open_wep = 1; - } - - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - else - ret = -EOPNOTSUPP; - - return ret; -} - -static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, - u32 value) -{ - int ret = 0; - unsigned long flags; - - switch (name) { - case IEEE_PARAM_WPA_ENABLED: - ret = ieee80211_wpa_enable(ieee, value); - break; - - case IEEE_PARAM_TKIP_COUNTERMEASURES: - ieee->tkip_countermeasures = value; - break; - - case IEEE_PARAM_DROP_UNENCRYPTED: { - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - struct ieee80211_security sec = { - .flags = SEC_ENABLED, - .enabled = value, - }; - ieee->drop_unencrypted = value; - /* We only change SEC_LEVEL for open mode. Others - * are set by ipw_wpa_set_encryption. - */ - if (!value) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_0; - } else { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - break; - } - - case IEEE_PARAM_PRIVACY_INVOKED: - ieee->privacy_invoked = value; - break; - case IEEE_PARAM_AUTH_ALGS: - ret = ieee80211_wpa_set_auth_algs(ieee, value); - break; - case IEEE_PARAM_IEEE_802_1X: - ieee->ieee802_1x = value; - break; - case IEEE_PARAM_WPAX_SELECT: - spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags); - ieee->wpax_type_set = 1; - ieee->wpax_type_notify = value; - spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags); - break; - default: - printk("Unknown WPA param: %d\n", name); - ret = -EOPNOTSUPP; - } - - return ret; -} - -/* implementation borrowed from hostap driver */ - -static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, - struct ieee_param *param, int param_len) -{ - int ret = 0; - - struct ieee80211_crypto_ops *ops; - struct ieee80211_crypt_data **crypt; - - struct ieee80211_security sec = { - .flags = 0, - }; - - param->u.crypt.err = 0; - param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len != - (int) ((char *) param->u.crypt.key - (char *) param) + - param->u.crypt.key_len) { - printk("Len mismatch %d, %d\n", param_len, - param->u.crypt.key_len); - return -EINVAL; - } - if (is_broadcast_ether_addr(param->sta_addr)) { - if (param->u.crypt.idx >= WEP_KEYS) - return -EINVAL; - crypt = &ieee->crypt[param->u.crypt.idx]; - } else { - return -EINVAL; - } - - if (strcmp(param->u.crypt.alg, "none") == 0) { - if (crypt) { - sec.enabled = 0; - /* FIXME FIXME */ - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; - ieee80211_crypt_delayed_deinit(ieee, crypt); - } - goto done; - } - sec.enabled = 1; - /* FIXME FIXME */ - sec.flags |= SEC_ENABLED; - - /* IPW HW cannot build TKIP MIC, host decryption still needed. */ - if (!(ieee->host_encrypt || ieee->host_decrypt) && - strcmp(param->u.crypt.alg, "TKIP")) - goto skip_host_crypt; - - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL) { - printk("unknown crypto alg '%s'\n", param->u.crypt.alg); - param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; - ret = -EINVAL; - goto done; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct ieee80211_crypt_data *new_crypt; - - ieee80211_crypt_delayed_deinit(ieee, crypt); - - new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); - new_crypt->ops = ops; - if (new_crypt->ops) - new_crypt->priv = - new_crypt->ops->init(param->u.crypt.idx); - - if (new_crypt->priv == NULL) { - kfree(new_crypt); - param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED; - ret = -EINVAL; - goto done; - } - - *crypt = new_crypt; - } - - if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(param->u.crypt.key, - param->u.crypt.key_len, param->u.crypt.seq, - (*crypt)->priv) < 0) { - printk("key setting failed\n"); - param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED; - ret = -EINVAL; - goto done; - } - - skip_host_crypt: - if (param->u.crypt.set_tx) { - ieee->tx_keyidx = param->u.crypt.idx; - sec.active_key = param->u.crypt.idx; - sec.flags |= SEC_ACTIVE_KEY; - } else - sec.flags &= ~SEC_ACTIVE_KEY; - - if (param->u.crypt.alg != NULL) { - memcpy(sec.keys[param->u.crypt.idx], - param->u.crypt.key, - param->u.crypt.key_len); - sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; - sec.flags |= (1 << param->u.crypt.idx); - - if (strcmp(param->u.crypt.alg, "WEP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - } - done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && - ieee->reset_port(ieee->dev)) { - printk("reset_port failed\n"); - param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED; - return -EINVAL; - } - - return ret; -} - -int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, - struct iw_point *p) -{ - struct ieee_param *param; - int ret = 0; - - down(&ieee->wx_sem); - - if (p->length < sizeof(struct ieee_param) || !p->pointer) { - ret = -EINVAL; - goto out; - } - - param = memdup_user(p->pointer, p->length); - if (IS_ERR(param)) { - ret = PTR_ERR(param); - goto out; - } - - switch (param->cmd) { - case IEEE_CMD_SET_WPA_PARAM: - ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name, - param->u.wpa_param.value); - break; - case IEEE_CMD_SET_WPA_IE: - ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length); - break; - case IEEE_CMD_SET_ENCRYPTION: - ret = ieee80211_wpa_set_encryption(ieee, param, p->length); - break; - case IEEE_CMD_MLME: - ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command, - param->u.mlme.reason_code); - break; - default: - printk("Unknown WPA supplicant request: %d\n", param->cmd); - ret = -EOPNOTSUPP; - break; - } - - if (ret == 0 && copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - - kfree(param); -out: - up(&ieee->wx_sem); - - return ret; -} - -void notify_wx_assoc_event(struct ieee80211_device *ieee) -{ - union iwreq_data wrqu; - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - if (ieee->state == IEEE80211_LINKED) - memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); - else - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c deleted file mode 100644 index 46f3564..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c +++ /dev/null @@ -1,567 +0,0 @@ -/* IEEE 802.11 SoftMAC layer - * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> - * - * Mostly extracted from the rtl8180-sa2400 driver for the - * in-kernel generic ieee802.11 stack. - * - * Some pieces of code might be stolen from ipw2100 driver - * copyright of who own it's copyright ;-) - * - * PS wx handler mostly stolen from hostap, copyright who - * own it's copyright ;-) - * - * released under the GPL - */ - - -#include <linux/etherdevice.h> - -#include "ieee80211.h" - -/* FIXME: add A freqs */ - -const long ieee80211_wlan_frequencies[] = { - 2412, 2417, 2422, 2427, - 2432, 2437, 2442, 2447, - 2452, 2457, 2462, 2467, - 2472, 2484 -}; - - -int ieee80211_wx_set_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - int ret; - struct iw_freq *fwrq = &wrqu->freq; -// printk("in %s\n",__func__); - down(&ieee->wx_sem); - - if (ieee->iw_mode == IW_MODE_INFRA) { - ret = -EOPNOTSUPP; - goto out; - } - - /* if setting by freq convert to channel */ - if (fwrq->e == 1) { - if ((fwrq->m >= (int) 2.412e8 && - fwrq->m <= (int) 2.487e8)) { - int f = fwrq->m / 100000; - int c = 0; - - while ((c < 14) && (f != ieee80211_wlan_frequencies[c])) - c++; - - /* hack to fall through */ - fwrq->e = 0; - fwrq->m = c + 1; - } - } - - if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) { - ret = -EOPNOTSUPP; - goto out; - - } else { /* Set the channel */ - - - ieee->current_network.channel = fwrq->m; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) - if (ieee->state == IEEE80211_LINKED) { - ieee80211_stop_send_beacons(ieee); - ieee80211_start_send_beacons(ieee); - } - } - - ret = 0; -out: - up(&ieee->wx_sem); - return ret; -} - - -int ieee80211_wx_get_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - struct iw_freq *fwrq = &wrqu->freq; - - if (ieee->current_network.channel == 0) - return -1; - - fwrq->m = ieee->current_network.channel; - fwrq->e = 0; - - return 0; -} - -int ieee80211_wx_get_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - unsigned long flags; - - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - /* We want avoid to give to the user inconsistent infos*/ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->state != IEEE80211_LINKED && - ieee->state != IEEE80211_LINKED_SCANNING && - ieee->wap_set == 0) - - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - else - memcpy(wrqu->ap_addr.sa_data, - ieee->current_network.bssid, ETH_ALEN); - - spin_unlock_irqrestore(&ieee->lock, flags); - - return 0; -} - - -int ieee80211_wx_set_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *awrq, - char *extra) -{ - - int ret = 0; - unsigned long flags; - - short ifup = ieee->proto_started;//dev->flags & IFF_UP; - struct sockaddr *temp = (struct sockaddr *)awrq; - - //printk("=======Set WAP:"); - ieee->sync_scan_hurryup = 1; - - down(&ieee->wx_sem); - /* use ifconfig hw ether */ - if (ieee->iw_mode == IW_MODE_MASTER) { - ret = -1; - goto out; - } - - if (temp->sa_family != ARPHRD_ETHER) { - ret = -EINVAL; - goto out; - } - - if (ifup) - ieee80211_stop_protocol(ieee); - - /* just to avoid to give inconsistent infos in the - * get wx method. not really needed otherwise - */ - spin_lock_irqsave(&ieee->lock, flags); - - memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); - ieee->wap_set = !is_zero_ether_addr(temp->sa_data); - //printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]); - - spin_unlock_irqrestore(&ieee->lock, flags); - - if (ifup) - ieee80211_start_protocol(ieee); - -out: - up(&ieee->wx_sem); - return ret; -} - -int ieee80211_wx_get_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - int len, ret = 0; - unsigned long flags; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - /* We want avoid to give to the user inconsistent infos*/ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->current_network.ssid[0] == '\0' || - ieee->current_network.ssid_len == 0){ - ret = -1; - goto out; - } - - if (ieee->state != IEEE80211_LINKED && - ieee->state != IEEE80211_LINKED_SCANNING && - ieee->ssid_set == 0){ - ret = -1; - goto out; - } - len = ieee->current_network.ssid_len; - wrqu->essid.length = len; - strncpy(b, ieee->current_network.ssid, len); - wrqu->essid.flags = 1; - -out: - spin_unlock_irqrestore(&ieee->lock, flags); - - return ret; - -} - -int ieee80211_wx_set_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - - u32 target_rate = wrqu->bitrate.value; - - //added by lizhaoming for auto mode - if (target_rate == -1) - ieee->rate = 110; - else - ieee->rate = target_rate/100000; - - //FIXME: we might want to limit rate also in management protocols. - return 0; -} - - - -int ieee80211_wx_get_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - - wrqu->bitrate.value = ieee->rate * 100000; - - return 0; -} - -int ieee80211_wx_set_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - - ieee->sync_scan_hurryup = 1; - - down(&ieee->wx_sem); - - if (wrqu->mode == ieee->iw_mode) - goto out; - - if (wrqu->mode == IW_MODE_MONITOR) - ieee->dev->type = ARPHRD_IEEE80211; - else - ieee->dev->type = ARPHRD_ETHER; - - if (!ieee->proto_started) { - ieee->iw_mode = wrqu->mode; - } else { - ieee80211_stop_protocol(ieee); - ieee->iw_mode = wrqu->mode; - ieee80211_start_protocol(ieee); - } - -out: - up(&ieee->wx_sem); - return 0; -} - - -void ieee80211_wx_sync_scan_wq(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq); - short chan; - - chan = ieee->current_network.channel; - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - - ieee80211_stop_send_beacons(ieee); - - ieee->state = IEEE80211_LINKED_SCANNING; - ieee->link_change(ieee->dev); - - ieee80211_start_scan_syncro(ieee); - - ieee->set_chan(ieee->dev, chan); - - ieee->state = IEEE80211_LINKED; - ieee->link_change(ieee->dev); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) - ieee80211_start_send_beacons(ieee); - - //YJ,add,080828, In prevent of lossing ping packet during scanning - //ieee80211_sta_ps_send_null_frame(ieee, false); - //YJ,add,080828,end - - up(&ieee->wx_sem); - -} - -int ieee80211_wx_set_scan(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - int ret = 0; - - down(&ieee->wx_sem); - - if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { - ret = -1; - goto out; - } - //YJ,add,080828 - //In prevent of lossing ping packet during scanning - //ieee80211_sta_ps_send_null_frame(ieee, true); - //YJ,add,080828,end - - if (ieee->state == IEEE80211_LINKED) { - queue_work(ieee->wq, &ieee->wx_sync_scan_wq); - /* intentionally forget to up sem */ - return 0; - } - -out: - up(&ieee->wx_sem); - return ret; -} - -int ieee80211_wx_set_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *extra) -{ - - int ret = 0, len; - short proto_started; - unsigned long flags; - - ieee->sync_scan_hurryup = 1; - - down(&ieee->wx_sem); - - proto_started = ieee->proto_started; - - if (wrqu->essid.length > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - goto out; - } - - if (ieee->iw_mode == IW_MODE_MONITOR) { - ret = -1; - goto out; - } - - if (proto_started) - ieee80211_stop_protocol(ieee); - - /* this is just to be sure that the GET wx callback - * has consistent infos. not needed otherwise - */ - spin_lock_irqsave(&ieee->lock, flags); - - if (wrqu->essid.flags && wrqu->essid.length) { -//YJ,modified,080819 - len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length) : IW_ESSID_MAX_SIZE; - memset(ieee->current_network.ssid, 0, ieee->current_network.ssid_len); //YJ,add,080819 - strncpy(ieee->current_network.ssid, extra, len); - ieee->current_network.ssid_len = len; - ieee->ssid_set = 1; -//YJ,modified,080819,end - - //YJ,add,080819,for hidden ap - if (len == 0) { - memset(ieee->current_network.bssid, 0, ETH_ALEN); - ieee->current_network.capability = 0; - } - //YJ,add,080819,for hidden ap,end - } else { - ieee->ssid_set = 0; - ieee->current_network.ssid[0] = '\0'; - ieee->current_network.ssid_len = 0; - } - //printk("==========set essid %s!\n",ieee->current_network.ssid); - spin_unlock_irqrestore(&ieee->lock, flags); - - if (proto_started) - ieee80211_start_protocol(ieee); -out: - up(&ieee->wx_sem); - return ret; -} - -int ieee80211_wx_get_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - - wrqu->mode = ieee->iw_mode; - return 0; -} - -int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - - int *parms = (int *)extra; - int enable = (parms[0] > 0); - short prev = ieee->raw_tx; - - down(&ieee->wx_sem); - - if (enable) - ieee->raw_tx = 1; - else - ieee->raw_tx = 0; - - netdev_info(ieee->dev, "raw TX is %s\n", - ieee->raw_tx ? "enabled" : "disabled"); - - if (ieee->iw_mode == IW_MODE_MONITOR) { - if (prev == 0 && ieee->raw_tx) { - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); - } - - if (prev && ieee->raw_tx == 1) - netif_carrier_off(ieee->dev); - } - - up(&ieee->wx_sem); - - return 0; -} - -int ieee80211_wx_get_name(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - strlcpy(wrqu->name, "802.11", IFNAMSIZ); - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - strlcat(wrqu->name, "b", IFNAMSIZ); - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strlcat(wrqu->name, "/g", IFNAMSIZ); - } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strlcat(wrqu->name, "g", IFNAMSIZ); - - if ((ieee->state == IEEE80211_LINKED) || - (ieee->state == IEEE80211_LINKED_SCANNING)) - strlcat(wrqu->name, " link", IFNAMSIZ); - else if (ieee->state != IEEE80211_NOLINK) - strlcat(wrqu->name, " .....", IFNAMSIZ); - - - return 0; -} - - -/* this is mostly stolen from hostap */ -int ieee80211_wx_set_power(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - int ret = 0; - - if ((!ieee->sta_wake_up) || - (!ieee->ps_request_tx_ack) || - (!ieee->enter_sleep_state) || - (!ieee->ps_is_queue_empty)) { - - printk("ERROR. PS mode tried to be use but driver missed a callback\n\n"); - - return -1; - } - - down(&ieee->wx_sem); - - if (wrqu->power.disabled) { - ieee->ps = IEEE80211_PS_DISABLED; - - goto exit; - } - switch (wrqu->power.flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - ieee->ps = IEEE80211_PS_UNICAST; - - break; - case IW_POWER_ALL_R: - ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST; - break; - - case IW_POWER_ON: - ieee->ps = IEEE80211_PS_DISABLED; - break; - - default: - ret = -EINVAL; - goto exit; - } - - if (wrqu->power.flags & IW_POWER_TIMEOUT) { - - ieee->ps_timeout = wrqu->power.value / 1000; - printk("Timeout %d\n", ieee->ps_timeout); - } - - if (wrqu->power.flags & IW_POWER_PERIOD) { - - ret = -EOPNOTSUPP; - goto exit; - //wrq->value / 1024; - - } -exit: - up(&ieee->wx_sem); - return ret; - -} - -/* this is stolen from hostap */ -int ieee80211_wx_get_power(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - int ret = 0; - - down(&ieee->wx_sem); - - if (ieee->ps == IEEE80211_PS_DISABLED) { - wrqu->power.disabled = 1; - goto exit; - } - - wrqu->power.disabled = 0; - -// if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - wrqu->power.flags = IW_POWER_TIMEOUT; - wrqu->power.value = ieee->ps_timeout * 1000; -// } else { -// ret = -EOPNOTSUPP; -// goto exit; - //wrqu->power.flags = IW_POWER_PERIOD; - //wrqu->power.value = ieee->current_network.dtim_period * - // ieee->current_network.beacon_interval * 1024; -// } - - - if (ieee->ps & IEEE80211_PS_MBCAST) - wrqu->power.flags |= IW_POWER_ALL_R; - else - wrqu->power.flags |= IW_POWER_UNICAST_R; - -exit: - up(&ieee->wx_sem); - return ret; - -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c deleted file mode 100644 index 0dc5ae4..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ /dev/null @@ -1,591 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 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 LICENSE. - - Contact Information: - James P. Ketrenos <ipw2100-admin@linux.intel.com> - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -****************************************************************************** - - Few modifications for Realtek's Wi-Fi drivers by - Andrea Merello <andrea.merello@gmail.com> - - A special thanks goes to Realtek for their support ! - -******************************************************************************/ - -#include <linux/compiler.h> -#include <linux/errno.h> -#include <linux/if_arp.h> -#include <linux/in6.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/wireless.h> -#include <linux/etherdevice.h> -#include <asm/uaccess.h> -#include <linux/if_vlan.h> - -#include "ieee80211.h" - - -/* - - -802.11 Data Frame - - -802.11 frame_contorl for data frames - 2 bytes - ,-----------------------------------------------------------------------------------------. -bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | - |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| -val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | - |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| -desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | - | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | - '-----------------------------------------------------------------------------------------' - /\ - | -802.11 Data Frame | - ,--------- 'ctrl' expands to >-----------' - | - ,--'---,-------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `--------------------------------------------------| |------' -Total: 28 non-data bytes `----.----' - | - .- 'Frame data' expands to <---------------------------' - | - V - ,---------------------------------------------------. -Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | - |------|------|---------|----------|------|---------| -Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | - | DSAP | SSAP | | | | Packet | - | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | - `-----------------------------------------| | -Total: 8 non-data bytes `----.----' - | - .- 'IP Packet' expands, if WEP enabled, to <--' - | - V - ,-----------------------. -Bytes | 4 | 0-2296 | 4 | - |-----|-----------|-----| -Desc. | IV | Encrypted | ICV | - | | IP Packet | | - `-----------------------' -Total: 8 non-data bytes - - -802.3 Ethernet Data Frame - - ,-----------------------------------------. -Bytes | 6 | 6 | 2 | Variable | 4 | - |-------|-------|------|-----------|------| -Desc. | Dest. | Source| Type | IP Packet | fcs | - | MAC | MAC | | | | - `-----------------------------------------' -Total: 18 non-data bytes - -In the event that fragmentation is required, the incoming payload is split into -N parts of size ieee->fts. The first fragment contains the SNAP header and the -remaining packets are just data. - -If encryption is enabled, each fragment payload size is reduced by enough space -to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) -So if you have 1500 bytes of payload with ieee->fts set to 500 without -encryption it will take 3 frames. With WEP it will take 4 frames as the -payload of each frame is reduced to 492 bytes. - -* SKB visualization -* -* ,- skb->data -* | -* | ETHERNET HEADER ,-<-- PAYLOAD -* | | 14 bytes from skb->data -* | 2 bytes for Type --> ,T. | (sizeof ethhdr) -* | | | | -* |,-Dest.--. ,--Src.---. | | | -* | 6 bytes| | 6 bytes | | | | -* v | | | | | | -* 0 | v 1 | v | v 2 -* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -* ^ | ^ | ^ | -* | | | | | | -* | | | | `T' <---- 2 bytes for Type -* | | | | -* | | '---SNAP--' <-------- 6 bytes for SNAP -* | | -* `-IV--' <-------------------- 4 bytes for IV (WEP) -* -* SNAP HEADER -* -*/ - -static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; -static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; - -static inline int ieee80211_put_snap(u8 *data, u16 h_proto) -{ - struct ieee80211_snap_hdr *snap; - u8 *oui; - - snap = (struct ieee80211_snap_hdr *)data; - snap->dsap = 0xaa; - snap->ssap = 0xaa; - snap->ctrl = 0x03; - - if (h_proto == 0x8137 || h_proto == 0x80f3) - oui = P802_1H_OUI; - else - oui = RFC1042_OUI; - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; - - *(u16 *)(data + SNAP_SIZE) = htons(h_proto); - - return SNAP_SIZE + sizeof(u16); -} - -int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, - struct sk_buff *frag, int hdr_len) -{ - struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx]; - int res; - - /* - * added to care about null crypt condition, to solve that system hangs - * when shared keys error - */ - if (!crypt || !crypt->ops) - return -1; - -#ifdef CONFIG_IEEE80211_CRYPT_TKIP - struct ieee80211_hdr_4addr *header; - - if (ieee->tkip_countermeasures && - crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { - header = (struct ieee80211_hdr_4addr *)frag->data; - if (net_ratelimit()) { - netdev_dbg(ieee->dev, "TKIP countermeasures: dropped " - "TX packet to %pM\n", header->addr1); - } - return -1; - } -#endif - /* - * To encrypt, frame format is: - * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) - * - * PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU - * encryption. - * - * Host-based IEEE 802.11 fragmentation for TX is not yet supported, so - * call both MSDU and MPDU encryption functions from here. - */ - atomic_inc(&crypt->refcnt); - res = 0; - if (crypt->ops->encrypt_msdu) - res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); - if (res == 0 && crypt->ops->encrypt_mpdu) - res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); - - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_info(ieee->dev, "Encryption failed: len=%d.\n", frag->len); - ieee->ieee_stats.tx_discards++; - return -1; - } - - return 0; -} - - -void ieee80211_txb_free(struct ieee80211_txb *txb) -{ - int i; - if (unlikely(!txb)) - return; - for (i = 0; i < txb->nr_frags; i++) - if (txb->fragments[i]) - dev_kfree_skb_any(txb->fragments[i]); - kfree(txb); -} - -static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, - gfp_t gfp_mask) -{ - struct ieee80211_txb *txb; - int i; - txb = kmalloc( - sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags), - gfp_mask); - if (!txb) - return NULL; - - memset(txb, 0, sizeof(struct ieee80211_txb)); - txb->nr_frags = nr_frags; - txb->frag_size = txb_size; - - for (i = 0; i < nr_frags; i++) { - txb->fragments[i] = dev_alloc_skb(txb_size); - if (unlikely(!txb->fragments[i])) { - i--; - break; - } - } - if (unlikely(i != nr_frags)) { - while (i >= 0) - dev_kfree_skb_any(txb->fragments[i--]); - kfree(txb); - return NULL; - } - return txb; -} - -/* - * Classify the to-be send data packet - * Need to acquire the sent queue index. - */ -static int ieee80211_classify(struct sk_buff *skb, - struct ieee80211_network *network) -{ - struct ether_header *eh = (struct ether_header *)skb->data; - unsigned int wme_UP = 0; - - if (!network->QoS_Enable) { - skb->priority = 0; - return(wme_UP); - } - - if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) { - const struct iphdr *ih = (struct iphdr *)(skb->data + - sizeof(struct ether_header)); - wme_UP = (ih->tos >> 5)&0x07; - } else if (vlan_tx_tag_present(skb)) {/* vtag packet */ -#ifndef VLAN_PRI_SHIFT -#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */ -#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */ -#endif - u32 tag = vlan_tx_tag_get(skb); - wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; - } else if (ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) { - wme_UP = 7; - } - - skb->priority = wme_UP; - return(wme_UP); -} - -/* SKBs are added to the ieee->tx_queue. */ -int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct ieee80211_device *ieee = netdev_priv(dev); - struct ieee80211_txb *txb = NULL; - struct ieee80211_hdr_3addrqos *frag_hdr; - int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; - unsigned long flags; - struct net_device_stats *stats = &ieee->stats; - int ether_type, encrypt; - int bytes, fc, qos_ctl, hdr_len; - struct sk_buff *skb_frag; - struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */ - .duration_id = 0, - .seq_ctl = 0, - .qos_ctl = 0 - }; - u8 dest[ETH_ALEN], src[ETH_ALEN]; - - struct ieee80211_crypt_data* crypt; - - spin_lock_irqsave(&ieee->lock, flags); - - /* - * If there is no driver handler to take the TXB, don't bother - * creating it... - */ - if ((!ieee->hard_start_xmit && - !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) || - ((!ieee->softmac_data_hard_start_xmit && - (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { - netdev_warn(ieee->dev, "No xmit handler.\n"); - goto success; - } - - ieee80211_classify(skb,&ieee->current_network); - if (likely(ieee->raw_tx == 0)){ - - if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { - netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len); - goto success; - } - - ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); - - crypt = ieee->crypt[ieee->tx_keyidx]; - - encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && - ieee->host_encrypt && crypt && crypt->ops; - - if (!encrypt && ieee->ieee802_1x && - ieee->drop_unencrypted && ether_type != ETH_P_PAE) { - stats->tx_dropped++; - goto success; - } - - #ifdef CONFIG_IEEE80211_DEBUG - if (crypt && !encrypt && ether_type == ETH_P_PAE) { - struct eapol *eap = (struct eapol *)(skb->data + - sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); - IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", - eap_get_type(eap->type)); - } - #endif - - /* Save source and destination addresses */ - memcpy(&dest, skb->data, ETH_ALEN); - memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); - - /* Advance the SKB to the start of the payload */ - skb_pull(skb, sizeof(struct ethhdr)); - - /* Determine total amount of storage required for TXB packets */ - bytes = skb->len + SNAP_SIZE + sizeof(u16); - - if (ieee->current_network.QoS_Enable) { - if (encrypt) - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA | - IEEE80211_FCTL_WEP; - else - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; - - } else { - if (encrypt) - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | - IEEE80211_FCTL_WEP; - else - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; - } - - if (ieee->iw_mode == IW_MODE_INFRA) { - fc |= IEEE80211_FCTL_TODS; - /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ - memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); - memcpy(&header.addr2, &src, ETH_ALEN); - memcpy(&header.addr3, &dest, ETH_ALEN); - } else if (ieee->iw_mode == IW_MODE_ADHOC) { - /* - * not From/To DS: Addr1 = DA, Addr2 = SA, - * Addr3 = BSSID - */ - memcpy(&header.addr1, dest, ETH_ALEN); - memcpy(&header.addr2, src, ETH_ALEN); - memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); - } - header.frame_ctl = cpu_to_le16(fc); - - /* - * Determine fragmentation size based on destination (multicast - * and broadcast are not fragmented) - */ - if (is_multicast_ether_addr(header.addr1)) { - frag_size = MAX_FRAG_THRESHOLD; - qos_ctl = QOS_CTL_NOTCONTAIN_ACK; - } else { - /* default:392 */ - frag_size = ieee->fts; - qos_ctl = 0; - } - - if (ieee->current_network.QoS_Enable) { - hdr_len = IEEE80211_3ADDR_LEN + 2; - /* skb->priority is set in the ieee80211_classify() */ - qos_ctl |= skb->priority; - header.qos_ctl = cpu_to_le16(qos_ctl); - } else { - hdr_len = IEEE80211_3ADDR_LEN; - } - - /* - * Determine amount of payload per fragment. Regardless of if - * this stack is providing the full 802.11 header, one will - * eventually be affixed to this fragment -- so we must account - * for it when determining the amount of payload space. - */ - bytes_per_frag = frag_size - hdr_len; - if (ieee->config & - (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) - bytes_per_frag -= IEEE80211_FCS_LEN; - - /* Each fragment may need to have room for encryption pre/postfix */ - if (encrypt) - bytes_per_frag -= crypt->ops->extra_prefix_len + - crypt->ops->extra_postfix_len; - - /* - * Number of fragments is the total bytes_per_frag / - * payload_per_fragment - */ - nr_frags = bytes / bytes_per_frag; - bytes_last_frag = bytes % bytes_per_frag; - if (bytes_last_frag) - nr_frags++; - else - bytes_last_frag = bytes_per_frag; - - /* - * When we allocate the TXB we allocate enough space for the - * reserve and full fragment bytes (bytes_per_frag doesn't - * include prefix, postfix, header, FCS, etc.) - */ - txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC); - if (unlikely(!txb)) { - netdev_warn(ieee->dev, "Could not allocate TXB\n"); - goto failed; - } - txb->encrypted = encrypt; - txb->payload_size = bytes; - - for (i = 0; i < nr_frags; i++) { - skb_frag = txb->fragments[i]; - skb_frag->priority = UP2AC(skb->priority); - if (encrypt) - skb_reserve(skb_frag, crypt->ops->extra_prefix_len); - - frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put( - skb_frag, hdr_len); - memcpy(frag_hdr, &header, hdr_len); - - /* - * If this is not the last fragment, then add the MOREFRAGS - * bit to the frame control - */ - if (i != nr_frags - 1) { - frag_hdr->frame_ctl = cpu_to_le16( - fc | IEEE80211_FCTL_MOREFRAGS); - bytes = bytes_per_frag; - - } else { - /* The last fragment takes the remaining length */ - bytes = bytes_last_frag; - } - if (ieee->current_network.QoS_Enable) { - /* - * add 1 only indicate to corresponding seq - * number control 2006/7/12 - */ - frag_hdr->seq_ctl = cpu_to_le16( - ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); - } else { - frag_hdr->seq_ctl = cpu_to_le16( - ieee->seq_ctrl[0]<<4 | i); - } - - /* Put a SNAP header on the first fragment */ - if (i == 0) { - ieee80211_put_snap( - skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), - ether_type); - bytes -= SNAP_SIZE + sizeof(u16); - } - - memcpy(skb_put(skb_frag, bytes), skb->data, bytes); - - /* Advance the SKB... */ - skb_pull(skb, bytes); - - /* - * Encryption routine will move the header forward in - * order to insert the IV between the header and the - * payload - */ - if (encrypt) - ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); - if (ieee->config & - (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) - skb_put(skb_frag, 4); - } - /* Advance sequence number in data frame. */ - if (ieee->current_network.QoS_Enable) { - if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) - ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; - else - ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; - } else { - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - } - } else { - if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { - netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len); - goto success; - } - - txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); - if (!txb) { - netdev_warn(ieee->dev, "Could not allocate TXB\n"); - goto failed; - } - - txb->encrypted = 0; - txb->payload_size = skb->len; - memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len); - } - - success: - spin_unlock_irqrestore(&ieee->lock, flags); - dev_kfree_skb_any(skb); - if (txb) { - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { - ieee80211_softmac_xmit(txb, ieee); - } else { - if ((*ieee->hard_start_xmit)(txb, dev) == 0) { - stats->tx_packets++; - stats->tx_bytes += txb->payload_size; - return NETDEV_TX_OK; - } - ieee80211_txb_free(txb); - } - } - - return NETDEV_TX_OK; - - failed: - spin_unlock_irqrestore(&ieee->lock, flags); - netif_stop_queue(dev); - stats->tx_errors++; - return NETDEV_TX_BUSY; - -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c deleted file mode 100644 index 07c3f71..0000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright(c) 2004 Intel Corporation. All rights reserved. - * - * Portions of this file are based on the WEP enablement code provided by the - * Host AP project hostap-drivers v0.1.3 - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 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 LICENSE. - * - * Contact Information: - * James P. Ketrenos <ipw2100-admin@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include <linux/wireless.h> -#include <linux/kmod.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/etherdevice.h> - -#include "ieee80211.h" -static const char *ieee80211_modes[] = { - "?", "a", "b", "ab", "g", "ag", "bg", "abg" -}; - -#define MAX_CUSTOM_LEN 64 -static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee, - char *start, char *stop, - struct ieee80211_network *network, - struct iw_request_info *info) -{ - char custom[MAX_CUSTOM_LEN]; - char *p; - struct iw_event iwe; - int i, j; - u8 max_rate, rate; - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - - /* Remaining entries will be displayed in the order we provide them */ - - /* Add the ESSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - if (network->ssid_len == 0) { - iwe.u.data.length = sizeof("<hidden>"); - start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>"); - } else { - iwe.u.data.length = min_t(u8, network->ssid_len, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); - } - /* Add the protocol name */ - iwe.cmd = SIOCGIWNAME; - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); - - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - if (network->capability & - (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) { - if (network->capability & WLAN_CAPABILITY_BSS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); - } - - /* Add frequency/channel */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = network->channel; - iwe.u.freq.e = 0; - iwe.u.freq.i = 0; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (network->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); - - /* Add basic and extended rates */ - max_rate = 0; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); - for (i = 0, j = 0; i < network->rates_len; ) { - if (j < network->rates_ex_len && - ((network->rates_ex[j] & 0x7F) < - (network->rates[i] & 0x7F))) - rate = network->rates_ex[j++] & 0x7F; - else - rate = network->rates[i++] & 0x7F; - if (rate > max_rate) - max_rate = rate; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - } - for (; j < network->rates_ex_len; j++) { - rate = network->rates_ex[j] & 0x7F; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - if (rate > max_rate) - max_rate = rate; - } - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = max_rate * 500000; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN); - - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - /* Add quality statistics */ - /* TODO: Fix these values... */ - if (network->stats.signal == 0 || network->stats.rssi == 0) - netdev_info(ieee->dev, "========>signal:%d, rssi:%d\n", - network->stats.signal, network->stats.rssi); - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = network->stats.signalstrength; - iwe.u.qual.level = network->stats.signal; - iwe.u.qual.noise = network->stats.noise; - iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK; - if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) - iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; - if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) - iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; - if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) - iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; - iwe.u.qual.updated = 7; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); - - iwe.cmd = IWEVCUSTOM; - p = custom; - - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - memset(&iwe, 0, sizeof(iwe)); - if (network->wpa_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, network->wpa_ie, network->wpa_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - memset(&iwe, 0, sizeof(iwe)); - if (network->rsn_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, network->rsn_ie, network->rsn_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - /* Add EXTRA: Age to display seconds since last beacon/probe response - * for given network. - */ - iwe.cmd = IWEVCUSTOM; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - return start; -} - -int ieee80211_wx_get_scan(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ieee80211_network *network; - unsigned long flags; - int err = 0; - char *ev = extra; - char *stop = ev + wrqu->data.length; - int i = 0; - - IEEE80211_DEBUG_WX("Getting scan\n"); - down(&ieee->wx_sem); - spin_lock_irqsave(&ieee->lock, flags); - - if (!ieee->bHwRadioOff) { - list_for_each_entry(network, &ieee->network_list, list) { - i++; - - if ((stop-ev) < 200) { - err = -E2BIG; - break; - } - if (ieee->scan_age == 0 || - time_after(network->last_scanned + ieee->scan_age, jiffies)) { - ev = rtl818x_translate_scan(ieee, ev, stop, network, info); - } else - IEEE80211_DEBUG_SCAN( - "Not showing network '%s (" - "%pM)' due to age (%lums).\n", - escape_essid(network->ssid, - network->ssid_len), - network->bssid, - (jiffies - network->last_scanned) / (HZ / 100)); - } - } - spin_unlock_irqrestore(&ieee->lock, flags); - up(&ieee->wx_sem); - wrqu->data.length = ev - extra; - wrqu->data.flags = 0; - IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i); - - return err; -} - -int ieee80211_wx_set_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &(wrqu->encoding); - struct net_device *dev = ieee->dev; - struct ieee80211_security sec = { - .flags = 0 - }; - int i, key, key_provided, len; - struct ieee80211_crypt_data **crypt; - - IEEE80211_DEBUG_WX("SET_ENCODE\n"); - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - key_provided = 1; - } else { - key_provided = 0; - key = ieee->tx_keyidx; - } - - IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? - "provided" : "default"); - - crypt = &ieee->crypt[key]; - - if (erq->flags & IW_ENCODE_DISABLED) { - if (key_provided && *crypt) { - IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", - key); - ieee80211_crypt_delayed_deinit(ieee, crypt); - } else - IEEE80211_DEBUG_WX("Disabling encryption.\n"); - - /* Check all the keys to see if any are still configured, - * and if no key index was provided, de-init them all. - */ - for (i = 0; i < WEP_KEYS; i++) { - if (ieee->crypt[i] != NULL) { - if (key_provided) - break; - ieee80211_crypt_delayed_deinit( - ieee, &ieee->crypt[i]); - } - } - - if (i == WEP_KEYS) { - sec.enabled = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; - } - - goto done; - } - - sec.enabled = 1; - sec.flags |= SEC_ENABLED; - - if (*crypt != NULL && (*crypt)->ops != NULL && - strcmp((*crypt)->ops->name, "WEP") != 0) { - /* changing to use WEP; deinit previously used algorithm - * on this key. - */ - ieee80211_crypt_delayed_deinit(ieee, crypt); - } - - if (*crypt == NULL) { - struct ieee80211_crypt_data *new_crypt; - - /* take WEP into use */ - new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), - GFP_KERNEL); - if (new_crypt == NULL) - return -ENOMEM; - new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) - new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - - if (new_crypt->ops) - new_crypt->priv = new_crypt->ops->init(key); - - if (!new_crypt->ops || !new_crypt->priv) { - kfree(new_crypt); - new_crypt = NULL; - - netdev_warn(ieee->dev, - "could not initialize WEP: load module ieee80211_crypt_wep\n"); - return -EOPNOTSUPP; - } - *crypt = new_crypt; - } - - /* If a new key was provided, set it up */ - if (erq->length > 0) { - len = erq->length <= 5 ? 5 : 13; - memcpy(sec.keys[key], keybuf, erq->length); - if (len > erq->length) - memset(sec.keys[key] + erq->length, 0, - len - erq->length); - IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", - key, escape_essid(sec.keys[key], len), - erq->length, len); - sec.key_sizes[key] = len; - (*crypt)->ops->set_key(sec.keys[key], len, NULL, - (*crypt)->priv); - sec.flags |= (1 << key); - /* This ensures a key will be activated if no key is - * explicitly set. - */ - if (key == sec.active_key) - sec.flags |= SEC_ACTIVE_KEY; - ieee->tx_keyidx = key; - } else { - len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, - NULL, (*crypt)->priv); - if (len == 0) { - /* Set a default key of all 0 */ - IEEE80211_DEBUG_WX("Setting key %d to all zero.\n", - key); - memset(sec.keys[key], 0, 13); - (*crypt)->ops->set_key(sec.keys[key], 13, NULL, - (*crypt)->priv); - sec.key_sizes[key] = 13; - sec.flags |= (1 << key); - } - - /* No key data - just set the default TX key index */ - if (key_provided) { - IEEE80211_DEBUG_WX( - "Setting key %d to default Tx key.\n", key); - ieee->tx_keyidx = key; - sec.active_key = key; - sec.flags |= SEC_ACTIVE_KEY; - } - } - - done: - ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); - sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; - sec.flags |= SEC_AUTH_MODE; - IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? - "OPEN" : "SHARED KEY"); - - /* For now we just support WEP, so only set that security level... - * TODO: When WPA is added this is one place that needs to change - */ - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ - - if (ieee->set_security) - ieee->set_security(dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. - */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - netdev_dbg(ieee->dev, "reset_port failed\n"); - return -EINVAL; - } - return 0; -} - -int ieee80211_wx_get_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &(wrqu->encoding); - int len, key; - struct ieee80211_crypt_data *crypt; - - IEEE80211_DEBUG_WX("GET_ENCODE\n"); - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - } else - key = ieee->tx_keyidx; - - crypt = ieee->crypt[key]; - erq->flags = key + 1; - - if (crypt == NULL || crypt->ops == NULL) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - - if (strcmp(crypt->ops->name, "WEP") != 0) { - /* only WEP is supported with wireless extensions, so just - * report that encryption is used. - */ - erq->length = 0; - erq->flags |= IW_ENCODE_ENABLED; - return 0; - } - - len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv); - erq->length = (len >= 0 ? len : 0); - - erq->flags |= IW_ENCODE_ENABLED; - - if (ieee->open_wep) - erq->flags |= IW_ENCODE_OPEN; - else - erq->flags |= IW_ENCODE_RESTRICTED; - - return 0; -} - -int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct net_device *dev = ieee->dev; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int i, idx, ret = 0; - int group_key = 0; - const char *alg; - struct ieee80211_crypto_ops *ops; - struct ieee80211_crypt_data **crypt; - - struct ieee80211_security sec = { - .flags = 0, - }; - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > WEP_KEYS) - return -EINVAL; - idx--; - } else - idx = ieee->tx_keyidx; - - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - crypt = &ieee->crypt[idx]; - group_key = 1; - } else { - /* some Cisco APs use idx>0 for unicast in dynamic WEP */ - if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) - return -EINVAL; - if (ieee->iw_mode == IW_MODE_INFRA) - crypt = &ieee->crypt[idx]; - else - return -EINVAL; - } - - sec.flags |= SEC_ENABLED; - if ((encoding->flags & IW_ENCODE_DISABLED) || - ext->alg == IW_ENCODE_ALG_NONE) { - if (*crypt) - ieee80211_crypt_delayed_deinit(ieee, crypt); - - for (i = 0; i < WEP_KEYS; i++) - if (ieee->crypt[i] != NULL) - break; - - if (i == WEP_KEYS) { - sec.enabled = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_LEVEL; - } - goto done; - } - - sec.enabled = 1; - - switch (ext->alg) { - case IW_ENCODE_ALG_WEP: - alg = "WEP"; - break; - case IW_ENCODE_ALG_TKIP: - alg = "TKIP"; - break; - case IW_ENCODE_ALG_CCMP: - alg = "CCMP"; - break; - default: - IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", - dev->name, ext->alg); - ret = -EINVAL; - goto done; - } - - ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) - ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) { - IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", - dev->name, ext->alg); - netdev_err(ieee->dev, "========>unknown crypto alg %d\n", - ext->alg); - ret = -EINVAL; - goto done; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct ieee80211_crypt_data *new_crypt; - - ieee80211_crypt_delayed_deinit(ieee, crypt); - - new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - new_crypt->ops = ops; - if (new_crypt->ops) - new_crypt->priv = new_crypt->ops->init(idx); - if (new_crypt->priv == NULL) { - kfree(new_crypt); - ret = -EINVAL; - goto done; - } - *crypt = new_crypt; - - } - - if (ext->key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, - (*crypt)->priv) < 0) { - IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name); - netdev_err(ieee->dev, "key setting failed\n"); - ret = -EINVAL; - goto done; - } -#if 1 - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - ieee->tx_keyidx = idx; - sec.active_key = idx; - sec.flags |= SEC_ACTIVE_KEY; - } - - if (ext->alg != IW_ENCODE_ALG_NONE) { - memcpy(sec.keys[idx], ext->key, ext->key_len); - sec.key_sizes[idx] = ext->key_len; - sec.flags |= (1 << idx); - if (ext->alg == IW_ENCODE_ALG_WEP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (ext->alg == IW_ENCODE_ALG_TKIP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (ext->alg == IW_ENCODE_ALG_CCMP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - /* Don't set sec level for group keys. */ - if (group_key) - sec.flags &= ~SEC_LEVEL; - } -#endif -done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name); - return -EINVAL; - } - - return ret; -} - -int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_mlme *mlme = (struct iw_mlme *) extra; -#if 1 - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - case IW_MLME_DISASSOC: - ieee80211_disassociate(ieee); - break; - default: - return -EOPNOTSUPP; - } -#endif - return 0; -} - -int ieee80211_wx_set_auth(struct ieee80211_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - /* need to support wpa2 here */ - break; - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* Host AP driver does not use these parameters and allows - * wpa_supplicant to control them internally. - */ - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - ieee->tkip_countermeasures = data->value; - break; - case IW_AUTH_DROP_UNENCRYPTED: - ieee->drop_unencrypted = data->value; - break; - - case IW_AUTH_80211_AUTH_ALG: - ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0; - break; - -#if 1 - case IW_AUTH_WPA_ENABLED: - ieee->wpa_enabled = (data->value) ? 1 : 0; - break; - -#endif - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ieee->ieee802_1x = data->value; - break; - case IW_AUTH_PRIVACY_INVOKED: - ieee->privacy_invoked = data->value; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -#if 1 -int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) -{ - u8 *buf = NULL; - - if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) { - netdev_err(ieee->dev, "return error out, len:%zu\n", len); - return -EINVAL; - } - - if (len) { - if (len != ie[1]+2) { - netdev_err(ieee->dev, "len:%zu, ie:%d\n", len, ie[1]); - return -EINVAL; - } - buf = kmemdup(ie, len, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = len; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - - return 0; - -} -#endif diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h deleted file mode 100644 index 9f931db..0000000 --- a/drivers/staging/rtl8187se/r8180.h +++ /dev/null @@ -1,640 +0,0 @@ -/* - * This is part of rtl8180 OpenSource driver. - * Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com> - * Released under the terms of GPL (General Public Licence) - * - * Parts of this driver are based on the GPL part of the official realtek driver - * - * Parts of this driver are based on the rtl8180 driver skeleton from Patric - * Schenke & Andres Salomon - * - * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver - * - * We want to thanks the Authors of those projects and the Ndiswrapper project - * Authors. - */ - -#ifndef R8180H -#define R8180H - -#include <linux/interrupt.h> - -#define RTL8180_MODULE_NAME "r8180" -#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a) -#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a) -#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a) - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/etherdevice.h> -#include <linux/delay.h> -#include <linux/rtnetlink.h> /* for rtnl_lock() */ -#include <linux/wireless.h> -#include <linux/timer.h> -#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */ -#include <linux/if_arp.h> -#include "ieee80211/ieee80211.h" -#include <asm/io.h> - -#define EPROM_93c46 0 -#define EPROM_93c56 1 - -#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30) - -#define DEFAULT_FRAG_THRESHOLD 2342U -#define MIN_FRAG_THRESHOLD 256U -#define DEFAULT_RTS_THRESHOLD 2342U -#define MIN_RTS_THRESHOLD 0U -#define MAX_RTS_THRESHOLD 2342U -#define DEFAULT_BEACONINTERVAL 0x64U - -#define DEFAULT_RETRY_RTS 7 -#define DEFAULT_RETRY_DATA 7 - -#define BEACON_QUEUE 6 - -#define aSifsTime 10 - -#define sCrcLng 4 -#define sAckCtsLng 112 /* bits in ACK and CTS frames. */ -/* +by amy 080312. */ -#define RATE_ADAPTIVE_TIMER_PERIOD 300 - -enum wireless_mode { - WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = 0x01, - WIRELESS_MODE_B = 0x02, - WIRELESS_MODE_G = 0x04, - WIRELESS_MODE_AUTO = 0x08, -}; - -struct chnl_access_setting { - u16 sifs_timer; - u16 difs_timer; - u16 slot_time_timer; - u16 eifs_timer; - u16 cwmin_index; - u16 cwmax_index; -}; - -enum nic_t { - NIC_8185 = 1, - NIC_8185B -}; - -typedef u32 AC_CODING; -#define AC0_BE 0 /* ACI: 0x00 */ /* Best Effort. */ -#define AC1_BK 1 /* ACI: 0x01 */ /* Background. */ -#define AC2_VI 2 /* ACI: 0x10 */ /* Video. */ -#define AC3_VO 3 /* ACI: 0x11 */ /* Voice. */ -#define AC_MAX 4 /* Max: define total number; Should not to be used as a real - * enum. - */ - -/* - * ECWmin/ECWmax field. - * Ref: WMM spec 2.2.2: WME Parameter Element, p.13. - */ -typedef union _ECW { - u8 charData; - struct { - u8 ECWmin:4; - u8 ECWmax:4; - } f; /* Field */ -} ECW, *PECW; - -/* - * ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12. - */ -typedef union _ACI_AIFSN { - u8 charData; - - struct { - u8 AIFSN:4; - u8 ACM:1; - u8 ACI:2; - u8 Reserved:1; - } f; /* Field */ -} ACI_AIFSN, *PACI_AIFSN; - -/* - * AC Parameters Record Format. - * Ref: WMM spec 2.2.2: WME Parameter Element, p.12. - */ -typedef union _AC_PARAM { - u32 longData; - u8 charData[4]; - - struct { - ACI_AIFSN AciAifsn; - ECW Ecw; - u16 TXOPLimit; - } f; /* Field */ -} AC_PARAM, *PAC_PARAM; - -struct buffer { - struct buffer *next; - u32 *buf; - dma_addr_t dma; -}; - -/* YJ,modified,080828. */ -struct stats { - unsigned long txrdu; - unsigned long rxrdu; - unsigned long rxnolast; - unsigned long rxnodata; - unsigned long rxnopointer; - unsigned long txnperr; - unsigned long txresumed; - unsigned long rxerr; - unsigned long rxoverflow; - unsigned long rxint; - unsigned long txbkpokint; - unsigned long txbepoking; - unsigned long txbkperr; - unsigned long txbeperr; - unsigned long txnpokint; - unsigned long txhpokint; - unsigned long txhperr; - unsigned long ints; - unsigned long shints; - unsigned long txoverflow; - unsigned long rxdmafail; - unsigned long txbeacon; - unsigned long txbeaconerr; - unsigned long txlpokint; - unsigned long txlperr; - unsigned long txretry; /* retry number tony 20060601 */ - unsigned long rxcrcerrmin; /* crc error (0-500) */ - unsigned long rxcrcerrmid; /* crc error (500-1000) */ - unsigned long rxcrcerrmax; /* crc error (>1000) */ - unsigned long rxicverr; /* ICV error */ -}; - -#define MAX_LD_SLOT_NUM 10 -#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */ -#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */ -#define DEFAULT_KEEP_ALIVE_LEVEL 1 -#define DEFAULT_SLOT_NUM 2 -#define POWER_PROFILE_AC 0 -#define POWER_PROFILE_BATTERY 1 - -struct link_detect_t { - u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame. - * CheckForHang_period to determine - * link status. - */ - u16 slot_num; /* number of CheckForHang period to determine link status, - * default is 2. - */ - u16 slot_index; - u32 num_tx_ok_in_period; /* number of packet transmitted during - * CheckForHang. - */ - u32 num_rx_ok_in_period; /* number of packet received during - * CheckForHang. - */ - u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */ - u32 last_num_tx_unicast; - u32 last_num_rx_unicast; - - bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */ -}; - -/* YJ,modified,080828,end */ - -/* by amy for led - * ========================================================================== - * LED customization. - * ========================================================================== - */ -enum led_strategy_8185 { - SW_LED_MODE0, - SW_LED_MODE1, - HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different - * control modes). */ -}; - -enum rt_rf_power_state { - RF_ON, - RF_SLEEP, - RF_OFF -}; - -enum _ReasonCode { - unspec_reason = 0x1, - auth_not_valid = 0x2, - deauth_lv_ss = 0x3, - inactivity = 0x4, - ap_overload = 0x5, - class2_err = 0x6, - class3_err = 0x7, - disas_lv_ss = 0x8, - asoc_not_auth = 0x9, - - /* ----MIC_CHECK */ - mic_failure = 0xe, - /* ----END MIC_CHECK */ - - /* Reason code defined in 802.11i D10.0 p.28. */ - invalid_IE = 0x0d, - four_way_tmout = 0x0f, - two_way_tmout = 0x10, - IE_dismatch = 0x11, - invalid_Gcipher = 0x12, - invalid_Pcipher = 0x13, - invalid_AKMP = 0x14, - unsup_RSNIEver = 0x15, - invalid_RSNIE = 0x16, - auth_802_1x_fail = 0x17, - ciper_reject = 0x18, - - /* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, - * 2005-11-15. - */ - QoS_unspec = 0x20, /* 32 */ - QAP_bandwidth = 0x21, /* 33 */ - poor_condition = 0x22, /* 34 */ - no_facility = 0x23, /* 35 */ - /* Where is 36??? */ - req_declined = 0x25, /* 37 */ - invalid_param = 0x26, /* 38 */ - req_not_honored = 0x27, /* 39 */ - TS_not_created = 0x2F, /* 47 */ - DL_not_allowed = 0x30, /* 48 */ - dest_not_exist = 0x31, /* 49 */ - dest_not_QSTA = 0x32, /* 50 */ -}; - -enum rt_ps_mode { - ACTIVE, /* Active/Continuous access. */ - MAX_PS, /* Max power save mode. */ - FAST_PS /* Fast power save mode. */ -}; - -/* by amy for power save. */ -struct r8180_priv { - struct pci_dev *pdev; - - short epromtype; - int irq; - struct ieee80211_device *ieee80211; - - short plcp_preamble_mode; /* 0:auto 1:short 2:long */ - - spinlock_t irq_th_lock; - spinlock_t tx_lock; - spinlock_t ps_lock; - spinlock_t rf_ps_lock; - - u16 irq_mask; - short irq_enabled; - struct net_device *dev; - short chan; - short sens; - short max_sens; - u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */ - u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */ - u8 channel_plan; /* it's the channel plan index. */ - short up; - short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */ - - struct timer_list scan_timer; - spinlock_t scan_lock; - u8 active_probe; - struct semaphore wx_sem; - short hw_wep; - - short digphy; - short antb; - short diversity; - u32 key0[4]; - short (*rf_set_sens)(struct net_device *dev, short sens); - void (*rf_set_chan)(struct net_device *dev, short ch); - void (*rf_close)(struct net_device *dev); - void (*rf_init)(struct net_device *dev); - void (*rf_sleep)(struct net_device *dev); - void (*rf_wakeup)(struct net_device *dev); - /* short rate; */ - short promisc; - /* stats */ - struct stats stats; - struct link_detect_t link_detect; /* YJ,add,080828 */ - struct iw_statistics wstats; - - /* RX stuff. */ - u32 *rxring; - u32 *rxringtail; - dma_addr_t rxringdma; - struct buffer *rxbuffer; - struct buffer *rxbufferhead; - int rxringcount; - u16 rxbuffersize; - - struct sk_buff *rx_skb; - - short rx_skb_complete; - - u32 rx_prevlen; - - u32 *txmapring; - u32 *txbkpring; - u32 *txbepring; - u32 *txvipring; - u32 *txvopring; - u32 *txhpring; - dma_addr_t txmapringdma; - dma_addr_t txbkpringdma; - dma_addr_t txbepringdma; - dma_addr_t txvipringdma; - dma_addr_t txvopringdma; - dma_addr_t txhpringdma; - u32 *txmapringtail; - u32 *txbkpringtail; - u32 *txbepringtail; - u32 *txvipringtail; - u32 *txvopringtail; - u32 *txhpringtail; - u32 *txmapringhead; - u32 *txbkpringhead; - u32 *txbepringhead; - u32 *txvipringhead; - u32 *txvopringhead; - u32 *txhpringhead; - struct buffer *txmapbufs; - struct buffer *txbkpbufs; - struct buffer *txbepbufs; - struct buffer *txvipbufs; - struct buffer *txvopbufs; - struct buffer *txhpbufs; - struct buffer *txmapbufstail; - struct buffer *txbkpbufstail; - struct buffer *txbepbufstail; - struct buffer *txvipbufstail; - struct buffer *txvopbufstail; - struct buffer *txhpbufstail; - - int txringcount; - int txbuffsize; - struct tasklet_struct irq_rx_tasklet; - u8 dma_poll_mask; - - /* adhoc/master mode stuff. */ - u32 *txbeaconringtail; - dma_addr_t txbeaconringdma; - u32 *txbeaconring; - int txbeaconcount; - struct buffer *txbeaconbufs; - struct buffer *txbeaconbufstail; - - u8 retry_data; - u8 retry_rts; - u16 rts; - - /* by amy for led. */ - enum led_strategy_8185 led_strategy; - /* by amy for led. */ - - /* by amy for power save. */ - struct timer_list watch_dog_timer; - bool bInactivePs; - bool bSwRfProcessing; - enum rt_rf_power_state eInactivePowerState; - enum rt_rf_power_state eRFPowerState; - u32 RfOffReason; - bool RFChangeInProgress; - bool SetRFPowerStateInProgress; - u8 RFProgType; - bool bLeisurePs; - enum rt_ps_mode dot11PowerSaveMode; - u8 TxPollingTimes; - - bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will - * keep eAwake until receive data or timeout. - */ - u8 WaitBufDataBcnCount; - u8 WaitBufDataTimeOut; - - /* by amy for power save. */ - /* by amy for antenna. */ - u8 EEPROMSwAntennaDiversity; - bool EEPROMDefaultAntenna1; - u8 RegSwAntennaDiversityMechanism; - bool bSwAntennaDiverity; - u8 RegDefaultAntenna; - bool bDefaultAntenna1; - u8 SignalStrength; - long Stats_SignalStrength; - long LastSignalStrengthInPercent; /* In percentage, used for smoothing, - * e.g. Moving Average. - */ - u8 SignalQuality; /* in 0-100 index. */ - long Stats_SignalQuality; - long RecvSignalPower; /* in dBm. */ - long Stats_RecvSignalPower; - u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted - * packet. 0: Aux, 1:Main. Added by Roger, - * 2008.01.25. - */ - u32 AdRxOkCnt; - long AdRxSignalStrength; - u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */ - u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */ - u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx - * signal strength for SW Antenna Diversity. - */ - u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */ - u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */ - long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */ - long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */ - bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal - * strength for last time switching antenna. - */ - long AdRxSsBeforeSwitched; /* Rx signal strength before we switched - * antenna. - */ - struct timer_list SwAntennaDiversityTimer; - /* by amy for antenna {by amy 080312 */ - - /* Crystal calibration. Added by Roger, 2007.12.11. */ - - bool bXtalCalibration; /* Crystal calibration.*/ - u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */ - u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */ - - /* Tx power tracking with thermal meter indication. - * Added by Roger, 2007.12.11. - */ - - bool bTxPowerTrack; /* Tx Power tracking. */ - u8 ThermalMeter; /* Thermal meter reference indication. */ - - /* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce, - * 2007-02-14. - */ - bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */ - bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010, - * by rcnjko. - */ - u32 FalseAlarmRegValue; - u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is - * used in DIG. - */ - u8 DIG_NumberFallbackVote; - u8 DIG_NumberUpgradeVote; - /* For HW antenna diversity, added by Roger, 2008.01.30. */ - u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */ - u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */ - bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW - * evaluation. - */ - /* RF High Power upper/lower threshold. */ - u8 RegHiPwrUpperTh; - u8 RegHiPwrLowerTh; - /* RF RSSI High Power upper/lower Threshold. */ - u8 RegRSSIHiPwrUpperTh; - u8 RegRSSIHiPwrLowerTh; - /* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ, - * by Bruce, 2007-04-12. - */ - u8 CurCCKRSSI; - bool bCurCCKPkt; - /* High Power Mechanism. Added by amy, 080312. */ - bool bToUpdateTxPwr; - long UndecoratedSmoothedSS; - long UndecoratedSmoothedRxPower; - u8 RSSI; - char RxPower; - u8 InitialGain; - /* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */ - u32 DozePeriodInPast2Sec; - /* Don't access BB/RF under disable PLL situation. */ - u8 InitialGainBackUp; - u8 RegBModeGainStage; - /* by amy for rate adaptive */ - struct timer_list rateadapter_timer; - u32 RateAdaptivePeriod; - bool bEnhanceTxPwr; - bool bUpdateARFR; - int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.) - */ - u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */ - u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */ - unsigned long NumTxOkTotal; - u16 LastRetryCnt; - u16 LastRetryRate; - unsigned long LastTxokCnt; - unsigned long LastRxokCnt; - u16 CurrRetryCnt; - unsigned long LastTxOKBytes; - unsigned long NumTxOkBytesTotal; - u8 LastFailTxRate; - long LastFailTxRateSS; - u8 FailTxRateCount; - u32 LastTxThroughput; - /* for up rate. */ - unsigned short bTryuping; - u8 CurrTxRate; /* the rate before up. */ - u16 CurrRetryRate; - u16 TryupingCount; - u8 TryDownCountLowData; - u8 TryupingCountNoData; - - u8 CurrentOperaRate; - struct work_struct reset_wq; - struct work_struct watch_dog_wq; - short ack_tx_to_ieee; - - u8 dma_poll_stop_mask; - - u16 ShortRetryLimit; - u16 LongRetryLimit; - u16 EarlyRxThreshold; - u32 TransmitConfig; - u32 ReceiveConfig; - u32 IntrMask; - - struct chnl_access_setting ChannelAccessSetting; -}; - -#define MANAGE_PRIORITY 0 -#define BK_PRIORITY 1 -#define BE_PRIORITY 2 -#define VI_PRIORITY 3 -#define VO_PRIORITY 4 -#define HI_PRIORITY 5 -#define BEACON_PRIORITY 6 - -#define LOW_PRIORITY VI_PRIORITY -#define NORM_PRIORITY VO_PRIORITY -/* AC2Queue mapping. */ -#define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \ - ((_ac) == WME_AC_VI) ? VI_PRIORITY : \ - ((_ac) == WME_AC_BK) ? BK_PRIORITY : \ - BE_PRIORITY) - -short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority, - bool morefrag, short fragdesc, int rate); - -u8 read_nic_byte(struct net_device *dev, int x); -u32 read_nic_dword(struct net_device *dev, int x); -u16 read_nic_word(struct net_device *dev, int x); -void write_nic_byte(struct net_device *dev, int x, u8 y); -void write_nic_word(struct net_device *dev, int x, u16 y); -void write_nic_dword(struct net_device *dev, int x, u32 y); -void force_pci_posting(struct net_device *dev); - -void rtl8180_rtx_disable(struct net_device *); -void rtl8180_set_anaparam(struct net_device *dev, u32 a); -void rtl8185_set_anaparam2(struct net_device *dev, u32 a); -void rtl8180_set_hw_wep(struct net_device *dev); -void rtl8180_no_hw_wep(struct net_device *dev); -void rtl8180_update_msr(struct net_device *dev); -void rtl8180_beacon_tx_disable(struct net_device *dev); -void rtl8180_beacon_rx_disable(struct net_device *dev); -int rtl8180_down(struct net_device *dev); -int rtl8180_up(struct net_device *dev); -void rtl8180_commit(struct net_device *dev); -void rtl8180_set_chan(struct net_device *dev, short ch); -void write_phy(struct net_device *dev, u8 adr, u8 data); -void write_phy_cck(struct net_device *dev, u8 adr, u32 data); -void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data); -void rtl8185_tx_antenna(struct net_device *dev, u8 ant); -void rtl8185_rf_pins_enable(struct net_device *dev); -void IPSEnter(struct net_device *dev); -void IPSLeave(struct net_device *dev); -int get_curr_tx_free_desc(struct net_device *dev, int priority); -void UpdateInitialGain(struct net_device *dev); -bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt, - bool bAntDiversity); - -void rtl8185b_adapter_start(struct net_device *dev); -void rtl8185b_rx_enable(struct net_device *dev); -void rtl8185b_tx_enable(struct net_device *dev); -void rtl8180_reset(struct net_device *dev); -void rtl8185b_irq_enable(struct net_device *dev); -void fix_rx_fifo(struct net_device *dev); -void fix_tx_fifo(struct net_device *dev); -void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch); -void rtl8180_rate_adapter(struct work_struct *work); -bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet, - u32 ChangeSource); - -#endif - -/* fun with the built-in ieee80211 stack... */ -extern int ieee80211_crypto_init(void); -extern void ieee80211_crypto_deinit(void); -extern int ieee80211_crypto_tkip_init(void); -extern void ieee80211_crypto_tkip_exit(void); -extern int ieee80211_crypto_ccmp_init(void); -extern void ieee80211_crypto_ccmp_exit(void); -extern int ieee80211_crypto_wep_init(void); -extern void ieee80211_crypto_wep_exit(void); diff --git a/drivers/staging/rtl8187se/r8180_93cx6.h b/drivers/staging/rtl8187se/r8180_93cx6.h deleted file mode 100644 index b52b5b0..0000000 --- a/drivers/staging/rtl8187se/r8180_93cx6.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - This is part of rtl8180 OpenSource driver - Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com> - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part of the official realtek driver - Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon - Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver - - We want to tanks the Authors of such projects and the Ndiswrapper project Authors. -*/ - -/*This files contains card eeprom (93c46 or 93c56) programming routines*/ -/*memory is addressed by WORDS*/ - -#include "r8180.h" -#include "r8180_hw.h" - -#define EPROM_DELAY 10 - -#define EPROM_ANAPARAM_ADDRLWORD 0xd -#define EPROM_ANAPARAM_ADDRHWORD 0xe - -#define RFCHIPID 0x6 -#define RFCHIPID_INTERSIL 1 -#define RFCHIPID_RFMD 2 -#define RFCHIPID_PHILIPS 3 -#define RFCHIPID_MAXIM 4 -#define RFCHIPID_GCT 5 -#define RFCHIPID_RTL8225 9 -#define RF_ZEBRA2 11 -#define EPROM_TXPW_BASE 0x05 -#define RF_ZEBRA4 12 -#define RFCHIPID_RTL8255 0xa -#define RF_PARAM 0x19 -#define RF_PARAM_DIGPHY_SHIFT 0 -#define RF_PARAM_ANTBDEFAULT_SHIFT 1 -#define RF_PARAM_CARRIERSENSE_SHIFT 2 -#define RF_PARAM_CARRIERSENSE_MASK (3<<2) -#define ENERGY_TRESHOLD 0x17 -#define EPROM_VERSION 0x1E -#define MAC_ADR 0x7 - -#define CIS 0x18 - -#define EPROM_TXPW_OFDM_CH1_2 0x20 - -#define EPROM_TXPW_CH1_2 0x30 - -#define RTL818X_EEPROM_CMD_READ (1 << 0) -#define RTL818X_EEPROM_CMD_WRITE (1 << 1) -#define RTL818X_EEPROM_CMD_CK (1 << 2) -#define RTL818X_EEPROM_CMD_CS (1 << 3) - diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c deleted file mode 100644 index a6022d4..0000000 --- a/drivers/staging/rtl8187se/r8180_core.c +++ /dev/null @@ -1,3775 +0,0 @@ -/* - * This is part of rtl818x pci OpenSource driver - v 0.1 - * Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com> - * Released under the terms of GPL (General Public License) - * - * Parts of this driver are based on the GPL part of the official - * Realtek driver. - * - * Parts of this driver are based on the rtl8180 driver skeleton - * from Patric Schenke & Andres Salomon. - * - * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. - * - * Parts of BB/RF code are derived from David Young rtl8180 netbsd driver. - * - * RSSI calc function from 'The Deuce' - * - * Some ideas borrowed from the 8139too.c driver included in linux kernel. - * - * We (I?) want to thanks the Authors of those projecs and also the - * Ndiswrapper's project Authors. - * - * A big big thanks goes also to Realtek corp. for their help in my attempt to - * add RTL8185 and RTL8225 support, and to David Young also. - * - * Power management interface routines. - * Written by Mariusz Matuszek. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#undef RX_DONT_PASS_UL -#undef DUMMY_RX - -#include <linux/slab.h> -#include <linux/syscalls.h> -#include <linux/eeprom_93cx6.h> -#include <linux/interrupt.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -#include "r8180_hw.h" -#include "r8180.h" -#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */ -#include "r8180_93cx6.h" /* Card EEPROM */ -#include "r8180_wx.h" -#include "r8180_dm.h" - -#include "ieee80211/dot11d.h" - -static struct pci_device_id rtl8180_pci_id_tbl[] = { - { - .vendor = PCI_VENDOR_ID_REALTEK, - .device = 0x8199, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = 0, - .device = 0, - .subvendor = 0, - .subdevice = 0, - .driver_data = 0, - } -}; - -static char ifname[IFNAMSIZ] = "wlan%d"; -static int hwwep; - -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl); -MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>"); -MODULE_DESCRIPTION("Linux driver for Realtek RTL8187SE WiFi cards"); - -module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); -module_param(hwwep, int, S_IRUGO|S_IWUSR); - -MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards"); - -static int rtl8180_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); - -static void rtl8180_pci_remove(struct pci_dev *pdev); - -static void rtl8180_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - if (dev->netdev_ops->ndo_stop) - dev->netdev_ops->ndo_stop(dev); - pci_disable_device(pdev); -} - -static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (!netif_running(dev)) - goto out_pci_suspend; - - if (dev->netdev_ops->ndo_stop) - dev->netdev_ops->ndo_stop(dev); - - netif_device_detach(dev); - -out_pci_suspend: - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int rtl8180_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - int err; - u32 val; - - pci_set_power_state(pdev, PCI_D0); - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "pci_enable_device failed on resume\n"); - - return err; - } - - pci_restore_state(pdev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries - * from interfering with C3 CPU state. pci_restore_state won't help - * here since it only restores the first 64 bytes pci config header. - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - if (!netif_running(dev)) - goto out; - - if (dev->netdev_ops->ndo_open) - dev->netdev_ops->ndo_open(dev); - - netif_device_attach(dev); -out: - return 0; -} - -static struct pci_driver rtl8180_pci_driver = { - .name = RTL8180_MODULE_NAME, - .id_table = rtl8180_pci_id_tbl, - .probe = rtl8180_pci_probe, - .remove = rtl8180_pci_remove, - .suspend = rtl8180_suspend, - .resume = rtl8180_resume, - .shutdown = rtl8180_shutdown, -}; - -u8 read_nic_byte(struct net_device *dev, int x) -{ - return 0xff&readb((u8 __iomem *)dev->mem_start + x); -} - -u32 read_nic_dword(struct net_device *dev, int x) -{ - return readl((u8 __iomem *)dev->mem_start + x); -} - -u16 read_nic_word(struct net_device *dev, int x) -{ - return readw((u8 __iomem *)dev->mem_start + x); -} - -void write_nic_byte(struct net_device *dev, int x, u8 y) -{ - writeb(y, (u8 __iomem *)dev->mem_start + x); - udelay(20); -} - -void write_nic_dword(struct net_device *dev, int x, u32 y) -{ - writel(y, (u8 __iomem *)dev->mem_start + x); - udelay(20); -} - -void write_nic_word(struct net_device *dev, int x, u16 y) -{ - writew(y, (u8 __iomem *)dev->mem_start + x); - udelay(20); -} - -inline void force_pci_posting(struct net_device *dev) -{ - read_nic_byte(dev, EPROM_CMD); - mb(); -} - -static irqreturn_t rtl8180_interrupt(int irq, void *netdev); -void set_nic_rxring(struct net_device *dev); -void set_nic_txring(struct net_device *dev); -static struct net_device_stats *rtl8180_stats(struct net_device *dev); -void rtl8180_commit(struct net_device *dev); -void rtl8180_start_tx_beacon(struct net_device *dev); - -static struct proc_dir_entry *rtl8180_proc; - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = 0xff; - - /* This dump the current register page */ - for (n = 0; n <= max;) { - seq_printf(m, "\nD: %2x > ", n); - - for (i = 0; i < 16 && n <= max; i++, n++) - seq_printf(m, "%2x ", read_nic_byte(dev, n)); - } - seq_putc(m, '\n'); - return 0; -} - -int get_curr_tx_free_desc(struct net_device *dev, int priority); - -static int proc_get_stats_hw(struct seq_file *m, void *v) -{ - return 0; -} - -static int proc_get_stats_rx(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - seq_printf(m, - "RX OK: %lu\n" - "RX Retry: %lu\n" - "RX CRC Error(0-500): %lu\n" - "RX CRC Error(500-1000): %lu\n" - "RX CRC Error(>1000): %lu\n" - "RX ICV Error: %lu\n", - priv->stats.rxint, - priv->stats.rxerr, - priv->stats.rxcrcerrmin, - priv->stats.rxcrcerrmid, - priv->stats.rxcrcerrmax, - priv->stats.rxicverr - ); - - return 0; -} - -static int proc_get_stats_tx(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long totalOK; - - totalOK = priv->stats.txnpokint + priv->stats.txhpokint + - priv->stats.txlpokint; - - seq_printf(m, - "TX OK: %lu\n" - "TX Error: %lu\n" - "TX Retry: %lu\n" - "TX beacon OK: %lu\n" - "TX beacon error: %lu\n", - totalOK, - priv->stats.txnperr+priv->stats.txhperr+priv->stats.txlperr, - priv->stats.txretry, - priv->stats.txbeacon, - priv->stats.txbeaconerr - ); - - return 0; -} - -static void rtl8180_proc_module_init(void) -{ - DMESG("Initializing proc filesystem"); - rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net); -} - -static void rtl8180_proc_module_remove(void) -{ - remove_proc_entry(RTL8180_MODULE_NAME, init_net.proc_net); -} - -static void rtl8180_proc_remove_one(struct net_device *dev) -{ - remove_proc_subtree(dev->name, rtl8180_proc); -} - -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8180_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); - - return single_open(file, show, dev); -} - -static const struct file_operations rtl8180_proc_fops = { - .open = rtl8180_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * Table of proc files we need to create. - */ -struct rtl8180_proc_file { - char name[12]; - int (*show)(struct seq_file *, void *); -}; - -static const struct rtl8180_proc_file rtl8180_proc_files[] = { - { "stats-hw", &proc_get_stats_hw }, - { "stats-rx", &proc_get_stats_rx }, - { "stats-tx", &proc_get_stats_tx }, - { "registers", &proc_get_registers }, - { "" } -}; - -static void rtl8180_proc_init_one(struct net_device *dev) -{ - const struct rtl8180_proc_file *f; - struct proc_dir_entry *dir; - - dir = proc_mkdir_data(dev->name, 0, rtl8180_proc, dev); - if (!dir) { - DMESGE("Unable to initialize /proc/net/r8180/%s\n", dev->name); - return; - } - - for (f = rtl8180_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8180_proc_fops, f->show)) { - DMESGE("Unable to initialize /proc/net/r8180/%s/%s\n", - dev->name, f->name); - return; - } - } -} - -/* - * FIXME: check if we can use some standard already-existent - * data type+functions in kernel. - */ - -static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma, - struct buffer **bufferhead) -{ - struct buffer *tmp; - - if (!*buffer) { - - *buffer = kmalloc(sizeof(struct buffer), GFP_KERNEL); - - if (*buffer == NULL) { - DMESGE("Failed to kmalloc head of TX/RX struct"); - return -1; - } - (*buffer)->next = *buffer; - (*buffer)->buf = buf; - (*buffer)->dma = dma; - if (bufferhead != NULL) - (*bufferhead) = (*buffer); - return 0; - } - tmp = *buffer; - - while (tmp->next != (*buffer)) - tmp = tmp->next; - tmp->next = kmalloc(sizeof(struct buffer), GFP_KERNEL); - if (tmp->next == NULL) { - DMESGE("Failed to kmalloc TX/RX struct"); - return -1; - } - tmp->next->buf = buf; - tmp->next->dma = dma; - tmp->next->next = *buffer; - - return 0; -} - -static void buffer_free(struct net_device *dev, struct buffer **buffer, int len, - short consistent) -{ - - struct buffer *tmp, *next; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - - if (!*buffer) - return; - - tmp = *buffer; - - do { - next = tmp->next; - if (consistent) { - pci_free_consistent(pdev, len, - tmp->buf, tmp->dma); - } else { - pci_unmap_single(pdev, tmp->dma, - len, PCI_DMA_FROMDEVICE); - kfree(tmp->buf); - } - kfree(tmp); - tmp = next; - } while (next != *buffer); - - *buffer = NULL; -} - -int get_curr_tx_free_desc(struct net_device *dev, int priority) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u32 *tail; - u32 *head; - int ret; - - switch (priority) { - case MANAGE_PRIORITY: - head = priv->txmapringhead; - tail = priv->txmapringtail; - break; - case BK_PRIORITY: - head = priv->txbkpringhead; - tail = priv->txbkpringtail; - break; - case BE_PRIORITY: - head = priv->txbepringhead; - tail = priv->txbepringtail; - break; - case VI_PRIORITY: - head = priv->txvipringhead; - tail = priv->txvipringtail; - break; - case VO_PRIORITY: - head = priv->txvopringhead; - tail = priv->txvopringtail; - break; - case HI_PRIORITY: - head = priv->txhpringhead; - tail = priv->txhpringtail; - break; - default: - return -1; - } - - if (head <= tail) - ret = priv->txringcount - (tail - head)/8; - else - ret = (head - tail)/8; - - if (ret > priv->txringcount) - DMESG("BUG"); - - return ret; -} - -static short check_nic_enought_desc(struct net_device *dev, int priority) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = netdev_priv(dev); - int requiredbyte; - int required; - - requiredbyte = priv->ieee80211->fts + - sizeof(struct ieee80211_header_data); - - if (ieee->current_network.QoS_Enable) - requiredbyte += 2; - - required = requiredbyte / (priv->txbuffsize-4); - - if (requiredbyte % priv->txbuffsize) - required++; - - /* for now we keep two free descriptor as a safety boundary - * between the tail and the head - */ - - return required + 2 < get_curr_tx_free_desc(dev, priority); -} - -void fix_tx_fifo(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 *tmp; - int i; - - for (tmp = priv->txmapring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txbkpring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txbepring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - for (tmp = priv->txvipring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txvopring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txhpring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txbeaconring, i = 0; - i < priv->txbeaconcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - priv->txmapringtail = priv->txmapring; - priv->txmapringhead = priv->txmapring; - priv->txmapbufstail = priv->txmapbufs; - - priv->txbkpringtail = priv->txbkpring; - priv->txbkpringhead = priv->txbkpring; - priv->txbkpbufstail = priv->txbkpbufs; - - priv->txbepringtail = priv->txbepring; - priv->txbepringhead = priv->txbepring; - priv->txbepbufstail = priv->txbepbufs; - - priv->txvipringtail = priv->txvipring; - priv->txvipringhead = priv->txvipring; - priv->txvipbufstail = priv->txvipbufs; - - priv->txvopringtail = priv->txvopring; - priv->txvopringhead = priv->txvopring; - priv->txvopbufstail = priv->txvopbufs; - - priv->txhpringtail = priv->txhpring; - priv->txhpringhead = priv->txhpring; - priv->txhpbufstail = priv->txhpbufs; - - priv->txbeaconringtail = priv->txbeaconring; - priv->txbeaconbufstail = priv->txbeaconbufs; - set_nic_txring(dev); - - ieee80211_reset_queue(priv->ieee80211); - priv->ack_tx_to_ieee = 0; -} - -void fix_rx_fifo(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 *tmp; - struct buffer *rxbuf; - u8 rx_desc_size; - - rx_desc_size = 8; /* 4*8 = 32 bytes */ - - for (tmp = priv->rxring, rxbuf = priv->rxbufferhead; - (tmp < (priv->rxring)+(priv->rxringcount)*rx_desc_size); - tmp += rx_desc_size, rxbuf = rxbuf->next) { - *(tmp+2) = rxbuf->dma; - *tmp = *tmp & ~0xfff; - *tmp = *tmp | priv->rxbuffersize; - *tmp |= (1<<31); - } - - priv->rxringtail = priv->rxring; - priv->rxbuffer = priv->rxbufferhead; - priv->rx_skb_complete = 1; - set_nic_rxring(dev); -} - -static void rtl8180_irq_disable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - write_nic_dword(dev, IMR, 0); - force_pci_posting(dev); - priv->irq_enabled = 0; -} - -void rtl8180_set_mode(struct net_device *dev, int mode) -{ - u8 ecmd; - - ecmd = read_nic_byte(dev, EPROM_CMD); - ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK; - ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT); - ecmd = ecmd & ~(1<<EPROM_CS_SHIFT); - ecmd = ecmd & ~(1<<EPROM_CK_SHIFT); - write_nic_byte(dev, EPROM_CMD, ecmd); -} - -void rtl8180_beacon_tx_enable(struct net_device *dev); - -void rtl8180_update_msr(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 msr; - u32 rxconf; - - msr = read_nic_byte(dev, MSR); - msr &= ~MSR_LINK_MASK; - - rxconf = read_nic_dword(dev, RX_CONF); - - if (priv->ieee80211->state == IEEE80211_LINKED) { - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT); - else if (priv->ieee80211->iw_mode == IW_MODE_MASTER) - msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT); - else if (priv->ieee80211->iw_mode == IW_MODE_INFRA) - msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT); - else - msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT); - rxconf |= (1<<RX_CHECK_BSSID_SHIFT); - - } else { - msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT); - rxconf &= ~(1<<RX_CHECK_BSSID_SHIFT); - } - - write_nic_byte(dev, MSR, msr); - write_nic_dword(dev, RX_CONF, rxconf); -} - -void rtl8180_set_chan(struct net_device *dev, short ch) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - if ((ch > 14) || (ch < 1)) { - netdev_err(dev, "In %s: Invalid channel %d\n", __func__, ch); - return; - } - - priv->chan = ch; - priv->rf_set_chan(dev, priv->chan); -} - -void set_nic_txring(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - write_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR, priv->txmapringdma); - write_nic_dword(dev, TX_BKPRIORITY_RING_ADDR, priv->txbkpringdma); - write_nic_dword(dev, TX_BEPRIORITY_RING_ADDR, priv->txbepringdma); - write_nic_dword(dev, TX_VIPRIORITY_RING_ADDR, priv->txvipringdma); - write_nic_dword(dev, TX_VOPRIORITY_RING_ADDR, priv->txvopringdma); - write_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR, priv->txhpringdma); - write_nic_dword(dev, TX_BEACON_RING_ADDR, priv->txbeaconringdma); -} - -void rtl8180_beacon_tx_enable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_BQ); - write_nic_byte(dev, TPPollStop, priv->dma_poll_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -void rtl8180_beacon_tx_disable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask |= TPPOLLSTOP_BQ; - write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - -} - -void rtl8180_rtx_disable(struct net_device *dev) -{ - u8 cmd; - struct r8180_priv *priv = ieee80211_priv(dev); - - cmd = read_nic_byte(dev, CMD); - write_nic_byte(dev, CMD, cmd & - ~((1<<CMD_RX_ENABLE_SHIFT)|(1<<CMD_TX_ENABLE_SHIFT))); - force_pci_posting(dev); - mdelay(10); - - if (!priv->rx_skb_complete) - dev_kfree_skb_any(priv->rx_skb); -} - -static short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count, - int addr) -{ - int i; - u32 *desc; - u32 *tmp; - dma_addr_t dma_desc, dma_tmp; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - void *buf; - - if ((bufsize & 0xfff) != bufsize) { - DMESGE("TX buffer allocation too large"); - return 0; - } - desc = (u32 *)pci_alloc_consistent(pdev, - sizeof(u32)*8*count+256, &dma_desc); - if (desc == NULL) - return -1; - - if (dma_desc & 0xff) - /* - * descriptor's buffer must be 256 byte aligned - * we shouldn't be here, since we set DMA mask ! - */ - WARN(1, "DMA buffer is not aligned\n"); - - tmp = desc; - - for (i = 0; i < count; i++) { - buf = (void *)pci_alloc_consistent(pdev, bufsize, &dma_tmp); - if (buf == NULL) - return -ENOMEM; - - switch (addr) { - case TX_MANAGEPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txmapbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer NP"); - return -ENOMEM; - } - break; - case TX_BKPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txbkpbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer LP"); - return -ENOMEM; - } - break; - case TX_BEPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txbepbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer NP"); - return -ENOMEM; - } - break; - case TX_VIPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txvipbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer LP"); - return -ENOMEM; - } - break; - case TX_VOPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txvopbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer NP"); - return -ENOMEM; - } - break; - case TX_HIGHPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txhpbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer HP"); - return -ENOMEM; - } - break; - case TX_BEACON_RING_ADDR: - if (-1 == buffer_add(&priv->txbeaconbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer BP"); - return -ENOMEM; - } - break; - } - *tmp = *tmp & ~(1<<31); /* descriptor empty, owned by the drv */ - *(tmp+2) = (u32)dma_tmp; - *(tmp+3) = bufsize; - - if (i+1 < count) - *(tmp+4) = (u32)dma_desc+((i+1)*8*4); - else - *(tmp+4) = (u32)dma_desc; - - tmp = tmp+8; - } - - switch (addr) { - case TX_MANAGEPRIORITY_RING_ADDR: - priv->txmapringdma = dma_desc; - priv->txmapring = desc; - break; - case TX_BKPRIORITY_RING_ADDR: - priv->txbkpringdma = dma_desc; - priv->txbkpring = desc; - break; - case TX_BEPRIORITY_RING_ADDR: - priv->txbepringdma = dma_desc; - priv->txbepring = desc; - break; - case TX_VIPRIORITY_RING_ADDR: - priv->txvipringdma = dma_desc; - priv->txvipring = desc; - break; - case TX_VOPRIORITY_RING_ADDR: - priv->txvopringdma = dma_desc; - priv->txvopring = desc; - break; - case TX_HIGHPRIORITY_RING_ADDR: - priv->txhpringdma = dma_desc; - priv->txhpring = desc; - break; - case TX_BEACON_RING_ADDR: - priv->txbeaconringdma = dma_desc; - priv->txbeaconring = desc; - break; - - } - - return 0; -} - -static void free_tx_desc_rings(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - int count = priv->txringcount; - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txmapring, priv->txmapringdma); - buffer_free(dev, &(priv->txmapbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txbkpring, priv->txbkpringdma); - buffer_free(dev, &(priv->txbkpbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txbepring, priv->txbepringdma); - buffer_free(dev, &(priv->txbepbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txvipring, priv->txvipringdma); - buffer_free(dev, &(priv->txvipbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txvopring, priv->txvopringdma); - buffer_free(dev, &(priv->txvopbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txhpring, priv->txhpringdma); - buffer_free(dev, &(priv->txhpbufs), priv->txbuffsize, 1); - - count = priv->txbeaconcount; - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txbeaconring, priv->txbeaconringdma); - buffer_free(dev, &(priv->txbeaconbufs), priv->txbuffsize, 1); -} - -static void free_rx_desc_ring(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - int count = priv->rxringcount; - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->rxring, priv->rxringdma); - - buffer_free(dev, &(priv->rxbuffer), priv->rxbuffersize, 0); -} - -static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count) -{ - int i; - u32 *desc; - u32 *tmp; - dma_addr_t dma_desc, dma_tmp; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - void *buf; - u8 rx_desc_size; - - rx_desc_size = 8; /* 4*8 = 32 bytes */ - - if ((bufsize & 0xfff) != bufsize) { - DMESGE("RX buffer allocation too large"); - return -1; - } - - desc = (u32 *)pci_alloc_consistent(pdev, - sizeof(u32) * rx_desc_size * count + 256, &dma_desc); - - if (dma_desc & 0xff) - /* - * descriptor's buffer must be 256 byte aligned - * should never happen since we specify the DMA mask - */ - WARN(1, "DMA buffer is not aligned\n"); - - priv->rxring = desc; - priv->rxringdma = dma_desc; - tmp = desc; - - for (i = 0; i < count; i++) { - buf = kmalloc(bufsize * sizeof(u8), GFP_ATOMIC); - if (buf == NULL) { - DMESGE("Failed to kmalloc RX buffer"); - return -1; - } - - dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma_tmp)) - return -1; - if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, - &(priv->rxbufferhead))) { - DMESGE("Unable to allocate mem RX buf"); - return -1; - } - *tmp = 0; /* zero pads the header of the descriptor */ - *tmp = *tmp | (bufsize&0xfff); - *(tmp+2) = (u32)dma_tmp; - *tmp = *tmp | (1<<31); /* descriptor void, owned by the NIC */ - - tmp = tmp+rx_desc_size; - } - - /* this is the last descriptor */ - *(tmp - rx_desc_size) = *(tmp - rx_desc_size) | (1 << 30); - - return 0; -} - - -void set_nic_rxring(struct net_device *dev) -{ - u8 pgreg; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - pgreg = read_nic_byte(dev, PGSELECT); - write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT)); - - write_nic_dword(dev, RXRING_ADDR, priv->rxringdma); -} - -void rtl8180_reset(struct net_device *dev) -{ - u8 cr; - - rtl8180_irq_disable(dev); - - cr = read_nic_byte(dev, CMD); - cr = cr & 2; - cr = cr | (1<<CMD_RST_SHIFT); - write_nic_byte(dev, CMD, cr); - - force_pci_posting(dev); - - mdelay(200); - - if (read_nic_byte(dev, CMD) & (1<<CMD_RST_SHIFT)) - DMESGW("Card reset timeout!"); - else - DMESG("Card successfully reset"); - - rtl8180_set_mode(dev, EPROM_CMD_LOAD); - force_pci_posting(dev); - mdelay(200); -} - -inline u16 ieeerate2rtlrate(int rate) -{ - switch (rate) { - case 10: - return 0; - case 20: - return 1; - case 55: - return 2; - case 110: - return 3; - case 60: - return 4; - case 90: - return 5; - case 120: - return 6; - case 180: - return 7; - case 240: - return 8; - case 360: - return 9; - case 480: - return 10; - case 540: - return 11; - default: - return 3; - } -} - -static u16 rtl_rate[] = {10, 20, 55, 110, 60, - 90, 120, 180, 240, 360, 480, 540, 720}; - -inline u16 rtl8180_rate2rate(short rate) -{ - if (rate > 12) - return 10; - return rtl_rate[rate]; -} - -inline u8 rtl8180_IsWirelessBMode(u16 rate) -{ - if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220)) - return 1; - else - return 0; -} - -u16 N_DBPSOfRate(u16 DataRate); - -static u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame, - u8 bShortPreamble) -{ - u16 FrameTime; - u16 N_DBPS; - u16 Ceiling; - - if (rtl8180_IsWirelessBMode(DataRate)) { - if (bManagementFrame || !bShortPreamble || DataRate == 10) - /* long preamble */ - FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10))); - else - /* short preamble */ - FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10))); - - if ((FrameLength*8 % (DataRate/10)) != 0) /* get the ceilling */ - FrameTime++; - } else { /* 802.11g DSSS-OFDM PLCP length field calculation. */ - N_DBPS = N_DBPSOfRate(DataRate); - Ceiling = (16 + 8*FrameLength + 6) / N_DBPS - + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0); - FrameTime = (u16)(16 + 4 + 4*Ceiling + 6); - } - return FrameTime; -} - -u16 N_DBPSOfRate(u16 DataRate) -{ - u16 N_DBPS = 24; - - switch (DataRate) { - case 60: - N_DBPS = 24; - break; - case 90: - N_DBPS = 36; - break; - case 120: - N_DBPS = 48; - break; - case 180: - N_DBPS = 72; - break; - case 240: - N_DBPS = 96; - break; - case 360: - N_DBPS = 144; - break; - case 480: - N_DBPS = 192; - break; - case 540: - N_DBPS = 216; - break; - default: - break; - } - - return N_DBPS; -} - -/* - * For Netgear case, they want good-looking signal strength. - */ -static long NetgearSignalStrengthTranslate(long LastSS, long CurrSS) -{ - long RetSS; - - /* Step 1. Scale mapping. */ - if (CurrSS >= 71 && CurrSS <= 100) - RetSS = 90 + ((CurrSS - 70) / 3); - else if (CurrSS >= 41 && CurrSS <= 70) - RetSS = 78 + ((CurrSS - 40) / 3); - else if (CurrSS >= 31 && CurrSS <= 40) - RetSS = 66 + (CurrSS - 30); - else if (CurrSS >= 21 && CurrSS <= 30) - RetSS = 54 + (CurrSS - 20); - else if (CurrSS >= 5 && CurrSS <= 20) - RetSS = 42 + (((CurrSS - 5) * 2) / 3); - else if (CurrSS == 4) - RetSS = 36; - else if (CurrSS == 3) - RetSS = 27; - else if (CurrSS == 2) - RetSS = 18; - else if (CurrSS == 1) - RetSS = 9; - else - RetSS = CurrSS; - - /* Step 2. Smoothing. */ - if (LastSS > 0) - RetSS = ((LastSS * 5) + (RetSS) + 5) / 6; - - return RetSS; -} - -/* - * Translate 0-100 signal strength index into dBm. - */ -static long TranslateToDbm8185(u8 SignalStrengthIndex) -{ - long SignalPower; - - /* Translate to dBm (x=0.5y-95). */ - SignalPower = (long)((SignalStrengthIndex + 1) >> 1); - SignalPower -= 95; - - return SignalPower; -} - -/* - * Perform signal smoothing for dynamic mechanism. - * This is different with PerformSignalSmoothing8185 in smoothing formula. - * No dramatic adjustment is applied because dynamic mechanism need some - * degree of correctness. Ported from 8187B. - */ -static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv, - bool bCckRate) -{ - long smoothedSS; - long smoothedRx; - - /* Determine the current packet is CCK rate. */ - priv->bCurCCKPkt = bCckRate; - - smoothedSS = priv->SignalStrength * 10; - - if (priv->UndecoratedSmoothedSS >= 0) - smoothedSS = ((priv->UndecoratedSmoothedSS * 5) + - smoothedSS) / 6; - - priv->UndecoratedSmoothedSS = smoothedSS; - - smoothedRx = ((priv->UndecoratedSmoothedRxPower * 50) + - (priv->RxPower * 11)) / 60; - - priv->UndecoratedSmoothedRxPower = smoothedRx; - - if (bCckRate) - priv->CurCCKRSSI = priv->RSSI; - else - priv->CurCCKRSSI = 0; -} - - -/* - * This is rough RX isr handling routine - */ -static void rtl8180_rx(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct sk_buff *tmp_skb; - short first, last; - u32 len; - int lastlen; - unsigned char quality, signal; - u8 rate; - u32 *tmp, *tmp2; - u8 rx_desc_size; - u8 padding; - char rxpower = 0; - u32 RXAGC = 0; - long RxAGC_dBm = 0; - u8 LNA = 0, BB = 0; - u8 LNA_gain[4] = {02, 17, 29, 39}; - u8 Antenna = 0; - struct ieee80211_hdr_4addr *hdr; - u16 fc, type; - u8 bHwError = 0, bCRC = 0, bICV = 0; - bool bCckRate = false; - u8 RSSI = 0; - long SignalStrengthIndex = 0; - struct ieee80211_rx_stats stats = { - .signal = 0, - .noise = -98, - .rate = 0, - .freq = IEEE80211_24GHZ_BAND, - }; - - stats.nic_type = NIC_8185B; - rx_desc_size = 8; - - if ((*(priv->rxringtail)) & (1<<31)) { - /* we have got an RX int, but the descriptor. we are pointing - * is empty. - */ - - priv->stats.rxnodata++; - priv->ieee80211->stats.rx_errors++; - - tmp2 = NULL; - tmp = priv->rxringtail; - do { - if (tmp == priv->rxring) - tmp = priv->rxring + (priv->rxringcount - 1) * - rx_desc_size; - else - tmp -= rx_desc_size; - - if (!(*tmp & (1<<31))) - tmp2 = tmp; - } while (tmp != priv->rxring); - - if (tmp2) - priv->rxringtail = tmp2; - } - - /* while there are filled descriptors */ - while (!(*(priv->rxringtail) & (1<<31))) { - if (*(priv->rxringtail) & (1<<26)) - DMESGW("RX buffer overflow"); - if (*(priv->rxringtail) & (1<<12)) - priv->stats.rxicverr++; - - if (*(priv->rxringtail) & (1<<27)) { - priv->stats.rxdmafail++; - goto drop; - } - - pci_dma_sync_single_for_cpu(priv->pdev, - priv->rxbuffer->dma, - priv->rxbuffersize * sizeof(u8), - PCI_DMA_FROMDEVICE); - - first = *(priv->rxringtail) & (1<<29) ? 1 : 0; - if (first) - priv->rx_prevlen = 0; - - last = *(priv->rxringtail) & (1<<28) ? 1 : 0; - if (last) { - lastlen = ((*priv->rxringtail) & 0xfff); - - /* if the last descriptor (that should tell us the total - * packet len) tell us something less than the - * descriptors len we had until now, then there is some - * problem.. - * workaround to prevent kernel panic - */ - if (lastlen < priv->rx_prevlen) - len = 0; - else - len = lastlen-priv->rx_prevlen; - - if (*(priv->rxringtail) & (1<<13)) { - if ((*(priv->rxringtail) & 0xfff) < 500) - priv->stats.rxcrcerrmin++; - else if ((*(priv->rxringtail) & 0x0fff) > 1000) - priv->stats.rxcrcerrmax++; - else - priv->stats.rxcrcerrmid++; - - } - - } else { - len = priv->rxbuffersize; - } - - if (first && last) { - padding = ((*(priv->rxringtail+3))&(0x04000000))>>26; - } else if (first) { - padding = ((*(priv->rxringtail+3))&(0x04000000))>>26; - if (padding) - len -= 2; - } else { - padding = 0; - } - padding = 0; - priv->rx_prevlen += len; - - if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) { - /* HW is probably passing several buggy frames without - * FD or LD flag set. - * Throw this garbage away to prevent skb memory - * exhausting - */ - if (!priv->rx_skb_complete) - dev_kfree_skb_any(priv->rx_skb); - priv->rx_skb_complete = 1; - } - - signal = (unsigned char)((*(priv->rxringtail + 3) & - 0x00ff0000) >> 16); - signal = (signal & 0xfe) >> 1; - - quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff)); - - stats.mac_time[0] = *(priv->rxringtail+1); - stats.mac_time[1] = *(priv->rxringtail+2); - - rxpower = ((char)((*(priv->rxringtail + 4) & - 0x00ff0000) >> 16)) / 2 - 42; - - RSSI = ((u8)((*(priv->rxringtail + 3) & - 0x0000ff00) >> 8)) & 0x7f; - - rate = ((*(priv->rxringtail)) & - ((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20; - - stats.rate = rtl8180_rate2rate(rate); - Antenna = (*(priv->rxringtail + 3) & 0x00008000) == 0 ? 0 : 1; - if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */ - RxAGC_dBm = rxpower+1; /* bias */ - } else { /* CCK rate. */ - RxAGC_dBm = signal; /* bit 0 discard */ - - LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */ - BB = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */ - - /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */ - RxAGC_dBm = -(LNA_gain[LNA] + (BB * 2)); - - RxAGC_dBm += 4; /* bias */ - } - - if (RxAGC_dBm & 0x80) /* absolute value */ - RXAGC = ~(RxAGC_dBm)+1; - bCckRate = rtl8180_IsWirelessBMode(stats.rate); - /* Translate RXAGC into 1-100. */ - if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */ - if (RXAGC > 90) - RXAGC = 90; - else if (RXAGC < 25) - RXAGC = 25; - RXAGC = (90-RXAGC)*100/65; - } else { /* CCK rate. */ - if (RXAGC > 95) - RXAGC = 95; - else if (RXAGC < 30) - RXAGC = 30; - RXAGC = (95-RXAGC)*100/65; - } - priv->SignalStrength = (u8)RXAGC; - priv->RecvSignalPower = RxAGC_dBm; - priv->RxPower = rxpower; - priv->RSSI = RSSI; - /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */ - if (quality >= 127) - /* 0 causes epc to show signal zero, walk around now */ - quality = 1; - else if (quality < 27) - quality = 100; - else - quality = 127 - quality; - priv->SignalQuality = quality; - - stats.signal = (u8) quality; - - stats.signalstrength = RXAGC; - if (stats.signalstrength > 100) - stats.signalstrength = 100; - stats.signalstrength = (stats.signalstrength * 70) / 100 + 30; - stats.rssi = priv->wstats.qual.qual = priv->SignalQuality; - stats.noise = priv->wstats.qual.noise = - 100 - priv->wstats.qual.qual; - bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) | - (((*(priv->rxringtail)) & (0x04000000)) != 0) | - (((*(priv->rxringtail)) & (0x08000000)) != 0) | - (((~(*(priv->rxringtail))) & (0x10000000)) != 0) | - (((~(*(priv->rxringtail))) & (0x20000000)) != 0); - bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13; - bICV = ((*(priv->rxringtail)) & (0x00001000)) >> 12; - hdr = (struct ieee80211_hdr_4addr *)priv->rxbuffer->buf; - fc = le16_to_cpu(hdr->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); - - if (IEEE80211_FTYPE_CTL != type && - !bHwError && !bCRC && !bICV && - eqMacAddr(priv->ieee80211->current_network.bssid, - fc & IEEE80211_FCTL_TODS ? hdr->addr1 : - fc & IEEE80211_FCTL_FROMDS ? hdr->addr2 : - hdr->addr3)) { - - /* Perform signal smoothing for dynamic - * mechanism on demand. This is different - * with PerformSignalSmoothing8185 in smoothing - * fomula. No dramatic adjustion is apply - * because dynamic mechanism need some degree - * of correctness. */ - PerformUndecoratedSignalSmoothing8185(priv, bCckRate); - - /* For good-looking singal strength. */ - SignalStrengthIndex = NetgearSignalStrengthTranslate( - priv->LastSignalStrengthInPercent, - priv->SignalStrength); - - priv->LastSignalStrengthInPercent = SignalStrengthIndex; - priv->Stats_SignalStrength = - TranslateToDbm8185((u8)SignalStrengthIndex); - - /* - * We need more correct power of received packets and - * the "SignalStrength" of RxStats is beautified, so we - * record the correct power here. - */ - - priv->Stats_SignalQuality = (long)( - priv->Stats_SignalQuality * 5 + - (long)priv->SignalQuality + 5) / 6; - - priv->Stats_RecvSignalPower = (long)( - priv->Stats_RecvSignalPower * 5 + - priv->RecvSignalPower - 1) / 6; - - /* - * Figure out which antenna received the last packet. - * 0: aux, 1: main - */ - priv->LastRxPktAntenna = Antenna ? 1 : 0; - SwAntennaDiversityRxOk8185(dev, priv->SignalStrength); - } - - if (first) { - if (!priv->rx_skb_complete) { - /* seems that HW sometimes fails to receive and - * doesn't provide the last descriptor. - */ - dev_kfree_skb_any(priv->rx_skb); - priv->stats.rxnolast++; - } - priv->rx_skb = dev_alloc_skb(len+2); - if (!priv->rx_skb) - goto drop; - - priv->rx_skb_complete = 0; - priv->rx_skb->dev = dev; - } else { - /* if we are here we should have already RXed the first - * frame. - * If we get here and the skb is not allocated then - * we have just throw out garbage (skb not allocated) - * and we are still rxing garbage.... - */ - if (!priv->rx_skb_complete) { - - tmp_skb = dev_alloc_skb( - priv->rx_skb->len + len + 2); - - if (!tmp_skb) - goto drop; - - tmp_skb->dev = dev; - - memcpy(skb_put(tmp_skb, priv->rx_skb->len), - priv->rx_skb->data, - priv->rx_skb->len); - - dev_kfree_skb_any(priv->rx_skb); - - priv->rx_skb = tmp_skb; - } - } - - if (!priv->rx_skb_complete) { - memcpy(skb_put(priv->rx_skb, len), ((unsigned char *) - priv->rxbuffer->buf) + (padding ? 2 : 0), len); - } - - if (last && !priv->rx_skb_complete) { - if (priv->rx_skb->len > 4) - skb_trim(priv->rx_skb, priv->rx_skb->len-4); - if (!ieee80211_rtl_rx(priv->ieee80211, - priv->rx_skb, &stats)) - dev_kfree_skb_any(priv->rx_skb); - priv->rx_skb_complete = 1; - } - - pci_dma_sync_single_for_device(priv->pdev, - priv->rxbuffer->dma, - priv->rxbuffersize * sizeof(u8), - PCI_DMA_FROMDEVICE); - -drop: /* this is used when we have not enough mem */ - /* restore the descriptor */ - *(priv->rxringtail+2) = priv->rxbuffer->dma; - *(priv->rxringtail) = *(priv->rxringtail) & ~0xfff; - *(priv->rxringtail) = - *(priv->rxringtail) | priv->rxbuffersize; - - *(priv->rxringtail) = - *(priv->rxringtail) | (1<<31); - - priv->rxringtail += rx_desc_size; - if (priv->rxringtail >= - (priv->rxring)+(priv->rxringcount)*rx_desc_size) - priv->rxringtail = priv->rxring; - - priv->rxbuffer = (priv->rxbuffer->next); - } -} - - -static void rtl8180_dma_kick(struct net_device *dev, int priority) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - write_nic_byte(dev, TX_DMA_POLLING, - (1 << (priority + 1)) | priv->dma_poll_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - force_pci_posting(dev); -} - -static void rtl8180_data_hard_stop(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask |= TPPOLLSTOP_AC_VIQ; - write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -static void rtl8180_data_hard_resume(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_AC_VIQ); - write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -/* - * This function TX data frames when the ieee80211 stack requires this. - * It checks also if we need to stop the ieee tx queue, eventually do it - */ -static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, - int rate) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - int mode; - struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *)skb->data; - bool morefrag = le16_to_cpu(h->frame_control) & IEEE80211_FCTL_MOREFRAGS; - unsigned long flags; - int priority; - - mode = priv->ieee80211->iw_mode; - - rate = ieeerate2rtlrate(rate); - /* - * This function doesn't require lock because we make sure it's called - * with the tx_lock already acquired. - * This come from the kernel's hard_xmit callback (through the ieee - * stack, or from the try_wake_queue (again through the ieee stack. - */ - priority = AC2Q(skb->priority); - spin_lock_irqsave(&priv->tx_lock, flags); - - if (priv->ieee80211->bHwRadioOff) { - spin_unlock_irqrestore(&priv->tx_lock, flags); - - return; - } - - if (!check_nic_enought_desc(dev, priority)) { - DMESGW("Error: no descriptor left by previous TX (avail %d) ", - get_curr_tx_free_desc(dev, priority)); - ieee80211_rtl_stop_queue(priv->ieee80211); - } - rtl8180_tx(dev, skb->data, skb->len, priority, morefrag, 0, rate); - if (!check_nic_enought_desc(dev, priority)) - ieee80211_rtl_stop_queue(priv->ieee80211); - - spin_unlock_irqrestore(&priv->tx_lock, flags); -} - -/* - * This is a rough attempt to TX a frame - * This is called by the ieee 80211 stack to TX management frames. - * If the ring is full packets are dropped (for data frame the queue - * is stopped before this can happen). For this reason it is better - * if the descriptors are larger than the largest management frame - * we intend to TX: i'm unsure what the HW does if it will not find - * the last fragment of a frame because it has been dropped... - * Since queues for Management and Data frames are different we - * might use a different lock than tx_lock (for example mgmt_tx_lock) - */ -/* these function may loop if invoked with 0 descriptors or 0 len buffer */ -static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long flags; - int priority; - - priority = MANAGE_PRIORITY; - - spin_lock_irqsave(&priv->tx_lock, flags); - - if (priv->ieee80211->bHwRadioOff) { - spin_unlock_irqrestore(&priv->tx_lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - rtl8180_tx(dev, skb->data, skb->len, priority, - 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate)); - - priv->ieee80211->stats.tx_bytes += skb->len; - priv->ieee80211->stats.tx_packets++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static void rtl8180_prepare_beacon(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct sk_buff *skb; - - u16 word = read_nic_word(dev, BcnItv); - word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */ - - /* word |= 0x64; */ - word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval); - - write_nic_word(dev, BcnItv, word); - - skb = ieee80211_get_beacon(priv->ieee80211); - if (skb) { - rtl8180_tx(dev, skb->data, skb->len, BEACON_PRIORITY, - 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate)); - dev_kfree_skb_any(skb); - } -} - -/* - * This function do the real dirty work: it enqueues a TX command descriptor in - * the ring buffer, copyes the frame in a TX buffer and kicks the NIC to ensure - * it does the DMA transfer. - */ -short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority, - bool morefrag, short descfrag, int rate) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u32 *tail, *temp_tail; - u32 *begin; - u32 *buf; - int i; - int remain; - int buflen; - int count; - struct buffer *buflist; - struct ieee80211_hdr_3addr *frag_hdr = - (struct ieee80211_hdr_3addr *)txbuf; - u8 dest[ETH_ALEN]; - u8 bUseShortPreamble = 0; - u8 bCTSEnable = 0; - u8 bRTSEnable = 0; - u16 Duration = 0; - u16 RtsDur = 0; - u16 ThisFrameTime = 0; - u16 TxDescDuration = 0; - bool ownbit_flag = false; - - switch (priority) { - case MANAGE_PRIORITY: - tail = priv->txmapringtail; - begin = priv->txmapring; - buflist = priv->txmapbufstail; - count = priv->txringcount; - break; - case BK_PRIORITY: - tail = priv->txbkpringtail; - begin = priv->txbkpring; - buflist = priv->txbkpbufstail; - count = priv->txringcount; - break; - case BE_PRIORITY: - tail = priv->txbepringtail; - begin = priv->txbepring; - buflist = priv->txbepbufstail; - count = priv->txringcount; - break; - case VI_PRIORITY: - tail = priv->txvipringtail; - begin = priv->txvipring; - buflist = priv->txvipbufstail; - count = priv->txringcount; - break; - case VO_PRIORITY: - tail = priv->txvopringtail; - begin = priv->txvopring; - buflist = priv->txvopbufstail; - count = priv->txringcount; - break; - case HI_PRIORITY: - tail = priv->txhpringtail; - begin = priv->txhpring; - buflist = priv->txhpbufstail; - count = priv->txringcount; - break; - case BEACON_PRIORITY: - tail = priv->txbeaconringtail; - begin = priv->txbeaconring; - buflist = priv->txbeaconbufstail; - count = priv->txbeaconcount; - break; - default: - return -1; - break; - } - - memcpy(&dest, frag_hdr->addr1, ETH_ALEN); - if (is_multicast_ether_addr(dest)) { - Duration = 0; - RtsDur = 0; - bRTSEnable = 0; - bCTSEnable = 0; - - ThisFrameTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, bUseShortPreamble); - TxDescDuration = ThisFrameTime; - } else { /* Unicast packet */ - u16 AckTime; - - /* for Keep alive */ - priv->NumTxUnicast++; - - /* Figure out ACK rate according to BSS basic rate - * and Tx rate. - * AckCTSLng = 14 use 1M bps send - */ - AckTime = ComputeTxTime(14, 10, 0, 0); - - if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */ - u16 RtsTime, CtsTime; - bRTSEnable = 1; - bCTSEnable = 0; - - /* Rate and time required for RTS. */ - RtsTime = ComputeTxTime(sAckCtsLng / 8, - priv->ieee80211->basic_rate, 0, 0); - - /* Rate and time required for CTS. - * AckCTSLng = 14 use 1M bps send - */ - CtsTime = ComputeTxTime(14, 10, 0, 0); - - /* Figure out time required to transmit this frame. */ - ThisFrameTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, - bUseShortPreamble); - - /* RTS-CTS-ThisFrame-ACK. */ - RtsDur = CtsTime + ThisFrameTime + - AckTime + 3 * aSifsTime; - - TxDescDuration = RtsTime + RtsDur; - } else { /* Normal case. */ - bCTSEnable = 0; - bRTSEnable = 0; - RtsDur = 0; - - ThisFrameTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, bUseShortPreamble); - TxDescDuration = ThisFrameTime + aSifsTime + AckTime; - } - - if (!(le16_to_cpu(frag_hdr->frame_control) & IEEE80211_FCTL_MOREFRAGS)) { - /* ThisFrame-ACK. */ - Duration = aSifsTime + AckTime; - } else { /* One or more fragments remained. */ - u16 NextFragTime; - - /* pretend following packet length = current packet */ - NextFragTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, bUseShortPreamble); - - /* ThisFrag-ACk-NextFrag-ACK. */ - Duration = NextFragTime + 3 * aSifsTime + 2 * AckTime; - } - - } /* End of Unicast packet */ - - frag_hdr->duration_id = Duration; - - buflen = priv->txbuffsize; - remain = len; - temp_tail = tail; - - while (remain != 0) { - mb(); - if (!buflist) { - DMESGE("TX buffer error, cannot TX frames. pri %d.", - priority); - return -1; - } - buf = buflist->buf; - - if ((*tail & (1 << 31)) && (priority != BEACON_PRIORITY)) { - DMESGW("No more TX desc, returning %x of %x", - remain, len); - priv->stats.txrdu++; - return remain; - } - - *tail = 0; /* zeroes header */ - *(tail+1) = 0; - *(tail+3) = 0; - *(tail+5) = 0; - *(tail+6) = 0; - *(tail+7) = 0; - - /* FIXME: should be triggered by HW encryption parameters.*/ - *tail |= (1<<15); /* no encrypt */ - - if (remain == len && !descfrag) { - ownbit_flag = false; - *tail = *tail | (1 << 29); /* first segment of packet */ - *tail = *tail | (len); - } else { - ownbit_flag = true; - } - - for (i = 0; i < buflen && remain > 0; i++, remain--) { - /* copy data into descriptor pointed DMAble buffer */ - ((u8 *)buf)[i] = txbuf[i]; - - if (remain == 4 && i+4 >= buflen) - break; - /* ensure the last desc has at least 4 bytes payload */ - } - txbuf = txbuf + i; - *(tail+3) = *(tail+3) & ~0xfff; - *(tail+3) = *(tail+3) | i; /* buffer length */ - - if (bCTSEnable) - *tail |= (1<<18); - - if (bRTSEnable) { /* rts enable */ - /* RTS RATE */ - *tail |= (ieeerate2rtlrate( - priv->ieee80211->basic_rate) << 19); - - *tail |= (1<<23); /* rts enable */ - *(tail+1) |= (RtsDur&0xffff); /* RTS Duration */ - } - *(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */ - - *(tail + 5) |= (11 << 8); /* retry lim; */ - - *tail = *tail | ((rate&0xf) << 24); - - if (morefrag) - *tail = (*tail) | (1<<17); /* more fragment */ - if (!remain) - *tail = (*tail) | (1<<28); /* last segment of frame */ - - *(tail+5) = *(tail+5)|(2<<27); - *(tail+7) = *(tail+7)|(1<<4); - - wmb(); - if (ownbit_flag) - /* descriptor ready to be txed */ - *tail |= (1 << 31); - - if ((tail - begin)/8 == count-1) - tail = begin; - else - tail = tail+8; - - buflist = buflist->next; - - mb(); - - switch (priority) { - case MANAGE_PRIORITY: - priv->txmapringtail = tail; - priv->txmapbufstail = buflist; - break; - case BK_PRIORITY: - priv->txbkpringtail = tail; - priv->txbkpbufstail = buflist; - break; - case BE_PRIORITY: - priv->txbepringtail = tail; - priv->txbepbufstail = buflist; - break; - case VI_PRIORITY: - priv->txvipringtail = tail; - priv->txvipbufstail = buflist; - break; - case VO_PRIORITY: - priv->txvopringtail = tail; - priv->txvopbufstail = buflist; - break; - case HI_PRIORITY: - priv->txhpringtail = tail; - priv->txhpbufstail = buflist; - break; - case BEACON_PRIORITY: - /* - * The HW seems to be happy with the 1st - * descriptor filled and the 2nd empty... - * So always update descriptor 1 and never - * touch 2nd - */ - break; - } - } - *temp_tail = *temp_tail | (1<<31); /* descriptor ready to be txed */ - rtl8180_dma_kick(dev, priority); - - return 0; -} - -void rtl8180_irq_rx_tasklet(struct r8180_priv *priv); - -static void rtl8180_link_change(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 beacon_interval; - struct ieee80211_network *net = &priv->ieee80211->current_network; - - rtl8180_update_msr(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - - write_nic_dword(dev, BSSID, ((u32 *)net->bssid)[0]); - write_nic_word(dev, BSSID+4, ((u16 *)net->bssid)[2]); - - beacon_interval = read_nic_word(dev, BEACON_INTERVAL); - beacon_interval &= ~BEACON_INTERVAL_MASK; - beacon_interval |= net->beacon_interval; - write_nic_word(dev, BEACON_INTERVAL, beacon_interval); - - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - rtl8180_set_chan(dev, priv->chan); -} - -static void rtl8180_rq_tx_ack(struct net_device *dev) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - - write_nic_byte(dev, CONFIG4, - read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT); - priv->ack_tx_to_ieee = 1; -} - -static short rtl8180_is_tx_queue_empty(struct net_device *dev) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - u32 *d; - - for (d = priv->txmapring; - d < priv->txmapring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txbkpring; - d < priv->txbkpring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txbepring; - d < priv->txbepring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txvipring; - d < priv->txvipring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txvopring; - d < priv->txvopring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txhpring; - d < priv->txhpring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - return 1; -} - -static void rtl8180_hw_wakeup(struct net_device *dev) -{ - unsigned long flags; - struct r8180_priv *priv = ieee80211_priv(dev); - - spin_lock_irqsave(&priv->ps_lock, flags); - write_nic_byte(dev, CONFIG4, - read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT); - if (priv->rf_wakeup) - priv->rf_wakeup(dev); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void rtl8180_hw_sleep_down(struct net_device *dev) -{ - unsigned long flags; - struct r8180_priv *priv = ieee80211_priv(dev); - - spin_lock_irqsave(&priv->ps_lock, flags); - if (priv->rf_sleep) - priv->rf_sleep(dev); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u32 rb = jiffies; - unsigned long flags; - - spin_lock_irqsave(&priv->ps_lock, flags); - - /* - * Writing HW register with 0 equals to disable - * the timer, that is not really what we want - */ - tl -= MSECS(4+16+7); - - /* - * If the interval in which we are requested to sleep is too - * short then give up and remain awake - */ - if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME)) - || ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) { - spin_unlock_irqrestore(&priv->ps_lock, flags); - netdev_warn(dev, "too short to sleep\n"); - return; - } - - { - u32 tmp = (tl > rb) ? (tl-rb) : (rb-tl); - - priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp); - /* as tl may be less than rb */ - queue_delayed_work(priv->ieee80211->wq, - &priv->ieee80211->hw_wakeup_wq, tmp); - } - /* - * If we suspect the TimerInt is gone beyond tl - * while setting it, then give up - */ - - if (((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME))) || - ((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) { - spin_unlock_irqrestore(&priv->ps_lock, flags); - return; - } - - queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void rtl8180_wmm_single_param_update(struct net_device *dev, - u8 mode, AC_CODING eACI, PAC_PARAM param) -{ - u8 u1bAIFS; - u32 u4bAcParam; - - /* Retrieve parameters to update. */ - /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */ - u1bAIFS = param->f.AciAifsn.f.AIFSN * ((mode & IEEE_G) == IEEE_G ? - 9 : 20) + aSifsTime; - u4bAcParam = (((u32)param->f.TXOPLimit << AC_PARAM_TXOP_LIMIT_OFFSET) | - ((u32)param->f.Ecw.f.ECWmax << AC_PARAM_ECW_MAX_OFFSET) | - ((u32)param->f.Ecw.f.ECWmin << AC_PARAM_ECW_MIN_OFFSET) | - ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); - - switch (eACI) { - case AC1_BK: - write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); - return; - case AC0_BE: - write_nic_dword(dev, AC_BE_PARAM, u4bAcParam); - return; - case AC2_VI: - write_nic_dword(dev, AC_VI_PARAM, u4bAcParam); - return; - case AC3_VO: - write_nic_dword(dev, AC_VO_PARAM, u4bAcParam); - return; - default: - pr_warn("SetHwReg8185(): invalid ACI: %d!\n", eACI); - return; - } -} - -static void rtl8180_wmm_param_update(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, - struct ieee80211_device, wmm_param_update_wq); - struct net_device *dev = ieee->dev; - u8 *ac_param = (u8 *)(ieee->current_network.wmm_param); - u8 mode = ieee->current_network.mode; - AC_CODING eACI; - AC_PARAM AcParam; - - if (!ieee->current_network.QoS_Enable) { - /* legacy ac_xx_param update */ - AcParam.longData = 0; - AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */ - AcParam.f.AciAifsn.f.ACM = 0; - AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */ - AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */ - AcParam.f.TXOPLimit = 0; - - for (eACI = 0; eACI < AC_MAX; eACI++) { - AcParam.f.AciAifsn.f.ACI = (u8)eACI; - - rtl8180_wmm_single_param_update(dev, mode, eACI, - (PAC_PARAM)&AcParam); - } - return; - } - - for (eACI = 0; eACI < AC_MAX; eACI++) { - rtl8180_wmm_single_param_update(dev, mode, - ((PAC_PARAM)ac_param)->f.AciAifsn.f.ACI, - (PAC_PARAM)ac_param); - - ac_param += sizeof(AC_PARAM); - } -} - -void rtl8180_restart_wq(struct work_struct *work); -void rtl8180_watch_dog_wq(struct work_struct *work); -void rtl8180_hw_wakeup_wq(struct work_struct *work); -void rtl8180_hw_sleep_wq(struct work_struct *work); -void rtl8180_sw_antenna_wq(struct work_struct *work); -void rtl8180_watch_dog(struct net_device *dev); - -static void watch_dog_adaptive(unsigned long data) -{ - struct r8180_priv *priv = ieee80211_priv((struct net_device *)data); - - if (!priv->up) { - DMESG("<----watch_dog_adaptive():driver is not up!\n"); - return; - } - - /* Tx High Power Mechanism. */ - if (CheckHighPower((struct net_device *)data)) - queue_work(priv->ieee80211->wq, - (void *)&priv->ieee80211->tx_pw_wq); - - /* Tx Power Tracking on 87SE. */ - if (CheckTxPwrTracking((struct net_device *)data)) - TxPwrTracking87SE((struct net_device *)data); - - /* Perform DIG immediately. */ - if (CheckDig((struct net_device *)data)) - queue_work(priv->ieee80211->wq, - (void *)&priv->ieee80211->hw_dig_wq); - - rtl8180_watch_dog((struct net_device *)data); - - queue_work(priv->ieee80211->wq, - (void *)&priv->ieee80211->GPIOChangeRFWorkItem); - - priv->watch_dog_timer.expires = jiffies + - MSECS(IEEE80211_WATCH_DOG_TIME); - - add_timer(&priv->watch_dog_timer); -} - -static struct rtl8187se_channel_list channel_plan_list[] = { - /* FCC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, - 44, 48, 52, 56, 60, 64}, 19}, - - /* IC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, - - /* ETSI */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* Spain. Change to ETSI. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* France. Change to ETSI. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* MKK */ - {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9}, - - /* MKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, - 40, 44, 48, 52, 56, 60, 64}, 22}, - - /* Israel. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* For 11a , TELEC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17}, - - /* For Global Domain. 1-11 active, 12-14 passive. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, - - /* world wide 13: ch1~ch11 active, ch12~13 passive */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13} -}; - -static void rtl8180_set_channel_map(u8 channel_plan, - struct ieee80211_device *ieee) -{ - int i; - - ieee->MinPassiveChnlNum = MAX_CHANNEL_NUMBER+1; - ieee->IbssStartChnl = 0; - - switch (channel_plan) { - case COUNTRY_CODE_FCC: - case COUNTRY_CODE_IC: - case COUNTRY_CODE_ETSI: - case COUNTRY_CODE_SPAIN: - case COUNTRY_CODE_FRANCE: - case COUNTRY_CODE_MKK: - case COUNTRY_CODE_MKK1: - case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_TELEC: - { - Dot11d_Init(ieee); - ieee->bGlobalDomain = false; - if (channel_plan_list[channel_plan].len != 0) { - /* Clear old channel map */ - memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); - /* Set new channel map */ - for (i = 0; i < channel_plan_list[channel_plan].len; i++) { - if (channel_plan_list[channel_plan].channel[i] <= 14) - GET_DOT11D_INFO(ieee)->channel_map[channel_plan_list[channel_plan].channel[i]] = 1; - } - } - break; - } - case COUNTRY_CODE_GLOBAL_DOMAIN: - { - GET_DOT11D_INFO(ieee)->bEnabled = false; - Dot11d_Reset(ieee); - ieee->bGlobalDomain = true; - break; - } - case COUNTRY_CODE_WORLD_WIDE_13_INDEX: - { - ieee->MinPassiveChnlNum = 12; - ieee->IbssStartChnl = 10; - break; - } - default: - { - Dot11d_Init(ieee); - ieee->bGlobalDomain = false; - memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); - for (i = 1; i <= 14; i++) - GET_DOT11D_INFO(ieee)->channel_map[i] = 1; - break; - } - } -} - -void GPIOChangeRFWorkItemCallBack(struct work_struct *work); - -static void rtl8180_statistics_init(struct stats *pstats) -{ - memset(pstats, 0, sizeof(struct stats)); -} - -static void rtl8180_link_detect_init(struct link_detect_t *plink_detect) -{ - memset(plink_detect, 0, sizeof(struct link_detect_t)); - plink_detect->slot_num = DEFAULT_SLOT_NUM; -} - -static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct net_device *dev = eeprom->data; - u8 reg = read_nic_byte(dev, EPROM_CMD); - - eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; - eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; - eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; - eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; -} - -static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct net_device *dev = eeprom->data; - u8 reg = 2 << 6; - - if (eeprom->reg_data_in) - reg |= RTL818X_EEPROM_CMD_WRITE; - if (eeprom->reg_data_out) - reg |= RTL818X_EEPROM_CMD_READ; - if (eeprom->reg_data_clock) - reg |= RTL818X_EEPROM_CMD_CK; - if (eeprom->reg_chip_select) - reg |= RTL818X_EEPROM_CMD_CS; - - write_nic_byte(dev, EPROM_CMD, reg); - read_nic_byte(dev, EPROM_CMD); - udelay(10); -} - -static short rtl8180_init(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 word; - u16 usValue; - u16 tmpu16; - int i, j; - struct eeprom_93cx6 eeprom; - u16 eeprom_val; - - eeprom.data = dev; - eeprom.register_read = rtl8187se_eeprom_register_read; - eeprom.register_write = rtl8187se_eeprom_register_write; - eeprom.width = PCI_EEPROM_WIDTH_93C46; - - eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val); - priv->channel_plan = eeprom_val & 0xFF; - if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) { - netdev_err(dev, "rtl8180_init: Invalid channel plan! Set to default.\n"); - priv->channel_plan = 0; - } - - DMESG("Channel plan is %d\n", priv->channel_plan); - rtl8180_set_channel_map(priv->channel_plan, priv->ieee80211); - - /* FIXME: these constants are placed in a bad pleace. */ - priv->txbuffsize = 2048; /* 1024; */ - priv->txringcount = 32; /* 32; */ - priv->rxbuffersize = 2048; /* 1024; */ - priv->rxringcount = 64; /* 32; */ - priv->txbeaconcount = 2; - priv->rx_skb_complete = 1; - - priv->RFChangeInProgress = false; - priv->SetRFPowerStateInProgress = false; - priv->RFProgType = 0; - - priv->irq_enabled = 0; - - rtl8180_statistics_init(&priv->stats); - rtl8180_link_detect_init(&priv->link_detect); - - priv->ack_tx_to_ieee = 0; - priv->ieee80211->current_network.beacon_interval = - DEFAULT_BEACONINTERVAL; - priv->ieee80211->iw_mode = IW_MODE_INFRA; - priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN | - IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | - IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE; - priv->ieee80211->active_scan = 1; - priv->ieee80211->rate = 110; /* 11 mbps */ - priv->ieee80211->modulation = IEEE80211_CCK_MODULATION; - priv->ieee80211->host_encrypt = 1; - priv->ieee80211->host_decrypt = 1; - priv->ieee80211->sta_wake_up = rtl8180_hw_wakeup; - priv->ieee80211->ps_request_tx_ack = rtl8180_rq_tx_ack; - priv->ieee80211->enter_sleep_state = rtl8180_hw_sleep; - priv->ieee80211->ps_is_queue_empty = rtl8180_is_tx_queue_empty; - - priv->hw_wep = hwwep; - priv->dev = dev; - priv->retry_rts = DEFAULT_RETRY_RTS; - priv->retry_data = DEFAULT_RETRY_DATA; - priv->RFChangeInProgress = false; - priv->SetRFPowerStateInProgress = false; - priv->RFProgType = 0; - priv->bInactivePs = true; /* false; */ - priv->ieee80211->bInactivePs = priv->bInactivePs; - priv->bSwRfProcessing = false; - priv->eRFPowerState = RF_OFF; - priv->RfOffReason = 0; - priv->led_strategy = SW_LED_MODE0; - priv->TxPollingTimes = 0; - priv->bLeisurePs = true; - priv->dot11PowerSaveMode = ACTIVE; - priv->AdMinCheckPeriod = 5; - priv->AdMaxCheckPeriod = 10; - priv->AdMaxRxSsThreshold = 30; /* 60->30 */ - priv->AdRxSsThreshold = 20; /* 50->20 */ - priv->AdCheckPeriod = priv->AdMinCheckPeriod; - priv->AdTickCount = 0; - priv->AdRxSignalStrength = -1; - priv->RegSwAntennaDiversityMechanism = 0; - priv->RegDefaultAntenna = 0; - priv->SignalStrength = 0; - priv->AdRxOkCnt = 0; - priv->CurrAntennaIndex = 0; - priv->AdRxSsBeforeSwitched = 0; - init_timer(&priv->SwAntennaDiversityTimer); - priv->SwAntennaDiversityTimer.data = (unsigned long)dev; - priv->SwAntennaDiversityTimer.function = - (void *)SwAntennaDiversityTimerCallback; - priv->bDigMechanism = true; - priv->InitialGain = 6; - priv->bXtalCalibration = false; - priv->XtalCal_Xin = 0; - priv->XtalCal_Xout = 0; - priv->bTxPowerTrack = false; - priv->ThermalMeter = 0; - priv->FalseAlarmRegValue = 0; - priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm, - which is used in DIG. */ - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote = 0; - priv->LastSignalStrengthInPercent = 0; - priv->Stats_SignalStrength = 0; - priv->LastRxPktAntenna = 0; - priv->SignalQuality = 0; /* in 0-100 index. */ - priv->Stats_SignalQuality = 0; - priv->RecvSignalPower = 0; /* in dBm. */ - priv->Stats_RecvSignalPower = 0; - priv->AdMainAntennaRxOkCnt = 0; - priv->AdAuxAntennaRxOkCnt = 0; - priv->bHWAdSwitched = false; - priv->bRegHighPowerMechanism = true; - priv->RegHiPwrUpperTh = 77; - priv->RegHiPwrLowerTh = 75; - priv->RegRSSIHiPwrUpperTh = 70; - priv->RegRSSIHiPwrLowerTh = 20; - priv->bCurCCKPkt = false; - priv->UndecoratedSmoothedSS = -1; - priv->bToUpdateTxPwr = false; - priv->CurCCKRSSI = 0; - priv->RxPower = 0; - priv->RSSI = 0; - priv->NumTxOkTotal = 0; - priv->NumTxUnicast = 0; - priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL; - priv->CurrRetryCnt = 0; - priv->LastRetryCnt = 0; - priv->LastTxokCnt = 0; - priv->LastRxokCnt = 0; - priv->LastRetryRate = 0; - priv->bTryuping = 0; - priv->CurrTxRate = 0; - priv->CurrRetryRate = 0; - priv->TryupingCount = 0; - priv->TryupingCountNoData = 0; - priv->TryDownCountLowData = 0; - priv->LastTxOKBytes = 0; - priv->LastFailTxRate = 0; - priv->LastFailTxRateSS = 0; - priv->FailTxRateCount = 0; - priv->LastTxThroughput = 0; - priv->NumTxOkBytesTotal = 0; - priv->ForcedDataRate = 0; - priv->RegBModeGainStage = 1; - - priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0; - spin_lock_init(&priv->irq_th_lock); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->ps_lock); - spin_lock_init(&priv->rf_ps_lock); - sema_init(&priv->wx_sem, 1); - INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq); - INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq, - (void *)rtl8180_hw_wakeup_wq); - INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq, - (void *)rtl8180_hw_sleep_wq); - INIT_WORK(&priv->ieee80211->wmm_param_update_wq, - (void *)rtl8180_wmm_param_update); - INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq, - (void *)rtl8180_rate_adapter); - INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq, - (void *)rtl8180_hw_dig_wq); - INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq, - (void *)rtl8180_tx_pw_wq); - INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem, - (void *) GPIOChangeRFWorkItemCallBack); - tasklet_init(&priv->irq_rx_tasklet, - (void(*)(unsigned long)) rtl8180_irq_rx_tasklet, - (unsigned long)priv); - - init_timer(&priv->watch_dog_timer); - priv->watch_dog_timer.data = (unsigned long)dev; - priv->watch_dog_timer.function = watch_dog_adaptive; - - init_timer(&priv->rateadapter_timer); - priv->rateadapter_timer.data = (unsigned long)dev; - priv->rateadapter_timer.function = timer_rate_adaptive; - priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD; - priv->bEnhanceTxPwr = false; - - priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit; - priv->ieee80211->set_chan = rtl8180_set_chan; - priv->ieee80211->link_change = rtl8180_link_change; - priv->ieee80211->softmac_data_hard_start_xmit = rtl8180_hard_data_xmit; - priv->ieee80211->data_hard_stop = rtl8180_data_hard_stop; - priv->ieee80211->data_hard_resume = rtl8180_data_hard_resume; - - priv->ieee80211->init_wmmparam_flag = 0; - - priv->ieee80211->start_send_beacons = rtl8180_start_tx_beacon; - priv->ieee80211->stop_send_beacons = rtl8180_beacon_tx_disable; - priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; - - priv->ShortRetryLimit = 7; - priv->LongRetryLimit = 7; - priv->EarlyRxThreshold = 7; - - priv->TransmitConfig = (1<<TCR_DurProcMode_OFFSET) | - (7<<TCR_MXDMA_OFFSET) | - (priv->ShortRetryLimit<<TCR_SRL_OFFSET) | - (priv->LongRetryLimit<<TCR_LRL_OFFSET); - - priv->ReceiveConfig = RCR_AMF | RCR_ADF | RCR_ACF | - RCR_AB | RCR_AM | RCR_APM | - (7<<RCR_MXDMA_OFFSET) | - (priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) | - (priv->EarlyRxThreshold == 7 ? - RCR_ONLYERLPKT : 0); - - priv->IntrMask = IMR_TMGDOK | IMR_TBDER | - IMR_THPDER | IMR_THPDOK | - IMR_TVODER | IMR_TVODOK | - IMR_TVIDER | IMR_TVIDOK | - IMR_TBEDER | IMR_TBEDOK | - IMR_TBKDER | IMR_TBKDOK | - IMR_RDU | - IMR_RER | IMR_ROK | - IMR_RQoSOK; - - priv->InitialGain = 6; - - DMESG("MAC controller is a RTL8187SE b/g"); - - priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION; - priv->ieee80211->short_slot = 1; - - eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &usValue); - DMESG("usValue is %#hx\n", usValue); - /* 3Read AntennaDiversity */ - - /* SW Antenna Diversity. */ - priv->EEPROMSwAntennaDiversity = (usValue & EEPROM_SW_AD_MASK) == - EEPROM_SW_AD_ENABLE; - - /* Default Antenna to use. */ - priv->EEPROMDefaultAntenna1 = (usValue & EEPROM_DEF_ANT_MASK) == - EEPROM_DEF_ANT_1; - - if (priv->RegSwAntennaDiversityMechanism == 0) /* Auto */ - /* 0: default from EEPROM. */ - priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity; - else - /* 1:disable antenna diversity, 2: enable antenna diversity. */ - priv->bSwAntennaDiverity = - priv->RegSwAntennaDiversityMechanism == 2; - - if (priv->RegDefaultAntenna == 0) - /* 0: default from EEPROM. */ - priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1; - else - /* 1: main, 2: aux. */ - priv->bDefaultAntenna1 = priv->RegDefaultAntenna == 2; - - priv->plcp_preamble_mode = 2; - /* the eeprom type is stored in RCR register bit #6 */ - if (RCR_9356SEL & read_nic_dword(dev, RCR)) - priv->epromtype = EPROM_93c56; - else - priv->epromtype = EPROM_93c46; - - eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *) - dev->dev_addr, 3); - - for (i = 1, j = 0; i < 14; i += 2, j++) { - eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word); - priv->chtxpwr[i] = word & 0xff; - priv->chtxpwr[i+1] = (word & 0xff00)>>8; - } - for (i = 1, j = 0; i < 14; i += 2, j++) { - eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word); - priv->chtxpwr_ofdm[i] = word & 0xff; - priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8; - } - - /* 3Read crystal calibration and thermal meter indication on 87SE. */ - eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16); - - /* Crystal calibration for Xin and Xout resp. */ - priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK; - priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4; - if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12) - priv->bXtalCalibration = true; - - /* Thermal meter reference indication. */ - priv->ThermalMeter = (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8); - if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13) - priv->bTxPowerTrack = true; - - priv->rf_sleep = rtl8225z4_rf_sleep; - priv->rf_wakeup = rtl8225z4_rf_wakeup; - DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!"); - - priv->rf_close = rtl8225z2_rf_close; - priv->rf_init = rtl8225z2_rf_init; - priv->rf_set_chan = rtl8225z2_rf_set_chan; - priv->rf_set_sens = NULL; - - if (0 != alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_MANAGEPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_BKPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_BEPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_VIPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_VOPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_HIGHPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txbeaconcount, - TX_BEACON_RING_ADDR)) - return -ENOMEM; - - if (request_irq(dev->irq, rtl8180_interrupt, - IRQF_SHARED, dev->name, dev)) { - DMESGE("Error allocating IRQ %d", dev->irq); - return -1; - } else { - priv->irq = dev->irq; - DMESG("IRQ %d", dev->irq); - } - - return 0; -} - -void rtl8180_no_hw_wep(struct net_device *dev) -{ -} - -void rtl8180_set_hw_wep(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 pgreg; - u8 security; - u32 key0_word4; - - pgreg = read_nic_byte(dev, PGSELECT); - write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT)); - - key0_word4 = read_nic_dword(dev, KEY0+4+4+4); - key0_word4 &= ~0xff; - key0_word4 |= priv->key0[3] & 0xff; - write_nic_dword(dev, KEY0, (priv->key0[0])); - write_nic_dword(dev, KEY0+4, (priv->key0[1])); - write_nic_dword(dev, KEY0+4+4, (priv->key0[2])); - write_nic_dword(dev, KEY0+4+4+4, (key0_word4)); - - security = read_nic_byte(dev, SECURITY); - security |= (1<<SECURITY_WEP_TX_ENABLE_SHIFT); - security |= (1<<SECURITY_WEP_RX_ENABLE_SHIFT); - security &= ~SECURITY_ENCRYP_MASK; - security |= (SECURITY_ENCRYP_104<<SECURITY_ENCRYP_SHIFT); - - write_nic_byte(dev, SECURITY, security); - - DMESG("key %x %x %x %x", read_nic_dword(dev, KEY0+4+4+4), - read_nic_dword(dev, KEY0+4+4), read_nic_dword(dev, KEY0+4), - read_nic_dword(dev, KEY0)); -} - - -void rtl8185_rf_pins_enable(struct net_device *dev) -{ - write_nic_word(dev, RFPinsEnable, 0x1fff); /* | tmp); */ -} - -void rtl8185_set_anaparam2(struct net_device *dev, u32 a) -{ - u8 conf3; - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - - conf3 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT)); - write_nic_dword(dev, ANAPARAM2, a); - - conf3 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT)); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -void rtl8180_set_anaparam(struct net_device *dev, u32 a) -{ - u8 conf3; - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - - conf3 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT)); - write_nic_dword(dev, ANAPARAM, a); - - conf3 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT)); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -void rtl8185_tx_antenna(struct net_device *dev, u8 ant) -{ - write_nic_byte(dev, TX_ANTENNA, ant); - force_pci_posting(dev); - mdelay(1); -} - -static void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data) -{ - u32 phyw; - - adr |= 0x80; - - phyw = ((data<<8) | adr); - - /* Note: we must write 0xff7c after 0x7d-0x7f to write BB register. */ - write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24)); - write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16)); - write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8)); - write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff))); -} - -inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data) -{ - data = data & 0xff; - rtl8185_write_phy(dev, adr, data); -} - -void write_phy_cck(struct net_device *dev, u8 adr, u32 data) -{ - data = data & 0xff; - rtl8185_write_phy(dev, adr, data | 0x10000); -} - -/* - * This configures registers for beacon tx and enables it via - * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might - * be used to stop beacon transmission - */ -void rtl8180_start_tx_beacon(struct net_device *dev) -{ - u16 word; - - DMESG("Enabling beacon TX"); - rtl8180_prepare_beacon(dev); - rtl8180_irq_disable(dev); - rtl8180_beacon_tx_enable(dev); - - word = read_nic_word(dev, AtimWnd) & ~AtimWnd_AtimWnd; - write_nic_word(dev, AtimWnd, word); /* word |= */ - - word = read_nic_word(dev, BintrItv); - word &= ~BintrItv_BintrItv; - word |= 1000; /* priv->ieee80211->current_network.beacon_interval * - * ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1); - * FIXME: check if correct ^^ worked with 0x3e8; - */ - write_nic_word(dev, BintrItv, word); - - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - rtl8185b_irq_enable(dev); -} - -static struct net_device_stats *rtl8180_stats(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return &priv->ieee80211->stats; -} - -/* - * Change current and default preamble mode. - */ -static bool MgntActSet_802_11_PowerSaveMode(struct r8180_priv *priv, - enum rt_ps_mode rtPsMode) -{ - /* Currently, we do not change power save mode on IBSS mode. */ - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - return false; - - priv->ieee80211->ps = rtPsMode; - - return true; -} - -static void LeisurePSEnter(struct r8180_priv *priv) -{ - if (priv->bLeisurePs) - if (priv->ieee80211->ps == IEEE80211_PS_DISABLED) - /* IEEE80211_PS_ENABLE */ - MgntActSet_802_11_PowerSaveMode(priv, - IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST); -} - -static void LeisurePSLeave(struct r8180_priv *priv) -{ - if (priv->bLeisurePs) - if (priv->ieee80211->ps != IEEE80211_PS_DISABLED) - MgntActSet_802_11_PowerSaveMode( - priv, IEEE80211_PS_DISABLED); -} - -void rtl8180_hw_wakeup_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of( - dwork, struct ieee80211_device, hw_wakeup_wq); - struct net_device *dev = ieee->dev; - - rtl8180_hw_wakeup(dev); -} - -void rtl8180_hw_sleep_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of( - dwork, struct ieee80211_device, hw_sleep_wq); - struct net_device *dev = ieee->dev; - - rtl8180_hw_sleep_down(dev); -} - -static void MgntLinkKeepAlive(struct r8180_priv *priv) -{ - if (priv->keepAliveLevel == 0) - return; - - if (priv->ieee80211->state == IEEE80211_LINKED) { - /* - * Keep-Alive. - */ - - if ((priv->keepAliveLevel == 2) || - (priv->link_detect.last_num_tx_unicast == - priv->NumTxUnicast && - priv->link_detect.last_num_rx_unicast == - priv->ieee80211->NumRxUnicast) - ) { - priv->link_detect.idle_count++; - - /* - * Send a Keep-Alive packet packet to AP if we had - * been idle for a while. - */ - if (priv->link_detect.idle_count >= - KEEP_ALIVE_INTERVAL / - CHECK_FOR_HANG_PERIOD - 1) { - priv->link_detect.idle_count = 0; - ieee80211_sta_ps_send_null_frame( - priv->ieee80211, false); - } - } else { - priv->link_detect.idle_count = 0; - } - priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast; - priv->link_detect.last_num_rx_unicast = - priv->ieee80211->NumRxUnicast; - } -} - -void rtl8180_watch_dog(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - bool bEnterPS = false; - bool bBusyTraffic = false; - u32 TotalRxNum = 0; - u16 SlotIndex = 0; - u16 i = 0; - if (priv->ieee80211->actscanning == false) { - if ((priv->ieee80211->iw_mode != IW_MODE_ADHOC) && - (priv->ieee80211->state == IEEE80211_NOLINK) && - (priv->ieee80211->beinretry == false) && - (priv->eRFPowerState == RF_ON)) - IPSEnter(dev); - } - if ((priv->ieee80211->state == IEEE80211_LINKED) && - (priv->ieee80211->iw_mode == IW_MODE_INFRA)) { - SlotIndex = (priv->link_detect.slot_index++) % - priv->link_detect.slot_num; - - priv->link_detect.rx_frame_num[SlotIndex] = - priv->ieee80211->NumRxDataInPeriod + - priv->ieee80211->NumRxBcnInPeriod; - - for (i = 0; i < priv->link_detect.slot_num; i++) - TotalRxNum += priv->link_detect.rx_frame_num[i]; - - if (TotalRxNum == 0) { - priv->ieee80211->state = IEEE80211_ASSOCIATING; - queue_work(priv->ieee80211->wq, - &priv->ieee80211->associate_procedure_wq); - } - } - - MgntLinkKeepAlive(priv); - - LeisurePSLeave(priv); - - if (priv->ieee80211->state == IEEE80211_LINKED) { - priv->link_detect.num_rx_ok_in_period = - priv->ieee80211->NumRxDataInPeriod; - if (priv->link_detect.num_rx_ok_in_period > 666 || - priv->link_detect.num_tx_ok_in_period > 666) { - bBusyTraffic = true; - } - if ((priv->link_detect.num_rx_ok_in_period + - priv->link_detect.num_tx_ok_in_period > 8) - || (priv->link_detect.num_rx_ok_in_period > 2)) { - bEnterPS = false; - } else - bEnterPS = true; - - if (bEnterPS) - LeisurePSEnter(priv); - else - LeisurePSLeave(priv); - } else - LeisurePSLeave(priv); - priv->link_detect.b_busy_traffic = bBusyTraffic; - priv->link_detect.num_rx_ok_in_period = 0; - priv->link_detect.num_tx_ok_in_period = 0; - priv->ieee80211->NumRxDataInPeriod = 0; - priv->ieee80211->NumRxBcnInPeriod = 0; -} - -static int _rtl8180_up(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - priv->up = 1; - - DMESG("Bringing up iface"); - rtl8185b_adapter_start(dev); - rtl8185b_rx_enable(dev); - rtl8185b_tx_enable(dev); - if (priv->bInactivePs) { - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - IPSLeave(dev); - } - timer_rate_adaptive((unsigned long)dev); - watch_dog_adaptive((unsigned long)dev); - if (priv->bSwAntennaDiverity) - SwAntennaDiversityTimerCallback(dev); - ieee80211_softmac_start_protocol(priv->ieee80211); - return 0; -} - -static int rtl8180_open(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - down(&priv->wx_sem); - ret = rtl8180_up(dev); - up(&priv->wx_sem); - return ret; -} - -int rtl8180_up(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->up == 1) - return -1; - - return _rtl8180_up(dev); -} - -static int rtl8180_close(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - down(&priv->wx_sem); - ret = rtl8180_down(dev); - up(&priv->wx_sem); - - return ret; -} - -int rtl8180_down(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->up == 0) - return -1; - - priv->up = 0; - - ieee80211_softmac_stop_protocol(priv->ieee80211); - /* FIXME */ - if (!netif_queue_stopped(dev)) - netif_stop_queue(dev); - rtl8180_rtx_disable(dev); - rtl8180_irq_disable(dev); - del_timer_sync(&priv->watch_dog_timer); - del_timer_sync(&priv->rateadapter_timer); - cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); - cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq); - cancel_delayed_work(&priv->ieee80211->hw_sleep_wq); - cancel_delayed_work(&priv->ieee80211->hw_dig_wq); - cancel_delayed_work(&priv->ieee80211->tx_pw_wq); - del_timer_sync(&priv->SwAntennaDiversityTimer); - SetZebraRFPowerState8185(dev, RF_OFF); - memset(&priv->ieee80211->current_network, - 0, sizeof(struct ieee80211_network)); - priv->ieee80211->state = IEEE80211_NOLINK; - return 0; -} - -void rtl8180_restart_wq(struct work_struct *work) -{ - struct r8180_priv *priv = container_of( - work, struct r8180_priv, reset_wq); - struct net_device *dev = priv->dev; - - down(&priv->wx_sem); - - rtl8180_commit(dev); - - up(&priv->wx_sem); -} - -static void rtl8180_restart(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - schedule_work(&priv->reset_wq); -} - -void rtl8180_commit(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->up == 0) - return; - - del_timer_sync(&priv->watch_dog_timer); - del_timer_sync(&priv->rateadapter_timer); - cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); - cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq); - cancel_delayed_work(&priv->ieee80211->hw_sleep_wq); - cancel_delayed_work(&priv->ieee80211->hw_dig_wq); - cancel_delayed_work(&priv->ieee80211->tx_pw_wq); - del_timer_sync(&priv->SwAntennaDiversityTimer); - ieee80211_softmac_stop_protocol(priv->ieee80211); - rtl8180_irq_disable(dev); - rtl8180_rtx_disable(dev); - _rtl8180_up(dev); -} - -static void r8180_set_multicast(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - short promisc; - - promisc = (dev->flags & IFF_PROMISC) ? 1 : 0; - - if (promisc != priv->promisc) - rtl8180_restart(dev); - - priv->promisc = promisc; -} - -static int r8180_set_mac_adr(struct net_device *dev, void *mac) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct sockaddr *addr = mac; - - down(&priv->wx_sem); - - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - - if (priv->ieee80211->iw_mode == IW_MODE_MASTER) - memcpy(priv->ieee80211->current_network.bssid, - dev->dev_addr, ETH_ALEN); - - if (priv->up) { - rtl8180_down(dev); - rtl8180_up(dev); - } - - up(&priv->wx_sem); - - return 0; -} - -/* based on ipw2200 driver */ -static int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct iwreq *wrq = (struct iwreq *) rq; - int ret = -1; - - switch (cmd) { - case RTL_IOCTL_WPA_SUPPLICANT: - ret = ieee80211_wpa_supplicant_ioctl( - priv->ieee80211, &wrq->u.data); - return ret; - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} - -static const struct net_device_ops rtl8180_netdev_ops = { - .ndo_open = rtl8180_open, - .ndo_stop = rtl8180_close, - .ndo_get_stats = rtl8180_stats, - .ndo_tx_timeout = rtl8180_restart, - .ndo_do_ioctl = rtl8180_ioctl, - .ndo_set_rx_mode = r8180_set_multicast, - .ndo_set_mac_address = r8180_set_mac_adr, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_start_xmit = ieee80211_rtl_xmit, -}; - -static int rtl8180_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long ioaddr = 0; - struct net_device *dev = NULL; - struct r8180_priv *priv = NULL; - u8 unit = 0; - int ret = -ENODEV; - - unsigned long pmem_start, pmem_len, pmem_flags; - - DMESG("Configuring chip resources"); - - if (pci_enable_device(pdev)) { - DMESG("Failed to enable PCI device"); - return -EIO; - } - - pci_set_master(pdev); - pci_set_dma_mask(pdev, 0xffffff00ULL); - pci_set_consistent_dma_mask(pdev, 0xffffff00ULL); - dev = alloc_ieee80211(sizeof(struct r8180_priv)); - if (!dev) { - ret = -ENOMEM; - goto fail_free; - } - priv = ieee80211_priv(dev); - priv->ieee80211 = netdev_priv(dev); - - pci_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - priv = ieee80211_priv(dev); - priv->pdev = pdev; - - pmem_start = pci_resource_start(pdev, 1); - pmem_len = pci_resource_len(pdev, 1); - pmem_flags = pci_resource_flags(pdev, 1); - - if (!(pmem_flags & IORESOURCE_MEM)) { - DMESG("region #1 not a MMIO resource, aborting"); - goto fail; - } - - if (!request_mem_region(pmem_start, pmem_len, RTL8180_MODULE_NAME)) { - DMESG("request_mem_region failed!"); - goto fail; - } - - ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len); - if (ioaddr == (unsigned long)NULL) { - DMESG("ioremap failed!"); - goto fail1; - } - - dev->mem_start = ioaddr; /* shared mem start */ - dev->mem_end = ioaddr + pci_resource_len(pdev, 0); /* shared mem end */ - - pci_read_config_byte(pdev, 0x05, &unit); - pci_write_config_byte(pdev, 0x05, unit & (~0x04)); - - dev->irq = pdev->irq; - priv->irq = 0; - - dev->netdev_ops = &rtl8180_netdev_ops; - dev->wireless_handlers = &r8180_wx_handlers_def; - - dev->type = ARPHRD_ETHER; - dev->watchdog_timeo = HZ*3; - - if (dev_alloc_name(dev, ifname) < 0) { - DMESG("Oops: devname already taken! Trying wlan%%d...\n"); - strcpy(ifname, "wlan%d"); - dev_alloc_name(dev, ifname); - } - - if (rtl8180_init(dev) != 0) { - DMESG("Initialization failed"); - goto fail1; - } - - netif_carrier_off(dev); - - if (register_netdev(dev)) - goto fail1; - - rtl8180_proc_init_one(dev); - - DMESG("Driver probe completed\n"); - return 0; -fail1: - if (dev->mem_start != (unsigned long)NULL) { - iounmap((void __iomem *)dev->mem_start); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - } -fail: - if (dev) { - if (priv->irq) { - free_irq(dev->irq, dev); - dev->irq = 0; - } - free_ieee80211(dev); - } - -fail_free: - pci_disable_device(pdev); - - DMESG("wlan driver load failed\n"); - return ret; -} - -static void rtl8180_pci_remove(struct pci_dev *pdev) -{ - struct r8180_priv *priv; - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - unregister_netdev(dev); - - priv = ieee80211_priv(dev); - - rtl8180_proc_remove_one(dev); - rtl8180_down(dev); - priv->rf_close(dev); - rtl8180_reset(dev); - mdelay(10); - - if (priv->irq) { - DMESG("Freeing irq %d", dev->irq); - free_irq(dev->irq, dev); - priv->irq = 0; - } - - free_rx_desc_ring(dev); - free_tx_desc_rings(dev); - - if (dev->mem_start != (unsigned long)NULL) { - iounmap((void __iomem *)dev->mem_start); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - } - - free_ieee80211(dev); - } - pci_disable_device(pdev); - - DMESG("wlan driver removed\n"); -} - -static int __init rtl8180_pci_module_init(void) -{ - int ret; - - ret = ieee80211_crypto_init(); - if (ret) { - pr_err("ieee80211_crypto_init() failed %d\n", ret); - return ret; - } - ret = ieee80211_crypto_tkip_init(); - if (ret) { - pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret); - return ret; - } - ret = ieee80211_crypto_ccmp_init(); - if (ret) { - pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret); - return ret; - } - ret = ieee80211_crypto_wep_init(); - if (ret) { - pr_err("ieee80211_crypto_wep_init() failed %d\n", ret); - return ret; - } - - pr_info("\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n"); - pr_info("Copyright (c) 2004-2005, Andrea Merello\n"); - DMESG("Initializing module"); - DMESG("Wireless extensions version %d", WIRELESS_EXT); - rtl8180_proc_module_init(); - - if (pci_register_driver(&rtl8180_pci_driver)) { - DMESG("No device found"); - return -ENODEV; - } - return 0; -} - -static void __exit rtl8180_pci_module_exit(void) -{ - pci_unregister_driver(&rtl8180_pci_driver); - rtl8180_proc_module_remove(); - ieee80211_crypto_tkip_exit(); - ieee80211_crypto_ccmp_exit(); - ieee80211_crypto_wep_exit(); - ieee80211_crypto_deinit(); - DMESG("Exiting"); -} - -static void rtl8180_try_wake_queue(struct net_device *dev, int pri) -{ - unsigned long flags; - short enough_desc; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - spin_lock_irqsave(&priv->tx_lock, flags); - enough_desc = check_nic_enought_desc(dev, pri); - spin_unlock_irqrestore(&priv->tx_lock, flags); - - if (enough_desc) - ieee80211_rtl_wake_queue(priv->ieee80211); -} - -static void rtl8180_tx_isr(struct net_device *dev, int pri, short error) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 *tail; /* tail virtual addr */ - u32 *head; /* head virtual addr */ - u32 *begin; /* start of ring virtual addr */ - u32 *nicv; /* nic pointer virtual addr */ - u32 nic; /* nic pointer physical addr */ - u32 nicbegin; /* start of ring physical addr */ - unsigned long flag; - /* physical addr are ok on 32 bits since we set DMA mask */ - int offs; - int j, i; - int hd; - if (error) - priv->stats.txretry++; - spin_lock_irqsave(&priv->tx_lock, flag); - switch (pri) { - case MANAGE_PRIORITY: - tail = priv->txmapringtail; - begin = priv->txmapring; - head = priv->txmapringhead; - nic = read_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR); - nicbegin = priv->txmapringdma; - break; - case BK_PRIORITY: - tail = priv->txbkpringtail; - begin = priv->txbkpring; - head = priv->txbkpringhead; - nic = read_nic_dword(dev, TX_BKPRIORITY_RING_ADDR); - nicbegin = priv->txbkpringdma; - break; - case BE_PRIORITY: - tail = priv->txbepringtail; - begin = priv->txbepring; - head = priv->txbepringhead; - nic = read_nic_dword(dev, TX_BEPRIORITY_RING_ADDR); - nicbegin = priv->txbepringdma; - break; - case VI_PRIORITY: - tail = priv->txvipringtail; - begin = priv->txvipring; - head = priv->txvipringhead; - nic = read_nic_dword(dev, TX_VIPRIORITY_RING_ADDR); - nicbegin = priv->txvipringdma; - break; - case VO_PRIORITY: - tail = priv->txvopringtail; - begin = priv->txvopring; - head = priv->txvopringhead; - nic = read_nic_dword(dev, TX_VOPRIORITY_RING_ADDR); - nicbegin = priv->txvopringdma; - break; - case HI_PRIORITY: - tail = priv->txhpringtail; - begin = priv->txhpring; - head = priv->txhpringhead; - nic = read_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR); - nicbegin = priv->txhpringdma; - break; - - default: - spin_unlock_irqrestore(&priv->tx_lock, flag); - return; - } - - nicv = (u32 *)((nic - nicbegin) + (u8 *)begin); - if ((head <= tail && (nicv > tail || nicv < head)) || - (head > tail && (nicv > tail && nicv < head))) { - DMESGW("nic has lost pointer"); - spin_unlock_irqrestore(&priv->tx_lock, flag); - rtl8180_restart(dev); - return; - } - - /* - * We check all the descriptors between the head and the nic, - * but not the currently pointed by the nic (the next to be txed) - * and the previous of the pointed (might be in process ??) - */ - offs = (nic - nicbegin); - offs = offs / 8 / 4; - hd = (head - begin) / 8; - - if (offs >= hd) - j = offs - hd; - else - j = offs + (priv->txringcount-1-hd); - - j -= 2; - if (j < 0) - j = 0; - - for (i = 0; i < j; i++) { - if ((*head) & (1<<31)) - break; - if (((*head)&(0x10000000)) != 0) { - priv->CurrRetryCnt += (u16)((*head) & (0x000000ff)); - if (!error) - priv->NumTxOkTotal++; - } - - if (!error) - priv->NumTxOkBytesTotal += (*(head+3)) & (0x00000fff); - - *head = *head & ~(1<<31); - - if ((head - begin)/8 == priv->txringcount-1) - head = begin; - else - head += 8; - } - - /* - * The head has been moved to the last certainly TXed - * (or at least processed by the nic) packet. - * The driver take forcefully owning of all these packets - * If the packet previous of the nic pointer has been - * processed this doesn't matter: it will be checked - * here at the next round. Anyway if no more packet are - * TXed no memory leak occur at all. - */ - - switch (pri) { - case MANAGE_PRIORITY: - priv->txmapringhead = head; - - if (priv->ack_tx_to_ieee) { - if (rtl8180_is_tx_queue_empty(dev)) { - priv->ack_tx_to_ieee = 0; - ieee80211_ps_tx_ack(priv->ieee80211, !error); - } - } - break; - case BK_PRIORITY: - priv->txbkpringhead = head; - break; - case BE_PRIORITY: - priv->txbepringhead = head; - break; - case VI_PRIORITY: - priv->txvipringhead = head; - break; - case VO_PRIORITY: - priv->txvopringhead = head; - break; - case HI_PRIORITY: - priv->txhpringhead = head; - break; - } - - spin_unlock_irqrestore(&priv->tx_lock, flag); -} - -static irqreturn_t rtl8180_interrupt(int irq, void *netdev) -{ - struct net_device *dev = (struct net_device *) netdev; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long flags; - u32 inta; - - /* We should return IRQ_NONE, but for now let me keep this */ - if (priv->irq_enabled == 0) - return IRQ_HANDLED; - - spin_lock_irqsave(&priv->irq_th_lock, flags); - - /* ISR: 4bytes */ - inta = read_nic_dword(dev, ISR); - write_nic_dword(dev, ISR, inta); /* reset int situation */ - - priv->stats.shints++; - - if (!inta) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return IRQ_HANDLED; - /* - * most probably we can safely return IRQ_NONE, - * but for now is better to avoid problems - */ - } - - if (inta == 0xffff) { - /* HW disappeared */ - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return IRQ_HANDLED; - } - - priv->stats.ints++; - - if (!netif_running(dev)) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return IRQ_HANDLED; - } - - if (inta & ISR_TimeOut) - write_nic_dword(dev, TimerInt, 0); - - if (inta & ISR_TBDOK) - priv->stats.txbeacon++; - - if (inta & ISR_TBDER) - priv->stats.txbeaconerr++; - - if (inta & IMR_TMGDOK) - rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0); - - if (inta & ISR_THPDER) { - priv->stats.txhperr++; - rtl8180_tx_isr(dev, HI_PRIORITY, 1); - priv->ieee80211->stats.tx_errors++; - } - - if (inta & ISR_THPDOK) { /* High priority tx ok */ - priv->link_detect.num_tx_ok_in_period++; - priv->stats.txhpokint++; - rtl8180_tx_isr(dev, HI_PRIORITY, 0); - } - - if (inta & ISR_RER) - priv->stats.rxerr++; - - if (inta & ISR_TBKDER) { /* corresponding to BK_PRIORITY */ - priv->stats.txbkperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, BK_PRIORITY, 1); - rtl8180_try_wake_queue(dev, BK_PRIORITY); - } - - if (inta & ISR_TBEDER) { /* corresponding to BE_PRIORITY */ - priv->stats.txbeperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, BE_PRIORITY, 1); - rtl8180_try_wake_queue(dev, BE_PRIORITY); - } - if (inta & ISR_TNPDER) { /* corresponding to VO_PRIORITY */ - priv->stats.txnperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, NORM_PRIORITY, 1); - rtl8180_try_wake_queue(dev, NORM_PRIORITY); - } - - if (inta & ISR_TLPDER) { /* corresponding to VI_PRIORITY */ - priv->stats.txlperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, LOW_PRIORITY, 1); - rtl8180_try_wake_queue(dev, LOW_PRIORITY); - } - - if (inta & ISR_ROK) { - priv->stats.rxint++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_RQoSOK) { - priv->stats.rxint++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_BcnInt) - rtl8180_prepare_beacon(dev); - - if (inta & ISR_RDU) { - DMESGW("No RX descriptor available"); - priv->stats.rxrdu++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_RXFOVW) { - priv->stats.rxoverflow++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_TXFOVW) - priv->stats.txoverflow++; - - if (inta & ISR_TNPDOK) { /* Normal priority tx ok */ - priv->link_detect.num_tx_ok_in_period++; - priv->stats.txnpokint++; - rtl8180_tx_isr(dev, NORM_PRIORITY, 0); - rtl8180_try_wake_queue(dev, NORM_PRIORITY); - } - - if (inta & ISR_TLPDOK) { /* Low priority tx ok */ - priv->link_detect.num_tx_ok_in_period++; - priv->stats.txlpokint++; - rtl8180_tx_isr(dev, LOW_PRIORITY, 0); - rtl8180_try_wake_queue(dev, LOW_PRIORITY); - } - - if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */ - priv->stats.txbkpokint++; - priv->link_detect.num_tx_ok_in_period++; - rtl8180_tx_isr(dev, BK_PRIORITY, 0); - rtl8180_try_wake_queue(dev, BE_PRIORITY); - } - - if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */ - priv->stats.txbeperr++; - priv->link_detect.num_tx_ok_in_period++; - rtl8180_tx_isr(dev, BE_PRIORITY, 0); - rtl8180_try_wake_queue(dev, BE_PRIORITY); - } - force_pci_posting(dev); - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - - return IRQ_HANDLED; -} - -void rtl8180_irq_rx_tasklet(struct r8180_priv *priv) -{ - rtl8180_rx(priv->dev); -} - -void GPIOChangeRFWorkItemCallBack(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of( - work, struct ieee80211_device, GPIOChangeRFWorkItem.work); - struct net_device *dev = ieee->dev; - struct r8180_priv *priv = ieee80211_priv(dev); - u8 btPSR; - u8 btConfig0; - enum rt_rf_power_state eRfPowerStateToSet; - bool bActuallySet = false; - - char *argv[3]; - static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh"; - static char *envp[] = {"HOME=/", "TERM=linux", - "PATH=/usr/bin:/bin", NULL}; - static int readf_count; - - readf_count = (readf_count+1)%0xffff; - /* We should turn off LED before polling FF51[4]. */ - - /* Turn off LED. */ - btPSR = read_nic_byte(dev, PSR); - write_nic_byte(dev, PSR, (btPSR & ~BIT3)); - - /* It need to delay 4us suggested */ - udelay(4); - - /* HW radio On/Off according to the value of FF51[4](config0) */ - btConfig0 = btPSR = read_nic_byte(dev, CONFIG0); - - eRfPowerStateToSet = (btConfig0 & BIT4) ? RF_ON : RF_OFF; - - /* Turn LED back on when radio enabled */ - if (eRfPowerStateToSet == RF_ON) - write_nic_byte(dev, PSR, btPSR | BIT3); - - if ((priv->ieee80211->bHwRadioOff == true) && - (eRfPowerStateToSet == RF_ON)) { - priv->ieee80211->bHwRadioOff = false; - bActuallySet = true; - } else if ((priv->ieee80211->bHwRadioOff == false) && - (eRfPowerStateToSet == RF_OFF)) { - priv->ieee80211->bHwRadioOff = true; - bActuallySet = true; - } - - if (bActuallySet) { - MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW); - - /* To update the UI status for Power status changed */ - if (priv->ieee80211->bHwRadioOff == true) - argv[1] = "RFOFF"; - else - argv[1] = "RFON"; - argv[0] = RadioPowerPath; - argv[2] = NULL; - - call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC); - } -} - -module_init(rtl8180_pci_module_init); -module_exit(rtl8180_pci_module_exit); diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c deleted file mode 100644 index 8c020e0..0000000 --- a/drivers/staging/rtl8187se/r8180_dm.c +++ /dev/null @@ -1,1139 +0,0 @@ -#include "r8180_dm.h" -#include "r8180_hw.h" -#include "r8180_93cx6.h" - - /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */ -#define RATE_ADAPTIVE_TIMER_PERIOD 300 - -bool CheckHighPower(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if (!priv->bRegHighPowerMechanism) - return false; - - if (ieee->state == IEEE80211_LINKED_SCANNING) - return false; - - return true; -} - -/* - * Description: - * Update Tx power level if necessary. - * See also DoRxHighPower() and SetTxPowerLevel8185() for reference. - * - * Note: - * The reason why we udpate Tx power level here instead of DoRxHighPower() - * is the number of IO to change Tx power is much more than channel TR switch - * and they are related to OFDM and MAC registers. - * So, we don't want to update it so frequently in per-Rx packet base. - */ -static void DoTxHighPower(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 HiPwrUpperTh = 0; - u16 HiPwrLowerTh = 0; - u8 RSSIHiPwrUpperTh; - u8 RSSIHiPwrLowerTh; - u8 u1bTmp; - char OfdmTxPwrIdx, CckTxPwrIdx; - - HiPwrUpperTh = priv->RegHiPwrUpperTh; - HiPwrLowerTh = priv->RegHiPwrLowerTh; - - HiPwrUpperTh = HiPwrUpperTh * 10; - HiPwrLowerTh = HiPwrLowerTh * 10; - RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh; - RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh; - - /* lzm add 080826 */ - OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; - CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; - - if ((priv->UndecoratedSmoothedSS > HiPwrUpperTh) || - (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) { - /* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */ - - priv->bToUpdateTxPwr = true; - u1bTmp = read_nic_byte(dev, CCK_TXAGC); - - /* If it never enter High Power. */ - if (CckTxPwrIdx == u1bTmp) { - u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */ - write_nic_byte(dev, CCK_TXAGC, u1bTmp); - - u1bTmp = read_nic_byte(dev, OFDM_TXAGC); - u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */ - write_nic_byte(dev, OFDM_TXAGC, u1bTmp); - } - - } else if ((priv->UndecoratedSmoothedSS < HiPwrLowerTh) && - (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) { - if (priv->bToUpdateTxPwr) { - priv->bToUpdateTxPwr = false; - /* SD3 required. */ - u1bTmp = read_nic_byte(dev, CCK_TXAGC); - if (u1bTmp < CckTxPwrIdx) { - write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx); - } - - u1bTmp = read_nic_byte(dev, OFDM_TXAGC); - if (u1bTmp < OfdmTxPwrIdx) { - write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); - } - } - } -} - - -/* - * Description: - * Callback function of UpdateTxPowerWorkItem. - * Because of some event happened, e.g. CCX TPC, High Power Mechanism, - * We update Tx power of current channel again. - */ -void rtl8180_tx_pw_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, tx_pw_wq); - struct net_device *dev = ieee->dev; - - DoTxHighPower(dev); -} - - -/* - * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise. - */ -bool CheckDig(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if (!priv->bDigMechanism) - return false; - - if (ieee->state != IEEE80211_LINKED) - return false; - - if ((priv->ieee80211->rate / 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */ - return false; - return true; -} -/* - * Implementation of DIG for Zebra and Zebra2. - */ -static void DIG_Zebra(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 CCKFalseAlarm, OFDMFalseAlarm; - u16 OfdmFA1, OfdmFA2; - int InitialGainStep = 7; /* The number of initial gain stages. */ - int LowestGainStage = 4; /* The capable lowest stage of performing dig workitem. */ - u32 AwakePeriodIn2Sec = 0; - - CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff); - OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff); - OfdmFA1 = 0x15; - OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8; - - /* The number of initial gain steps is different, by Bruce, 2007-04-13. */ - if (priv->InitialGain == 0) { /* autoDIG */ - /* Advised from SD3 DZ */ - priv->InitialGain = 4; /* In 87B, m74dBm means State 4 (m82dBm) */ - } - /* Advised from SD3 DZ */ - OfdmFA1 = 0x20; - -#if 1 /* lzm reserved 080826 */ - AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec); - priv->DozePeriodInPast2Sec = 0; - - if (AwakePeriodIn2Sec) { - OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000); - OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000); - } else { - ; - } -#endif - - InitialGainStep = 8; - LowestGainStage = priv->RegBModeGainStage; /* Lowest gain stage. */ - - if (OFDMFalseAlarm > OfdmFA1) { - if (OFDMFalseAlarm > OfdmFA2) { - priv->DIG_NumberFallbackVote++; - if (priv->DIG_NumberFallbackVote > 1) { - /* serious OFDM False Alarm, need fallback */ - if (priv->InitialGain < InitialGainStep) { - priv->InitialGainBackUp = priv->InitialGain; - - priv->InitialGain = (priv->InitialGain + 1); - UpdateInitialGain(dev); - } - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote = 0; - } - } else { - if (priv->DIG_NumberFallbackVote) - priv->DIG_NumberFallbackVote--; - } - priv->DIG_NumberUpgradeVote = 0; - } else { - if (priv->DIG_NumberFallbackVote) - priv->DIG_NumberFallbackVote--; - priv->DIG_NumberUpgradeVote++; - - if (priv->DIG_NumberUpgradeVote > 9) { - if (priv->InitialGain > LowestGainStage) { /* In 87B, m78dBm means State 4 (m864dBm) */ - priv->InitialGainBackUp = priv->InitialGain; - - priv->InitialGain = (priv->InitialGain - 1); - UpdateInitialGain(dev); - } - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote = 0; - } - } -} - -/* - * Dispatch DIG implementation according to RF. - */ -static void DynamicInitGain(struct net_device *dev) -{ - DIG_Zebra(dev); -} - -void rtl8180_hw_dig_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_dig_wq); - struct net_device *dev = ieee->dev; - struct r8180_priv *priv = ieee80211_priv(dev); - - /* Read CCK and OFDM False Alarm. */ - priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM); - - - /* Adjust Initial Gain dynamically. */ - DynamicInitGain(dev); - -} - -static int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate) -{ - u8 rate_len; - u8 rate_ex_len; - u8 RateMask = 0x7F; - u8 idx; - unsigned short Found = 0; - u8 NaiveTxRate = TxRate&RateMask; - - rate_len = priv->ieee80211->current_network.rates_len; - rate_ex_len = priv->ieee80211->current_network.rates_ex_len; - for (idx = 0; idx < rate_len; idx++) { - if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) { - Found = 1; - goto found_rate; - } - } - for (idx = 0; idx < rate_ex_len; idx++) { - if ((priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate) { - Found = 1; - goto found_rate; - } - } - return Found; -found_rate: - return Found; -} - -/* - * Get the Tx rate one degree up form the input rate in the supported rates. - * Return the upgrade rate if it is successed, otherwise return the input rate. - */ -static u8 GetUpgradeTxRate(struct net_device *dev, u8 rate) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 UpRate; - - /* Upgrade 1 degree. */ - switch (rate) { - case 108: /* Up to 54Mbps. */ - UpRate = 108; - break; - - case 96: /* Up to 54Mbps. */ - UpRate = 108; - break; - - case 72: /* Up to 48Mbps. */ - UpRate = 96; - break; - - case 48: /* Up to 36Mbps. */ - UpRate = 72; - break; - - case 36: /* Up to 24Mbps. */ - UpRate = 48; - break; - - case 22: /* Up to 18Mbps. */ - UpRate = 36; - break; - - case 11: /* Up to 11Mbps. */ - UpRate = 22; - break; - - case 4: /* Up to 5.5Mbps. */ - UpRate = 11; - break; - - case 2: /* Up to 2Mbps. */ - UpRate = 4; - break; - - default: - printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); - return rate; - } - /* Check if the rate is valid. */ - if (IncludedInSupportedRates(priv, UpRate)) { - return UpRate; - } else { - return rate; - } - return rate; -} -/* - * Get the Tx rate one degree down form the input rate in the supported rates. - * Return the degrade rate if it is successed, otherwise return the input rate. - */ - -static u8 GetDegradeTxRate(struct net_device *dev, u8 rate) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 DownRate; - - /* Upgrade 1 degree. */ - switch (rate) { - case 108: /* Down to 48Mbps. */ - DownRate = 96; - break; - - case 96: /* Down to 36Mbps. */ - DownRate = 72; - break; - - case 72: /* Down to 24Mbps. */ - DownRate = 48; - break; - - case 48: /* Down to 18Mbps. */ - DownRate = 36; - break; - - case 36: /* Down to 11Mbps. */ - DownRate = 22; - break; - - case 22: /* Down to 5.5Mbps. */ - DownRate = 11; - break; - - case 11: /* Down to 2Mbps. */ - DownRate = 4; - break; - - case 4: /* Down to 1Mbps. */ - DownRate = 2; - break; - - case 2: /* Down to 1Mbps. */ - DownRate = 2; - break; - - default: - printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); - return rate; - } - /* Check if the rate is valid. */ - if (IncludedInSupportedRates(priv, DownRate)) { - return DownRate; - } else { - return rate; - } - return rate; -} -/* - * Helper function to determine if specified data rate is - * CCK rate. - */ - -static bool MgntIsCckRate(u16 rate) -{ - bool bReturn = false; - - if ((rate <= 22) && (rate != 12) && (rate != 18)) { - bReturn = true; - } - - return bReturn; -} -/* - * Description: - * Tx Power tracking mechanism routine on 87SE. - */ -void TxPwrTracking87SE(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 tmpu1Byte, CurrentThermal, Idx; - char CckTxPwrIdx, OfdmTxPwrIdx; - - tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); - CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */ - CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c : CurrentThermal;/* lzm add 080826 */ - - if (CurrentThermal != priv->ThermalMeter) { - /* Update Tx Power level on each channel. */ - for (Idx = 1; Idx < 15; Idx++) { - CckTxPwrIdx = priv->chtxpwr[Idx]; - OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; - - if (CurrentThermal > priv->ThermalMeter) { - /* higher thermal meter. */ - CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; - OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; - - if (CckTxPwrIdx > 35) - CckTxPwrIdx = 35; /* Force TxPower to maximal index. */ - if (OfdmTxPwrIdx > 35) - OfdmTxPwrIdx = 35; - } else { - /* lower thermal meter. */ - CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; - OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; - - if (CckTxPwrIdx < 0) - CckTxPwrIdx = 0; - if (OfdmTxPwrIdx < 0) - OfdmTxPwrIdx = 0; - } - - /* Update TxPower level on CCK and OFDM resp. */ - priv->chtxpwr[Idx] = CckTxPwrIdx; - priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; - } - - /* Update TxPower level immediately. */ - rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); - } - priv->ThermalMeter = CurrentThermal; -} -static void StaRateAdaptive87SE(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long CurrTxokCnt; - u16 CurrRetryCnt; - u16 CurrRetryRate; - unsigned long CurrRxokCnt; - bool bTryUp = false; - bool bTryDown = false; - u8 TryUpTh = 1; - u8 TryDownTh = 2; - u32 TxThroughput; - long CurrSignalStrength; - bool bUpdateInitialGain = false; - u8 u1bOfdm = 0, u1bCck = 0; - char OfdmTxPwrIdx, CckTxPwrIdx; - - priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD; - - - CurrRetryCnt = priv->CurrRetryCnt; - CurrTxokCnt = priv->NumTxOkTotal - priv->LastTxokCnt; - CurrRxokCnt = priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt; - CurrSignalStrength = priv->Stats_RecvSignalPower; - TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes); - priv->LastTxOKBytes = priv->NumTxOkBytesTotal; - priv->CurrentOperaRate = priv->ieee80211->rate / 5; - /* 2 Compute retry ratio. */ - if (CurrTxokCnt > 0) { - CurrRetryRate = (u16)(CurrRetryCnt * 100 / CurrTxokCnt); - } else { - /* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */ - CurrRetryRate = (u16)(CurrRetryCnt * 100 / 1); - } - - priv->LastRetryCnt = priv->CurrRetryCnt; - priv->LastTxokCnt = priv->NumTxOkTotal; - priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal; - priv->CurrRetryCnt = 0; - - /* 2No Tx packets, return to init_rate or not? */ - if (CurrRetryRate == 0 && CurrTxokCnt == 0) { - /* - * After 9 (30*300ms) seconds in this condition, we try to raise rate. - */ - priv->TryupingCountNoData++; - - /* [TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 */ - if (priv->TryupingCountNoData > 30) { - priv->TryupingCountNoData = 0; - priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); - /* Reset Fail Record */ - priv->LastFailTxRate = 0; - priv->LastFailTxRateSS = -200; - priv->FailTxRateCount = 0; - } - goto SetInitialGain; - } else { - priv->TryupingCountNoData = 0; /*Reset trying up times. */ - } - - - /* - * For Netgear case, I comment out the following signal strength estimation, - * which can results in lower rate to transmit when sample is NOT enough (e.g. PING request). - * - * Restructure rate adaptive as the following main stages: - * (1) Add retry threshold in 54M upgrading condition with signal strength. - * (2) Add the mechanism to degrade to CCK rate according to signal strength - * and retry rate. - * (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated - * situation, Initial Gain Update is upon on DIG mechanism except CCK rate. - * (4) Add the mechanism of trying to upgrade tx rate. - * (5) Record the information of upping tx rate to avoid trying upping tx rate constantly. - * - */ - - /* - * 11Mbps or 36Mbps - * Check more times in these rate(key rates). - */ - if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72) - TryUpTh += 9; - /* - * Let these rates down more difficult. - */ - if (MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36) - TryDownTh += 1; - - /* 1 Adjust Rate. */ - if (priv->bTryuping == true) { - /* 2 For Test Upgrading mechanism - * Note: - * Sometimes the throughput is upon on the capability between the AP and NIC, - * thus the low data rate does not improve the performance. - * We randomly upgrade the data rate and check if the retry rate is improved. - */ - - /* Upgrading rate did not improve the retry rate, fallback to the original rate. */ - if ((CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) { - /*Not necessary raising rate, fall back rate. */ - bTryDown = true; - } else { - priv->bTryuping = false; - } - } else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) { - /* - * 2For High Power - * - * Return to highest data rate, if signal strength is good enough. - * SignalStrength threshold(-50dbm) is for RTL8186. - * Revise SignalStrength threshold to -51dbm. - */ - /* Also need to check retry rate for safety, by Bruce, 2007-06-05. */ - if (priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate) { - bTryUp = true; - /* Upgrade Tx Rate directly. */ - priv->TryupingCount += TryUpTh; - } - - } else if (CurrTxokCnt > 9 && CurrTxokCnt < 100 && CurrRetryRate >= 600) { - /* - *2 For Serious Retry - * - * Traffic is not busy but our Tx retry is serious. - */ - bTryDown = true; - /* Let Rate Mechanism to degrade tx rate directly. */ - priv->TryDownCountLowData += TryDownTh; - } else if (priv->CurrentOperaRate == 108) { - /* 2For 54Mbps */ - /* Air Link */ - if ((CurrRetryRate > 26) && (priv->LastRetryRate > 25)) { - bTryDown = true; - } - /* Cable Link */ - else if ((CurrRetryRate > 17) && (priv->LastRetryRate > 16) && (CurrSignalStrength > -72)) { - bTryDown = true; - } - - if (bTryDown && (CurrSignalStrength < -75)) /* cable link */ - priv->TryDownCountLowData += TryDownTh; - } else if (priv->CurrentOperaRate == 96) { - /* 2For 48Mbps */ - /* Air Link */ - if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) { - bTryDown = true; - } else if (((CurrRetryRate > 21) && (priv->LastRetryRate > 20)) && (CurrSignalStrength > -74)) { /* Cable Link */ - /* Down to rate 36Mbps. */ - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 8) && (priv->LastRetryRate < 8)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - - if (bTryDown && (CurrSignalStrength < -75)) { - priv->TryDownCountLowData += TryDownTh; - } - } else if (priv->CurrentOperaRate == 72) { - /* 2For 36Mbps */ - if ((CurrRetryRate > 43) && (priv->LastRetryRate > 41)) { - /* Down to rate 24Mbps. */ - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 15) && (priv->LastRetryRate < 16)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - - if (bTryDown && (CurrSignalStrength < -80)) - priv->TryDownCountLowData += TryDownTh; - - } else if (priv->CurrentOperaRate == 48) { - /* 2For 24Mbps */ - /* Air Link */ - if (((CurrRetryRate > 63) && (priv->LastRetryRate > 62))) { - bTryDown = true; - } else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */ - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - - if (bTryDown && (CurrSignalStrength < -82)) - priv->TryDownCountLowData += TryDownTh; - - } else if (priv->CurrentOperaRate == 36) { - if (((CurrRetryRate > 85) && (priv->LastRetryRate > 86))) { - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 22) && (priv->LastRetryRate < 23)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 22) { - /* 2For 11Mbps */ - if (CurrRetryRate > 95) { - bTryDown = true; - } else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */ - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 11) { - /* 2For 5.5Mbps */ - if (CurrRetryRate > 149) { - bTryDown = true; - } else if ((CurrRetryRate < 60) && (priv->LastRetryRate < 65)) { - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 4) { - /* 2For 2 Mbps */ - if ((CurrRetryRate > 99) && (priv->LastRetryRate > 99)) { - bTryDown = true; - } else if ((CurrRetryRate < 65) && (priv->LastRetryRate < 70)) { - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 2) { - /* 2For 1 Mbps */ - if ((CurrRetryRate < 70) && (priv->LastRetryRate < 75)) { - bTryUp = true; - } - } - - if (bTryUp && bTryDown) - printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n"); - - /* 1 Test Upgrading Tx Rate - * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC. - * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate. - */ - if (!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0) - && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) { - if (jiffies % (CurrRetryRate + 101) == 0) { - bTryUp = true; - priv->bTryuping = true; - } - } - - /* 1 Rate Mechanism */ - if (bTryUp) { - priv->TryupingCount++; - priv->TryDownCountLowData = 0; - - /* - * Check more times if we need to upgrade indeed. - * Because the largest value of pHalData->TryupingCount is 0xFFFF and - * the largest value of pHalData->FailTxRateCount is 0x14, - * this condition will be satisfied at most every 2 min. - */ - - if ((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) || - (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) { - priv->TryupingCount = 0; - /* - * When transferring from CCK to OFDM, DIG is an important issue. - */ - if (priv->CurrentOperaRate == 22) - bUpdateInitialGain = true; - - /* - * The difference in throughput between 48Mbps and 36Mbps is 8M. - * So, we must be careful in this rate scale. Isaiah 2008-02-15. - */ - if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) && - (priv->FailTxRateCount > 2)) - priv->RateAdaptivePeriod = (RATE_ADAPTIVE_TIMER_PERIOD / 2); - - /* (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. */ - /* (2)If the signal strength is increased, it may be able to upgrade. */ - - priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); - - if (priv->CurrentOperaRate == 36) { - priv->bUpdateARFR = true; - write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */ - } else if (priv->bUpdateARFR) { - priv->bUpdateARFR = false; - write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */ - } - - /* Update Fail Tx rate and count. */ - if (priv->LastFailTxRate != priv->CurrentOperaRate) { - priv->LastFailTxRate = priv->CurrentOperaRate; - priv->FailTxRateCount = 0; - priv->LastFailTxRateSS = -200; /* Set lowest power. */ - } - } - } else { - if (priv->TryupingCount > 0) - priv->TryupingCount--; - } - - if (bTryDown) { - priv->TryDownCountLowData++; - priv->TryupingCount = 0; - - /* Check if Tx rate can be degraded or Test trying upgrading should fallback. */ - if (priv->TryDownCountLowData > TryDownTh || priv->bTryuping) { - priv->TryDownCountLowData = 0; - priv->bTryuping = false; - /* Update fail information. */ - if (priv->LastFailTxRate == priv->CurrentOperaRate) { - priv->FailTxRateCount++; - /* Record the Tx fail rate signal strength. */ - if (CurrSignalStrength > priv->LastFailTxRateSS) - priv->LastFailTxRateSS = CurrSignalStrength; - } else { - priv->LastFailTxRate = priv->CurrentOperaRate; - priv->FailTxRateCount = 1; - priv->LastFailTxRateSS = CurrSignalStrength; - } - priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate); - - /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */ - if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72)) { - priv->CurrentOperaRate = 72; - } - - if (priv->CurrentOperaRate == 36) { - priv->bUpdateARFR = true; - write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */ - } else if (priv->bUpdateARFR) { - priv->bUpdateARFR = false; - write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */ - } - - /* - * When it is CCK rate, it may need to update initial gain to receive lower power packets. - */ - if (MgntIsCckRate(priv->CurrentOperaRate)) { - bUpdateInitialGain = true; - } - } - } else { - if (priv->TryDownCountLowData > 0) - priv->TryDownCountLowData--; - } - - /* - * Keep the Tx fail rate count to equal to 0x15 at most. - * Reduce the fail count at least to 10 sec if tx rate is tending stable. - */ - if (priv->FailTxRateCount >= 0x15 || - (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) { - priv->FailTxRateCount--; - } - - - OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; - CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; - - /* Mac0x9e increase 2 level in 36M~18M situation */ - if ((priv->CurrentOperaRate < 96) && (priv->CurrentOperaRate > 22)) { - u1bCck = read_nic_byte(dev, CCK_TXAGC); - u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); - - /* case 1: Never enter High power */ - if (u1bCck == CckTxPwrIdx) { - if (u1bOfdm != (OfdmTxPwrIdx + 2)) { - priv->bEnhanceTxPwr = true; - u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2); - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - } - } else if (u1bCck < CckTxPwrIdx) { - /* case 2: enter high power */ - if (!priv->bEnhanceTxPwr) { - priv->bEnhanceTxPwr = true; - u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2); - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - } - } - } else if (priv->bEnhanceTxPwr) { /* 54/48/11/5.5/2/1 */ - u1bCck = read_nic_byte(dev, CCK_TXAGC); - u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); - - /* case 1: Never enter High power */ - if (u1bCck == CckTxPwrIdx) { - priv->bEnhanceTxPwr = false; - write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); - } - /* case 2: enter high power */ - else if (u1bCck < CckTxPwrIdx) { - priv->bEnhanceTxPwr = false; - u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2) : 0; - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - } - } - - /* - * We need update initial gain when we set tx rate "from OFDM to CCK" or - * "from CCK to OFDM". - */ -SetInitialGain: - if (bUpdateInitialGain) { - if (MgntIsCckRate(priv->CurrentOperaRate)) { /* CCK */ - if (priv->InitialGain > priv->RegBModeGainStage) { - priv->InitialGainBackUp = priv->InitialGain; - - if (CurrSignalStrength < -85) /* Low power, OFDM [0x17] = 26. */ - /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */ - priv->InitialGain = priv->RegBModeGainStage; - - else if (priv->InitialGain > priv->RegBModeGainStage + 1) - priv->InitialGain -= 2; - - else - priv->InitialGain--; - - printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate); - UpdateInitialGain(dev); - } - } else { /* OFDM */ - if (priv->InitialGain < 4) { - priv->InitialGainBackUp = priv->InitialGain; - - priv->InitialGain++; - printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate); - UpdateInitialGain(dev); - } - } - } - - /* Record the related info */ - priv->LastRetryRate = CurrRetryRate; - priv->LastTxThroughput = TxThroughput; - priv->ieee80211->rate = priv->CurrentOperaRate * 5; -} - -void rtl8180_rate_adapter(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, rate_adapter_wq); - struct net_device *dev = ieee->dev; - StaRateAdaptive87SE(dev); -} -void timer_rate_adaptive(unsigned long data) -{ - struct r8180_priv *priv = ieee80211_priv((struct net_device *)data); - if (!priv->up) { - return; - } - if ((priv->ieee80211->iw_mode != IW_MODE_MASTER) - && (priv->ieee80211->state == IEEE80211_LINKED) && - (priv->ForcedDataRate == 0)) { - queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq); - } - priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod); - add_timer(&priv->rateadapter_timer); -} - -void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - priv->AdRxOkCnt++; - - if (priv->AdRxSignalStrength != -1) { - priv->AdRxSignalStrength = ((priv->AdRxSignalStrength * 7) + (SignalStrength * 3)) / 10; - } else { /* Initialization case. */ - priv->AdRxSignalStrength = SignalStrength; - } - - if (priv->LastRxPktAntenna) /* Main antenna. */ - priv->AdMainAntennaRxOkCnt++; - else /* Aux antenna. */ - priv->AdAuxAntennaRxOkCnt++; -} - /* Change Antenna Switch. */ -bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bAntennaSwitched = false; - - switch (u1bAntennaIndex) { - case 0: - /* Mac register, main antenna */ - write_nic_byte(dev, ANTSEL, 0x03); - /* base band */ - write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */ - write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */ - - bAntennaSwitched = true; - break; - - case 1: - /* Mac register, aux antenna */ - write_nic_byte(dev, ANTSEL, 0x00); - /* base band */ - write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */ - write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */ - - bAntennaSwitched = true; - - break; - - default: - printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex); - break; - } - - if (bAntennaSwitched) - priv->CurrAntennaIndex = u1bAntennaIndex; - - return bAntennaSwitched; -} - /* Toggle Antenna switch. */ -bool SwitchAntenna(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - bool bResult; - - if (priv->CurrAntennaIndex == 0) { - bResult = SetAntenna8185(dev, 1); - } else { - bResult = SetAntenna8185(dev, 0); - } - - return bResult; -} -/* - * Engine of SW Antenna Diversity mechanism. - * Since 8187 has no Tx part information, - * this implementation is only dependend on Rx part information. - */ -void SwAntennaDiversity(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bSwCheckSS = false; - if (bSwCheckSS) { - priv->AdTickCount++; - - printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n", - priv->AdTickCount, priv->AdCheckPeriod); - printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n", - priv->AdRxSignalStrength, priv->AdRxSsThreshold); - } - - /* Case 1. No Link. */ - if (priv->ieee80211->state != IEEE80211_LINKED) { - priv->bAdSwitchedChecking = false; - /* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */ - SwitchAntenna(dev); - - /* Case 2. Linked but no packet receive.d */ - } else if (priv->AdRxOkCnt == 0) { - priv->bAdSwitchedChecking = false; - SwitchAntenna(dev); - - /* Case 3. Evaluate last antenna switch action and undo it if necessary. */ - } else if (priv->bAdSwitchedChecking == true) { - priv->bAdSwitchedChecking = false; - - /* Adjust Rx signal strength threshold. */ - priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; - - priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? - priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold; - if (priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) { - /* Rx signal strength is not improved after we swtiched antenna. => Swich back. */ - /* Increase Antenna Diversity checking period due to bad decision. */ - priv->AdCheckPeriod *= 2; - /* Increase Antenna Diversity checking period. */ - if (priv->AdCheckPeriod > priv->AdMaxCheckPeriod) - priv->AdCheckPeriod = priv->AdMaxCheckPeriod; - - /* Wrong decision => switch back. */ - SwitchAntenna(dev); - } else { - /* Rx Signal Strength is improved. */ - - /* Reset Antenna Diversity checking period to its min value. */ - priv->AdCheckPeriod = priv->AdMinCheckPeriod; - } - - } - /* Case 4. Evaluate if we shall switch antenna now. */ - /* Cause Table Speed is very fast in TRC Dell Lab, we check it every time. */ - else { - priv->AdTickCount = 0; - - /* - * <Roger_Notes> We evaluate RxOk counts for each antenna first and than - * evaluate signal strength. - * The following operation can overcome the disability of CCA on both two antennas - * When signal strength was extremely low or high. - * 2008.01.30. - */ - - /* - * Evaluate RxOk count from each antenna if we shall switch default antenna now. - */ - if ((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt) - && (priv->CurrAntennaIndex == 0)) { - /* We set Main antenna as default but RxOk count was less than Aux ones. */ - - /* Switch to Aux antenna. */ - SwitchAntenna(dev); - priv->bHWAdSwitched = true; - } else if ((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt) - && (priv->CurrAntennaIndex == 1)) { - /* We set Aux antenna as default but RxOk count was less than Main ones. */ - - /* Switch to Main antenna. */ - SwitchAntenna(dev); - priv->bHWAdSwitched = true; - } else { - /* Default antenna is better. */ - - /* Still need to check current signal strength. */ - priv->bHWAdSwitched = false; - } - /* - * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna - * didn't change by HW evaluation. - * 2008.02.27. - * - * [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05 - * For example, Throughput of aux is better than main antenna(about 10M v.s 2M), - * but AdRxSignalStrength is less than main. - * Our guess is that main antenna have lower throughput and get many change - * to receive more CCK packets(ex.Beacon) which have stronger SignalStrength. - */ - if ((!priv->bHWAdSwitched) && (bSwCheckSS)) { - /* Evaluate Rx signal strength if we shall switch antenna now. */ - if (priv->AdRxSignalStrength < priv->AdRxSsThreshold) { - /* Rx signal strength is weak => Switch Antenna. */ - priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength; - priv->bAdSwitchedChecking = true; - - SwitchAntenna(dev); - } else { - /* Rx signal strength is OK. */ - priv->bAdSwitchedChecking = false; - /* Increase Rx signal strength threshold if necessary. */ - if ((priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && /* Signal is much stronger than current threshold */ - priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) { /* Current threhold is not yet reach upper limit. */ - - priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2; - priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? - priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;/* +by amy 080312 */ - } - - /* Reduce Antenna Diversity checking period if possible. */ - if (priv->AdCheckPeriod > priv->AdMinCheckPeriod) - priv->AdCheckPeriod /= 2; - } - } - } - /* Reset antenna diversity Rx related statistics. */ - priv->AdRxOkCnt = 0; - priv->AdMainAntennaRxOkCnt = 0; - priv->AdAuxAntennaRxOkCnt = 0; -} - - /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */ -bool CheckTxPwrTracking(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - if (!priv->bTxPowerTrack) - return false; - - /* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */ - if (priv->bToUpdateTxPwr) - return false; - - return true; -} - - - /* Timer callback function of SW Antenna Diversity. */ -void SwAntennaDiversityTimerCallback(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - enum rt_rf_power_state rtState; - - /* We do NOT need to switch antenna while RF is off. */ - rtState = priv->eRFPowerState; - do { - if (rtState == RF_OFF) { - break; - } else if (rtState == RF_SLEEP) { - /* Don't access BB/RF under Disable PLL situation. */ - break; - } - SwAntennaDiversity(dev); - - } while (false); - - if (priv->up) { - priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD); - add_timer(&priv->SwAntennaDiversityTimer); - } -} - diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h deleted file mode 100644 index cb4046f..0000000 --- a/drivers/staging/rtl8187se/r8180_dm.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef R8180_DM_H -#define R8180_DM_H - -#include "r8180.h" -/* #include "r8180_hw.h" */ -/* #include "r8180_93cx6.h" */ -void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength); -bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex); -bool SwitchAntenna(struct net_device *dev); -void SwAntennaDiversity(struct net_device *dev); -void SwAntennaDiversityTimerCallback(struct net_device *dev); -bool CheckDig(struct net_device *dev); -bool CheckHighPower(struct net_device *dev); -void rtl8180_hw_dig_wq(struct work_struct *work); -void rtl8180_tx_pw_wq(struct work_struct *work); -void rtl8180_rate_adapter(struct work_struct *work); -void TxPwrTracking87SE(struct net_device *dev); -bool CheckTxPwrTracking(struct net_device *dev); -void rtl8180_rate_adapter(struct work_struct *work); -void timer_rate_adaptive(unsigned long data); - - -#endif diff --git a/drivers/staging/rtl8187se/r8180_hw.h b/drivers/staging/rtl8187se/r8180_hw.h deleted file mode 100644 index e59d74f..0000000 --- a/drivers/staging/rtl8187se/r8180_hw.h +++ /dev/null @@ -1,588 +0,0 @@ -/* - This is part of rtl8180 OpenSource driver. - Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com> - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part of the - official Realtek driver. - Parts of this driver are based on the rtl8180 driver skeleton - from Patric Schenke & Andres Salomon. - Parts of this driver are based on the Intel Pro Wireless - 2100 GPL driver. - - We want to tanks the Authors of those projects - and the Ndiswrapper project Authors. -*/ - -/* Mariusz Matuszek added full registers definition with Realtek's name */ - -/* this file contains register definitions for the rtl8180 MAC controller */ -#ifndef R8180_HW -#define R8180_HW - - -#define BIT0 0x00000001 -#define BIT1 0x00000002 -#define BIT2 0x00000004 -#define BIT3 0x00000008 -#define BIT4 0x00000010 -#define BIT5 0x00000020 -#define BIT6 0x00000040 -#define BIT7 0x00000080 -#define BIT9 0x00000200 -#define BIT11 0x00000800 -#define BIT13 0x00002000 -#define BIT15 0x00008000 -#define BIT20 0x00100000 -#define BIT21 0x00200000 -#define BIT22 0x00400000 -#define BIT23 0x00800000 -#define BIT24 0x01000000 -#define BIT25 0x02000000 -#define BIT26 0x04000000 -#define BIT27 0x08000000 -#define BIT28 0x10000000 -#define BIT29 0x20000000 -#define BIT30 0x40000000 -#define BIT31 0x80000000 - -#define MAX_SLEEP_TIME (10000) -#define MIN_SLEEP_TIME (50) - -#define BB_HOST_BANG_EN (1<<2) -#define BB_HOST_BANG_CLK (1<<1) - -#define MAC0 0 -#define MAC4 4 - -#define CMD 0x37 -#define CMD_RST_SHIFT 4 -#define CMD_RX_ENABLE_SHIFT 3 -#define CMD_TX_ENABLE_SHIFT 2 - -#define EPROM_CMD 0x50 -#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4)) -#define EPROM_CMD_OPERATING_MODE_SHIFT 6 -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_NORMAL 0 -#define EPROM_CMD_LOAD 1 -#define EPROM_CMD_PROGRAM 2 -#define EPROM_CS_SHIFT 3 -#define EPROM_CK_SHIFT 2 -#define EPROM_W_SHIFT 1 -#define EPROM_R_SHIFT 0 -#define CONFIG2_DMA_POLLING_MODE_SHIFT 3 - -#define INTA_TXOVERFLOW (1<<15) -#define INTA_TIMEOUT (1<<14) -#define INTA_HIPRIORITYDESCERR (1<<9) -#define INTA_HIPRIORITYDESCOK (1<<8) -#define INTA_NORMPRIORITYDESCERR (1<<7) -#define INTA_NORMPRIORITYDESCOK (1<<6) -#define INTA_RXOVERFLOW (1<<5) -#define INTA_RXDESCERR (1<<4) -#define INTA_LOWPRIORITYDESCERR (1<<3) -#define INTA_LOWPRIORITYDESCOK (1<<2) -#define INTA_RXOK (1) -#define INTA_MASK 0x3c - -#define RXRING_ADDR 0xe4 /* page 0 */ -#define PGSELECT 0x5e -#define PGSELECT_PG_SHIFT 0 -#define RX_CONF 0x44 -#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \ -(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)) -#define RX_CHECK_BSSID_SHIFT 23 -#define ACCEPT_PWR_FRAME_SHIFT 22 -#define ACCEPT_MNG_FRAME_SHIFT 20 -#define ACCEPT_CTL_FRAME_SHIFT 19 -#define ACCEPT_DATA_FRAME_SHIFT 18 -#define ACCEPT_ICVERR_FRAME_SHIFT 12 -#define ACCEPT_CRCERR_FRAME_SHIFT 5 -#define ACCEPT_BCAST_FRAME_SHIFT 3 -#define ACCEPT_MCAST_FRAME_SHIFT 2 -#define ACCEPT_ALLMAC_FRAME_SHIFT 0 -#define ACCEPT_NICMAC_FRAME_SHIFT 1 - -#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15)) -#define RX_FIFO_THRESHOLD_SHIFT 13 -#define RX_FIFO_THRESHOLD_NONE 7 -#define RX_AUTORESETPHY_SHIFT 28 - -#define TX_CONF 0x40 -#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30 -#define TX_LOOPBACK_SHIFT 17 -#define TX_LOOPBACK_NONE 0 -#define TX_LOOPBACK_CONTINUE 3 -#define TX_LOOPBACK_MASK ((1<<17)|(1<<18)) -#define TX_DPRETRY_SHIFT 0 -#define R8180_MAX_RETRY 255 -#define TX_RTSRETRY_SHIFT 8 -#define TX_NOICV_SHIFT 19 -#define TX_NOCRC_SHIFT 16 -#define TX_DMA_POLLING 0xd9 -#define TX_DMA_POLLING_BEACON_SHIFT 7 -#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6 -#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5 -#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4 -#define TX_MANAGEPRIORITY_RING_ADDR 0x0C -#define TX_BKPRIORITY_RING_ADDR 0x10 -#define TX_BEPRIORITY_RING_ADDR 0x14 -#define TX_VIPRIORITY_RING_ADDR 0x20 -#define TX_VOPRIORITY_RING_ADDR 0x24 -#define TX_HIGHPRIORITY_RING_ADDR 0x28 -#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10)) -#define MAX_RX_DMA_2048 7 -#define MAX_RX_DMA_1024 6 -#define MAX_RX_DMA_SHIFT 10 -#define INT_TIMEOUT 0x48 -#define CONFIG3_CLKRUN_SHIFT 2 -#define CONFIG3_ANAPARAM_W_SHIFT 6 -#define ANAPARAM 0x54 -#define BEACON_INTERVAL 0x70 -#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \ -(1<<6)|(1<<7)|(1<<8)|(1<<9)) -#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \ -(1<<8)|(1<<9)) -#define ATIM 0x72 -#define EPROM_CS_SHIFT 3 -#define EPROM_CK_SHIFT 2 -#define PHY_ADR 0x7c -#define SECURITY 0x5f /* 1209 this is sth wrong */ -#define SECURITY_WEP_TX_ENABLE_SHIFT 1 -#define SECURITY_WEP_RX_ENABLE_SHIFT 0 -#define SECURITY_ENCRYP_104 1 -#define SECURITY_ENCRYP_SHIFT 4 -#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5)) -#define KEY0 0x90 /* 1209 this is sth wrong */ -#define CONFIG2_ANTENNA_SHIFT 6 -#define TX_BEACON_RING_ADDR 0x4c -#define CONFIG0_WEP40_SHIFT 7 -#define CONFIG0_WEP104_SHIFT 6 -#define AGCRESET_SHIFT 5 - - - -/* - * Operational registers offsets in PCI (I/O) space. - * RealTek names are used. - */ - -#define TSFTR 0x0018 - -#define TLPDA 0x0020 - -#define BSSID 0x002E - -#define CR 0x0037 - -#define RF_SW_CONFIG 0x8 /* store data which is transmitted to RF for driver */ -#define RF_SW_CFG_SI BIT1 -#define EIFS 0x2D /* Extended InterFrame Space Timer, in unit of 4 us. */ - -#define BRSR 0x34 /* Basic rate set */ - -#define IMR 0x006C -#define ISR 0x003C - -#define TCR 0x0040 - -#define RCR 0x0044 - -#define TimerInt 0x0048 - -#define CR9346 0x0050 - -#define CONFIG0 0x0051 -#define CONFIG2 0x0053 - -#define MSR 0x0058 - -#define CONFIG3 0x0059 -#define CONFIG4 0x005A - /* SD3 szuyitasi: Mac0x57= CC -> B0 Mac0x60= D1 -> C6 */ - /* Mac0x60 = 0x000004C6 power save parameters */ - #define ANAPARM_ASIC_ON 0xB0054D00 - #define ANAPARM2_ASIC_ON 0x000004C6 - - #define ANAPARM_ON ANAPARM_ASIC_ON - #define ANAPARM2_ON ANAPARM2_ASIC_ON - -#define TESTR 0x005B - -#define PSR 0x005E - -#define BcnItv 0x0070 - -#define AtimWnd 0x0072 - -#define BintrItv 0x0074 - -#define PhyAddr 0x007C -#define PhyDataR 0x007E - -/* following are for rtl8185 */ -#define RFPinsOutput 0x80 -#define RFPinsEnable 0x82 -#define RF_TIMING 0x8c -#define RFPinsSelect 0x84 -#define ANAPARAM2 0x60 -#define RF_PARA 0x88 -#define RFPinsInput 0x86 -#define GP_ENABLE 0x90 -#define GPIO 0x91 -#define SW_CONTROL_GPIO 0x400 -#define TX_ANTENNA 0x9f -#define TX_GAIN_OFDM 0x9e -#define TX_GAIN_CCK 0x9d -#define WPA_CONFIG 0xb0 -#define TX_AGC_CTL 0x9c -#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0 -#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1 -#define TX_AGC_CTL_FEEDBACK_ANT 2 -#define RESP_RATE 0x34 -#define SIFS 0xb4 -#define DIFS 0xb5 - -#define SLOT 0xb6 -#define CW_CONF 0xbc -#define CW_CONF_PERPACKET_RETRY_SHIFT 1 -#define CW_CONF_PERPACKET_CW_SHIFT 0 -#define CW_VAL 0xbd -#define MAX_RESP_RATE_SHIFT 4 -#define MIN_RESP_RATE_SHIFT 0 -#define RATE_FALLBACK 0xbe - -#define CONFIG5 0x00D8 - -#define PHYPR 0xDA /* 0xDA - 0x0B PHY Parameter Register. */ - -#define FEMR 0x1D4 /* Function Event Mask register */ - -#define FFER 0x00FC -#define FFER_END 0x00FF - - - -/* - * Bitmasks for specific register functions. - * Names are derived from the register name and function name. - * - * <REGISTER>_<FUNCTION>[<bit>] - * - * this leads to some awkward names... - */ - -#define BRSR_BPLCP ((1 << 8)) -#define BRSR_MBR ((1 << 1)|(1 << 0)) -#define BRSR_MBR_8185 ((1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0)) -#define BRSR_MBR0 ((1 << 0)) -#define BRSR_MBR1 ((1 << 1)) - -#define CR_RST ((1 << 4)) -#define CR_RE ((1 << 3)) -#define CR_TE ((1 << 2)) -#define CR_MulRW ((1 << 0)) - -#define IMR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */ -#define IMR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */ -#define IMR_WakeInt ((1 << 23)) /*Wake Up Interrupt */ -#define IMR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */ -#define IMR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */ -#define IMR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */ -#define IMR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */ -#define IMR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */ -#define IMR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */ -#define IMR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */ -#define IMR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */ -#define IMR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */ -#define IMR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */ -#define IMR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */ -#define IMR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */ -#define IMR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */ -#define IMR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */ -#define IMR_RER ((1 << 8)) /*Rx Error Interrupt */ -#define IMR_ROK ((1 << 7)) /*Receive OK Interrupt */ -#define IMR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */ -#define IMR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */ -#define IMR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */ -#define IMR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */ -#define IMR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */ -#define IMR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */ -#define IMR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */ -#define IMR_TMGDOK ((1 << 30)) -#define ISR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */ -#define ISR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */ -#define ISR_WakeInt ((1 << 23)) /*Wake Up Interrupt */ -#define ISR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */ -#define ISR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */ -#define ISR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */ -#define ISR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */ -#define ISR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */ -#define ISR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */ -#define ISR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */ -#define ISR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */ -#define ISR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */ -#define ISR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */ -#define ISR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */ -#define ISR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */ -#define ISR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */ -#define ISR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */ -#define ISR_RER ((1 << 8)) /*Rx Error Interrupt */ -#define ISR_ROK ((1 << 7)) /*Receive OK Interrupt */ -#define ISR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */ -#define ISR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */ -#define ISR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */ -#define ISR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */ -#define ISR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */ -#define ISR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */ -#define ISR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */ - -/* these definition is used for Tx/Rx test temporarily */ -#define ISR_TLPDER ISR_TVIDER -#define ISR_TLPDOK ISR_TVIDOK -#define ISR_TNPDER ISR_TVODER -#define ISR_TNPDOK ISR_TVODOK -#define ISR_TimeOut ISR_TimeOut1 -#define ISR_RXFOVW ISR_FOVW - - -#define HW_VERID_R8180_F 3 -#define HW_VERID_R8180_ABCD 2 -#define HW_VERID_R8185_ABC 4 -#define HW_VERID_R8185_D 5 -#define HW_VERID_R8185B_B 6 - -#define TCR_CWMIN ((1 << 31)) -#define TCR_SWSEQ ((1 << 30)) -#define TCR_HWVERID_MASK ((1 << 27)|(1 << 26)|(1 << 25)) -#define TCR_HWVERID_SHIFT 25 -#define TCR_SAT ((1 << 24)) -#define TCR_PLCP_LEN TCR_SAT /* rtl8180 */ -#define TCR_MXDMA_MASK ((1 << 23)|(1 << 22)|(1 << 21)) -#define TCR_MXDMA_1024 6 -#define TCR_MXDMA_2048 7 -#define TCR_MXDMA_SHIFT 21 -#define TCR_DISCW ((1 << 20)) -#define TCR_ICV ((1 << 19)) -#define TCR_LBK ((1 << 18)|(1 << 17)) -#define TCR_LBK1 ((1 << 18)) -#define TCR_LBK0 ((1 << 17)) -#define TCR_CRC ((1 << 16)) -#define TCR_DPRETRY_MASK ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)) -#define TCR_RTSRETRY_MASK ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7)) -#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 /* rtl8185 */ - -#define RCR_ONLYERLPKT ((1 << 31)) -#define RCR_CS_SHIFT 29 -#define RCR_CS_MASK ((1 << 30) | (1 << 29)) -#define RCR_ENMARP ((1 << 28)) -#define RCR_CBSSID ((1 << 23)) -#define RCR_APWRMGT ((1 << 22)) -#define RCR_ADD3 ((1 << 21)) -#define RCR_AMF ((1 << 20)) -#define RCR_ACF ((1 << 19)) -#define RCR_ADF ((1 << 18)) -#define RCR_RXFTH ((1 << 15)|(1 << 14)|(1 << 13)) -#define RCR_RXFTH2 ((1 << 15)) -#define RCR_RXFTH1 ((1 << 14)) -#define RCR_RXFTH0 ((1 << 13)) -#define RCR_AICV ((1 << 12)) -#define RCR_MXDMA ((1 << 10)|(1 << 9)|(1 << 8)) -#define RCR_MXDMA2 ((1 << 10)) -#define RCR_MXDMA1 ((1 << 9)) -#define RCR_MXDMA0 ((1 << 8)) -#define RCR_9356SEL ((1 << 6)) -#define RCR_ACRC32 ((1 << 5)) -#define RCR_AB ((1 << 3)) -#define RCR_AM ((1 << 2)) -#define RCR_APM ((1 << 1)) -#define RCR_AAP ((1 << 0)) - -#define CR9346_EEM ((1 << 7)|(1 << 6)) -#define CR9346_EEM1 ((1 << 7)) -#define CR9346_EEM0 ((1 << 6)) -#define CR9346_EECS ((1 << 3)) -#define CR9346_EESK ((1 << 2)) -#define CR9346_EED1 ((1 << 1)) -#define CR9346_EED0 ((1 << 0)) - -#define CONFIG3_PARM_En ((1 << 6)) -#define CONFIG3_FuncRegEn ((1 << 1)) - -#define CONFIG4_PWRMGT ((1 << 5)) - -#define MSR_LINK_MASK ((1 << 2)|(1 << 3)) -#define MSR_LINK_MANAGED 2 -#define MSR_LINK_NONE 0 -#define MSR_LINK_SHIFT 2 -#define MSR_LINK_ADHOC 1 -#define MSR_LINK_MASTER 3 - -#define BcnItv_BcnItv (0x01FF) - -#define AtimWnd_AtimWnd (0x01FF) - -#define BintrItv_BintrItv (0x01FF) - -#define FEMR_INTR ((1 << 15)) -#define FEMR_WKUP ((1 << 14)) -#define FEMR_GWAKE ((1 << 4)) - -#define FFER_INTR ((1 << 15)) -#define FFER_GWAKE ((1 << 4)) - -/* Three wire mode. */ -#define SW_THREE_WIRE 0 -#define HW_THREE_WIRE 2 -/* RTL8187S by amy */ -#define HW_THREE_WIRE_PI 5 -#define HW_THREE_WIRE_SI 6 -/* by amy */ -#define TCR_LRL_OFFSET 0 -#define TCR_SRL_OFFSET 8 -#define TCR_MXDMA_OFFSET 21 -#define TCR_DISReqQsize_OFFSET 28 -#define TCR_DurProcMode_OFFSET 30 - -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define AckTimeOutReg 0x79 /* ACK timeout register, in unit of 4 us. */ - -#define RFTiming 0x8C - -#define TPPollStop 0x93 - -#define TXAGC_CTL 0x9C /*< RJ_TODO_8185B> TX_AGC_CONTROL (0x9C seems be removed at 8185B, see p37). */ -#define CCK_TXAGC 0x9D -#define OFDM_TXAGC 0x9E -#define ANTSEL 0x9F - -#define ACM_CONTROL 0x00BF /* ACM Control Registe */ - -#define IntMig 0xE2 /* Interrupt Migration (0xE2 ~ 0xE3) */ - -#define TID_AC_MAP 0xE8 /* TID to AC Mapping Register */ - -#define ANAPARAM3 0xEE /* <RJ_TODO_8185B> How to use it? */ - -#define AC_VO_PARAM 0xF0 /* AC_VO Parameters Record */ -#define AC_VI_PARAM 0xF4 /* AC_VI Parameters Record */ -#define AC_BE_PARAM 0xF8 /* AC_BE Parameters Record */ -#define AC_BK_PARAM 0xFC /* AC_BK Parameters Record */ - -#define GPIOCtrl 0x16B /*GPIO Control Register. */ -#define ARFR 0x1E0 /* Auto Rate Fallback Register (0x1e0 ~ 0x1e2) */ - -#define RFSW_CTRL 0x272 /* 0x272-0x273. */ -#define SW_3W_DB0 0x274 /* Software 3-wire data buffer bit 31~0. */ -#define SW_3W_DB1 0x278 /* Software 3-wire data buffer bit 63~32. */ -#define SW_3W_CMD0 0x27C /* Software 3-wire Control/Status Register. */ -#define SW_3W_CMD1 0x27D /* Software 3-wire Control/Status Register. */ - -#define PI_DATA_READ 0X360 /* 0x360 - 0x361 Parallel Interface Data Register. */ -#define SI_DATA_READ 0x362 /* 0x362 - 0x363 Serial Interface Data Register. */ - -/* ----------------------------------------------------------------------------- - 8185B TPPollStop bits (offset 0x93, 1 byte) ----------------------------------------------------------------------------- -*/ -#define TPPOLLSTOP_BQ (0x01 << 7) -#define TPPOLLSTOP_AC_VIQ (0x01 << 4) - -#define MSR_LINK_ENEDCA (1<<4) - -/* ----------------------------------------------------------------------------- - 8187B AC_XX_PARAM bits ----------------------------------------------------------------------------- -*/ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -/* ----------------------------------------------------------------------------- - 8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte) ----------------------------------------------------------------------------- -*/ -#define VOQ_ACM_EN (0x01 << 7) /*BIT7 */ -#define VIQ_ACM_EN (0x01 << 6) /*BIT6 */ -#define BEQ_ACM_EN (0x01 << 5) /*BIT5 */ -#define ACM_HW_EN (0x01 << 4) /*BIT4 */ -#define VOQ_ACM_CTL (0x01 << 2) /*BIT2 */ /* Set to 1 when AC_VO used time reaches or exceeds the admitted time */ -#define VIQ_ACM_CTL (0x01 << 1) /*BIT1 */ /* Set to 1 when AC_VI used time reaches or exceeds the admitted time */ -#define BEQ_ACM_CTL (0x01 << 0) /*BIT0 */ /* Set to 1 when AC_BE used time reaches or exceeds the admitted time */ - - -/* ----------------------------------------------------------------------------- - 8185B SW_3W_CMD bits (Offset 0x27C-0x27D, 16bit) ----------------------------------------------------------------------------- -*/ -#define SW_3W_CMD0_HOLD ((1 << 7)) -#define SW_3W_CMD1_RE ((1 << 0)) /* BIT8 */ -#define SW_3W_CMD1_WE ((1 << 1)) /* BIT9 */ -#define SW_3W_CMD1_DONE ((1 << 2)) /* BIT10 */ - -#define BB_HOST_BANG_RW (1 << 3) - -/* ----------------------------------------------------------------------------- - 8185B RATE_FALLBACK_CTL bits (Offset 0xBE, 8bit) ----------------------------------------------------------------------------- -*/ -#define RATE_FALLBACK_CTL_ENABLE ((1 << 7)) -#define RATE_FALLBACK_CTL_ENABLE_RTSCTS ((1 << 6)) -/* Auto rate fallback per 2^n retry. */ -#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00 -#define RATE_FALLBACK_CTL_AUTO_STEP1 0x01 -#define RATE_FALLBACK_CTL_AUTO_STEP2 0x02 -#define RATE_FALLBACK_CTL_AUTO_STEP3 0x03 - - -#define RTL8225z2_ANAPARAM_OFF 0x55480658 -#define RTL8225z2_ANAPARAM2_OFF 0x72003f70 -/* by amy for power save */ -#define RF_CHANGE_BY_HW BIT30 -#define RF_CHANGE_BY_PS BIT29 -#define RF_CHANGE_BY_IPS BIT28 -/* by amy for power save */ -/* by amy for antenna */ -#define EEPROM_SW_REVD_OFFSET 0x3f - -/* BIT[8-9] is for SW Antenna Diversity. - * Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable. - */ -#define EEPROM_SW_AD_MASK 0x0300 -#define EEPROM_SW_AD_ENABLE 0x0100 - -/* BIT[10-11] determine if Antenna 1 is the Default Antenna. - * Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE. - */ -#define EEPROM_DEF_ANT_MASK 0x0C00 -#define EEPROM_DEF_ANT_1 0x0400 -/*by amy for antenna */ -/* {by amy 080312 */ -/* 0x7C, 0x7D Crystal calibration and Tx Power tracking mechanism. Added by Roger. 2007.12.10. */ -#define EEPROM_RSV 0x7C -#define EEPROM_XTAL_CAL_XOUT_MASK 0x0F /* 0x7C[3:0], Crystal calibration for Xout. */ -#define EEPROM_XTAL_CAL_XIN_MASK 0xF0 /* 0x7C[7:4], Crystal calibration for Xin. */ -#define EEPROM_THERMAL_METER_MASK 0x0F00 /* 0x7D[3:0], Thermal meter reference level. */ -#define EEPROM_XTAL_CAL_ENABLE 0x1000 /* 0x7D[4], Crystal calibration enabled/disabled BIT. */ -#define EEPROM_THERMAL_METER_ENABLE 0x2000 /* 0x7D[5], Thermal meter enabled/disabled BIT. */ -#define EN_LPF_CAL 0x238 /* Enable LPF Calibration. */ -#define PWR_METER_EN BIT1 -/* <RJ_TODO_8185B> where are false alarm counters in 8185B? */ -#define CCK_FALSE_ALARM 0xD0 -/* by amy 080312} */ - -/* YJ,add for Country IE, 080630 */ -#define EEPROM_COUNTRY_CODE 0x2E -/* YJ,add,080630,end */ - -#endif diff --git a/drivers/staging/rtl8187se/r8180_rtl8225.h b/drivers/staging/rtl8187se/r8180_rtl8225.h deleted file mode 100644 index 7df7392..0000000 --- a/drivers/staging/rtl8187se/r8180_rtl8225.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This is part of the rtl8180-sa2400 driver released under the GPL (See file - * COPYING for details). - * - * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> - * - * This files contains programming code for the rtl8225 radio frontend. - * - * *Many* thanks to Realtek Corp. for their great support! - */ - -#include "r8180.h" - -#define RTL8225_ANAPARAM_ON 0xa0000b59 -#define RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8225_ANAPARAM2_OFF 0x840dec11 -#define RTL8225_ANAPARAM2_ON 0x860dec11 -#define RTL8225_ANAPARAM_SLEEP 0xa00bab59 -#define RTL8225_ANAPARAM2_SLEEP 0x840dec11 - -void rtl8225z2_rf_init(struct net_device *dev); -void rtl8225z2_rf_set_chan(struct net_device *dev, short ch); -void rtl8225z2_rf_close(struct net_device *dev); - -void RF_WriteReg(struct net_device *dev, u8 offset, u16 data); -u16 RF_ReadReg(struct net_device *dev, u8 offset); - -void rtl8180_set_mode(struct net_device *dev, int mode); -void rtl8180_set_mode(struct net_device *dev, int mode); -bool SetZebraRFPowerState8185(struct net_device *dev, - enum rt_rf_power_state eRFPowerState); -void rtl8225z4_rf_sleep(struct net_device *dev); -void rtl8225z4_rf_wakeup(struct net_device *dev); - diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c deleted file mode 100644 index 47104fa..0000000 --- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * This is part of the rtl8180-sa2400 driver - * released under the GPL (See file COPYING for details). - * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> - * - * This files contains programming code for the rtl8225 - * radio frontend. - * - * *Many* thanks to Realtek Corp. for their great support! - */ - -#include "r8180_hw.h" -#include "r8180_rtl8225.h" -#include "r8180_93cx6.h" - -#include "ieee80211/dot11d.h" - -static void write_rtl8225(struct net_device *dev, u8 adr, u16 data) -{ - int i; - u16 out, select; - u8 bit; - u32 bangdata = (data << 4) | (adr & 0xf); - - out = read_nic_word(dev, RFPinsOutput) & 0xfff3; - - write_nic_word(dev, RFPinsEnable, - (read_nic_word(dev, RFPinsEnable) | 0x7)); - - select = read_nic_word(dev, RFPinsSelect); - - write_nic_word(dev, RFPinsSelect, select | 0x7 | - SW_CONTROL_GPIO); - - force_pci_posting(dev); - udelay(10); - - write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - - force_pci_posting(dev); - udelay(2); - - write_nic_word(dev, RFPinsOutput, out); - - force_pci_posting(dev); - udelay(10); - - for (i = 15; i >= 0; i--) { - bit = (bangdata & (1 << i)) >> i; - - write_nic_word(dev, RFPinsOutput, bit | out); - - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - - i--; - bit = (bangdata & (1 << i)) >> i; - - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - - write_nic_word(dev, RFPinsOutput, bit | out); - - } - - write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - - force_pci_posting(dev); - udelay(10); - - write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - - write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO); - - rtl8185_rf_pins_enable(dev); -} - -static const u8 rtl8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, - 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, - 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, - 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, - 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -}; - -static const u32 rtl8225_chan[] = { - 0, - 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, - 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A, -}; - -static const u8 rtl8225z2_gain_bg[] = { - 0x23, 0x15, 0xa5, /* -82-1dBm */ - 0x23, 0x15, 0xb5, /* -82-2dBm */ - 0x23, 0x15, 0xc5, /* -82-3dBm */ - 0x33, 0x15, 0xc5, /* -78dBm */ - 0x43, 0x15, 0xc5, /* -74dBm */ - 0x53, 0x15, 0xc5, /* -70dBm */ - 0x63, 0x15, 0xc5, /* -66dBm */ -}; - -static const u8 rtl8225z2_gain_a[] = { - 0x13, 0x27, 0x5a, /* -82dBm */ - 0x23, 0x23, 0x58, /* -82dBm */ - 0x33, 0x1f, 0x56, /* -82dBm */ - 0x43, 0x1b, 0x54, /* -78dBm */ - 0x53, 0x17, 0x51, /* -74dBm */ - 0x63, 0x24, 0x4f, /* -70dBm */ - 0x73, 0x0f, 0x4c, /* -66dBm */ -}; - -static const u16 rtl8225z2_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb - -}; - -static void rtl8225z2_set_gain(struct net_device *dev, short gain) -{ - const u8 *rtl8225_gain; - struct r8180_priv *priv = ieee80211_priv(dev); - u8 mode = priv->ieee80211->mode; - - if (mode == IEEE_B || mode == IEEE_G) - rtl8225_gain = rtl8225z2_gain_bg; - else - rtl8225_gain = rtl8225z2_gain_a; - - write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]); - write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]); - write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]); - write_phy_ofdm(dev, 0x21, 0x37); -} - -static u32 read_rtl8225(struct net_device *dev, u8 adr) -{ - u32 data2Write = ((u32)(adr & 0x1f)) << 27; - u32 dataRead; - u32 mask; - u16 oval, oval2, oval3, tmp; - int i; - short bit, rw; - u8 wLength = 6; - u8 rLength = 12; - u8 low2high = 0; - - oval = read_nic_word(dev, RFPinsOutput); - oval2 = read_nic_word(dev, RFPinsEnable); - oval3 = read_nic_word(dev, RFPinsSelect); - - write_nic_word(dev, RFPinsEnable, (oval2|0xf)); - write_nic_word(dev, RFPinsSelect, (oval3|0xf)); - - dataRead = 0; - - oval &= ~0xf; - - write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN); - udelay(4); - - write_nic_word(dev, RFPinsOutput, oval); - udelay(5); - - rw = 0; - - mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1)); - - for (i = 0; i < wLength/2; i++) { - bit = ((data2Write&mask) != 0) ? 1 : 0; - write_nic_word(dev, RFPinsOutput, bit | oval | rw); - udelay(1); - - write_nic_word(dev, RFPinsOutput, - bit | oval | BB_HOST_BANG_CLK | rw); - udelay(2); - write_nic_word(dev, RFPinsOutput, - bit | oval | BB_HOST_BANG_CLK | rw); - udelay(2); - - mask = (low2high) ? (mask<<1) : (mask>>1); - - if (i == 2) { - rw = BB_HOST_BANG_RW; - write_nic_word(dev, RFPinsOutput, - bit | oval | BB_HOST_BANG_CLK | rw); - udelay(2); - write_nic_word(dev, RFPinsOutput, bit | oval | rw); - udelay(2); - break; - } - - bit = ((data2Write&mask) != 0) ? 1 : 0; - - write_nic_word(dev, RFPinsOutput, - oval | bit | rw | BB_HOST_BANG_CLK); - udelay(2); - write_nic_word(dev, RFPinsOutput, - oval | bit | rw | BB_HOST_BANG_CLK); - udelay(2); - - write_nic_word(dev, RFPinsOutput, oval | bit | rw); - udelay(1); - - mask = (low2high) ? (mask<<1) : (mask>>1); - } - - write_nic_word(dev, RFPinsOutput, rw|oval); - udelay(2); - mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1)); - - /* - * We must set data pin to HW controlled, otherwise RF can't driver it - * and value RF register won't be able to read back properly. - */ - write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01))); - - for (i = 0; i < rLength; i++) { - write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1); - - write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); - udelay(2); - write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); - udelay(2); - write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); - udelay(2); - tmp = read_nic_word(dev, RFPinsInput); - - dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0); - - write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2); - - mask = (low2high) ? (mask<<1) : (mask>>1); - } - - write_nic_word(dev, RFPinsOutput, - BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval); - udelay(2); - - write_nic_word(dev, RFPinsEnable, oval2); - write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */ - write_nic_word(dev, RFPinsOutput, 0x3a0); - - return dataRead; -} - -void rtl8225z2_rf_close(struct net_device *dev) -{ - RF_WriteReg(dev, 0x4, 0x1f); - - force_pci_posting(dev); - mdelay(1); - - rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF); - rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF); -} - -/* - * Map dBm into Tx power index according to current HW model, for example, - * RF and PA, and current wireless mode. - */ -static s8 DbmToTxPwrIdx(struct r8180_priv *priv, - enum wireless_mode mode, s32 PowerInDbm) -{ - bool bUseDefault = true; - s8 TxPwrIdx = 0; - - /* - * OFDM Power in dBm = Index * 0.5 + 0 - * CCK Power in dBm = Index * 0.25 + 13 - */ - s32 tmp = 0; - - if (mode == WIRELESS_MODE_G) { - bUseDefault = false; - tmp = (2 * PowerInDbm); - - if (tmp < 0) - TxPwrIdx = 0; - else if (tmp > 40) /* 40 means 20 dBm. */ - TxPwrIdx = 40; - else - TxPwrIdx = (s8)tmp; - } else if (mode == WIRELESS_MODE_B) { - bUseDefault = false; - tmp = (4 * PowerInDbm) - 52; - - if (tmp < 0) - TxPwrIdx = 0; - else if (tmp > 28) /* 28 means 20 dBm. */ - TxPwrIdx = 28; - else - TxPwrIdx = (s8)tmp; - } - - /* - * TRUE if we want to use a default implementation. - * We shall set it to FALSE when we have exact translation formula - * for target IC. 070622, by rcnjko. - */ - if (bUseDefault) { - if (PowerInDbm < 0) - TxPwrIdx = 0; - else if (PowerInDbm > 35) - TxPwrIdx = 35; - else - TxPwrIdx = (u8)PowerInDbm; - } - - return TxPwrIdx; -} - -void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 max_cck_power_level; - u8 max_ofdm_power_level; - u8 min_ofdm_power_level; - char cck_power_level = (char)(0xff & priv->chtxpwr[ch]); - char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]); - - if (IS_DOT11D_ENABLE(priv->ieee80211) && - IS_DOT11D_STATE_DONE(priv->ieee80211)) { - u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch); - u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B, - MaxTxPwrInDbm); - u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G, - MaxTxPwrInDbm); - - if (cck_power_level > CckMaxPwrIdx) - cck_power_level = CckMaxPwrIdx; - if (ofdm_power_level > OfdmMaxPwrIdx) - ofdm_power_level = OfdmMaxPwrIdx; - } - - max_cck_power_level = 15; - max_ofdm_power_level = 25; - min_ofdm_power_level = 10; - - if (cck_power_level > 35) - cck_power_level = 35; - - write_nic_byte(dev, CCK_TXAGC, cck_power_level); - force_pci_posting(dev); - mdelay(1); - - if (ofdm_power_level > 35) - ofdm_power_level = 35; - - if (priv->up == 0) { - write_phy_ofdm(dev, 2, 0x42); - write_phy_ofdm(dev, 5, 0x00); - write_phy_ofdm(dev, 6, 0x40); - write_phy_ofdm(dev, 7, 0x00); - write_phy_ofdm(dev, 8, 0x40); - } - - write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level); - - if (ofdm_power_level <= 11) { - write_phy_ofdm(dev, 0x07, 0x5c); - write_phy_ofdm(dev, 0x09, 0x5c); - } - - if (ofdm_power_level <= 17) { - write_phy_ofdm(dev, 0x07, 0x54); - write_phy_ofdm(dev, 0x09, 0x54); - } else { - write_phy_ofdm(dev, 0x07, 0x50); - write_phy_ofdm(dev, 0x09, 0x50); - } - - force_pci_posting(dev); - mdelay(1); -} - -void rtl8225z2_rf_set_chan(struct net_device *dev, short ch) -{ - rtl8225z2_SetTXPowerLevel(dev, ch); - - RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); - - if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch]) - RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); - - mdelay(1); - - force_pci_posting(dev); - mdelay(10); -} - -static void rtl8225_host_pci_init(struct net_device *dev) -{ - write_nic_word(dev, RFPinsOutput, 0x480); - - rtl8185_rf_pins_enable(dev); - - write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO); - - write_nic_byte(dev, GP_ENABLE, 0); - - force_pci_posting(dev); - mdelay(200); - - /* bit 6 is for RF on/off detection */ - write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6))); -} - -void rtl8225z2_rf_init(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int i; - short channel = 1; - u16 brsr; - u32 data; - - priv->chan = channel; - - rtl8225_host_pci_init(dev); - - write_nic_dword(dev, RF_TIMING, 0x000a8008); - - brsr = read_nic_word(dev, BRSR); - - write_nic_word(dev, BRSR, 0xffff); - - write_nic_dword(dev, RF_PARA, 0x100044); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - write_nic_byte(dev, CONFIG3, 0x44); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - rtl8185_rf_pins_enable(dev); - - write_rtl8225(dev, 0x0, 0x2bf); mdelay(1); - write_rtl8225(dev, 0x1, 0xee0); mdelay(1); - write_rtl8225(dev, 0x2, 0x44d); mdelay(1); - write_rtl8225(dev, 0x3, 0x441); mdelay(1); - write_rtl8225(dev, 0x4, 0x8c3); mdelay(1); - write_rtl8225(dev, 0x5, 0xc72); mdelay(1); - write_rtl8225(dev, 0x6, 0xe6); mdelay(1); - write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1); - write_rtl8225(dev, 0x8, 0x3f); mdelay(1); - write_rtl8225(dev, 0x9, 0x335); mdelay(1); - write_rtl8225(dev, 0xa, 0x9d4); mdelay(1); - write_rtl8225(dev, 0xb, 0x7bb); mdelay(1); - write_rtl8225(dev, 0xc, 0x850); mdelay(1); - write_rtl8225(dev, 0xd, 0xcdf); mdelay(1); - write_rtl8225(dev, 0xe, 0x2b); mdelay(1); - write_rtl8225(dev, 0xf, 0x114); - - mdelay(100); - - write_rtl8225(dev, 0x0, 0x1b7); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - write_rtl8225(dev, 0x1, i + 1); - write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]); - } - - write_rtl8225(dev, 0x3, 0x80); - write_rtl8225(dev, 0x5, 0x4); - - write_rtl8225(dev, 0x0, 0xb7); - - write_rtl8225(dev, 0x2, 0xc4d); - - /* FIXME!! rtl8187 we have to check if calibrarion - * is successful and eventually cal. again (repeat - * the two write on reg 2) - */ - data = read_rtl8225(dev, 6); - if (!(data & 0x00000080)) { - write_rtl8225(dev, 0x02, 0x0c4d); - force_pci_posting(dev); mdelay(200); - write_rtl8225(dev, 0x02, 0x044d); - force_pci_posting(dev); mdelay(100); - data = read_rtl8225(dev, 6); - if (!(data & 0x00000080)) - DMESGW("RF Calibration Failed!!!!\n"); - } - - mdelay(200); - - write_rtl8225(dev, 0x0, 0x2bf); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - write_phy_ofdm(dev, 0xb, rtl8225_agc[i]); - mdelay(1); - - /* enable writing AGC table */ - write_phy_ofdm(dev, 0xa, i + 0x80); - mdelay(1); - } - - force_pci_posting(dev); - mdelay(1); - - write_phy_ofdm(dev, 0x00, 0x01); mdelay(1); - write_phy_ofdm(dev, 0x01, 0x02); mdelay(1); - write_phy_ofdm(dev, 0x02, 0x62); mdelay(1); - write_phy_ofdm(dev, 0x03, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x04, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x05, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x06, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x07, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x08, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1); - write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1); - write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1); - write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1); - write_phy_ofdm(dev, 0x0d, 0x43); - write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1); - write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1); - write_phy_ofdm(dev, 0x10, 0x84); mdelay(1); - write_phy_ofdm(dev, 0x11, 0x07); mdelay(1); - write_phy_ofdm(dev, 0x12, 0x20); mdelay(1); - write_phy_ofdm(dev, 0x13, 0x20); mdelay(1); - write_phy_ofdm(dev, 0x14, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x15, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x16, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x17, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x18, 0xef); mdelay(1); - write_phy_ofdm(dev, 0x19, 0x19); mdelay(1); - write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1); - write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1); - write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1); - write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1); - write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1); - write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1); - write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1); - write_phy_ofdm(dev, 0x21, 0x17); mdelay(1); - write_phy_ofdm(dev, 0x22, 0x16); mdelay(1); - write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */ - write_phy_ofdm(dev, 0x24, 0x46); mdelay(1); - write_phy_ofdm(dev, 0x25, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); - write_phy_ofdm(dev, 0x27, 0x88); mdelay(1); - - rtl8225z2_set_gain(dev, 4); - - write_phy_cck(dev, 0x0, 0x98); mdelay(1); - write_phy_cck(dev, 0x3, 0x20); mdelay(1); - write_phy_cck(dev, 0x4, 0x7e); mdelay(1); - write_phy_cck(dev, 0x5, 0x12); mdelay(1); - write_phy_cck(dev, 0x6, 0xfc); mdelay(1); - write_phy_cck(dev, 0x7, 0x78); mdelay(1); - write_phy_cck(dev, 0x8, 0x2e); mdelay(1); - write_phy_cck(dev, 0x10, 0x93); mdelay(1); - write_phy_cck(dev, 0x11, 0x88); mdelay(1); - write_phy_cck(dev, 0x12, 0x47); mdelay(1); - write_phy_cck(dev, 0x13, 0xd0); - write_phy_cck(dev, 0x19, 0x00); - write_phy_cck(dev, 0x1a, 0xa0); - write_phy_cck(dev, 0x1b, 0x08); - write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */ - write_phy_cck(dev, 0x41, 0x8d); mdelay(1); - write_phy_cck(dev, 0x42, 0x15); mdelay(1); - write_phy_cck(dev, 0x43, 0x18); mdelay(1); - write_phy_cck(dev, 0x44, 0x36); mdelay(1); - write_phy_cck(dev, 0x45, 0x35); mdelay(1); - write_phy_cck(dev, 0x46, 0x2e); mdelay(1); - write_phy_cck(dev, 0x47, 0x25); mdelay(1); - write_phy_cck(dev, 0x48, 0x1c); mdelay(1); - write_phy_cck(dev, 0x49, 0x12); mdelay(1); - write_phy_cck(dev, 0x4a, 0x09); mdelay(1); - write_phy_cck(dev, 0x4b, 0x04); mdelay(1); - write_phy_cck(dev, 0x4c, 0x05); mdelay(1); - - write_nic_byte(dev, 0x5b, 0x0d); mdelay(1); - - rtl8225z2_SetTXPowerLevel(dev, channel); - - /* RX antenna default to A */ - write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */ - write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */ - - rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */ - - /* switch to high-speed 3-wire - * last digit. 2 for both cck and ofdm - */ - write_nic_dword(dev, 0x94, 0x15c00002); - rtl8185_rf_pins_enable(dev); - - rtl8225z2_rf_set_chan(dev, priv->chan); -} - -#define MAX_DOZE_WAITING_TIMES_85B 20 -#define MAX_POLLING_24F_TIMES_87SE 10 -#define LPS_MAX_SLEEP_WAITING_TIMES_87SE 5 - -bool SetZebraRFPowerState8185(struct net_device *dev, - enum rt_rf_power_state eRFPowerState) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 btCR9346, btConfig3; - bool bActionAllowed = true, bTurnOffBB = true; - u8 u1bTmp; - int i; - bool bResult = true; - u8 QueueID; - - if (priv->SetRFPowerStateInProgress == true) - return false; - - priv->SetRFPowerStateInProgress = true; - - btCR9346 = read_nic_byte(dev, CR9346); - write_nic_byte(dev, CR9346, (btCR9346 | 0xC0)); - - btConfig3 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En)); - - switch (eRFPowerState) { - case RF_ON: - write_nic_word(dev, 0x37C, 0x00EC); - - /* turn on AFE */ - write_nic_byte(dev, 0x54, 0x00); - write_nic_byte(dev, 0x62, 0x00); - - /* turn on RF */ - RF_WriteReg(dev, 0x0, 0x009f); udelay(500); - RF_WriteReg(dev, 0x4, 0x0972); udelay(500); - - /* turn on RF again */ - RF_WriteReg(dev, 0x0, 0x009f); udelay(500); - RF_WriteReg(dev, 0x4, 0x0972); udelay(500); - - /* turn on BB */ - write_phy_ofdm(dev, 0x10, 0x40); - write_phy_ofdm(dev, 0x12, 0x40); - - /* Avoid power down at init time. */ - write_nic_byte(dev, CONFIG4, priv->RFProgType); - - u1bTmp = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6)))); - break; - case RF_SLEEP: - for (QueueID = 0, i = 0; QueueID < 6;) { - if (get_curr_tx_free_desc(dev, QueueID) == - priv->txringcount) { - QueueID++; - continue; - } else { - priv->TxPollingTimes++; - if (priv->TxPollingTimes >= - LPS_MAX_SLEEP_WAITING_TIMES_87SE) { - bActionAllowed = false; - break; - } else - udelay(10); - } - } - - if (bActionAllowed) { - /* turn off BB RXIQ matrix to cut off rx signal */ - write_phy_ofdm(dev, 0x10, 0x00); - write_phy_ofdm(dev, 0x12, 0x00); - - /* turn off RF */ - RF_WriteReg(dev, 0x4, 0x0000); - RF_WriteReg(dev, 0x0, 0x0000); - - /* turn off AFE except PLL */ - write_nic_byte(dev, 0x62, 0xff); - write_nic_byte(dev, 0x54, 0xec); - - mdelay(1); - - { - int i = 0; - while (true) { - u8 tmp24F = read_nic_byte(dev, 0x24f); - - if ((tmp24F == 0x01) || - (tmp24F == 0x09)) { - bTurnOffBB = true; - break; - } else { - udelay(10); - i++; - priv->TxPollingTimes++; - - if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) { - bTurnOffBB = false; - break; - } else - udelay(10); - } - } - } - - if (bTurnOffBB) { - /* turn off BB */ - u1bTmp = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, - (u1bTmp | BIT5 | BIT6)); - - /* turn off AFE PLL */ - write_nic_byte(dev, 0x54, 0xFC); - write_nic_word(dev, 0x37C, 0x00FC); - } - } - break; - case RF_OFF: - for (QueueID = 0, i = 0; QueueID < 6;) { - if (get_curr_tx_free_desc(dev, QueueID) == - priv->txringcount) { - QueueID++; - continue; - } else { - udelay(10); - i++; - } - - if (i >= MAX_DOZE_WAITING_TIMES_85B) - break; - } - - /* turn off BB RXIQ matrix to cut off rx signal */ - write_phy_ofdm(dev, 0x10, 0x00); - write_phy_ofdm(dev, 0x12, 0x00); - - /* turn off RF */ - RF_WriteReg(dev, 0x4, 0x0000); - RF_WriteReg(dev, 0x0, 0x0000); - - /* turn off AFE except PLL */ - write_nic_byte(dev, 0x62, 0xff); - write_nic_byte(dev, 0x54, 0xec); - - mdelay(1); - - { - int i = 0; - - while (true) { - u8 tmp24F = read_nic_byte(dev, 0x24f); - - if ((tmp24F == 0x01) || (tmp24F == 0x09)) { - bTurnOffBB = true; - break; - } else { - bTurnOffBB = false; - udelay(10); - i++; - } - - if (i > MAX_POLLING_24F_TIMES_87SE) - break; - } - } - - if (bTurnOffBB) { - /* turn off BB */ - u1bTmp = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6)); - - /* turn off AFE PLL (80M) */ - write_nic_byte(dev, 0x54, 0xFC); - write_nic_word(dev, 0x37C, 0x00FC); - } - break; - } - - btConfig3 &= ~(CONFIG3_PARM_En); - write_nic_byte(dev, CONFIG3, btConfig3); - - btCR9346 &= ~(0xC0); - write_nic_byte(dev, CR9346, btCR9346); - - if (bResult && bActionAllowed) - priv->eRFPowerState = eRFPowerState; - - priv->SetRFPowerStateInProgress = false; - - return bResult && bActionAllowed; -} - -void rtl8225z4_rf_sleep(struct net_device *dev) -{ - MgntActSet_RF_State(dev, RF_SLEEP, RF_CHANGE_BY_PS); -} - -void rtl8225z4_rf_wakeup(struct net_device *dev) -{ - MgntActSet_RF_State(dev, RF_ON, RF_CHANGE_BY_PS); -} diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c deleted file mode 100644 index b552491..0000000 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - This file contains wireless extension handlers. - - This is part of rtl8180 OpenSource driver. - Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com> - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part - of the official realtek driver. - - Parts of this driver are based on the rtl8180 driver skeleton - from Patric Schenke & Andres Salomon. - - Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. - - We want to thanks the Authors of those projects and the Ndiswrapper - project Authors. -*/ - - -#include "r8180.h" -#include "r8180_hw.h" - -#include <net/iw_handler.h> -#include "ieee80211/dot11d.h" - -static u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000, - 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000}; - -#define RATE_COUNT ARRAY_SIZE(rtl8180_rates) - -static struct rtl8187se_channel_list default_channel_plan[] = { - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19}, /* FCC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* IC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* ETSI */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* Spain. Change to ETSI. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* France. Change to ETSI. */ - {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9}, /* MKK */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22}, /* MKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* Israel */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17}, /* For 11a , TELEC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14} /* For Global Domain. 1-11:active scan, 12-14 passive scan.*/ /* +YJ, 080626 */ -}; -static int r8180_wx_get_freq(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b); -} - - -static int r8180_wx_set_key(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct iw_point *erq = &(wrqu->encoding); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (erq->length > 0) { - u32 *tkey = (u32 *) key; - priv->key0[0] = tkey[0]; - priv->key0[1] = tkey[1]; - priv->key0[2] = tkey[2]; - priv->key0[3] = tkey[3] & 0xff; - DMESG("Setting wep key to %x %x %x %x", - tkey[0], tkey[1], tkey[2], tkey[3]); - rtl8180_set_hw_wep(dev); - } - return 0; -} - - -static int r8180_wx_set_beaconinterval(struct net_device *dev, - struct iw_request_info *aa, - union iwreq_data *wrqu, char *b) -{ - int *parms = (int *)b; - int bi = parms[0]; - - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - DMESG("setting beacon interval to %x", bi); - - priv->ieee80211->current_network.beacon_interval = bi; - rtl8180_commit(dev); - up(&priv->wx_sem); - - return 0; -} - - - -static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b); -} - - - -static int r8180_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra); -} - - - -static int r8180_wx_set_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; -} - - -static int r8180_wx_set_crcmon(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int *parms = (int *)extra; - int enable = (parms[0] > 0); - short prev = priv->crcmon; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - if (enable) - priv->crcmon = 1; - else - priv->crcmon = 0; - - DMESG("bad CRC in monitor mode are %s", - priv->crcmon ? "accepted" : "rejected"); - - if (prev != priv->crcmon && priv->up) { - rtl8180_down(dev); - rtl8180_up(dev); - } - - up(&priv->wx_sem); - - return 0; -} - - -static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (priv->bInactivePs) { - if (wrqu->mode == IW_MODE_ADHOC) - IPSLeave(dev); - } - ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - return ret; -} - -/* YJ,add,080819,for hidden ap */ -struct iw_range_with_scan_capa { - /* Informative stuff (to choose between different interface) */ - - __u32 throughput; /* To give an idea... */ - - /* In theory this value should be the maximum benchmarked - * TCP/IP throughput, because with most of these devices the - * bit rate is meaningless (overhead an co) to estimate how - * fast the connection will go and pick the fastest one. - * I suggest people to play with Netperf or any benchmark... - */ - - /* NWID (or domain id) */ - __u32 min_nwid; /* Minimal NWID we are able to set */ - __u32 max_nwid; /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ - __u16 old_num_channels; - __u8 old_num_frequency; - - /* Scan capabilities */ - __u8 scan_capa; -}; -/* YJ,add,080819,for hidden ap */ - - -static int rtl8180_wx_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - struct r8180_priv *priv = ieee80211_priv(dev); - u16 val; - int i; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - /* Let's try to keep this struct in the same order as in - * linux/include/wireless.h - */ - - /* TODO: See what values we can set, and remove the ones we can't - * set, or fill them with some default data. - */ - - /* ~5 Mb/s real (802.11b) */ - range->throughput = 5 * 1000 * 1000; - - /* TODO: Not used in 802.11b? */ -/* range->min_nwid; */ /* Minimal NWID we are able to set */ - /* TODO: Not used in 802.11b? */ -/* range->max_nwid; */ /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ -/* range->old_num_channels; */ -/* range->old_num_frequency; */ -/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */ - if (priv->rf_set_sens != NULL) - range->sensitivity = priv->max_sens; /* signal level threshold range */ - - range->max_qual.qual = 100; - /* TODO: Find real max RSSI and stick here */ - range->max_qual.level = 0; - range->max_qual.noise = -98; - range->max_qual.updated = 7; /* Updated all three */ - - range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ - range->avg_qual.level = 20 + -98; - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - - range->num_bitrates = RATE_COUNT; - - for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) - range->bitrate[i] = rtl8180_rates[i]; - - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->pm_capa = 0; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; - - range->num_channels = 14; - - for (i = 0, val = 0; i < 14; i++) { - - /* Include only legal frequencies for some countries */ - if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { - range->freq[val].i = i + 1; - range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; - range->freq[val].e = 1; - val++; - } else { - /* FIXME: do we need to set anything for channels */ - /* we don't use ? */ - } - - if (val == IW_MAX_FREQUENCIES) - break; - } - - range->num_frequency = val; - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - return 0; -} - - -static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - struct ieee80211_device *ieee = priv->ieee80211; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct iw_scan_req *req = (struct iw_scan_req *)b; - if (req->essid_len) { - ieee->current_network.ssid_len = req->essid_len; - memcpy(ieee->current_network.ssid, req->essid, req->essid_len); - } - } - - down(&priv->wx_sem); - if (priv->up) { - priv->ieee80211->actscanning = true; - if (priv->bInactivePs && (priv->ieee80211->state != IEEE80211_LINKED)) { - IPSLeave(dev); - ieee80211_softmac_ips_scan_syncro(priv->ieee80211); - ret = 0; - } else { - /* prevent scan in BusyTraffic */ - /* FIXME: Need to consider last scan time */ - if ((priv->link_detect.b_busy_traffic) && (true)) { - ret = 0; - printk("Now traffic is busy, please try later!\n"); - } else - /* prevent scan in BusyTraffic,end */ - ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b); - } - } else - ret = -1; - - up(&priv->wx_sem); - - return ret; -} - - -static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - down(&priv->wx_sem); - if (priv->up) - ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b); - else - ret = -1; - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_set_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - int ret; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (priv->bInactivePs) - IPSLeave(dev); - - ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_get_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - down(&priv->wx_sem); - - ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - - return ret; -} - - -static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); -} - -static int r8180_wx_set_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (wrqu->frag.disabled) - priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; - else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) - return -EINVAL; - - priv->ieee80211->fts = wrqu->frag.value & ~0x1; - } - - return 0; -} - - -static int r8180_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - wrqu->frag.value = priv->ieee80211->fts; - wrqu->frag.fixed = 0; /* no auto select */ - wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); - - return 0; -} - - -static int r8180_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra); - - up(&priv->wx_sem); - return ret; - -} - - -static int r8180_wx_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra); -} - - -static int r8180_wx_set_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); - - if (priv->hw_wep) - ret = r8180_wx_set_key(dev, info, wrqu, key); - else { - DMESG("Setting SW wep key"); - ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key); - } - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_get_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); -} - - -static int r8180_wx_set_scan_type(struct net_device *dev, - struct iw_request_info *aa, - union iwreq_data *wrqu, char *p) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - int *parms = (int *)p; - int mode = parms[0]; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - priv->ieee80211->active_scan = mode; - - return 1; -} - -static int r8180_wx_set_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int err = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - if (wrqu->retry.flags & IW_RETRY_LIFETIME || - wrqu->retry.disabled) { - err = -EINVAL; - goto exit; - } - if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { - err = -EINVAL; - goto exit; - } - - if (wrqu->retry.value > R8180_MAX_RETRY) { - err = -EINVAL; - goto exit; - } - if (wrqu->retry.flags & IW_RETRY_MAX) { - priv->retry_rts = wrqu->retry.value; - DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); - - } else { - priv->retry_data = wrqu->retry.value; - DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); - } - - /* FIXME ! - * We might try to write directly the TX config register - * or to restart just the (R)TX process. - * I'm unsure if whole reset is really needed - */ - - rtl8180_commit(dev); -exit: - up(&priv->wx_sem); - - return err; -} - -static int r8180_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - wrqu->retry.disabled = 0; /* can't be disabled */ - - if ((wrqu->retry.flags & IW_RETRY_TYPE) == - IW_RETRY_LIFETIME) - return -EINVAL; - - if (wrqu->retry.flags & IW_RETRY_MAX) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - wrqu->retry.value = priv->retry_rts; - } else { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - wrqu->retry.value = priv->retry_data; - } - - return 0; -} - -static int r8180_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - if (priv->rf_set_sens == NULL) - return -1; /* we have not this support for this radio */ - wrqu->sens.value = priv->sens; - return 0; -} - - -static int r8180_wx_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - - short err = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (priv->rf_set_sens == NULL) { - err = -1; /* we have not this support for this radio */ - goto exit; - } - if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) - priv->sens = wrqu->sens.value; - else - err = -EINVAL; - -exit: - up(&priv->wx_sem); - - return err; -} - - -static int r8180_wx_set_rawtx(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; - -} - -static int r8180_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - down(&priv->wx_sem); - - ret = ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; -} - -static int r8180_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - printk("=>>>>>>>>>>=============================>set power:%d, %d!\n", wrqu->power.disabled, wrqu->power.flags); - if (wrqu->power.disabled == 0) { - wrqu->power.flags |= IW_POWER_ALL_R; - wrqu->power.flags |= IW_POWER_TIMEOUT; - wrqu->power.value = 1000; - } - - ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; -} - -static int r8180_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (wrqu->rts.disabled) - priv->rts = DEFAULT_RTS_THRESHOLD; - else { - if (wrqu->rts.value < MIN_RTS_THRESHOLD || - wrqu->rts.value > MAX_RTS_THRESHOLD) - return -EINVAL; - - priv->rts = wrqu->rts.value; - } - - return 0; -} -static int r8180_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - - wrqu->rts.value = priv->rts; - wrqu->rts.fixed = 0; /* no auto select */ - wrqu->rts.disabled = (wrqu->rts.value == 0); - - return 0; -} -static int dummy(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - return -1; -} - -static int r8180_wx_get_iwmode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee; - int ret = 0; - - - - down(&priv->wx_sem); - - ieee = priv->ieee80211; - - strcpy(extra, "802.11"); - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - strcat(extra, "b"); - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strcat(extra, "/g"); - } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strcat(extra, "g"); - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_set_iwmode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - int *param = (int *)extra; - int ret = 0; - int modulation = 0, mode = 0; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - if (*param == 1) { - modulation |= IEEE80211_CCK_MODULATION; - mode = IEEE_B; - printk(KERN_INFO "B mode!\n"); - } else if (*param == 2) { - modulation |= IEEE80211_OFDM_MODULATION; - mode = IEEE_G; - printk(KERN_INFO "G mode!\n"); - } else if (*param == 3) { - modulation |= IEEE80211_CCK_MODULATION; - modulation |= IEEE80211_OFDM_MODULATION; - mode = IEEE_B|IEEE_G; - printk(KERN_INFO "B/G mode!\n"); - } - - if (ieee->proto_started) { - ieee80211_stop_protocol(ieee); - ieee->mode = mode; - ieee->modulation = modulation; - ieee80211_start_protocol(ieee); - } else { - ieee->mode = mode; - ieee->modulation = modulation; - } - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - - down(&priv->wx_sem); - - - - *extra = (char) priv->plcp_preamble_mode; /* 0:auto 1:short 2:long */ - up(&priv->wx_sem); - - return 0; -} -static int r8180_wx_set_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (*extra < 0 || *extra > 2) - ret = -1; - else - priv->plcp_preamble_mode = *((short *)extra); - - - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_get_siglevel(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - - - down(&priv->wx_sem); - /* Modify by hikaru 6.5 */ - *((int *)extra) = priv->wstats.qual.level;/*for interface test ,it should be the priv->wstats.qual.level; */ - - - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_get_sigqual(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - - - down(&priv->wx_sem); - /* Modify by hikaru 6.5 */ - *((int *)extra) = priv->wstats.qual.qual;/* for interface test ,it should be the priv->wstats.qual.qual; */ - - - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_reset_stats(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - down(&priv->wx_sem); - - priv->stats.txrdu = 0; - priv->stats.rxrdu = 0; - priv->stats.rxnolast = 0; - priv->stats.rxnodata = 0; - priv->stats.rxnopointer = 0; - priv->stats.txnperr = 0; - priv->stats.txresumed = 0; - priv->stats.rxerr = 0; - priv->stats.rxoverflow = 0; - priv->stats.rxint = 0; - - priv->stats.txnpokint = 0; - priv->stats.txhpokint = 0; - priv->stats.txhperr = 0; - priv->stats.ints = 0; - priv->stats.shints = 0; - priv->stats.txoverflow = 0; - priv->stats.rxdmafail = 0; - priv->stats.txbeacon = 0; - priv->stats.txbeaconerr = 0; - priv->stats.txlpokint = 0; - priv->stats.txlperr = 0; - priv->stats.txretry = 0;/* 20060601 */ - priv->stats.rxcrcerrmin = 0 ; - priv->stats.rxcrcerrmid = 0; - priv->stats.rxcrcerrmax = 0; - priv->stats.rxicverr = 0; - - up(&priv->wx_sem); - - return 0; - -} -static int r8180_wx_radio_on(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); - priv->rf_wakeup(dev); - - up(&priv->wx_sem); - - return 0; - -} - -static int r8180_wx_radio_off(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); - priv->rf_sleep(dev); - - up(&priv->wx_sem); - - return 0; - -} -static int r8180_wx_get_channelplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - - down(&priv->wx_sem); - *extra = priv->channel_plan; - - - - up(&priv->wx_sem); - - return 0; -} -static int r8180_wx_set_channelplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int *val = (int *)extra; - int i; - printk("-----in fun %s\n", __func__); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - /* unsigned long flags; */ - down(&priv->wx_sem); - if (default_channel_plan[*val].len != 0) { - priv->channel_plan = *val; - /* Clear old channel map 8 */ - for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) - GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0; - - /* Set new channel map */ - for (i = 1; i <= default_channel_plan[*val].len; i++) - GET_DOT11D_INFO(priv->ieee80211)->channel_map[default_channel_plan[*val].channel[i-1]] = 1; - - } - up(&priv->wx_sem); - - return 0; -} - -static int r8180_wx_get_version(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - /* struct ieee80211_device *ieee; */ - - down(&priv->wx_sem); - strcpy(extra, "1020.0808"); - up(&priv->wx_sem); - - return 0; -} - -/* added by amy 080818 */ -/*receive datarate from user typing valid rate is from 2 to 108 (1 - 54M), if input 0, return to normal rate adaptive. */ -static int r8180_wx_set_forcerate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 forcerate = *extra; - - down(&priv->wx_sem); - - printk("==============>%s(): forcerate is %d\n", __func__, forcerate); - if ((forcerate == 2) || (forcerate == 4) || (forcerate == 11) || (forcerate == 22) || (forcerate == 12) || - (forcerate == 18) || (forcerate == 24) || (forcerate == 36) || (forcerate == 48) || (forcerate == 72) || - (forcerate == 96) || (forcerate == 108)) { - priv->ForcedDataRate = 1; - priv->ieee80211->rate = forcerate * 5; - } else if (forcerate == 0) { - priv->ForcedDataRate = 0; - printk("OK! return rate adaptive\n"); - } else - printk("ERR: wrong rate\n"); - up(&priv->wx_sem); - return 0; -} - -static int r8180_wx_set_enc_ext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - - int ret = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); - up(&priv->wx_sem); - return ret; - -} -static int r8180_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - ret = ieee80211_wx_set_auth(priv->ieee80211, info, &wrqu->param, extra); - up(&priv->wx_sem); - return ret; -} - -static int r8180_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); -#if 1 - ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); -#endif - up(&priv->wx_sem); - return ret; -} -static int r8180_wx_set_gen_ie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); -#if 1 - ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length); -#endif - up(&priv->wx_sem); - return ret; - - -} - -static const iw_handler r8180_wx_handlers[] = { - IW_HANDLER(SIOCGIWNAME, r8180_wx_get_name), - IW_HANDLER(SIOCSIWNWID, dummy), - IW_HANDLER(SIOCGIWNWID, dummy), - IW_HANDLER(SIOCSIWFREQ, r8180_wx_set_freq), - IW_HANDLER(SIOCGIWFREQ, r8180_wx_get_freq), - IW_HANDLER(SIOCSIWMODE, r8180_wx_set_mode), - IW_HANDLER(SIOCGIWMODE, r8180_wx_get_mode), - IW_HANDLER(SIOCSIWSENS, r8180_wx_set_sens), - IW_HANDLER(SIOCGIWSENS, r8180_wx_get_sens), - IW_HANDLER(SIOCGIWRANGE, rtl8180_wx_get_range), - IW_HANDLER(SIOCSIWSPY, dummy), - IW_HANDLER(SIOCGIWSPY, dummy), - IW_HANDLER(SIOCSIWAP, r8180_wx_set_wap), - IW_HANDLER(SIOCGIWAP, r8180_wx_get_wap), - IW_HANDLER(SIOCSIWMLME, r8180_wx_set_mlme), - IW_HANDLER(SIOCGIWAPLIST, dummy), /* deprecated */ - IW_HANDLER(SIOCSIWSCAN, r8180_wx_set_scan), - IW_HANDLER(SIOCGIWSCAN, r8180_wx_get_scan), - IW_HANDLER(SIOCSIWESSID, r8180_wx_set_essid), - IW_HANDLER(SIOCGIWESSID, r8180_wx_get_essid), - IW_HANDLER(SIOCSIWNICKN, dummy), - IW_HANDLER(SIOCGIWNICKN, dummy), - IW_HANDLER(SIOCSIWRATE, r8180_wx_set_rate), - IW_HANDLER(SIOCGIWRATE, r8180_wx_get_rate), - IW_HANDLER(SIOCSIWRTS, r8180_wx_set_rts), - IW_HANDLER(SIOCGIWRTS, r8180_wx_get_rts), - IW_HANDLER(SIOCSIWFRAG, r8180_wx_set_frag), - IW_HANDLER(SIOCGIWFRAG, r8180_wx_get_frag), - IW_HANDLER(SIOCSIWTXPOW, dummy), - IW_HANDLER(SIOCGIWTXPOW, dummy), - IW_HANDLER(SIOCSIWRETRY, r8180_wx_set_retry), - IW_HANDLER(SIOCGIWRETRY, r8180_wx_get_retry), - IW_HANDLER(SIOCSIWENCODE, r8180_wx_set_enc), - IW_HANDLER(SIOCGIWENCODE, r8180_wx_get_enc), - IW_HANDLER(SIOCSIWPOWER, r8180_wx_set_power), - IW_HANDLER(SIOCGIWPOWER, r8180_wx_get_power), - IW_HANDLER(SIOCSIWGENIE, r8180_wx_set_gen_ie), - IW_HANDLER(SIOCSIWAUTH, r8180_wx_set_auth), - IW_HANDLER(SIOCSIWENCODEEXT, r8180_wx_set_enc_ext), -}; - -static const struct iw_priv_args r8180_private_args[] = { - { - SIOCIWFIRSTPRIV + 0x0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" - }, - { SIOCIWFIRSTPRIV + 0x1, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x2, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beaconint" - }, - { SIOCIWFIRSTPRIV + 0x3, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" - - }, - { SIOCIWFIRSTPRIV + 0x5, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x6, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" - - }, - { SIOCIWFIRSTPRIV + 0x7, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x8, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setiwmode" - }, - { - SIOCIWFIRSTPRIV + 0x9, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getiwmode" - }, - { - SIOCIWFIRSTPRIV + 0xA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpreamble" - }, - { - SIOCIWFIRSTPRIV + 0xB, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpreamble" - }, - { SIOCIWFIRSTPRIV + 0xC, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0xD, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrssi" - }, - { SIOCIWFIRSTPRIV + 0xE, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0xF, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getlinkqual" - }, - { - SIOCIWFIRSTPRIV + 0x10, - 0, 0, "resetstats" - }, - { - SIOCIWFIRSTPRIV + 0x11, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0x12, - 0, 0, "radioon" - }, - { - SIOCIWFIRSTPRIV + 0x13, - 0, 0, "radiooff" - }, - { - SIOCIWFIRSTPRIV + 0x14, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setchannel" - }, - { - SIOCIWFIRSTPRIV + 0x15, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel" - }, - { - SIOCIWFIRSTPRIV + 0x16, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0x17, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getversion" - }, - { - SIOCIWFIRSTPRIV + 0x18, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrate" - }, -}; - - -static iw_handler r8180_private_handler[] = { - r8180_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ - dummy, - r8180_wx_set_beaconinterval, - dummy, - /* r8180_wx_set_monitor_type, */ - r8180_wx_set_scan_type, - dummy, - r8180_wx_set_rawtx, - dummy, - r8180_wx_set_iwmode, - r8180_wx_get_iwmode, - r8180_wx_set_preamble, - r8180_wx_get_preamble, - dummy, - r8180_wx_get_siglevel, - dummy, - r8180_wx_get_sigqual, - r8180_wx_reset_stats, - dummy,/* r8180_wx_get_stats */ - r8180_wx_radio_on, - r8180_wx_radio_off, - r8180_wx_set_channelplan, - r8180_wx_get_channelplan, - dummy, - r8180_wx_get_version, - r8180_wx_set_forcerate, -}; - -static inline int is_same_network(struct ieee80211_network *src, - struct ieee80211_network *dst, - struct ieee80211_device *ieee) -{ - /* A network is only a duplicate if the channel, BSSID, ESSID - * and the capability field (in particular IBSS and BSS) all match. - * We treat all <hidden> with the same BSSID and channel - * as one network - */ - if (src->channel != dst->channel) - return 0; - - if (memcmp(src->bssid, dst->bssid, ETH_ALEN) != 0) - return 0; - - if (ieee->iw_mode != IW_MODE_INFRA) { - if (src->ssid_len != dst->ssid_len) - return 0; - if (memcmp(src->ssid, dst->ssid, src->ssid_len) != 0) - return 0; - } - - if ((src->capability & WLAN_CAPABILITY_IBSS) != - (dst->capability & WLAN_CAPABILITY_IBSS)) - return 0; - if ((src->capability & WLAN_CAPABILITY_BSS) != - (dst->capability & WLAN_CAPABILITY_BSS)) - return 0; - - return 1; -} - -/* WB modified to show signal to GUI on 18-01-2008 */ -static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - struct iw_statistics *wstats = &priv->wstats; - int tmp_level = 0; - int tmp_qual = 0; - int tmp_noise = 0; - - if (ieee->state < IEEE80211_LINKED) { - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; - } - - tmp_level = (&ieee->current_network)->stats.signal; - tmp_qual = (&ieee->current_network)->stats.signalstrength; - tmp_noise = (&ieee->current_network)->stats.noise; - - wstats->qual.level = tmp_level; - wstats->qual.qual = tmp_qual; - wstats->qual.noise = tmp_noise; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; -} - -struct iw_handler_def r8180_wx_handlers_def = { - .standard = r8180_wx_handlers, - .num_standard = ARRAY_SIZE(r8180_wx_handlers), - .private = r8180_private_handler, - .num_private = ARRAY_SIZE(r8180_private_handler), - .num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args), - .get_wireless_stats = r8180_get_wireless_stats, - .private_args = (struct iw_priv_args *)r8180_private_args, -}; - - diff --git a/drivers/staging/rtl8187se/r8180_wx.h b/drivers/staging/rtl8187se/r8180_wx.h deleted file mode 100644 index d471520..0000000 --- a/drivers/staging/rtl8187se/r8180_wx.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - This is part of rtl8180 OpenSource driver - v 0.3 - Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com> - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part of the official realtek driver - Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon - Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver - - We want to thanks the Authors of such projects and the Ndiswrapper project Authors. -*/ - -/* this file (will) contains wireless extension handlers*/ - -#ifndef R8180_WX_H -#define R8180_WX_H -#include <linux/wireless.h> -#include "ieee80211/ieee80211.h" -extern struct iw_handler_def r8180_wx_handlers_def; - -#endif diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c deleted file mode 100644 index cc6f100..0000000 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ /dev/null @@ -1,1464 +0,0 @@ -/* - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * Module Name: - * r8185b_init.c - * - * Abstract: - * Hardware Initialization and Hardware IO for RTL8185B - * - * Major Change History: - * When Who What - * ---------- --------------- ------------------------------- - * 2006-11-15 Xiong Created - * - * Notes: - * This file is ported from RTL8185B Windows driver. - * - * - */ - -/*--------------------------Include File------------------------------------*/ -#include <linux/spinlock.h> -#include "r8180_hw.h" -#include "r8180.h" -#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */ -#include "r8180_93cx6.h" /* Card EEPROM */ -#include "r8180_wx.h" -#include "ieee80211/dot11d.h" -/* #define CONFIG_RTL8180_IO_MAP */ -#define TC_3W_POLL_MAX_TRY_CNT 5 - -static u8 MAC_REG_TABLE[][2] = { - /* - * PAGE 0: - * 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in - * HwConfigureRTL8185() - * 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185(). - * 0x1F0~0x1F8 set in MacConfig_85BASIC() - */ - {0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42}, - {0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03}, - {0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03}, - {0x94, 0x0F}, {0x95, 0x32}, - {0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00}, - {0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32}, - {0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4}, - {0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00}, - {0xff, 0x00}, - - /* - * PAGE 1: - * For Flextronics system Logo PCIHCT failure: - * 0x1C4~0x1CD set no-zero value to avoid PCI configuration - * space 0x45[7]=1 - */ - {0x5e, 0x01}, - {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24}, - {0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF}, - {0x82, 0xFF}, {0x83, 0x03}, - /* lzm add 080826 */ - {0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22}, - /* lzm add 080826 */ - {0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22}, - {0xe2, 0x00}, - - - /* PAGE 2: */ - {0x5e, 0x02}, - {0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5}, - {0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff}, - {0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08}, - {0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f}, - {0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f}, - {0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff}, - {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00}, - - /* PAGE 0: */ - {0x5e, 0x00}, {0x9f, 0x03} - }; - - -static u8 ZEBRA_AGC[] = { - 0, - 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, - 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x48, 0x47, 0x46, 0x45, - 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07, - 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x17, 0x18, 0x18, - 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, - 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, - 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F - }; - -static u32 ZEBRA_RF_RX_GAIN_TABLE[] = { - 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6, - 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057, - 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3, - 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3, - 0x0183, 0x0163, 0x0143, 0x0123, 0x0103 - }; - -static u8 OFDM_CONFIG[] = { - /* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */ - /* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */ - /* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */ - /* 0x00 */ - 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, - /* 0x10 */ - 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26, - 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB, - /* 0x20 */ - 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00, - 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00, - /* 0x30 */ - 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e, - 0xD8, 0x3C, 0x7B, 0x10, 0x10 - }; - - /*--------------------------------------------------------------- - * Hardware IO - * the code is ported from Windows source code - *--------------------------------------------------------------- - */ - -static u8 PlatformIORead1Byte(struct net_device *dev, u32 offset) -{ - return read_nic_byte(dev, offset); -} - -static void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data) -{ - write_nic_byte(dev, offset, data); - /* - * To make sure write operation is completed, - * 2005.11.09, by rcnjko. - */ - read_nic_byte(dev, offset); -} - -static void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data) -{ - write_nic_word(dev, offset, data); - /* - * To make sure write operation is completed, - * 2005.11.09, by rcnjko. - */ - read_nic_word(dev, offset); -} - -static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data) -{ - if (offset == PhyAddr) { - /* For Base Band configuration. */ - unsigned char cmdByte; - unsigned long dataBytes; - unsigned char idx; - u8 u1bTmp; - - cmdByte = (u8)(data & 0x000000ff); - dataBytes = data>>8; - - /* - * 071010, rcnjko: - * The critical section is only BB read/write race - * condition. Assumption: - * 1. We assume NO one will access BB at DIRQL, otherwise, - * system will crash for - * acquiring the spinlock in such context. - * 2. PlatformIOWrite4Byte() MUST NOT be recursive. - */ - /* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */ - - for (idx = 0; idx < 30; idx++) { - /* Make sure command bit is clear before access it. */ - u1bTmp = PlatformIORead1Byte(dev, PhyAddr); - if ((u1bTmp & BIT7) == 0) - break; - else - mdelay(10); - } - - for (idx = 0; idx < 3; idx++) - PlatformIOWrite1Byte(dev, offset+1+idx, - ((u8 *)&dataBytes)[idx]); - - write_nic_byte(dev, offset, cmdByte); - - /* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */ - } else { - write_nic_dword(dev, offset, data); - /* - * To make sure write operation is completed, 2005.11.09, - * by rcnjko. - */ - read_nic_dword(dev, offset); - } -} - -static void SetOutputEnableOfRfPins(struct net_device *dev) -{ - write_nic_word(dev, RFPinsEnable, 0x1bff); -} - -static bool HwHSSIThreeWire(struct net_device *dev, - u8 *pDataBuf, - bool write) -{ - u8 TryCnt; - u8 u1bTmp; - - /* Check if WE and RE are cleared. */ - for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) { - u1bTmp = read_nic_byte(dev, SW_3W_CMD1); - if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0) - break; - - udelay(10); - } - if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) { - netdev_err(dev, - "HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", - u1bTmp); - return false; - } - - /* RTL8187S HSSI Read/Write Function */ - u1bTmp = read_nic_byte(dev, RF_SW_CONFIG); - u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */ - write_nic_byte(dev, RF_SW_CONFIG, u1bTmp); - - /* jong: HW SI read must set reg84[3]=0. */ - u1bTmp = read_nic_byte(dev, RFPinsSelect); - u1bTmp &= ~BIT3; - write_nic_byte(dev, RFPinsSelect, u1bTmp); - /* Fill up data buffer for write operation. */ - - /* SI - reg274[3:0] : RF register's Address */ - if (write) - write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf)); - else - write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf)); - - /* Set up command: WE or RE. */ - if (write) - write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE); - else - write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE); - - - /* Check if DONE is set. */ - for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) { - u1bTmp = read_nic_byte(dev, SW_3W_CMD1); - if (u1bTmp & SW_3W_CMD1_DONE) - break; - - udelay(10); - } - - write_nic_byte(dev, SW_3W_CMD1, 0); - - /* Read back data for read operation. */ - if (!write) { - /* Serial Interface : reg363_362[11:0] */ - *((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ); - *((u16 *)pDataBuf) &= 0x0FFF; - } - - return true; -} - -void RF_WriteReg(struct net_device *dev, u8 offset, u16 data) -{ - u16 reg = (data << 4) | (offset & 0x0f); - HwHSSIThreeWire(dev, (u8 *)®, true); -} - -u16 RF_ReadReg(struct net_device *dev, u8 offset) -{ - u16 reg = offset & 0x0f; - HwHSSIThreeWire(dev, (u8 *)®, false); - return reg; -} - -static u8 ReadBBPortUchar(struct net_device *dev, u32 addr) -{ - PlatformIOWrite4Byte(dev, PhyAddr, addr & 0xffffff7f); - return PlatformIORead1Byte(dev, PhyDataR); -} - -/* by Owen on 04/07/14 for writing BB register successfully */ -static void WriteBBPortUchar(struct net_device *dev, u32 Data) -{ - PlatformIOWrite4Byte(dev, PhyAddr, Data); - ReadBBPortUchar(dev, Data); -} - -/* - * Description: - * Perform Antenna settings with antenna diversity on 87SE. - * Created by Roger, 2008.01.25. - */ -bool SetAntennaConfig87SE(struct net_device *dev, - u8 DefaultAnt, /* 0: Main, 1: Aux. */ - bool bAntDiversity) /* 1:Enable, 0: Disable. */ -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bAntennaSwitched = true; - /* 0x00 = disabled, 0x80 = enabled */ - u8 ant_diversity_offset = 0x00; - - /* - * printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n", - * DefaultAnt, bAntDiversity); - */ - - /* Threshold for antenna diversity. */ - write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */ - - if (bAntDiversity) /* Enable Antenna Diversity. */ - ant_diversity_offset = 0x80; - - if (DefaultAnt == 1) { /* aux Antenna */ - /* Mac register, aux antenna */ - write_nic_byte(dev, ANTSEL, 0x00); - - /* Config CCK RX antenna. */ - write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */ - - /* Reg01 : 47 | ant_diversity_offset */ - write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset); - - /* Config OFDM RX antenna. */ - write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */ - /* Reg18 : 32 */ - write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset); - } else { /* main Antenna */ - /* Mac register, main antenna */ - write_nic_byte(dev, ANTSEL, 0x03); - - /* Config CCK RX antenna. */ - write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */ - /* Reg01 : 47 */ - write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset); - - /* Config OFDM RX antenna. */ - write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */ - /*Reg18 : 32 */ - write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset); - } - priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */ - return bAntennaSwitched; -} -/* - *-------------------------------------------------------------- - * Hardware Initialization. - * the code is ported from Windows source code - *-------------------------------------------------------------- - */ - -static void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev) -{ - - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 i; - u32 addr, data; - u32 u4bRegOffset, u4bRegValue; - u16 u4bRF23, u4bRF24; - u8 u1b24E; - int d_cut = 0; - - -/* - *=========================================================================== - * 87S_PCIE :: RADIOCFG.TXT - *=========================================================================== - */ - - - /* Page1 : reg16-reg30 */ - RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); /* switch to page1 */ - u4bRF23 = RF_ReadReg(dev, 0x08); mdelay(1); - u4bRF24 = RF_ReadReg(dev, 0x09); mdelay(1); - - if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) { - d_cut = 1; - netdev_info(dev, "card type changed from C- to D-cut\n"); - } - - /* Page0 : reg0-reg15 */ - - RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);/* 1 */ - RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1); - RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);/* 2 */ - RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);/* 3 */ - RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); - RF_WriteReg(dev, 0x05, 0x0c72); mdelay(1); - RF_WriteReg(dev, 0x06, 0x0ae6); mdelay(1); - RF_WriteReg(dev, 0x07, 0x00ca); mdelay(1); - RF_WriteReg(dev, 0x08, 0x0e1c); mdelay(1); - RF_WriteReg(dev, 0x09, 0x02f0); mdelay(1); - RF_WriteReg(dev, 0x0a, 0x09d0); mdelay(1); - RF_WriteReg(dev, 0x0b, 0x01ba); mdelay(1); - RF_WriteReg(dev, 0x0c, 0x0640); mdelay(1); - RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); - RF_WriteReg(dev, 0x0e, 0x0020); mdelay(1); - RF_WriteReg(dev, 0x0f, 0x0990); mdelay(1); - - /* Page1 : reg16-reg30 */ - RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); - RF_WriteReg(dev, 0x03, 0x0806); mdelay(1); - RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1); - RF_WriteReg(dev, 0x05, 0x059b); mdelay(1); - RF_WriteReg(dev, 0x06, 0x0081); mdelay(1); - RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1); -/* - * Don't write RF23/RF24 to make a difference between 87S C cut and D cut. - * asked by SD3 stevenl. - */ - RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1); - RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1); - - if (d_cut) { - RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1); - RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); - /* RX LO buffer */ - RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1); - } else { - RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1); - RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); - /* RX LO buffer */ - RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1); - } - - RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1); - RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1); /* 6 */ - RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1); - RF_WriteReg(dev, 0x04, 0x0e50); mdelay(1); - - for (i = 0; i <= 36; i++) { - RF_WriteReg(dev, 0x01, i); mdelay(1); - RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1); - } - - RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /* 203, 343 */ - RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); /* 400 */ - /* switch to reg16-reg30, and HSSI disable 137 */ - RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* Z4 synthesizer loop filter setting, 392 */ - RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* switch to reg0-reg15, and HSSI disable */ - RF_WriteReg(dev, 0x00, 0x0037); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* CBC on, Tx Rx disable, High gain */ - RF_WriteReg(dev, 0x04, 0x0160); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* Z4 setted channel 1 */ - RF_WriteReg(dev, 0x07, 0x0080); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - RF_WriteReg(dev, 0x02, 0x088D); mdelay(1); /* LC calibration */ - mdelay(200); /* Deay 200 ms. */ /* 0xfd */ - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* switch to reg16-reg30 137, and HSSI disable 137 */ - RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - RF_WriteReg(dev, 0x07, 0x0000); mdelay(1); - RF_WriteReg(dev, 0x07, 0x0180); mdelay(1); - RF_WriteReg(dev, 0x07, 0x0220); mdelay(1); - RF_WriteReg(dev, 0x07, 0x03E0); mdelay(1); - - /* DAC calibration off 20070702 */ - RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1); - RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1); - /* For crystal calibration, added by Roger, 2007.12.11. */ - if (priv->bXtalCalibration) { /* reg 30. */ - /* - * enable crystal calibration. - * RF Reg[30], (1)Xin:[12:9], Xout:[8:5], addr[4:0]. - * (2)PA Pwr delay timer[15:14], default: 2.4us, - * set BIT15=0 - * (3)RF signal on/off when calibration[13], default: on, - * set BIT13=0. - * So we should minus 4 BITs offset. - */ - RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | - (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1); - netdev_info(dev, "ZEBRA_Config_85BASIC_HardCode(): (%02x)\n", - (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | - BIT11 | BIT9); - } else { - /* using default value. Xin=6, Xout=6. */ - RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1); - } - /* switch to reg0-reg15, and HSSI enable */ - RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1); - /* Rx BB start calibration, 00c//+edward */ - RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); - /* temperature meter off */ - RF_WriteReg(dev, 0x02, 0x004d); mdelay(1); - RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); /* Rx mode */ - mdelay(10); /* Deay 10 ms.*/ /* 0xfe */ - mdelay(10); /* Deay 10 ms.*/ /* 0xfe */ - mdelay(10); /* Deay 10 ms.*/ /* 0xfe */ - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x00, 0x0197); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x00, 0x009f); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x01, 0x0000); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x02, 0x0000); mdelay(1); - /* power save parameters. */ - u1b24E = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6)))); - - /*====================================================================== - * - *====================================================================== - * CCKCONF.TXT - *====================================================================== - * - * [POWER SAVE] Power Saving Parameters by jong. 2007-11-27 - * CCK reg0x00[7]=1'b1 :power saving for TX (default) - * CCK reg0x00[6]=1'b1: power saving for RX (default) - * CCK reg0x06[4]=1'b1: turn off channel estimation related - * circuits if not doing channel estimation. - * CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1 - * CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0 - */ - - write_phy_cck(dev, 0x00, 0xc8); - write_phy_cck(dev, 0x06, 0x1c); - write_phy_cck(dev, 0x10, 0x78); - write_phy_cck(dev, 0x2e, 0xd0); - write_phy_cck(dev, 0x2f, 0x06); - write_phy_cck(dev, 0x01, 0x46); - - /* power control */ - write_nic_byte(dev, CCK_TXAGC, 0x10); - write_nic_byte(dev, OFDM_TXAGC, 0x1B); - write_nic_byte(dev, ANTSEL, 0x03); - - - - /* - *====================================================================== - * AGC.txt - *====================================================================== - */ - - write_phy_ofdm(dev, 0x00, 0x12); - - for (i = 0; i < 128; i++) { - - data = ZEBRA_AGC[i+1]; - data = data << 8; - data = data | 0x0000008F; - - addr = i + 0x80; /* enable writing AGC table */ - addr = addr << 8; - addr = addr | 0x0000008E; - - WriteBBPortUchar(dev, data); - WriteBBPortUchar(dev, addr); - WriteBBPortUchar(dev, 0x0000008E); - } - - PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080); /* Annie, 2006-05-05 */ - - /* - *====================================================================== - * - *====================================================================== - * OFDMCONF.TXT - *====================================================================== - */ - - for (i = 0; i < 60; i++) { - u4bRegOffset = i; - u4bRegValue = OFDM_CONFIG[i]; - - WriteBBPortUchar(dev, - (0x00000080 | - (u4bRegOffset & 0x7f) | - ((u4bRegValue & 0xff) << 8))); - } - - /* - *====================================================================== - * by amy for antenna - *====================================================================== - */ - /* - * Config Sw/Hw Combinational Antenna Diversity. Added by Roger, - * 2008.02.26. - */ - SetAntennaConfig87SE(dev, priv->bDefaultAntenna1, - priv->bSwAntennaDiverity); -} - - -void UpdateInitialGain(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - /* lzm add 080826 */ - if (priv->eRFPowerState != RF_ON) { - /* Don't access BB/RF under disable PLL situation. - * RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain - - * pHalData->eRFPowerState!=RF_ON\n")); - * Back to the original state - */ - priv->InitialGain = priv->InitialGainBackUp; - return; - } - - switch (priv->InitialGain) { - case 1: /* m861dBm */ - write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1); - break; - - case 2: /* m862dBm */ - write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1); - break; - - case 3: /* m863dBm */ - write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1); - break; - - case 4: /* m864dBm */ - write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1); - break; - - case 5: /* m82dBm */ - write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1); - break; - - case 6: /* m78dBm */ - write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1); - break; - - case 7: /* m74dBm */ - write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); - write_phy_ofdm(dev, 0x24, 0xa6); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1); - break; - - case 8: - write_phy_ofdm(dev, 0x17, 0x66); mdelay(1); - write_phy_ofdm(dev, 0x24, 0xb6); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1); - break; - - default: /* MP */ - write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1); - break; - } -} -/* - * Description: - * Tx Power tracking mechanism routine on 87SE. - * Created by Roger, 2007.12.11. - */ -static void InitTxPwrTracking87SE(struct net_device *dev) -{ - u32 u4bRfReg; - - u4bRfReg = RF_ReadReg(dev, 0x02); - - /* Enable Thermal meter indication. */ - RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN); mdelay(1); -} - -static void PhyConfig8185(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - write_nic_dword(dev, RCR, priv->ReceiveConfig); - priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03; - /* RF config */ - ZEBRA_Config_85BASIC_HardCode(dev); - /* Set default initial gain state to 4, approved by SD3 DZ, by Bruce, - * 2007-06-06. - */ - if (priv->bDigMechanism) { - if (priv->InitialGain == 0) - priv->InitialGain = 4; - } - - /* - * Enable thermal meter indication to implement TxPower tracking - * on 87SE. We initialize thermal meter here to avoid unsuccessful - * configuration. Added by Roger, 2007.12.11. - */ - if (priv->bTxPowerTrack) - InitTxPwrTracking87SE(dev); - - priv->InitialGainBackUp = priv->InitialGain; - UpdateInitialGain(dev); - - return; -} - -static void HwConfigureRTL8185(struct net_device *dev) -{ - /* - * RTL8185_TODO: Determine Retrylimit, TxAGC, - * AutoRateFallback control. - */ - u8 bUNIVERSAL_CONTROL_RL = 0; - u8 bUNIVERSAL_CONTROL_AGC = 1; - u8 bUNIVERSAL_CONTROL_ANT = 1; - u8 bAUTO_RATE_FALLBACK_CTL = 1; - u8 val8; - write_nic_word(dev, BRSR, 0x0fff); - /* Retry limit */ - val8 = read_nic_byte(dev, CW_CONF); - - if (bUNIVERSAL_CONTROL_RL) - val8 = val8 & 0xfd; - else - val8 = val8 | 0x02; - - write_nic_byte(dev, CW_CONF, val8); - - /* Tx AGC */ - val8 = read_nic_byte(dev, TXAGC_CTL); - if (bUNIVERSAL_CONTROL_AGC) { - write_nic_byte(dev, CCK_TXAGC, 128); - write_nic_byte(dev, OFDM_TXAGC, 128); - val8 = val8 & 0xfe; - } else { - val8 = val8 | 0x01; - } - - - write_nic_byte(dev, TXAGC_CTL, val8); - - /* Tx Antenna including Feedback control */ - val8 = read_nic_byte(dev, TXAGC_CTL); - - if (bUNIVERSAL_CONTROL_ANT) { - write_nic_byte(dev, ANTSEL, 0x00); - val8 = val8 & 0xfd; - } else { - val8 = val8 & (val8|0x02); /* xiong-2006-11-15 */ - } - - write_nic_byte(dev, TXAGC_CTL, val8); - - /* Auto Rate fallback control */ - val8 = read_nic_byte(dev, RATE_FALLBACK); - val8 &= 0x7c; - if (bAUTO_RATE_FALLBACK_CTL) { - val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1; - - /* <RJ_TODO_8185B> We shall set up the ARFR according - * to user's setting. - */ - PlatformIOWrite2Byte(dev, ARFR, 0x0fff); /* set 1M ~ 54Mbps. */ - } - write_nic_byte(dev, RATE_FALLBACK, val8); -} - -static void MacConfig_85BASIC_HardCode(struct net_device *dev) -{ - /* - *====================================================================== - * MACREG.TXT - *====================================================================== - */ - int nLinesRead = 0; - u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0; - int i; - - nLinesRead = sizeof(MAC_REG_TABLE)/2; - - for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */ - u4bRegOffset = MAC_REG_TABLE[i][0]; - u4bRegValue = MAC_REG_TABLE[i][1]; - - if (u4bRegOffset == 0x5e) - u4bPageIndex = u4bRegValue; - else - u4bRegOffset |= (u4bPageIndex << 8); - - write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue); - } - /* ================================================================= */ -} - -static void MacConfig_85BASIC(struct net_device *dev) -{ - - u8 u1DA; - MacConfig_85BASIC_HardCode(dev); - - /* ================================================================= */ - - /* Follow TID_AC_MAP of WMac. */ - write_nic_word(dev, TID_AC_MAP, 0xfa50); - - /* Interrupt Migration, Jong suggested we use set 0x0000 first, - * 2005.12.14, by rcnjko. - */ - write_nic_word(dev, IntMig, 0x0000); - - /* Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. */ - PlatformIOWrite4Byte(dev, 0x1F0, 0x00000000); - PlatformIOWrite4Byte(dev, 0x1F4, 0x00000000); - PlatformIOWrite1Byte(dev, 0x1F8, 0x00); - - /* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */ - - /* - * power save parameter based on - * "87SE power save parameters 20071127.doc", as follow. - */ - - /* Enable DA10 TX power saving */ - u1DA = read_nic_byte(dev, PHYPR); - write_nic_byte(dev, PHYPR, (u1DA | BIT2)); - - /* POWER: */ - write_nic_word(dev, 0x360, 0x1000); - write_nic_word(dev, 0x362, 0x1000); - - /* AFE. */ - write_nic_word(dev, 0x370, 0x0560); - write_nic_word(dev, 0x372, 0x0560); - write_nic_word(dev, 0x374, 0x0DA4); - write_nic_word(dev, 0x376, 0x0DA4); - write_nic_word(dev, 0x378, 0x0560); - write_nic_word(dev, 0x37A, 0x0560); - write_nic_word(dev, 0x37C, 0x00EC); - write_nic_word(dev, 0x37E, 0x00EC); /* +edward */ - write_nic_byte(dev, 0x24E, 0x01); -} - -static u8 GetSupportedWirelessMode8185(struct net_device *dev) -{ - return WIRELESS_MODE_B | WIRELESS_MODE_G; -} - -static void -ActUpdateChannelAccessSetting(struct net_device *dev, - enum wireless_mode mode, - struct chnl_access_setting *chnl_access_setting) -{ - AC_CODING eACI; - - /* - * <RJ_TODO_8185B> - * TODO: We still don't know how to set up these registers, - * just follow WMAC to verify 8185B FPAG. - * - * <RJ_TODO_8185B> - * Jong said CWmin/CWmax register are not functional in 8185B, - * so we shall fill channel access realted register into AC - * parameter registers, - * even in nQBss. - */ - - /* Suggested by Jong, 2005.12.08. */ - chnl_access_setting->sifs_timer = 0x22; - chnl_access_setting->difs_timer = 0x1C; /* 2006.06.02, by rcnjko. */ - chnl_access_setting->slot_time_timer = 9; /* 2006.06.02, by rcnjko. */ - /* - * Suggested by wcchu, it is the default value of EIFS register, - * 2005.12.08. - */ - chnl_access_setting->eifs_timer = 0x5B; - chnl_access_setting->cwmin_index = 3; /* 2006.06.02, by rcnjko. */ - chnl_access_setting->cwmax_index = 7; /* 2006.06.02, by rcnjko. */ - - write_nic_byte(dev, SIFS, chnl_access_setting->sifs_timer); - /* - * Rewrited from directly use PlatformEFIOWrite1Byte(), - * by Annie, 2006-03-29. - */ - write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer); - - write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer); - - /* - * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS - * register, 2005.12.08. - */ - write_nic_byte(dev, AckTimeOutReg, 0x5B); - - for (eACI = 0; eACI < AC_MAX; eACI++) - write_nic_byte(dev, ACM_CONTROL, 0); -} - -static void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - u8 btSupportedWirelessMode = GetSupportedWirelessMode8185(dev); - - if ((btWirelessMode & btSupportedWirelessMode) == 0) { - /* - * Don't switch to unsupported wireless mode, 2006.02.15, - * by rcnjko. - */ - DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n", - btWirelessMode, btSupportedWirelessMode); - return; - } - - /* 1. Assign wireless mode to switch if necessary. */ - if (btWirelessMode == WIRELESS_MODE_AUTO) { - if ((btSupportedWirelessMode & WIRELESS_MODE_A)) { - btWirelessMode = WIRELESS_MODE_A; - } else if (btSupportedWirelessMode & WIRELESS_MODE_G) { - btWirelessMode = WIRELESS_MODE_G; - - } else if ((btSupportedWirelessMode & WIRELESS_MODE_B)) { - btWirelessMode = WIRELESS_MODE_B; - } else { - DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n", - btSupportedWirelessMode); - btWirelessMode = WIRELESS_MODE_B; - } - } - - /* - * 2. Swtich band: RF or BB specific actions, - * for example, refresh tables in omc8255, or change initial gain if - * necessary. Nothing to do for Zebra to switch band. Update current - * wireless mode if we switch to specified band successfully. - */ - - ieee->mode = (enum wireless_mode)btWirelessMode; - - /* 3. Change related setting. */ - if (ieee->mode == WIRELESS_MODE_A) - DMESG("WIRELESS_MODE_A\n"); - else if (ieee->mode == WIRELESS_MODE_B) - DMESG("WIRELESS_MODE_B\n"); - else if (ieee->mode == WIRELESS_MODE_G) - DMESG("WIRELESS_MODE_G\n"); - - ActUpdateChannelAccessSetting(dev, ieee->mode, - &priv->ChannelAccessSetting); -} - -void rtl8185b_irq_enable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - priv->irq_enabled = 1; - write_nic_dword(dev, IMR, priv->IntrMask); -} - -static void MgntDisconnectIBSS(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 i; - - for (i = 0; i < 6; i++) - priv->ieee80211->current_network.bssid[i] = 0x55; - - - - priv->ieee80211->state = IEEE80211_NOLINK; - /* - * Stop Beacon. - * - * Vista add a Adhoc profile, HW radio off until - * OID_DOT11_RESET_REQUEST Driver would set MSR=NO_LINK, - * then HW Radio ON, MgntQueue Stuck. Because Bcn DMA isn't - * complete, mgnt queue would stuck until Bcn packet send. - * - * Disable Beacon Queue Own bit, suggested by jong - */ - ieee80211_stop_send_beacons(priv->ieee80211); - - priv->ieee80211->link_change(dev); - notify_wx_assoc_event(priv->ieee80211); -} - -static void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 i; - - SendDisassociation(priv->ieee80211, asSta, asRsn); - - if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) { - /* ShuChen TODO: change media status. */ - - for (i = 0; i < 6; i++) - priv->ieee80211->current_network.bssid[i] = 0x22; - - ieee80211_disassociate(priv->ieee80211); - } -} - -static void MgntDisconnectAP(struct net_device *dev, u8 asRsn) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - /* - * Commented out by rcnjko, 2005.01.27: - * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE(). - * - * 2004/09/15, kcwu, the key should be cleared, or the new - * handshaking will not success - * - * In WPA WPA2 need to Clear all key ... because new key will set - * after new handshaking. 2004.10.11, by rcnjko. - */ - MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid, - asRsn); - - priv->ieee80211->state = IEEE80211_NOLINK; -} - -static bool MgntDisconnect(struct net_device *dev, u8 asRsn) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - /* - * Schedule an workitem to wake up for ps mode, 070109, by rcnjko. - */ - - if (IS_DOT11D_ENABLE(priv->ieee80211)) - Dot11d_Reset(priv->ieee80211); - /* In adhoc mode, update beacon frame. */ - if (priv->ieee80211->state == IEEE80211_LINKED) { - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - MgntDisconnectIBSS(dev); - - if (priv->ieee80211->iw_mode == IW_MODE_INFRA) { - /* - * We clear key here instead of MgntDisconnectAP() - * because that MgntActSet_802_11_DISASSOCIATE() - * is an interface called by OS, e.g. - * OID_802_11_DISASSOCIATE in Windows while as - * MgntDisconnectAP() is used to handle - * disassociation related things to AP, e.g. send - * Disassoc frame to AP. 2005.01.27, by rcnjko. - */ - MgntDisconnectAP(dev, asRsn); - } - /* Indicate Disconnect, 2005.02.23, by rcnjko. */ - } - return true; -} -/* - * Description: - * Chang RF Power State. - * Note that, only MgntActSet_RF_State() is allowed to set - * HW_VAR_RF_STATE. - * - * Assumption: - * PASSIVE LEVEL. - */ -static bool SetRFPowerState(struct net_device *dev, - enum rt_rf_power_state eRFPowerState) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bResult = false; - - if (eRFPowerState == priv->eRFPowerState) - return bResult; - - bResult = SetZebraRFPowerState8185(dev, eRFPowerState); - - return bResult; -} - -bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet, - u32 ChangeSource) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bActionAllowed = false; - bool bConnectBySSID = false; - enum rt_rf_power_state rtState; - u16 RFWaitCounter = 0; - unsigned long flag; - /* - * Prevent the race condition of RF state change. By Bruce, - * 2007-11-28. Only one thread can change the RF state at one time, - * and others should wait to be executed. - */ - while (true) { - spin_lock_irqsave(&priv->rf_ps_lock, flag); - if (priv->RFChangeInProgress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - /* Set RF after the previous action is done. */ - while (priv->RFChangeInProgress) { - RFWaitCounter++; - udelay(1000); /* 1 ms */ - - /* - * Wait too long, return FALSE to avoid - * to be stuck here. - */ - if (RFWaitCounter > 1000) { /* 1sec */ - netdev_info(dev, "MgntActSet_RF_State(): Wait too long to set RF\n"); - /* TODO: Reset RF state? */ - return false; - } - } - } else { - priv->RFChangeInProgress = true; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - break; - } - } - rtState = priv->eRFPowerState; - - switch (StateToSet) { - case RF_ON: - /* - * Turn On RF no matter the IPS setting because we need to - * update the RF state to Ndis under Vista, or the Windows - * does not allow the driver to perform site survey any - * more. By Bruce, 2007-10-02. - */ - priv->RfOffReason &= (~ChangeSource); - - if (!priv->RfOffReason) { - priv->RfOffReason = 0; - bActionAllowed = true; - - if (rtState == RF_OFF && - ChangeSource >= RF_CHANGE_BY_HW) - bConnectBySSID = true; - } - break; - - case RF_OFF: - /* 070125, rcnjko: we always keep connected in AP mode. */ - - if (priv->RfOffReason > RF_CHANGE_BY_IPS) { - /* - * 060808, Annie: - * Disconnect to current BSS when radio off. - * Asked by QuanTa. - * - * Calling MgntDisconnect() instead of - * MgntActSet_802_11_DISASSOCIATE(), because - * we do NOT need to set ssid to dummy ones. - */ - MgntDisconnect(dev, disas_lv_ss); - /* - * Clear content of bssDesc[] and bssDesc4Query[] - * to avoid reporting old bss to UI. - */ - } - - priv->RfOffReason |= ChangeSource; - bActionAllowed = true; - break; - case RF_SLEEP: - priv->RfOffReason |= ChangeSource; - bActionAllowed = true; - break; - default: - break; - } - - if (bActionAllowed) { - /* Config HW to the specified mode. */ - SetRFPowerState(dev, StateToSet); - } - - /* Release RF spinlock */ - spin_lock_irqsave(&priv->rf_ps_lock, flag); - priv->RFChangeInProgress = false; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - return bActionAllowed; -} - -static void InactivePowerSave(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - /* - * This flag "bSwRfProcessing", indicates the status of IPS - * procedure, should be set if the IPS workitem is really - * scheduled. The old code, sets this flag before scheduling the - * IPS workitem and however, at the same time the previous IPS - * workitem did not end yet, fails to schedule the current - * workitem. Thus, bSwRfProcessing blocks the IPS procedure of - * switching RF. - */ - priv->bSwRfProcessing = true; - - MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS); - - /* - * To solve CAM values miss in RF OFF, rewrite CAM values after - * RF ON. By Bruce, 2007-09-20. - */ - - priv->bSwRfProcessing = false; -} - -/* - * Description: - * Enter the inactive power save mode. RF will be off - */ -void IPSEnter(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - enum rt_rf_power_state rtState; - if (priv->bInactivePs) { - rtState = priv->eRFPowerState; - - /* - * Do not enter IPS in the following conditions: - * (1) RF is already OFF or - * Sleep (2) bSwRfProcessing (indicates the IPS is still - * under going) (3) Connected (only disconnected can - * trigger IPS)(4) IBSS (send Beacon) - * (5) AP mode (send Beacon) - */ - if (rtState == RF_ON && !priv->bSwRfProcessing - && (priv->ieee80211->state != IEEE80211_LINKED)) { - priv->eInactivePowerState = RF_OFF; - InactivePowerSave(dev); - } - } -} -void IPSLeave(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - enum rt_rf_power_state rtState; - if (priv->bInactivePs) { - rtState = priv->eRFPowerState; - if ((rtState == RF_OFF || rtState == RF_SLEEP) && - !priv->bSwRfProcessing - && priv->RfOffReason <= RF_CHANGE_BY_IPS) { - priv->eInactivePowerState = RF_ON; - InactivePowerSave(dev); - } - } -} - -void rtl8185b_adapter_start(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - u8 SupportedWirelessMode; - u8 InitWirelessMode; - u8 bInvalidWirelessMode = 0; - u8 tmpu8; - u8 btCR9346; - u8 TmpU1b; - u8 btPSR; - - write_nic_byte(dev, 0x24e, (BIT5|BIT6|BIT0)); - rtl8180_reset(dev); - - priv->dma_poll_mask = 0; - priv->dma_poll_stop_mask = 0; - - HwConfigureRTL8185(dev); - write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]); - write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff); - /* default network type to 'No Link' */ - write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); - write_nic_word(dev, BcnItv, 100); - write_nic_word(dev, AtimWnd, 2); - PlatformIOWrite2Byte(dev, FEMR, 0xFFFF); - write_nic_byte(dev, WPA_CONFIG, 0); - MacConfig_85BASIC(dev); - /* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, - * by rcnjko. - */ - /* BT_DEMO_BOARD type */ - PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a); - - /* - *--------------------------------------------------------------------- - * Set up PHY related. - *--------------------------------------------------------------------- - */ - /* Enable Config3.PARAM_En to revise AnaaParm. */ - write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */ - tmpu8 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En)); - /* Turn on Analog power. */ - /* Asked for by William, otherwise, MAC 3-wire can't work, - * 2006.06.27, by rcnjko. - */ - write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON); - write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON); - write_nic_word(dev, ANAPARAM3, 0x0010); - - write_nic_byte(dev, CONFIG3, tmpu8); - write_nic_byte(dev, CR9346, 0x00); - /* enable EEM0 and EEM1 in 9346CR */ - btCR9346 = read_nic_byte(dev, CR9346); - write_nic_byte(dev, CR9346, (btCR9346 | 0xC0)); - - /* B cut use LED1 to control HW RF on/off */ - TmpU1b = read_nic_byte(dev, CONFIG5); - TmpU1b = TmpU1b & ~BIT3; - write_nic_byte(dev, CONFIG5, TmpU1b); - - /* disable EEM0 and EEM1 in 9346CR */ - btCR9346 &= ~(0xC0); - write_nic_byte(dev, CR9346, btCR9346); - - /* Enable Led (suggested by Jong) */ - /* B-cut RF Radio on/off 5e[3]=0 */ - btPSR = read_nic_byte(dev, PSR); - write_nic_byte(dev, PSR, (btPSR | BIT3)); - /* setup initial timing for RFE. */ - write_nic_word(dev, RFPinsOutput, 0x0480); - SetOutputEnableOfRfPins(dev); - write_nic_word(dev, RFPinsSelect, 0x2488); - - /* PHY config. */ - PhyConfig8185(dev); - - /* - * We assume RegWirelessMode has already been initialized before, - * however, we has to validate the wireless mode here and provide a - * reasonable initialized value if necessary. 2005.01.13, - * by rcnjko. - */ - SupportedWirelessMode = GetSupportedWirelessMode8185(dev); - if ((ieee->mode != WIRELESS_MODE_B) && - (ieee->mode != WIRELESS_MODE_G) && - (ieee->mode != WIRELESS_MODE_A) && - (ieee->mode != WIRELESS_MODE_AUTO)) { - /* It should be one of B, G, A, or AUTO. */ - bInvalidWirelessMode = 1; - } else { - /* One of B, G, A, or AUTO. */ - /* Check if the wireless mode is supported by RF. */ - if ((ieee->mode != WIRELESS_MODE_AUTO) && - (ieee->mode & SupportedWirelessMode) == 0) { - bInvalidWirelessMode = 1; - } - } - - if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) { - /* Auto or other invalid value. */ - /* Assigne a wireless mode to initialize. */ - if ((SupportedWirelessMode & WIRELESS_MODE_A)) { - InitWirelessMode = WIRELESS_MODE_A; - } else if ((SupportedWirelessMode & WIRELESS_MODE_G)) { - InitWirelessMode = WIRELESS_MODE_G; - } else if ((SupportedWirelessMode & WIRELESS_MODE_B)) { - InitWirelessMode = WIRELESS_MODE_B; - } else { - DMESGW("InitializeAdapter8185(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", - SupportedWirelessMode); - InitWirelessMode = WIRELESS_MODE_B; - } - - /* Initialize RegWirelessMode if it is not a valid one. */ - if (bInvalidWirelessMode) - ieee->mode = (enum wireless_mode)InitWirelessMode; - - } else { - /* One of B, G, A. */ - InitWirelessMode = ieee->mode; - } - priv->eRFPowerState = RF_OFF; - priv->RfOffReason = 0; - { - MgntActSet_RF_State(dev, RF_ON, 0); - } - /* - * If inactive power mode is enabled, disable rf while in - * disconnected state. - */ - if (priv->bInactivePs) - MgntActSet_RF_State(dev , RF_OFF, RF_CHANGE_BY_IPS); - - ActSetWirelessMode8185(dev, (u8)(InitWirelessMode)); - - /* ----------------------------------------------------------------- */ - - rtl8185b_irq_enable(dev); - - netif_start_queue(dev); -} - -void rtl8185b_rx_enable(struct net_device *dev) -{ - u8 cmd; - /* for now we accept data, management & ctl frame*/ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - - if (dev->flags & IFF_PROMISC) - DMESG("NIC in promisc mode"); - - if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || dev->flags & - IFF_PROMISC) { - priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM); - priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP; - } - - if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) - priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF | - RCR_APWRMGT | RCR_AICV; - - - if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR) - priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACRC32; - - write_nic_dword(dev, RCR, priv->ReceiveConfig); - - fix_rx_fifo(dev); - - cmd = read_nic_byte(dev, CMD); - write_nic_byte(dev, CMD, cmd | (1<<CMD_RX_ENABLE_SHIFT)); - -} - -void rtl8185b_tx_enable(struct net_device *dev) -{ - u8 cmd; - u8 byte; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - write_nic_dword(dev, TCR, priv->TransmitConfig); - byte = read_nic_byte(dev, MSR); - byte |= MSR_LINK_ENEDCA; - write_nic_byte(dev, MSR, byte); - - fix_tx_fifo(dev); - - cmd = read_nic_byte(dev, CMD); - write_nic_byte(dev, CMD, cmd | (1<<CMD_TX_ENABLE_SHIFT)); -} - diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 636ec55..e305d43 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -545,20 +545,18 @@ static struct recv_frame *decryptor(struct adapter *padapter, static struct recv_frame *portctrl(struct adapter *adapter, struct recv_frame *precv_frame) { - u8 *psta_addr = NULL, *ptr; + u8 *psta_addr, *ptr; uint auth_alg; struct recv_frame *pfhdr; struct sta_info *psta; struct sta_priv *pstapriv; struct recv_frame *prtnframe; - u16 ether_type = 0; + u16 ether_type; u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */ struct rx_pkt_attrib *pattrib; - __be16 be_tmp; pstapriv = &adapter->stapriv; - psta = rtw_get_stainfo(pstapriv, psta_addr); auth_alg = adapter->securitypriv.dot11AuthAlgrthm; @@ -566,24 +564,23 @@ static struct recv_frame *portctrl(struct adapter *adapter, pfhdr = precv_frame; pattrib = &pfhdr->attrib; psta_addr = pattrib->ta; + psta = rtw_get_stainfo(pstapriv, psta_addr); prtnframe = NULL; RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n", adapter->securitypriv.dot11AuthAlgrthm)); if (auth_alg == 2) { + /* get ether_type */ + ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; + memcpy(ðer_type, ptr, 2); + ether_type = ntohs((unsigned short)ether_type); + if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked */ /* only accept EAPOL frame */ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked==1\n")); - prtnframe = precv_frame; - - /* get ether_type */ - ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE; - memcpy(&be_tmp, ptr, 2); - ether_type = ntohs(be_tmp); - if (ether_type == eapol_type) { prtnframe = precv_frame; } else { diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 2636e7f..cf30a08 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -359,7 +359,7 @@ static char *translate_scan(struct adapter *padapter, if (wpa_len > 0) { p = buf; _rtw_memset(buf, 0, MAX_WPA_IE_LEN); - p += sprintf(p, "wpa_ie ="); + p += sprintf(p, "wpa_ie="); for (i = 0; i < wpa_len; i++) p += sprintf(p, "%02x", wpa_ie[i]); @@ -376,7 +376,7 @@ static char *translate_scan(struct adapter *padapter, if (rsn_len > 0) { p = buf; _rtw_memset(buf, 0, MAX_WPA_IE_LEN); - p += sprintf(p, "rsn_ie ="); + p += sprintf(p, "rsn_ie="); for (i = 0; i < rsn_len; i++) p += sprintf(p, "%02x", rsn_ie[i]); _rtw_memset(&iwe, 0, sizeof(iwe)); @@ -2899,7 +2899,7 @@ static int rtw_p2p_get_status(struct net_device *dev, /* Commented by Albert 2010/10/12 */ /* Because of the output size limitation, I had removed the "Role" information. */ /* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */ - sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo)); + sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo)); wrqu->data.length = strlen(extra); return ret; @@ -2918,7 +2918,7 @@ static int rtw_p2p_get_req_cm(struct net_device *dev, struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req); + sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req); wrqu->data.length = strlen(extra); return ret; } @@ -2935,7 +2935,7 @@ static int rtw_p2p_get_role(struct net_device *dev, pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]); - sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo)); + sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo)); wrqu->data.length = strlen(extra); return ret; } @@ -3022,7 +3022,7 @@ static int rtw_p2p_get_op_ch(struct net_device *dev, DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel); - sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel); + sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel); wrqu->data.length = strlen(extra); return ret; } @@ -3043,7 +3043,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev, u8 blnMatch = 0; u16 attr_content = 0; uint attr_contentlen = 0; - /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */ + /* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */ u8 attr_content_str[6 + 17] = {0x00}; /* Commented by Albert 20110727 */ @@ -3079,7 +3079,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev, rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen); if (attr_contentlen) { attr_content = be16_to_cpu(be_tmp); - sprintf(attr_content_str, "\n\nM =%.4d", attr_content); + sprintf(attr_content_str, "\n\nM=%.4d", attr_content); blnMatch = 1; } } @@ -3091,7 +3091,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(attr_content_str, "\n\nM = 0000"); + sprintf(attr_content_str, "\n\nM=0000"); if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17)) return -EFAULT; @@ -3172,9 +3172,9 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL"); + snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL"); else - snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", + snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]); if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str))) @@ -3198,7 +3198,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev, u8 blnMatch = 0; u8 dev_type[8] = {0x00}; uint dev_type_len = 0; - u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */ + u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */ /* Commented by Albert 20121209 */ /* The input data is the MAC address which the application wants to know its device type. */ @@ -3239,7 +3239,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev, memcpy(&be_tmp, dev_type, 2); type = be16_to_cpu(be_tmp); - sprintf(dev_type_str, "\n\nN =%.2d", type); + sprintf(dev_type_str, "\n\nN=%.2d", type); blnMatch = 1; } } @@ -3252,7 +3252,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(dev_type_str, "\n\nN = 00"); + sprintf(dev_type_str, "\n\nN=00"); if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) { return -EFAULT; @@ -3277,7 +3277,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev, u8 blnMatch = 0; u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00}; uint dev_len = 0; - u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */ + u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */ /* Commented by Albert 20121225 */ /* The input data is the MAC address which the application wants to know its device name. */ @@ -3310,7 +3310,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev, if (wpsie) { rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len); if (dev_len) { - sprintf(dev_name_str, "\n\nN =%s", dev_name); + sprintf(dev_name_str, "\n\nN=%s", dev_name); blnMatch = 1; } } @@ -3323,7 +3323,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(dev_name_str, "\n\nN = 0000"); + sprintf(dev_name_str, "\n\nN=0000"); if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17))) return -EFAULT; @@ -3349,7 +3349,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev, u8 attr_content[2] = {0x00}; u8 inv_proc_str[17 + 8] = {0x00}; - /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */ + /* +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */ /* Commented by Ouden 20121226 */ /* The application wants to know P2P initiation procedure is supported or not. */ @@ -3397,12 +3397,12 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) { - sprintf(inv_proc_str, "\nIP =-1"); + sprintf(inv_proc_str, "\nIP=-1"); } else { if (attr_content[0] & 0x20) - sprintf(inv_proc_str, "\nIP = 1"); + sprintf(inv_proc_str, "\nIP=1"); else - sprintf(inv_proc_str, "\nIP = 0"); + sprintf(inv_proc_str, "\nIP=0"); } if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17)) return -EFAULT; @@ -3512,7 +3512,7 @@ static int rtw_p2p_invite_req(struct net_device *dev, /* The input data contains two informations. */ /* 1. First information is the P2P device address which you want to send to. */ /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */ - /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */ + /* Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */ /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */ DBG_88E("[%s] data = %s\n", __func__, extra); @@ -3805,48 +3805,48 @@ static int rtw_p2p_set(struct net_device *dev, #ifdef CONFIG_88EU_P2P DBG_88E("[%s] extra = %s\n", __func__, extra); - if (!memcmp(extra, "enable =", 7)) { + if (!memcmp(extra, "enable=", 7)) { rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "setDN =", 6)) { + } else if (!memcmp(extra, "setDN=", 6)) { wrqu->data.length -= 6; rtw_p2p_setDN(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "profilefound =", 13)) { + } else if (!memcmp(extra, "profilefound=", 13)) { wrqu->data.length -= 13; rtw_p2p_profilefound(dev, info, wrqu, &extra[13]); - } else if (!memcmp(extra, "prov_disc =", 10)) { + } else if (!memcmp(extra, "prov_disc=", 10)) { wrqu->data.length -= 10; rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "nego =", 5)) { + } else if (!memcmp(extra, "nego=", 5)) { wrqu->data.length -= 5; rtw_p2p_connect(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "intent =", 7)) { + } else if (!memcmp(extra, "intent=", 7)) { /* Commented by Albert 2011/03/23 */ /* The wrqu->data.length will include the null character */ /* So, we will decrease 7 + 1 */ wrqu->data.length -= 8; rtw_p2p_set_intent(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "ssid =", 5)) { + } else if (!memcmp(extra, "ssid=", 5)) { wrqu->data.length -= 5; rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "got_wpsinfo =", 12)) { + } else if (!memcmp(extra, "got_wpsinfo=", 12)) { wrqu->data.length -= 12; rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]); - } else if (!memcmp(extra, "listen_ch =", 10)) { + } else if (!memcmp(extra, "listen_ch=", 10)) { /* Commented by Albert 2011/05/24 */ /* The wrqu->data.length will include the null character */ /* So, we will decrease (10 + 1) */ wrqu->data.length -= 11; rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "op_ch =", 6)) { + } else if (!memcmp(extra, "op_ch=", 6)) { /* Commented by Albert 2011/05/24 */ /* The wrqu->data.length will include the null character */ /* So, we will decrease (6 + 1) */ wrqu->data.length -= 7; rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "invite =", 7)) { + } else if (!memcmp(extra, "invite=", 7)) { wrqu->data.length -= 8; rtw_p2p_invite_req(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "persistent =", 11)) { + } else if (!memcmp(extra, "persistent=", 11)) { wrqu->data.length -= 11; rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]); } @@ -3887,7 +3887,7 @@ static int rtw_p2p_get(struct net_device *dev, "group_id", 8)) { rtw_p2p_get_groupid(dev, info, wrqu, extra); } else if (!memcmp((__force const char *)wrqu->data.pointer, - "peer_deva_inv", 9)) { + "peer_deva_inv", 13)) { /* Get the P2P device address when receiving the P2P Invitation request frame. */ rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra); } else if (!memcmp((__force const char *)wrqu->data.pointer, @@ -6920,7 +6920,7 @@ static int rtw_mp_ctx(struct net_device *dev, DBG_88E("%s: in =%s\n", __func__, extra); - countPkTx = strncmp(extra, "count =", 5); /* strncmp true is 0 */ + countPkTx = strncmp(extra, "count=", 6); /* strncmp true is 0 */ cotuTx = strncmp(extra, "background", 20); CarrSprTx = strncmp(extra, "background, cs", 20); scTx = strncmp(extra, "background, sc", 20); @@ -7044,7 +7044,7 @@ static int rtw_mp_arx(struct net_device *dev, DBG_88E("%s: %s\n", __func__, input); bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */ - bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0 */ + bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /* strncmp true is 0 */ bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */ if (bStartRx) { diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 23ec684..274c359 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -254,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, struct sta_info *psta; struct sta_priv *pstapriv; union recv_frame *prtnframe; - u16 ether_type = 0; + u16 ether_type; pstapriv = &adapter->stapriv; ptr = get_recvframe_data(precv_frame); @@ -263,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, psta = r8712_get_stainfo(pstapriv, psta_addr); auth_alg = adapter->securitypriv.AuthAlgrthm; if (auth_alg == 2) { + /* get ether_type */ + ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; + memcpy(ðer_type, ptr, 2); + ether_type = ntohs((unsigned short)ether_type); + if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked * only accept EAPOL frame */ - prtnframe = precv_frame; - /*get ether_type */ - ptr = ptr + pfhdr->attrib.hdrlen + - pfhdr->attrib.iv_len + LLC_HEADER_SIZE; - memcpy(ðer_type, ptr, 2); - ether_type = ntohs((unsigned short)ether_type); if (ether_type == 0x888e) prtnframe = precv_frame; else { diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c index 780631f..a48ab25 100644 --- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c @@ -1496,45 +1496,23 @@ void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_ int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen) { int match; - uint cnt = 0; - u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A}; + const u8 *ie; - match = false; + match = 0; - if (in_len < 0) { + if (in_len < 0) return match; - } - - while (cnt < in_len) - { - eid = in_ie[cnt]; - if ((eid == _VENDOR_SPECIFIC_IE_) && - !memcmp(&in_ie[cnt+2], wfd_oui, 4)) { - if (wfd_ie != NULL) { - memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - } else { - if (wfd_ielen != NULL) { - *wfd_ielen = 0; - } - } - - if (wfd_ielen != NULL) { - *wfd_ielen = in_ie[cnt + 1] + 2; - } - - cnt += in_ie[cnt + 1] + 2; - - match = true; - break; - } else { - cnt += in_ie[cnt + 1] +2; /* goto next */ - } - } + ie = cfg80211_find_vendor_ie(0x506F9A, 0x0A, in_ie, in_len); + if (ie && (ie[1] <= (MAX_WFD_IE_LEN - 2))) { + if (wfd_ie) { + *wfd_ielen = ie[1] + 2; + memcpy(wfd_ie, ie, ie[1] + 2); + } else + if (wfd_ielen) + *wfd_ielen = 0; - if (match == true) { - match = cnt; + match = 1; } return match; diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c index 4c75363..1f3e8a0 100644 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c @@ -1281,7 +1281,7 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec u8 p2p_status_code = P2P_STATUS_SUCCESS; u8 *p2pie; u32 p2pielen = 0; - u8 wfd_ie[ 128 ] = { 0x00 }; + u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 }; u32 wfd_ielen = 0; #endif /* CONFIG_8723AU_P2P */ diff --git a/drivers/staging/rtl8723au/core/rtw_p2p.c b/drivers/staging/rtl8723au/core/rtw_p2p.c index 27a6cc7..1a961e3 100644 --- a/drivers/staging/rtl8723au/core/rtw_p2p.c +++ b/drivers/staging/rtl8723au/core/rtw_p2p.c @@ -2535,7 +2535,7 @@ u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pfra u16 wps_devicepassword_id = 0x0000; uint wps_devicepassword_id_len = 0; #ifdef CONFIG_8723AU_P2P - u8 wfd_ie[ 128 ] = { 0x00 }; + u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 }; u32 wfd_ielen = 0; #endif /* CONFIG_8723AU_P2P */ @@ -2741,7 +2741,7 @@ u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pfr u32 ies_len; u8 * p2p_ie; #ifdef CONFIG_8723AU_P2P - u8 wfd_ie[ 128 ] = { 0x00 }; + u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 }; u32 wfd_ielen = 0; #endif /* CONFIG_8723AU_P2P */ diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c index 0dfcfbc..99d81e6 100644 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c @@ -570,7 +570,7 @@ void flush_all_cam_entry23a(struct rtw_adapter *padapter) int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE) { struct wifidirect_info *pwdinfo; - u8 wfd_ie[128] = {0x00}; + u8 wfd_ie[MAX_WFD_IE_LEN] = {0x00}; u32 wfd_ielen = 0; pwdinfo = &padapter->wdinfo; @@ -681,7 +681,7 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter) inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; if (pregpriv->wifi_spec == 1) { - u32 j, tmp, change_inx; + u32 j, tmp, change_inx = false; /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ for (i = 0; i < 4; i++) { diff --git a/drivers/staging/rtl8821ae/base.c b/drivers/staging/rtl8821ae/base.c index e5073fe..a4c9cc4 100644 --- a/drivers/staging/rtl8821ae/base.c +++ b/drivers/staging/rtl8821ae/base.c @@ -388,7 +388,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) } -static void _rtl_init_deferred_work(struct ieee80211_hw *hw) +static int _rtl_init_deferred_work(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -410,6 +410,9 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name); #endif /*<delete in kernel end>*/ + if (!rtlpriv->works.rtl_wq) + return -ENOMEM; + INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, @@ -421,6 +424,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, (void *)rtl_fwevt_wq_callback); + return 0; + } void rtl_deinit_deferred_work(struct ieee80211_hw *hw) @@ -519,7 +524,8 @@ int rtl_init_core(struct ieee80211_hw *hw) INIT_LIST_HEAD(&rtlpriv->entry_list); /* <6> init deferred work */ - _rtl_init_deferred_work(hw); + if (_rtl_init_deferred_work(hw)) + return 1; /* <7> */ #ifdef VIF_TODO diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index ef5933b..3b6e535 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -1855,8 +1855,9 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) { static u_char goto_buf[8]; static int num; - int maxlen, go_pos; + int maxlen; char *cp; + if (type == KT_SPKUP && ch == SPEAKUP_GOTO) goto do_goto; if (type == KT_LATIN && ch == '\n') @@ -1891,25 +1892,24 @@ oops: spk_special_handler = NULL; return 1; } - go_pos = kstrtol(goto_buf, 10, (long *)&cp); - goto_pos = (u_long) go_pos; + + goto_pos = simple_strtoul(goto_buf, &cp, 10); + if (*cp == 'x') { if (*goto_buf < '0') goto_pos += spk_x; - else + else if (goto_pos > 0) goto_pos--; - if (goto_pos < 0) - goto_pos = 0; + if (goto_pos >= vc->vc_cols) goto_pos = vc->vc_cols - 1; goto_x = 1; } else { if (*goto_buf < '0') goto_pos += spk_y; - else + else if (goto_pos > 0) goto_pos--; - if (goto_pos < 0) - goto_pos = 0; + if (goto_pos >= vc->vc_rows) goto_pos = vc->vc_rows - 1; goto_x = 0; diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 8ea9c46..3152a21 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -381,17 +381,17 @@ create_bus(CONTROLVM_MESSAGE *msg, char *buf) cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid; cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid; if (!VirtControlChanFunc) { - kfree(bus); LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered."); POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo, POSTCODE_SEVERITY_ERR); + kfree(bus); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; } if (!VirtControlChanFunc(&cmd)) { - kfree(bus); LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error."); POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo, POSTCODE_SEVERITY_ERR); + kfree(bus); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; } diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index d4bf203..d95825d 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -104,9 +104,9 @@ finddevice(struct list_head *list, U32 busNo, U32 devNo) static inline void delbusdevices(struct list_head *list, U32 busNo) { - VISORCHIPSET_DEVICE_INFO *p; + VISORCHIPSET_DEVICE_INFO *p, *tmp; - list_for_each_entry(p, list, entry) { + list_for_each_entry_safe(p, tmp, list, entry) { if (p->busNo == busNo) { list_del(&p->entry); kfree(p); diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 257c6e5..c475e25 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -605,16 +605,16 @@ EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client); static void cleanup_controlvm_structures(void) { - VISORCHIPSET_BUS_INFO *bi; - VISORCHIPSET_DEVICE_INFO *di; + VISORCHIPSET_BUS_INFO *bi, *tmp_bi; + VISORCHIPSET_DEVICE_INFO *di, *tmp_di; - list_for_each_entry(bi, &BusInfoList, entry) { + list_for_each_entry_safe(bi, tmp_bi, &BusInfoList, entry) { busInfo_clear(bi); list_del(&bi->entry); kfree(bi); } - list_for_each_entry(di, &DevInfoList, entry) { + list_for_each_entry_safe(di, tmp_di, &DevInfoList, entry) { devInfo_clear(di); list_del(&di->entry); kfree(di); diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c index c5bf60b..92caef7 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c +++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c @@ -118,6 +118,7 @@ static int refresh_exported_devices(void) struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; const char *path; + const char *driver; enumerate = udev_enumerate_new(udev_context); udev_enumerate_add_match_subsystem(enumerate, "usb"); @@ -128,10 +129,12 @@ static int refresh_exported_devices(void) udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev_context, path); + if (dev == NULL) + continue; /* Check whether device uses usbip-host driver. */ - if (!strcmp(udev_device_get_driver(dev), - USBIP_HOST_DRV_NAME)) { + driver = udev_device_get_driver(dev); + if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) { edev = usbip_exported_device_new(path); if (!edev) { dbg("usbip_exported_device_new failed"); diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c index 47bddcd..211f43f 100644 --- a/drivers/staging/usbip/vhci_sysfs.c +++ b/drivers/staging/usbip/vhci_sysfs.c @@ -184,7 +184,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, * @devid: unique device identifier in a remote host * @speed: usb device speed in a remote host */ - if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 1) + if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4) return -EINVAL; usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n", diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index 7927927..ffb4eee 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -776,7 +776,8 @@ static int vme_user_probe(struct vme_dev *vdev) image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL); if (image[i].kern_buf == NULL) { err = -ENOMEM; - goto err_master_buf; + vme_master_free(image[i].resource); + goto err_master; } } @@ -819,8 +820,6 @@ static int vme_user_probe(struct vme_dev *vdev) return 0; - /* Ensure counter set correcty to destroy all sysfs devices */ - i = VME_DEVS; err_sysfs: while (i > 0) { i--; @@ -830,12 +829,10 @@ err_sysfs: /* Ensure counter set correcty to unalloc all master windows */ i = MASTER_MAX + 1; -err_master_buf: - for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) - kfree(image[i].kern_buf); err_master: while (i > MASTER_MINOR) { i--; + kfree(image[i].kern_buf); vme_master_free(image[i].resource); } diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 81f909c..0e1bf88 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1520,7 +1520,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status = serial8250_rx_chars(up, status); } serial8250_modem_status(up); - if (status & UART_LSR_THRE) + if (!up->dma && (status & UART_LSR_THRE)) serial8250_tx_chars(up); spin_unlock_irqrestore(&port->lock, flags); diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index 7046769..ab9096d 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -20,12 +20,15 @@ static void __dma_tx_complete(void *param) struct uart_8250_port *p = param; struct uart_8250_dma *dma = p->dma; struct circ_buf *xmit = &p->port.state->xmit; - - dma->tx_running = 0; + unsigned long flags; dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); + spin_lock_irqsave(&p->port.lock, flags); + + dma->tx_running = 0; + xmit->tail += dma->tx_size; xmit->tail &= UART_XMIT_SIZE - 1; p->port.icount.tx += dma->tx_size; @@ -35,6 +38,8 @@ static void __dma_tx_complete(void *param) if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) serial8250_tx_dma(p); + + spin_unlock_irqrestore(&p->port.lock, flags); } static void __dma_rx_complete(void *param) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2e6d8dd..5d9b01a 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1226,6 +1226,7 @@ config SERIAL_BFIN_SPORT3_UART_CTSRTS config SERIAL_TIMBERDALE tristate "Support for timberdale UART" select SERIAL_CORE + depends on X86_32 || COMPILE_TEST ---help--- Add support for UART controller on timberdale. diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d4eda24..dacf0a0 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -318,7 +318,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * .src_addr = uap->port.mapbase + UART01x_DR, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_DEV_TO_MEM, - .src_maxburst = uap->fifosize >> 1, + .src_maxburst = uap->fifosize >> 2, .device_fc = false, }; @@ -2176,6 +2176,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) static int pl011_remove(struct amba_device *dev) { struct uart_amba_port *uap = amba_get_drvdata(dev); + bool busy = false; int i; uart_remove_one_port(&amba_reg, &uap->port); @@ -2183,9 +2184,12 @@ static int pl011_remove(struct amba_device *dev) for (i = 0; i < ARRAY_SIZE(amba_ports); i++) if (amba_ports[i] == uap) amba_ports[i] = NULL; + else if (amba_ports[i]) + busy = true; pl011_dma_remove(uap); - uart_unregister_driver(&amba_reg); + if (!busy) + uart_unregister_driver(&amba_reg); return 0; } diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 5e6fdb1..14aaea0 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -368,16 +368,12 @@ static const struct uart_ops uart_clps711x_ops = { static void uart_clps711x_console_putchar(struct uart_port *port, int ch) { struct clps711x_port *s = dev_get_drvdata(port->dev); + u32 sysflg = 0; /* Wait for FIFO is not full */ - while (1) { - u32 sysflg = 0; - + do { regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); - if (!(sysflg & SYSFLG_UTXFF)) - break; - cond_resched(); - } + } while (sysflg & SYSFLG_UTXFF); writew(ch, port->membase + UARTDR_OFFSET); } @@ -387,18 +383,14 @@ static void uart_clps711x_console_write(struct console *co, const char *c, { struct uart_port *port = clps711x_uart.state[co->index].uart_port; struct clps711x_port *s = dev_get_drvdata(port->dev); + u32 sysflg = 0; uart_console_write(port, c, n, uart_clps711x_console_putchar); /* Wait for transmitter to become empty */ - while (1) { - u32 sysflg = 0; - + do { regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); - if (!(sysflg & SYSFLG_UBUSY)) - break; - cond_resched(); - } + } while (sysflg & SYSFLG_UBUSY); } static int uart_clps711x_console_setup(struct console *co, char *options) diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 028582e..c167a71 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -798,6 +798,9 @@ static int efm32_uart_remove(struct platform_device *pdev) static const struct of_device_id efm32_uart_dt_ids[] = { { + .compatible = "energymicro,efm32-uart", + }, { + /* doesn't follow the "vendor,device" scheme, don't use */ .compatible = "efm32,uart", }, { /* sentinel */ diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index dd8b1a5..08b6b94 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -225,14 +225,19 @@ static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up, if (enable) enable_irq(up->wakeirq); else - disable_irq(up->wakeirq); + disable_irq_nosync(up->wakeirq); } static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) { struct omap_uart_port_info *pdata = dev_get_platdata(up->dev); + if (enable == up->wakeups_enabled) + return; + serial_omap_enable_wakeirq(up, enable); + up->wakeups_enabled = enable; + if (!pdata || !pdata->enable_wakeup) return; @@ -1495,6 +1500,11 @@ static int serial_omap_suspend(struct device *dev) uart_suspend_port(&serial_omap_reg, &up->port); flush_work(&up->qos_work); + if (device_may_wakeup(dev)) + serial_omap_enable_wakeup(up, true); + else + serial_omap_enable_wakeup(up, false); + return 0; } @@ -1502,6 +1512,9 @@ static int serial_omap_resume(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) + serial_omap_enable_wakeup(up, false); + uart_resume_port(&serial_omap_reg, &up->port); return 0; @@ -1789,6 +1802,7 @@ static int serial_omap_remove(struct platform_device *dev) pm_runtime_disable(up->dev); uart_remove_one_port(&serial_omap_reg, &up->port); pm_qos_remove_request(&up->pm_qos_request); + device_init_wakeup(&dev->dev, false); return 0; } @@ -1877,17 +1891,7 @@ static int serial_omap_runtime_suspend(struct device *dev) up->context_loss_cnt = serial_omap_get_context_loss_count(up); - if (device_may_wakeup(dev)) { - if (!up->wakeups_enabled) { - serial_omap_enable_wakeup(up, true); - up->wakeups_enabled = true; - } - } else { - if (up->wakeups_enabled) { - serial_omap_enable_wakeup(up, false); - up->wakeups_enabled = false; - } - } + serial_omap_enable_wakeup(up, true); up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; schedule_work(&up->qos_work); @@ -1901,6 +1905,8 @@ static int serial_omap_runtime_resume(struct device *dev) int loss_cnt = serial_omap_get_context_loss_count(up); + serial_omap_enable_wakeup(up, false); + if (loss_cnt < 0) { dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n", loss_cnt); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 23f4596..1f5505e 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1446,8 +1446,8 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port) static void s3c24xx_serial_put_poll_char(struct uart_port *port, unsigned char c) { - unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); - unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); + unsigned int ufcon = rd_regl(port, S3C2410_UFCON); + unsigned int ucon = rd_regl(port, S3C2410_UCON); /* not possible to xmit on unconfigured port */ if (!s3c24xx_port_configured(ucon)) @@ -1455,7 +1455,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, while (!s3c24xx_serial_console_txrdy(port, ufcon)) cpu_relax(); - wr_regb(cons_uart, S3C2410_UTXH, c); + wr_regb(port, S3C2410_UTXH, c); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1463,22 +1463,23 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch) { - unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); - unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); - - /* not possible to xmit on unconfigured port */ - if (!s3c24xx_port_configured(ucon)) - return; + unsigned int ufcon = rd_regl(port, S3C2410_UFCON); while (!s3c24xx_serial_console_txrdy(port, ufcon)) - barrier(); - wr_regb(cons_uart, S3C2410_UTXH, ch); + cpu_relax(); + wr_regb(port, S3C2410_UTXH, ch); } static void s3c24xx_serial_console_write(struct console *co, const char *s, unsigned int count) { + unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); + + /* not possible to xmit on unconfigured port */ + if (!s3c24xx_port_configured(ucon)) + return; + uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2cf5649..b68550d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -89,8 +89,7 @@ static void __uart_start(struct tty_struct *tty) struct uart_state *state = tty->driver_data; struct uart_port *port = state->uart_port; - if (!uart_circ_empty(&state->xmit) && state->xmit.buf && - !tty->stopped && !tty->hw_stopped) + if (!tty->stopped && !tty->hw_stopped) port->ops->start_tx(port); } @@ -138,6 +137,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, return 1; /* + * Make sure the device is in D0 state. + */ + uart_change_pm(state, UART_PM_STATE_ON); + + /* * Initialise and allocate the transmit and temporary * buffer. */ @@ -826,25 +830,29 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, * If we fail to request resources for the * new port, try to restore the old settings. */ - if (retval && old_type != PORT_UNKNOWN) { + if (retval) { uport->iobase = old_iobase; uport->type = old_type; uport->hub6 = old_hub6; uport->iotype = old_iotype; uport->regshift = old_shift; uport->mapbase = old_mapbase; - retval = uport->ops->request_port(uport); - /* - * If we failed to restore the old settings, - * we fail like this. - */ - if (retval) - uport->type = PORT_UNKNOWN; - /* - * We failed anyway. - */ - retval = -EBUSY; + if (old_type != PORT_UNKNOWN) { + retval = uport->ops->request_port(uport); + /* + * If we failed to restore the old settings, + * we fail like this. + */ + if (retval) + uport->type = PORT_UNKNOWN; + + /* + * We failed anyway. + */ + retval = -EBUSY; + } + /* Added to return the correct error -Ram Gupta */ goto exit; } @@ -1452,6 +1460,8 @@ static void uart_hangup(struct tty_struct *tty) clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); spin_unlock_irqrestore(&port->lock, flags); tty_port_tty_set(port, NULL); + if (!uart_console(state->uart_port)) + uart_change_pm(state, UART_PM_STATE_OFF); wake_up_interruptible(&port->open_wait); wake_up_interruptible(&port->delta_msr_wait); } @@ -1570,12 +1580,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) } /* - * Make sure the device is in D0 state. - */ - if (port->count == 1) - uart_change_pm(state, UART_PM_STATE_ON); - - /* * Start up the serial port. */ retval = uart_startup(tty, state, 0); diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 21e6e84..dd3a96e 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -295,7 +295,7 @@ static void asc_receive_chars(struct uart_port *port) status & ASC_STA_OE) { if (c & ASC_RXBUF_FE) { - if (c == ASC_RXBUF_FE) { + if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) { port->icount.brk++; if (uart_handle_break(port)) continue; @@ -325,7 +325,7 @@ static void asc_receive_chars(struct uart_port *port) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, c)) + if (uart_handle_sysrq_char(port, c & 0xff)) continue; uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag); diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 8ebd9f8..f1d30f6 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -255,11 +255,16 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, if (change || left < size) { /* This is the slow path - looking for new buffers to use */ if ((n = tty_buffer_alloc(port, size)) != NULL) { + unsigned long iflags; + n->flags = flags; buf->tail = n; + + spin_lock_irqsave(&buf->flush_lock, iflags); b->commit = b->used; - smp_mb(); b->next = n; + spin_unlock_irqrestore(&buf->flush_lock, iflags); + } else if (change) size = 0; else @@ -443,6 +448,7 @@ static void flush_to_ldisc(struct work_struct *work) mutex_lock(&buf->lock); while (1) { + unsigned long flags; struct tty_buffer *head = buf->head; int count; @@ -450,14 +456,19 @@ static void flush_to_ldisc(struct work_struct *work) if (atomic_read(&buf->priority)) break; + spin_lock_irqsave(&buf->flush_lock, flags); count = head->commit - head->read; if (!count) { - if (head->next == NULL) + if (head->next == NULL) { + spin_unlock_irqrestore(&buf->flush_lock, flags); break; + } buf->head = head->next; + spin_unlock_irqrestore(&buf->flush_lock, flags); tty_buffer_free(port, head); continue; } + spin_unlock_irqrestore(&buf->flush_lock, flags); count = receive_buf(tty, head, count); if (!count) @@ -512,6 +523,7 @@ void tty_buffer_init(struct tty_port *port) struct tty_bufhead *buf = &port->buf; mutex_init(&buf->lock); + spin_lock_init(&buf->flush_lock); tty_buffer_reset(&buf->sentinel, 0); buf->head = &buf->sentinel; buf->tail = &buf->sentinel; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d3448a9..3411071 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -878,9 +878,8 @@ void disassociate_ctty(int on_exit) spin_lock_irq(¤t->sighand->siglock); put_pid(current->signal->tty_old_pgrp); current->signal->tty_old_pgrp = NULL; - spin_unlock_irq(¤t->sighand->siglock); - tty = get_current_tty(); + tty = tty_kref_get(current->signal->tty); if (tty) { unsigned long flags; spin_lock_irqsave(&tty->ctrl_lock, flags); @@ -897,6 +896,7 @@ void disassociate_ctty(int on_exit) #endif } + spin_unlock_irq(¤t->sighand->siglock); /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); session_clear_tty(task_session(current)); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index ca6831c..1cd5d0b 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -277,6 +277,39 @@ static void hw_phymode_configure(struct ci_hdrc *ci) } /** + * ci_usb_phy_init: initialize phy according to different phy type + * @ci: the controller + * + * This function returns an error code if usb_phy_init has failed + */ +static int ci_usb_phy_init(struct ci_hdrc *ci) +{ + int ret; + + switch (ci->platdata->phy_mode) { + case USBPHY_INTERFACE_MODE_UTMI: + case USBPHY_INTERFACE_MODE_UTMIW: + case USBPHY_INTERFACE_MODE_HSIC: + ret = usb_phy_init(ci->transceiver); + if (ret) + return ret; + hw_phymode_configure(ci); + break; + case USBPHY_INTERFACE_MODE_ULPI: + case USBPHY_INTERFACE_MODE_SERIAL: + hw_phymode_configure(ci); + ret = usb_phy_init(ci->transceiver); + if (ret) + return ret; + break; + default: + ret = usb_phy_init(ci->transceiver); + } + + return ret; +} + +/** * hw_device_reset: resets chip (execute without interruption) * @ci: the controller * @@ -543,8 +576,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) return -ENODEV; } - hw_phymode_configure(ci); - if (ci->platdata->phy) ci->transceiver = ci->platdata->phy; else @@ -564,7 +595,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) return -EPROBE_DEFER; } - ret = usb_phy_init(ci->transceiver); + ret = ci_usb_phy_init(ci); if (ret) { dev_err(dev, "unable to init phy: %d\n", ret); return ret; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 900f7ff..904efb6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -518,13 +518,16 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dev_err(&acm->control->dev, "%s - usb_submit_urb(ctrl irq) failed\n", __func__); + usb_autopm_put_interface(acm->control); goto error_submit_urb; } acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; if (acm_set_control(acm, acm->ctrlout) < 0 && - (acm->ctrl_caps & USB_CDC_CAP_LINE)) + (acm->ctrl_caps & USB_CDC_CAP_LINE)) { + usb_autopm_put_interface(acm->control); goto error_set_control; + } usb_autopm_put_interface(acm->control); @@ -549,7 +552,6 @@ error_submit_read_urbs: error_set_control: usb_kill_urb(acm->ctrlurb); error_submit_urb: - usb_autopm_put_interface(acm->control); error_get_interface: disconnected: mutex_unlock(&acm->mutex); @@ -1652,13 +1654,27 @@ static const struct usb_device_id acm_ids[] = { }, /* Motorola H24 HSPA module: */ { USB_DEVICE(0x22b8, 0x2d91) }, /* modem */ - { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */ - { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */ - { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */ - { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */ - { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */ - { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */ - { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */ + { USB_DEVICE(0x22b8, 0x2d92), /* modem + diagnostics */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d93), /* modem + AT port */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d95), /* modem + AT port + diagnostics */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d96), /* modem + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d97), /* modem + diagnostics + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d99), /* modem + AT port + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d9a), /* modem + AT port + diagnostics + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index d59d993..1f02e65 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd, PCI_SLOT(companion->devfn) != slot) continue; companion_hcd = pci_get_drvdata(companion); - if (!companion_hcd) + if (!companion_hcd || !companion_hcd->self.root_hub) continue; fn(pdev, hcd, companion, companion_hcd); } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d001417..10aaaae 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -821,6 +821,7 @@ static void dwc3_complete(struct device *dev) spin_lock_irqsave(&dwc->lock, flags); + dwc3_event_buffers_setup(dwc); switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_OTG: @@ -828,7 +829,6 @@ static void dwc3_complete(struct device *dev) /* FALLTHROUGH */ case USB_DR_MODE_HOST: default: - dwc3_event_buffers_setup(dwc); break; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a740eac..70715ee 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -187,15 +187,12 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) * improve this algorithm so that we better use the internal * FIFO space */ - for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) { - struct dwc3_ep *dep = dwc->eps[num]; - int fifo_number = dep->number >> 1; + for (num = 0; num < dwc->num_in_eps; num++) { + /* bit0 indicates direction; 1 means IN ep */ + struct dwc3_ep *dep = dwc->eps[(num << 1) | 1]; int mult = 1; int tmp; - if (!(dep->number & 1)) - continue; - if (!(dep->flags & DWC3_EP_ENABLED)) continue; @@ -224,8 +221,7 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n", dep->name, last_fifo_depth, fifo_size & 0xffff); - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number), - fifo_size); + dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size); last_fifo_depth += (fifo_size & 0xffff); } diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dc..1e12b3e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) */ struct usb_gadget *gadget = epfile->ffs->gadget; + spin_lock_irq(&epfile->ffs->eps_lock); + /* In the meantime, endpoint got disabled or changed. */ + if (epfile->ep != ep) { + spin_unlock_irq(&epfile->ffs->eps_lock); + return -ESHUTDOWN; + } /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. @@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = io_data->read ? usb_ep_align_maybe(gadget, ep->ep, io_data->len) : io_data->len; + spin_unlock_irq(&epfile->ffs->eps_lock); data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index c11761c..9a4f49d 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -377,7 +377,7 @@ static struct sk_buff *rndis_add_header(struct gether *port, if (skb2) rndis_add_hdr(skb2); - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); return skb2; } diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 15960af..a2f26cd 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1219,6 +1219,10 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on) struct fsl_udc *udc; udc = container_of(gadget, struct fsl_udc, gadget); + + if (!udc->vbus_active) + return -EOPNOTSUPP; + udc->softconnect = (is_on != 0); if (can_pullup(udc)) fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP), @@ -2532,8 +2536,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) if (!udc_controller) return -ENODEV; - usb_del_gadget_udc(&udc_controller->gadget); udc_controller->done = &done; + usb_del_gadget_udc(&udc_controller->gadget); fsl_udc_clk_release(); diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index b5be6f03..a925d0c 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -2043,6 +2043,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) return -ESRCH; /* fake probe to determine $CHIP */ + CHIP = NULL; usb_gadget_probe_driver(&probe_driver); if (!CHIP) return -ENODEV; diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index d822d82..7ed452d 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -35,6 +35,7 @@ #include <asm/byteorder.h> #include <asm/unaligned.h> +#include "u_rndis.h" #undef VERBOSE_DEBUG diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 50d09c2..b7d4f82 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -48,8 +48,6 @@ #define UETH__VERSION "29-May-2008" -#define GETHER_NAPI_WEIGHT 32 - struct eth_dev { /* lock is held while accessing port_usb */ @@ -74,7 +72,6 @@ struct eth_dev { struct sk_buff_head *list); struct work_struct work; - struct napi_struct rx_napi; unsigned long todo; #define WORK_RX_MEMORY 0 @@ -256,16 +253,18 @@ enomem: DBG(dev, "rx submit --> %d\n", retval); if (skb) dev_kfree_skb_any(skb); + spin_lock_irqsave(&dev->req_lock, flags); + list_add(&req->list, &dev->rx_reqs); + spin_unlock_irqrestore(&dev->req_lock, flags); } return retval; } static void rx_complete(struct usb_ep *ep, struct usb_request *req) { - struct sk_buff *skb = req->context; + struct sk_buff *skb = req->context, *skb2; struct eth_dev *dev = ep->driver_data; int status = req->status; - bool rx_queue = 0; switch (status) { @@ -289,8 +288,30 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req) } else { skb_queue_tail(&dev->rx_frames, skb); } - if (!status) - rx_queue = 1; + skb = NULL; + + skb2 = skb_dequeue(&dev->rx_frames); + while (skb2) { + if (status < 0 + || ETH_HLEN > skb2->len + || skb2->len > VLAN_ETH_FRAME_LEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + DBG(dev, "rx length %d\n", skb2->len); + dev_kfree_skb_any(skb2); + goto next_frame; + } + skb2->protocol = eth_type_trans(skb2, dev->net); + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += skb2->len; + + /* no buffer copies needed, unless hardware can't + * use skb buffers. + */ + status = netif_rx(skb2); +next_frame: + skb2 = skb_dequeue(&dev->rx_frames); + } break; /* software-driven interface shutdown */ @@ -313,20 +334,22 @@ quiesce: /* FALLTHROUGH */ default: - rx_queue = 1; - dev_kfree_skb_any(skb); dev->net->stats.rx_errors++; DBG(dev, "rx status %d\n", status); break; } + if (skb) + dev_kfree_skb_any(skb); + if (!netif_running(dev->net)) { clean: spin_lock(&dev->req_lock); list_add(&req->list, &dev->rx_reqs); spin_unlock(&dev->req_lock); - - if (rx_queue && likely(napi_schedule_prep(&dev->rx_napi))) - __napi_schedule(&dev->rx_napi); + req = NULL; + } + if (req) + rx_submit(dev, req, GFP_ATOMIC); } static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) @@ -391,24 +414,16 @@ static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) { struct usb_request *req; unsigned long flags; - int rx_counts = 0; /* fill unused rxq slots with some skb */ spin_lock_irqsave(&dev->req_lock, flags); while (!list_empty(&dev->rx_reqs)) { - - if (++rx_counts > qlen(dev->gadget, dev->qmult)) - break; - req = container_of(dev->rx_reqs.next, struct usb_request, list); list_del_init(&req->list); spin_unlock_irqrestore(&dev->req_lock, flags); if (rx_submit(dev, req, gfp_flags) < 0) { - spin_lock_irqsave(&dev->req_lock, flags); - list_add(&req->list, &dev->rx_reqs); - spin_unlock_irqrestore(&dev->req_lock, flags); defer_kevent(dev, WORK_RX_MEMORY); return; } @@ -418,41 +433,6 @@ static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) spin_unlock_irqrestore(&dev->req_lock, flags); } -static int gether_poll(struct napi_struct *napi, int budget) -{ - struct eth_dev *dev = container_of(napi, struct eth_dev, rx_napi); - struct sk_buff *skb; - unsigned int work_done = 0; - int status = 0; - - while ((skb = skb_dequeue(&dev->rx_frames))) { - if (status < 0 - || ETH_HLEN > skb->len - || skb->len > VLAN_ETH_FRAME_LEN) { - dev->net->stats.rx_errors++; - dev->net->stats.rx_length_errors++; - DBG(dev, "rx length %d\n", skb->len); - dev_kfree_skb_any(skb); - continue; - } - skb->protocol = eth_type_trans(skb, dev->net); - dev->net->stats.rx_packets++; - dev->net->stats.rx_bytes += skb->len; - - status = netif_rx_ni(skb); - } - - if (netif_running(dev->net)) { - rx_fill(dev, GFP_KERNEL); - work_done++; - } - - if (work_done < budget) - napi_complete(&dev->rx_napi); - - return work_done; -} - static void eth_work(struct work_struct *work) { struct eth_dev *dev = container_of(work, struct eth_dev, work); @@ -645,7 +625,6 @@ static void eth_start(struct eth_dev *dev, gfp_t gfp_flags) /* and open the tx floodgates */ atomic_set(&dev->tx_qlen, 0); netif_wake_queue(dev->net); - napi_enable(&dev->rx_napi); } static int eth_open(struct net_device *net) @@ -672,7 +651,6 @@ static int eth_stop(struct net_device *net) unsigned long flags; VDBG(dev, "%s\n", __func__); - napi_disable(&dev->rx_napi); netif_stop_queue(net); DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", @@ -790,7 +768,6 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, return ERR_PTR(-ENOMEM); dev = netdev_priv(net); - netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT); spin_lock_init(&dev->lock); spin_lock_init(&dev->req_lock); INIT_WORK(&dev->work, eth_work); @@ -853,7 +830,6 @@ struct net_device *gether_setup_name_default(const char *netname) return ERR_PTR(-ENOMEM); dev = netdev_priv(net); - netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT); spin_lock_init(&dev->lock); spin_lock_init(&dev->req_lock); INIT_WORK(&dev->work, eth_work); @@ -1137,7 +1113,6 @@ void gether_disconnect(struct gether *link) { struct eth_dev *dev = link->ioport; struct usb_request *req; - struct sk_buff *skb; WARN_ON(!dev); if (!dev) @@ -1164,12 +1139,6 @@ void gether_disconnect(struct gether *link) spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); - - spin_lock(&dev->rx_frames.lock); - while ((skb = __skb_dequeue(&dev->rx_frames))) - dev_kfree_skb_any(skb); - spin_unlock(&dev->rx_frames.lock); - link->in_ep->driver_data = NULL; link->in_ep->desc = NULL; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 9f170c5..134f354 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -300,7 +300,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev) ss_opts->isoc_interval = gzero_options.isoc_interval; ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket; ss_opts->isoc_mult = gzero_options.isoc_mult; - ss_opts->isoc_maxburst = gzero_options.isoc_maxpacket; + ss_opts->isoc_maxburst = gzero_options.isoc_maxburst; ss_opts->bulk_buflen = gzero_options.bulk_buflen; func_ss = usb_get_function(func_inst_ss); diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index d1d8c47..7f425ac 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -212,6 +212,8 @@ static int exynos_ehci_suspend(struct device *dev) int rc; rc = ehci_suspend(hcd, do_wakeup); + if (rc) + return rc; if (exynos_ehci->otg) exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index b3a0e11..c7dd93a 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -303,6 +303,8 @@ static int ehci_platform_suspend(struct device *dev) int ret; ret = ehci_suspend(hcd, do_wakeup); + if (ret) + return ret; if (pdata->power_suspend) pdata->power_suspend(pdev); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 27ac6ad..7ef00ec 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -509,8 +509,31 @@ static struct platform_driver tegra_ehci_driver = { } }; +static int tegra_ehci_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + int txfifothresh; + + retval = ehci_setup(hcd); + if (retval) + return retval; + + /* + * We should really pull this value out of tegra_ehci_soc_config, but + * to avoid needing access to it, make use of the fact that Tegra20 is + * the only one so far that needs a value of 10, and Tegra20 is the + * only one which doesn't set has_hostpc. + */ + txfifothresh = ehci->has_hostpc ? 0x10 : 10; + ehci_writel(ehci, txfifothresh << 16, &ehci->regs->txfill_tuning); + + return 0; +} + static const struct ehci_driver_overrides tegra_overrides __initconst = { .extra_priv_size = sizeof(struct tegra_ehci_hcd), + .reset = tegra_ehci_reset, }; static int __init ehci_tegra_init(void) diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index af8dc1b..c2c221a 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c @@ -82,14 +82,14 @@ static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); - int ret; + int ret = 0; switch (typeReq) { - case SetHubFeature: + case SetPortFeature: if (wValue == USB_PORT_FEAT_POWER) ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true); break; - case ClearHubFeature: + case ClearPortFeature: if (wValue == USB_PORT_FEAT_POWER) ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false); break; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 47390e3..35d4477 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -134,6 +134,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) */ if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP) xhci->quirks |= XHCI_SPURIOUS_WAKEUP; + + xhci->quirks |= XHCI_SPURIOUS_REBOOT; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { @@ -143,9 +145,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_RENESAS && - pdev->device == 0x0015 && - pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && - pdev->subsystem_device == 0xc0cd) + pdev->device == 0x0015) xhci->quirks |= XHCI_RESET_ON_RESUME; if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 5f926be..7a0e3c7 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -550,6 +550,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, struct xhci_ring *ep_ring; struct xhci_generic_trb *trb; dma_addr_t addr; + u64 hw_dequeue; ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id, ep_index, stream_id); @@ -559,16 +560,6 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, stream_id); return; } - state->new_cycle_state = 0; - xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, - "Finding segment containing stopped TRB."); - state->new_deq_seg = find_trb_seg(cur_td->start_seg, - dev->eps[ep_index].stopped_trb, - &state->new_cycle_state); - if (!state->new_deq_seg) { - WARN_ON(1); - return; - } /* Dig out the cycle state saved by the xHC during the stop ep cmd */ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, @@ -577,46 +568,57 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, if (ep->ep_state & EP_HAS_STREAMS) { struct xhci_stream_ctx *ctx = &ep->stream_info->stream_ctx_array[stream_id]; - state->new_cycle_state = 0x1 & le64_to_cpu(ctx->stream_ring); + hw_dequeue = le64_to_cpu(ctx->stream_ring); } else { struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); - state->new_cycle_state = 0x1 & le64_to_cpu(ep_ctx->deq); + hw_dequeue = le64_to_cpu(ep_ctx->deq); } + /* Find virtual address and segment of hardware dequeue pointer */ + state->new_deq_seg = ep_ring->deq_seg; + state->new_deq_ptr = ep_ring->dequeue; + while (xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr) + != (dma_addr_t)(hw_dequeue & ~0xf)) { + next_trb(xhci, ep_ring, &state->new_deq_seg, + &state->new_deq_ptr); + if (state->new_deq_ptr == ep_ring->dequeue) { + WARN_ON(1); + return; + } + } + /* + * Find cycle state for last_trb, starting at old cycle state of + * hw_dequeue. If there is only one segment ring, find_trb_seg() will + * return immediately and cannot toggle the cycle state if this search + * wraps around, so add one more toggle manually in that case. + */ + state->new_cycle_state = hw_dequeue & 0x1; + if (ep_ring->first_seg == ep_ring->first_seg->next && + cur_td->last_trb < state->new_deq_ptr) + state->new_cycle_state ^= 0x1; + state->new_deq_ptr = cur_td->last_trb; xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "Finding segment containing last TRB in TD."); state->new_deq_seg = find_trb_seg(state->new_deq_seg, - state->new_deq_ptr, - &state->new_cycle_state); + state->new_deq_ptr, &state->new_cycle_state); if (!state->new_deq_seg) { WARN_ON(1); return; } + /* Increment to find next TRB after last_trb. Cycle if appropriate. */ trb = &state->new_deq_ptr->generic; if (TRB_TYPE_LINK_LE32(trb->field[3]) && (trb->field[3] & cpu_to_le32(LINK_TOGGLE))) state->new_cycle_state ^= 0x1; next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr); - /* - * If there is only one segment in a ring, find_trb_seg()'s while loop - * will not run, and it will return before it has a chance to see if it - * needs to toggle the cycle bit. It can't tell if the stalled transfer - * ended just before the link TRB on a one-segment ring, or if the TD - * wrapped around the top of the ring, because it doesn't have the TD in - * question. Look for the one-segment case where stalled TRB's address - * is greater than the new dequeue pointer address. - */ - if (ep_ring->first_seg == ep_ring->first_seg->next && - state->new_deq_ptr < dev->eps[ep_index].stopped_trb) - state->new_cycle_state ^= 0x1; + /* Don't update the ring cycle state for the producer (us). */ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "Cycle state = 0x%x", state->new_cycle_state); - /* Don't update the ring cycle state for the producer (us). */ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "New dequeue segment = %p (virtual)", state->new_deq_seg); @@ -799,7 +801,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, if (list_empty(&ep->cancelled_td_list)) { xhci_stop_watchdog_timer_in_irq(xhci, ep); ep->stopped_td = NULL; - ep->stopped_trb = NULL; ring_doorbell_for_active_rings(xhci, slot_id, ep_index); return; } @@ -867,11 +868,9 @@ remove_finished_td: ring_doorbell_for_active_rings(xhci, slot_id, ep_index); } - /* Clear stopped_td and stopped_trb if endpoint is not halted */ - if (!(ep->ep_state & EP_HALTED)) { + /* Clear stopped_td if endpoint is not halted */ + if (!(ep->ep_state & EP_HALTED)) ep->stopped_td = NULL; - ep->stopped_trb = NULL; - } /* * Drop the lock and complete the URBs in the cancelled TD list. @@ -1941,14 +1940,12 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; ep->ep_state |= EP_HALTED; ep->stopped_td = td; - ep->stopped_trb = event_trb; ep->stopped_stream = stream_id; xhci_queue_reset_ep(xhci, slot_id, ep_index); xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index); ep->stopped_td = NULL; - ep->stopped_trb = NULL; ep->stopped_stream = 0; xhci_ring_cmd_db(xhci); @@ -2030,7 +2027,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, * the ring dequeue pointer or take this TD off any lists yet. */ ep->stopped_td = td; - ep->stopped_trb = event_trb; return 0; } else { if (trb_comp_code == COMP_STALL) { @@ -2042,7 +2038,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, * USB class driver clear the stall later. */ ep->stopped_td = td; - ep->stopped_trb = event_trb; ep->stopped_stream = ep_ring->stream_id; } else if (xhci_requires_manual_halt_cleanup(xhci, ep_ctx, trb_comp_code)) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8fe4e12..3008369 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -408,16 +408,16 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) #else -static int xhci_try_enable_msi(struct usb_hcd *hcd) +static inline int xhci_try_enable_msi(struct usb_hcd *hcd) { return 0; } -static void xhci_cleanup_msix(struct xhci_hcd *xhci) +static inline void xhci_cleanup_msix(struct xhci_hcd *xhci) { } -static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) +static inline void xhci_msix_sync_irqs(struct xhci_hcd *xhci) { } @@ -2954,7 +2954,6 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, xhci_ring_cmd_db(xhci); } virt_ep->stopped_td = NULL; - virt_ep->stopped_trb = NULL; virt_ep->stopped_stream = 0; spin_unlock_irqrestore(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d280e92..4746816 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -865,8 +865,6 @@ struct xhci_virt_ep { #define EP_GETTING_NO_STREAMS (1 << 5) /* ---- Related to URB cancellation ---- */ struct list_head cancelled_td_list; - /* The TRB that was last reported in a stopped endpoint ring */ - union xhci_trb *stopped_trb; struct xhci_td *stopped_td; unsigned int stopped_stream; /* Watchdog timer for stop endpoint command to cancel URBs */ diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 3372ded..e2fd263 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -470,8 +470,9 @@ static int dsps_musb_exit(struct musb *musb) struct dsps_glue *glue = dev_get_drvdata(dev->parent); del_timer_sync(&glue->timer); - usb_phy_shutdown(musb->xceiv); + debugfs_remove_recursive(glue->dbgfs_root); + return 0; } @@ -708,8 +709,6 @@ static int dsps_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); - debugfs_remove_recursive(glue->dbgfs_root); - return 0; } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index d341c14..d369bf1 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -316,7 +316,13 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work) { struct omap2430_glue *glue = container_of(mailbox_work, struct omap2430_glue, omap_musb_mailbox_work); + struct musb *musb = glue_to_musb(glue); + struct device *dev = musb->controller; + + pm_runtime_get_sync(dev); omap_musb_set_mailbox(glue); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); } static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci) @@ -416,6 +422,7 @@ static int omap2430_musb_init(struct musb *musb) omap_musb_set_mailbox(glue); phy_init(musb->phy); + phy_power_on(musb->phy); pm_runtime_put_noidle(musb->controller); return 0; @@ -478,6 +485,7 @@ static int omap2430_musb_exit(struct musb *musb) del_timer_sync(&musb_idle_timer); omap2430_low_level_exit(musb); + phy_power_off(musb->phy); phy_exit(musb->phy); return 0; diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c index d75196a..35b6083 100644 --- a/drivers/usb/phy/phy-am335x-control.c +++ b/drivers/usb/phy/phy-am335x-control.c @@ -3,6 +3,7 @@ #include <linux/err.h> #include <linux/of.h> #include <linux/io.h> +#include <linux/delay.h> #include "am35x-phy-control.h" struct am335x_control_usb { @@ -86,6 +87,14 @@ static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on) } writel(val, usb_ctrl->phy_reg + reg); + + /* + * Give the PHY ~1ms to complete the power up operation. + * Tests have shown unstable behaviour if other USB PHY related + * registers are written too shortly after such a transition. + */ + if (on) + mdelay(1); } static const struct phy_control ctrl_am335x = { diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 8afa813..36b6bce 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -132,6 +132,9 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type) if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { pr_debug("PHY: unable to find transceiver of type %s\n", usb_phy_type_string(type)); + if (!IS_ERR(phy)) + phy = ERR_PTR(-ENODEV); + goto err0; } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 95fa121..762e4a5 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -104,6 +104,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ + { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 44ab129..7c6e1de 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -909,6 +909,39 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, /* Cressi Devices */ { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) }, + /* Brainboxes Devices */ + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index e599fbf..993c93d 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1326,3 +1326,40 @@ * Manufacturer: Cressi */ #define FTDI_CRESSI_PID 0x87d0 + +/* + * Brainboxes devices + */ +#define BRAINBOXES_VID 0x05d1 +#define BRAINBOXES_VX_001_PID 0x1001 /* VX-001 ExpressCard 1 Port RS232 */ +#define BRAINBOXES_VX_012_PID 0x1002 /* VX-012 ExpressCard 2 Port RS232 */ +#define BRAINBOXES_VX_023_PID 0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */ +#define BRAINBOXES_VX_034_PID 0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */ +#define BRAINBOXES_US_101_PID 0x1011 /* US-101 1xRS232 */ +#define BRAINBOXES_US_324_PID 0x1013 /* US-324 1xRS422/485 1Mbaud */ +#define BRAINBOXES_US_606_1_PID 0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */ +#define BRAINBOXES_US_606_2_PID 0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */ +#define BRAINBOXES_US_606_3_PID 0x2003 /* US-606 6 Port RS232 Serial Port 4 and 6 */ +#define BRAINBOXES_US_701_1_PID 0x2011 /* US-701 4xRS232 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_701_2_PID 0x2012 /* US-701 4xRS422 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_279_1_PID 0x2021 /* US-279 8xRS422 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_279_2_PID 0x2022 /* US-279 8xRS422 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_279_3_PID 0x2023 /* US-279 8xRS422 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_279_4_PID 0x2024 /* US-279 8xRS422 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_346_1_PID 0x3011 /* US-346 4xRS422/485 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_346_2_PID 0x3012 /* US-346 4xRS422/485 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_257_PID 0x5001 /* US-257 2xRS232 1Mbaud */ +#define BRAINBOXES_US_313_PID 0x6001 /* US-313 2xRS422/485 1Mbaud */ +#define BRAINBOXES_US_357_PID 0x7001 /* US_357 1xRS232/422/485 */ +#define BRAINBOXES_US_842_1_PID 0x8001 /* US-842 8xRS422/485 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_842_2_PID 0x8002 /* US-842 8xRS422/485 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_842_3_PID 0x8003 /* US-842 8xRS422/485 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_842_4_PID 0x8004 /* US-842 8xRS422/485 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_160_1_PID 0x9001 /* US-160 16xRS232 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_160_2_PID 0x9002 /* US-160 16xRS232 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_160_3_PID 0x9003 /* US-160 16xRS232 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_160_4_PID 0x9004 /* US-160 16xRS232 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_160_5_PID 0x9005 /* US-160 16xRS232 1Mbaud Port 9 and 10 */ +#define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */ +#define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */ +#define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */ diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a2db5be..df90dae 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -28,6 +28,7 @@ #include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/serial.h> +#include <linux/swab.h> #include <linux/kfifo.h> #include <linux/ioctl.h> #include <linux/firmware.h> @@ -280,7 +281,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, { int status = 0; __u8 read_length; - __be16 be_start_address; + u16 be_start_address; dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length); @@ -296,10 +297,14 @@ static int read_download_mem(struct usb_device *dev, int start_address, if (read_length > 1) { dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length); } - be_start_address = cpu_to_be16(start_address); + /* + * NOTE: Must use swab as wIndex is sent in little-endian + * byte order regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vread_sync(dev, UMPC_MEMORY_READ, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, read_length); if (status) { @@ -394,7 +399,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, struct device *dev = &serial->serial->dev->dev; int status = 0; int write_length; - __be16 be_start_address; + u16 be_start_address; /* We can only send a maximum of 1 aligned byte page at a time */ @@ -409,11 +414,16 @@ static int write_i2c_mem(struct edgeport_serial *serial, __func__, start_address, write_length); usb_serial_debug_data(dev, __func__, write_length, buffer); - /* Write first page */ - be_start_address = cpu_to_be16(start_address); + /* + * Write first page. + * + * NOTE: Must use swab as wIndex is sent in little-endian byte order + * regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, write_length); if (status) { dev_dbg(dev, "%s - ERROR %d\n", __func__, status); @@ -436,11 +446,16 @@ static int write_i2c_mem(struct edgeport_serial *serial, __func__, start_address, write_length); usb_serial_debug_data(dev, __func__, write_length, buffer); - /* Write next page */ - be_start_address = cpu_to_be16(start_address); + /* + * Write next page. + * + * NOTE: Must use swab as wIndex is sent in little-endian byte + * order regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, write_length); if (status) { dev_err(dev, "%s - ERROR %d\n", __func__, status); @@ -585,8 +600,8 @@ static int get_descriptor_addr(struct edgeport_serial *serial, if (rom_desc->Type == desc_type) return start_address; - start_address = start_address + sizeof(struct ti_i2c_desc) - + rom_desc->Size; + start_address = start_address + sizeof(struct ti_i2c_desc) + + le16_to_cpu(rom_desc->Size); } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); @@ -599,7 +614,7 @@ static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer) __u16 i; __u8 cs = 0; - for (i = 0; i < rom_desc->Size; i++) + for (i = 0; i < le16_to_cpu(rom_desc->Size); i++) cs = (__u8)(cs + buffer[i]); if (cs != rom_desc->CheckSum) { @@ -650,7 +665,7 @@ static int check_i2c_image(struct edgeport_serial *serial) break; if ((start_address + sizeof(struct ti_i2c_desc) + - rom_desc->Size) > TI_MAX_I2C_SIZE) { + le16_to_cpu(rom_desc->Size)) > TI_MAX_I2C_SIZE) { status = -ENODEV; dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__); break; @@ -665,7 +680,8 @@ static int check_i2c_image(struct edgeport_serial *serial) /* Read the descriptor data */ status = read_rom(serial, start_address + sizeof(struct ti_i2c_desc), - rom_desc->Size, buffer); + le16_to_cpu(rom_desc->Size), + buffer); if (status) break; @@ -674,7 +690,7 @@ static int check_i2c_image(struct edgeport_serial *serial) break; } start_address = start_address + sizeof(struct ti_i2c_desc) + - rom_desc->Size; + le16_to_cpu(rom_desc->Size); } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); @@ -712,7 +728,7 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) /* Read the descriptor data */ status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc), - rom_desc->Size, buffer); + le16_to_cpu(rom_desc->Size), buffer); if (status) goto exit; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 68fc9fe..f213ee9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -234,8 +234,31 @@ static void option_instat_callback(struct urb *urb); #define QUALCOMM_VENDOR_ID 0x05C6 #define CMOTECH_VENDOR_ID 0x16d8 -#define CMOTECH_PRODUCT_6008 0x6008 -#define CMOTECH_PRODUCT_6280 0x6280 +#define CMOTECH_PRODUCT_6001 0x6001 +#define CMOTECH_PRODUCT_CMU_300 0x6002 +#define CMOTECH_PRODUCT_6003 0x6003 +#define CMOTECH_PRODUCT_6004 0x6004 +#define CMOTECH_PRODUCT_6005 0x6005 +#define CMOTECH_PRODUCT_CGU_628A 0x6006 +#define CMOTECH_PRODUCT_CHE_628S 0x6007 +#define CMOTECH_PRODUCT_CMU_301 0x6008 +#define CMOTECH_PRODUCT_CHU_628 0x6280 +#define CMOTECH_PRODUCT_CHU_628S 0x6281 +#define CMOTECH_PRODUCT_CDU_680 0x6803 +#define CMOTECH_PRODUCT_CDU_685A 0x6804 +#define CMOTECH_PRODUCT_CHU_720S 0x7001 +#define CMOTECH_PRODUCT_7002 0x7002 +#define CMOTECH_PRODUCT_CHU_629K 0x7003 +#define CMOTECH_PRODUCT_7004 0x7004 +#define CMOTECH_PRODUCT_7005 0x7005 +#define CMOTECH_PRODUCT_CGU_629 0x7006 +#define CMOTECH_PRODUCT_CHU_629S 0x700a +#define CMOTECH_PRODUCT_CHU_720I 0x7211 +#define CMOTECH_PRODUCT_7212 0x7212 +#define CMOTECH_PRODUCT_7213 0x7213 +#define CMOTECH_PRODUCT_7251 0x7251 +#define CMOTECH_PRODUCT_7252 0x7252 +#define CMOTECH_PRODUCT_7253 0x7253 #define TELIT_VENDOR_ID 0x1bc7 #define TELIT_PRODUCT_UC864E 0x1003 @@ -243,6 +266,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 +#define TELIT_PRODUCT_UE910_V2 0x1012 #define TELIT_PRODUCT_LE920 0x1200 /* ZTE PRODUCTS */ @@ -286,6 +310,7 @@ static void option_instat_callback(struct urb *urb); #define ALCATEL_PRODUCT_X060S_X200 0x0000 #define ALCATEL_PRODUCT_X220_X500D 0x0017 #define ALCATEL_PRODUCT_L100V 0x011e +#define ALCATEL_PRODUCT_L800MA 0x0203 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -348,6 +373,7 @@ static void option_instat_callback(struct urb *urb); #define OLIVETTI_PRODUCT_OLICARD100 0xc000 #define OLIVETTI_PRODUCT_OLICARD145 0xc003 #define OLIVETTI_PRODUCT_OLICARD200 0xc005 +#define OLIVETTI_PRODUCT_OLICARD500 0xc00b /* Celot products */ #define CELOT_VENDOR_ID 0x211f @@ -501,6 +527,10 @@ static const struct option_blacklist_info huawei_cdc12_blacklist = { .reserved = BIT(1) | BIT(2), }; +static const struct option_blacklist_info net_intf0_blacklist = { + .reserved = BIT(0), +}; + static const struct option_blacklist_info net_intf1_blacklist = { .reserved = BIT(1), }; @@ -1034,13 +1064,53 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ - { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ - { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6004) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6005) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_628A) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHE_628S), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_301), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628S) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_680) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_685A) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720S), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7002), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629K), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7004), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7005) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_629), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629S), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720I), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7212), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7213), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7251), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7252), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7253), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ @@ -1498,6 +1568,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L800MA), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), @@ -1543,6 +1615,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200), .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD500), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist + }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2e22fc2..b3d5a35 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -83,6 +83,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index c38b8c0..42bc082 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -121,8 +121,11 @@ #define SUPERIAL_VENDOR_ID 0x5372 #define SUPERIAL_PRODUCT_ID 0x2303 -/* Hewlett-Packard LD220-HP POS Pole Display */ +/* Hewlett-Packard POS Pole Displays */ #define HP_VENDOR_ID 0x03f0 +#define HP_LD960_PRODUCT_ID 0x0b39 +#define HP_LCM220_PRODUCT_ID 0x3139 +#define HP_LCM960_PRODUCT_ID 0x3239 #define HP_LD220_PRODUCT_ID 0x3524 /* Cressi Edy (diving computer) PC interface */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 968a402..7ed681a 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -136,9 +136,18 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 0)}, /* Sierra Wireless MC7710 Device Management */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 2)}, /* Sierra Wireless MC7710 NMEA */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 3)}, /* Sierra Wireless MC7710 Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68c0, 0)}, /* Sierra Wireless MC73xx Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68c0, 2)}, /* Sierra Wireless MC73xx NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68c0, 3)}, /* Sierra Wireless MC73xx Modem */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 0)}, /* Sierra Wireless EM7700 Device Management */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 2)}, /* Sierra Wireless EM7700 NMEA */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 3)}, /* Sierra Wireless EM7700 Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901f, 0)}, /* Sierra Wireless EM7355 Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901f, 2)}, /* Sierra Wireless EM7355 NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901f, 3)}, /* Sierra Wireless EM7355 Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9041, 0)}, /* Sierra Wireless MC7305/MC7355 Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9041, 2)}, /* Sierra Wireless MC7305/MC7355 NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9041, 3)}, /* Sierra Wireless MC7305/MC7355 Modem */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 0)}, /* Netgear AirCard 340U Device Management */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 2)}, /* Netgear AirCard 340U NMEA */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 3)}, /* Netgear AirCard 340U Modem */ diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index a9eb6221..6b192e6 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -291,7 +291,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, - { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */ { } }; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 81fc0df..6d40d56 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1347,10 +1347,12 @@ static int usb_serial_register(struct usb_serial_driver *driver) static void usb_serial_deregister(struct usb_serial_driver *device) { pr_info("USB Serial deregistering driver %s\n", device->description); + mutex_lock(&table_lock); list_del(&device->driver_list); - usb_serial_bus_deregister(device); mutex_unlock(&table_lock); + + usb_serial_bus_deregister(device); } /** diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 640fe01..b078440 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -466,6 +466,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port) int err; int i; + if (!port->bulk_in_size || !port->bulk_out_size) + return -ENODEV; + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) return -ENOMEM; @@ -473,9 +476,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) init_usb_anchor(&portdata->delayed); for (i = 0; i < N_IN_URB; i++) { - if (!port->bulk_in_size) - break; - buffer = (u8 *)__get_free_page(GFP_KERNEL); if (!buffer) goto bail_out_error; @@ -489,9 +489,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) } for (i = 0; i < N_OUT_URB; i++) { - if (!port->bulk_out_size) - break; - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); if (!buffer) goto bail_out_error2; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index a7ac97c..511b229 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -137,7 +137,7 @@ static void uas_do_work(struct work_struct *work) if (!(cmdinfo->state & IS_IN_WORK_LIST)) continue; - err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); if (!err) cmdinfo->state &= ~IS_IN_WORK_LIST; else @@ -803,7 +803,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, devinfo->running_task = 1; memset(&devinfo->response, 0, sizeof(devinfo->response)); - sense_urb = uas_submit_sense_urb(cmnd, GFP_NOIO, + sense_urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC, devinfo->use_streams ? tag : 0); if (!sense_urb) { shost_printk(KERN_INFO, shost, @@ -813,7 +813,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, spin_unlock_irqrestore(&devinfo->lock, flags); return FAILED; } - if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) { + if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit task mgmt urb failed\n", __func__, fname); @@ -1030,7 +1030,7 @@ static int uas_configure_endpoints(struct uas_dev_info *devinfo) devinfo->use_streams = 0; } else { devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, - 3, 256, GFP_KERNEL); + 3, 256, GFP_NOIO); if (devinfo->qdepth < 0) return devinfo->qdepth; devinfo->use_streams = 1; @@ -1047,7 +1047,7 @@ static void uas_free_streams(struct uas_dev_info *devinfo) eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); - usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); + usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO); } static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1096,16 +1096,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) if (result) goto free_streams; + usb_set_intfdata(intf, shost); result = scsi_add_host(shost, &intf->dev); if (result) goto free_streams; scsi_scan_host(shost); - usb_set_intfdata(intf, shost); return result; free_streams: uas_free_streams(devinfo); + usb_set_intfdata(intf, NULL); set_alt0: usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); if (shost) diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index d771870a..6dfd30a 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c @@ -69,7 +69,7 @@ const char *usb_state_string(enum usb_device_state state) [USB_STATE_RECONNECTING] = "reconnecting", [USB_STATE_UNAUTHENTICATED] = "unauthenticated", [USB_STATE_DEFAULT] = "default", - [USB_STATE_ADDRESS] = "addresssed", + [USB_STATE_ADDRESS] = "addressed", [USB_STATE_CONFIGURED] = "configured", [USB_STATE_SUSPENDED] = "suspended", }; diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c index 4474126..3f485df 100644 --- a/drivers/usb/wusbcore/mmc.c +++ b/drivers/usb/wusbcore/mmc.c @@ -301,7 +301,7 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) if (chid) result = uwb_radio_start(&wusbhc->pal); - else + else if (wusbhc->uwb_rc) uwb_radio_stop(&wusbhc->pal); return result; diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index c8e2a47..3e2e4ed 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -2390,10 +2390,10 @@ error_complete: done) { dev_info(dev, "Control EP stall. Queue delayed work.\n"); - spin_lock_irq(&wa->xfer_list_lock); + spin_lock(&wa->xfer_list_lock); /* move xfer from xfer_list to xfer_errored_list. */ list_move_tail(&xfer->list_node, &wa->xfer_errored_list); - spin_unlock_irq(&wa->xfer_list_lock); + spin_unlock(&wa->xfer_list_lock); spin_unlock_irqrestore(&xfer->lock, flags); queue_work(wusbd, &wa->xfer_error_work); } else { diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index 16ada83..468c89f 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c @@ -59,6 +59,7 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, struct uwb_rceb *reply, ssize_t reply_size) { struct uwb_rc_evt_set_drp_ie *r = (struct uwb_rc_evt_set_drp_ie *)reply; + unsigned long flags; if (r != NULL) { if (r->bResultCode != UWB_RC_RES_SUCCESS) @@ -67,14 +68,14 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, } else dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); - spin_lock_irq(&rc->rsvs_lock); + spin_lock_irqsave(&rc->rsvs_lock, flags); if (rc->set_drp_ie_pending > 1) { rc->set_drp_ie_pending = 0; - uwb_rsv_queue_update(rc); + uwb_rsv_queue_update(rc); } else { - rc->set_drp_ie_pending = 0; + rc->set_drp_ie_pending = 0; } - spin_unlock_irq(&rc->rsvs_lock); + spin_unlock_irqrestore(&rc->rsvs_lock, flags); } /** @@ -599,8 +600,11 @@ static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_i /* alloc and initialize new uwb_cnflt_alien */ cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL); - if (!cnflt) + if (!cnflt) { dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n"); + return; + } + INIT_LIST_HEAD(&cnflt->rc_node); init_timer(&cnflt->timer); cnflt->timer.function = uwb_cnflt_timer; diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 06990c6..61e706c0 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -320,7 +320,7 @@ static int tsi148_irq_init(struct vme_bridge *tsi148_bridge) struct pci_dev *pdev; struct tsi148_driver *bridge; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); bridge = tsi148_bridge->driver_priv; @@ -433,9 +433,7 @@ static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); if (sync != 0) { - pdev = container_of(tsi148_bridge->parent, - struct pci_dev, dev); - + pdev = to_pci_dev(tsi148_bridge->parent); synchronize_irq(pdev->irq); } } else { @@ -741,7 +739,7 @@ static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, reg_join(vme_bound_high, vme_bound_low, &vme_bound); reg_join(pci_offset_high, pci_offset_low, &pci_offset); - *pci_base = (dma_addr_t)vme_base + pci_offset; + *pci_base = (dma_addr_t)(*vme_base + pci_offset); *enabled = 0; *aspace = 0; @@ -814,7 +812,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, tsi148_bridge = image->parent; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); existing_size = (unsigned long long)(image->bus_resource.end - image->bus_resource.start); @@ -910,11 +908,15 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, unsigned long long pci_bound, vme_offset, pci_base; struct vme_bridge *tsi148_bridge; struct tsi148_driver *bridge; + struct pci_bus_region region; + struct pci_dev *pdev; tsi148_bridge = image->parent; bridge = tsi148_bridge->driver_priv; + pdev = to_pci_dev(tsi148_bridge->parent); + /* Verify input data */ if (vme_base & 0xFFFF) { dev_err(tsi148_bridge->parent, "Invalid VME Window " @@ -949,7 +951,9 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, pci_bound = 0; vme_offset = 0; } else { - pci_base = (unsigned long long)image->bus_resource.start; + pcibios_resource_to_bus(pdev->bus, ®ion, + &image->bus_resource); + pci_base = region.start; /* * Bound address is a valid address for the window, adjust @@ -2232,7 +2236,7 @@ static void *tsi148_alloc_consistent(struct device *parent, size_t size, struct pci_dev *pdev; /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); + pdev = to_pci_dev(parent); return pci_alloc_consistent(pdev, size, dma); } @@ -2243,7 +2247,7 @@ static void tsi148_free_consistent(struct device *parent, size_t size, struct pci_dev *pdev; /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); + pdev = to_pci_dev(parent); pci_free_consistent(pdev, size, vaddr, dma); } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index b96f61b..ff52618 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -614,27 +614,11 @@ end: return err; } -/* - * Handle sysfs file creation and removal here, before userspace is told that - * the device is added / removed from the system - */ -static int w1_bus_notify(struct notifier_block *nb, unsigned long action, - void *data) +static int w1_family_notify(unsigned long action, struct w1_slave *sl) { - struct device *dev = data; - struct w1_slave *sl; struct w1_family_ops *fops; int err; - /* - * Only care about slave devices at the moment. Yes, we should use a - * separate "type" for this, but for now, look at the release function - * to know which type it is... - */ - if (dev->release != w1_slave_release) - return 0; - - sl = dev_to_w1_slave(dev); fops = sl->family->fops; if (!fops) @@ -673,10 +657,6 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action, return 0; } -static struct notifier_block w1_bus_nb = { - .notifier_call = w1_bus_notify, -}; - static int __w1_attach_slave_device(struct w1_slave *sl) { int err; @@ -698,6 +678,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl) dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, dev_name(&sl->dev), sl); + /* suppress for w1_family_notify before sending KOBJ_ADD */ + dev_set_uevent_suppress(&sl->dev, true); + err = device_register(&sl->dev); if (err < 0) { dev_err(&sl->dev, @@ -705,7 +688,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) dev_name(&sl->dev), err); return err; } - + w1_family_notify(BUS_NOTIFY_ADD_DEVICE, sl); dev_set_uevent_suppress(&sl->dev, false); kobject_uevent(&sl->dev.kobj, KOBJ_ADD); @@ -799,6 +782,7 @@ int w1_unref_slave(struct w1_slave *sl) msg.type = W1_SLAVE_REMOVE; w1_netlink_send(sl->master, &msg); + w1_family_notify(BUS_NOTIFY_DEL_DEVICE, sl); device_unregister(&sl->dev); #ifdef DEBUG memset(sl, 0, sizeof(*sl)); @@ -1186,10 +1170,6 @@ static int __init w1_init(void) goto err_out_exit_init; } - retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb); - if (retval) - goto err_out_bus_unregister; - retval = driver_register(&w1_master_driver); if (retval) { printk(KERN_ERR diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index 5234964..a02704a 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c @@ -300,12 +300,6 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *w; u32 *id; - if (mcmd->type != W1_LIST_MASTERS) { - printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n", - __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len); - return -EPROTO; - } - cn = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!cn) return -ENOMEM; @@ -441,6 +435,9 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) w1_netlink_send_error(&node->block->msg, node->m, cmd, node->block->portid, err); + /* ref taken in w1_search_slave or w1_search_master_id when building + * the block + */ if (sl) w1_unref_slave(sl); else @@ -503,30 +500,42 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) msg_len = msg->len; while (msg_len && !err) { - struct w1_reg_num id; - u16 mlen = m->len; dev = NULL; sl = NULL; - memcpy(&id, m->id.id, sizeof(id)); -#if 0 - printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n", - __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len); -#endif if (m->len + sizeof(struct w1_netlink_msg) > msg_len) { err = -E2BIG; break; } + /* execute on this thread, no need to process later */ + if (m->type == W1_LIST_MASTERS) { + err = w1_process_command_root(msg, m, nsp->portid); + goto out_cont; + } + + /* All following message types require additional data, + * check here before references are taken. + */ + if (!m->len) { + err = -EPROTO; + goto out_cont; + } + + /* both search calls take reference counts */ if (m->type == W1_MASTER_CMD) { dev = w1_search_master_id(m->id.mst.id); } else if (m->type == W1_SLAVE_CMD) { - sl = w1_search_slave(&id); + sl = w1_search_slave((struct w1_reg_num *)m->id.id); if (sl) dev = sl->master; } else { - err = w1_process_command_root(msg, m, nsp->portid); + printk(KERN_NOTICE + "%s: msg: %x.%x, wrong type: %u, len: %u.\n", + __func__, msg->id.idx, msg->id.val, + m->type, m->len); + err = -EPROTO; goto out_cont; } @@ -536,8 +545,6 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) } err = 0; - if (!mlen) - goto out_cont; atomic_inc(&block->refcnt); node->async.cb = w1_process_cb; @@ -557,7 +564,8 @@ out_cont: if (err) w1_netlink_send_error(msg, m, NULL, nsp->portid, err); msg_len -= sizeof(struct w1_netlink_msg) + m->len; - m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); + m = (struct w1_netlink_msg *)(((u8 *)m) + + sizeof(struct w1_netlink_msg) + m->len); /* * Let's allow requests for nonexisting devices. |